How to Set Up 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
| Task | Command |
|---|---|
| Create SFTP group | sudo groupadd sftponly |
| Create chroot user | sudo useradd -g sftponly -s /bin/false -m -d /home/user user |
| Set home directory ownership | sudo chown root: /home/user |
| Set home directory permissions | sudo chmod 755 /home/user |
| Restart SSH (Debian/Ubuntu) | sudo systemctl restart ssh |
| Restart SSH (Fedora/RHEL) | sudo systemctl restart sshd |
| Test SSH config syntax | sudo 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:
sudo groupadd sftponlyAdding 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:
sudo useradd -g sftponly -s /bin/false -m -d /home/username username- The
-g sftponlyoption will add the user to the sftponly group. - The
-s /bin/falseoption 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/usernameoptions tell useradd to create the user home directory.
Set a strong password for the newly created user:
sudo passwd usernameIf the user you want to restrict already exists, add the user to the sftponly group
and change the user’s shell:
sudo usermod -G sftponly -s /bin/false username2The user home directory must be owned by root and have 755 permissions
:
sudo chown root: /home/username
sudo chmod 755 /home/usernameSince 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:
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
:
sudo nano /etc/ssh/sshd_configSearch 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:
Subsystem sftp internal-sftpTowards the end of the file, add the following block of settings:
Match Group sftponly
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding noThe 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:
sudo sshd -tOnce you are done, save the file and restart the SSH service to apply the changes. On Ubuntu and Debian:
sudo systemctl restart sshOn Fedora, RHEL, and derivatives, the SSH service is named sshd:
sudo systemctl restart sshdTesting 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:
sftp username@192.168.121.30You will be prompted to enter the user password. Once connected, the remote server will display a confirmation message and the sftp> prompt:
username@192.168.121.30's password:
sftp>Run the pwd command, and if everything is working as expected the command should return /:
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:
sftp> ls
public_html uploadsTroubleshooting
“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 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