This post walks you through the steps to make some user accounts that can connect only by sftp (Secure FTP, a subsystem of openSSH) and are chrooted into their home directories. That is, they can’t see anything else outside their homes. You will be able to have other regular users on the system, the sftp-only users will be a special group.
Create a volume for chroot homes and mount it with options nodev, nosuid
This volume is used by the chrooting part of the mechanism. It will contain the home directories of the sftp-only users. The easiest way to make this on an already-installed OS is to create a loop mounted image. You must be root for these commands to work.
su - # become root dd if=/dev/zero of=/home/sftponly_image.ext3 bs=1M count=512 # this makes a 512 MB volume mkfs.ext3 /home/sftponly_image.ext3 # create the filesystem. Answer y to "Proceed anyway?" mkdir /home/sftponly # make a mountpoint mount -o loop,nodev,nosuid /home/sftponly_image.ext3 /home/sftponly # mount the image
Also you’ll want the image to mount automatically at boot. Add this to /etc/fstab:
/home/sftponly_image.ext3 /home/sftponly ext3 loop,nodev,nosuid 0 0
Everything up until now was laying the foundation for the actual sftp-only configuration that follows. Without all that, you would see this error in /var/log/messages when you try to login with sftp-only accounts:
sshd[...]: fatal: chroot into directory without nodev or nosuid
Create a sftponly group
Members of this group will be able to connect only by SFTP and will be chrooted to their home directories.
groupadd --system sftponly
Create a sftp user
The following command creates a sftp-only user named “sftpexample” with the home directory inside the mounted image. The user is a member of sftponly group and does not have permission to login with ssh, only sftp.
useradd --comment "SFTP example" --create-home --home /home/sftponly/sftpexample --groups sftponly --shell /bin/false sftpexample passwd sftpexample # set a password
Add options to SSH daemon configuration file
Add this to /etc/ssh/sshd_config
Match Group sftponly ChrootDirectory /home/sftponly/%u ForceCommand internal-sftp
Reload the ssh daemon:
systemctl reload sshd.service
Verify that it works
Login through sftp and verify the chroot environment:
sftp sftpexample@localhost Password: Connected to localhost. sftp> ls bin public_html sftp> cd / sftp> ls bin public_html sftp> quit
Must not be able to login with ssh:
ssh sftpexample@localhost Password: Connection to localhost closed by remote host. Connection to localhost closed.