Ubuntu 16.04 に Dropbox をインストール

メインマシンの apostrophe (OS は Ubuntu 16.04 LTS)に Dropbox をインストールする。

まずはこのページから .deb ファイルをダウンロード。で、インストールする。.deb ファイルのインストールは dpkg コマンド。apt じゃないんだな。

takatoh@apostrophe $ cd Downloads
takatoh@apostrophe $ ls
dropbox_2019.02.14_amd64.deb
takatoh@apostrophe $ sudo dpkg -i dropbox_2019.02.14_amd64.deb
[sudo] takatoh のパスワード: 
以前に未選択のパッケージ dropbox を選択しています。
(データベースを読み込んでいます … 現在 239399 個のファイルとディレクトリがインストールされています。)
dropbox_2019.02.14_amd64.deb を展開する準備をしています …
dropbox (2019.02.14) を展開しています…
dpkg: 依存関係の問題により dropbox の設定ができません:
 dropbox は以下に依存 (depends) します: libpango1.0-0 (>= 1.36.3) …しかし:
  パッケージ libpango1.0-0 はまだインストールされていません。

dpkg: パッケージ dropbox の処理中にエラーが発生しました (--install):
 依存関係の問題 - 設定を見送ります
man-db (2.7.5-1) のトリガを処理しています …
desktop-file-utils (0.22-1ubuntu5.2) のトリガを処理しています …
bamfdaemon (0.5.3~bzr0+16.04.20180209-0ubuntu1) のトリガを処理しています …
Rebuilding /usr/share/applications/bamf-2.index…
gnome-menus (3.13.3-6ubuntu3.1) のトリガを処理しています …
mime-support (3.59ubuntu1) のトリガを処理しています …
hicolor-icon-theme (0.15-0ubuntu1.1) のトリガを処理しています …
処理中にエラーが発生しました:
 dropbox

あれ、エラーが発生した。libpango1.0-0 っていうパッケージがインストールされてないみたいだ。インストールする。こんどは apt で。

takatoh@apostrophe $ sudo apt install libpango1.0-0

もういちど Dropbox のインストール。

takatoh@apostrophe $ sudo dpkg -i dropbox_2019.02.14_amd64.deb
(データベースを読み込んでいます … 現在 239431 個のファイルとディレクトリがインストールされています。)
dropbox_2019.02.14_amd64.deb を展開する準備をしています …
dropbox (2019.02.14) で (2019.02.14 に) 上書き展開しています …
dropbox (2019.02.14) を設定しています …
Please restart all running instances of Nautilus, or you will experience problems. i.e. nautilus --quit
Dropbox installation successfully completed! You can start Dropbox from your applications menu.
man-db (2.7.5-1) のトリガを処理しています …
desktop-file-utils (0.22-1ubuntu5.2) のトリガを処理しています …
bamfdaemon (0.5.3~bzr0+16.04.20180209-0ubuntu1) のトリガを処理しています …
Rebuilding /usr/share/applications/bamf-2.index…
gnome-menus (3.13.3-6ubuntu3.1) のトリガを処理しています …
mime-support (3.59ubuntu1) のトリガを処理しています …
hicolor-icon-theme (0.15-0ubuntu1.1) のトリガを処理しています …

こんどは大丈夫のようだ。しばらく待つと、Dropbox のウィンドウが立ち上がるので、指示に従って Dropbox をスタート。あとはアカウントの設定をすれば、ファイルの同期が始まる。

web サーバからファイルをダウンロードできない問題、その後

前エントリ、というかその追記部分の続き。

MyDNS にログインして、DNS の更新ログを見てみると、最後に IPv4 が更新されたのが24日の17時ころ。その後更新されてない。

いったんはうまくいったのは、24日17時ころに更新した IPv4 アドレスが有効だったからだろう。その後 WiMAX 端末に割り当てられたアドレスが変わったにもかかわらず、DNS が更新されなかったのが原因ではないか。もう少し正確に言うと、IPv6 アドレスだけが更新されて IPv4 アドレスが更新されなかったのが原因なんだと思う。

そこで、試しに MyDNS の設定ページで IPv4 アドレスを 0.0.0.0、IPv6 アドレスを 0:0:0:0:0:0:0:0 に設定しておいて、bigswifty 上でアドレス通知のスクリプトを実行してみた。すると案の定、IPv6 アドレスだけが更新されて、IPv4 アドレスは 0.0.0.0 のままだった。思ったとおりだ。

で、どうすればいいかというと、MyDNS のページにヒントが書いてあった。曰く、IPv4 と IPv6 のデュアルスタックのマシンでは通常の通知先 www.mydns.jp ではうまくいかないことがあるらしく、IPv4 アドレスを更新したい場合は ipv4.mydns.jp に通知しろ、ということのようだ。

なのでアドレス通知スクリプトの中の通知先ホスト名を上記の通り変更して、実行してみた。すると、今度はちゃんと IPv4 アドレスが更新された。ログでも確認できたし、ping も通るようになった。

さあ、これでやっと解決だ……というところまでが昨日の朝の話。

その後、夕方ころに出先からファイルダウンロードを試してみたらちゃんとダウンロードできたので大丈夫だと思っていた。ところが家に返ってきて試してみると、やっぱりエラーページが表示されてダウンロードできない。けれどふと気がついて、借りている VPS に ssh でログインして、そこから(つまり家のローカルネットワークでないところから)試してみると、ちゃんとダウンロードできる。どうも家のネットワークからだとエラーになるみたいだ。どゆこと?

でも、まぁ、外部向けの web サーバなんだから外部から使えればそれでいいか。

CentOS 7: 2つのネットワークに繋ぐ

web サーバにしている PC を2つのネットワークに繋ぐようにしたら問題が発生した。よく理解できてないけど、なんとか解決したので書く。

状況整理

まずは、2つ目のネットワークに繋ぐ前の状況を整理しておく。

ウチには2つのインターネット回線があって、それぞれに web サーバを公開している。1つは光回線で1つ目の web サーバのほか、いくつかある PC は全てこのネットワークに繋がっている。もう1つは去年の12月に導入した WiMAX で、2つ目の web サーバだけが有線で繋がっている(クレードルを介している)。2つのネットワークはウチの中では独立していて繋がっていない。

なので、2つ目の web サーバ――面倒だからホスト名で呼ぼう、bigswifty だ――を操作したい時には直接操作するか、インターネット経由で ssh 接続する必要があった。まぁ、これで用は足りてたんだけど、インターネット経由だとホスト名が長いのが微妙だった。

ついでに先に書いておこう、bigswifty の OS は CentOS 7.6 だ。

今日突然思いついた

ほぼ1年間、上記の状態で使ってたんだけど、今日突然思いついた。bigswifty は有線で WiMAXに繋がってるけど、WiFi もあるじゃないか。WiFi で光回線側のネットワークに繋げば、いつもメインで使ってる apostrophe からインターネットを経由しないで ssh できるようになるはずだ。

というわけで、さっそく bigswifty に直接ログインして、WiFi を有効にし、光回線側のネットワークに繋いだ。これで apostrophe から bigswifty に、インターネットを経由しなくても繋がるようになった。やったぜ!

問題発覚

ところがしばらくして問題が発覚した。bigswifty が web サーバとして機能してないのだ。具体的に言うと、インターネット経由で bigswifty からファイルをダウンロードしようとしても Nginx のエラーページが表示されて、ダウンロードできない。

試しに WiFi を無効にしてみると、ちゃんとファイルをダンロードできるようになった。

よくわからないけど解決編

いろいろググった結果、↓このページを見つけた。

 cf. 複数NICでのデフォルトゲートウェイ設定方法 – maruko2 note

ルータの DHCP 機能にまかせていたルーティングを手動で設定してやればいいようだ。これをスタティックルートというらしい。

じゃ、手順を始めよう。まずはデフォルトゲートウェイを設定する。/etc/sysconfig/network ファイルにつぎのように記述する。

GATEWAY=192.168.100.1

デフォルトゲートウェイは WiMAX 端末だ。つぎに、光回線側のネットワークと通信するための設定を書く。WiFi のインターフェイス名は wlo1 なので、/etc/sysconfig/networs-scripts ディレクトリの下に route-wlo1 というファイルを作って、つぎのようにする。

192.168.1.0/24 via 192.168.1.1

192.168.1.0/24(光回線のネットワークのこと)にアクセスするには 192.168.1.1(光回線側のルータ)を経由しろ、っていうことだと思う。

そして network を再起動。

[takatoh@bigswifty ~]$ sudo systemctl restart network

これで作業は終わり。

はたして、無事、光回線側からも ssh で繋がるし、インターネットからもファイルをダウンロードできるようになった。

[追記:11/25]

現在11月25日午前4時過ぎ。インターネット経由でファイルをダウンロードしようとしたら、Nginx のエラーページが表示されてダウンロードできなかった。

ごめん、上に書いた方法じゃダメだったみたいだ。いったんはちゃんと繋がった(ホントだよ!)から解決できたものだと思ったんだけど……

ローカルネットワーク(光回線側)から ssh で繋ぐことはできる。ping を試してみるとつぎの通り、応答が返ってくる。

takatoh@apostrophe $ ping bigswifty
PING bigswifty (192.168.1.13) 56(84) bytes of data.
64 bytes from bigswifty (192.168.1.13): icmp_seq=1 ttl=64 time=27.2 ms
64 bytes from bigswifty (192.168.1.13): icmp_seq=2 ttl=64 time=3.87 ms
64 bytes from bigswifty (192.168.1.13): icmp_seq=3 ttl=64 time=3.96 ms
64 bytes from bigswifty (192.168.1.13): icmp_seq=4 ttl=64 time=5.47 ms
64 bytes from bigswifty (192.168.1.13): icmp_seq=5 ttl=64 time=5.03 ms
64 bytes from bigswifty (192.168.1.13): icmp_seq=6 ttl=64 time=9.35 ms
^C
--- bigswifty ping statistics ---
6 packets transmitted, 6 received, 0% packet loss, time 5007ms
rtt min/avg/max/mdev = 3.875/9.153/27.218/8.282 ms

だけど、インターネット経由だと応答が返ってこない。

takatoh@apostrophe $ ping lathercraft-storage3.mydns.jp
PING lathercraft-storage3.mydns.jp (49.135.111.90) 56(84) bytes of data.
^C
--- lathercraft-storage3.mydns.jp ping statistics ---
37 packets transmitted, 0 received, 100% packet loss, time 35999ms

lathercraft-storage3.mydns.jp っていうのは、bigswifty をインターネットに公開した時のホスト名だ。DDNS の mydns を使ってる。

ここでちょっと思いついて、lathercraft-storage3.mydns.jp が現在どんなアドレスを使ってるのか確かめてみた。このサイトで確認できる。すると、49.135.102.186 だった。これは lathercraft-storage3.mydns.jp に ping を打った時に応答したアドレスと違う。

てことは、問題は DNS だ。mydns には cron にスクリプトを登録して定期的にアドレスの通知をしてるんだけど、手動でやってみた結果がこれ:

<head>
<title>Free Dynamic DNS (DDNS) for Home Server and VPS etc  | MyDNS.JP</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<LINK href="./site.css" rel=stylesheet type=text/css>

</head>
<BODY BGCOLOR="#FFFFFF"
      TEXT="#304040"
      leftmargin="0" topmargin="0" marginwidth="0" marginheight="0"
>
Login and IP address notify OK.<BR>
login_status = 1.<BR>
<BR>
<DT>MASTERID :</DT><DD>mydns882612</DD>
<DT>REMOTE ADDRESS:</DT><DD>240b:12:1461:6100:c480:657b:ef6b:892d</DD>
<DT>ACCESS DAYTIME:</DT><DD>2019/11/24 19:46:44 UTC</DD>
<DT>SERVER ADDRESS:</DT><DD>2604:180:3:ab6::245c</DD>
<BR>

</body>
</html>

REMOTE ADDRESS が通知したアドレスなんだけど、IPv6 のアドレスになっている。問題はこれかぁ。

さて、どうしよう?

Nginx + Unicorn on CentOS 8 with SELinux

前のエントリで 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.

はぁ、長かった。

Ruby 製アプリを Unicorn で動かす

昨日に引き続きデプロイの続きをするよ。今日の作業はまず Unicorn でアプリを動かすことだ。

Gemfile に unicorn を書き足して bundle install。

source "https://rubygems.org"

gem 'sinatra'
gem 'httpclient'
gem 'json'
gem 'filestorage'
gem 'unicorn'
[lcstorage@rollo lcstorage]$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/………….
Resolving dependencies…
Using bundler 2.0.2
Using filestorage 0.1.0
Using httpclient 2.8.3
Using json 2.2.0
Fetching kgio 2.11.2
Installing kgio 2.11.2 with native extensions
Using mustermann 1.0.3
Using rack 2.0.7
Using rack-protection 2.0.7
Fetching raindrops 0.19.0
Installing raindrops 0.19.0 with native extensions
Using tilt 2.0.10
Using sinatra 2.0.7
Fetching unicorn 5.5.1
Installing unicorn 5.5.1 with native extensions
Bundle complete! 5 Gemfile dependencies, 12 gems now installed.
Bundled gems are installed into ./vendor/bundle

Unicorn の設定ファイル unicorn.conf を書く。

listen "9000"
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]$ bundle exec unicorn -c unicorn.conf -E production

昨日と同じく、別のコンソールからアクセス。

[takatoh@rollo ~]$ curl http://localhost:9000/
File not found.[takatoh@rollo ~]$ 
[takatoh@rollo ~]$ curl http://localhost:9000/path/to/file
File not found.[takatoh@rollo ~]$

うん、ちゃんと File not found. が返ってきてる。昨日も書いたけど、返すファイルがまだ無いのでこれは正しい動作だ。

さて、あとは Nginx との連携だけど、これはエントリを分ける。というわけでとりあえずここまで。

CentOS 8 のマシンに Ruby 製 web アプリをデプロイしようとしたら bundle install でコケた

前にやった時もそうだったような気がするんだよなぁ。

詳しい話に入る前に、作業環境を整理しよう。web アプリのデプロイ先は、この間買った新しい マシン rollo (OS は CentOS 8)。これにいつもの作業用メインマシン apostrophe(OS は Ubuntu 16.04 LTS)から ssh で接続して作業してる。rollo 上での作業はアプリの専用ユーザ lcstorage で行った。

まずは、BitBucket から git clone した。

GitHub じゃないのは公開したくないプライベートなプロジェクトだから。オープンにしてもいいプロジェクトは GitHub、そうでないのは BitBucket と使い分けてる。

閑話休題。git clone が終わったので、必要なライブラリをインストールすべく bundle install したらコケた。

[lcstorage@rollo lcstorage]$ bundle install --path vendor/bundle
Fetching gem metadata from https://rubygems.org/………….
Using bundler 2.0.2
Fetching filestorage 0.1.0
Installing filestorage 0.1.0
Fetching httpclient 2.8.3
Installing httpclient 2.8.3
Fetching json 2.2.0
Installing json 2.2.0 with native extensions
Gem::Ext::BuildError: ERROR: Failed to build gem native extension.

current directory:
/home/lcstorage/lcstorage/vendor/bundle/ruby/2.5.0/gems/json-2.2.0/ext/json/ext/generator
/usr/bin/ruby -r ./siteconf20191122-22908-wlblo2.rb extconf.rb
mkmf.rb can't find header files for ruby at /usr/share/include/ruby.h

extconf failed, exit code 1

Gem files will remain installed in
/home/lcstorage/lcstorage/vendor/bundle/ruby/2.5.0/gems/json-2.2.0 for
inspection.
Results logged to
/home/lcstorage/lcstorage/vendor/bundle/ruby/2.5.0/extensions/x86_64-linux/2.5.0/json-2.2.0/gem_make.out

An error occurred while installing json (2.2.0), and Bundler cannot
continue.
Make sure that gem install json -v '2.2.0' --source 'https://rubygems.org/'
succeeds before bundling.

In Gemfile:
  json

どうも json gem が拡張ライブラリで、ビルドできなくてコケてるようだ。いろいろググって試行錯誤した結果、つぎのパッケージを dnf install したらできた。

  • gcc
  • make
  • ruby-devel
  • rpm-build

gcc や make が入ってなかったのか……

ともあれこれでインストールはできた。必要な設定ファイルやらディレクトリやらを作って、試しに起動してみた。

[lcstorage@rollo lcstorage]$ bundle exec rackup
[2019-11-22 22:32:38] INFO  WEBrick 1.4.2
[2019-11-22 22:32:38] INFO  ruby 2.5.3 (2018-10-18) [x86_64-linux]
[2019-11-22 22:32:38] INFO  WEBrick::HTTPServer#start: pid=25617 port=9292

起動は大丈夫のようだ。9292番のポートは開けてないので、別のターミナルから別のユーザで rollo に入ってアクセスしてみた。

[takatoh@rollo ~]$ curl http://localhost:9292/
File not found.[takatoh@rollo ~]$ 
[takatoh@rollo ~]$ curl http://localhost:9292/path/to/file
File not found.[takatoh@rollo ~]$

返すファイルがないので File not found. が帰ってくるのは正しい動作。どうやら大丈夫のようだ。

明日は Nginx を介して外部からアクセスできるようにする予定。

CentOS 8 に Nginx をインストールしてみた

インストール

dnf install コマンドでインストール。

[takatoh@rollo ~]$ sudo dnf install nginx

有効化とスタート。

[takatoh@rollo ~]$ sudo systemctl enable nginx
Created symlink /etc/systemd/system/multi-user.target.wants/nginx.service → /usr/lib/systemd/system/nginx.service.
[takatoh@rollo ~]$ sudo systemctl start nginx

ステータスの確認。

[takatoh@rollo ~]$ systemctl status nginx
● nginx.service - The nginx HTTP and reverse proxy server
   Loaded: loaded (/usr/lib/systemd/system/nginx.service; enabled; vendor preset: disabled)
   Active: active (running) since Tue 2019-11-19 03:01:37 JST; 8min ago
  Process: 10021 ExecStart=/usr/sbin/nginx (code=exited, status=0/SUCCESS)
  Process: 10019 ExecStartPre=/usr/sbin/nginx -t (code=exited, status=0/SUCCESS)
  Process: 10017 ExecStartPre=/usr/bin/rm -f /run/nginx.pid (code=exited, status=0/SUCCESS)
 Main PID: 10022 (nginx)
    Tasks: 5 (limit: 26213)
   Memory: 8.9M
   CGroup: /system.slice/nginx.service
           ├─10022 nginx: master process /usr/sbin/nginx
           ├─10023 nginx: worker process
           ├─10024 nginx: worker process
           ├─10025 nginx: worker process
           └─10026 nginx: worker process
11月 19 03:01:37 rollo systemd[1]: Starting The nginx HTTP and reverse proxy server…
11月 19 03:01:37 rollo nginx[10019]: nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
11月 19 03:01:37 rollo nginx[10019]: nginx: configuration file /etc/nginx/nginx.conf test is successful
11月 19 03:01:37 rollo systemd[1]: Started The nginx HTTP and reverse proxy server.

OK。ちゃんと起動したようだ。

ファイアウォールの設定

80番ポートを開ける。

[takatoh@rollo ~]$ sudo firewall-cmd --permanent --zone=public --add-service=http
success

firewalld をリロード。

[takatoh@rollo ~]$ sudo firewall-cmd --reload
success

これで OK のはず。ほかのマシンからブラウザでアクセスしてみたら、ちゃんと Nginx のデフォルトページが表示された。

CentOS 8 をインストールしてみた

新しい PC を買ったんだ。これまで Dell か HP だったので、今回は Lenovo にしてみた。ThinkCentre M630e Tiny っていうモデル。てのひらにはちょっとあまるけど、超小型 PC と言っていい大きさだ。

で、せっかくなので最近リリースされたばかりの CentOS 8.0.1905 をインストールしてみた。プレインストールされていた Windows 10 は削除。

インストーラは CentOS 7 と特段変わらない印象。でもデフォルトのインストールタイプ(っていうんだっけ?)が、「サーバー(GUI使用)」になってた。もちろんこれでOK。ひととおりインストールが済んで再起動すると、ちゃんと CentOS が立ち上がった。いつかの Dell の PC みたいに起動しないなんてことはなかった。いい兆候だ。あと、ホスト名は rollo にした。

日本語入力

インストール時に日本語を選んでいるので、メニューとかは日本語になってるんだけど、そのままでは入力はできないようだ。↓このページが参考になった。

cf. デスクトップ環境 : GNOME デスクトップ インストール – Server World

まずは日本語入力プログラムをインストール。

[takatoh@rollo ~]$ sudo dnf -y install ibus-kkc

CentOS 7 までの yum コマンドじゃなくて dnf っていうコマンドでパッケージをインストールするらしい。

それから、背景画面の適当なところで右クリックして設定ウィンドウをひらいて、 Region & Language に移動する。入力ソースの欄で、日本語(かな漢字)を追加すれば準備は完了。画面右上のアイコンをクリックして日本語(かな漢字)を選べば OK だ。あとは半角/全角キーで入力モードを切り替えられる。今日のこのエントリもそうやって書いている。

Ruby とか Python とか

Python が入ってない、と思ったら python3 コマンドだった。

[takatoh@rollo ~]$ python3 -V
Python 3.6.8

Python はデフォルトが 3 系になったらしい。なら python コマンドでいいだろうになんで python3 なんだ。

Ruby は入ってない。のでインストールした。

[takatoh@rollo ~]$ ruby -v
bash: ruby: コマンドが見つかりませんでした…
コマンド ruby' を提供するためにパッケージ 'ruby' をインストールしますか? [N/y] y
キューで待機中… 
パッケージの一覧をロード中。… 
以下のパッケージはインストールされるべきものです:
ruby-2.5.3-104.module_el8.0.0+179+565e49e2.x86_64    An interpreter of object-oriented scripting language
ruby-irb-2.5.3-104.module_el8.0.0+179+565e49e2.noarch    The Interactive Ruby
ruby-libs-2.5.3-104.module_el8.0.0+179+565e49e2.x86_64    Libraries necessary to run Ruby
rubygem-bigdecimal-1.3.4-104.module_el8.0.0+179+565e49e2.x86_64    BigDecimal provides arbitrary-precision floating point decimal arithmetic
rubygem-did_you_mean-1.2.0-104.module_el8.0.0+179+565e49e2.noarch    "Did you mean?" experience in Ruby
rubygem-io-console-0.4.6-104.module_el8.0.0+179+565e49e2.x86_64    IO/Console is a simple console utilizing library
rubygem-json-2.1.0-104.module_el8.0.0+179+565e49e2.x86_64    This is a JSON implementation as a Ruby extension in C
rubygem-openssl-2.1.2-104.module_el8.0.0+179+565e49e2.x86_64    OpenSSL provides SSL, TLS and general purpose cryptography
rubygem-psych-3.0.2-104.module_el8.0.0+179+565e49e2.x86_64    A libyaml wrapper for Ruby
rubygem-rdoc-6.0.1-104.module_el8.0.0+179+565e49e2.noarch    A tool to generate HTML and command-line documentation for Ruby projects
rubygems-2.7.6-104.module_el8.0.0+179+565e49e2.noarch    The Ruby standard for packaging ruby libraries
変更したまま継続しますか? [N/y] y
キューで待機中… 
認証を待ち受け中… 
キューで待機中… 
パッケージをダウンロード中… 
データを要求中… 
変更をテスト中… 
パッケージのインストール中… 
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux] 
[takatoh@rollo ~]$ ruby -v
ruby 2.5.3p105 (2018-10-18 revision 65156) [x86_64-linux]

2.5.3 がインストールされた。

というところで、今日はここまで。