33

I installed Nginx using Ansible. To install on Centos7 I used the yum package so it by default was run as root user. I want it to start and run as a different user (ex - nginx user) in the Centos box. When I try to run it with a different user I get the following error:

Job for nginx.service failed because the control process exited with error code. See "systemctl status nginx.service" and "journalctl -xe" for details.

I know it's not advisable to run as root. So how do I get around this and run nginx as a non root user. Thanks

Roald Nefs
  • 1,302
  • 10
  • 29
Sarith
  • 381
  • 1
  • 3
  • 4
  • 2
    Maybe [Allow non-root process to bind to port 80 and 443?](http://superuser.com/q/710253/173513) and [Bind to ports less than 1024 without root access](https://serverfault.com/questions/268099/bind-to-ports-less-than-1024-without-root-access) will help. Also see [Is there a way for non-root processes to bind to “privileged” ports (<1024) on Linux?](http://stackoverflow.com/q/413807/608639). – jww Feb 19 '17 at 17:33

6 Answers6

47

Add/Change the following in your /etc/nginx/nginx.conf:

user nginx;

You should create the user and grant permissions on the webroot directories recursively.

This way only master process runs as root. Because: Only root processes can listen to ports below 1024. A webserver typically runs at port 80 and/or 443. That means it needs to be started as root.

Note from the documentation on master and worker processes:

The main purpose of the master process is to read and evaluate configuration files, as well as maintain the worker processes.

The worker processes do the actual processing of requests.

To run master process as non root user:

Change the ownership of the files whose path are specified by following Nginx directives:

  • error_log
  • access_log
  • pid
  • client_body_temp_path
  • fastcgi_temp_path
  • proxy_temp_path
  • scgi_temp_path
  • uwsgi_temp_path

Change the listen directives to ports above 1024, log in as desired user and run nginx by nginx -c /path/to/nginx.conf

Nagev
  • 10,835
  • 4
  • 58
  • 69
Farhad Farahi
  • 35,528
  • 7
  • 73
  • 70
19

Just in case it helps, for testing/debugging purpose, I sometimes run an nginx instance as a non privileged user on my Debian (stretch) laptop.

I use a minimal config file like this:

worker_processes 1;
error_log stderr;
daemon off;
pid nginx.pid;

events {
  worker_connections  1024;
}

http {
  include             /etc/nginx/mime.types;
  default_type        application/octet-stream;

  sendfile on;

  keepalive_timeout   65;

  ssl_protocols TLSv1 TLSv1.1 TLSv1.2; 
  ssl_prefer_server_ciphers on;
  access_log access.log;
  server {
    listen            8080;
    server_name       localhost;

    location / {
      include /etc/nginx/uwsgi_params;
      uwsgi_pass localhost:8081;
    }
  }
}

and I start the process with:

/usr/sbin/nginx -c nginx.conf -p $PWD
David Douard
  • 191
  • 1
  • 2
17

Just in case it helps someone stumbling over this question in 2020, here is my minimal nginx.conf for running a web server on port 8088, works for a non-root user. No modding of file permissions necessary! (Tested on Centos 7.4 with nginx 1.16.1)

    error_log /tmp/error.log;
    pid       /tmp/nginx.pid;
    
    events {
      # No special events for this simple setup
    }
    http {
      server {
        listen       8088;
        server_name  localhost;
    
        # Set a number of log, temp and cache file options that will otherwise
        # default to restricted locations accessible only to root.
        access_log /tmp/nginx_host.access.log;
        client_body_temp_path /tmp/client_body;
        fastcgi_temp_path /tmp/fastcgi_temp;
        proxy_temp_path /tmp/proxy_temp;
        scgi_temp_path /tmp/scgi_temp;
        uwsgi_temp_path /tmp/uwsgi_temp;
    
        # Serve local files
        location / {
          root /home/<your_user>/web;
          index  index.html index.htm;
          try_files $uri $uri/ /index.html;
        }
      }
    }
OleDahle
  • 305
  • 2
  • 8
  • the answer by @david-douard mentions the same principle, but thanks anyways! :). – jg6 Oct 01 '20 at 22:42
4

Why not use the rootless bitnami/nginx image:

$ docker run --name nginx bitnami/nginx:latest
  • More info

To verify it is not running as root but as your standard user (belonging to the docker group):

$ docker exec -it nginx id
uid=1**8 gid=0(root) groups=0(root)

And to verify that Nginx isn't listening to a root-restricted port 443 even internally:

$ docker ps -a | grep nginx
2453b37a9084   bitnami/nginx:latest                       "/opt/bitnami/script…"   4 minutes ago    Up 30 seconds                 8080/tcp, 0.0.0.0:8443->8443/tcp                  jenkins_nginx

It's easy to configure (see docs) and runs even under random UIDs defined at run time (i.e. not hard-coded in the Dockerfile). In fact this is Bitnami's policy to have all their containers rootless and prepared for UID changes at runtime, which is why we've been using them for a few years now under very security-conscious Openshift 3.x (bitnami/nginx in particular as a reverse proxy needed to enable authentication to MLflow web app).

mirekphd
  • 4,799
  • 3
  • 38
  • 59
  • 1
    Very easy to setup and security-minded. This answer should be way higher. – Alistair Jones Nov 07 '21 at 20:35
  • 1
    I like the answer. Just to add, there is a use-case where you want a smaller image. This Bitnami size ( uncompressed ) is ~90MB vs `nginx:1.23.3-alpine-slim` which is 11.5MB. – rustyMagnet Jan 17 '23 at 12:28
0

In order for the master nginx process to be run as a non privileged user you have to:

  1. change ownership of the /etc/nginx directory to be owned by the said user.

  2. change ownership of the /var/log/nginx to be owned by same user.

  3. Update the /etc/nginx/nginx.conf file to give it read permission (644).

Disclaimer: Ensure that in the /etc/nginx/sites-enabled/default listen is on a non-privileged port.

finally login as the said user and execute " nginx -c /etc/nginx/nginx.conf"

  • Master process should now be running as your 'said user'.
0

It's quite possible to run nginx as an ordinary user with a capability to listed to 443 port. In order to do that, you need to utilize the systemd hardening capabilities. Check out this repo to learn how

starball
  • 20,030
  • 7
  • 43
  • 238
  • While this link may answer the question, it is better to include the essential parts of the answer here and provide the link for reference. Link-only answers can become invalid if the linked page changes. - [From Review](/review/late-answers/34896241) – mechnicov Aug 27 '23 at 13:10