有馬総一郎のブログ

(彼氏の事情)

2026年03月31日 03:58:42 JST - 8 minute read - Linux

Nginx Proxy Managerを導入してnginx.conf地獄から脱却する

Cloudflareを使っていて、個人的には不満があったわけでもないが、とりあえず、気分的にLet’s EncryptでSSL証明書を生成して内部ネットワークSSL化することにした。同時にnginxを使って、サービス、アプリをインストールする度にnginx.confを追加していたが、どうせなら Nginx Proxy Managerを使った方が管理が楽ですよ、とGeminiが提案するので、そうすることにした。

Nginx Proxy Manager

cloudflareでユーザAPIトークンを発行する

cloudflareでユーザAPIトークンを発行は、特に証明書をワイルドカード証明書で一括管理せず、追加するホスト毎に証明書を管理する場合は不要。

  1. ユーザアイコンからクリック、プロフィールからプロフィール画面を表示

  2. 左メニューに APIトークン が表示されるので、それをクリックしてユーザーAPI トークン画面を表示する

    Cloudflare
  3. トークンを作成する ボタンをクリックする

  4. ゾーンDNSを編集する テンプレートを使用する

    Cloudflare
  5. ゾーンリリース 項目で、以下のように設定する

    含む| 特定のゾーン| 自身のドメイン

    Cloudflare
  6. 概要を表示して、確認したらトークンを作成する

    Cloudflare
    Cloudflare

サーバーでLet’s Encryptで証明書を発行できるようにする。 (この手順はNginx Proxy Managerでは不要)

  1. sudo apt install certbot python3-certbot-dns-cloudflareを実行して、証明書発行のためのアプリとcloudflare用プラグインをインストールする
  2. sudo mkdir -p /root/.secrets/certbot Let’s Encrypt証明書のためのディレクトリを作成する
  3. sudoedit /root/.secrets/certbot/cloudflare.iniトークンを追記する
  dns_cloudflare_api_token = 取得したトークン
  1. sudo chmod 600 /root/.secrets/certbot/cloudflare.ini権限をroot以外誰も読み取れないようにする
  2. サブドメイン含めてワイルドカード証明書を発行する
  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
  1. 無事、発行されたことを、証明書の保存場所を確認する
  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

Nginx Proxy ManagerサーバーのIPアドレス:81で管理画面にアクセスする。管理者パスワードを設定する。

nginxのエラー画面として No Response (444) を設定しておく。

Nginx Proxy Manager

もしホストでnginxを起動・有効化しているなら、sudo systemctl stop nginxsudo systemctl disable nginxして停止・無効化する。

Nginx Proxy Managerでワイルドカードの証明書を発行する。

以下は、特に証明書をワイルドカード証明書で一括管理せず、追加するホスト毎に証明書を管理する場合は不要。

  1. 上部メニューから Certificates をクリックして証明書一覧画面を表示する。

  2. Add Certificate ボタンをクリックして、 Let’s Encrypt via DNS ボタンをクリックして Add Let’s Encrypt via DNS ダイアログを表示する。

  3. Domain Namesを入力する(例:example.com*.example.comの両方)。何故かFirefox?だと入力項目にフォーカスがうまくいかない?

  4. Key Typeはそのまま

  5. DNS Providerで Cloudflare を選択する。

  6. Credentials File ContentにユーザAPIトークンを設定する。

    # Cloudflare API token
    dns_cloudflare_api_token=ユーザAPIトークン
    

    ユーザAPIトークンは平文で保存されるので注意。

  7. Propagation Seconds(伝達秒数)は空で良し。もし空でエラーとなる場合は、60、120秒で試す。

  8. Saveボタンを押す。

    Nginx Proxy Manager

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 のメニューをクリックする。

Nginx Proxy Manager
Nginx Proxy Manager

  1. Domain Namesを入力する(例:app.example.com)。何故かFirefox?だと入力項目にフォーカスがうまくいかない?

  2. Scheme、 Foward HostName / IP、Forward Portを入力する。

    1. 基本http
    2. Forward HostNameはコンテナ名もしくは、自サーバーIPアドレス
    3. コンテナが待ち受けているポートを指定する
    4. Websockets Support は手紙のような送信、受信のみのやりとりでは不要だが、電話のようなリアルタイムでのやりとりが必要な場合、オンにする、基本オンにした方が不具合は起きない。
    Nginx Proxy Manager
  3. サブディレクトリ(Location)を指定する場合は Custom Locations タブを開き、 Add Location をクリックする。

    1. Locationを入力する。

    2. Locationの横の歯車で、生のnginx.confの記述が可能。

      • rewrite ^/joplin/(.*)$ /$1 break;サブディレクトリ構成でサブディレトリを削ってコンテナに渡す場合

        Nginx Proxy Manager
      • Syncthingの自己署名証明書をNPMに信用させる場合、proxy_ssl_verify off;とする

        Nginx Proxy Manager
        Nginx Proxy Manager

    3. 基本、 Details タブと同じ。

    Nginx Proxy Manager
  4. SSL タブでは Request a new Certification を選択する、もしくは既に証明書(ワイルドカード証明書など)があればそれを選択する。

    • 保存のさいに、他のタブの設定でエラーになったりすると、既に重複エラーなどになったりした。そのときはDockerを再起動しなおしたら、とりあえず直った。
    • 画面の上メニューに Certification というタブがあるのでそこで確認できる。
    • Force SSL はCloudflareなどを使っている場合、無限ループの原因となるのでしない。
    Nginx Proxy Manager

起動順序

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を一つ一つ管理するよりはずっと楽になった。


  1. ただ、ここまでやると正直、管理が煩雑になる気がする。 ↩︎