umask controls which permission bits are removed when a new file or directory is created. For normal shell work, you may set umask in /etc/profile, /etc/login.defs, .bashrc, .profile, or a systemd service. SFTP is different.
OpenSSH SFTP sessions are commonly handled by internal-sftp or sftp-server, and they do not behave like an interactive login shell. That means a user's .bashrc umask is not a reliable way to control SFTP upload permissions, especially for chrooted SFTP users.
This guide explains how to set SFTP umask with OpenSSH, how to apply different umask values per user or group, how to validate sshd_config, and why SFTP umask can remove permissions but cannot add permissions that the client did not request.
The examples below were tested on Ubuntu with OpenSSH 9.9p1. A local-only temporary sshd instance was started on 127.0.0.1:2222 to validate ForceCommand internal-sftp -u 0027 without modifying the real SSH service.
Match User or Match Group with ForceCommand internal-sftp -u 0027. This changes SFTP behavior for selected users without changing SSH/SFTP behavior globally.
Quick Command Summary
| Task | Command or config |
|---|---|
| Check current shell umask | umask |
| Show current SFTP subsystem | `sshd -T |
| Show sftp-server supported options | /usr/lib/openssh/sftp-server -h |
| Set global internal-sftp umask | Subsystem sftp internal-sftp -u 0027 |
| Set per-group SFTP umask | Match Group sftpusers with ForceCommand internal-sftp -u 0027 |
| Set per-user SFTP umask | Match User alice with ForceCommand internal-sftp -u 0022 |
| Validate SSHD config | sudo sshd -t |
| Reload SSHD safely | sudo systemctl reload sshd or sudo systemctl reload ssh |
| Verify uploaded mode | stat -c '%a %U %G %n' file |
What umask Means for SFTP Permissions
Linux file creation normally starts from a requested mode and then applies umask:
| Object | Common requested mode | With umask 0022 |
With umask 0027 |
With umask 0077 |
|---|---|---|---|---|
| File | 0666 |
0644 |
0640 |
0600 |
| Directory | 0777 |
0755 |
0750 |
0700 |
The important rule is: umask removes permission bits; it does not add missing permission bits.
This local permission test was run to show the behavior:
umask 0077
touch shell-077-file
mkdir shell-077-dir
stat -c '%a %n' shell-077-file shell-077-dirTested output:
600 shell-077-file
700 shell-077-dirThe same idea applies to SFTP uploads. If the client asks to create a file as 0644, SFTP umask 0027 can reduce it to 0640. If the client asks to create it as 0600, umask 0027 cannot add group read permission.
For general permission changes after files already exist, see chmod recursive examples and chown command examples.
Check the Current OpenSSH SFTP Subsystem
First check how SFTP is currently configured:
sshd -T | grep -i '^subsystem'Tested output:
subsystem sftp /usr/lib/openssh/sftp-serverThis system uses the external /usr/lib/openssh/sftp-server binary. Many hardened SFTP-only setups use internal-sftp instead, especially with chroot.
Check OpenSSH server version:
sshd -V 2>&1Tested output:
OpenSSH_9.9p1 Ubuntu-3ubuntu3.2, OpenSSL 3.4.1 11 Feb 2025Check sftp-server supported options:
/usr/lib/openssh/sftp-server -h 2>&1 | head -n 12Tested output:
usage: sftp-server [-ehR] [-d start_directory] [-f log_facility] [-l log_level]
[-P denied_requests] [-p allowed_requests] [-u umask]
sftp-server -Q protocol_featureThe -u umask option is the OpenSSH SFTP server option used in this article.
For broader SSH configuration security, see OpenSSH authentication methods in sshd_config.
Set SFTP umask Globally with Subsystem
Use a global subsystem setting only when the same SFTP umask should apply to all SFTP users.
Edit /etc/ssh/sshd_config:
Subsystem sftp internal-sftp -u 0027This makes internal-sftp apply umask 0027 to new SFTP-created files and directories.
A temporary config with this line was validated with sshd -t:
sshd -t -f /tmp/glc-sshd-test/sshd_config_global
sshd -T -f /tmp/glc-sshd-test/sshd_config_global | grep -i '^subsystem'Tested output:
subsystem sftp internal-sftp -u 0027Use this global method carefully because it changes every SFTP user's default create permissions.
Set SFTP umask Per Group with Match Group
A per-group SFTP umask is usually cleaner than a global subsystem change. This is common for SFTP-only groups.
Example /etc/ssh/sshd_config block:
Subsystem sftp internal-sftp
Match Group sftpusers
ChrootDirectory /sftp/%u
ForceCommand internal-sftp -u 0027
AllowTcpForwarding no
X11Forwarding noThis applies umask 0027 only to users in the sftpusers group that match the block. It also forces SFTP and disables interactive shell access for those matched sessions.
A temporary Match Group config was validated with sshd -t:
sshd -t -f /tmp/glc-sshd-test/sshd_config_matchTested output:
OKIn a real config, sshd -t prints no output when the syntax is valid. The OK line above was printed by the test wrapper after sshd -t returned successfully.
For chroot setup details, see restrict SFTP user to a specific directory. For group membership management, see add user to group in Linux.
Set SFTP umask Per User with Match User
Use Match User when only one user needs a different SFTP umask:
Subsystem sftp internal-sftp
Match User deploy
ForceCommand internal-sftp -u 0022
AllowTcpForwarding no
X11Forwarding noThis applies umask 0022 to SFTP sessions for deploy, but not to other users.
If the user also needs a chroot, include ChrootDirectory and make sure the chroot path is owned by root and not writable by the user. SFTP chroot ownership rules are strict; incorrect ownership causes login failures.
Validate Before Reloading sshd
Always validate SSHD configuration before reload or restart:
sudo sshd -tIf the command returns no output, the syntax is valid. For a custom file, use:
sshd -t -f /tmp/glc-sshd-test/sshd_config_matchTested output:
OKAfter validation, reload SSHD if your distribution supports it:
sudo systemctl reload sshdOn Ubuntu and Debian, the service may be named ssh:
sudo systemctl reload sshKeep an existing SSH session open while testing. For connection testing and troubleshooting, see test SSH connection commands and SSH command examples.
Tested SFTP Upload with internal-sftp -u 0027
A local-only temporary SSH daemon was started on 127.0.0.1:2222 with this test block:
Subsystem sftp internal-sftp
Match User golinuxcloud
ForceCommand internal-sftp -u 0027
AllowTcpForwarding no
X11Forwarding noTwo files were uploaded through SFTP:
source-644.txt, mode0644source-600.txt, mode0600
The SFTP batch uploaded both files and created a directory:
sftp -q -P 2222 -i /tmp/glc-sftp-umask-test/id_ed25519 \
-o StrictHostKeyChecking=no \
-o UserKnownHostsFile=/tmp/glc-sftp-umask-test/known_hosts \
-b /tmp/glc-sftp-umask-test/batch \
[email protected]:/tmp/glc-sftp-umask-test/targetTested output:
sftp> put /tmp/glc-sftp-umask-test/source-644.txt source-644.txt
sftp> put /tmp/glc-sftp-umask-test/source-600.txt source-600.txt
sftp> mkdir uploaded-dir
sftp> bye
# effective subsystem in temp config
subsystem sftp internal-sftp
# source permissions
644 root root /tmp/glc-sftp-umask-test/source-644.txt
600 root root /tmp/glc-sftp-umask-test/source-600.txt
# uploaded permissions
640 golinuxcloud golinuxcloud /tmp/glc-sftp-umask-test/target/source-644.txt
600 golinuxcloud golinuxcloud /tmp/glc-sftp-umask-test/target/source-600.txt
750 golinuxcloud golinuxcloud /tmp/glc-sftp-umask-test/target/uploaded-dirThis confirms the common SFTP umask confusion:
0644uploaded with umask0027becomes0640.0600uploaded with umask0027stays0600.- A directory created with umask
0027becomes0750.
So if your SFTP upload stays 600, the problem may not be that -u 0027 is ignored. The SFTP client may be requesting a restrictive mode, and umask cannot add group-read permission.
For one-line SFTP batch usage, see single-line SFTP command examples. For scripted transfers, see automate SFTP using a shell script.
Troubleshooting SFTP umask
| Problem | Likely cause | What to check |
|---|---|---|
Uploaded file is still 600 |
Client requested 0600; umask cannot add permissions |
Compare source/requested mode and upload result with stat |
.bashrc umask is ignored |
SFTP session is not an interactive shell | Use internal-sftp -u or sftp-server -u |
| Group umask does not apply | User did not match the Match Group block |
Check id username and sshd -T -C user=username,host=host,addr=ip |
| Chroot login fails | Chroot directory ownership or permissions are wrong | Root must own the chroot path and it must not be writable by the user |
| SSH config reload fails | Syntax error in sshd_config |
Run sudo sshd -t before reload |
| File owner or group is unexpected | Upload user primary group or directory ACL differs | Check id, directory ownership, ACLs, and setgid bit |
If permissions display a trailing dot on some systems, see remove dot in Linux permissions. If you need to restrict SSH access by users or groups, see restrict or allow SSH users and groups.
When umask Is Not Enough
Use SFTP umask when you only need to remove permissions from newly created files and directories.
Use other controls when you need stronger behavior:
| Need | Better control |
|---|---|
| Force group ownership | Set directory group ownership and setgid bit |
| Apply default ACLs | setfacl -d on the upload directory |
| Restrict user to one directory | ChrootDirectory with ForceCommand internal-sftp |
| Prevent shell access | ForceCommand internal-sftp |
| Harden SSH exposure | Key authentication, user restrictions, Fail2ban |
For SFTP over IPv6, see use SFTP with IPv6 address in Linux. For SSH brute-force hardening, see Fail2ban SSH configuration.
Frequently Asked Questions
1. How do I set umask for SFTP in Linux?
For OpenSSH internal-sftp, set ForceCommand internal-sftp -u 0027 inside a Match User or Match Group block in sshd_config. For a global SFTP subsystem, use Subsystem sftp internal-sftp -u 0027.2. Does .bashrc umask apply to SFTP uploads?
Usually no. Non-interactive SFTP sessions handled by internal-sftp or sftp-server do not run the user shell startup files in the same way as an interactive shell, so .bashrc umask is not a reliable SFTP control.3. What permissions does SFTP umask 0027 create?
For normal uploaded files requested as 0666, umask 0027 results in 0640. For directories requested as 0777, it results in 0750.4. Why did my SFTP file stay 600 after setting umask 0027?
umask can remove permissions from the mode requested by the client, but it cannot add permissions that were not requested. If the uploaded source or client request is 0600, umask 0027 still leaves it as 0600.5. Should I use Subsystem sftp internal-sftp -u or ForceCommand internal-sftp -u?
Use Subsystem sftp internal-sftp -u only when the same umask should apply to every SFTP user. Use Match User or Match Group with ForceCommand internal-sftp -u when only selected SFTP users or groups need that umask.6. Do I need to restart sshd after changing SFTP umask?
Validate the config first with sshd -t, then reload or restart sshd depending on your distribution. Reload is usually safer for active SSH sessions than a full restart.Summary
To set SFTP umask in Linux with OpenSSH, use internal-sftp -u UMASK or sftp-server -u UMASK. Apply it globally with Subsystem sftp internal-sftp -u 0027, or apply it selectively with a Match User or Match Group block and ForceCommand internal-sftp -u 0027.
For most SFTP-only users, the best pattern is a Match Group block with ForceCommand internal-sftp -u 0027, optional ChrootDirectory, and SSH features such as TCP forwarding disabled. Validate with sshd -t before reloading SSHD.
Remember the key rule: umask removes permissions; it does not add permissions. If an upload is requested as 0600, SFTP umask 0027 will not turn it into 0640.

