Ryuji Goto Raspberry Pi 5

Ryuji Goto

IT Engineer

自宅サーバーを、どこまで堅牢にできるか。

構成図

Raspberry Pi 5 でオンプレ Google Photo・テレビ録画・ファイル共有サービスを運用しています。外からの入口は 2 つだけ。
Web は Caddy → Authelia(パスキー)を通り、ファイル共有とルーター管理は WireGuard を通らないと到達できません。

インターネット ルーター HTTPS と VPN のみ開放 家の端末 iPhone・iPad・Mac・Apple TV 家族の端末 HTTPS / VPN Wi-Fi Raspberry Pi 5 有線 LAN ファイアウォール 通れるのは HTTPS と VPN だけ ポート転送 HTTPS → Caddy VPN → WireGuard それ以外は全部ここで遮断 Caddy(HTTPS) 自動証明書・HSTS・HTTP/2 Let's Encrypt(DNS-01) Authelia パスキー・2 要素必須 OIDC(Immich のログインも) 毎晩の自動運転 02:00 バックアップ 03:30 更新 04:30 セキュリティ監査 → Slack 認証 オンプレ Google Photo(Immich) テレビ録画(EPGStation+Mirakurun) ファイル共有(Samba) ルーター管理画面 公開ページ(このサイト) 静的ファイルのみ・認証なし WireGuard VPN 端末ごとの鍵+事前共有鍵 オンデマンド接続(家の Wi-Fi では自動オフ) VPN 経由だけ iStorage(HDD) 写真・動画・録画 アプリのデータ iBackup(HDD) 毎晩 02:00 に 丸ごとミラー 点線=VPN 経由でのみ到達できる経路。外側ルーターが開けているのは HTTPS と VPN の 2 つだけ。
Web アプリはすべて Caddy と Authelia の後ろ。ファイル共有とルーター管理には外から直接届かない。

WireGuard のオンデマンド接続

家の中(家の Wi-Fi に接続中) iPhone / iPad / Mac 家の Wi-Fi VPN 自動オフ ラズパイ 家の LAN 家の LAN に直接 ・オンプレ Google Photo、録画、ファイル共有に LAN の速度でそのまま接続 ・VPN は勝手に切れているので、何も操作しない ・ファイル共有は家の中と VPN からしか見えない 外(4G・外の Wi-Fi・旅先) iPhone / iPad / Mac 家の Wi-Fi を離れた VPN 自動オン 家 ラズパイ・ルーター 暗号化トンネル(家宛てだけ) インターネット Web・SNS・動画 それ以外の通信はそのままインターネットへ(速度低下なし) ・Wi-Fi を離れると自動で接続、帰宅すると自動で切断(操作ゼロ) ・トンネルを通るのは家のアドレス宛てだけ(分割トンネル) ・鍵は端末ごとに専用、事前共有鍵つき。家族の端末は VPN なし オンプレ Google Photo(Immich)は VPN なしでも HTTPS+パスキーで使える。VPN が要るのはファイル共有とルーター管理だけ。
端末側に「家の Wi-Fi 以外では自動で VPN を張る」設定を入れてあるので、使う人は VPN の存在を意識しない。

守りの設計

方針は「入口を減らし、入口にはパスキー、裏口は VPN、毎晩検査する」。

1入口は 2 つだけ

ルーターが外に開けているのは HTTPS と VPN のみ。SSH は家の中と VPN からだけ、鍵認証のみ。ファイル共有は外に出していません。

2Web は Caddy の後ろ

すべての Web アプリはリバースプロキシ Caddy を通ります。証明書は Let's Encrypt から DNS 認証で自動取得・自動更新、HSTS 付き。公開サーバーは静的ファイルだけ。

3ログインはパスキー、2 要素必須

認証は Authelia に集約。Face ID / Touch ID のパスキーで 1 タップ、パスワードだけでは何にも入れません。Immich も同じ認証を OIDC で使い、連続失敗は自動ロック。

4VPN は自動で張る

WireGuard を端末ごとの鍵+事前共有鍵で。家の Wi-Fi では自動オフ、外では家宛ての通信だけトンネルに乗るオンデマンド接続。ファイル共有とルーター管理は VPN 経由のみ。

5ホストもコンテナも締める

ufw は入る方も出る方も既定拒否で、Pi から外へは DNS・HTTP/HTTPS・NTP しか出られません(侵入後の外部通信を防ぐ)。AppArmor でプロセスとコンテナを閉じ込め、使わないカーネルモジュールとサービスは無効化。コンテナは新しい特権を取れず、Samba はゲスト禁止・ロックアウト・監査ログ。設定は CIS ベンチマーク で毎晩点検。

6毎晩、勝手に整う

02:00 に HDD を丸ごとバックアップ、03:30 にコンテナを最新化、04:30 にセキュリティ監査。結果は Slack に届き、録画中は TV の更新を見送ります。

セキュリティ監査の仕組み

毎晩 04:30 に、設定の堅牢さ・改ざんや侵入の兆候・既知の脆弱性・マシンヘルスを別々の道具で調べ、1 枚にまとめます。結果は下に公開し、異常があれば Slack に届きます。

毎晩 04:30 cron(root) security-report.sh 設定は堅牢か CIS Debian 12 L2 Cinc Auditor・298 項目 SSH ベースライン DevSec ssh-baseline Docker Bench CIS Docker Benchmark Lynis 堅牢化指数 0〜100 改ざん・侵入の兆候 AIDE ファイルの指紋を前日と比較 debsums パッケージ実体の照合 rkhunter ルートキット検査 期待状態との差分 ポート・ユーザー・鍵・cron ほか 攻撃の痕跡 SSH・Authelia・Samba・Web のログ 既知の脆弱性 Trivy 稼働中イメージの CVE マシンヘルス 更新・再起動待ち 証明書・バックアップ ディスク・SMART・温度 集計 日本語化・判定・履歴 render.py このページ status/latest.json Slack 通知 異常や変化があった日だけ Cinc Auditor は Chainguard の非 root コンテナで動き、ホストの名前空間に入る補助コンテナを通して Pi 本体を監査する(監査中だけ起動)。 CIS の 298 項目と Docker Bench の 117 項目は日本語化済み。意図的に満たさない項目は「免除」として理由を記録する。 AIDE と rkhunter は検査後に基準を更新し、翌日は「前日からの差分」を出す。apt の更新で変わったファイルは自動で区別する。
道具ごとに「何を・どう」調べるかを分け、集計で 1 つの信号にする。詳細はログイン後の監査ページで。

今日の監査結果

読み込み中…