How to Configure a Chroot Jail for SFTP Users on Ubuntu 22.04

# How to Configure a Chroot Jail for SFTP Users on Ubuntu 22.04

Providing external vendors, contractors, or clients with a way to securely upload files to your Linux server is a common administrative requirement. SFTP (SSH File Transfer Protocol) is the industry standard for this task, utilizing the robust encryption of the SSH protocol.

However, simply creating a new user and granting them SSH access is a severe security risk. By default, any SSH user can navigate up the directory tree and view system files, configuration data, and the existence of other user directories.

To secure your server, you must implement a “Chroot Jail.” A chroot jail modifies the apparent root directory for the user. When they log in via SFTP, their home directory becomes their absolute `/` root. They are physically incapable of navigating higher or viewing system files outside of their designated folder.

This guide details the process of configuring an OpenSSH chroot jail for SFTP-only users on Ubuntu 22.04.

## Step 1: Create the SFTP User and Group

It is best practice to create a dedicated group for all users who will be restricted to the chroot jail. This allows you to apply a single SSH configuration rule to the entire group.

1. **Create the restricted group:**
“`bash
sudo groupadd sftp_users
“`

2. **Create the new user:**
We will create a user named `vendor1`. We append them to the `sftp_users` group and disable their ability to access a standard interactive shell by setting their shell to `/bin/false`. This ensures they can *only* use SFTP for file transfers and cannot execute terminal commands via SSH.
“`bash
sudo useradd -m -g sftp_users -s /bin/false vendor1
“`

3. **Set a strong password for the user:**
“`bash
sudo passwd vendor1
“`

## Step 2: Configure the Directory Structure and Permissions

OpenSSH has incredibly strict requirements for chroot jails. The directory that acts as the jail (the root) **must be owned by the `root` user and must not be writable by anyone else.** If these permissions are incorrect, the SFTP connection will instantly fail and close.

Because the user cannot write to the root of their jail, we must create a sub-directory inside the jail where they have write permissions to upload their files.

1. **Modify the ownership of the user’s home directory (the jail):**
“`bash
sudo chown root:root /home/vendor1
“`

2. **Set the correct permissions for the jail:**
The root user has read/write/execute, while the group and others only have read/execute.
“`bash
sudo chmod 755 /home/vendor1
“`

3. **Create the upload sub-directory:**
This is where the user will actually store their files.
“`bash
sudo mkdir /home/vendor1/uploads
“`

4. **Grant the user ownership of the upload directory:**
“`bash
sudo chown vendor1:sftp_users /home/vendor1/uploads
“`

With this structure, when `vendor1` logs in, they will be placed in `/home/vendor1/` (which appears to them as `/`). They can see the `uploads` folder, but they cannot upload files directly to `/`. They must navigate into the `uploads` folder to transfer their data.

## Step 3: Configure the SSH Daemon (sshd_config)

Now that the user and directories are prepared, we must configure the SSH service to enforce the chroot jail.

1. **Open the SSH configuration file:**
“`bash
sudo nano /etc/ssh/sshd_config
“`

2. **Modify the Subsystem directive:**
Scroll down (usually near the bottom) and look for the `Subsystem` line. By default, it points to the `sftp-server` binary. We must change this to use the `internal-sftp` subsystem, which is built into OpenSSH and works seamlessly with chroot jails without requiring you to copy system binaries into the jail.

**Change this:**
`Subsystem sftp /usr/lib/openssh/sftp-server`

**To this:**
`Subsystem sftp internal-sftp`

3. **Append the Chroot Rules:**
At the very bottom of the file (it is critical that `Match` blocks are at the end of the file), add the following configuration:

“`text
Match Group sftp_users
ChrootDirectory %h
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
“`

### Explaining the Configuration:
– **`Match Group sftp_users`**: Applies these rules only to users within this specific group.
– **`ChrootDirectory %h`**: Tells SSH to jail the user in their home directory (`%h` is a variable for the user’s home path, e.g., `/home/vendor1`).
– **`ForceCommand internal-sftp`**: Forces the SSH server to drop the user immediately into an SFTP session upon login, disregarding any attempts to request a standard shell.
– **`AllowTcpForwarding no` & `X11Forwarding no`**: Disables SSH tunneling and graphical forwarding, further restricting the user’s capabilities.

4. **Save and exit the file.**

## Step 4: Validate and Restart SSH

Before restarting the SSH service, it is highly recommended to validate the configuration file to prevent syntax errors from locking you out of your server.

1. **Test the configuration:**
“`bash
sudo sshd -t
“`
*If the command returns no output, the syntax is correct.*

2. **Restart the SSH service to apply the changes:**
“`bash
sudo systemctl restart ssh
“`

## Step 5: Test the Chroot Jail

You can verify the configuration from a client machine (or a different terminal window on the same machine).

1. **Attempt a standard SSH connection:**
“`bash
ssh vendor1@your_server_ip
“`
The connection should establish, prompt for a password, and then immediately terminate with a message similar to: `This service allows sftp connections only. Connection to your_server_ip closed.` This confirms the shell restriction is working.

2. **Attempt an SFTP connection:**
“`bash
sftp vendor1@your_server_ip
“`
Enter the password when prompted. You should successfully log in and see an `sftp>` prompt.

3. **Verify the jail:**
Type `pwd`. It should return `/` (not `/home/vendor1`).
Type `cd ..`. You will remain in `/`. The jail is working.

4. **Verify upload permissions:**
Attempt to upload a file directly to the root directory using the `put` command. You should receive a `Permission denied` error.
Change directories into the uploads folder (`cd uploads`) and attempt the upload again. The file should transfer successfully.

By meticulously configuring ownership permissions and updating the `sshd_config`, you have created an incredibly secure file transfer environment, isolating third-party users entirely from the rest of your underlying Linux server.

Get the best tech tips delivered straight to your inbox.

Join thousands of readers mastering Apple, Google, Microsoft, and Linux.