SFTP-only accounts are useful when a partner, automation job, or internal team needs to exchange files but should not receive a shell on the SSH server. The restriction has to block interactive SSH sessions while still allowing the SFTP subsystem to read and write the intended upload directory.
OpenSSH handles this with a Match block in /etc/ssh/sshd_config. A matched group can be forced into internal-sftp, placed in a per-user chroot under /srv/sftp, and denied forwarding features that would otherwise keep extra SSH channels available.
The chroot boundary is strict about ownership. The directory named by ChrootDirectory and every parent in that path must be owned by root and not writable by group or others, while a separate child directory inside the jail can be owned by the SFTP user for uploads. Keep an existing admin session open while changing sshd so a bad edit can be rolled back from the current connection or a console.
Related: How to copy a file over SSH
Related: How to configure SSH Match blocks
Related: How to disable SSH TCP forwarding
Steps to restrict SSH users to SFTP only:
- Back up the current sshd configuration.
$ sudo cp /etc/ssh/sshd_config /etc/ssh/sshd_config.backup
Do not close your current admin session until the restricted account has been tested. A syntax error or wrong Match rule can block new SSH logins.
- Create a dedicated group for SFTP-only accounts.
$ sudo groupadd --system sftpusers
Using a separate group keeps the SFTP-only policy separate from normal SSH users.
- Create the restricted account in that group.
$ sudo useradd --no-create-home --home-dir / --shell /usr/sbin/nologin --gid sftpusers sftpuser1
The home directory is set to / because the account will be chrooted to /srv/sftp/sftpuser1 before internal-sftp starts.
- Set an authentication method for the restricted account.
$ sudo passwd sftpuser1 New password: Retype new password: passwd: password updated successfully
If the server uses key-only authentication, install the user's public key through the same approved process used for other SSH accounts before testing SFTP.
- Create the chroot and upload directory path.
$ sudo mkdir -p /srv/sftp/sftpuser1/upload
- Set root ownership on the chroot directories.
$ sudo chown root:root /srv/sftp /srv/sftp/sftpuser1
- Keep the chroot directories writable only by root.
$ sudo chmod 755 /srv/sftp /srv/sftp/sftpuser1
sshd refuses the login if /srv/sftp or /srv/sftp/sftpuser1 is writable by sftpuser1 or by sftpusers. Put writable content below the chroot directory, not on the chroot directory itself.
Tool: chmod Calculator
- Set the upload directory ownership to the restricted user.
$ sudo chown sftpuser1:sftpusers /srv/sftp/sftpuser1/upload
- Allow only the restricted user and group to enter the upload directory.
$ sudo chmod 750 /srv/sftp/sftpuser1/upload
- Verify the chroot and upload directory ownership.
$ sudo ls -ld /srv/sftp /srv/sftp/sftpuser1 /srv/sftp/sftpuser1/upload drwxr-xr-x 3 root root 4096 Jun 13 11:48 /srv/sftp drwxr-xr-x 3 root root 4096 Jun 13 11:48 /srv/sftp/sftpuser1 drwxr-x--- 2 sftpuser1 sftpusers 4096 Jun 13 11:48 /srv/sftp/sftpuser1/upload
- Open /etc/ssh/sshd_config with sudo privileges.
$ sudoedit /etc/ssh/sshd_config
- Set the SFTP subsystem to internal-sftp.
Subsystem sftp internal-sftp
Keep only one active Subsystem sftp line. Comment out an older line that points to an external sftp-server binary.
- Add the Match Group block after the global sshd settings.
Match Group sftpusers ChrootDirectory /srv/sftp/%u ForceCommand internal-sftp DisableForwarding yes PermitTTY noThe %u token expands to the login name, so sftpuser1 is jailed under /srv/sftp/sftpuser1. DisableForwarding blocks forwarding channels, and PermitTTY no prevents terminal allocation for matched users.
Related: How to configure SSH Match blocks
Related: How to disable SSH TCP forwarding - Test the sshd configuration before applying it.
$ sudo sshd -t
No output means the configuration parsed successfully.
Related: How to test SSH server configuration
- Restart the SSH service to apply the SFTP-only rule.
$ sudo systemctl restart ssh
On RHEL, CentOS, Fedora, and similar systems, the service name is commonly sshd instead of ssh.
- Connect with SFTP and upload a test file into the writable directory.
$ sftp sftpuser1@host.example.net sftp> pwd Remote working directory: / sftp> ls upload sftp> cd upload sftp> put local-file.txt local-file.txt Uploading local-file.txt to /upload/local-file.txt sftp> ls local-file.txt sftp> rm local-file.txt sftp> bye
The restricted account starts at the chroot root and can write only inside /upload.
- Confirm the same account cannot open an SSH shell.
$ ssh -T sftpuser1@host.example.net This service allows sftp connections only.
The nonzero SSH exit and internal-sftp message confirm that the matched account is forced into SFTP instead of a shell or remote command session.
Mohd Shakir Zakaria is a cloud architect with deep roots in software development and open-source advocacy. Certified in AWS, Red Hat, VMware, ITIL, and Linux, he specializes in designing and managing robust cloud and on-premises infrastructures.