How to Configure Chroot SFTP Server in Linux

There are some scenario where system admin wants only few users should be allowed to transfer files to Linux boxes but no ssh. We can achieve this by setting up SFTP in chroot environment.

Background of SFTP & chroot :

SFTP stands for SSH File Transfer protocol or Secure File Transfer Protocol. SFTP provides file access, file transfer, and file management functionalities over any reliable data stream. When we configure SFTP in chroot environment , then only allowed users will be limited to their home directory , or we can say allowed users will be in jail like environment where they can’t even change their directory.

In article we will configure Chroot SFTP server on RHEL & CentOS system . We have one user ‘Jack’ , this user will be allowed to transfer files on Linux box but no ssh access.

Step :1) Create a group

Create sftp_users group using groupadd command,

[root@localhost ~]# groupadd  sftp_users

Step: 2) Assign the secondary group(sftp_users) to the user

If the users doesn’t exist on system , use below command command to create it,

[root@localhost ~]# useradd  -G sftp_users -s /sbin/nologin  jack
[root@localhost ~]# passwd jack

For already existing users , use below usermod command :

[root@localhost ~]# usermod –G sftp_users -s /sbin/nologin  jack

Note : If you want to change the default home directory of users , then use ‘-d’ option in useradd and usermod  command and set the correct permissions.

Step :3) Now edit the config file “/etc/ssh/sshd_config”

Edit the sshd_config using your favorite editor,

# vi /etc/ssh/sshd_config

#comment out the below line and add a line like below
#Subsystem sftp /usr/libexec/openssh/sftp-server
Subsystem sftp internal-sftp

# add Below lines at the end of file
Match Group sftp_users
X11Forwarding no
AllowTcpForwarding no
ChrootDirectory %h
ForceCommand internal-sftp

Where :

Match Group sftp_users – This indicates that the following lines will be matched only for users who belong to group sftp_users
ChrootDirectory %h – This is the path(default user’s home directory) that will be used for chroot after the user is authenticated. So, for Jack, this will be /home/jack.
ForceCommand internal-sftp – This forces the execution of the internal-sftp and ignores any command that are mentioned in the ~/.ssh/rc file.

After making the above changes, restart the ssh service using following command,

[root@localhost ~] # systemctl restart sshd

Step :4) Set the required permissions on user’s home directory

As in our demonstration we are using jack user as sftp user, so run the following commands to set the required permissions on his home directory,

[root@localhost ~]# chmod 755 /home/jack
[root@localhost ~]# chown root /home/jack
[root@localhost ~]# chgrp -R sftp_users /home/jack

In case you want that jack user should be allowed to upload files, then create a upload folder with the below permissions ,

[root@localhost jack]# mkdir /home/jack/upload
[root@localhost jack]# chown jack. /home/jack upload/

In case selinux is enabled on your system then execute the following command to set selinux rules

[root@localhost ~] setsebool -P ssh_chroot_full_access on

Step :5)  Test Sftp server

First try to access the system using ssh via jack user,

ssh-try

As we can see in output above user jack is allowed to ssh.

Now let’s try to login using sftp,

sftp-login

As you can see above,  jack user is logged in via SFTP and but can’t change the directory because of chroot environment.

Now do the uploading and downloading testing as shown below:

sftp-upload-download

As we can see above , both uploading & downloading working fine for jack user. That’s conclude the article, you are most welcome to share your feedback and comments in the comments sections below. 

Also Read How to Configure SFTP Server with Chroot in Debian 10

14 thoughts on “How to Configure Chroot SFTP Server in Linux”

  1. I like sftp much better than regular FTP. Main reason, you can exchange keys for user that use SFTP so there are no passwords. This improves security on your server!!!

    Reply
  2. I have followed the exact steps given in the tutorial, but I am getting error in uploading a file. I am able to downlaod any files.
    sftp> put sftp_file
    Uploading sftp_file to /upload/sftp_file
    remote open(“/upload/sftp_file”): Permission denied
    sftp>

    Is SELinux need to be configured anyway?

    Reply
    • Hi Gopal ,

      If Selinux is enable on your linux box , then for Chroot SFTP you need to write SELiux rule “setsebool -P ssh_chroot_rw_homedirs on”.

      I hope this might help you.

      Reply
  3. Following the same exact instructions In ubuntu 14.04 I got an error after entering the password when invoking ssh wstest@localhost : Write failed broken pipe

    Reply
    • Hi ,

      These steps are tested on CentOS 6.X and RHEL 6.X , i am not sure whether these steps will work on Ubuntu Linux.

      Reply
    • I usually see this error when I don’t have ‘root’ set as the owner & group and 755 for permissions of the user’s directory (‘Jack’ in the author’s example).

      Reply
  4. This line needs some improvement

    [root@localhost jack]# chown jack. /home/jack upload/

    1) All the commands above have absolute directory paths. This command make assumption that it’s in the directory /home.
    2) There is a . DOT after jack ? Either a typo or means current directory. See 1.
    3) Why upload/ is this just upload or /home/jack/upload ?

    [root@localhost jack]# cd /home/jack ; chown jack $PWD /home/jack/upload

    Reply
    • Hi Fred ,

      I have used . DOT after jack in chown command because i want to make this user both File Owner and Group Owner of upload folder. I have choose upload folder because i want jack user to upload its files and directory on upload directory only.

      Reply
  5. I’ve gone through this step by step, but when I try to log in using WinSCP, I get “Error listing directory ‘/upload’ Permission denied.
    Error code: 3
    Error message from server: Permission denied
    Request code: 11

    I can go into the folder, but I can’t list anything, and when I try to upload a file I get Permission denied.
    Error code: 3
    Error message from server: Permission denied
    Request code: 3

    Reply
  6. Okay, when I put SELinux in Permissive mode, it works. I’m running CentOS 6, and I tried your setsebool -P ssh_chroot_rw_homedirs on but it didn’t work.

    Sorry for the multiple posts

    Reply
  7. These instructions WILL NOT work for Ubuntu Linux and you will effectively lock yourself (admin/root) out if working remotely.

    Reply

Leave a Comment