I have messed around with assigning different users and groups to the files in /var/www, but each way that I've tried so far ends up being overly complicated and error-prone. I'm looking for a simple and repeatable pattern that differs minimally from the default file-system settings (permissions, sticky bits, ACLs, etc.) Once I get this nailed down, I plan to replicate it across multiple servers over time.

My situation is that I have a web application that lives in /var/www/foo and needs to be uploaded via SFTP. I'm planning on having git-ftp do the actual uploads. All files need to be readable by Apache. Some folders, and any subfolders created by the application, need to be writable by Apache. I have a single user account on the server in question that does not belong to any special groups at the moment, but does have full sudo access. There will be multiple uploads over time and after each upload, I need to run a script that may create, modify, or delete files.

What is the least invasive way to get the files in place and not run into any permissions issues, either during the upload or at run-time?

In case it helps, I'm setting up Laravel applications on Debian, though the pattern that I'm looking for should hopefully generalize beyond that framework, the language it runs on, and that distribution.

  • Transfer files through SSH. – Ramhound Feb 24 '17 at 18:36
  • Yes, that is implicit in "SFTP". – Michael Cordingley Feb 24 '17 at 18:40
  • The title is misleading. This is not a question about uploading (to which the best answer would be ssh). I think it may be about file permissions, though am not 100% sure. – ctrl-alt-delor Feb 24 '17 at 18:40
  • @richard Updated. Is that better? – Michael Cordingley Feb 24 '17 at 18:41
  • Git support pushing directly over SSH. just add apache to SSH group(ssh user's group) and set www's directory-root permission as 755 with ownership ssh_user:www-data . If you need some directory be writable by apache, then change permissions to 775 – Alex Feb 24 '17 at 18:44

First, to make your permissions simpler to apply and maintain, I suggest you separate out your data into location outside of your main webroot. Use configuration within your code, or symlinks to point out to the separate folder.

We will assume you are concerned about security, so that you will not be using a root account to upload. Update your web server document root if needed.

Create a group like www-pub, add the account you use to publish code to that group.

  • /var/www/www.example.org/data
  • /var/www/www.example.org/www

With that in place I usually set permissions like this. These commands are written in a way that should make them safely repeatable.

# perms for the code/html folder
find /var/www/www.example.org/www -type d ! -perm 2775 -print0 | xargs --null --no-run-if-empty chmod 2775
find /var/www/www.example.org/www -type f ! -perm 0664 -print0 | xargs --null --no-run-if-empty chmod 0664
find /var/www/www.example.org/www \( ! -user root -o ! -group www-pub \) -print0 | \
xargs --verbose --null --no-run-if-empty chown root:www-www-pub

# perms for the data folder
find /var/www/www.example.org/data -type d ! -perm 2755 -print0 | xargs --null --no-run-if-empty chmod 2755
find /var/www/www.example.org/data -type f ! -perm 0644 -print0 | xargs --null --no-run-if-empty chmod 0644
find /var/www/www.example.org/data \( ! -user www-data -o ! -group www-data \) -print0 | \
xargs --verbose --null --no-run-if-empty chown www-data:www-data

The one other important thing is to set your shell and sftp server to have a umask of 0002. Without setting changing the umask from the common default of 0022 files written would only be group readable. But you need it to not mask the group write bit.

If you don't want to mess around with the masks, and ACLs are enabled for your filesystem, then you could use ACLs instead, which in some ways simplifies things, since the environments umask isn't considered for non default entries when you are using ACLs.

# set on empty directory before uploading files
# the parent directory has full read-write-execute for www-pub
# newly create files will be read-write for www-pub
setfacl --recursive --modify group:www-pub:rwx,default:group:www-pub:rw- /var/www/www.example.org/www

setfacl --recursive --modify group:www-data:rwx,default:group:www-data:rw- /var/www/www.example.org/data

Anyway there is no one-true way, but hopefully the above might be a useful starting point.

  • Summarizing to check my understanding: All directories get 2775. All code files get 0664. All data files get 0644. Areas that need to be accessible to the uploading user get set to the root user and www-pub group, the rest stay as-is with www-data on both user and group. Apache can read, but not write, application files because it's neither the owner nor group, but the readable bit for "other" is set. The SGID on directories keeps any new files as owned by the same group as the directory. The ACLs make sure that new files are 664 instead of 644. Is this all correct? – Michael Cordingley Feb 24 '17 at 20:27
  • Could you please add some more information on what's going on with the ACLs? That's the one part that I don't fully follow. – Michael Cordingley Feb 24 '17 at 20:35

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.