前のエントリで web アプリを Unicorn で動かすことに成功したので、今度は Nginx と連携する。
その前に unicorn.conf をちょっと修正して、ポートじゃなくて UNIX ソケットを利用するようにする。
#listen "9000" listen "/run/lcstorage/unicorn.sock" worker_processes 2 working_directory "/home/lcstorage/lcstorage" pid "/home/lcstorage/lcstorage/unicorn.pid" stdout_path "/home/lcstorage/lcstorage/unicorn.log" stderr_path "/home/lcstorage/lcstorage/unicorn.log" preload_app true
そしてソケットファイルを置くディレクトリを作る。
[lcstorage@rollo lcstorage]$ sudo mkdir /run/lcstorage [lcstorage@rollo lcstorage]$ sudo chown lcstorage:lcstorage /run/lcstorage
Unicorn の準備はこれで終わり。起動しておく。
[lcstorage@rollo lcstorage]$ bundle exec unicorn -c unicorn.conf -E production
さて、つぎは Nginx の設定だ。storage1 というホスト名でアクセスできるよう、/etc/nginx/conf.d の下に storage1.conf という名前で設定ファイルを作る。
upstream lcstorage { server unix:/run/lcstorage/unicorn.sock; #server 127.0.0.1:9000; } server { # port listen 80; # server name server_name storage1; # document root #root /home/lcstorage/lcstorage; # index #index index.php index.html index.htm; client_max_body_size 4G; # log files access_log /var/log/nginx/storage1/access.log main; error_log /var/log/nginx/storage1/error.log warn; keepalive_timeout 60; proxy_connect_timeout 60; proxy_read_timeout 60; proxy_send_timeout 60; location / { #root /home/lcstorage/lcstorage; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header Host $http_host; proxy_pass http://lcstorage; } }
ログを書き込むディレクトリを忘れずに作っておく。
これで準備はできたはずだ。Nginx を再起動しよう。
[takatoh@rollo conf.d]$ sudo systemctl restart nginx
で、別マシンから http://storage1/ にアクセスしてみると、結果はこうだった。
502 Bad Gateway
あー、これはあれだ、SELinux のせいだ。試しに SELinux を Permissive モードにしてみる。
[takatoh@rollo ~]$ sudo setenforce 0 [takatoh@rollo ~]$ getenforce Permissive
この状態でもう一度アクセスしていると、ちゃんと File not found. と表示された。なんどもいうけど、返すファイルがないのでこれが正しい動作だ。
つまり、SELinux をどうにかしてやらないといけないわけだ。だけどググってみると、解決策として出てくるのは SELinux を無効にしろ、っていうのばっかり。ちゃんと使い方を説明しているページはほとんど無い。そんな中で参考になったのが以下のページ。
cf. 【ゼロから始める】初期設定のみのLinuxサーバーに既存のRailsアプリとWebサーバーを導入する – Takeshi’s Blog
と、そこからリンクされているページ。
cf. RedmineをCentOS 7上で動かすーUnicornとNginx編 – ソフトウェアエンジニアリング
Nginx のエラーログを調べると:
2019/11/23 11:33:23 [crit] 2526#0: *1 connect() to unix:/run/lcstorage/unicorn.sock failed (13: Permission denied) while connecting to upstream, client: 192.168.1.11, server: storage1, request: "GET / HTTP/1.1", upstream: "http://unix:/run/lcstorage/unicorn.sock:/", host: "storage1"
となっていて、ソケットファイルにアクセスできないようだ。じゃあ、ソケットファイルのパーミッションはどうなってるかというと:
[takatoh@rollo ~]$ ls -lZ /run/lcstorage 合計 0 srwxrwxrwx. 1 lcstorage lcstorage unconfined_u:object_r:var_run_t:s0 0 11月 23 11:42 unicorn.sock
Z は SELinux のアクセス権限を表示するオプション。うん、よくわからん。SELinux が原因かどうかは /var/log/audit/audit.log を調べるとわかるらしい。再度 SELinux を有効にしてアクセスしてみてから:
[takatoh@rollo ~]$ sudo cat /var/log/audit/audit.log | grep nginx | tail type=SERVICE_STOP msg=audit(1574476367.153:1276): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=SERVICE_START msg=audit(1574476367.207:1277): pid=1 uid=0 auid=4294967295 ses=4294967295 subj=system_u:system_r:init_t:s0 msg='unit=nginx comm="systemd" exe="/usr/lib/systemd/systemd" hostname=? addr=? terminal=? res=success'UID="root" AUID="unset" type=AVC msg=audit(1574476403.391:1281): avc: denied { connectto } for pid=2526 comm="nginx" path="/run/lcstorage/unicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1574476403.391:1281): arch=c000003e syscall=42 success=no exit=-13 a0=e a1=561f05479e28 a2=6e a3=7ffe9aa20e0c items=0 ppid=2522 pid=2526 auid=4294967295 uid=977 gid=975 euid=977 suid=977 fsuid=977 egid=975 sgid=975 fsgid=975 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="nginx" GID="nginx" EUID="nginx" SUID="nginx" FSUID="nginx" EGID="nginx" SGID="nginx" FSGID="nginx" type=AVC msg=audit(1574476651.650:1290): avc: denied { connectto } for pid=2526 comm="nginx" path="/run/lcstorage/unicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=1 type=SYSCALL msg=audit(1574476651.650:1290): arch=c000003e syscall=42 success=yes exit=0 a0=e a1=561f05479e28 a2=6e a3=7ffe9aa20e0c items=0 ppid=2522 pid=2526 auid=4294967295 uid=977 gid=975 euid=977 suid=977 fsuid=977 egid=975 sgid=975 fsgid=975 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="nginx" GID="nginx" EUID="nginx" SUID="nginx" FSUID="nginx" EGID="nginx" SGID="nginx" FSGID="nginx" type=AVC msg=audit(1574477463.658:1309): avc: denied { connectto } for pid=2526 comm="nginx" path="/run/lcstorage/unicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=1 type=SYSCALL msg=audit(1574477463.658:1309): arch=c000003e syscall=42 success=yes exit=0 a0=e a1=561f05479e28 a2=6e a3=7ffe9aa20e0c items=0 ppid=2522 pid=2526 auid=4294967295 uid=977 gid=975 euid=977 suid=977 fsuid=977 egid=975 sgid=975 fsgid=975 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="nginx" GID="nginx" EUID="nginx" SUID="nginx" FSUID="nginx" EGID="nginx" SGID="nginx" FSGID="nginx" type=AVC msg=audit(1574477957.417:1347): avc: denied { connectto } for pid=2526 comm="nginx" path="/run/lcstorage/unicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0 type=SYSCALL msg=audit(1574477957.417:1347): arch=c000003e syscall=42 success=no exit=-13 a0=e a1=561f05479e28 a2=6e a3=7ffe9aa20e0c items=0 ppid=2522 pid=2526 auid=4294967295 uid=977 gid=975 euid=977 suid=977 fsuid=977 egid=975 sgid=975 fsgid=975 tty=(none) ses=4294967295 comm="nginx" exe="/usr/sbin/nginx" subj=system_u:system_r:httpd_t:s0 key=(null)ARCH=x86_64 SYSCALL=connect AUID="unset" UID="nginx" GID="nginx" EUID="nginx" SUID="nginx" FSUID="nginx" EGID="nginx" SGID="nginx" FSGID="nginx"
さぱーりわからん。けど、どうやら↓ここらしい。
type=AVC msg=audit(1574477957.417:1347): avc: denied { connectto } for pid=2526 comm="nginx" path="/run/lcstorage/unicorn.sock" scontext=system_u:system_r:httpd_t:s0 tcontext=unconfined_u:unconfined_r:unconfined_t:s0-s0:c0.c1023 tclass=unix_stream_socket permissive=0
nginx が /run/lcstorage/unicorn.sock にアクセスしようとして denied になってるようだ。つまりここを何とかすればいいわけ。
SELinux の上のアクセスを許可する設定は、/var/log/audit/audit.log ファイルから audit2allow コマンドで作れるようだ。まず確認。
[takatoh@rollo ~]$ sudo grep nginx /var/log/audit/audit.log | audit2allow #============= httpd_t ============== #!!!! This avc can be allowed using the boolean 'httpd_can_network_connect' allow httpd_t glance_port_t:tcp_socket name_connect; #!!!! This avc can be allowed using one of the these booleans: # httpd_can_network_connect, httpd_graceful_shutdown, httpd_can_network_relay, nis_enabled allow httpd_t http_port_t:tcp_socket name_connect; allow httpd_t unconfined_t:unix_stream_socket connectto;
設定用のファイルを作るにはこうする。
[takatoh@rollo ~]$ sudo grep nginx /var/log/audit/audit.log | audit2allow -M nginx [sudo] takatoh のパスワード: ******************* 重要 ******************** このポリシーパッケージを有効にするには、以下を実行して下さい: semodule -i nginx.pp
指示にあるようにして、SELinux に設定する。
[takatoh@rollo ~]$ sudo semodule -i nginx.pp
さてこれでどうだろう。はたして、別のマシンからブラウザでアクセスしてみると、ちゃんと File not found. って表示された。なんどもいうけどこれが(ry。
つぎは web アプリをサービスとして登録する。/etc/systemd/system ディレクトリの下に lcstorage.service ファイルを作る。
[Unit] Description=LatherCraft storage service After=network.target [Service] Type=forking PIDFile=/home/lcstorage/lcstorage/unicorn.pid ExecStart=/usr/local/bin/bundle exec unicorn -c unicorn.conf -E production -D ExecReload=/bin/kill -HUP $MAINPID ExecStop=/bin/kill -QUIT $MAINPID WorkingDirectory=/home/lcstorage/lcstorage User=lcstorage Group=lcstorage [Install] WantedBy=multi-user.target
これで起動してみる。
[takatoh@rollo system]$ sudo systemctl start lcstorage
あれ?おかしい。プロンプトが戻ってこない。ほかのターミナルからステータスを見てみると:
[lcstorage@rollo lcstorage]$ systemctl status lcstorage ● lcstorage.service - LatherCraft storage service Loaded: loaded (/etc/systemd/system/lcstorage.service; disabled; vendor pres> Active: activating (start) since Sat 2019-11-23 12:57:57 JST; 1min 14s ago Process: 3931 ExecStart=/usr/local/bin/bundle exec unicorn -c unicorn.conf -E production -D (code=exited, status=0/SUCCESS) Tasks: 6 (limit: 26213) Memory: 31.4M CGroup: /system.slice/lcstorage.service ├─3936 unicorn master -c unicorn.conf -E production -D production -D ├─3939 unicorn worker[0] -c unicorn.conf -E production -D productio> └─3942 unicorn worker[1] -c unicorn.conf -E production -D productio> 11月 23 12:57:57 rollo systemd[1]: Starting LatherCraft storage service… 11月 23 12:57:58 rollo systemd[1]: lcstorage.service: Can't convert PID files /home/lcstorage/lcstorage/unicorn.pid O_PATH file descriptor to proper file descriptor: Permission denied 11月 23 12:57:58 rollo systemd[1]: lcstorage.service: Can't convert PID files /home/lcstorage/lcstorage/unicorn.pid O_PATH file descriptor to proper file descriptor: Permission denied
pid ファイルにアクセスできないっぽい?じゃあ、場所を変えてみようか。/home/lcstorage/lcstorage/unicorn.conf と /etc/systemd/system/lcstorage.service の両方で pid ファイルを作る場所を /run に変えてみた。
でもまだダメ。もとに戻す。もう一度やってみてもこうなる。
[takatoh@rollo system]$ sudo systemctl start lcstorage Job for lcstorage.service failed because a timeout was exceeded. See "systemctl status lcstorage.service" and "journalctl -xe" for details.
で、SELinux を無効にしてやってみた。
[takatoh@rollo system]$ sudo setenforce 0 [takatoh@rollo system]$ getenforce Permissive [takatoh@rollo system]$ sudo systemctl start lcstorage
あ、これだとすんなりいく。ブラウザからアクセスしてもうまくいった。またお前か、SELinux!
さっきとおなじように /var/log/audit/audit.log を調べてみるとこうなってた。
type=AVC msg=audit(1574483152.115:1720): avc: denied { open } for pid=1 comm="systemd" path="/home/lcstorage/lcstorage/unicorn.pid" dev="dm-2" ino=24382 scontext=system_u:system_r:init_t:s0 tcontext=system_u:object_r:user_home_t:s0 tclass=file permissive=1
やっぱり pid ファイルにアクセスできないみたいだ。ポリシーを作ってやる。
[takatoh@rollo ~]$ sudo grep unicorn /var/log/audit/audit.log | audit2allow -M unicorn
[takatoh@rollo ~]$ sudo semodule -i unicorn.pp
これでどうだろう。
[takatoh@rollo ~]$ sudo setenforce 1 [takatoh@rollo ~]$ getenforce Enforcing [takatoh@rollo ~]$ sudo systemctl start lcstorage
お、うまくいったっぽい。ブラウザからアクセスしても大丈夫だった。
最後に。マシンを起動した時に自動起動するようにする。
[takatoh@rollo ~]$ sudo systemctl enable lcstorage Created symlink /etc/systemd/system/multi-user.target.wants/lcstorage.service → /etc/systemd/system/lcstorage.service.
はぁ、長かった。