2019年3月16日土曜日

OpenWrt on WZR-HP-AG300H: nginx

デフォルトの uHTTPd に替えて当初は Apache を入れようとしたが、マトモに動かなかった(公式のフォーラムでもそのような話が出ていた)。それで諦めかけていたのだが、どうしても Virtual Host を実現したいので、nginx を入れてみることにした。

公式 wiki に従って(PHP は使う予定がないので、該当部分は飛ばした。)入れてみると、とても軽快で、さらに設定も /etc/nginx/nginx.conf に記載された内容で行うだけという、とてもシンプルなものだった。歴史が長過ぎて半ば妖怪化しつつあるような Apache と違って、一発で気に入った。

Virtual Host は nginx.conf で server {} を追加するのが基本。

ただし、デメリットも 2 点発生した。

  1. デフォルトでは HTTPS に対応していない
  2. CGI に対応していない

OpenWrt 用 nginx の HTTPS 化

nginx 自体は HTTPS に対応しているのだが、OpenWrt 標準の nginx モジュール(.ipk)は HTTPS 非対応でコンパイルされているため、自前で nginx モジュールをコンパイルして用意しなければならない。大変だったが(nginx の HTTPS 化そのものについては、一箇所しか情報が存在しなかったほど、情報が限られていた)、最終的に実現できた。

  1. 【下準備】Linux で git を使える環境を整える:
    apt install git-core build-essential libssl-dev libncurses5-dev unzip gawk zlib1g-dev subversion libncurses5-dev gcc-multilib flex gettext mercurial
  2. git clone して、ソースコードを用意する:
    git clone https://git.openwrt.org/openwrt/openwrt.git
    cd openwrt
  3. このままでは有無を言わさず最新のソースコードが使われてしまい、ライブラリーとのバージョンの不整合が起こるため、自分の使っている stable バージョンに絞って checkout する。
    git checkout v18.06.2
  4. make menuconfig
    Target System、Subtarget、Target Profile のみ、ルーターに合わせて適当に設定し、Build the OpenWrt SDK をチェックして SAVE -> EXIT。
  5. make V=s
    コンパイルが始まるので、時間がかかる。
  6. scripts/feeds update
    scripts/feeds search nginx
    scripts/feeds install nginx
  7. make menuconfig
    再度、menuconfig を立ち上げると、nginx に関するコンパイルオプションを設定できる状態になるので、望みのように設定して SAVE -> EXIT。
    network > Web Servers/Proxies にある。nginx そのものは M(モジュール)で選択し、さらに詳細はその中に入って設定する。Enable SSL module で HTTPS が有効になる(ついでで HTTP2 と LUA も有効にしておいた)。
  8. make -j5
    コンパイルし直す
  9. .ipk を拾い出す。bin の中にあるが、find コマンドを使って場所を特定するなどする:
    find . -type f -name nginx\*ipk
  10. .ipk をルーターに持っていって、opkg コマンドでインストールする。

OpenWrt で Let's Encrypt

acme.sh を使った。

wget なり、curl なりで acme.sh をダウンロードして、あとは acme.sh コマンドを駆使してお任せ。

root@WWW:~# ./acme.sh --install
It is recommended to install socat first.
We use socat for standalone server if you use standalone mode.
If you don't use standalone mode, just ignore this warning.
Installing to /root/.acme.sh
Installed to /root/.acme.sh/acme.sh
No profile is found, you will need to go into /root/.acme.sh to use acme.sh
Installing cron job
OK

socat なるものが必要とされるが、スタンドアローン・モードに限った話であり、スタンドアローン・モードで使う予定はないので問題なし。

root@WWW:~# cd .acme.sh
root@WWW:~/.acme.sh# ./acme.sh --issue -d scaredeer.com -d www.scaredeer.com -w /mnt/data/www/scaredeer.com --accountemail scaredeer@scaredeer.com
Registering account
Registered
ACCOUNT_THUMBPRINT='(省略)'
Creating domain key
The domain key is here: /root/.acme.sh/scaredeer.com/scaredeer.com.key
Multi domain='DNS:scaredeer.com,DNS:www.scaredeer.com'
Getting domain auth token for each domain
Getting webroot for domain='scaredeer.com'
Getting new-authz for domain='scaredeer.com'
The new-authz request is ok.
Getting webroot for domain='www.scaredeer.com'
Getting new-authz for domain='www.scaredeer.com'
The new-authz request is ok.
Verifying: scaredeer.com
Success
Verifying: www.scaredeer.com
Success
Verify finished, start to sign.
Cert success.
-----BEGIN CERTIFICATE-----
(省略)
-----END CERTIFICATE-----
Your cert is in  /root/.acme.sh/scaredeer.com/scaredeer.com.cer 
Your cert key is in  /root/.acme.sh/scaredeer.com/scaredeer.com.key 
The intermediate CA cert is in  /root/.acme.sh/scaredeer.com/ca.cer 
And the full chain certs is there:  /root/.acme.sh/scaredeer.com/fullchain.cer 

以上で、certification の issue が終わる(issue の段階では nginx.conf を更新・リロードしないこと。nginx が落ちてしまい、acme-challenge に失敗してしまう)。あとは発行した証明書を nginx 用にインストール。インストール先としては、nginx.conf で指定する予定の path(未だ存在しない場合は予め mkdir しておく)を使った。

root@WWW:~/.acme.sh# ./acme.sh --install-cert -d scaredeer.com -d www.scaredeer.com --key-file /mnt/data/www/scaredeer.com/cert/cert.key --fullchain-file /mnt/data/www/scaredeer.com/cert/cert.pem --reloadcmd "service nginx reload"
Installing key to:/mnt/data/www/scaredeer.com/cert/cert.key
Installing full chain to:/mnt/data/www/scaredeer.com/cert/cert.pem
Run reload cmd: service nginx reload
./acme.sh: eval: line 1: service: not found
Reload error for :

acme.sh が service コマンドを使った nginx の reload まで面倒を見てくれているが、何故かエラーになっている。自分で手動で service nginx reload すればいいだけなので、別に問題ない、はず。ただ、acme.sh は証明書の自動更新まで面倒を見てくれるようで、自動更新にこの --reloadcmd が関係している可能性もあり、今後自動更新が無事に行われるかどうかは、その時になってみないと不明。

Please take care: The reloadcmd is very important. The cert can be automatically renewed, but, without a correct 'reloadcmd' the cert may not be flushed to your server(like nginx or apache), then your website will not be able to show renewed cert in 60 days.

ともかく、(nginx.conf を更新した上で)service nginx reload して、実際に HTTPS でアクセスできるようになっていれば、無事終了である。

HTTP (80) を HTTPS (443) にリダクレクト

上で HTTPS 化にも成功したので、あとは、HTTP にアクセスしたら、自動的に HTTPS の方にリダイレクトするための設定で完成する。HTTP (80) の方の nginx.conf の該当する server ブロックの設定を次のように修正しておけばよい。

server {
	listen 80;
	server_name www.scaredeer.com scaredeer.com;
	return 301 https://$host$request_uri;
}

CGI の扱い

色々調べて試した結果、リバースプロキシで uHTTPd のポート(この例では 81)から出力結果を引っ張ってくるという対処方法に落ち着いた。nginx.conf の該当する server ブロック内に次の location ブロックを追加する:

location /cgi-bin {
	proxy_pass http://127.0.0.1:81;
}

2019年3月4日月曜日

OpenWrt on WZR-HP-AG300H: MariaDB

データベースとしては、MySQL 互換らしい MariaDB を入れた。

パッケージ

  • mariadb-server
  • mariadb-client

要点

  1. MariaDB 用に /etc/mysql/my.cnf の datadir と tmpdir を USB メモリーディスク(/mnt/data)下に作成した mysql ディレクトリと tmp ディレクトリに指定する。(my.cnf のコメントに、これらのディレクトリの配置場所として NAND フラッシュ領域を使わないようにと書かれている)
  2. さらに、/var/run に mysqld ディレクトリが存在しなければ、予め作成しておく。(mysqld.sock ファイルのために使われることになる。)
  3. my.cnf で Linux Native AIO を無効化しておく([mysqld] に innodb_use_native_aio = 0 を追加)。さらにスワップ(USB メモリーディスク参照)が有効だと、InnoDB のエラーが解消され、MariaDB-server が正常に動くようになる。
  4. (当然ながら)MariaDB-client もインストールしないと、mysql コマンド自体が使えない。動作テストができない。
  5. mysql コマンドで対話画面を起動して、ちゃんと動いているかを確かめる。システムログを見ると、InnoDB のエラーが出ていたりするのが確認できる。

OpenWrt on WZR-HP-AG300H: SFTP サーバー

/etc/config にある設定ファイルを扱う程度ならば scp コマンドで十分だが、WWW サーバーとしてセットアップすると、ファイルのアップロード作業が頻繁に発生するようになってくるので、FileZilla のような FTP クライアントを使ってファイルのやりとりが出来るように SFTP サーバーをセットアップしておくことにする。openssh-sftp-server をインストールする。

もちろん、SSH の拡張的な SFTP ではなく、ちゃんとした FTP サーバーの方をインストールする手もある。👉 FTP servers