クラウドサービスvsセルフホスト:本当の違いとは?
多くの開発者は最初、同じようなデフォルトのスタックに落ち着く。パスワード管理にLastPass、コードにGitHub、死活監視にPingdom。問題が起きるまでは、これで十分うまく機能する。2022年にLastPassは暗号化済みのVaultが流出する大規模な侵害を受けた。Pingdomはマルチロケーションモニタリングの価格を月額約15ドルから89ドルへと一気に引き上げた。GitHubの組織向け無料プランのルールも一度ならず変更されている。
そこで初めて、セルフホスティングが趣味プロジェクトではなく合理的な選択肢に見えてくる。不信感の話ではない。他人の値上げやセキュリティの実績に依存しないためだ。
自前でサービスを動かすアプローチはいくつかある:
- ベアメタルインストール — OSに直接サービスをインストールする。最初はシンプルだが、アップデートや移行がすぐに頭痛の種になる。
- Docker(単体コンテナ) — 各サービスを独立して実行する。出発点としては悪くないが、5つの別々の
docker runコマンドを管理するのはすぐに煩雑になる。 - Docker Compose — スタック全体を1つのYAMLファイルで定義する。混乱なくコントロールしたいホームラボ愛好者の定番。
- Kubernetes — 本番グレードのオーケストレーションを学ぶには最高。個人の3サービス構成には明らかにオーバースペック。
Docker Composeはここでちょうどいいバランスを保っている。午後一つで理解できるほど明快で、小チームが実際にステージング環境を管理する方法とも一致している。
自前スタックを運用するメリットとデメリット
セルフホスティングが合理的な理由
- 完全なデータ所有権 — パスワード、リポジトリ、監視メトリクスはサードパーティのサーバーではなく、あなたのハードウェア上に存在する。
- ベンダーロックインなし — 移行、バックアップ、シャットダウンをすべて自分の判断で行える。
- 実質的なコスト削減 — 月額5〜10ドルのVPSで、合計30〜50ドルにもなるサブスクリプションを置き換えられる。LastPass Premiumだけでも年間36ドル、GitHub Teamは1ユーザーあたり月額4ドルだ。
- 実践的な学習 — 実際のサービスを稼働させ続けることで、どんなチュートリアルよりもLinux、ネットワーク、コンテナについて深く学べる。
覚悟しておくべきこと
- 稼働率はあなたの責任 — サーバーが落ちればパスワードマネージャーも落ちる。それを前提に計画を立てること。
- セキュリティはあなたの責任 — アップデート、ファイアウォールルール、バックアップは自動では行われない。
- 初期構築の時間 — 最初にすべてきれいに動かすまでに2〜3時間を見ておくこと。
ホームラボを運用することで、私の本番デバッグへのアプローチは大きく変わった。最初のスタックを安定稼働させてから6ヶ月後、職場でもずっと早く障害パターンを見抜けるようになった。午前2時に自分のサービスのアラートで起こされる経験は、ドキュメントでは絶対に得られない直感を研ぎ澄ませてくれる。
推奨構成
今回構築するスタックはこちら:
- Vaultwarden — 非公式のRust製Bitwarden互換サーバー。アイドル時のRAM使用量は約10MBで、公式Bitwardenスタックの2GB以上と比較して非常に軽量。すべてのBitwardenクライアントと完全互換。
- Gitea — セルフホスト型Gitサービス。月額5ドルのVPSでも余裕を持って動作するほど軽量。
- Uptime Kuma — 洗練されたUIを持つシンプルな死活監視ツール。スケジュールに従ってサービスをチェックし、何か問題があると即アラートを発する。
サーバー要件:Ubuntu 22.04またはDebian 12、最低1〜2GB RAM、DockerとDocker Composeがインストール済みであること。ドメイン名はオプションだが、Vaultwardenには強く推奨する。ブラウザはHTTPでパスワードマネージャーへのアクセスを積極的にブロックするため、日常使用においてHTTPSは必須だ。
実装ガイド
ステップ1:Dockerをインストールする
# 公式スクリプトを使ってDockerをインストール
curl -fsSL https://get.docker.com | sh
# インストールを確認
docker --version
docker compose version
ステップ2:プロジェクト構造を作成する
mkdir ~/homelab && cd ~/homelab
mkdir -p vaultwarden gitea uptime-kuma
touch docker-compose.yml
ステップ3:Docker Composeファイルを作成する
version: "3.8"
services:
vaultwarden:
image: vaultwarden/server:latest
container_name: vaultwarden
restart: unless-stopped
volumes:
- ./vaultwarden:/data
environment:
- SIGNUPS_ALLOWED=true # アカウント作成後はfalseに変更
- WEBSOCKET_ENABLED=true
ports:
- "8080:80"
- "3012:3012"
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__database__DB_TYPE=sqlite3
volumes:
- ./gitea:/data
ports:
- "3000:3000"
- "2222:22"
uptime-kuma:
image: louislam/uptime-kuma:1
container_name: uptime-kuma
restart: unless-stopped
volumes:
- ./uptime-kuma:/app/data
ports:
- "3001:3001"
ステップ4:スタックを起動する
cd ~/homelab
docker compose up -d
# 3つのコンテナがすべて起動していることを確認
docker compose ps
初期化に約60秒かかる。コンテナが起動したら、以下のURLでサービスにアクセスできる:
- Vaultwarden:
http://your-server-ip:8080 - Gitea:
http://your-server-ip:3000 - Uptime Kuma:
http://your-server-ip:3001
ステップ5:初回設定
Vaultwarden — Web UIを開いてアカウントを作成したら、即座に登録をロックダウンする。docker-compose.ymlを編集してSIGNUPS_ALLOWEDをfalseに変更し、再起動する:
docker compose restart vaultwarden
公式のBitwardenブラウザ拡張機能をインストールする。設定からサーバーURLをbitwarden.comではなくVaultwardenのアドレスに変更する。拡張機能はVaultwardenと通信していることを知らないし、気にもしない。動作はまったく同じだ。
Gitea — ポート3000にアクセスしてセットアップウィザードを進める。SQLiteは個人利用や小規模チームには十分だ。CI/CDパイプラインを持つ数十のアクティブなリポジトリを運用するまで、制限に達することはない。ウィザードの最後に管理者アカウントを作成する。
Uptime Kuma — ポート3001にアクセス。管理者アカウントを作成してから、他のサービスのモニターを追加する。自分で気づく前に通知が届くようになる:
- モニタータイプ:
HTTP(s) - URL:
http://localhost:8080(内部アドレスを使用 — パブリックIPを経由するよりも正確) - インターバル:60秒
ステップ6:NginxリバースプロキシでHTTPSを追加する
ローカルテストにはIPアドレスとポートで十分だ。日常的に使うもの、特にパスワードマネージャーには、HTTPSは必須だ。NginxとLet’s Encryptで設定する:
sudo apt install nginx certbot python3-certbot-nginx -y
sudo nano /etc/nginx/sites-available/vaultwarden
server {
listen 80;
server_name vault.yourdomain.com;
location / {
proxy_pass http://127.0.0.1:8080;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
location /notifications/hub {
proxy_pass http://127.0.0.1:3012;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
}
}
sudo ln -s /etc/nginx/sites-available/vaultwarden /etc/nginx/sites-enabled/
sudo certbot --nginx -d vault.yourdomain.com
sudo systemctl reload nginx
Gitea(git.yourdomain.com)とUptime Kuma(status.yourdomain.com)にも同様のブロックを設定し、proxy_passを各ポートに向ける。
ステップ7:自動バックアップを設定する
誰もが本当に必要になるまでこのステップを飛ばす。そうならないでほしい。毎日のcronジョブで2行で済む:
# crontabエディタを開く
crontab -e
# この行を追加 — 毎日午前2時に実行
0 2 * * * tar -czf /backup/homelab-$(date +\%Y\%m\%d).tar.gz ~/homelab/vaultwarden ~/homelab/gitea ~/homelab/uptime-kuma
バックアップはサーバー外の場所に保管すること。S3バケット、ローカルNAS、USBドライブでも構わない。それよりも重要なのは:リストアをテストすること。一度もリストアしたことのないバックアップは、圧縮された希望に過ぎない。
スタックを健全に保つ
日々のメンテナンスは、ほとんどの人が思うより軽い。3つの習慣で90%をカバーできる:
- 月次でコンテナを更新する:
docker compose pull && docker compose up -d - 週に一度Uptime Kumaのダッシュボードを確認し、問題になる前にサイレント障害を捉える
- ログイン問題が発生したらVaultwardenのログを確認する:
docker logs vaultwarden
3つのサービス、1台のサーバー、パスワード・コード・インフラの可視性を完全にコントロール。ここに慣れたら、Nextcloud、Home Assistant、PortainerもDockerComposeのまったく同じパターンで追加できる。難しいのは技術ではない。更新し続ける習慣を維持することだ。

