I need to create an SFTP only user on CentOS 7. I've read how to do it from various sources. The setup needs to only support a single user with SFTP only access to a single folder.

If the user's home directory is /home/user and in sshd_config I have ChrootDirectory as %h, given that sshd will change directory to /home/user AFTER the chroot:

ChrootDirectory Specifies the pathname of a directory to chroot(2) to after authentication. All components of the pathname must be root-owned directories that are not writable by any other user or group. After the chroot, sshd(8) changes the working directory to the user's home directory.

How does this work? Surely it will fail, because sshd will try to CD to /home/user/home/user?

Supplementary question: Is there a best practise for whether to chroot such a user in the home directory as defined when creating the user, or having them chrooted outside of /home e.g. /var/sftp/user? When creating a chroot outside of /home, what is the purpose of the user's home directory? Is it still used to read ~/.ssh/authorized_keys?

2 Answers 2


You'll need to pay attention to the other restriction placed on the directory used as ChrootDirectory: All components of the pathname must be root-owned directories that are not writable by any other user or group. If the user needs to be able to write to their own home directory inside the chroot, then the home directory must not be the same as ChrootDirectory.

Historical note:

The chroot support of OpenSSH originated as a separate patch, and even after it was integrated to the main OpenSSH distribution the exact requirements placed on the directory used as ChrootDirectory have changed with different OpenSSH versions. Newer versions generally tend to enforce more strict requirements than older ones, in response to discovered security vulnerabilities in previous set-ups.

Also, the requirement to have the same home directory path be applicable both inside and outside the chroot is clearly suboptimal, and some distributions have applied patches to modify the behavior. Unfortunately, not all such patches in the past have included updates to the man pages and other relevant documentation.

But to satisfy the requirements as written, you could do this, for example:

mkdir -p /jail/username/home

# First, the chroot directory:
chown root:root /jail/username
chmod 755 /jail/username

# Then, the user's home directory:
chown username: /jail/username/home
chmod 750 /jail/username/home
usermod -d /jail/username/home username

# And here's the magic:
cd /jail/username
ln -s . jail       # this would normally be a silly thing to do
ln -s . username   # but with chroot it can be useful

Now, we can set ChrootDirectory /jail/%u.

When viewed outside the chroot, the user's home directory will be /jail/username/home. A bit of a departure from the normal naming convention, but otherwise nothing special.

And inside the chroot, the same home directory path will indeed refer to /jail/username/jail/username/home... but did you see those two silly symbolic links above? Dereference them, and you'll get /jail/username/././home, which ends up being exactly the same as /jail/username/home. And so the same path ends up pointing to the same place both inside and outside the chroot.

The user inside the chroot will see their home directory as /jail/username/home = /././home = /home, and they can use it as normal. They will be able to see one level above their home directory, /, but only root can write there.

This will also allow things like syslog-style logging: you can create a root-owned directory /jail/username/dev and tell rsyslog to create an extra /dev/log-style socket at /jail/username/dev/log... and now the chrooted user can produce log messages and have them handled by the regular syslog subsystem.

This is by no means the only way to arrange the chroot environment, although the above-style setup makes the user's home directory as normal (= no symlinks nor other weirdness) as possible for processes outside the chroot, if that is important.

If you instead want a chroot that is maximally sterile for the jailed user, you could do it this way instead:

mkdir -p /jail/username/username

# Prepare the chroot directory
chown root:root /jail /jail/username
chmod 755 /jail /jail/username

# Prepare the user's actual home directory
chown username: /jail/username/username
chmod 750 /jail/username/username

# Make it usable outside the chroot too
ln -s /jail/username/username /username

# And now it can be assigned to the user.
usermod -d /username username

Again, we set ChrootDirectory /jail/%u.

Outside the chroot, /username will be a symbolic link pointing to /jail/username/username, so the user's home directory will be valid.

For chrooted processes /username will be just a regular directory, perfectly usable as user's home directory.

Yes, the actual pathnames are a bit repetitive, and the symbolic links will clutter up the root directory of the system, but there will be nothing extraneous inside the chroot environment.

And if the only thing the chrooted user needs is SFTP, the accepted answer to this question describes an even simpler way.

  • I will need a PHP process to be able to read and write in the "home" directory (in your example) but I had assumed with the correct ACLs and permissions this would just work, so didn't include that detail in my question. Is that not the case? Sep 18, 2019 at 19:23
  • Yes, that works... however, if you use SSH key authentication for SFTP, remember that neither the ~/.ssh directory, the user's home directory, nor any directory above it can be writeable by anyone other than the user themselves and root, or else sshd will ignore the authorized_keys file on the assumption that it may have been tampered with. But you can certainly create a sub-directory under the home directory with absolutely any permissions you need.
    – telcoM
    Sep 18, 2019 at 19:28
  • Perfect. So the clever symlink trick is only required so that sshd can CD to the user's home directory after the chroot and end up at the same place. Odd that I've not seen this approach written in any of the many threads read dealing with setting up chroots for user home directories. The purest in me doesn't like the fact that one level up the user will see .ssh, username and home but I like less that the user's home directory wouldn't resolve to a valid path. I'm assuming it's a good idea to actually set a home folder for the user? Sep 18, 2019 at 19:45
  • I did see the accepted comment of the post you linked to, but I'm not sure how to make that work, as I don't have separate mount points. You're right that I'm only interested in the SFTP user connecting via SFTP and dropping and reading files. Sep 18, 2019 at 19:48
  • Not setting a home directory is not really possible: a user needs to have a home directory somewhere and it needs to be inside the chroot or else sshd will complain about the home directory not being available, which might alarm the user. Note that my second recipe results in a chroot environment that allows the chrooted user to see their home directory as /username, and nothing other than that directory at the apparent / level, at the price of cluttering up the real root directory of the system with symbolic links.
    – telcoM
    Sep 19, 2019 at 6:14

Surely it will fail, because sshd will try to cd to /home/user/home/user?

Well, only if that directory doesn't exist.

You did mention you only need SFTP, but a feature like ChrootDirectory could be used to provide chroot environments with a somewhat larger set of tools, requiring binary files and libraries, or there could be multiple users using a same chroot environment. In those cases you might well have /some/chroot/home/user. Granted, ChrootDirectory %h wouldn't seem very useful in that case.

Somewhat silly as it may be, you could just create /home/user/home/user and let the user work there.

When creating a chroot outside of /home, what is the purpose of the user's home directory? Is it still used to read ~/.ssh/authorized_keys?

Actually, that's a very good point. The man page says of ChrootDirectory:

Specifies the pathname of a directory to chroot(2) to after authentication.

So it would seem to imply it reads authorized_keys from outside the chroot.

That prevents another configuration ideas I had. I thought of setting the user's actual home directory to just / and setting ChrootDirectory /home/%u, but that doesn't seem a good idea now.

  • 1
    I keep finding online examples where the general approach is to create a user with a home dir at /home/user and ChrootDirectory as %h, with no other steps for creating the directory structure again to satisfy the part where sshd is supposed to CD to the user's home folder. I can only assume it silently fails on every setup and leaves you in the chroot folder, or I've misunderstood how it works. Sep 18, 2019 at 18:56
  • @jamieburchell, mm-hmm. Well, actually, I didn't test that combination. Can you post a link to one of those examples?
    – ilkkachu
    Sep 18, 2019 at 19:02
  • Sure, one of many askubuntu.com/questions/134425/… Sep 18, 2019 at 19:08

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .