Nginx error: (13: Permission denied) while connecting to upstream

Anyone who lands here from the Googles and is trying to run Flask on AWS using the default Ubuntu image after installing nginx and still can't figure out what the problem is:

Nginx runs as user "www-data" by default, but the most common Flask WSGI tutorial from Digital Ocean has you use the logged in user for the systemd service file. Change the user that nginx is running as from "www-data" (which is the default) to "ubuntu" in /etc/nginx/nginx.conf if your Flask/wsgi user is "ubuntu" and everything will start working. You can do this with one line in a script:

sudo sed -i 's/user www-data;/user ubuntu;/' /etc/nginx/nginx.conf

Trying to make Flask and uwsgi run as www-data did not work off the bat, but making nginx run as ubuntu worked just fine since all I'm running with this instance is Flask anyhow.


You have to set these permissions (chmod/chown) in uWSGI configuration.

It is the chmod-socket and the chown-socket.

http://uwsgi-docs.readthedocs.org/en/latest/Options.html#chmod-socket http://uwsgi-docs.readthedocs.org/en/latest/Options.html#chown-socket


The permission issue occurs because uwsgi resets the ownership and permissions of /tmp/uwsgi.sock to 755 and the user running uwsgi every time uwsgi starts.

The correct way to solve the problem is to make uwsgi change the ownership and/or permission of /tmp/uwsgi.sock such that nginx can write to this socket. Therefore, there are three possible solutions.

  1. Run uwsgi as the www-data user so that this user owns the socket file created by it.

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --uid www-data --gid www-data
    
  2. Change the ownership of the socket file so that www-data owns it.

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --chown-socket=www-data:www-data
    
  3. Change the permissions of the socket file, so that www-data can write to it.

    uwsgi -s /tmp/uwsgi.sock -w my_app:app --chmod-socket=666
    

I prefer the first approach because it does not leave uwsgi running as root.

The first two commands need to be run as root user. The third command does not need to be run as root user.

The first command leaves uwsgi running as www-data user. The second and third commands leave uwsgi running as the actual user that ran the command.

The first and second command allow only www-data user to write to the socket. The third command allows any user to write to the socket.

I prefer the first approach because it does not leave uwsgi running as root user and it does not make the socket file world-writeable .


While the accepted solution is true there might also SELinux be blocking the access. If you did set the permissions correctly and still get permission denied messages try:

sudo setenforce Permissive

If it works then SELinux was at fault - or rather was working as expected! To add the permissions needed to nginx do:

  # to see what permissions are needed.
sudo grep nginx /var/log/audit/audit.log | audit2allow
  # to create a nginx.pp policy file
sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx
  # to apply the new policy
sudo semodule -i nginx.pp

After that reset the SELinux Policy to Enforcing with:

sudo setenforce Enforcing