When setting up SFTP (SSH File Transfer Protocol) users, system administrators often need to restrict users to file transfer only, preventing shell access. The common approach of changing the shell to /sbin/nologin
or /dev/null
doesn't work because SFTP still requires a valid shell for authentication.
OpenSSH provides a built-in SFTP server that can be configured to chroot users while denying shell access. Here's how to properly set it up:
# 1. Create the user with no login shell
sudo adduser --shell /usr/sbin/nologin sftpuser
# 2. Set up the chroot directory
sudo mkdir -p /var/sftp/sftpuser/uploads
sudo chown root:root /var/sftp/sftpuser
sudo chmod 755 /var/sftp/sftpuser
sudo chown sftpuser:sftpuser /var/sftp/sftpuser/uploads
# 3. Configure SSH server (add to /etc/ssh/sshd_config)
Match User sftpuser
ChrootDirectory /var/sftp/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
After making these changes, restart the SSH service:
sudo systemctl restart sshd
Test the configuration by attempting to connect:
sftp sftpuser@yourserver.com
Then try to get a shell (which should fail):
ssh sftpuser@yourserver.com
For more complex setups, you might want to:
- Set up multiple SFTP-only users with different directories
- Configure disk quotas
- Implement logging for file transfers
Here's an example for multiple users:
Match Group sftponly
ChrootDirectory /var/sftp/%u
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
If you encounter problems:
- Check permissions on the chroot directory (must be owned by root)
- Verify SELinux contexts if you're using SELinux
- Check SSH logs (
/var/log/auth.log
) for errors
Creating a user restricted to SFTP-only access is a common security requirement for system administrators. While the adduser
tool creates standard accounts, we need additional configuration to prevent shell access while allowing secure file transfers.
Many administrators first try modifying shell assignments in /etc/passwd
:
# Common but ineffective attempts:
sftpuser:x:1001:1001::/home/sftpuser:/sbin/nologin
sftpuser:x:1001:1001::/home/sftpuser:/dev/null
sftpuser:x:1001:1001::/home/sftpuser:/bin/false
These methods block shell access but typically break SFTP functionality because OpenSSH requires a valid shell for authentication.
The proper method involves configuring OpenSSH's internal-sftp
subsystem:
# Step 1: Create the user (no shell change yet)
sudo adduser sftpuser
sudo passwd sftpuser
# Step 2: Edit /etc/ssh/sshd_config
Match User sftpuser
ChrootDirectory /home/sftpuser
ForceCommand internal-sftp
AllowTcpForwarding no
X11Forwarding no
PermitTTY no
Proper permissions are crucial for security:
# Set up the chroot environment
sudo mkdir -p /home/sftpuser/uploads
sudo chown root:root /home/sftpuser
sudo chmod 755 /home/sftpuser
sudo chown sftpuser:sftpuser /home/sftpuser/uploads
sudo chmod 755 /home/sftpuser/uploads
After restarting SSH (sudo systemctl restart sshd
), verify with:
sftp sftpuser@localhost
# Should connect successfully
ssh sftpuser@localhost
# Should fail with "This service allows sftp connections only"
For more complex setups, consider these additions:
# Multiple users in group
Match Group sftponly
ChrootDirectory /home/%u
ForceCommand internal-sftp
# ... other restrictions
# Logging configuration
Subsystem sftp internal-sftp -l INFO -f AUTH
If connections fail, check:
- SSH logs (
/var/log/auth.log
) - Directory ownership (must be root:root)
- SELinux contexts if enabled
- SSH config syntax (indentation matters)