UbuntuでのNginx Proxy Managerのインストールと設定:Web UIで管理するリバースプロキシとLet’s Encrypt SSL

Ubuntu tutorial - IT technology blog
Ubuntu tutorial - IT technology blog

/etc/nginx/sites-available/配下の設定ファイルを1行ずつ編集し、サービスをリロードした瞬間に真っ赤な構文エラーが表示される――これはWebサーバー管理者なら誰もが通る道でしょう。CertbotによるSSL更新のたびにcronジョブが正常に動くか気を揉んだり、インフラが拡大してサブドメインが15〜20個に達すると手動設定でのミスも多発しがちです。Nginx Proxy Manager(NPM)を使えば、これらの煩雑な作業を直感的なWeb UIに集約し、長大な設定ファイルの編集をシンプルな入力フォームへと置き換えることができます。

1. クイックスタート:5分で始めるNginx Proxy Managerのデプロイ

クリーンインストール直後のUbuntu 22.04または24.04 VPSにおいて、社内・内部Webアプリケーション向けのリバースプロキシゲートウェイとして最初に構築することが多い構成です。必要なコンポーネントはすべてDocker Composeにパッケージ化されています。

UbuntuにDockerエンジンとComposeプラグインをインストールします:

sudo apt update && sudo apt install -y docker.io docker-compose-v2
sudo systemctl enable --now docker

設定ファイルを配置するディレクトリを作成します:

mkdir -p ~/npm && cd ~/npm
nano docker-compose.yml

docker-compose.ymlに以下の内容を貼り付けます:

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt

バックグラウンドでコンテナを起動します:

docker compose up -d

SQLiteデータベースの初期化が完了するまで30〜45秒ほど待ち、ブラウザからhttp://IP_SERVER:81にアクセスします。

初期ログイン情報:

初回ログイン時にメールアドレスとパスワードの変更が求められます。ポート81がインターネットに公開されている状態のため、この変更作業はスキップせず必ず実施してください。

2. 詳細解説:Nginx Proxy Managerの動作メカニズム

従来のNginx運用で陥りがちな課題

従来の手法では、ドメインをNode.jsアプリ(ポート3000)やDockerコンテナ(ポート8080)へルーティングする際、仮想ホスト設定ファイルを個別に作成する必要がありました。その中にはupstreamやlocation /ブロックの定義、proxy_passの調整、X-Real-IPやX-Forwarded-Forなどの適切なヘッダー転送設定が含まれます。

さらにCertbotを実行してSSL証明書を取得する手順も伴います。数十個のアプリを運用する規模になると、1つのファイルでセミコロン;を忘れただけでNginx全体のリロードが失敗するリスクを抱えることになります。

Nginx Proxy Managerはどのように解決するか?

NPMはNginxをゼロから再実装したものではなく、コンテナ内部で稼働するNginxとCertbotを制御するWeb管理パネルとして機能します:

  • Web UIでホストを作成するたびに、./data/nginx/proxy_host/ディレクトリ配下に適切な形式の.confファイルが自動生成されます。
  • コンテナ内のCertbotが自動的にHTTP-01またはDNS-01によるACMEチャレンジを実行し、Let’s Encryptから証明書を取得して./letsencryptへ保存します。
  • アクティブなHTTP接続を切断することなく、即座にnginx -s reloadシグナルを発行して設定を反映します。

プロキシホスト作成のステップガイド

  1. メニューのHosts → Proxy Hostsを開き、Add Proxy Hostボタンをクリックします。
  2. Detailsタブ:
    • Domain Names: ドメイン名(例: api.itfromzero.com)を入力します。DNSのAレコードがVPSのIPアドレスを正しく指していることを事前に確認してください。
    • Scheme: 内部アプリ側でSSLが未有効の場合はhttpのままにします。
    • Forward Hostname / IP: サーバーのローカルIP、または同一ネットワーク内のDockerコンテナ名を入力します。
    • Forward Port: アプリケーションのポート番号(例: 3000)を指定します。
    • Websockets Supportをオンにします(Socket.io、NestJS、ライブリロードやチャット機能を持つNext.jsなどを利用する場合は必須です)。
    • Block Common Exploitsを有効化し、基本的なSQLインジェクションやディレクトリトラバーサルなどの悪意あるペイロードをフィルタリングします。
  3. SSLタブ:
    • SSL Certificate: Request a new SSL Certificateを選択します。
    • Force SSLをオンにし、HTTP(ポート80)への全アクセスをHTTPS(ポート443)へ強制リダイレクトします。
    • HTTP/2 SupportとHSTS Enabledを有効化して、ページの読み込み速度向上とプロトコルダウングレード攻撃への対策を施します。
    • I Agree to the Let’s Encrypt Terms of Serviceにチェックを入れ、Saveをクリックします。

3. 発展編:Access Listsと内部Docker Networkの活用

Access Listsによる管理画面のアクセス制限

Portainer、pgAdmin、社内バックアップツールなどのセンシティブなダッシュボードを誰でも閲覧可能な状態で公開するべきではありません。NPMのAccess Lists機能を用いれば、2段階のセキュリティレイヤーを実装できます:

  • HTTP Basic Authentication: アプリケーション本来のログイン画面に到達する前に、ブラウザのダイアログでユーザー名とパスワードの認証を要求します。
  • IP Whitelisting: 指定した固定IPレンジ(社内ネットワークのIP 14.241.x.x/32やWireGuard VPNのIPなど)からの接続のみを許可し、それ以外の外部アクセスには403 Forbiddenを返します。

Docker Networkを介したコンテナ間の直接接続

ports: ["8080:8080"]のようにポートをホスト外へ直接公開すると、自動スキャンボットの標的になりやすくなります。最も安全なアプローチは、NPMとバックエンドアプリを同一の内部ブリッジネットワークに所属させる構成です:

# 共通ブリッジネットワークを作成
docker network create proxy-net

このネットワークを利用するようにNginx Proxy Managerのdocker-compose.ymlを更新します:

services:
  app:
    image: 'jc21/nginx-proxy-manager:latest'
    restart: unless-stopped
    ports:
      - '80:80'
      - '81:81'
      - '443:443'
    volumes:
      - ./data:/data
      - ./letsencrypt:/etc/letsencrypt
    networks:
      - proxy-net

networks:
  proxy-net:
    external: true

docker compose up -dを実行して変更を適用します。これにより、proxy-netに参加しているWebアプリであれば、NPM管理画面のForward HostnameにIPアドレスではなくコンテナ名(例: strapi-cmsやgrafana)を直接指定して通信できるようになります。

4. Ubuntu環境での実践・運用ノウハウ

既存VPSにおけるポート80/443の競合解消

セットアップ時によく遭遇するエラーがDockerのbind: address already in useです。これはホスト上で他のプロセスがすでにポート80または443を占有していることを意味します。以下のコマンドで原因となっているプロセスを特定してください:

sudo ss -tulpn | grep -E ':(80|443)'

Ubuntuにプリインストールされたapache2やnginxがポートを占有している場合は、サービスを停止して自動起動を無効化します:

sudo systemctl stop nginx apache2
sudo systemctl disable nginx apache2

管理ポート81のインターネット公開を防ぐ

ポート81をグローバルに開放したままにしておくと、管理者アカウントへのブルートフォース攻撃を受けるリスクが高まります。以下の2つの対策が推奨されます:

  1. docker-compose.ymlでバインドIPを制限する: ポートマッピングを- '127.0.0.1:81:81'に変更します。設定画面を開く際は、ローカル端末からSSHトンネル(ssh -L 8181:localhost:81 user@IP_SERVER)を経由してhttp://localhost:8181へアクセスします。
  2. NPM自身へのProxy Hostを設定する: 内部用ドメイン(例: npm.internal.yourdomain.com)を127.0.0.1:81に向けてプロキシ設定し、Access Listでアクセス可能IPを制限します。

安全なバックアップ手順

プロキシ設定およびSSL証明書は、すべて./dataと./letsencryptの2つのディレクトリ内に保持されています。データベース書き込み中のコピーによるSQLiteファイルの破損を防ぐため、アーカイブ作成前にコンテナを一時停止(pause)することをおすすめします:

cd ~/npm
docker compose pause
tar -czvf npm-backup-$(date +%F).tar.gz data/ letsencrypt/
docker compose unpause

コンテナの一時停止にかかる時間はわずか2秒程度であるため、実質的なダウンタイムを発生させることなく、確実で整合性のあるバックアップデータを取得できます。

Share: