I've set up a SFTP server using OpenSSH, everything works fine and the users I created can connect.

After authentication, the users find themselves directly inside /chroot, a directory they are not allowed to write into. So I've put a /subdirectory into /chroot they have write access to (inspired by this blog post) which works fine as well.

However, due to the nature of the project I'm working on, users should find themselves directly in a folder they are allowed to write into after authentication. Forwarding them into the /chroot/subdirectory might be the best solution but I've found no resource explaining how to achieve that.

Can it be done? How?

3 Answers 3


[EDIT] Yes I believe it is possible, but I also believe not with openssh:

Here is how I chroot sftp using openssh:

I put sftp users in a special group sftponly which is identified in the sshd_config file. I make sure sftp users have no shell (so they can't log in with ssh) and use the .%h environment variable to force them into a sftp chroot subdir named after their home directory using the ChrootDirectory directive. Other environment variables interpreted by sshd_config are documented in the sshd_conf man page like so:

The pathname may contain the following tokens that are expanded at runtime once the connecting user has been authenticated: %% is replaced by a literal '%', %h is replaced by the home directory of the user being authenticated, and %u is replaced by the username of that user.

Here is a copy of my notes for achieving this on OpenBSD, if you use a different system the .%h environment variable may of course differ:

# 1. Create the sftp jail directories
# These directory permissions work with this /etc/ssh/sshd_config:
# drwxr-xr-x  4 root    wheel  512 May 14 16:20 /home/sftproot
# drwxr-xr-x  3 root  wheel  512 May 14 16:21 /home/sftproot/home
# drwxr-xr-x  3 root  wheel  512 May 14 16:37 /home/sftproot/home/User01
# drwxr-xr-x  3 User01  sftponly  512 May 14 16:39 /home/sftproot/home/User01/upload
# drwxr-xr-x  3 root  wheel  512 May 14 16:37 /home/sftproot/home/User02
# drwxr-xr-x  3 User02  sftponly  512 May 14 16:39 /home/sftproot/home/User02/upload

# 2. Make sure /etc/ssh/sshd_config jails /home/sftproot/.%h

# 3. Create a group whose members will only be allowed sftp access
# groupadd sftponly

# 4. Create User01 + User02 whom will only get sftp access
# useradd -s /sbin/nologin -m -G sftponly User01
# useradd -s /sbin/nologin -m -G sftponly User02

# 5. In /etc/ssh/sshd_config enable use of chroot(internal-sftp) then force chroot dirs per user:
# override default of no subsystems
# Subsystem     sftp    /usr/libexec/sftp-server
# Subsystem       sftp    internal-sftp
# Rules for sftponly members
# Match group sftponly
#         ChrootDirectory /home/sftproot/.%h
#         X11Forwarding no
#         AllowTcpForwarding no
#        ForceCommand internal-sftp

# [Comment] Make sure /etc/ssh/sshd_config jails /home/sftproot/.%h
# Which will translate .%h to /home/$username

# [Comment] The sftp users will not be able to log in outside of sftp (as they have no shell).
# As they sftp in they will land in the /home/sftproot/home/Userxx directory which
# will be named "./" and where they have no write access.
# However the directory ./upload is read/writable.

[EDIT part 2] However, the sshd_conf man page also specifies that:


Specifies the pathname of a directory to chroot(2) to after authentication. At session startup sshd(8) checks that all components of the pathname are root-owned directories which are not writable by any other user or group. After the chroot, sshd(8) changes the working directory to the user's home directory.

So the chroot directory path, including the part specified by variable expansion, is expected and tested for by sshd to be owned and writable exclusively by root. Therefore, a user of an openssh sftp chrooted service needs writable subdirectories to be able to write to the home directory.

I believe this is not a requirement with all ssh servers however. We also use Tectia where I observe that users are able to write to their respective root directories. However we run it only where Windows is a requirement, so regrettably I cannot readily test the corresponding *nix configuration. The Tectia sftp chrooting support page does not explicitly specify that the user home needs to be owned by root in a Unix environment. I would therefore guess that with Tectia this is not a requirement but that the ownership of a chrooted user home rootdir may be that of the actual user.

  • Thanks! Unfortunately, I don't think that solves my problem. As outlined in my question, "users should find themselves directly in a folder they are allowed to write into after authentication". But according to your code comments: "...they will land in the /home/sftproot/home/Userxx directory which will be named "./" and where they have no write access. However the directory ./upload is read/writable." How can I forward the users directly to "./upload" without them ever seeing "./" ?
    – zerodot
    Jul 11, 2015 at 14:33
  • My bad, I missed that. I have edited the answer accordingly.
    – ErikE
    Jul 11, 2015 at 21:59
  • Thanks for the edit. I fear Tectia is not a solution we can use but I'll investigate it further and keep this thread updated.
    – zerodot
    Jul 14, 2015 at 9:15

ChrootDirectory /upload/%u

ForceCommand internal-sftp -d data

This will put the sftp in /upload/UserXX/data directory. The data directory is owned and read/writable by the UserXX

  • I spent over an hour looking for exactly this solution. This worked perfectly for me.
    – chapkom
    Feb 25, 2019 at 21:20

With help of user474056 answer. It worked nicely this way :

sudo addgroup exchangefiles

sudo mkdir /home/chroot/

sudo chmod g+rx /home/chroot/

sudo mkdir /home/chroot/exchangefiles/

sudo chmod g+rwx /home/chroot/exchangefiles/

sudo chgrp -R exchangefiles /home/chroot/exchangefiles/

sudo useradd -g exchangefiles -s /usr/bin/false -d /home/chroot/exchangefiles/username username

sudo passwd username

vi /etc/ssh/sshd_config

sshd_config quote A:

# override default of no subsystems
#Subsystem  sftp    /usr/lib/openssh/sftp-server
Subsystem      sftp    internal-sftp

sshd_config quote B:

Match Group exchangefiles
  # Force the connection to use SFTP and chroot to the required directory.
  ForceCommand internal-sftp -d %u
  ChrootDirectory /home/chroot/exchangefiles/
  # Disable tunneling, authentication agent, TCP and X11 forwarding.
  PermitTunnel no
  AllowAgentForwarding no
  AllowTcpForwarding no
  X11Forwarding no

sudo service sshd restart

You must log in to answer this question.

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