Cloudflareを使っていて、個人的には不満があったわけでもないが、とりあえず、気分的にLet’s EncryptでSSL証明書を生成して内部ネットワークSSL化することにした。同時にnginxを使って、サービス、アプリをインストールする度にnginx.confを追加していたが、どうせなら Nginx Proxy Managerを使った方が管理が楽ですよ、とGeminiが提案するので、そうすることにした。
cloudflareでユーザAPIトークンを発行する
cloudflareでユーザAPIトークンを発行は、特に証明書をワイルドカード証明書で一括管理せず、追加するホスト毎に証明書を管理する場合は不要。
-
ユーザアイコンからクリック、プロフィールからプロフィール画面を表示
-
左メニューに APIトークン が表示されるので、それをクリックしてユーザーAPI トークン画面を表示する
-
トークンを作成する ボタンをクリックする
-
ゾーンDNSを編集する テンプレートを使用する
-
ゾーンリリース 項目で、以下のように設定する
含む| 特定のゾーン| 自身のドメイン
-
概要を表示して、確認したらトークンを作成する
サーバーでLet’s Encryptで証明書を発行できるようにする。 (この手順はNginx Proxy Managerでは不要)
sudo apt install certbot python3-certbot-dns-cloudflareを実行して、証明書発行のためのアプリとcloudflare用プラグインをインストールするsudo mkdir -p /root/.secrets/certbotLet’s Encrypt証明書のためのディレクトリを作成するsudoedit /root/.secrets/certbot/cloudflare.iniトークンを追記する
dns_cloudflare_api_token = 取得したトークン
sudo chmod 600 /root/.secrets/certbot/cloudflare.ini権限をroot以外誰も読み取れないようにする- サブドメイン含めてワイルドカード証明書を発行する
arimasou16@ubuntu:~$ sudo certbot certonly \
--dns-cloudflare \
--dns-cloudflare-credentials /root/.secrets/certbot/cloudflare.ini \
-d example.com \
-d "*.example.com"
Saving debug log to /var/log/letsencrypt/letsencrypt.log
Requesting a certificate for example.com and *.example.com
Waiting 10 seconds for DNS changes to propagate
- 無事、発行されたことを、証明書の保存場所を確認する
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/example.com/fullchain.pem
Key is saved at: /etc/letsencrypt/live/example.com/privkey.pem
ここまではNginx Proxy Managerを使わない場合のケースなので、やる意味はない。ただcloudflareを使わなくなることもあるのでメモとして残しておく。
Nginx Proxy Managerをインストール・設定する
ここではdockerで導入していく。まずは、自宅内の別端末からNginx Proxy Managerの管理者ページに接続できるようにファイヤーウォールで81を開ける。
$ sudoedit /etc/ufw/applications.d/nginx-proxy-manager
[NginxProxyManager]
title=Nginx Proxy Manager GUI
description=Web interface for managing Nginx Proxy Manager
ports=81/tcp
$ sudo ufw app update NginxProxyManager
$ sudo ufw allow NginxProxyManager
しかし、これだけでは駄目で、(root権限なし)Rootless Dockerを使っている場合、1024より下の番号を開いてはいけないルールになっている。
Error response from daemon: failed to set up container networking: driver failed programming external connectivity on endpoint arimasou16-app-1 (5ecd16b059558f21d25cb9bd7842f18ec99ec8f66f918e0db1503cb72f0c042d): error while calling RootlessKit PortManager.AddPort(): cannot expose privileged port 80, you can add 'net.ipv4.ip_unprivileged_port_start=80' to /etc/sysctl.conf (currently 1024), or set CAP_NET_BIND_SERVICE on rootlesskit binary, or choose a larger port number (>= 1024): listen tcp4 0.0.0.0:80: bind: permission denied
以下のコマンドを実行して、Nginx Proxy Managerにリバースプロキシーの役割をさせるので、80から1023番までのウェルノウンポートを開ける。
echo "net.ipv4.ip_unprivileged_port_start=80" | sudo tee -a /etc/sysctl.conf
次にNginx Proxy Managerで使うネットワークをnpm_app-netを作成する。
docker network create npm_app-net
npm-component.yml
services:
npm:
image: 'docker.io/jc21/nginx-proxy-manager:latest'
container_name: npm
restart: unless-stopped
ports:
- '80:80'
- '81:81'
- '443:443'
volumes:
- ./data:/data
- ./letsencrypt:/etc/letsencrypt
networks:
- app-net
networks:
app-net:
external: true
name: npm_app-net
その後、他のDockerでもNginx Proxy Managerと同じネットワークを使うようにする。そして、Nginx Proxy Managerを経由するコンテナについてはポートを開ける必要がないので項目自体を削除、もしくはコメントアウトする。
app-compose.yml
services:
db:
image: postgres:16-alpine
container_name: postgresql-server
・・・中略・・・
networks:
- app-net
#ports:
# - "127.0.0.1:5432:5432"
・・・中略・・・
joplin:
image: joplin/server:latest
container_name: joplin-server
・・・中略・・・
#ports:
# - "127.0.0.1:22300:22300"
・・・中略・・・
networks:
- app-net
・・・中略・・・
networks:
app-net:
external: true
name: npm_app-net
このように各アプリがカプセル化できるのでセキュリティも向上する。
Nginx Proxy Manager管理者ログイン
Nginx Proxy Manager起動後、Nginx Proxy ManagerサーバーのIPアドレス:80にアクセスして Congratulations! と表示されれば起動成功。
Nginx Proxy ManagerサーバーのIPアドレス:81で管理画面にアクセスする。管理者パスワードを設定する。
nginxのエラー画面として No Response (444) を設定しておく。
もしホストでnginxを起動・有効化しているなら、sudo systemctl stop nginx、sudo systemctl disable nginxして停止・無効化する。
Nginx Proxy Managerでワイルドカードの証明書を発行する。
以下は、特に証明書をワイルドカード証明書で一括管理せず、追加するホスト毎に証明書を管理する場合は不要。
-
上部メニューから Certificates をクリックして証明書一覧画面を表示する。
-
Add Certificate ボタンをクリックして、 Let’s Encrypt via DNS ボタンをクリックして Add Let’s Encrypt via DNS ダイアログを表示する。
-
Domain Namesを入力する(例:
example.com、*.example.comの両方)。何故かFirefox?だと入力項目にフォーカスがうまくいかない? -
Key Typeはそのまま
-
DNS Providerで Cloudflare を選択する。
-
Credentials File ContentにユーザAPIトークンを設定する。
# Cloudflare API token dns_cloudflare_api_token=ユーザAPIトークンユーザAPIトークンは平文で保存されるので注意。
-
Propagation Seconds(伝達秒数)は空で良し。もし空でエラーとなる場合は、60、120秒で試す。
-
Saveボタンを押す。
example.com *.example.comの証明書が作成されて、一覧に表示されることを確認する。証明書の更新などは自動でやってくれる。なので、もしホストにcertbotをインストール済の場合、タイマーを停止、無効にしておく。
sudo systemctl stop certbot.timer
sudo systemctl disable certbot.timer
Nginx Proxy ManagerでProxy Hostを追加する。
全てDockerアプリというわけでなく、バイナリで動いたり、サブディレクトリ構成で動いてるのもあるが、nginxでできることは、Nginx Proxy Managerで出来る。最悪、 Custom Nginx Configuration でそれまでの設定を貼り付けてしまえば移行できる。
Hosts -> Proxy Host のメニューをクリックする。
-
Domain Namesを入力する(例:
app.example.com)。何故かFirefox?だと入力項目にフォーカスがうまくいかない? -
Scheme、 Foward HostName / IP、Forward Portを入力する。
- 基本
http - Forward HostNameはコンテナ名もしくは、自サーバーIPアドレス
- コンテナが待ち受けているポートを指定する
- Websockets Support は手紙のような送信、受信のみのやりとりでは不要だが、電話のようなリアルタイムでのやりとりが必要な場合、オンにする、基本オンにした方が不具合は起きない。
- 基本
-
サブディレクトリ(
Location)を指定する場合は Custom Locations タブを開き、 Add Location をクリックする。-
Locationを入力する。 -
Locationの横の歯車で、生のnginx.confの記述が可能。 -
基本、 Details タブと同じ。
-
-
SSL タブでは Request a new Certification を選択する、もしくは既に証明書(ワイルドカード証明書など)があればそれを選択する。
- 保存のさいに、他のタブの設定でエラーになったりすると、既に重複エラーなどになったりした。そのときはDockerを再起動しなおしたら、とりあえず直った。
- 画面の上メニューに Certification というタブがあるのでそこで確認できる。
- Force SSL はCloudflareなどを使っている場合、無限ループの原因となるのでしない。
起動順序
Nginx Proxy Managerということでかなり便利で管理しやすくなるのだけど、大きな欠点がある。それは接続するホスト名をコンテナ名にしてる場合、もしコンテナが起動していないと…
❯ Starting nginx ...
nginx: [emerg] host not found in upstream "isso" in /data/nginx/proxy_host/1.conf:76
と名前解決できずに、Nginx Proxy Manager起動に失敗してしまう、ということ。これを防ぎたい場合は、コンテナ名でのホスト名の設定をやめてIPアドレスを指定して、docker portsの設定をする必要がある。ある意味、Nginx Proxy Managerから生粋のnginxに、すぐ戻せるようになる。
もしくは Issues · NginxProxyManager/nginx-proxy-managerのような解決方法がある1
また、再起動を繰り返すと、コンテナに割り当てられたIPアドレスが変わっているが、Nginx Proxy ManagerでDNSキャッシュされてIPアドレスとズレて接続できない、ということも起こりうる。その場合、Nginx Proxy Managerを再起動するなりしてキャッシュをクリアする。
バックアップなど
設定は、./data/nginx/proxy_host配下にnginx.confとしてあるのでこれをバックアップしておけばいつでも、バイナリのnginx運用に戻したり、サーバー移行でも使える。
$ ls -l npm/data/nginx/proxy_host/
合計 20
-rw-r--r-- 1 arimasou16 arimasou16 2272 3月 29 09:23 1.conf
-rw-r--r-- 1 arimasou16 arimasou16 4009 3月 29 10:21 4.conf
-rw-r--r-- 1 arimasou16 arimasou16 1014 3月 29 09:23 5.conf
-rw-r--r-- 1 arimasou16 arimasou16 1255 3月 29 09:23 6.conf
-rw-r--r-- 1 arimasou16 arimasou16 1255 3月 29 09:23 7.conf
証明書は./letsencrypt配下にある。これでサーバー移動や端末を変更しても直ぐに元に戻せる。
と確かにnginx.confを一つ一つ管理するよりはずっと楽になった。
-
ただ、ここまでやると正直、管理が煩雑になる気がする。 ↩︎






