mattintosh note

数年ぶりにカメラを買ったのでフィギュアを撮る練習をしています

Amazon Linux 2とNginx 1.20.xでログローテーション後にログが書き込めなくなる件

結論から言うと Amazon Linux 2 の nginx パッケージの問題でもあるけど Nginx の仕様も問題 ということになった。


Nginx を起動するときは特に問題ないのだけどログを見てると夜中のログローテーションのタイミングで何故かログが書き込みできなくなっていた。

2022/01/30 03:26:01 [emerg] 8725#8725: open() "/var/log/nginx/error.log" failed (13: Permission denied)
2022/01/30 03:26:01 [emerg] 8725#8725: open() "/var/log/nginx/access.log" failed (13: Permission denied)

Amazon Linux 2 のバージョンと Nginx のバージョン。(Docker だけど)

bash-4.2# uname -a
Linux 82589fcda577 5.10.76-linuxkit #1 SMP Mon Nov 8 10:21:19 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
bash-4.2# yum info nginx
Loaded plugins: ovl, priorities
Installed Packages
Name        : nginx
Arch        : x86_64
Epoch       : 1
Version     : 1.20.0
Release     : 2.amzn2.0.4
Size        : 1.7 M
Repo        : installed
From repo   : amzn2extra-nginx1
Summary     : A high performance web server and reverse proxy server
URL         : https://nginx.org
License     : BSD
Description : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
            : IMAP protocols, with a strong focus on high concurrency, performance and low
            : memory usage.

logrotate の設定ファイルを見ると postrotatekill -USR1nginx -s reopen)している。

/etc/logrotate.d/nginx

/var/log/nginx/*log {
    daily
    rotate 10
    missingok
    notifempty
    compress
    sharedscripts
    postrotate
        /bin/kill -USR1 `cat /run/nginx.pid 2>/dev/null` 2>/dev/null || true
    endscript
}

/var/log/nginxroot:root 700 だけどマスタープロセスは root で動いているし、起動や再起動のときにログに書き込みができないようなエラーは出ない。ただ、ローテーションしたタイミングでログファイルの所有権が nginx:root に変わってるのが謎だった。

Nginx のインストール構成に問題があるのかと思ったので調べてみる。

RPM パッケージのスクリプトでは特にパーミッションを弄るような操作はしていない模様。

bash-4.2# yum reinstall --downloadonly --downloaddir=/tmp nginx
bash-4.2# rpm -qp --scripts /tmp/nginx-1.20.0-2.amzn2.0.4.x86_64.rpm
postinstall scriptlet (using /bin/sh):

if [ $1 -eq 1 ] ; then
        # Initial installation
        systemctl preset nginx.service >/dev/null 2>&1 || :
fi
preuninstall scriptlet (using /bin/sh):

if [ $1 -eq 0 ] ; then
        # Package removal, not upgrade
        systemctl --no-reload disable nginx.service > /dev/null 2>&1 || :
        systemctl stop nginx.service > /dev/null 2>&1 || :
fi
postuninstall scriptlet (using /bin/sh):

systemctl daemon-reload >/dev/null 2>&1 || :

if [ $1 -ge 1 ]; then
    /usr/bin/nginx-upgrade >/dev/null 2>&1 || :
fi

--queryformat|--qf オプションでコンテンツの内容を確認してみる。

bash-4.2# rpm -q --qf "[%{FILEMODES:perms} %{FILEUSERNAME}:%{FILEGROUPNAME} %{FILENAMES}\n]" nginx | column -t
-rw-r--r--  root:root   /etc/logrotate.d/nginx
-rw-r--r--  root:root   /etc/nginx/fastcgi.conf
-rw-r--r--  root:root   /etc/nginx/fastcgi.conf.default
-rw-r--r--  root:root   /etc/nginx/fastcgi_params
-rw-r--r--  root:root   /etc/nginx/fastcgi_params.default
-rw-r--r--  root:root   /etc/nginx/koi-utf
-rw-r--r--  root:root   /etc/nginx/koi-win
-rw-r--r--  root:root   /etc/nginx/mime.types
-rw-r--r--  root:root   /etc/nginx/mime.types.default
-rw-r--r--  root:root   /etc/nginx/nginx.conf
-rw-r--r--  root:root   /etc/nginx/nginx.conf.default
-rw-r--r--  root:root   /etc/nginx/scgi_params
-rw-r--r--  root:root   /etc/nginx/scgi_params.default
-rw-r--r--  root:root   /etc/nginx/uwsgi_params
-rw-r--r--  root:root   /etc/nginx/uwsgi_params.default
-rw-r--r--  root:root   /etc/nginx/win-utf
-rwxr-xr-x  root:root   /usr/bin/nginx-upgrade
-rw-r--r--  root:root   /usr/lib/systemd/system/nginx.service
drwxr-xr-x  root:root   /usr/lib64/nginx/modules
-rwxr-xr-x  root:root   /usr/sbin/nginx
drwxr-xr-x  root:root   /usr/share/doc/nginx-1.20.0
-rw-r--r--  root:root   /usr/share/doc/nginx-1.20.0/CHANGES
-rw-r--r--  root:root   /usr/share/doc/nginx-1.20.0/README
-rw-r--r--  root:root   /usr/share/doc/nginx-1.20.0/README.dynamic
-rw-r--r--  root:root   /usr/share/doc/nginx-1.20.0/UPGRADE-NOTES-1.6-to-1.10
drwxr-xr-x  root:root   /usr/share/licenses/nginx-1.20.0
-rw-r--r--  root:root   /usr/share/licenses/nginx-1.20.0/LICENSE
-r--r--r--  root:root   /usr/share/man/man3/nginx.3pm.gz
-rw-r--r--  root:root   /usr/share/man/man8/nginx-upgrade.8.gz
-rw-r--r--  root:root   /usr/share/man/man8/nginx.8.gz
-rw-r--r--  root:root   /usr/share/nginx/html/404.html
-rw-r--r--  root:root   /usr/share/nginx/html/50x.html
drwxr-xr-x  root:root   /usr/share/nginx/html/icons
lrwxrwxrwx  root:root   /usr/share/nginx/html/icons/poweredby.png
-rw-r--r--  root:root   /usr/share/nginx/html/index.html
-rw-r--r--  root:root   /usr/share/nginx/html/nginx-logo.png
lrwxrwxrwx  root:root   /usr/share/nginx/html/poweredby.png
-rw-r--r--  root:root   /usr/share/vim/vimfiles/ftdetect/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/ftplugin/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/indent/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/syntax/nginx.vim
drwxrwx---  nginx:root  /var/lib/nginx
drwxrwx---  nginx:root  /var/lib/nginx/tmp
drwx------  root:root   /var/log/nginx

これを見てみると /var/log/nginx は最初から root:root 0700 なようだ。

Amazon Linux 1 はどうなっていたのか

Nginx のバージョンは 1.18 系。

bash-4.2# yum info nginx
Loaded plugins: ovl, priorities
Installed Packages
Name        : nginx
Arch        : x86_64
Epoch       : 1
Version     : 1.18.0
Release     : 1.43.amzn1
Size        : 1.5 M
Repo        : installed
From repo   : amzn-updates
Summary     : A high performance web server and reverse proxy server
URL         : https://nginx.org
License     : BSD
Description : Nginx is a web server and a reverse proxy server for HTTP, SMTP, POP3 and
            : IMAP protocols, with a strong focus on high concurrency, performance and low
            : memory usage.
bash-4.2# rpm -q --qf "[%{FILEMODES:perms} %{FILEUSERNAME}:%{FILEGROUPNAME} %{FILENAMES}\\n]" nginx | column -t
-rw-r--r--  root:root   /etc/logrotate.d/nginx
drwxr-xr-x  root:root   /etc/nginx
drwxr-xr-x  root:root   /etc/nginx/conf.d
-rw-r--r--  root:root   /etc/nginx/conf.d/virtual.conf
drwxr-xr-x  root:root   /etc/nginx/default.d
-rw-r--r--  root:root   /etc/nginx/fastcgi.conf
-rw-r--r--  root:root   /etc/nginx/fastcgi.conf.default
-rw-r--r--  root:root   /etc/nginx/fastcgi_params
-rw-r--r--  root:root   /etc/nginx/fastcgi_params.default
-rw-r--r--  root:root   /etc/nginx/koi-utf
-rw-r--r--  root:root   /etc/nginx/koi-win
-rw-r--r--  root:root   /etc/nginx/mime.types
-rw-r--r--  root:root   /etc/nginx/mime.types.default
-rw-r--r--  root:root   /etc/nginx/nginx.conf
-rw-r--r--  root:root   /etc/nginx/nginx.conf.default
-rw-r--r--  root:root   /etc/nginx/scgi_params
-rw-r--r--  root:root   /etc/nginx/scgi_params.default
-rw-r--r--  root:root   /etc/nginx/uwsgi_params
-rw-r--r--  root:root   /etc/nginx/uwsgi_params.default
-rw-r--r--  root:root   /etc/nginx/win-utf
-rwxr-xr-x  root:root   /etc/rc.d/init.d/nginx
-rw-r--r--  root:root   /etc/sysconfig/nginx
drwxr-xr-x  root:root   /usr/lib64/nginx/modules
-rwxr-xr-x  root:root   /usr/sbin/nginx
drwxr-xr-x  root:root   /usr/share/doc/nginx-1.18.0
-rw-r--r--  root:root   /usr/share/doc/nginx-1.18.0/CHANGES
-rw-r--r--  root:root   /usr/share/doc/nginx-1.18.0/README
-rw-r--r--  root:root   /usr/share/doc/nginx-1.18.0/README.dynamic
drwxr-xr-x  root:root   /usr/share/licenses/nginx-1.18.0
-rw-r--r--  root:root   /usr/share/licenses/nginx-1.18.0/LICENSE
-r--r--r--  root:root   /usr/share/man/man3/nginx.3pm.gz
-rw-r--r--  root:root   /usr/share/man/man8/nginx.8.gz
drwxr-xr-x  root:root   /usr/share/nginx
drwxr-xr-x  root:root   /usr/share/nginx/html
-rw-r--r--  root:root   /usr/share/nginx/html/404.html
-rw-r--r--  root:root   /usr/share/nginx/html/50x.html
drwxr-xr-x  root:root   /usr/share/nginx/html/icons
lrwxrwxrwx  root:root   /usr/share/nginx/html/icons/poweredby.png
-rw-r--r--  root:root   /usr/share/nginx/html/index.html
-rw-r--r--  root:root   /usr/share/nginx/html/nginx-logo.png
lrwxrwxrwx  root:root   /usr/share/nginx/html/poweredby.png
-rw-r--r--  root:root   /usr/share/vim/vimfiles/ftdetect/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/ftplugin/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/indent/nginx.vim
-rw-r--r--  root:root   /usr/share/vim/vimfiles/syntax/nginx.vim
drwxrwx---  nginx:root  /var/lib/nginx
drwxrwx---  nginx:root  /var/lib/nginx/tmp
drwxrwx---  nginx:root  /var/log/nginx

1.18 系のときは /var/log/nginxnginx:root 770 だったようだ。

Amazon Linux 1 と Amazon Linux 2 でどこが変わったのか

色々差はあるけど今回問題なのはここ。

--- /tmp/1.txt   2022-02-05 10:44:56.000000000 +0900
+++ /tmp/2.txt    2022-02-05 10:44:30.000000000 +0900
@@ -45,4 +41,4 @@
 -rw-r--r--  root:root   /usr/share/vim/vimfiles/syntax/nginx.vim
 drwxrwx---  nginx:root  /var/lib/nginx
 drwxrwx---  nginx:root  /var/lib/nginx/tmp
-drwxrwx---  nginx:root  /var/log/nginx
+drwx------  root:root   /var/log/nginx

Nginx 1.18 系では nginx:root 770 になっていたものが 1.20 系では root:root 700 に変わっている。

Nginx をソースコードからビルドしたらどうなるのか

気になったので nginx-1.20.2 をビルドして動かしてみた。普通に make install したら logs ディレクトリは 755

bash-4.2# ls -l /usr/local/nginx
total 36
drwxr-xr-x 2 root   root 4096 Feb  5 02:02 conf
drwxr-xr-x 2 root   root 4096 Feb  5 02:02 html
drwxr-xr-x 2 root   root 4096 Feb  5 02:12 logs
drwxr-xr-x 2 root   root 4096 Feb  5 02:02 sbin

kill -USR1 でやっぱりログの所有権が変わってしまうようだが書き込みはできている模様。

bash-4.2# ls -l /usr/local/nginx/logs
total 20
-rw-r--r-- 1 nobody root 173 Feb  5 02:13 access.log
-rw-r--r-- 1 root   root  31 Feb  5 02:07 access.log.gz
-rw-r--r-- 1 nobody root 196 Feb  5 02:13 error.log
-rw-r--r-- 1 root   root  89 Feb  5 02:08 error.log.gz
-rw-r--r-- 1 root   root   6 Feb  5 02:08 nginx.pid

パーミッション変えてみたら書き込めなくなった。

bash-4.2# chmod 700 /usr/local/nginx/logs
bash-4.2# rm /usr/local/nginx/logs/*
bash-4.2# kill -USR1 `cat /usr/local/nginx/logs/nginx.pid`
bash-4.2# curl localhost
bash-4.2# ls -l /usr/local/nginx/logs
total 8
-rw-r--r-- 1 nobody root  0 Feb  5 02:15 access.log
-rw-r--r-- 1 nobody root  0 Feb  5 02:15 error.log
-rw-r--r-- 1 root   root  6 Feb  5 02:08 nginx.pid

その後 770 も試してみたところ書き込みできているように見えるのに error.logPermission denied が出たり意味不明。

また、logs755 に戻しただけでは書き込みは再開されず、一旦 kill -USR1 する必要がある模様。ということは reopen するときにログに書き込みできるかどうか見てるのだろうか。

Amazon Linux 2 の nginx-1.20.0 でも同じように 755 にして kill -USR1 したら問題なく書き込めることが確認できた。

なにこの挙動

Nginx を nginx ユーザで動かしたときにアバウトに確認してみたところ下記のようになった(気がする)。

root:root nginx:root
777 true true
775 true true
770 false true
755 true true
750 false true
707 true true
705 true true
700 false true

reopen 時にログファイルが存在しているかどうかのチェックは実行ユーザでしていて書き込みは root でしてるの…?

(ついでに)Nginx 公式の CentOS パッケージ

root:root755 だそうです。

[root@66e4b0919a1e /]# ls -l /var/log
total 52
-rw------- 1 root utmp      0 Nov 13  2020 btmp
-rw-r--r-- 1 root root    193 Nov 13  2020 grubby_prune_debug
-rw-r--r-- 1 root root 292000 Feb  5 03:55 lastlog
drwxr-xr-x 2 root root   4096 Feb  5 03:55 nginx
-rw------- 1 root root  64000 Feb  5 03:55 tallylog
-rw-rw-r-- 1 root utmp      0 Nov 13  2020 wtmp
-rw------- 1 root root   1665 Feb  5 03:55 yum.log

標準の動作だとログを削除して reopen すると nginx:root になるんだけど logrotate のときは nginx:admcreate するようにしてるっぽい。

/etc/logrotate.d/nginx

/var/log/nginx/*.log {
        daily
        missingok
        rotate 52
        compress
        delaycompress
        notifempty
        create 640 nginx adm
        sharedscripts
        postrotate
                if [ -f /var/run/nginx.pid ]; then
                        kill -USR1 `cat /var/run/nginx.pid`
                fi
        endscript
}

結局どうするのがいいのか

  • 一般ユーザがログを閲覧できていいなら root:root755
  • 一般ユーザにログを見せたくないなら nginx:root700

かなぁ…

Amazon Linux Extras リポジトリの問い合わせってどこにすればええんや…