Adding SFTP User with Correct Permissions for nginx with PHP-FPM

When you self-host WordPress on your own VPS like Vultr or Digital Ocean you do not get a default ftp user (besides root). You do not want to use the root user or you will get permission errors. This post shows you how to correct the permission problems if you want to have an SFTP user with nginx and php-fpm.

I am using Debian 9 for this tutorial so I am assuming you are using PHP 7.

Adding SFTP User with Correct Permissions for nginx with PHP-FPM

  • Create a new user with the right home folder
  • ftp user is made member of www-data group
  • Configure nginx to run as ftp user
  • php-fpm runs as ftpuser and www-data group
  • Correct permissions

Create SFTP User

Create a new ftp user, /var/www is the home folder for the ftp user

sudo useradd -d /var/www/ ftpuser

Set the password for the ftpuser, when you are prompted for the password you will not see characters as you type!

sudo passwd ftpuser

Add the ftpuser to the www-data group

sudo usermod -aG www-data ftpuser

Your new ftp user is now a member of the right group and has the right home folder

We can make the user have the primary group www-data so that becomes the group owner by default

sudo usermod -g www-data ftpuser

Change nginx User

Note: if you notice weird behavior after making this change return the user to root and reload nginx.
Open your nginx configuration

sudo nano /etc/nginx/nginx.conf

Change the user value to your ftpuser

# WP-Bullet.com nginx configuration
user ftpuser;
worker_processes auto;
pid /run/nginx.pid;

Verify the nginx syntax is correct

sudo nginx -t

You should get these confirmation messages

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Now nginx will run as the ftp user.

Change PHP-FPM User

Open your php-fpm configuration

sudo nano /etc/php/7.0/fpm/pool.d/www.conf

Change the user value to your ftpuser

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = ftpuser
group = www-data

Verify the php-fpm syntax

sudo php-fpm7.0 -t

You should see this success message

[25-Mar-2017 07:05:24] NOTICE: configuration file /etc/php/7.0/fpm/php-fpm.conf test is successful

Now php-fpm is configured to run as the ftpuser.

Correcting Permissions

Recursively change the permissions for the ftpuser‘s home folder

sudo chown -R ftpuser:www-data /var/www

Set 775 for folders so the ftpuser and www-data group can execute

sudo find /var/www/ -type d -exec chmod 775 {} +

Set 664 for files so the ftpuser and www-data group can write to files

sudo find /var/www/ -type f -exec chmod 664 {} +

Change the permissions for the /var/lib/nginx folder

sudo chown -R ftpuser:www-data /var/lib/nginx

Change the log folder permissions as well

sudo chown -R ftpuser:www-data /var/log/nginx

Change php sessions permissions

sudo chown -R ftpuser:www-data /var/lib/php/sessions

That should do it for the permissions.

Finalizing

Now the services just need to be restarted

sudo service php7.0-fpm restart
sudo service nginx restart

You should now be able to upload files over SFTP without any permission problems.
If you still have FTP prompts then try adding these to your wp-config.php file.

// permission fixes
define( 'FS_METHOD', 'direct' );
define( 'FS_CHMOD_DIR', ( 0775 & ~ umask() ) );
define( 'FS_CHMOD_FILE', ( 0664 & ~ umask() ) );

You can use this script as a permissions reset

USER=ftpuser
sudo chown -R ${USER}:www-data /var/www/
sudo find /var/www/ -type f -exec chmod 664 {} +
sudo find /var/www/ -type d -exec chmod 775 {} +
sudo chown -R ${USER}:www-data /var/lib/nginx
sudo chown -R ${USER}:www-data /var/log/nginx
sudo chown -R ${USER}:www-data /var/lib/php/sessions

Sources

Incomplete Chunked Encoding Error
Create Home Directory for Users
Add Linux User to Group
Connection Reset by Peer
Editing wp-config.php

3 thoughts on “Adding SFTP User with Correct Permissions for nginx with PHP-FPM”

Comments are closed.