こんにちは。ENDoDoです。
いつもアプリサイドの話がメインなので、今回はサーバサイドで起こった話を少し描きたいと思います。
背景
個人アプリのAPI取得元サーバーを2ヶ月ほど前にconohaに移行して、同時にnginx使い始めたんですが、sslについては、ここ無料じゃん!てことでLet's Encryptを使ってました。
ただ有効期限が90日しかなく、定期的に証明書の取得に更新をかけてやる必要がありました。
今回はその更新作業に失敗したらしく、以下のようなメールが来て、このままだとあと、19日でSSL死ぬよ?って言われたので対応しました。
Hello,
Your certificate (or certificates) for the names listed below will expire in 19 days (on 28 Oct 18 10:30 +0000). Please make sure to renew your certificate before then, or visitors to your website will encounter errors.
We recommend renewing certificates automatically when they have a third of their
total lifetime left. For Let's Encrypt's current 90-day certificates, that means
renewing 30 days before expiration. See
https://letsencrypt.org/docs/integration-guide/ for details.
エラー内容
certbot renewを実行したら、以下のようなことを言われました。
Waiting for verification...
Cleaning up challenges
Attempting to renew cert (xxx) from /etc/letsencrypt/renewal/xxx.conf produced an unexpected error: Failed authorization procedure. xxx (http-01): urn:acme:error:connection :: The server could not connect to the client to verify the domain :: Fetching http://newstock.tokyo/.well-known/acme-challenge/0UjfzETbb_cV1XC0_EFFb9RRHs2xgw6oIOOQAwy5DDE: Connection refused. Skipping.
All renewal attempts failed. The following certs could not be renewed:
/etc/letsencrypt/live/xxx/fullchain.pem (failure)
-------------------------------------------------------------------------------
1 renew failure(s), 0 parse failure(s)
IMPORTANT NOTES:
- The following errors were reported by the server:
Domain: xxx
Type: connection
Detail: Fetching
http://xxx/.well-known/acme-challenge/0UjfzETbb_cV1XC0_EFFb9RRHs2xgw6oIOOQAwy5DDE:
Connection refused
To fix these errors, please make sure that your domain name was
entered correctly and the DNS A/AAAA record(s) for that domain
contain(s) the right IP address. Additionally, please check that
your computer has a publicly routable IP address and that no
firewalls are preventing the server from communicating with the
client. If you're using the webroot plugin, you should also verify
that you are serving files from the webroot path you provided.
※xxxはドメイン名が入ります。
原因
色々調査したのですが、結論としてはどうやら、
http://xxx/.well-known/acme-challenge/
にアクセスできないのが原因でした。
※エラーにそう書いてるやんwって話なんですけどね。英語読めるようになりたい。。。
対応した事
1. フォルダの作成
ルートディレクトリ上に/.well-known/acme-challenge/ ディレクトリを作成しました。
2. nginx.confの設定内容変更
$ vi /etc/nginx/conf.d/default.conf を編集してlocationの設定を追加しました。
***
location / {
root /usr/share/nginx/html;
index index.html index.htm;
}
//追加箇所
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /usr/share/nginx/html;
}
***
3. 80番ポートの解放
セキュリティの為にhttp通信は切ってたんですが、Let's Encryptがhttpでアクセスしたがるので止むを得ず解放しました。
$ vi /etc/nginx/conf.d/default.conf を編集してserverの設定を追加しました。
server {
listen 80; //追加した
listen 443 ssl;
4. 再起動して実行
$ systemctl reload nginx
これで http://xxx/.well-known/acme-challenge/ にアクセスできるようになりました。
補足. 自動更新の設定
ここはcronで元々設定していたのですが、毎回3ヶ月ごとに更新かけるのも面倒だと思うのでやっておくことをオススメします。
# crontab -l
## Certificate renewal
0 4 1 * * /usr/bin/certbot renew && /usr/bin/systemctl reload nginx
僕はこんな感じで毎月1日に走るように設定してます。
感想
iOSアプリがhttps通信必須になってから、サーバーサイドの最低必要スキルが日々上がって来て面倒だなと感じる日々ですね。。
DBとウェブサーバーの繋ぎ込みやAPIの自動生成とか安価でやってくれるサービスとか出てくれるとありがたいのですが、GCPやAWSとか従量課金系は見積もりづらくてプライベートで使うにはハードルが高すぎる気がしてなりません。
なんかオススメのサービスとかあったら教えてください。