より少ないリソースで動くと言う内容を検索でみてx86ベース(32bit)でvpsの再構築をしました。
それとコンテナのlxcはできるだけメジャーなディストリビューションを使わず少ないリソースで動くOpenWrtベースで作りました。
出来立てのvpsはとっても調子がいいのですが、困った問題が出てきました。ssl証明書の発行でcertbotを使おうとしたのですが、python用のcertbotでは64ビット版rustしかなくインストールできません。そこでOpenwrtのサイトを検索したらacme.shが使えるとありました。
luci用パッケージもあるので楽々インストールできるかとたかを括っていたらどうも違うようです。
# /etc/init.d/acme start
acme: Option "keylength" is deprecated, please use key_type (e.g., ec256, rsa2048) instead.
acme: Option "webroot" is deprecated, please remove it and change your web server's config so it serves ACME challenge requests from /var/run/acme/challenge.
acme-acmesh: Running ACME for hottunalabs.net with validation_method webroot
acme-acmesh: /usr/lib/acme/client/acme.sh --renew --home /etc/acme -d hottunalabs.net
It seems that you are using sudo, please read this link first:
https://github.com/acmesh-official/acme.sh/wiki/sudo
このエラーの意味がわかからず、サイトの情報をよくみてもやはりわからないので、コマンドラインで取得する方法を調べてみました。
私流のssl証明書の取得方法
ネットワークのレイアウトは次のようになっています。
Internet --- Reverse Proxy --- Web Server1, Web Server2, Mail Server, Web Mail
一般的な証明書の取得方法はまずPort80にアクセスしてKeyを取得、CAサーバーがssl接続で申し込みをするDNSのサイトにアクセスしてそのKeyがあれば証明書を発行という流れです。
これとは別にWebサーバーのいらないacme.shのDNSで取得する方法もあり、一見便利そうですが、これには問題があり、更新時のことを考えてPort80を常に開けておかなければならないので、例えばhttpでサイトに接続しようとした場合、http接続からhttps接続に変換してくれない。これは使い勝手が悪くなるので、残念ながらこの方法は使えない。それで次のような方法でやってみました。
まずはProxyに認証用の仮サイトをPort80を指定して作る。必要なサイトはhttpからhttpsに変換するコードを入れる。
次にNginxの設定にacmeで取得したキーを読めるようにする。
参考:設定
Nignx
Reverse Proxy:
nginx.conf
stream {
map $ssl_preread_server_name $name {
labs.hottunalabs.net wp_labs_backend;
travel.hottunalabs.net wp_travel_backend;
upstream wp_labs_backend {
server 10.0.0.2:443;
server [2001:ce8:77:e::5654:a2]:443;
}
upstream wp_travel_backend {
server 10.0.0.3:2443;
server [2001:ce8:77:e::5654:a3]:2443;
}
server {
listen 443;
proxy_connect_timeout 8s;
proxy_timeout 16s;
proxy_pass $name;
ssl_preread on;
}
log_format basic '$ssl_preread_server_name $remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log /var/log/nginx/stream.access.log basic;
error_log /var/log/nginx/stream.error.log;
}
sites-available/proxy
1箇所、Port80でアクセスできるようにする。
server {
if ($host = hottunalabs.net) {
return 301 https://labs.hottunalabs.net$request_uri;
}
location ~ /.well-known/acme-challenge {
allow all;
}
server_name hottunalabs.net;
root /var/run/acme/challenge;
listen 80;
listen [::]:80;
}
他はhttpsサイトに接続できるようにする。
server {
if ($host = labs.hottunalabs.net) {
return 301 https://$host$request_uri;
}
server_name labs.hottunalabs.net;
return 301 https://labs.hottunalabs.net$request_uri;
location ~ /.well-known/acme-challenge {
allow all;
}
listen 80;
listen [::]:80;
}
使わないサブドメインは404を返すかほかのサブドメインに飛ばす。
server {
if ($host = www.hottunalabs.net) {
return 301 https://labs.hottunalabs.net$request_uri;
}
location ~ /.well-known/acme-challenge {
allow all;
}
listen 80;
listen [::]:80;
server_name www.hottunalabs.net;
return 404;
}
Backend Server:
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name labs.hottunalabs.net;
root /var/www/labs/wordpress;
index index.php;
client_max_body_size 2M;
proxy_ssl_name labs.hottunalabs.net;
proxy_ssl_server_name on;
ssl_certificate /etc/acme/hottunalabs.net/hottunalabs.net.cer;
# ssl_certificate /etc/acme/hottunalabs.net/fullchain.cer;
ssl_certificate_key /etc/acme/hottunalabs.net/hottunalabs.net.key;
ssl_session_cache builtin:1000 shared:SSL:10m;
ssl_dhparam /etc/acme/ssl-dhparams.pem;
# Use these if you built with OpenSSL.
ssl_ciphers TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-256-GCM-SHA384:TLS13-AES-128-GCM-SHA256:EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH;
ssl_ecdh_curve secp384r1;
ssl_prefer_server_ciphers on;
ssl_protocols TLSv1.3 TLSv1.2;
location / {
# This is cool because no php is touched for static content.
# include the "?$args" part so non-default permalinks doesn't break when using query string
try_files $uri $uri/ /index.php?$args;
}
location ~ /.well-known/acme-challenge {
allow all;
}
... 省略(wordpressのサイトの細かい設定) ...
location ~ \.php$ {
#NOTE: You should have "cgi.fix_pathinfo = 0;" in php.ini
include fastcgi.conf;
fastcgi_intercept_errors on;
fastcgi_pass php;
}
location ~* \.(js|css|png|jpg|jpeg|gif|ico)$ {
expires max;
log_not_found off;
}
location ~ ^/\.user\.ini {
deny all;
}
}
必ずこのラインlocation ~ /.well-known/acme-challengeを入れて外部から読めるようにしておく。
ここまでのざっくりとサーバーの設定でssl認証の取得が可能になります。
次はssl証明書をどうやってサーバー間で共有するかという問題、これはlxcを使っているのでoverlayで共有できるので、意外と簡単に解決できる。ただいくつかの制約があって、openwrtのサイトを見るとチャレンジkeyは/var/run/acmeに入れると書いてある。しかしoverlayしようとすると/run(/var/run)上にはなぜかできないので、/var/run/acmeを/var/www/htmlにシンボリックリンクを貼る。そしてBackend Serverの/var/www/html上にoverlayさせる。/var/www/html/.well-knownを各サーバーにシンボリックリンクを貼って(.well-known -> /var/www/html/acme/.well-known)、各サイトから見えるようする、という具合で解決する。
LXC: Backend Server
lxc.mount.entry = /var/lib/lxc/srv1-proxy/overlay/delta/var/run/acme/challenge var/www/html/acme none rbind,create=dir,optional 0 0
lxc.mount.entry = /var/lib/lxc/srv1-proxy/overlay/delta/etc/acme etc/acme none rbind,optional 0 0
lxc.apparmor.raw = mount,
WebサーバーもLXCも設定ができたら、acme.shを実行してssl証明書を取得する。
sudo /usr/lib/acme/client/acme.sh -d hottunalabs.net -d www.hottunalabs.net -d labs.hottunalabs.net -d travel.hottunalabs.net -d x1.hottunalabs.net -d x2.hottunalabs.net --keylength 2048 --accountemail xxxxxxxxxxxxxx@hotmail.com --server letsencrypt --webroot /var/run/acme/challenge --issue --home /etc/acme --debug
acmeの方法はcertbotに比べて使い方が難しいが、一度設定すれば後はリニューアルをするだけの簡単作業になりますが、たどり着くまでがなかなか苦戦するという今回の経験でした。
参考
- https://github.com/acmesh-official/acme.sh
- https://www.reddit.com/r/Proxmox/comments/10ehfhc/zfs_dataset_bind_mount_issue_how_do_i_mount/