How to Set Up SFTP Chroot Jail

By 

Updated on

6 min read

Linux SFTP Chroot Jail

If you are a system administrator managing a Linux server, you may need to grant SFTP access to some users to upload files to their home directories. By default, users that can log in to the system via SSH, SFTP, and SCP can browse the entire filesystem, including other users’ directories.

This may not be a problem if these users are trusted. If you do not want logged-in users to navigate around the system, you will need to restrict user access to their home directory. This adds an extra layer of security, especially on systems with multiple users.

In this guide, we will explain how to set up an SFTP Chroot Jail environment that will restrict users to their home directories. The users will have SFTP access only; SSH access will be disabled. These instructions work for any modern Linux distribution including Ubuntu, Debian, and Fedora.

Quick Reference

TaskCommand
Create SFTP groupsudo groupadd sftponly
Create chroot usersudo useradd -g sftponly -s /bin/false -m -d /home/user user
Set home directory ownershipsudo chown root: /home/user
Set home directory permissionssudo chmod 755 /home/user
Restart SSH (Debian/Ubuntu)sudo systemctl restart ssh
Restart SSH (Fedora/RHEL)sudo systemctl restart sshd
Test SSH config syntaxsudo sshd -t

For a printable quick reference, see the SSH cheatsheet .

Creating an SFTP Group

Instead of configuring the OpenSSH server for each user individually, we will create a new group and add all our chrooted users to this group.

Run the following groupadd command to create the sftponly user group:

Terminal
sudo groupadd sftponly
Tip
You can name the group as you like.

Adding Users to the SFTP Group

The next step is to add the users you want to restrict to the sftponly group.

If this is a new setup and the user does not exist, you can create a new user account by typing:

Terminal
sudo useradd -g sftponly -s /bin/false -m -d /home/username username
  • The -g sftponly option will add the user to the sftponly group.
  • The -s /bin/false option sets the user’s login shell. By setting the login shell to /bin/false, the user will not be able to log in to the server via SSH.
  • The -m -d /home/username options tell useradd to create the user home directory.

Set a strong password for the newly created user:

Terminal
sudo passwd username

If the user you want to restrict already exists, add the user to the sftponly group and change the user’s shell:

Terminal
sudo usermod -G sftponly -s /bin/false username2

The user home directory must be owned by root and have 755 permissions :

Terminal
sudo chown root: /home/username
sudo chmod 755 /home/username

Since the user home directories are owned by the root user, these users will not be able to create files and directories in their home directories. If there are no directories in the user’s home, you will need to create new directories to which the user will have full access. For example, you can create the following directories:

Terminal
sudo mkdir /home/username/{public_html,uploads}
sudo chmod 755 /home/username/{public_html,uploads}
sudo chown username:sftponly /home/username/{public_html,uploads}

If a web application is using the user’s public_html directory as document root, these changes may lead to permissions issues. For example, if you are running WordPress you will need to create a PHP pool that will run as the user owning the files and add the web server to the sftponly group.

Configuring SSH

SFTP is a subsystem of SSH and supports all SSH authentication mechanisms.

Open the SSH configuration file /etc/ssh/sshd_config with your text editor :

Terminal
sudo nano /etc/ssh/sshd_config

Search for the line starting with Subsystem sftp, usually at the end of the file. If the line starts with a hash #, remove the hash and modify it to look like the following:

/etc/ssh/sshd_configini
Subsystem sftp internal-sftp

Towards the end of the file, add the following block of settings:

/etc/ssh/sshd_configini
Match Group sftponly
  ChrootDirectory %h
  ForceCommand internal-sftp
  AllowTcpForwarding no
  X11Forwarding no

The ChrootDirectory directive specifies the path to the chroot directory. %h means the user home directory. This directory must be owned by the root user and not writable by any other user or group.

Be extra careful when modifying the SSH configuration file. An incorrect configuration may cause the SSH service to fail to start. You can test the configuration syntax before restarting the service:

Terminal
sudo sshd -t

Once you are done, save the file and restart the SSH service to apply the changes. On Ubuntu and Debian:

Terminal
sudo systemctl restart ssh

On Fedora, RHEL, and derivatives, the SSH service is named sshd:

Terminal
sudo systemctl restart sshd

Testing the Configuration

Now that you have configured SFTP chroot, you can try to log in to the remote machine through SFTP using the credentials of the chrooted user. In most cases, you will use a desktop SFTP client like FileZilla , but in this example, we will use the sftp command .

Open an SFTP connection using the sftp command followed by the remote server username and the server IP address or domain name:

Terminal
sftp username@192.168.121.30

You will be prompted to enter the user password. Once connected, the remote server will display a confirmation message and the sftp> prompt:

output
username@192.168.121.30's password:
sftp>

Run the pwd command, and if everything is working as expected the command should return /:

output
sftp> pwd
Remote working directory: /

You can also list the remote files and directories using the ls command, and you should see the directories that we have previously created:

output
sftp> ls
public_html  uploads

Troubleshooting

“bad ownership or modes for chroot directory” error The chroot directory must be owned by root and must not be writable by the group or other users. Run sudo chown root: /home/username and sudo chmod 755 /home/username to fix ownership and permissions.

SSH service fails to start after editing sshd_config Run sudo sshd -t before restarting the service to check the configuration for syntax errors. Fix any reported errors before restarting.

User can still log in via SSH Verify the user shell is set to /bin/false with getent passwd username. Also confirm the ForceCommand internal-sftp line is present inside the Match Group sftponly block in sshd_config.

SFTP connection is refused or times out Ensure the Subsystem sftp internal-sftp line is uncommented in sshd_config and the SSH service has been restarted. Check the SSH service status with sudo systemctl status ssh.

On Fedora, RHEL, and derivatives, use sudo systemctl status sshd instead.

FAQ

Can I allow SFTP access without granting SSH shell access? Yes. Set the user’s login shell to /bin/false and add ForceCommand internal-sftp inside the Match Group block. This allows SFTP connections while blocking interactive SSH sessions.

Does SFTP chroot support SSH key authentication? Yes. SFTP is a subsystem of SSH and supports all SSH authentication mechanisms, including key-based authentication.

Can multiple users share the same chroot setup? Yes. Add all users to the sftponly group and set ChrootDirectory %h so each user is jailed to their own home directory.

Why must the chroot directory be owned by root? OpenSSH requires the chroot directory to be owned by root and not writable by anyone else. If this condition is not met, the connection will fail with a “bad ownership or modes” error.

Conclusion

You have now set up an SFTP Chroot Jail on your Linux server, restricting SFTP users to their own home directories while blocking SSH shell access. For additional security, consider changing the default SSH port or enabling SSH key-based authentication to further harden your server.

Linuxize Weekly Newsletter

A quick weekly roundup of new tutorials, news, and tips.

About the authors

Dejan Panovski

Dejan Panovski

Dejan Panovski is the founder of Linuxize, an RHCSA-certified Linux system administrator and DevOps engineer based in Skopje, Macedonia. Author of 800+ Linux tutorials with 20+ years of experience turning complex Linux tasks into clear, reliable guides.

View author page