nginxのmaster processをroot以外のユーザで起動してみる

# 目次
[#1.はじめに](#1はじめに)
[#2.前提環境](#2前提環境)
[#3.デフォルトの確認](#3デフォルトの確認)
[#4.設定変更](#4設定変更)
[#5.結果確認](#5結果確認)
[#6.あとがき](#6あとがき)

# 1.はじめに
昨今セキュリティの要件が厳しくなってきており、基本的にはrootユーザは利用しない運用になっています。
サービスの起動ユーザについてもrootユーザが利用不可が要件となることもあるかと思い、nginxの起動ユーザの変更をしてみたので、自分用のメモとして残しておきます。

# 2.前提環境
Amazon Linux release 2023
nginx 1.22.1-1.amzn2023.0.3

# 3.デフォルトの確認
まずはnginxを導入してサービスを起動します。

```shell-session
$ sudo yum install nginx
$ sudo systemctl start nginx
```

デフォルトのプロセスを確認してみます。

```shell-session
$ 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
```

workerプロセスはnginxユーザで起動していますが、master processについてはrootユーザで起動しています。

# 4.設定変更
今回はworker processと同様にmaster processについてもnginxユーザで起動してみようと思います。

・nginxの設定
起動ユーザを変更する都合上、権限についても気にする必要があります。
今回は/nginx_testというディレクトリを作成し、権限変更、設定の変更を行います。

```shell-session
$ 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はpidファイル格納用、logはlogファイル格納用のディレクトリ、htmlはサンプルページ格納用のディレクトリです。

次にデフォルトの設定ファイルとサンプルページのhtmlファイルを今回作成したディレクトリにコピーし、ディレクトリの権限を変更します。
※検証なので777のnginx nginxに設定します

```shell-session
$ 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/*
```

では設定ファイルの内容を今回の検証向けにコンバートしていきます。

変更点：

```shell-session
$ 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;
```

変更後のファイル：

```/nginx_test/conf/nginx.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 ポート番号の種類について（自分用メモ](https://qiita.com/ss12345/items/36fdc1a2705b36f5be77)

・serviceファイルの設定変更
次にserviceファイルの変更を行います。

変更点：
```shell-session
$ 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
```

```/usr/lib/systemd/system/nginx.service
[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で再起動します。

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

デフォルトを確認した時と同様にプロセスの起動ユーザを確認します。

```shell-session
$ 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
```

master processの起動ユーザをnginxに変更できました。
念のためcurlで接続確認も実施します。

```shell-session
$ curl http://localhost:9999 -o /dev/null -w '%{http_code}\n' -s
200
```
ステータスコード200が確認できました。

# 6.あとがき
nginxサービスを一般ユーザで起動することに成功しました。
こういう検証がぱぱっとできるのがクラウドの利点ですね。

そういえばcurlコマンドってカールって読むんですね。
今までキュールと発音していたので気を付けます…。