What is a simple and secure way to handle file permissions for Apache?

0

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.

Michael Cordingley

Posted 2017-02-24T18:14:03.450

Reputation: 103

Transfer files through SSH. – Ramhound – 2017-02-24T18:36:56.303

Yes, that is implicit in "SFTP". – Michael Cordingley – 2017-02-24T18:40:33.663

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 – 2017-02-24T18:40:47.970

@richard Updated. Is that better? – Michael Cordingley – 2017-02-24T18:41:40.383

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 – 2017-02-24T18:44:54.377

Have you looked at default permissions use access control lists? You can make group, read, write and/or execute inherit. – ctrl-alt-delor – 2017-02-24T18:45:55.373

@Ramhound Huh. I always understood it as a file transfer, not necessarily FTP but conforming to the look and feel of it, tunneled over SSH. Thanks for the correction. – Michael Cordingley – 2017-02-24T18:48:04.760

may depend on which sftp “sftp is an interactive file transfer program, similar to ftp(1), which performs all operations over an encrypted ssh(1) transport.” — sftp manual. However this is not what the question is about. – ctrl-alt-delor – 2017-02-24T18:48:42.873

If you set the permissions on the desination folder ahead of time, new and any modified files, will inherit those permissions. Your real problem is you have a single user account, which means I presume its being used to launch Apache, which means thats a security concern itself. Apache should be ran with a user that only has the permissions it needs to run Apache. What permission, of course, Apache will needs is project dependent. If you are creating files with a script be sure the script is ran, with a user, with only the permissions required. The script's files should inherit permissions – Ramhound – 2017-02-24T18:52:15.027

Will the files that Apache needs write access to every need to be manually updated via the ssh/sftp? Or are those files exclusively data? If it is exclusively data, then it should be pretty easy. – Zoredache – 2017-02-24T19:11:49.200

@Zoredache Exclusively data. If I ever go in for manual manipulation of them, it'd be a simple one-off. The SFTP upload would be syncing code and supporting files, not data. – Michael Cordingley – 2017-02-24T19:34:42.613

Answers

1

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.

Zoredache

Posted 2017-02-24T18:14:03.450

Reputation: 18 453

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 – 2017-02-24T20:27:29.760

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 – 2017-02-24T20:35:37.043