When working with SFTP servers using OpenSSH's sftp-server
, many administrators encounter persistent umask issues. Unlike regular SSH sessions where umask settings from .profile
or PAM configurations apply properly, SFTP connections often default to 022 regardless of system-wide settings.
The standard approaches - PAM configuration (/etc/pam.d/common-session
) and shell profiles - don't work because:
- SFTP sessions are non-interactive and don't source user profiles
sftp-server
runs as a subsystem without full shell initialization- PAM sessions might not be processed the same way for SFTP connections
Method 1: Subsystem Wrapper Script
Create a wrapper script that sets umask before executing sftp-server
:
#!/bin/sh
umask 0002
exec /usr/lib/openssh/sftp-server "$@"
Then modify sshd_config
:
Subsystem sftp /path/to/your/sftp-wrapper.sh
Method 2: ForceCommand in sshd_config
For specific users or groups, add to sshd_config
:
Match Group sftponly
ForceCommand umask 0002 && /usr/lib/openssh/sftp-server
Method 3: Using internal-sftp
Modern OpenSSH versions support internal SFTP implementation:
Subsystem sftp internal-sftp -u 0002
- Verify permissions on wrapper scripts (must be executable)
- Check SELinux/AppArmor contexts if security modules are enabled
- Test with
sftp -v user@host
for debug output - Confirm the actual umask during SFTP sessions with
!umask
in sftp client
For a development team needing shared write access to uploaded files:
# /etc/ssh/sshd_config
Subsystem sftp /usr/local/bin/sftp-umask-wrapper
# /usr/local/bin/sftp-umask-wrapper
#!/bin/bash
umask 0002
/usr/lib/openssh/sftp-server
Remember to restart sshd after changes:
systemctl restart sshd
When working with OpenSSH's SFTP subsystem, many administrators encounter a frustrating behavior: the default umask (022) remains stubbornly persistent, ignoring system-wide PAM configurations or user shell profiles. This occurs because SFTP sessions don't initiate a full login shell environment.
The sftp-server process operates differently than standard SSH logins. Here's the critical sequence:
1. Client establishes SSH connection
2. SSH daemon executes sftp-server directly (not through user shell)
3. Session runs with default umask (022)
4. Traditional profile/PAM settings are bypassed
Method 1: ForceCommand Wrapper Script
Create a wrapper script that sets the umask before invoking sftp-server:
#!/bin/sh
umask 002
exec /usr/lib/openssh/sftp-server
Then modify sshd_config:
Subsystem sftp /usr/local/bin/sftp-wrapper
Method 2: AuthorizedKeysCommand Hook
For per-user control, leverage the authorized_keys command option:
command="umask 002 && /usr/lib/openssh/sftp-server" ssh-rsa AAAAB3Nza...
Method 3: Systemd Service Override (For System-Wide Changes)
Create an override for sshd.service:
[Service]
UMask=0002
Environment="UMASK=0002"
Then reload systemd:
systemctl daemon-reload
systemctl restart ssh
After implementation, verify with:
sftp user@host
> echo "test" > testfile
> ls -l testfile
-rw-rw-r-- 1 user user 5 May 1 10:00 testfile
- Ensure wrapper scripts have execute permissions (chmod +x)
- Check SELinux/AppArmor contexts if permissions fail
- Restart SSH service after configuration changes
- Test with different clients (OpenSSH sftp, FileZilla, etc.)
The wrapper method adds minimal overhead (one additional process fork). For high-volume SFTP servers, the systemd override provides the cleanest solution without process spawning overhead.