| Tested on | Red Hat Enterprise Linux 10.2 (Coughlan) |
|---|---|
| Package | openssh-server 9.9p1-25.el10_2openssh-clients 9.9p1-25.el10_2 |
| Applies to | RHEL, Rocky Linux, AlmaLinux, Fedora, Ubuntu, and Debian with OpenSSH internal-sftp or sftp-server |
| Privilege | sudo or root to edit /etc/ssh/sshd_config and reload sshd |
| Scope | Set SFTP umask globally or with Match User / Match Group, validate sshd_config, and verify upload modes. Does not cover SFTP chroot setup or SSH hardening beyond umask. |
| Related guides | umask on Linux Restrict SFTP to a directory OpenSSH authentication in sshd_config chmod recursive examples Add user to group in Linux |
umask controls which permission bits are removed when a new file or directory
is created. For interactive shells, you set it in /etc/profile, .bashrc,
or similar files — the umask on Linux guide covers that
calculation. SFTP is different: OpenSSH handles uploads with internal-sftp
or sftp-server, not your login shell, so a user's .bashrc umask is not a
reliable way to control SFTP file modes.
Quick answer
| Goal | Config or command |
|---|---|
| Check current SFTP subsystem | sshd -T | grep -i '^subsystem' |
| Global SFTP umask | Subsystem sftp internal-sftp -u 0027 in /etc/ssh/sshd_config |
| Per-group SFTP umask | Match Group sftpusers with ForceCommand internal-sftp -u 0027 |
| Per-user SFTP umask | Match User deploy with ForceCommand internal-sftp -u 0022 |
| Validate before reload | sudo sshd -t |
Reload sshd on RHEL |
sudo systemctl reload sshd |
| Verify uploaded mode | stat -c '%a %n' file |
For most SFTP-only accounts, a Match Group block with
ForceCommand internal-sftp -u is cleaner than changing the global subsystem
line.
How SFTP umask changes permissions
If the SFTP client requests these creation modes, umask 0027 removes the
listed bits:
| Object | Requested mode | With umask 0027 |
|---|---|---|
| File | 0666 |
0640 |
| Directory | 0777 |
0750 |
The mode requested by an SFTP client can vary, especially when the client is
asked to preserve permissions. The server-side -u setting applies its umask
to newly created files and directories, so it can remove permission bits but
cannot add missing ones.
The rule that trips up SFTP admins: umask removes permission bits; it does not
add missing bits. Umask 0027 does not force new files to 0640. If the
client requests 0600, the result remains 0600.
Check the current SFTP subsystem
Before editing sshd_config, see how SFTP is wired today:
sshd -T | grep -i '^subsystem'Sample output:
subsystem sftp /usr/libexec/openssh/sftp-serverOn RHEL and Fedora the binary lives under /usr/libexec/openssh/. On Debian
and Ubuntu it is usually /usr/lib/openssh/sftp-server. Add -u through
internal-sftp in the subsystem line or in a Match block with
ForceCommand.
Set SFTP umask globally
Use a global subsystem line only when every SFTP user should share the same
umask. Edit /etc/ssh/sshd_config:
Subsystem sftp internal-sftp -u 0027That tells OpenSSH to run internal-sftp with umask 0027 for all SFTP
sessions. A global change affects every SFTP user on the host, so prefer
Match blocks when only some accounts need a custom umask.
Set SFTP umask for a group or user
ForceCommand internal-sftp makes matching accounts SFTP-only; use this form
when that is intended. If users still need normal SSH shell access, do not add
ForceCommand just to set an SFTP umask.
To give members of sftpusers umask 0027 on SFTP sessions:
Subsystem sftp internal-sftp
Match Group sftpusers
ForceCommand internal-sftp -u 0027When one account needs a different umask, use Match User:
Subsystem sftp internal-sftp
Match User deploy
ForceCommand internal-sftp -u 0022Only deploy gets umask 0022 on SFTP sessions. Other users keep the default
subsystem behavior. If these accounts also need chroot or forwarding
restrictions, configure those separately — see
restrict SFTP to a directory.
Validate and reload sshd
Always syntax-check sshd_config before reload or restart:
sudo sshd -tNo output and exit status 0 mean the file parsed cleanly. On RHEL, Rocky
Linux, and AlmaLinux, reload the running daemon:
sudo systemctl reload sshdOn Ubuntu and Debian the unit is often named ssh instead of sshd:
sudo systemctl reload sshKeep an existing SSH session open while testing a reload.
Verify uploaded permissions
Upload a normal test file over SFTP after you set -u 0027:
sftp user@serverAt the sftp> prompt:
sftp> put test.txtOn the server, check the mode of the uploaded file:
stat -c '%a %n' /upload/path/test.txtNote the resulting mode and compare it with the mode requested or preserved by
your SFTP client. Replace /upload/path/ with the directory where that user's
SFTP session can write.
To show that umask cannot add permission bits, upload two small local files
with different source modes and compare the results. With the OpenSSH sftp
client used in this test and umask 0027 configured, a 0644 source was
created remotely as 0640, while a 0600 source stayed 0600. Your client
may request different modes, so check with stat rather than assuming a fixed
result.
The important rule is that the server-side umask can remove permission bits,
but cannot add bits the client did not request. If uploads stay at mode
600, compare the source mode with the remote file before assuming
-u 0027 is ignored.
Troubleshooting
| Symptom | Likely cause | Fix |
|---|---|---|
Uploaded file stays 600 |
Client requested 0600; umask cannot add permissions |
Compare source and upload modes with stat |
.bashrc umask ignored |
SFTP is not an interactive shell session | Set internal-sftp -u or sftp-server -u in sshd_config |
| Group umask does not apply | User did not match the Match Group block |
Run id username; check with sshd -T -C user=...,host=...,addr=... |
| Reload fails | Syntax error in sshd_config |
Run sudo sshd -t before systemctl reload |
| Unexpected owner or group | Primary group or directory setgid differs | Check id, directory ownership, ACLs, and setgid on the upload path |
When umask alone is not enough — for example you need forced group ownership
or default ACLs on every new file — use setgid directories or setfacl -d
rather than expecting umask to add permissions.
References
Summary
SFTP upload permissions are controlled in OpenSSH, not in .bashrc. Set umask
with internal-sftp -u UMASK inside sshd_config. A global
Subsystem sftp internal-sftp -u 0027 line applies one umask to every SFTP
user; Match Group or Match User with ForceCommand internal-sftp -u
limits the change to selected accounts.
Umask 0027 does not force files to 0640. It removes permission bits from
the mode the SFTP client requests. If the client requests 0600, the result
remains 0600. Before reloading production sshd, run sshd -t, then
confirm remote modes with stat -c '%a %n' file.

