Setting the umask for SFTP transactions

I ran into this problem when was setting up a web server for usage by a team setting up our company web site. There were two developers and they both would be uploading files to the machine, and they both were going to want to modify each others files if need-be. I made a common group and set the sgid bit on the parent directory. I didn’t want to open up straight FTP access to the box so I told them to use SFTP or SCP. This worked great until I found that each users umask was not being applied to new files and directories. The two developers could see each others files but not modify them. I found that the sftp process is spawned by the root user and its umask is applied to the transaction. I wasn’t in favor or modifying the root umask so I came up with another solution.

The only thing I could find to work was to create a wrapper script around the sftp process that would temporarily set the umask for the transaction.

First I created the wrapper script:

#!/bin/bash
 
umask 0002
 
# The path to your sftp-server binary may differ
exec /usr/libexec/openssh/sftp-server

Then I pointed the Subsystem directive in the sshd_config file to my script:

Subsystem       sftp    /opt/sftp-server-wrapper.sh

A quick restart/reload of the sshd configuration and I was in business. Both users could see and edit each others files. Email or comment with questions.

—Edit (20090619)
Or even simpler still as @Gilles pointed out in the comments you can do away with the wrapper script entirely and simply change the Subsystem line in your sshd_config to this:

Subsystem sftp /bin/sh -cumask 0002; /usr/libexec/openssh/sftp-server’

Thanks Gilles!

—Edit (20110525)
Or simplest yet, as @Larry and @simingol pointed out in the comments, there is a new flag for the sftp-server, ‘-u’, that allows you to directly set the umask, overriding the user umask. So to use it, just do this:

Subsystem sftp /usr/libexec/openssh/sftp-server -u 0002
  1. #1 by Bryan on December 19, 2011 - 1:13 pm

    try adding umask command to .bashrc
    (.bash_profile is for interactive)

    ~]$ cat .bashrc
    # .bashrc

    # Source global definitions
    if [ -f /etc/bashrc ]; then
    . /etc/bashrc
    fi

    # User specific aliases and functions

    # Friendly file creation mask
    umask u=rwx,g=rwx,o=r

  2. #2 by jeffro on December 19, 2011 - 8:24 pm

    HI Bryan, this unfortunately doesn’t work. The sftp subsystem doesn’t spin up a bash shell to complete the command. Thus, your.bashrc file is never read. This was one of the first things I tried when I initially encountered this issue.

  3. #3 by Steven on March 16, 2012 - 9:33 am

    If you use chroot-jails and therefore are forced to use the internal-sftp subsystem, you can also pass the -u parameter to it:

    Subsystem sftp internal-sftp -u 0002

    This also works for the ForceCommand directive:
    ForceCommand internal-sftp -u 0002

  4. #4 by jeffro on March 16, 2012 - 10:04 am

    Thanks Steve, pretty close to my last edit on the article, but worth mentioning anyway. The new ‘u’ flag does make life a bit easier.

  5. #5 by Heather on June 12, 2012 - 12:46 am

    Alternatively, if you don’t want this to extend to all users you can set it per user/group like this:
    Match User localuser
    ForceCommand /bin/sh -c ‘umask 0002; ${SSH_ORIGINAL_COMMAND:-$SHELL}’

  6. #6 by jeffro on June 12, 2012 - 10:27 am

    Thanks for the tip Heather. I haven’t tried this but being able to apply this per user/group is definitely preferred to forcing a universal umask. Generally the only people that have access to my systems are the ones that need this applied though, I will give this a shot in the future.

  7. #7 by birger on June 15, 2012 - 6:18 am

    at least for some sftp implementations it seems to work if you put it in the users .profile

  8. #8 by Paul on September 5, 2012 - 11:01 am

    Not sure if it’s Filezilla’s fault, but all newly created files/folders do not have the group writeable bit set. Even after trying above instructions.
    How can I force that bit on all newly uploaded files?

  9. #9 by jeffro on September 13, 2012 - 9:50 am

    The umask enforces r/w permissions, its just WHOSE umask is being applied when you create a file is the kicker . Yes, Filezilla can reset r/w permissions on upload, so you are going to want to check those first. If the above instructions aren’t working then you are going to want to check whose umask IS being used

  10. #10 by William Murat on February 18, 2013 - 1:07 pm

    Thanks a lot, Jeff!

    I have this problem and finally I found a solution.

    :-)

  11. #11 by Alex Jurado on May 13, 2013 - 8:46 am

    Thanks, Jeff.

    Following your steps, I created in my server the wrapper /usr/local/sbin/sftp_server.sh

    Then, I’ve edited /etc/passwd, there are user which I do not want to have ssh , interactive access, so they have: /usr/local/sbin/sft_server.sh instead of the usual /bin/bash

  12. #12 by Gagandeep on October 2, 2013 - 1:29 am

    Hi Jeff,

    I am using solaris 10, and I want to change umask for sftp from default to 0002. After following instructions above I am still unable to get the required result.
    Solaris 10 has its default sftp server (internal-sftp). when i changed Subsystem in my default sftp server to accept “-u 0002″ and i restarted ssh service but still unable to get the files with required permissions.

    Than I installed openSSH and changed the sshd_config there and stopeed my default ssh but still unable to resolve.

    Can you please help.

  13. #13 by Dave on January 6, 2014 - 12:46 am

    Steven :
    If you use chroot-jails and therefore are forced to use the internal-sftp subsystem, you can also pass the -u parameter to it:
    Subsystem sftp internal-sftp -u 0002
    This also works for the ForceCommand directive:
    ForceCommand internal-sftp -u 0002

    By the way folks this one works for all users, and Heathers solution works for individual users when you need to implement scponly users on FreeNAS boxen.
    Thanks guys and gals. Keep up the good fight Jeff. :)

  14. #14 by Jon on January 9, 2014 - 1:59 pm

    This is such a good article it has spawned a (very errily similar) child! All the best stuff gets ripped off..
    http://www.linux4beginners.info/linux-how-to/umask-for-sftp-users-connections-linux-centos-fedora-ubuntu/

  15. #15 by jeffro on January 9, 2014 - 2:05 pm

    Thanks for the heads-up Jon. Odd, the guy didn’t even change most of the text from my site, including a call out to one of the comments ;-)

  16. #16 by Karn on January 13, 2014 - 9:23 am

    Hello Jeff, I just went thro the stuff discussed above and discussion looks hot & intresting…

    I would like to Know how we can setup sftp in solaris 10 host. I see the config on ssh_config file ..
    # override default of no subsystems
    Subsystem sftp /usr/libexec/openssh/sftp-server

    what this really mean .. any opinion will be great in help

  17. #17 by Russ Sanderlin on January 17, 2014 - 3:36 pm

    I just ran into a similar issue. Thank you for posting this.

  18. #18 by Andrew Taylor on January 21, 2014 - 4:29 am

    Alternatively, if you don’t want this to extend to all users you can set it per user/group like this:
    Match User localuser
    ForceCommand /bin/sh -c ‘umask 0002; ${SSH_ORIGINAL_COMMAND:-$SHELL}’

  19. #19 by César on January 27, 2014 - 7:19 am

    Thanks Jeff, this helped me with my SFTP issues.

  20. #20 by Adam Smith on March 28, 2014 - 3:40 am

    Hello Jeff,
    Really thanks a lot for this . it really takes me out from a trouble. it is really useful. Thanks again :)

(will not be published)