NGINX / PHP / Server Setup

NGINX and PHP-FPM. What my permissions should be?

by , , revisited on

We have by far the largest RPM repository with NGINX module packages and VMODs for Varnish. If you want to install NGINX, Varnish, and lots of useful performance/security software with smooth yum upgrades for production use, this is the repository for you.
Active subscription is required.

Being an avid StackExchange user, I could see how many users completely lack understanding of the proper permissions model in the most popular, LEMP stack.

You can see recommendations that 777 is never good, but I could not see a simple guide on permissions that can be used as a reference point for everyone.

The following permissions/ownership model applies to all NGINX/PHP-FPM websites and allows you to host websites without any problems, in a secure way.

PHP-FPM user (as known as the website user)

The PHP-FPM user should be a special user that you create for running your website, whether it is Magento, WordPress, or anything.
Its characteristics are the following:

  • This is the user that PHP-FPM will execute scripts with
  • This user must be unique. Do not reuse an existing user account. Create a separate user for each website!
  • Do not reuse any sudo capable users. If your website user is ubuntu or centos, or, root – you’re asking for much trouble.
  • Do not use www-data or nginx as website user. This is wrong and will lead to more troubles!
  • The username should reflect either the domain name of the website that it “runs”, or the type of corresponding CMS, e.g. magento for a Magento website; or example for website.

Let’s create this user:

useradd example

Now, set its password by running:

passwd example

Each website in PHP-FPM should be run under a separate pool. In the pool settings file, e.g. /etc/php-fpm.d/, you must set things to match with the created username:

listen = /var/run/php-fpm/
listen.owner = example = example
listen.mode = 0660

The webserver user

NGINX must run with it own unprivileged user, which is nginx (RHEL-based systems) or www-data (Debian-based systems).

This is the “global” webserver user that is used for all websites. So the configuration is straightforward and translates to the following directives in /etc/nginx/nginx.conf:

user nginx;

Connecting website and webserver users

Now the magic. We must connect things up so that NGINX (webserver) user can read files that belong to the website user’s group.

This will allow us to control what NGINX can read or not, via group chmod permission bit.

usermod -a -G example nginx

This reads as: add nginx user to group example.

File ownership (chown)

Here is a simple rule: all the files should be owned by the website user and the website user’s group:

chown -R example:example /path/to/website/files

Incorrect chown examples:

  • www-data:www-data
  • example:nginx
  • nginx:nginx

Correct chown example:

  • example:example
  • foo:foo

Permissions (chmod)

The following general chmod setup will allow for any website to function properly:

chmod -R u=rwX,g=rX,o= /path/to/website/files

This translates to the following:

  • Website user (example) can read, write all files and read all directories
  • Website group (webserver user) can read all files and traverse all directories, but not write
  • All other users cannot read or write anything

In octal notation, this results in 0750 chmod for all directories and 0640 for all files.

If you simply stick to this permissions model, you will not encounter any chmod / chown issues in the future.
This is the only proper model, functionality, and security-wise.

These general permissions are quite secure already out of the box. But of course, if you know your website structure, you may want to tighten up permissions even further.

For example, see Magento 1.x lockdown chmod.

  1. Shnoulle

    With chmod -R u=rwX,g=rX,o= /path/to/website/files ,

    If you have assets in /path/to/website/files/assets/css for example : nginx can not read/load it …

    How do you manage this?
    A potential solution ACL for nginx/www-data user.

    • Danila Vershinin

      NGINX will be able to read the files.

      css directory will be owned by example:example (owned by example user and by example group). Because we added nginx user (or www-data, depends on distro) as a member of the site user group, and the directory chmod allows for group reads, it will be able to access the directory just fine.

      See the “Connecting website and webserver users” section. This is the essential step: the webserver user is a member of each website’s user group. Not the other way around.

      All the files are owned by example:example. Where necessary for NGINX to read the files, the group permission bit is used to control what it can and what it can’t read.

  2. suges

    It really helped a lot, thank you, Danila.


Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.

%d bloggers like this: