I have a server with Ubuntu with a web server (Apache or Nginx) running a PHP application. The application consists of the following parts:

  • An executable code that handles HTTP requests (say in the /var/www/demoapp/app directory)
  • A configuration (say the /var/www/demoapp/.env file)
  • A file storage where the application puts its data (caches, uploads, etc; say in the /var/www/demoapp/storage directory). The application writes files behalf the web server user with 644 mode (let's say I can't make the application write with another mode).

A deployment of the PHP application is made via SSH (the server is connected to) and consists of two stages:

  1. Upload the executable code to the server
  2. Run migrations. The migrations must be able to write the configuration file and the file storage. Running migrations means executing a shell command (e.g. cd /var/www/demoapp/app && ./migrate.php).

What is the proper or the most common strategy of user/group accesses and file permissions for such application and deployment process? I expect an answer like «the web server should be run behalf user1, the SSH should be accessed via user2, the /var/www/demoapp directory should have the xxx mode and so on».

Due to security concerns, I don't want the SSH deployment user to be able to run commands behalf root. And I don't want the web application to be able to write the executable and the configuration files (except when there is a migration running). I admit these requirements may be omitted keeping a good security level.

2 Answers 2


According to the Nginx docs you can configure the user which runs Nginx. By default the user is nobody.

You can read this Ask Ubuntu question that explains how to configure Apache2 to run as a different user. The default user running Apache2 is www-data.

A common strategy, and one I think may work for your goal, is to assign the users that need to deploy the application to a common group. For instance, if you added them to the www-data group:

sudo adduser <user> www-data

You can see which groups is a member of with:

groups <user>

Then change the group of the directory where users will run migrate.php:

sudo chgrp -R www-data /var/www/demoapp

Then assign the group read/write/execute permissions to the directory:

sudo chmod -R g+rwx /var/www/demoapp/

The users in this group should now be able to write and run scripts within the demoapp/ directory.

  • When an application runs, it creates files with default mode and owner (rw-r--r-- www-data:www-data) and <user> can't write them during a migration. How to solve this? By running sudo -user www-data chmod -R g+w /var/www/demoapp/storage?
    – Finesse
    Jun 20, 2019 at 5:13
  • @Finesse could the application that is running, and can write files to the storage directory, be configured to change the permissions of the directory when it is finished? I guess I would need a little more information about what the applications is doing when executed by a user.
    – Argyle
    Jun 20, 2019 at 13:02
  • The application uses third party components so a developer can't fully control what application writes. For the sake of simplicity let's say that the application writes data file both when it's executed by the web server and a user.
    – Finesse
    Jun 21, 2019 at 2:07

I usually stick to a 755 (or rwxr-xr-x) on my web root, but I do not think this is the issue you're running into since your directory is already set to that. nginx should have access to your directory. The question then becomes the permissions (or existence of) the file you're trying to access. The files within your directory will need to be readable by the user nginx is running as. I usually leave these files set to a 755 (the same as the directory). You can change the entire directory by doing

sudo chmod -R 755 /var/www/demoapp/
sudo chgrp -R www-data /var/www/demoapp

If there is not an index file in the directory, however, you will still get the same error. The index file is used when you request a directory that doesn't have directory listings enabled. The most common index file is index.html. This default can be edited in your config, however, using something like:

location / {
    index index.php;

If you want nginx to generate a list of files in that directory for you, simply turn on directory indexing, like so:

location  /  {
  autoindex  on;
  • An application that doesn't write files is a pretty straightforward case. What about the files that the application writes (see the question for more details)?
    – Finesse
    Jun 24, 2019 at 7:36

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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