Chroot SFTP users to home directory

I’m trying to prevent SFTP users from navigating outside of their home directory. I’ve made the following configuration changes, yet when I SFTP to the server logged in as the new user, I’m still able to navigate to the system root.

Ubuntu 24.04.1 LTS
OpenSSH_9.6p1 Ubuntu-3ubuntu13.5, OpenSSL 3.0.13 30 Jan 2024

Created sftp_user group, added users with /path/to/home to group

updated /etc/ssh/sshd_config, adding the following lines:

#first directive
Subsystem sftp internal-sftp

#last directive
Match Group sftp_user
 X11Forwarding no
 AllowTcpForwarding no
 ChrootDirectory %h
 ForceCommand internal-sftp

saved and restarted SSH:

sudo systemctl restart ssh
systemctl status ssh

● ssh.service - OpenBSD Secure Shell server
     Loaded: loaded (/usr/lib/systemd/system/ssh.service; disabled; preset: enabled)
     Active: active (running) since Mon 2025-01-13 23:40:30 EST; 36s ago
TriggeredBy: ● ssh.socket
       Docs: man:sshd(8)
             man:sshd_config(5)
    Process: 358916 ExecStartPre=/usr/sbin/sshd -t (code=exited, status=0/SUCCESS)
   Main PID: 358917 (sshd)
      Tasks: 1 (limit: 73321)
     Memory: 1.2M (peak: 2.0M)
        CPU: 17ms
     CGroup: /system.slice/ssh.service
             └─358917 "sshd: /usr/sbin/sshd -D [listener] 0 of 10-100 startups"

Jan 13 23:40:30 usa1 systemd[1]: Stopping ssh.service - OpenBSD Secure Shell server...
Jan 13 23:40:30 usa1 systemd[1]: ssh.service: Deactivated successfully.
Jan 13 23:40:30 usa1 systemd[1]: Stopped ssh.service - OpenBSD Secure Shell server.
Jan 13 23:40:30 usa1 systemd[1]: Starting ssh.service - OpenBSD Secure Shell server...
Jan 13 23:40:30 usa1 sshd[358917]: Server listening on :: port 46.
Jan 13 23:40:30 usa1 systemd[1]: Started ssh.service - OpenBSD Secure Shell server.
'''

Could you edit your post and put three backticks ``` on the lines above and below pasted code so the indentation and formatting stays intact ? That way it stays readable for all of us …

1 Like

It doesn’t work like that, you can’t chroot a user into their home directory.

See the sshd_config man page for more info on the ChrootDirectory directive.

At session startup sshd(8) checks that all components of the pathname are root-owned directories which are not writable by group or others.

The easy way to find out what’s going on is to run sshd in debug mode on an alternative port, as root on the server /usr/sbin/sshd -ddd -p 2022 To connect to that use sftp -v -P 2022 user@host
In the output you’ll see a message such as

debug3: safely_chroot: checking '/'
debug3: safely_chroot: checking '/home/'
debug3: safely_chroot: checking '/home/user'
bad ownership or modes for chroot directory "/home/user"

You can work around this with a few minor changes to your config.

Assuming your home directories are under /home, change ChrootDirectory to

ChrootDirectory            /home

The internal-sftp command uses the same code base as the sftp-server command and thus the options available are identical. See man sftp-server for more details.
You’ll need to change the ForceCommand to

ForceCommand            internal-sftp -d /%u -u 0027

The -u options sets the umask to restrict access to any files that are uploaded.

If you then connect via SFTP you’ll then be placed in the Chroot under the /user directory.

The sftp-server / internal-sftp process uses the socket /dev/log to log what’s going on. Without that in place in your Chroot environment you’re unable to see what your users are up to.

You can restrict access further by changing the permissions on /home and the users home directories themselves to limit what other users can see / access.

There are more complicated setups available using bind mounts, but this should get you up and running.

1 Like

starting over, I was editing the /etc/ssh/ssh_config file, not sshd_config.

doh!

1 Like