Usually I setup my Ubuntu server to have at least 2 users:

  • A user behalf which the web server (Apache or Nginx) runs, e.g. www-data in group www-data
  • A user that updates and maintains the web applications, e.g. deployer in groups deployer and www-data

A web application consists of 2 directories:

  • A directory for executable files (e.g. PHP or JS) served by the web server (Apache or Nginx) and a code interpreter, e.g. app
  • A directory for the application to write (caches, logs, uploads, etc.), e.g. storage

I setup the directories with the following permissions:

├ app          rwxrwxr-x deployer:deployer
│ └ index.php  rwxrwxr-x deployer:deployer
└ storage      rwxrwxr-x www-data:www-data
  ├ logs       rwxrwxr-x www-data:www-data
  └ cache      rwxrwxr-x www-data:www-data

The problem is that it's inconvenient to maintain the web application because it writes the files to storage with the default permission and therefore deployer can't write them. And vise versa, deployer can leave files in storage that are not writable by the application. An example of what happens after a while:

├ app                 rwxrwxr-x deployer:deployer
│ └ index.php         rwxrwxr-x deployer:deployer
└ storage             rwxrwxr-x www-data:www-data
  ├ logs              rwxrwxr-x www-data:www-data
  │ └ applogs.log     rw-r--r-- www-data:www-data # Deployer can't write
  └ cache             rwxrwxr-x www-data:www-data
    └ somecache.json  rw-r--r-- deployer:deployer # Application can't write

I can't make the application write files with other group or mode. I have to make some complex sudo setup and watch carefully the files created by deployer to maintain the application and keep it running.

Does the application self-write restriction worth the inconveniences? Is it ok (considering security concerns) to run the web server and maintain the application using a single user that can write the files both in the app and storage directories?

2 Answers 2


Some applications work around this by using ftp. They login to localhost with a given username. That’s more portable on some Webhosters that sudo.

It is a good practice if the web server cannot modify code, because this is a very common way for permanent infection. On the other hand for convenience it’s often done. If your scripts are secure (and you don’t use thirdparty modules like mailers, guestbooks, Blog or,forum software with a known weakness) then its acceptable.

Having said that, any other method like ftp or sudo has the same problem if the credentials are stored reachable for the web server.

  • What exactly do the applications they do using FTP? Do they connect to the storage directory and read/write it behalf deployer?
    – Finesse
    Jun 19, 2019 at 6:54
  • Depends on the app, Wordpress does connect to its app directory to update php files.
    – eckes
    Jun 19, 2019 at 15:35

To answer your question: It's really not a good idea to let any less-than-fully-trusted process self-modify, and that's especially true for frequently-launched and highly-exposed programs like web servers. The principle of least privilege applies really strongly here, and web servers do not need the ability to self-modify.

Fortunately, there are solutions. The best possible fix, assuming your file system supports ACLs (most do) and is mounted with the acl option (probably, but make sure), is to create a default ACL on the storage directory, which will make all files and subdirectories created within it writable by both the deployer and www-data users. There's a decent summary of Linux ACLs here, but the short version is that you'd need to run setfacl -d -m u:www-data:rw -m u:deployer:rw storage. That would cause any new files or directories in storage to automatically inherit an ACL that grants R/W access to both www-data and deployer.

Another possible fix, using just standard Unix permission bits:

  • Mark the storage directory with the setgid bit, and ensure its group is set to www-data. This will cause all files (or subdirectories) created within the storage directory to also have the www-data group, no matter what the default group of the process that created them is. New subdirectories will also inherit the setgid bit.
  • Set the umask of the deployer to 002. This means that files and directories created by the deployer will have mode 664/775 (file/directory) by default.
  • If possible, change the umask of the app to 002 as well. This way, files that it creates will be writable by the deployer without extra work.

At this point, the deployer will be creating files with mode 664 (rw-rw-r--), which would be bad if there were anything else that was in group deployer... but there presumably isn't. If it creates a file under app, the file will be writable by the user deployer and also the group deployer, but not by anybody else. If it creates a file under storage, though, the file will be writable by user deployer but by group www-data (because the file inherit its group from the setgid directory). Because user deployer is a member of www-data, it will still be able to write to this file, but - critically - so will the app. If you can change the app's umask too, then the deployer will also be able to write to files that the app creates.

  • Thank you for the great answer. I considered using the setgid+umask way but I thought it may be too complex too. As my quick research shown, it's possible to change umask of www-data. I will learn the ACL approach and try to implement it.
    – Finesse
    Jun 19, 2019 at 9:16

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .