【VPSセキュリティ】Ubuntu+Docker環境を安全に公開する初期設定5選!SSH鍵認証・UFW・Dockerポート露出の罠
Difyやn8n、Pythonの定期実行スクリプトなどを24時間動かすために、国内VPS(Ubuntu環境)を契約してDockerコンテナを立ち上げたあと、「とりあえず動いたから、サーバーの初期設定はそのまま放置している」という状態になっていないでしょうか?
実は、グローバルIPアドレスを持つVPSをインターネット上に公開すると、立ち上げた瞬間から世界中のボット(自動巡回プログラム)によるSSHの総当たり攻撃(ブルートフォースアタック)や、開いているポートの脆弱性スキャンが24時間絶え間なく着弾し始めます。
さらに、Dockerを使ってDifyやn8nをセルフホストしている環境には、「Ubuntu標準のファイアウォール(UFW)でポートを閉じたはずなのに、Dockerコンテナのポート(DBの5432番や管理画面の5678番など)がUFWを貫通して全世界に丸見えになってしまう」という、初心者が見落としやすい極めて危険な仕様上の罠が存在します。
本記事では、自分の操作ミスでサーバーから締め出される事故を防ぎながら、Ubuntu + Docker環境のVPSを鉄壁に守る「5つの必須セキュリティ初期設定」と「Dockerポート露出の完全対策」をコピペで使えるコマンド付きで徹底解説します。
なぜVPS(Ubuntu+Docker)を初期状態のまま放置すると危険なのか?
まずは、契約直後のVPSで何が起きているのか、そしてDocker環境特有のセキュリティリスクを整理しておきましょう。
契約直後のVPSが抱える「3大セキュリティリスク」
| 放置リスク | 初期状態(デフォルト)の挙動 | 発生する被害・トラブル |
|---|---|---|
| ① rootパスワードへの総当たり攻撃 | 22番ポート で root ユーザーのパスワードログインが許可されている |
毎分何百回ものログイン試行を受け、突破されるとサーバーを乗っ取られる(仮想通貨マイニングの踏み台化など) |
| ② DockerのUFWバイパス(ポート露出) | ports: - "5432:5432" と書くと、UFWの設定を無視して外部へポートが開放される |
PostgreSQLやRedis、n8n等の内部ポートに直接外部から侵入・データ改ざんされる |
| ③ OS・パッケージの脆弱性放置 | 手動で apt upgrade しない限り古いパッケージのまま稼働し続ける |
既知のOS脆弱性(OpenSSH等のセキュリティホール)を突かれて侵入される |
実際にしばらく放置したVPSで sudo grep "Failed password" /var/log/auth.log | wc -l というコマンドを叩いてみると、数日間で数千〜数万件もの不正ログイン試行ログが記録されていることに驚くはずです。以下の5つの鉄則を順番に適用し、攻撃の入り口を完全に塞ぎましょう。
💡 Dify・n8nを動かすVPSの選び方やDocker初期構築手順はこちら:
・【2026年最新】開発・自動化におすすめのVPS 3選を徹底比較!コストとスペックで選ぶ最適解
・【脱・無料枠制限】Difyを格安VPSにセルフホスト構築する完全手順!DockerでAI基盤を自作しよう
・【脱Zapier】n8nを格安VPSにDocker構築する完全手順!タスク無制限のAPI自動化基盤を作る
【鉄則1】作業用一般ユーザーの作成と「rootログイン・パスワード認証」の完全無効化
攻撃者はまず「最高権限を持つ root というユーザー名」を狙い撃ちにしてパスワード総当たり攻撃を仕掛けてきます。そのため、①普段作業する一般ユーザー(sudo権限付き)を作成し、②SSH公開鍵認証を設定した上で、③rootログインとパスワード認証を両方とも無効化します。
STEP 1:作業用ユーザー(例:opsuser)を作成し、sudo・docker権限を付与する
まずは現在の root ユーザーでVPSへSSH接続し、以下のコマンドを実行します。
# 1. 新しい一般ユーザーを作成(パスワード入力が求められるので強固なものを設定)
adduser opsuser
# 2. 管理者権限(sudo)グループへ追加
usermod -aG sudo opsuser
# 3. すでにDockerを導入済みの場合は、sudoなしでdockerコマンドを叩けるようdockerグループにも追加
usermod -aG docker opsuser
STEP 2:手元のPC(Mac / Windows)でSSH鍵ペアを作成し、VPSへ公開鍵を登録する
手元のパソコンのターミナル(PowerShellまたはMacターミナル)を開き、まだSSH鍵を持っていない場合は次世代暗号方式の ed25519 で鍵を作成します。
# 【手元のPCで実行】ed25519方式でSSH鍵ペアを生成
ssh-keygen -t ed25519 -C "vps-opsuser-key"
# 生成された公開鍵(.pub)の中身を表示してコピーする
cat ~/.ssh/id_ed25519.pub
続いて、再びVPS側のターミナルに戻り、作成した一般ユーザー(opsuser)のディレクトリに公開鍵を貼り付けます。
# 【VPS側で実行】作成した一般ユーザーに切り替える
su - opsuser
# .sshディレクトリを作成して権限を700(所有者のみアクセス可)に設定
mkdir -p ~/.ssh
chmod 700 ~/.ssh
# authorized_keysファイルに先ほどコピーした公開鍵(ssh-ed25519 AAAA...)を貼り付ける
nano ~/.ssh/authorized_keys
# ファイルの権限を600に設定(権限が緩いとSSH認証が弾かれるため必須)
chmod 600 ~/.ssh/authorized_keys
STEP 3:SSH設定(sshd_config)でrootログインとパスワード認証を禁止する
⚠️ 【超重要】サーバーから締め出されないための安全ルール:
以下の設定を変更する際は、現在開いているSSHターミナルを絶対に閉じないでください。設定変更後、必ず「もう1つ別のターミナル画面」を新しく立ち上げて、新ユーザー(opsuser)+公開鍵でログインできることを確認してから元の画面を閉じるようにしてください。
Ubuntu 22.04 / 24.04以降では、/etc/ssh/sshd_config 本体だけでなく /etc/ssh/sshd_config.d/ 配下にクラウド事業者の初期設定ファイル(例:50-cloud-init.conf)が存在し、設定を上書きしてしまうことがあります。そのため、優先度の高いカスタム設定ファイル(00-hardening.conf)を作成して制御するのが最も確実です。
# SSHのセキュリティ強化設定ファイルを新規作成
sudo nano /etc/ssh/sshd_config.d/00-hardening.conf
開いたエディタに以下の4行を貼り付けて保存(Ctrl + O ➔ Enter ➔ Ctrl + X)します。
# rootユーザーでの直接SSHログインを完全禁止
PermitRootLogin no
# パスワードによるログインを完全禁止(SSH公開鍵認証のみ許可)
PasswordAuthentication no
KbdInteractiveAuthentication no
PubkeyAuthentication yes
設定ファイルに文法ミスがないかテストしてから、SSHサービスを再起動します。
# 文法チェック(何もエラーが出なければOK)
sudo sshd -t
# SSHサービスを再起動(Ubuntuではサービス名は ssh です)
sudo systemctl restart ssh
この状態で別ウィンドウのターミナルから ssh opsuser@あなたのVPSのIPアドレス でログインでき、かつ ssh root@あなたのVPSのIPアドレス が Permission denied (publickey) で弾かれれば、パスワード総当たり攻撃に対する防御は100%完了です!
【鉄則2】SSHポート番号の変更と「Fail2ban」による不正アクセス自動遮断
公開鍵認証にした時点で突破されるリスクはほぼゼロになりますが、デフォルトの 22番ポート を開けていると、ボットからの無駄なアクセス試行でログが汚れ、CPUやネットワーク帯域も微妙に消費され続けます。
1. Fail2banを導入して、連続失敗する攻撃元IPを自動でBANする
Fail2ban(フェイル・トゥ・バン)は、SSHなどの認証ログを常時監視し、短時間に規定回数(例:5回)ログインに失敗した攻撃元のIPアドレスをファイアウォールレベルで自動遮断してくれる必須ツールです。
# Fail2banのインストール
sudo apt update && sudo apt install -y fail2ban
# ローカル設定ファイル(jail.local)を作成
sudo nano /etc/fail2ban/jail.local
以下の設定を貼り付けて保存します(10分間に5回失敗したIPを、24時間遮断する設定です)。
[DEFAULT]
bantime = 24h
findtime = 10m
maxretry = 5
backend = systemd
[sshd]
enabled = true
port = ssh
# Fail2banを有効化して起動
sudo systemctl enable --now fail2ban
# 稼働状況と現在BANされているIP数を確認するコマンド
sudo fail2ban-client status sshd
これだけで、執拗にアタックしてくるボットのIPアドレスが片っ端から自動的にブラックリストへ放り込まれるようになります。
【鉄則3・最重要】UFWの設定と「Dockerがファイアウォールを貫通する罠」の完全対策
ここがUbuntu + Docker環境における最重要セクションです。多くの入門記事では「UFW(Uncomplicated Firewall)で22番・80番・443番だけ許可すれば安全」と解説されていますが、Dockerを使っている場合、UFWの設定だけではコンテナのポートは一切守られません。
まずは基本のUFW(SSH・HTTP・HTTPSのみ許可)を設定する
最初に、ホストOS自体の通信を制御するUFWの基本設定を入れておきます(⚠️必ず 22/tcp を allow してから enable を実行してください)。
# 1. デフォルトルール:外部からの着信をすべて遮断し、内部からの発信は許可
sudo ufw default deny incoming
sudo ufw default allow outgoing
# 2. SSH(22番)とWeb公開用(80番・443番)のみ許可
sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# 3. UFWを有効化(y を入力してEnter)
sudo ufw enable
# 4. 現在のルールを確認
sudo ufw status numbered
【恐怖の罠】なぜUFWで閉じたはずのDockerポートが全世界に露出するのか?
UFWを有効化した状態で、たとえばn8nやPostgreSQLの docker-compose.yml に以下のように記述して起動したとします。
# ❌ 危険な記述例(全インターフェース 0.0.0.0 にバインドされる)
services:
n8n:
image: n8nio/n8n:latest
ports:
- "5678:5678"
postgres:
image: postgres:15
ports:
- "5432:5432"
このとき、あなたは「UFWで 5678 も 5432 も許可していないから、外部からはアクセスできないはずだ」と思うかもしれません。しかし実際には、Dockerエンジンは起動時にLinuxカーネルの iptables(PREROUTING / DOCKERチェーン)を直接書き換え、UFWのフィルタリングルールよりも手前でパケットを通過させてしまいます。
その結果、ブラウザや外部のポートスキャナから http://VPSのIPアドレス:5678 や 5432 を叩くと、UFWを完全に素通りして世界中から直接コンテナへ接続できてしまうのです。
解決手順A(最も確実):docker-compose.ymlで「127.0.0.1(ローカルホスト)」にバインドする
このDockerポート貫通問題を最もシンプルかつ確実に防ぐ方法は、docker-compose.yml の ports 指定の先頭に 127.0.0.1: を付けることです。
# ⭕ 安全な記述例(VPS内部からのアクセスのみ許可し、外部からの直接通信を完全遮断)
services:
n8n:
image: n8nio/n8n:latest
ports:
- "127.0.0.1:5678:5678"
postgres:
image: postgres:15
# そもそもDBはDocker内部ネットワークで通信できれば良いため、ports自体を削除するか127.0.0.1に限定する
ports:
- "127.0.0.1:5432:5432"
127.0.0.1:5678:5678と書くメリット: コンテナのポートが「VPS自身の内部ループバックアドレス(localhost)」にしか開かれなくなります。これにより、外部からIPアドレス:5678を直接叩かれても100%拒否され、同じVPS上のNginxリバースプロキシやCloudflare Tunnel(443番 HTTPS)を経由した正規の通信だけを通すことができます。- 設定変更後の確認コマンド: コンテナ再起動後に以下のコマンドを実行し、Local Address列が
0.0.0.0:5678ではなく127.0.0.1:5678になっていれば安全です。
# 外部公開されているポート(LISTEN状態)を一覧確認する
sudo ss -tulpn
解決手順B(Dify等の大規模構成向け):ufw-docker を導入してUFWルールを強制適用する
Difyのように多数のコンテナが絡み合う公式の docker-compose.yaml を直接書き換えたくない場合(アップデート時の競合を避けたい場合)は、オープンソースの定番スクリプト ufw-docker を導入することで、Dockerが勝手にUFWをバイパスする挙動を根本から修正できます。
# 1. ufw-docker スクリプトをダウンロードして実行権限を付与
sudo wget -O /usr/local/bin/ufw-docker https://github.com/chaifeng/ufw-docker/raw/master/ufw-docker
sudo chmod +x /usr/local/bin/ufw-docker
# 2. UFWの設定ファイル(/etc/ufw/after.rules)にDocker制御ルールを自動追記
sudo ufw-docker install
# 3. UFWを再起動して反映
sudo systemctl restart ufw
これを導入すると、Dockerの ports で公開したポートであってもデフォルトですべて外部遮断されるようになり、sudo ufw route allow proto tcp from any to any port 80 のように明示的に許可したポート(DifyのNginx 80/443番など)だけを安全に外部公開できるようになります。
💡 Dify・n8nの安全なアップデート手順や502エラー復旧ガイドはこちら:
・【VPS運用】Dify・n8nのDocker環境を自動バックアップ&安全にアップデートする完全手順
・【Dify】アップデート後に「502 Bad Gateway」で画面が開かない原因と5分での復旧手順
【鉄則4・5】OSセキュリティパッチの自動適用とCloudflareによるIP隠蔽
最後に、24時間365日稼働させる自動化サーバーの「メンテナンス負荷」と「外部公開リスク」をさらに引き下げる2つの設定を仕上げます。
【鉄則4】unattended-upgrades でOSの緊急セキュリティ更新を完全自動化する
毎日VPSにログインして sudo apt update && sudo apt upgrade を手動実行するのは現実的ではありません。Ubuntu標準の unattended-upgrades(無人自動アップグレード)を有効化し、重大なセキュリティパッチが公開されたらバックグラウンドで自動適用されるように設定します。
# パッケージのインストールと有効化ウィザードの起動
sudo apt update && sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
確認画面が出たら 「Yes」 を選択してEnterを押すだけで、/etc/apt/apt.conf.d/20auto-upgrades が生成され、毎日のセキュリティパッチ自動適用が有効になります。
【鉄則5】自分専用の管理画面(Dify・n8n)はCloudflare Zero Trustで保護する
Difyのスタジオ画面やn8nのワークフロー編集画面は、そもそも読者に公開するものではなく、「サイト運営者であるあなた(+Webhookの送信元)」だけがアクセスできれば良い管理画面です。
- 独自ドメイン + Cloudflareプロキシ(オレンジ雲)の活用: VPSの生IPアドレスを直接DNSに出すのではなく、CloudflareのDNSプロキシ(またはCloudflare Tunnel)を経由させることで、VPS本体のグローバルIPアドレスを外部から隠蔽し、DDoS攻撃をCloudflareのエッジ側で吸収できます。
- Cloudflare Access(Zero Trust・無料枠50ユーザーまで)の併用: Difyやn8nのURLに対してCloudflare Accessで「自分のGoogleアカウント(メールアドレス)でワンタイムPIN認証を通過した場合のみ画面を表示する」というゲートを被せておけば、万が一アプリのパスワードが漏洩したりゼロデイ脆弱性が出たりしても、第三者はログイン画面にすら到達できなくなります(Webhook用のパスだけBypass設定にすれば自動化も止まりません)。
💡 VPS上のDify・n8nを活用した24時間自動化ワークフローの実践例はこちら:
・【Dify×n8n連携】AIワークフローを24時間完全自動化する構築手順!Webhook・API接続の実践ガイド
・【完全自動化】n8n × X(Twitter)APIで記事公開を自動ポスト!microCMS Webhook連携の実践手順
まとめ:堅牢なVPSセキュリティ基盤の上でDifyやn8nの24時間自動化を回そう
本記事では、Ubuntu + Docker環境のVPSを安全に24時間運用するための必須セキュリティ初期設定5選を解説しました。
- rootログインとパスワード認証の完全禁止: 作業用一般ユーザーを作成し、
ed25519公開鍵認証のみに限定することで総当たり攻撃を無効化する。 - Fail2banによる自動BAN: 不正アクセスを試みるボットIPを
systemdログ監視で自動遮断する。 - UFW設定 + Dockerポート露出の防止(最重要):
docker-compose.ymlのポート指定を127.0.0.1:ポート:ポートに限定するかufw-dockerを導入し、UFWバイパスによる内部ポート流出を防ぐ。 - unattended-upgradesの有効化: OSの重要なセキュリティパッチを毎日自動で適用する。
- Cloudflareによる保護: プロキシやZero Trustを活用し、管理画面への不正侵入をエッジ側でブロックする。
ここまでの設定を一度済ませておけば、深夜にサーバー乗っ取りや不正アクセスの心配をすることなく、安心してDifyやn8n、Pythonスクリプトに24時間の自動化業務を任せることができます。これから新しく自動化用のVPSを立ち上げる方や、スペック不足でサーバーの乗り換えを検討している方は、以下の国内VPS比較ガイドもあわせて参考にしてください!