Moving files to a server with plain FTP means sending usernames, passwords, and data across the network in clear text. SFTP fixes that, and if your Linux server already runs SSH, you’re most of the way to having it.

SFTP (SSH File Transfer Protocol) transfers files over an encrypted SSH connection. Despite the similar name, it isn’t FTP with security bolted on. It’s a separate protocol that runs on a single port (22), which makes it much easier to firewall than FTP.

This guide shows how to set up an SFTP server on Linux using OpenSSH, create a restricted user who can only access their own folder, and optionally lock it down with SSH keys. The commands use Ubuntu/Debian, with notes for RHEL-based systems where they differ.

Why Use SFTP Instead of FTP?

  • Encrypted by default. Credentials and file contents are protected in transit.
  • One port. Only port 22 needs to be open, with no passive port ranges to manage.
  • Built on SSH. You get the same authentication options, including SSH keys.
  • No extra server software. OpenSSH already includes an SFTP subsystem.

Step 1: Install and Enable OpenSSH

Most servers already have OpenSSH. If yours doesn’t, install it:

sudo apt update
sudo apt install openssh-server

On RHEL, Rocky, or AlmaLinux:

sudo dnf install openssh-server

Make sure the service is running and starts on boot (the service is called ssh on Ubuntu/Debian and sshd on RHEL-based systems):

sudo systemctl enable --now ssh
sudo systemctl status ssh

Step 2: Create a Group and a User for SFTP

Rather than configuring each user individually, create a group and apply the SFTP rules to everyone in it:

sudo groupadd sftpusers

Create a user with no shell access, so they can transfer files but can’t log in to a terminal:

sudo useradd -m -G sftpusers -s /usr/sbin/nologin sftpuser
sudo passwd sftpuser

The -s /usr/sbin/nologin option blocks interactive shell logins, while SFTP still works because it’s handled by the SSH daemon itself.

Step 3: Create the Chroot Directory Structure

A chroot “jail” confines the user to a specific directory so they can’t browse the rest of the filesystem. OpenSSH has a strict requirement here: the chroot directory and every parent directory must be owned by root and not writable by anyone else. The user can’t write to the jail root itself, so you create a writable subfolder inside it.

sudo mkdir -p /srv/sftp/sftpuser/uploads
sudo chown root:root /srv/sftp /srv/sftp/sftpuser
sudo chmod 755 /srv/sftp /srv/sftp/sftpuser
sudo chown sftpuser:sftpusers /srv/sftp/sftpuser/uploads
sudo chmod 755 /srv/sftp/sftpuser/uploads

When sftpuser connects, they land in their jail and see only an uploads folder, which is where they can read and write files.

Step 4: Configure the SSH Daemon

Open the SSH server configuration:

sudo nano /etc/ssh/sshd_config

Find the line that begins with Subsystem sftp and change it to use the internal SFTP server, which is required for chroot to work without copying binaries into the jail:

Subsystem sftp internal-sftp

Then add this block at the end of the file:

Match Group sftpusers
    ChrootDirectory /srv/sftp/%u
    ForceCommand internal-sftp
    X11Forwarding no
    AllowTcpForwarding no

What each line does:

  • Match Group sftpusers applies the following settings only to members of that group.
  • ChrootDirectory /srv/sftp/%u jails the user in a folder named after their username (%u).
  • ForceCommand internal-sftp allows SFTP only and refuses any other command.
  • X11Forwarding no / AllowTcpForwarding no disable features an SFTP-only user doesn’t need.

Because a Match block applies until the next Match or end of file, always keep it at the bottom.

Step 5: Test the Configuration and Restart SSH

Check the file for syntax errors before restarting. A typo here could lock you out of the server:

sudo sshd -t

No output means the configuration is valid. Then restart the service:

sudo systemctl restart ssh

Keep your current SSH session open while you test from a second terminal, so you can fix any mistakes.

Step 6: Open the Firewall

If you use UFW and SSH is already allowed, nothing more is needed. Otherwise:

sudo ufw allow 22/tcp

On RHEL-based systems with firewalld:

sudo firewall-cmd --permanent --add-service=ssh
sudo firewall-cmd --reload

Step 7: Connect and Test

From another machine, connect with the command-line client:

sftp sftpuser@your-server-ip

Once connected, try a few commands:

sftp> pwd
Remote working directory: /
sftp> cd uploads
sftp> put report.pdf
sftp> ls
sftp> get report.pdf
sftp> exit

The jailed user sees / as their root, which is really /srv/sftp/sftpuser on the server. If you prefer a graphical client, FileZilla, WinSCP, and Cyberduck all support SFTP. Choose the SFTP protocol and port 22.

Optional: Use SSH Keys Instead of Passwords

Key-based authentication is more secure than passwords and avoids brute-force login attempts. On your client machine, generate a key pair:

ssh-keygen -t ed25519 -C "sftpuser"

Copy the public key to the server:

ssh-copy-id sftpuser@your-server-ip

ssh-copy-id needs password login to work the first time, and it writes to the user’s real home directory (/home/sftpuser/.ssh/authorized_keys), not the jail. That works fine, because sshd reads the key file before it applies the chroot.

Once key login works, you can disable passwords for the SFTP group by adding this line inside the Match Group sftpusers block:

PasswordAuthentication no

Run sudo sshd -t and restart SSH again.

Troubleshooting Common SFTP Issues

  • “Broken pipe” or the connection closes right after login. This is almost always a chroot permissions problem. Verify that /srv/sftp and /srv/sftp/sftpuser are owned by root:root and aren’t group- or world-writable.
  • “Permission denied” when uploading. The user can’t write to the jail root. Upload into the uploads subfolder instead, and confirm it’s owned by the user.
  • Login works but the user gets a shell prompt. The Match Group block isn’t being applied. Check that the user is in the group (groups sftpuser), and that the block is at the end of sshd_config.
  • Changes have no effect. Confirm you restarted the service and that sshd -t passes. Check the logs with sudo journalctl -u ssh -e (or /var/log/auth.log on Debian-based systems).
  • “Connection refused.” Check that the service is running and that the firewall allows port 22.

Security Tips

  • Disable root login over SSH with PermitRootLogin no.
  • Prefer SSH keys over passwords, and consider fail2ban to block repeated failed logins.
  • Give each user their own jail directory so they can’t see each other’s files.
  • Keep OpenSSH updated with regular apt upgrade or dnf update runs.

Conclusion

Setting up an SFTP server on Linux takes only a few minutes because OpenSSH already does the heavy lifting. Create a dedicated group and user, build a root-owned chroot directory with a writable subfolder, add a Match Group block to sshd_config, and restart the service. The result is an encrypted file transfer service that keeps each user confined to their own folder.

From there, add SSH keys, tighten your firewall rules, and monitor your logs, and you’ll have a file transfer setup that’s far safer than traditional FTP, with no extra software to maintain.