GICT knowledge base
Restrict an OpenSSH SFTP Account to One Directory
Published
OpenSSH can confine a dedicated SFTP account to a directory using ChrootDirectory and force its sessions into internal-sftp. This is a self-managed server-administration procedure, not a shared-hosting entitlement or a reason to edit panel-managed SSH settings without vendor guidance.
Prepare a recoverable change
Keep a working administrative session and console recovery available. Back up the existing SSH configuration privately under a new name. Inspect included configuration files and existing Match blocks before adding another one. Confirm your installed OpenSSH supports each directive; validation must pass before reloading anything.
Create a dedicated account and jail layout
Use a dedicated group such as sftponly and a non-administrative account such as uploaduser. Check that the names do not already belong to another purpose before creating them. Do not add an existing administrator to this group. Account expiry, PAM policy and locked-account handling can still reject public-key login; resolve those narrowly according to the distribution, without enabling password login globally.
For a jail at /srv/sftp/uploaduser, every component of the chroot path must be root-owned and not writable by another user or group. Create a writable child such as /srv/sftp/uploaduser/upload owned only as required by the transfer account. Inside the jail that child appears as /upload. Do not make the jail root user-writable to fix an upload error.
On GNU/Linux, namei -l /srv/sftp/uploaduser/upload helps inspect each ancestor. Use precise ownership and mode changes on the new paths, not recursive repairs on /srv or other accounts. A dedicated host-side key directory such as /etc/ssh/authorized_keys can hold root-managed per-user authorized-key files. It must permit the access SSH needs while preventing unauthorized writes: for this public-key-only layout, root-owned mode 755 for that directory and 644 for each public-key file are suitable examples. Store no private keys there.
Scope the SSH restrictions to the dedicated group
This configuration fragment assumes the account, jail, writable child and authorized public key already exist. It is not a complete replacement sshd_config. Place it with deliberate Match boundaries so later settings are not accidentally included, and retain the distribution’s appropriate global SFTP Subsystem configuration.
Match Group sftponly
ChrootDirectory /srv/sftp/%u
ForceCommand internal-sftp -d /upload -u 0077
AuthorizedKeysFile /etc/ssh/authorized_keys/%u
AuthenticationMethods publickey
PubkeyAuthentication yes
PasswordAuthentication no
KbdInteractiveAuthentication no
DisableForwarding yes
PermitTTY no
PermitTunnel no
The server reads this authorized-key path before entering the chroot. The forced internal SFTP server avoids needing to copy shells and libraries into the jail. -u 0077 restricts newly created permissions; it does not retroactively fix existing files or override all ACL behavior. Forcing SFTP alone does not disable forwarding, which is why forwarding is explicitly restricted.
Validate effective settings, then reload carefully
sshd -t
sshd -T -C user=uploaduser,host=client.example,addr=192.0.2.10
Run the installed server binary with appropriate administrative privileges and its actual configuration path. The test address is documentation space; substitute the relevant connection attributes. Syntax success does not prove the intended Match block wins. Inspect the effective chroot, forced command, authentication and forwarding settings for both the dedicated user and an administrator who should remain unaffected.
Only after successful validation, reload the correct distribution service using its documented mechanism; service names differ. Do not close the original administrative session until a separate administrator login still works and the SFTP account’s restrictions have been tested.
Test both permitted and denied behavior
- Connect with a maintained SFTP client, verifying the server fingerprint independently.
- Upload and download a harmless file in
/upload, compare bytes and remove only that file. - Confirm writing to the jail root is denied and the account cannot see the host’s real filesystem root.
- Confirm a requested remote shell command does not execute and forwarding is disabled. A successful SFTP login alone is not a complete confinement test.
- Check server logs for the exact failure if login is denied. Investigate account policy, authorized keys and jail ownership without disabling host-key checks or weakening unrelated users.
Legacy SCP needs a remote shell and is incompatible with a forced-SFTP account. Modern OpenSSH scp uses SFTP by default, subject to client/server path support. A chroot is not a universal sandbox: review shared mounts, hard links, ACLs and every other service through which that account’s files are accessible.
References: OpenSSH server configuration, internal SFTP options and current scp behavior.
Reviewed October 15, 2026. The fragment and a loopback-only synthetic account were tested in a disposable container, including a writable child, denied jail-root write, forced SFTP and effective forwarding restrictions. No customer SSH service was reloaded.
Related guides
Plan a Safe Redis-to-Valkey Migration
Plan a Redis-to-Valkey migration: check version compatibility, rehearse recovery, stop writers for cutover and protect against lost writes during rollback.
Linux AdministrationHow to Restrict an SSH Key to One Command
Restrict an SSH key to one command with authorized_keys options. Protect the command and check that unwanted shell and forwarding access are denied.
Linux AdministrationHow to Schedule Tasks with systemd Timers
Schedule tasks with systemd timers. Verify service results separately from timer status, test missed-run handling and use an explicit UTC schedule.
Linux AdministrationHow to Restrict a Linux Service with systemd Security Settings
Restrict a Linux service with systemd drop-ins, a dedicated account, read-only paths, private temporary storage, and controlled writable directories.
