尝试使用非root用户启动nginx的master进程

索引

1. 首先
2. 前提条件
3. 确认默认设置
4. 修改设置
5. 确认结果
6. 结语

首先

最近安全需求变得更加严格,基本上不再使用root用户进行运维。
考虑到有些服务启动时要求不允许使用root用户,所以尝试修改了nginx的启动用户,并将此作为备忘录留下。

前提環境-提供原始条件

亚马逊 Linux 发布版本为 2023。
nginx 版本为 1.22.1-1.amzn2023.0.3。

默认确认

首先,安装并启动nginx服务。

$ sudo yum install nginx
$ sudo systemctl start nginx

我会检查默认的进程。

$ ps -ef |grep nginx
root       25126       1  0 13:41 ?        00:00:00 nginx: master process /usr/sbin/nginx
nginx      25127   25126  0 13:41 ?        00:00:00 nginx: worker process

工作进程以nginx用户启动,但主进程以root用户启动。

4. 更改设定

我打算尝试像worker进程一样,用nginx用户启动主进程。

由于需要更改启动用户,所以需要考虑权限问题。
本次将创建一个名为/nginx_test的目录,并对其进行权限更改和配置更改。

$ sudo mkdir -p /nginx_test/conf
$ sudo mkdir -p /nginx_test/run
$ sudo mkdir -p /nginx_test/log 
$ sudo mkdir -p /nginx_test/html

conf是用于存储定义文件的目录,run是用于存储进程ID文件的目录,log是用于存储日志文件的目录,html是用于存储示例页面的目录。

你需要将默认的配置文件和示例页面的HTML文件复制到你创建的目录中,并更改该目录的权限。
由于这只是一次测试,所以将权限设置为777的nginx nginx。

$ sudo cp -rp /etc/nginx/* /nginx_test/conf/
$ sudo cp -rp /usr/share/nginx/html/* /nginx_test/html/
$ sudo chown nginx:nginx /nginx_test/*
$ sudo chmod 777 /nginx_test/*

为了本次验证的目的,我们将把配置文件的内容转换成适用于此次验证的格式。

修改点:

$ diff /nginx_test/conf/nginx.conf /nginx_test/conf/nginx.conf_bk 
7,8c7,8
< error_log /nginx_test/log/error.log notice;
< pid /nginx_test/run/nginx.pid;
---
> error_log /var/log/nginx/error.log notice;
> pid /run/nginx.pid;
11c11
< include /nginx_test/modules/*.conf;
---
> include /usr/share/nginx/modules/*.conf;
22c22
<     access_log  /nginx_test/log/access.log  main;
---
>     access_log  /var/log/nginx/access.log  main;
29c29
<     include             /nginx_test/conf/mime.types;
---
>     include             /etc/nginx/mime.types;
35c35
<     include /nginx_test/conf/conf.d/*.conf;
---
>     include /etc/nginx/conf.d/*.conf;
38,39c38,39
<         listen       9999;
<         listen       [::]:9999;
---
>         listen       80;
>         listen       [::]:80;
41c41
<         root        /nginx_test/html;
---
>         root         /usr/share/nginx/html;
44c44
<         include /nginx_test/conf/default.d/*.conf;
---
>         include /etc/nginx/default.d/*.conf;

修改后的文件:

# For more information on configuration, see:
#   * Official English Documentation: http://nginx.org/en/docs/
#   * Official Russian Documentation: http://nginx.org/ru/docs/

user nginx;
worker_processes auto;
error_log /nginx_test/log/error.log notice;
pid /nginx_test/run/nginx.pid;

# Load dynamic modules. See /usr/share/doc/nginx/README.dynamic.
include /nginx_test/modules/*.conf;

events {
    worker_connections 1024;
}

http {
    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
                      '$status $body_bytes_sent "$http_referer" '
                      '"$http_user_agent" "$http_x_forwarded_for"';

    access_log  /nginx_test/log/access.log  main;

    sendfile            on;
    tcp_nopush          on;
    keepalive_timeout   65;
    types_hash_max_size 4096;

    include             /nginx_test/conf/mime.types;
    default_type        application/octet-stream;

    # Load modular configuration files from the /etc/nginx/conf.d directory.
    # See http://nginx.org/en/docs/ngx_core_module.html#include
    # for more information.
    include /nginx_test/conf/conf.d/*.conf;

    server {
        listen       9999;
        listen       [::]:9999;
        server_name  _;
        root        /nginx_test/html;

        # Load configuration files for the default server block.
        include /nginx_test/conf/default.d/*.conf;

        error_page 404 /404.html;
        location = /404.html {
        }

        error_page 500 502 503 504 /50x.html;
        location = /50x.html {
        }
    }

# Settings for a TLS enabled server.
#
#    server {
#        listen       443 ssl http2;
#        listen       [::]:443 ssl http2;
#        server_name  _;
#        root         /usr/share/nginx/html;
#
#        ssl_certificate "/etc/pki/nginx/server.crt";
#        ssl_certificate_key "/etc/pki/nginx/private/server.key";
#        ssl_session_cache shared:SSL:1m;
#        ssl_session_timeout  10m;
#        ssl_ciphers PROFILE=SYSTEM;
#        ssl_prefer_server_ciphers on;
#
#        # Load configuration files for the default server block.
#        include /etc/nginx/default.d/*.conf;
#
#        error_page 404 /404.html;
#        location = /404.html {
#        }
#
#        error_page 500 502 503 504 /50x.html;
#        location = /50x.html {
#        }
#    }

}

基本上只對文件路徑進行了更改,但需要注意端口號。

根据下面的报道,如果使用常用端口(0至1023号),需要root权限。因此,这次我们改变了端口号为9999。

参考的文章:

关于Linux端口号的种类(个人备忘)

接下来我们要进行service文件的设置更改。

改动内容:

$ diff /usr/lib/systemd/system/nginx.service /usr/lib/systemd/system/nginx.service_bk
8c8
< PIDFile=/nginx_test/run/nginx.pid
---
> PIDFile=/run/nginx.pid
12,14c12,14
< ExecStartPre=/usr/bin/rm -f /nginx_test/run/nginx.pid
< #ExecStartPre=/usr/sbin/nginx -t
< ExecStart=/usr/sbin/nginx -c /nginx_test/conf/nginx.conf
---
> ExecStartPre=/usr/bin/rm -f /run/nginx.pid
> ExecStartPre=/usr/sbin/nginx -t
> ExecStart=/usr/sbin/nginx
20,21d19
< User=nginx
< Group=nginx
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network-online.target remote-fs.target nss-lookup.target
Wants=network-online.target

[Service]
Type=forking
PIDFile=/nginx_test/run/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f /nginx_test/run/nginx.pid
#ExecStartPre=/usr/sbin/nginx -t
ExecStart=/usr/sbin/nginx -c /nginx_test/conf/nginx.conf
ExecReload=/usr/sbin/nginx -s reload
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true
User=nginx
Group=nginx

[Install]
WantedBy=multi-user.target

以下是变更点的4个选项:
-将路径更改为/nginx_test
-注释掉ExecStartPre语法检查
-在ExecStart中单独指定配置文件
-在User和Group中添加对nginx的指定

5. 确认结果

由于更改了service文件,所以需要执行daemon-reload命令并进行stop/start操作以重新启动。

$ sudo systemctl daemon-reload
$ sudo systemctl stop nginx
$ sudo systemctl start nginx

与确认默认值时的相同,我们将确认进程的启动用户。

$ ps -ef |grep nginx
nginx       5207       1  0 15:17 ?        00:00:00 nginx: master process /usr/sbin/nginx -c /nginx_test/conf/nginx.conf
nginx       5208    5207  0 15:17 ?        00:00:00 nginx: worker process

我成功将主进程的启动用户更改为 nginx 。为了确保连接正常,我还将使用 curl 进行连接测试。

$ curl http://localhost:9999 -o /dev/null -w '%{http_code}\n' -s
200

可以确认状态码200。

在中国式的后记

我成功地使用普通用户启动了nginx服务。这就是云计算的优点之一,可以快速进行此类验证。

顺便提一下,curl命令是读作”卡尔”的。
以前我一直读成”丘尔”,以后要注意了…。