How to create a sftp chroot jail

What is a sftp chroot jail?

SFTP Chroot Jails are a simple and easy way of creating a secure area on your Linux system that can be used for transferring files. A SFTP chroot jail allows you to create a secure directory that confines a user to specific area.

In the following example we will create a SFTP chroot jail that will confine a user to a particular directory. Our remote server is running CentOS 8. We will be connecting to our sftp server from an Linux Mint 20 system. The following sections will take you through the set-up process that is required.

SFTP Chroot Jail

First we are going to modify the file "/etc/ssh/sshd_config" on the remote "CentOS" server. Comment out the line that begins Subsystem and replace it with the following line:


Subsystem       sftp    internal-sftp

Next add the following lines to the bottom of the same file:


Match Group sftpgroup
      ChrootDirectory %h
      ForceCommand internal-sftp
      AllowTcpForwarding no
      X11Forwarding no

The file "/etc/ssh/sshd_config" is the OpenSSH Daemon configuration file. Below is an explanation of the parameters used above:

Subsystem - The subsystem option allows for the configuration of an external subsystem. The basic syntax is for a subsystem name, followed by a command.
On our system we are specifying “internal-sftp” which allows us to implement an in process "sftp” server. This is used to simplify the configuration of a ChrootDirectory.

Match - Is known as a conditional block. If all of the criteria of the Match line are met, then the following lines are used instead of the settings found in the global section.

In our example we are specifying a "Group" called "sftpgroup". You may change this name to something that matches your system naming convention. This line means that the following lines will only be applicable to members of the specified group.

ChrootDirectory %h - Specifies that the user will be chrooted to their home directory.

The line "ForceCommand internal-sftp" will force execution of the internal-sftp subsystem.

The line "AllowTcpForwarding no" Specifies whether TCP forwarding is permitted. The default setting is “yes”. Note that disabling TCP forwarding does not improve security unless users are also denied shell access.

X11Forwarding no - Specifies that X11 forwarding is not allowed.

Creating a sftp user and group

The next part of this tutorial will show you how to create the user and group that we are going to use in our example. Here we will be using standard commands for the creation of the user and associated group.

Again, these commands are issued on the CentOS system.

Create a sftp group

To create a group we use the command "groupadd". Note the group you create must be the group that you have specified in the "sshd_config" file. In our example we will create a group called "sftpgroup".


groupadd sftpgroup

Create the sftp user account on CentOS server

To create a user, we will use the "useradd" command. Here we will specify that the user must be a member of the group "sftpgroup and that their default shell is set to "nologin. By specifying the "nologin" option, we can limit the users access to only a sftp connection.


useradd -G sftpgroup -s /sbin/nologin sftpuser

Change the ownership and permissions of the sftpuser

When using a chroot jail, it is important to set the specified top level directory to be owned by root. To change the ownership from the normal user to that of the root user, we use the command chown.


chown root:root /home/sftpuser

Next we change the permissions on the directory as follows:


chmod 755 /home/sftpuser/

Create directory structure for sftpuser

In the next step we will create an upload and download directory structure. We will then grant the necessary privileges to the sftpuser.


cd /home/sftpuser/

mkdir upload

mkdir download

chown sftpuser:sftpgroup upload

chown sftpuser:sftpgroup download

You should now have a similar directory structure with the following ownership and permissions set.


# ls -ld /home/sftpuser/
drwxr-xr-x. 6 root root 4096 Jun  7 09:37 /home/sftpuser/

# ls -ld /home/sftpuser/upload/
drwxr-xr-x. 2 sftpuser sftpgroup 4096 Jun  7 09:37 /home/sftpuser/upload/

# ls -ld /home/sftpuser/download/
drwxr-xr-x. 2 sftpuser sftpgroup 4096 Jun  7 09:37 /home/sftpuser/download/

Create a Password for the sftpuser

For the user to access the server, a password will need to be assigned to the account that was created earlier. To do this, we will use the command "passwd".


passwd sftpuser

Testing access to the SFTP Server

The final test now is to connect to our test server.


john@mint01a:~$ sftp sftpuser@192.168.122.75
sftpuser@192.168.122.75's password: 
Connected to 192.168.122.75.

sftp> pwd
Remote working directory: /

sftp> ls
download  upload    

sftp> lcd /home/john

sftp> cd upload/

sftp> put test.txt
Uploading test.txt to /upload/test.txt
test.txt                                                             100%   16     0.9KB/s   00:00    

sftp> cd ..

sftp> pwd
Remote working directory: /

sftp> cd download/
sftp> pwd
Remote working directory: /download

sftp> cd /
sftp> pwd
Remote working directory: /

sftp> quit

In the above example we initiated our sftp connection by issuing the command: sftp sftpuser@192.168.122.75

(sftpuser is the user we are using to connect with and the address 192.168.122.75 is the address of our remote CentOS server).
You can replace this address with your address or the hostname of the server you are connecting to.

First we issue the command "pwd" as this will display our current working directory.

If we issue the "ls" command we can see the two directories that we created earlier.

Next I changed the remote directory to the upload directory using the command "cd upload".

As a test I then changed the local directory on the local machine (Linux Mint) to "/home/john" where I have a small test file called "test.txt". The command "lcd" is used to specify a local directory to be used.

As I test I used the "put command to upload a file to the remote directory. The output can be seen in the above example.

Note, when the command "cd /" is issued, we are taken to the "root" directory of our chroot jail.