Setting up an SFTP-only account with OpenSSH

There are many guides on creating SFTP-only accounts, however I found that most of them are outdated and do not make use of the features of OpenSSH. In this HOWTO I describe how I setup an SFTP account to allow a group of users to collaboratively maintain a website.

Requirements

For my SFTP account I had the following requirements:

  1. Support public key authentication;
  2. Use a chroot environment;
  3. Enforce SFTP only.

Configuration

First of all we need to create a group that is used to match the SFTP only users:

sudo groupadd -r sftponly

Now our users need to be made member of the sftponly group, when you create a new user you should use the -G sftponly option on the useradd command:

sudo useradd -m -G sftponly -b /home -s /bin/sh -c 'SFTP account for username' username

If you turn an existing user into an sftponly user you should user the options -a -G sftponly to the usermod command:

sudo usermod -a -G sftponly username

We also need to create the directory into which we will chroot our users, this directory must not be writeable for any of the chroot users, so keep root as owner:

sudo mkdir -p /path/to/chroot
sudo chmod 0755 /path/to/chroot

For each user we need to create a directory into which they can write:

sudo mkdir -p /path/to/chroot/username
sudo chown username:username /path/to/chroot/username
sudo chmod 0700 /path/to/chroot/username

Next, you need to edit the /etc/ssh/sshd_config SSHD configuration and add a new Match to enforce sftp for members of the sftponly group.

Match Group sftponly
  ForceCommand internal-sftp
  ChrootDirectory /path/to/chroot
  PubkeyAuthentication yes

Finally we need to install the user’s public key in the home directory of the user. The public key is generated with the command ssh-keygen, and will be found in the home directory (~/.ssh/id_rsa.pub) of the user on his own computer. This file needs to be copied into the file containing the authorized keys on the server (~/.ssh/authorized_keys).

sudo mkdir ~username/.ssh
sudo chown username:username ~username/.ssh
sudo chmod 0700 ~username/.ssh
sudo cat id_rsa.pub >> ~username/.ssh/authorized_keys
sudo chown username:username ~username/.ssh/authorized_keys

Conclusions

With these steps I created a highly secured environment that allows users to upload files. This setup has significant advantages over old-fashioned FTP accounts. It is more secure than the plain text authentication of traditional FTP; it is more firewall friendly since it will only use a single port (22/tcp) and it does away with password authentication, which is one mayor risks on the internet.

4 thoughts on “Setting up an SFTP-only account with OpenSSH”

  1. Hi
    I think there are 2 mistakes in this procedure.

    sudo chown username:username /path/to/chroot/username
    Must be
    sudo chown username:sftponly /path/to/chroot/username

    sudo chown username:username ~username/.ssh
    Must be
    sudo chown username:sftponly ~username/.ssh

  2. Roy,
    Thank you for your feedback. These settings do work as posted, however I assume that the system will create a primary group for the user with the same name as the username. If your system doesn’t you should use the appropriate primary group for the user instead.

    I think you should not use the sftponly group for these directories, since that group doesn’t denote an intrinsic property of the user, but is used as an attribute to restrict the user’s privileges. It might be that the user’s privileges will be extended at some time and that therefor the user will no longer be member of this group. I would find it undesirable if some of the user’s files or directories were own by a group he is not a member of.

  3. I was searching everywhere for something like this!

    Do you think your howto is still correct, considering some of the newer features in OpenSSH > 6.6 ?
    I only just learned about them and am trying to find out how others are incorporating this functionality into scp/sftp only configurations.

Leave a Reply

Your email address will not be published. Required fields are marked *