なぜ公開が一つの章になるか
ここまでの章は、すべて自宅のLAN内で安全に練習できた。ファイル共有も、メモ同期も、第7章のデータベースも、第8章で建てた自作アプリも、家の中だけで動かしているうちは、接続してくる相手はあなた一人だ。失敗しても、誰にも見られていない。だから気楽に壊して、作り直せた。
公開は、その安全圏から一歩外に出る決断だ。そして、公開は不可逆に近い。 一度サーバーをインターネットに晒すと、第1章で書いたとおり、接続してくる相手は全世界になる。世界中の自動化された探査プログラムが、公開直後から24時間休みなくあなたのサーバーを叩き始める。これは脅し文句ではなく、公開した日のログに必ず現れる観測事実だ。攻撃面が一気に変わる。だから公開は、第5章で築いた守り(ファイアウォール、SSHの鍵認証、fail2ban)がすべて前提になる。
ここで最初に、はっきり言っておきたい。「公開しない」も立派な選択だ。 あなたが自分のサーバーに外から入りたいだけなら、世界に向けて入口を開ける必要はない。Tailscale のような仕組みを使えば、「自分(と許可した人)だけが、外から自宅のLANに安全に入る」ことができる。これは公開ではなく、いわば自分専用の延長ケーブルだ。攻撃面はほとんど増えない。家族の写真サーバーや自分のメモ同期なら、これで十分なことが多い。
それでもなお「世界に向けて何かを公開したい」——自分のブログ、誰かと共有したいサービス、外部から使ってもらうアプリ——という場面はある。この章は、そのときに必要な部品と、自宅回線特有の難所を、正直に整理する。
第一節 公開の三点セット
何かを「インターネットで誰でも見られる」状態にするには、最低限三つの部品が要る。それぞれが何者なのかを、一段落ずつで掴んでおく。
ドメイン。 example.com のような、人間が覚えられる名前だ。サーバーには数字のIPアドレスしかないが、それを覚えるのは現実的でない。ドメインは、その数字に付ける「看板」だ。レジストラ(ドメイン登録業者)で取得し、費用は .com などで年に千円前後。これがあなたのサーバーの住所表記になる。
DNS。 ドメインという名前を、実際のIPアドレスに変換する電話帳の仕組みだ。あなたは取得したドメインの管理画面で、「この名前は、このIPアドレスを指す」という対応を登録する。IPv4ならAレコード、IPv6ならAAAAレコードと呼ぶ。これを設定して初めて、世界中の人が名前であなたのサーバーにたどり着ける。
TLS証明書。 通信を暗号化し、https:// の鍵マークを成立させるものだ。これがないと、通信が平文で流れ、パスワードなどが盗み見られる。かつては有料で手間もかかったが、今は Let's Encrypt という仕組みで無料・自動で取れる。後述のリバースプロキシが、これをほぼ全自動で面倒みてくれる。
この三つが揃って初めて、https://あなたのドメイン が世界から見える状態になる。
Claudeに聞いてみよう①:自分の回線に合った公開経路を設計させる
私はDebian 13で自宅サーバーを運用していて、〔公開したいもの。例:自分のブログ / 友人と共有する写真アルバム / 外部から使う自作アプリ〕を公開したいです。回線の状況は次のとおりです: 〔契約しているプロバイダ名、回線種別(光/モバイル等)、グローバルIPがあるか、IPv6が使えるか、分かる範囲で〕
この回線でその公開を実現する経路を、いくつか案として設計してください。それぞれの案について、必要な部品、費用の目安、攻撃面がどれだけ増えるか、私の状況での向き不向きを添えてください。
公開経路は、回線の素性によって取れる手が変わる。後述するCGNATの問題は、自分で気づきにくい。まず自分の回線をClaudeに伝えて、現実的な選択肢を絞り込むのが出発点だ。
第二節 リバースプロキシという型
公開するサービスが一つでも、複数でも、現代的な公開にはリバースプロキシという型を使う。
リバースプロキシとは、一台の入口(443番ポート、つまり https://)が、後ろにある複数のサービスへ、ホスト名で振り分ける仕組みだ。blog.example.com への接続はブログのサービスへ、photos.example.com への接続は写真サーバーへ、と一台が交通整理する。外から見える入口は一つだけで、TLSの面倒もこの入口がまとめて見る。第6章の作法で複数のサービスを動かしているなら、その出口をこのリバースプロキシ一つに集約できる。
この章では Caddy を例にする。理由は、設定ファイル(Caddyfile)が数行で済み、しかもTLS証明書の取得・更新まで全自動だからだ。Let's Encrypt とのやり取りを、Caddyが裏で勝手にやってくれる。設定テキストが短いということは、Claudeと相性が良いということでもある。
# /etc/caddy/Caddyfile
# 2つのサービスをホスト名で振り分ける例
blog.example.com {
reverse_proxy localhost:8080
}
photos.example.com {
reverse_proxy localhost:8081
}
これだけだ。blog.example.com に来た https:// の通信を、手元の 8080 番で動いているブログ(第6章のサービスや、第8章で建てたFastAPIアプリなど)に渡す。photos.example.com は 8081 番へ。TLS証明書は、Caddyが起動時に Let's Encrypt から自動で取得し、期限が来れば自動で更新する。証明書の存在を意識しなくていい。
# Caddyを入れて、設定を反映する
sudo apt install caddy
sudo nano /etc/caddy/Caddyfile # 上の内容を書く
sudo systemctl reload caddy # 設定を読み直す
systemctl status caddy # 動いているか確認
なお、同じことは nginx でもできる。nginxは情報量が多く、細かい制御もきくが、TLSの自動化は certbot という別ツールを組み合わせる必要があり、設定テキストはCaddyより長くなる。「短いテキストで自動TLSまで終わる」という一点でCaddyを推すが、すでにnginxに慣れているなら無理に乗り換える必要はない。
Claudeに聞いてみよう②:Caddyfile を書かせて各行を説明させる
私はDebian 13のサーバーで、次のサービスを公開したいです: 〔例:blog.example.com → localhost:8080 のブログ、photos.example.com → localhost:8081 の写真サーバー、など。自分のドメインとサービスを列挙〕
これを実現する Caddyfile を書いてください。そのうえで、各行が何をしているのかを一行ずつ解説してください。TLS証明書がどう扱われるかも説明してください。
ここでも、第6章の unit file と同じ作法を使う。書かせるだけでなく、各行の意味を説明させる。 リバースプロキシは「外から内への入口」そのものなので、意味の分からない行を残したまま動かすのは危険だ。一行ずつ解説させて、自分の入口を自分で読めるようにしておく。
第三節 自宅からの公開という難所
公開の三点セットを揃えても、自宅サーバーには独特の壁がある。家のネットワークは、もともと「外から入られない」ように作られているからだ。
第一の壁がポート開放だ。自宅のルーターは、外から来る接続を初期状態ですべて遮断している。サーバーを公開するには、ルーターの設定で「443番ポートに来た接続は、このサーバーへ通す」という穴を開ける(ポートフォワーディング)必要がある。これは家の玄関に鍵穴を一つ増やすようなものだ。開けた瞬間、世界中の探査がその穴を叩き始める。 だから第5章の守りが前提になる。
第二の、そしてより厄介な壁が CGNAT だ。近年の多くの回線(特にモバイル回線や一部の光回線)では、契約者に固有のグローバルIPアドレスが割り当てられていない。複数の契約者が一つのグローバルIPを共有する CGNAT(キャリアグレードNAT) という方式が使われている。この場合、そもそも外から指せる住所が自分にないので、従来型のポート開放は不可能だ。 自分の回線がこれに該当するかどうかは、第一節①でClaudeに確認するのが早い。
CGNATの壁を越える、現代的な迂回路がいくつかある。いずれも一長一短だ。
- Cloudflare Tunnel:自宅から外向きにトンネルを張り、Cloudflare経由で公開する。ポート開放もグローバルIPも不要。手軽だが、通信がCloudflareを通る(依存先が一つ増える)。
- Tailscale Funnel:第1章でも触れたTailscaleの公開機能。同じくポート開放不要で、設定が素直。小規模な公開向き。
- 安いVPSを入口にする:ネット上に小さなVPSを一台借りて公開の入口にし、そこから自宅サーバーへトンネルでつなぐ。自由度は高いが、VPSという管理対象が一つ増える。
ここで正直に書いておく。これらの迂回路は、どれも「自分の手の外にある誰か」に依存先を一つ増やすことを意味する。これは本書が一貫して掲げてきた「依存先を減らし、自分の手で直せる範囲を広げる」という思想と、緊張関係にある。便利さと自立は、ここで一度ぶつかる。
その緊張を踏まえたうえで、本書の前提(自宅サーバーかVPSで、データも自分で管理)に沿った整理を示す。本体がVPSにあるなら、この難所はそもそも存在しない。 VPSにはグローバルIPがあるので、第二節のCaddyをそのまま外に向けて開けばいい。本体が自宅にあるなら、本体は動かさず「入口」だけを借りる。 Cloudflare TunnelやTailscale Funnelはまさにこの形だし、安いVPSを入口(トンネルの出口)にして、データベースもファイルも自宅側に残す手もある。どちらの構えでも、データは自分がrootを持つ機械の上にあり、主導権は手放さない。
静的サイトなら、Cloudflareで無料で公開できる
もう一つ、覚えておくと構えが軽くなる事実がある。中身が動かないサイト——HTMLとCSSだけのブログや紹介ページ——なら、そもそも自分のサーバーから公開する必要がない。 Cloudflare Pages のような静的ホスティングに置けば、無料で、独自ドメインとTLS込みで、世界中に配信される。ポート開放もトンネルも、この章の難所のほとんどが要らない。
しかも、線引きは「完全に静的」よりもう少し先まで延ばせる。お問い合わせフォーム程度の軽い動的処理なら、Cloudflare側のJavaScript実行環境(Pages Functions / Workers)の無料枠で済んでしまう。 フォームの送信を受け取って、メールに転送したり小さなストレージに記録したりする数十行のJavaScriptは、まさにClaudeが得意とする規模だ。「フォームの内容をメールで受け取るPages Functionを書いて」と頼めばいい。
だから役割を分ければいい。読まれるだけのページと、お問い合わせ程度の軽い処理まではCloudflareへ。自分のデータベースを持つ本体——第7章のデータベースを読み書きする、第8章のような自作アプリ——は自分のサーバーへ。 自分のサーバーから公開する価値があるのは、後者だけだ。静的サイトの作り方そのものは本書の範囲外だが、手元のMarkdownやHTMLをClaudeに渡して「Cloudflare Pagesで公開する手順を教えて」と聞けば、その日のうちに公開できるはずだ。
Claudeに聞いてみよう③:自分の回線でCGNATか確認し、経路を決める
私の自宅回線の状況は次のとおりです: 〔プロバイダ名、回線種別。ルーターの管理画面で見えるWAN側IPアドレス(例:100.x.x.x や 10.x.x.x なら共有IPの可能性)、IPv6の有無〕
この回線が CGNAT(グローバルIPを共有する方式)かどうかを、判断する方法と一緒に教えてください。そのうえで、第二節で挙げた迂回路(Cloudflare Tunnel / Tailscale Funnel / VPS入口)のうち、私の状況に向くものを理由を添えて勧めてください。
CGNATかどうかは、ルーターのWAN側IPと、外部から見た自分のIPが一致するかで判断できる。判断の手順ごとClaudeに聞けば、自分の回線で何が可能かが一度ではっきりする。
第四節 公開した日にやること
設定を終えて公開した「その日」に、必ずやるべきことがある。守りの確認と、外からの観察だ。
まず、第5章で築いた守りを、公開状態でもう一度見直す。
# ファイアウォールが意図したポートだけ開けているか
sudo ufw status verbose
# SSHへのログイン試行を観察する(公開後は急増する)
sudo journalctl -u ssh --since "1 hour ago"
# fail2ban が攻撃元を弾いているか
sudo fail2ban-client status sshd
次に、外から実際に見えているかを確認する。サーバー自身からではなく、できれば回線の外(スマホのモバイル回線など)から打つのがいい。
# 外から、自分のサイトのヘッダだけ取って疎通とTLSを確認する
curl -I https://あなたのドメイン
HTTP/2 200 のような応答と、証明書のエラーが出ないことを確認できれば、公開は成立している。
そして、公開直後ならではの体験がある。何もしていないのに、ログには見知らぬアクセスが流れ始める。 存在しないURL(/wp-login.php や /.env など)への執拗なアクセス、ありふれたユーザー名でのSSHログイン試行——これらはすべて、世界中の自動化された探査プログラムが、公開されたばかりのサーバーを機械的に叩いている痕跡だ。
このログを、ぜひそのままClaudeに読ませてほしい。「これは何を狙った偵察なのか」を解説させると、攻撃の世界の地図が一気に具体的になる。「世界に晒す」とはこういうことか、という実感が、教科書の文字ではなく自分のログとして手に入る。第5章の脅威モデルが、ここで初めて目の前の現実になる。
Claudeに聞いてみよう④:公開後のアクセスログの不審な行を読ませる
自宅サーバーを公開しました。公開直後のアクセスログ(またはSSHのログ)に、次のような行が流れています:
〔Caddyのアクセスログや journalctl -u ssh の出力から、不審な行をそのまま貼る〕これらはそれぞれ、何を狙った偵察や攻撃ですか。私のサーバーで対策できていること・まだ穴がありそうなことを、第5章で設定したファイアウォール・鍵認証・fail2ban を前提に教えてください。
第3章で身につけた「ログをテキストのまま貼る」作法が、公開という最も緊張する場面でそのまま効く。不審な行の意味が分かれば、過剰に怯える必要も、油断する必要もなくなる。何が来ていて、何を防げているのかを、自分の言葉で説明できるようになる。
まとめ
この章でやったこと:
- 公開が不可逆に近い決断であること、「公開しない(Tailscale等)」も立派な選択であることを確認した
- 公開の三点セット(ドメイン・DNS・TLS証明書)が何者かを押さえた
- リバースプロキシという型を理解し、Caddyfile で複数サービスを振り分ける例を書いた
- 自宅公開の難所(ポート開放・CGNAT)と迂回路の一長一短を整理し、静的サイトならCloudflareで無料公開できる——自分のサーバーから公開するのはデータを持つ動的なものだけ——と役割を分けた
- 公開した日にやること(守りの再確認・外からの疎通確認・bot観察)をClaudeと一緒にやった
手元に残ったもの:
- 自分の回線に合った公開経路の設計(または「公開せずTailscaleで入る」という結論)
- 動いた Caddyfile(または公開しない判断のメモ)
- 公開直後のログを読んだ経験——「世界に晒す」の実感
次の第10章では、ここまで動かしてきたサービスとデータを、いよいよ守ることを考える。第7章でデータをデータベースという一箇所に集めた意味が、ここで効いてくる。何を、どこへ、どのくらいの頻度でバックアップし、どうやって「本当に戻せるか」を確かめるのか——壊れる前提で備える作法を、Claudeと一緒に組み立てる。
シリーズ全体はClaudeと一緒に学ぶDebian サーバー編 一覧から辿れる。本編(デスクトップ編)は全章一覧へ。コメント・議論は Facebook グループへ:AISeed — 生物多様性・食料・AIと暮らし