Dr Fragen in the operating room

chroot'd SFTP on Mac OS X server


So here you are finding that you need to grant someone else SFTP access to your server. There are lots of reasons to do this, in my case it’s because I needed to grant access to someone’s web designer. We initially worked it out by him emailing me files and me SFTP’ing them up to the server in the correct location. Now he needs direct access to fix some things and I want to give him only what he needs without compromising security. Enter the chroot jail. After lots of googling and some encouragement from the Mac OS X Server email list, I’ve got it working. Here’s how it works.
First, you should create the new user in Workgroup Admin and either assign them access privileges for SSH via Server Admin or assign them to a group that has SSH access privileges. Further discussion is below.
From the Terminal, start off right.

sudo cp /etc/sshd_config /etc/sshd_config.bkup
sudo chown root /
sudo chmod 755 /
sudo mkdir -p /chroot/user/scratchpad
sudo chown -R root /chroot
sudo chown user /chroot/user/scratchpad
sudo chmod -R 755 /chroot

Every additional new user added will then be something along the lines of the following.

sudo mkdir -p /chroot/user2/scratchpad
sudo chown root /chroot/user2
sudo chown user2 /chroot/user2/scratchpad
sudo chmod -R 755 /chroot/user2

Every folder in the path to the chroot jail must be owned by root. I don’t think it matters what group the folder is in. What I did above was to

  1. backup /etc/sshd_config
  2. change ownership of the root directory to root
  3. change permissions of the root directory to 755
  4. create a chroot folder
  5. create a user folder inside the chroot folder
  6. create a folder inside the user folder that user can modify
  7. set ownership and permissions

Now to edit /etc/sshd_config to the following.

#Subsystem sftp /usr/libexec/sftp-server
Subsystem sftp internal-sftp
Match User user
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
ChrootDirectory /chroot/userCode language: PHP (php)

This creates a chroot jail. When the user logs in will drop them into the folder /chroot/user, in that folder is a folder they can add things to /chroot/user/scratchpad.
If you want to create a Group in Workgroup Admin for ‘Chroot Users’ then add the new users that you created in Workgroup Admin to the Group; you won’t have to keep editing the /etc/sshd_config file. Instead of the above, add the following. Make sure you add the ‘Chroot Users’ group to the SSH access ACL in Server Admin.

#Subsystem sftp /usr/libexec/sftp-server
Subsystem sftp internal-sftp
Match Group chrootusers
X11Forwarding no
AllowTcpForwarding no
ForceCommand internal-sftp
ChrootDirectory /chroot/%uCode language: PHP (php)

If you have more than one chroot group just repeat the Match Group setup again.
To test whether the above is working, issue the following from the terminal.

$ sftp user@domain.com

Getting in is one thing. Now you have to mount the folder you want to use. Unfortunately you can’t use a symlink inside of a chroot jail. This is where Homebrew is your best friend. I don’t know why I’ve never seen fit to install this before. After installation just issue the following commands.

brew install bindfs

You might have to restart. Now with an empty folder created in /chroot/user you can mount --bind to a folder outside of the chroot jail. For example

sudo /usr/local/bin/bindfs -u user /Library/Server/Web/Sites/Server/Documents/mysite/yourfolder /chroot/user/scratchpad

So far this seems to work here.
Update for Mountain Lion Server
As I’ve updated my server from Snow Leopard to Mountain Lion, there’s one extra step.
From Workgroup Manager, you will need to create a home folder. Nothing really has to go into it, but it needs to be present. My settings are as follows.
Mac OS X Server/Share Point URL:afp://myserver.example.com/Users
Path to Home Folderusername
Full Path/Network/Servers/myserver.example.com/Users/username
After setting this up the first time it seems to auto-populate for every other user. You’ll have to go to the Home tab, select it and Save.


7 responses to “chroot'd SFTP on Mac OS X server”

  1. James Payne Avatar
    James Payne

    Nice post andy. Thanks for this. I’ve been searching for a solution to this problem and this works as far as read and write goes but (unless I’ve stuffed it up) it still gives you the ability navigate further up the tree to the root filesystem and see whats there. When I connect via the terminal, it takes me to the chrooted directory but I can still navigate to / in my FTP client (in my case fetch) Is this expected behaviour with the setup you’ve posted? It seems that I definitely can’t read or write in folders other than the chrooted directory but the thing that concerns me is you can still see the root filesystem. Thanks.

    1. Andy Fragen Avatar
      Andy Fragen

      James, I’m using Transmit and what I see as the ‘/’ directory when I log in using the restricted user is the /chroot/user directory. There doesn’t seem to be any ability to see further up the actual root directory. Are you sure you’re using the chroot’d user in Fetch?

  2. James Payne Avatar
    James Payne

    Well theres one thing you didn’t seem to mention – Did you create the user/password through the workgroup manager? If you did, did you do it using the local user db or an LDAP database? Also, did you actually specify a home directory or just leave that part of the user info blank? I also found that the sftp connection will not work unless you give that user access to the SSH service through server admin. Thanks.

  3. Andy Fragen Avatar
    Andy Fragen

    James, you are correct. I didn’t mention that I added the user via Workgroup Manager and then added the user access to the SSH service via Server Admin. The user was added to the LDAP database and I found that if I didn’t use Workgroup Manager locally, at the server, there were some strange issues (I kept seeing untitled_1 in my logs).

    Other than log in access, no other privileges were given to the user in WM, no home directory was specified. I guess if I were going to add a lot to chroot users I would create a group for them and them add the group SSH access.

  4. Andy Fragen Avatar
    Andy Fragen

    Added instructions in post to show how to use a group in Workgroup Admin instead of adding individual users. This means you only need to edit the /etc/sshd_config file once to add the group, not for each individual user. Then just create the users in Workgroup Admin and add them to the ‘Chroot Users’ group.

    1. Andy Fragen Avatar
      Andy Fragen

      Anne, glad you found this helpful and thanks for confirming it works on Mavericks.