← Blog 一覧

個人開発でも「管理画面」はつくる — 公開サイトと分けて Cloudflare Access で守る

サービスを 1 つ作ると、ほぼ必ず「裏側」が要ります。コンテンツを投入する、届いた問い合わせや注文を確認する、 データの状態をチェックする、ちょっとした運用作業をする——こういう作業を毎回 SSH で入って DB を直に叩いて、 では事故が起きるし続きません。なので僕はサービスを作るとき、運用に必要なら「管理者用の画面」も一緒に作る ことにしています。表(公開サイト)と裏(管理画面)はワンセット、という感覚です。

ただ、管理画面は「自分だけが触れればいい」かわりに、漏れたときの被害が公開サイトの比ではありません。 この記事では、個人開発で管理画面をどう用意して、どう守っているかを整理します。結論を先に言うと、 「公開サイトと完全に分ける」+「認証は Cloudflare Access に前出しする」の 2 つが軸です。

1. 公開サイトと管理画面は完全に分ける

まず大原則として、管理画面は公開サイトとURL も認証体系も別物にします。具体的にはこうしています。

  • 別サブドメインに置く。さらに、推測されにくいランダムな文字列を含めて、URL 自体を簡単には言い当てられないようにする。
  • 公開サイトから管理画面へのリンク・リダイレクト・参照を一切置かない。導線がなければ、存在に気づかれる確率がそもそも下がる。
  • robots.txt で管理画面・管理 API・認証ページをインデックス対象から除外する。検索結果に裏口が出てこないようにする。
  • 公開側のサーバーは、/api/admin/ のような管理用パスへのリクエストを404 で突き返す。表からは「無いことになっている」状態にする。

URL の秘匿はあくまで「最初のひと枚」で、これ単体をセキュリティとは呼びません。けれど、 分離されていれば後段の対策が効きやすくなる(公開トラフィックと混ざらないので、IP 制限や認証を強めに掛けても誰も困らない)という意味で効きます。

2. 認証は Cloudflare Access に「前出し」する

個人開発でいちばん効いているのがこれです。管理画面の認証を、アプリの中に全部書くのではなく、 Cloudflare Access(Zero Trust)をサイトの前段に置いて、そこで先に弾く構成にしています。

Cloudflare Access は、保護したいドメイン/パスに「ポリシー」を貼る仕組みです。アクセスしてきた人は、 アプリに届く前に Cloudflare のエッジで認証を求められます。許可リストに載ったメールアドレスへのワンタイム PIN、 あるいは Google などの ID プロバイダ(IdP)でのログイン——通った人だけが、署名付きのトークン (Cf-Access-Jwt-Assertion ヘッダ)を持った状態でアプリに到達します。通らなければアプリのコードは 1 行も実行されません。

これの何が嬉しいかというと、「ログイン機能を自前でフルスクラッチしなくていい」こと。 パスワードのハッシュ保存も、セッション管理も、総当たり対策も、まず Cloudflare 側の関所が肩代わりしてくれます。 個人開発では、この「認証を自分で全部書かない」が地味にいちばん事故を減らします。アプリ側は、必要なら 受け取った JWT を検証して二重に確認する、くらいで済みます。

3. 守りは「重ねる」— 単発で頼らない

ひとつの対策に全部を背負わせないのがコツです。実際には次を重ねています。

  • 推測困難なサブドメイン(URL を当てにくくする)
  • Cloudflare Access によるゼロトラスト認証(アプリ前段の関所)
  • IP 制限(自宅・作業環境など、入口をさらに絞る)
  • アプリ側のログイン+ TOTP(2 段階認証)(関所を抜けた後の本人確認)
  • ログイン試行の記録(成功・失敗とも残して、後から異常を追える)

どれか 1 枚が破られても、次の 1 枚で止まる。これが「多層防御」で、難しいことはしていません。 個人開発でも、関所を 2〜3 枚重ねるだけで、現実的な攻撃のほとんどは入口で力尽きます。

4. 中身(実装)は素直に作る

守りを Cloudflare Access に寄せると、アプリ本体は業務ロジックに集中できます。 管理画面そのものは、一覧・詳細・作成・更新・削除(CRUD)が回ればいいので、その手のことが速いフレームワーク (僕は PHP のフレームワークや、軽い管理ダッシュボードを使うことが多い)でサッと組みます。凝った UI は要りません。 運用で毎日見る数字と、ポチッと押すボタンがあれば十分です。

公開側と管理側でデータベースを分けるか、同じ DB を共有して管理 API だけ裏から触れるようにするかは、 サービスの規模で決めます。小さいうちは同居でよく、「管理 API は公開サイトの経路からは絶対に叩けない」 という一点だけ守れば破綻しません。

まとめ

表に 1 枚ページを足すたび、裏の運用画面も小さく用意しておく。守りは 「公開サイトと完全に分ける」+「認証は Cloudflare Access に前出しする」を土台にして、 IP 制限と 2FA を重ねる。こうしておくと、アプリのコードは業務ロジックだけに専念できて、 個人開発でも「裏側がいちばん怖い」状態を避けられます。実は、このサイトの問い合わせも、 最終的にはこの方式で守った管理ツールに集約して見ています。