SFTP (SSH File Transfer Protocol) is the secure way to transfer files to a server. It runs over SSH, so if your server has OpenSSH, you already have an SFTP server: nothing extra to install, and no plain-text passwords like FTP. With a few settings, you can give clients, colleagues or applications SFTP access that is locked to their own folder, with no shell access.

SFTP vs FTP vs FTPS

FTP FTPS SFTP
Encryption None TLS SSH
Ports 21 + data port range 21/990 + data port range 22 only
Firewall friendliness Poor Poor Good
Extra software vsftpd etc. vsftpd + certificates Built into OpenSSH

For most uses, SFTP is the simplest secure choice.

1. Basic SFTP for existing users

Any user who can SSH can already use SFTP:

sftp [email protected]
sftp> put backup.tar.gz
sftp> get logs/app.log

The rest of this guide creates SFTP-only users confined to a directory.

2. Create a group and user

sudo groupadd sftpusers
sudo useradd -m -d /home/client1 -s /usr/sbin/nologin -G sftpusers client1
sudo passwd client1

-s /usr/sbin/nologin prevents shell logins.

3. Set up the chroot directory

OpenSSH requires the chroot directory and every directory above it to be owned by root, and not writable by anyone else. So the user gets a writable subfolder inside it:

sudo mkdir -p /srv/sftp/client1/upload
sudo chown root:root /srv/sftp /srv/sftp/client1
sudo chmod 755 /srv/sftp /srv/sftp/client1
sudo chown client1:sftpusers /srv/sftp/client1/upload
sudo chmod 750 /srv/sftp/client1/upload

4. Configure sshd

Edit /etc/ssh/sshd_config. Make sure the SFTP subsystem uses the internal server:

Subsystem sftp internal-sftp

Add at the end of the file (Match blocks apply until the next Match or the end of the file):

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

%u expands to the username. Test and reload:

sudo sshd -t && sudo systemctl reload ssh      # the service is "sshd" on RHEL family

Keep your current SSH session open while testing, so a mistake can’t lock you out.

5. Test

sftp [email protected]
sftp> pwd          # Remote working directory: /
sftp> ls           # upload
sftp> cd upload
sftp> put test.txt

ssh [email protected] should be refused (“This service allows sftp connections only”).

6. Use SSH keys instead of passwords

For automated transfers and better security:

sudo mkdir -p /home/client1/.ssh
sudo nano /home/client1/.ssh/authorized_keys      # paste the client's public key
sudo chown -R client1:client1 /home/client1/.ssh
sudo chmod 700 /home/client1/.ssh && sudo chmod 600 /home/client1/.ssh/authorized_keys

The keys live in the normal home directory, outside the chroot, which is fine. You can then disable passwords for the group with PasswordAuthentication no inside the Match block. See SSH keys with ssh-keygen.

Connecting with GUI clients

Client Platform Settings
FileZilla Windows, macOS, Linux Protocol: SFTP; host; port 22; user; password or key file
WinSCP Windows File protocol: SFTP
Cyberduck macOS, Windows SFTP (SSH File Transfer Protocol)

In FileZilla, keys are added under Settings → Connection → SFTP.

Logging

With -l INFO on internal-sftp, file operations are logged. In a chroot, the SFTP process can’t reach /dev/log, so add a log socket inside the chroot base if you need full logs (for rsyslog: $AddUnixListenSocket /srv/sftp/dev/log, with a dev directory). Authentication events always appear in /var/log/auth.log or journalctl -u ssh.

Security tips

  • Protect SSH from brute force: keys, Fail2ban, or limiting port 22 to known IPs. See Fail2ban.
  • One user per client, so access can be revoked individually.
  • Set disk quotas if users might upload a lot. Monitor disk space. See the df command.
  • For a multi-user file server with a web UI, S3 and WebDAV, consider SFTPGo. See SFTPGo.

Troubleshooting

Error Cause / fix
“Connection closed” right after login Chroot ownership wrong: every directory in the chroot path must be root-owned and not group/other-writable. Check journalctl -u ssh for “bad ownership or modes”
“Permission denied” on upload User has no write access to the folder: upload into upload/, check owner and mode
“Received message too long” Shell startup files print text; use ForceCommand internal-sftp
Key not accepted Permissions on .ssh / authorized_keys; check /var/log/auth.log

Quick reference

Task Command / setting
SFTP-only user useradd -s /usr/sbin/nologin -G sftpusers user
Jail ChrootDirectory /srv/sftp/%u (root-owned)
No shell ForceCommand internal-sftp
Apply sshd -t && systemctl reload ssh
Connect sftp user@host

Related: the scp command and connecting to a VPS with SSH.

  • Linux
  • SFTP
  • Security