How to configure an sftp server with restricted chroot users with ssh keys

Solution Verified - Updated -


  • Red Hat Enterprise Linux 8
  • Red Hat Enterprise Linux 7
  • Red Hat Enterprise Linux 6


  • Restrict chroot users to sftp connections using ssh keys without affecting normal user's access.


  • Configuring a SFTP server with chroot users and ssh keys

Server setup

  1. Create the user on the server

    [root@server ~]# useradd user1
    [root@server ~]# passwd user1

Client setup for password-less login

  1. Copy the ssh key from the client to the server (The user does not have to exist on the client)

    [clientuser@client ~]$ ssh-copy-id user1@server
  2. Verify the ssh key works correctly from the client

    [clientuser@client ~]$ ssh user1@server
    [user1@server ~]$ exit
    Connection to server closed.
    [clientuser@client ~]$ 
  3. Verify that your sftp connection works without a password prompt

    [clientuser@client ~]$ sftp user1@server
    Connected to server
    sftp> quit
    [clientuser@client ~]$

Without making any changes, user1 has full access and can ssh or sftp and change to any directory. We'll now make the necessary changes
to chroot user1 and keep them jailed and locked down to a specified directory.

Server setup for sftp only

  1. Create a new group to add all your jailed chroot users on the server

    [root@server ~]# groupadd sftpusers
  2. Create a common directory for all of your jailed chroot users

    [root@server ~]# mkdir /sftp
  3. Create a subdirectory for each individual user that you want to chroot

    [root@server ~]# mkdir /sftp/user1
  4. Create the "home" directory for the user

    [root@server ~]# mkdir /sftp/user1/home
  5. Modify the user to add them to the new group you created

    [root@server ~]# usermod -aG sftpusers user1
  6. Change permission for the users chrooted "home" directory only. It's important to leave everything else with the default root permissions.

    [root@server ~]# chown user1:sftpusers /sftp/user1/home/
  7. Modify the /etc/ssh/sshd_config file and add the following lines:

    Subsystem   sftp    internal-sftp -d /home
    Match Group sftpusers
    ChrootDirectory /sftp/%u
  8. Restart the sshd service

    • RHEL 7 and later:

      [root@server ~]# systemctl restart sshd
    • RHEL 6

      [root@server ~]# service sshd restart

Client verification

  1. From the client, verify that everything is working now

    [clientuser@client ~]$ ssh user1@server
    Last login: Sat Jun 25 12:54:32 2016 from
    Could not chdir to home directory /home/user1: No such file or directory
    /bin/bash: No such file or directory
    Connection to server closed.
    [clientuser@client ~]$ 
    • The user can no longer connect via ssh. Let's try sftp:

      [clientuser@client ~]$ sftp user1@server
      Connected to server.
      sftp> pwd
      Remote working directory: /home
      sftp> cd /etc
      Couldn't canonicalize: No such file or directory
    • OK, the user can successfully connect via sftp and they are still restricted to their "home" directory.

  2. Make sure a regular user can still log in via ssh without the chroot restrictions

    [clientuser@client ~]$ ssh user2@server
    Last login: Sat Jun 25 13:49:43 2016 from
    [user2@server ~]$ 

You have successfully configured a sftp server with jailed chroot users with ssh keys

This solution is part of Red Hat’s fast-track publication program, providing a huge library of solutions that Red Hat engineers have created while supporting our customers. To give you the knowledge you need the instant it becomes available, these articles may be presented in a raw and unedited form.


It helped me

I'm glad it helped you. Thank-you !

is it possible to have multiple users access 'user1' home folder ?

May need this also...

setsebool -P selinuxuser_use_ssh_chroot 1

What exactly does that do? It appears undocumented? I want to ensure it doesn't soften security elsewhere.

Should there be a step where the user's .ssh dir is copied into the chroot so ssh keys will work?

What I did is the following: 1) create a directory /etc/ssh-pool 2) modify sshd_config to add: AuthorizedKeysFile /etc/ssh-pool/ 3) add public keys to the directory /etc/ssh-pool and rename them to 4) Set ownership to user:group and set permissions 600 5) restart sshd service So for user named johndoe , the public key is named

You can put the ssh keys in whatever directory you wish as long as the location is listed correctly in the sshd_config file.

On my redhat-release-server-7.3-7.el7 I faced with: server sshd[19998]: /etc/ssh/sshd_config line 156: Subsystem 'sftp' already defined. server systemd[1]: sshd.service: control process exited, code=exited status=255 server systemd[1]: Failed to start OpenSSH server daemon.

Because of:

override default of no subsystems

Subsystem sftp /usr/libexec/openssh/sftp-server


Currently I have a request to access a folder under chroot directory I need to grant permission to a user which is able to do ssh but not to the sftp service, What do I need to do in order to can solve this?

I will really appreciate if somebody can help me to do this.

This is the OS version. REDHAT_BUGZILLA_PRODUCT="Red Hat Enterprise Linux 8" REDHAT_BUGZILLA_PRODUCT_VERSION=8.5

Regards, Carlos.

Great documentation!

If anyone of you wants to give access to some files outside of the /sftp/user1/home directory, symlinking won't work since the user is chrooted. You can use the binded mount instead.

For example here I am giving the sftp users access to /public_data/

mkdir -p /sftp/user1/home/data
mount --bind /public_data/ /sftp/user1/home/data

Make sure that you had provided enough permissions on /public_data to the sftpusers group

Thanks for the info. Do you know how to show/list bindings and how to unbind? Found listing, and umount

# sudo mount --bind /data /sftp/sftpuser/home <enter>
# sudo findmnt | grep  "\[" <enter>

└─/sftp/sftpuser/home                 /dev/mapper/rootvg-root[/data]      xfs         rw,relatime,attr2,inode64,noquota
# sudo umount /sftp/sftpuser/home

As far as i know, the only way to unbind the directory is by using the unmount command. As you mentioned in your comment you can find the binded mounts by using the:

sudo findmnt | grep  "\["

and using the

sudo unmount <path>
rm -rdf <path>

You can also use some tools like ansible if you want to automate this.