SFTP isn’t really a protocol on its own; it’s just SSH with a file-transfer subsystem tacked on.
Let’s get an SFTP server up and running. We’ll use sshd itself, which is already installed on most Linux systems.
First, ensure you have openssh-server installed:
sudo apt update && sudo apt install openssh-server
Or on RHEL/CentOS:
sudo yum update && sudo yum install openssh-server
Now, we need to configure sshd to allow SFTP. The default sshd_config (/etc/ssh/sshd_config) usually has this set up, but we’ll explicitly check and potentially modify it.
The key directive is Subsystem sftp. It tells SSH which program to execute when a client requests the SFTP subsystem. The standard setup is:
Subsystem sftp /usr/lib/openssh/sftp-server
If this line is commented out (starts with #) or missing, uncomment or add it. The path to sftp-server might vary slightly depending on your distribution. You can find it using which sftp-server or find /usr/ -name sftp-server.
After modifying sshd_config, you must reload or restart the sshd service for the changes to take effect:
sudo systemctl reload sshd
or
sudo systemctl restart sshd
Now, let’s create a dedicated user for SFTP access. It’s a bad idea to use root or your regular user for this. We’ll call our user sftpuser.
sudo adduser sftpuser
This command will prompt you to set a password and some optional information.
Next, we need to configure sshd_config for chrooting this user. Chrooting restricts the user to a specific directory, preventing them from seeing or accessing anything outside of it. This is crucial for security.
We’ll use Match User to apply specific configurations only to sftpuser. Add the following block to the end of your /etc/ssh/sshd_config file:
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
Let’s break this down:
Match User sftpuser: This section only applies to the usersftpuser.ChrootDirectory /home/sftpuser: This is the directorysftpuserwill be confined to. The SSH daemon will chroot into this directory. Crucially, this directory and all its parent directories up to the root must be owned by root and not writable by any other user or group. This is a security requirement ofsshd.ForceCommand internal-sftp: This forces the user to use the internal SFTP server, preventing them from executing arbitrary shell commands.AllowTcpForwarding noandX11Forwarding no: These disable features that are not needed for SFTP and reduce the attack surface.
Now, let’s set up the directory permissions for ChrootDirectory.
First, ensure the user sftpuser is created and has a password.
Then, we need to make sure /home/sftpuser is owned by root.
sudo chown root:root /home/sftpuser
sudo chmod 755 /home/sftpuser
Inside this chroot directory, you’ll want to create a directory where sftpuser can actually upload files. This subdirectory should be owned by sftpuser.
sudo mkdir /home/sftpuser/uploads
sudo chown sftpuser:sftpuser /home/sftpuser/uploads
Now, reload sshd again for the Match User block to take effect:
sudo systemctl reload sshd
You should now be able to connect as sftpuser using an SFTP client (like FileZilla, Cyberduck, or the command-line sftp client) and upload files to the /uploads directory. You will not be able to navigate outside of /home/sftpuser.
If you try to connect and get an error like "Permission denied, please login as a user with SFTP privileges" or "fatal: bad ownership or modes for chroot directory component", double-check the ownership and permissions of /home/sftpuser and its parent directories. They must be owned by root:root and have no write permissions for others.
The next thing you’ll likely want to configure is setting up SSH keys for passwordless SFTP authentication.