rssh support chrooting option. If you want to chroot users, use chrootpath option. It is used to set the directory where the root of the chroot jail will be located. This is a security feature.


A chroot on Linux or Unix OS is an operation that changes the root directory. It affects only the current process and its children. If your default home directory is /home/vivek normal user can access files in /etc, /sbin or /bin directory. This allows an attacker to install programs / backdoor via your web server in /tmp. chroot allows to restrict file system access and locks down user to their own directory.

Configuring rssh chroot

=> Chroot directory: /users.
Tip: If possible mount /users filesystem with the noexec/nosuid option to improve security.

=> Required directories in jail:

  • /users/dev – Device file
  • /users/etc – Configuration file such as passwd
  • /users/lib – Shared libs
  • /users/usr – rssh and other binaries
  • /users/bin – Copy default shell such as /bin/csh or /bin/bash

=> Required files in jail at /users directory (default for RHEL / CentOS / Debian Linux):

  • /etc/
  • /etc/*
  • /etc/
  • /etc/nsswitch.conf
  • /etc/passwd
  • /etc/group
  • /etc/hosts
  • /etc/resolv.conf
  • /usr/bin/scp
  • /usr/bin/rssh
  • /usr/bin/sftp
  • /usr/libexec/openssh/sftp-server OR /usr/lib/openssh/sftp-server
  • /usr/libexec/rssh_chroot_helper OR /usr/lib/rssh/rssh_chroot_helper (suid must be set on this binary)
  • /bin/sh or /bin/bash (default shell)

Tip: Limit the binaries which live in the jail to the absolute minimum required to improve security. Usually /bin/bash and /bin/sh is not required but some system may give out error.

A note about jail file system

Note: The files need to be placed in the jail directory (such as /users) in directories that mimic their placement in the root (/) file system. So you need to copy all required files. For example, /usr/bin/rssh is located on / file system. If your jail is located at /users, then copy /usr/bin/rssh to /users/usr/bin/rssh. Following instuctions are tested on:

  • FreeBSD
  • Solaris UNIX
  • RHEL / Redhat / Fedora / CentOS Linux
  • Debian Linux

Building the Chrooted Jail

Create all required directories:
# mkdir -p /users/{dev,etc,lib,usr,bin}
# mkdir -p /users/usr/bin
# mkdir -p /users/libexec/openssh

Create /users/dev/null:
# mknod -m 666 /users/dev/null c 1 3
Copy required /etc/ configuration files, as described above to your jail directory /users/etc:
# cd /users/etc
# cp /etc/ .
# cp -avr /etc/ .
# cp /etc/ .
# cp /etc/nsswitch.conf .
# cp /etc/passwd .
# cp /etc/group .
# cp /etc/hosts .
# cp /etc/resolv.conf .

Open /usres/group and /users/passwd file and remove root and all other accounts.

Copy required binary files, as described above to your jail directory /users/bin and other locations:
# cd /users/usr/bin
# cp /usr/bin/scp .
# cp /usr/bin/rssh .
# cp /usr/bin/sftp .
# cd /users/usr/libexec/openssh/
# cp /usr/libexec/openssh/sftp-server .

# cp /usr/lib/openssh/sftp-server .
# cd /users/usr/libexec/
# cp /usr/libexec/rssh_chroot_helper

# cp /usr/lib/rssh/rssh_chroot_helper
# cd /users/bin/
# cp /bin/sh .

# cp /bin/bash .

Copy all shared library files

The library files that any of these binary files need can be found by using the ldd / strace command. For example, running ldd against /usr/bin/sftp provides the following output:
ldd /usr/bin/sftp
Output: =>  (0x00456000) => /lib/ (0x0050e000) => /lib/ (0x0013e000) => /lib/ (0x008ba000) => /usr/lib/ (0x00110000) => /lib/ (0x0080e000) => /lib/ (0x00a8c000) => /usr/lib/ (0x00656000) => /usr/lib/ (0x00271000) => /usr/lib/ (0x00304000) => /lib/ (0x00777000) => /lib/ (0x00123000) => /usr/lib/ (0x00569000) => /lib/ (0x00b6c000) => /usr/lib/ (0x00127000) => /lib/ (0x00130000)
        /lib/ (0x00525000) => /usr/lib/ (0x008c9000) => /usr/lib/ (0x00133000) => /usr/lib/ (0x00d04000) => /lib/ (0x0032a000) => /lib/ (0x00341000) => /lib/ (0x00964000)

You need to copy all those libraries to /lib and other appropriate location. However, I recommend using my automated script called l2chroot:
# cd /sbin
# wget -O l2chroot
# chmod +x l2chroot

Open l2chroot and set BASE variable to point to chroot directory (jail) location:
Now copy all shared library files
# l2chroot /usr/bin/scp
# l2chroot /usr/bin/rssh
# l2chroot /usr/bin/sftp
# l2chroot /usr/libexec/openssh/sftp-server

# l2chroot /usr/lib/openssh/sftp-server
# l2chroot /usr/libexec/rssh_chroot_helper

# l2chroot /usr/lib/rssh/rssh_chroot_helper
# l2chroot /bin/sh

# l2chroot /bin/bash

Modify syslogd configuration

The syslog library function works by writing messages into a FIFO file such as /dev/log. You need to pass -a /path/to/chroot/dev/log option. Using this argument you can specify additional sockets from that syslogd has to listen to. This is needed if youÒ€ℒre going to let some daemon run within a chroot() environment. You can use up to 19 additional sockets. If your environment needs even more, you have to increase the symbol MAXFUNIX within the syslogd.c source file. Open /etc/sysconfig/syslog file:
# vi /etc/sysconfig/syslog
Find line that read as follows:
Append -a /users/dev/log
SYSLOGD_OPTIONS="-m 0 -a /users/dev/log"
Save and close the file. Restart syslog:
# /etc/init.d/syslog restart
If you are using Debian / Ubuntu Linux apply changes to /etc/default/syslogd file.

Set chroot path

Open configuration file /etc/rssh.conf:
# vi /etc/rssh.conf
Set chrootpath to /users
Save and close the file. If sshd is not running start it:
# /etc/init.d/sshd start

Add user to jail

As explained eariler, configure rssh user account. For example, add user vivek in chrooted jail with the following command:
# useradd -m -d /users/vivek -s /usr/bin/rssh vivek
# passwd vivek

Now vivek can login using sftp or copy files using scp:

sftp's password:
sftp> ls
sftp> pwd
Remote working directory: /vivek
sftp> cd /tmp
Couldn't canonicalise: No such file or directory

User vivek is allowed to login to server to trasfer files, but not allowed to browse entier file system.

πŸ₯Ί Was this helpful? Please add a comment to show your appreciation or feedback.

nixCrat Tux Pixel Penguin
Hi! 🀠
I'm Vivek Gite, and I write about Linux, macOS, Unix, IT, programming, infosec, and open source. Subscribe to my RSS feed or email newsletter for updates.

61 comments… add one
  • X Jul 8, 2011 @ 2:14

    Everyone stuck at:

    “… ssh_chroot_helper[4470]: changing working directory to / (inside jail)”

    but then getting a refused connection on your sftp client. *Trust other posters* in that it is a library issue… I thought it was bullshit myself and almost gave up hope (no aparent error on my /var/log/syslog). My last resort was to copy all the files in the /lib folder to the /chroot/lib folder. Use the -p and –preserve=link switches so you preserve permissions and links (otherwise linked libraries will be copied as a file…).

    cp -v -p -d –preserve=link /lib/* /chroot/lib/

    It *will* work… Now it’s a matter of deleting one by one (if you want) and figuring it out the minimum subset required. In my case (Ubuntu 11.04 server):

    I also followed all previous suggestions in the earlier comments on this site (e.g., adding user to /chroot/etc/passwd… etcetera). Good hunting!

  • Amit Jul 8, 2011 @ 5:22

    Try to upgrade openSSH version and enjoy the new inbuilt jailroot system. Much easier.

    CyberCiti : please post an article for the same.

  • Solaria Jul 22, 2011 @ 20:29

    Got this working on Solaris, works well. Here are some of the errors encountered, and the solutions:

    Error: unknown user xxx

    Occurs during SCP. Missing “nss* lib in chroot, copy /lib/ to chroot. (Solaris 10)

    Error: connection closed

    Occurs during SFTP. Missing *ksh* in chroot, copy /bin/ksh and/or /usr/bin/ksh to chroot

    Error: connection closed

    Occurs during SCP on Solaris 9. Missing *nss* lib in chroot, different library path than in Solaris 10. Copy /usr/lib/ to chroot.

    Error: rssh_chroot_helper failed, Not owner

    /usr/local/libexec/rssh_chroot_helper must be SUID root

    Error: user attempted to execute forbidden commands; /usr/lib/ssh/sftp-server

    Occurs during SFTP, logged in /var/adm/messages. Target system had both OpenSSH and SolarisSSH, error caused by conflict between rssh config and sshd_config. run ‘/usr/local/bin/rssh -v’ to get sftp server binary path, compare to ‘Subsystem sftp’ path in sshd_config (both config files, OpenSSH and SolarisSSH). Edit sshd_config to match rssh config.

    Found a pretty good script file for setting up the chroot on Solaris…

  • tgutierrez Sep 9, 2011 @ 22:56

    This work perfectly,at first I’d connection problems but these problems were fixed just adding /chroot/lib64/
    I have RHEL 6


  • Gustavo Sep 10, 2011 @ 3:36

    Very good tutorial, I wonder if there is no way to change the message out to access “This account is restricted by rssh.
    Allowed commands: scp

    If you believe this is in error, please contact your system administrator.

    For another message.

    Thank you for your help. Greetings from Colombia

  • Loshen Sep 12, 2011 @ 8:40

    In version 5, jailing is now natively supported.
    The problem is that SSH with centos 5.5 lower came with ssh 4.8 < .
    So if you upgrade you will automatically get Jailing.
    I followed these instructions.

  • Sean Ackley Mar 22, 2012 @ 22:21

    Vivek, this is a crazy good utility to use, made my life so much easier when I implemented chroot.

    I ran into one issue, in which certain utilities like “vim” and “file” require support libraries under /usr/share. I also needed to include /usr/share/locale and /usr/share/terminfo (for “vim” for instance.

    Is there a way to check within l2chroot for these support libs as well? It makes the installation a little more bullet proof.

    Thanks so much.

  • Eli Wapniarski Apr 2, 2012 @ 9:21

    You can confine the user to their home folder by changing permissions on all the folders other than their home folder to 751. As per the example in this article:

    cd /
    chmod 751 users
    cd users
    find . -type d -exec chmod 751 {} ;

    If you need to return the home folder back to normal permissions then:

    chmod 700 vivek
    cd vivek
    find . -type d -exec chmod 755 {} ;

  • Sergios Jul 18, 2012 @ 15:20

    If user home is chmod 700
    And internal folders is find . -type d -exec chmod 755 {} ;
    How is possible to readable by apache2 the public_html , or if we execute the username:nobody /home/username/public_html and set the virtual host is can readable by the world ?
    Thank you.

  • TooMeeK May 5, 2013 @ 0:46

    Hi, just discovered problem on 64-bit OS, not copying shared libs:
    l2chroot /usr/bin/scp
    Copying shared files/libs to /home/jails…
    Copying /lib64/ /home/jails/lib64…

    when it should be:
    ldd /usr/bin/scp => (0x00007fff4e35f000) => /lib/x86_64-linux-gnu/ (0x00007ffb9ed2e000)
    /lib64/ (0x00007ffb9f2cf000)

  • David Beecher Dec 21, 2015 @ 2:46

    This is one area where SSH really falls down. I’ve looked at other options like RSSH– what a joke. Unnecessarily complex. This should be just as easy as implementing cvsroot for ftp. Well, it is but nobody seems to know about it– take a look at Minstrel– have been using this solution production since 2008 without a single problem Just specify the user’s shell and the appropriate path to their home directory and voila, root-jailed sftp only.:

Leave a Reply

Your email address will not be published. Required fields are marked *

Use HTML <pre>...</pre> for code samples. Your comment will appear only after approval by the site admin.