view · edit · print · history

This howto covers the setup of a chroot jail for an account that is intended to be accessed via sftp.


Why a chroot jail? Firstly for security. Secondly the user can access only a limited part of the filesystem. Of course you can do quite a lot with carefully defining and setting permissions and ownership. But still quite a lot of the file system would be visible. Which most likley you do not want. At least I do not want it at my Slug. I want to lock the sftp user it its home directory with very limited functionality. An interactive SSH session is not required. The account is intended to share files between friends. This page describes how to setup a chroot jail at OpenSlug. It is very generic, so I expect it will work at other firmware versions as well.

There is a patch around that adds chroot functionality to the OpenSSH server directly. But there is no package for this OpenSSH patch available at our Slug. I didn't want to go throug the hassle to compile it myself. So I looked for another solution. It is possible to implement a chroot jail using existing packages and a little script. This is what this page describes.

What is not described here


This page assumes that you use public key authentication for logging in to the SSH server. So carefully follow the UseOpenSSHForRemoteAccess. Also the user account you want to use has been setup already.

Required packages

The next packages must be installed to make this all work. If not available at your Slug, then install them.

  • bash (ipkg install bash)
  • sudo (ipkg install sudo)
  • OpenSSH (ipkg install openssh)
  • OpenSSH sftp server (ipkg install openssh-sftp)

Account setup

Setup an account for sftp access. For this example the username will be public and the groupname will be remote. The home directory is /home/public. In this directory, create the next directories:

  • .ssh
  • bin
  • dev
  • etc
  • lib
  • usr
  • usr/lib
  • usr/libexec
  • public

The directories .ssh and public should be owner by public:remote. Others by root:root. Permissions must be 755 for all except .ssh, this must be 700. The .ssh directory should contain the authorized_keys file for public key authentication. This is still normal, the other directories contain copies from specific files from the real file system. All commands in the next sub sections must be executed as root.

Directory bin

cd /home/public/bin
cp /bin/busybox .
cp /bin/tinylogin .
ln -s busybox sh
ln -s tinylogin su

Directory dev

Here you must create two devices required for OpenSSH. Execute the next commands:

cd /home/public/dev
mknod -m 0666 tty c 5 0
mknod -m 0644 urandom c 1 9

Directory etc

Create a group and passwd file here. The content of the group file should be:


Assuming that 64006 is the group id of your remote group the real /etc/group. Adjust this to your own needs. You might want to add other group names that might put files/directories in the account when in use.

The content of the passwd file should be:

public:*:507:64006:sftp account,,,:/public:/bin/sh

Again, assuming that 64006 is the group id of your remote group in both /etc/group and /home/public/etc/group. And that 507 is user id of public in the real /etc/passwd as well. You might want to add other user names that might put files/directories in the account when in use.

Directory lib

Simply copy everything from the real /lib to /home/public/lib:

cd /home/public/lib
cp -R /lib/* .

TODO - I have to admit, I need to do some optimization here. Firstly the symlinks in /lib are copied as real files. Secondly I did not check, which are actually needed. I will do that and then update this page accordingly.

Directory public

This one remains empty. This will contain the actual files when the account is in use. This will be the home directory of the chroot-ed user.

Directory usr

This directory only contains the lib and libexec subdirectories.

Directory usr/lib

This directory contains the next libraries (copied from /usr/lib):

  • libcrypto.so.0.9.7
  • libz.so.1

Directory usr/libexec

This directory contains actual sftp server (copied from /usr/libexec):

  • sftp-server

Final settings

Fake shell

Now you must create a 'fake shell' This shell will be started when the public user log on the Slug. This fake shell is actually a script, which performs the change root actual. As chroot can be executed by root only, we must use sudo to be able to make this work. Create a new shell script and name it /bin/chrootshell. Its contents must be:

if [ "$1" = "-c" ]; then 
        for param in $*; do 
                if [ $i -gt 0 ]; then 
                        PARAMS="$PARAMS $param"; 
                let i++; 
        sudo /usr/sbin/chroot /home/$USER /bin/su - $USER -c "$PARAMS" 
        echo "Interactive login not allowed!"                  
        # comment out this line (and the next line) when you want to allow an interactive login
        exit 1
        # sudo /usr/sbin/chroot /home/$USER /bin/su - $USER
        # uncomment this line when you want to allow an interactive login

make sure you set the permissions of this file to 755.
This fake shell will terminate with an error message in case an interative login is started. So, this fake shell only allows the SFTP connection. See the comment in the false-branch of the if-then-else construction what to di in case you do want to enable interactive logins.

Setup sudo

Edit the /etc/sudoers' using visudo. Add the next line at the end of the sudoers file:

public ALL= NOPASSWD: /usr/sbin/chroot /home/public /bin/su - public*

Setup the real public account

You did already setup a real system account named public. This must be adapted slightly. Edit the real /etc/passwd file and Make sure it has the next content for the line that defines the public user:

public:x:507:64006:sftp user,,,:/home/public:/bin/chrootshell

Of course the clue is in the entry that defines the shell for this public account. Which actually is the script that we just have created.

Orginal home directoy

I changed the permissions and ownership of the orginal home directory. Now root:root owns /home/public. Permissions have been set to 755. This prevents the user to write anywhere but the /home/public/public (when in the chroot jail /public) directory.


For the major part this solution is based upon work by Tony J. White and Brian Rhodes found at http://www.tjw.org/chroot-login-HOWTO .

view · edit · print · history · Last edited by marceln.
Based on work by marceln and marty_k71.
Originally by marty_k71.
Page last modified on June 23, 2007, at 09:16 PM