/01 Architecture
端末はどれもただの窓口。
正本は、いつも家にある。
持ち歩く端末が増えるほど「どれが最新か分からない」が起きます。そこで「この情報の正本(マスター)はここ」を1つずつ決め、 すべて自宅サーバーに置きました。どのPCから作業しても、書き込む先は同じ1箇所です。
作業する端末
Tailscale(WireGuard ベースの暗号メッシュVPN)で1つの閉じた網に入れる
自宅ハブサーバー
旧サブデスクトップを転用 / Core i5-6400・メモリ16GB / Ubuntu 24.04 LTS(サポートは2029年5月まで)
外への通信はサーバー発の一方向だけ(外から入ってくる口は無い)
クラウドストレージ
毎晩03:30のバックアップ先。14世代を保持
GitHub
読み取り用のミラー(片方向のコピー)
トンネルサービス
Minecraft を友人に公開するときだけ
ポイント: サーバー側から出ていく通信はあっても、インターネット側から入ってくる経路が存在しません。 ルーターのポート開放も、固定IPも、DDNSも使っていません。
柱 01
正本の一元化
進捗とログは自作の進捗ハブ、コードは自宅Git、設定とスキルは設定リポジトリ、文書はクラウドストレージ。 「どれが最新か分からない」状態を作らないために、1つの情報につき置き場所は1つと決めています。
柱 02
閉域ネットワーク
全端末を暗号化されたメッシュVPNで接続し、各サービスはそのVPNのアドレスにだけ待ち受けます。 ファイアウォールもVPNのインターフェース以外を通しません。攻撃面は「その網に入れる端末だけ」に絞られます。
柱 03
AIに任せる自動化
git 操作は人間が触らない前提で、AIが自動で commit と push を行います。作業記録もAIがAPIへ直接書き込みます。 人間に残るのは指示・承認・実機確認の3つだけです。
/02 Network
外出先のスマホから、
なぜ家のサーバーに届くのか。
自宅サーバーというと「ルーターのポートを開けて危険」という話になりがちですが、この構成では1つも開けていません。 端末同士を直接つなぐVPNを使うと、外向きの穴を作らずに家の中へ入れます。
Step 01
アプリを入れてログイン
各端末にVPNクライアントを入れ、同じアカウントでログインする。設定はこれだけ。
Step 02
端末同士が直接つながる
WireGuard の暗号トンネルで端末間を直接接続。事業者が仲介するのは鍵交換だけで、通信の中身は通らない。
Step 03
NAT越えは自動
ポート開放・固定IP・DDNSはすべて不要。外出先のモバイル回線からでも同じように届く。
Step 04
サーバーが応答する
閉域内の専用アドレスと名前でのみ応答。同じ網にいない相手からは、存在ごと見えない。
公開したいものが出てきたら、この閉域とは切り離して外部のホスティングへ置きます(このポートフォリオ自体がそうです)。 「家の中で回すもの」と「世界に見せるもの」を混ぜないのが基本方針です。
/03 Services
サーバーの中で
動いているもの。
すべて Docker Compose で動かし、1サービス=1ディレクトリ=1つの compose ファイルに統一しています。 構成ファイルはサーバー上で git 管理し、イメージはダイジェスト(版の指紋)で固定。更新は月に一度、リリースノートを読んでから手で上げます。
| サービス | ポート | 役割 | 状態 |
|---|---|---|---|
| 入口・可視化 | |||
| ダッシュボード(Homepage) | :8080 | 全サービスの入口。どの端末もまずここを開く | 稼働 |
| 進捗ハブ(自作・Node 22) | :8081 | 全プロジェクトの状態・実行ログ・TODO・各PCの構成を SQLite で一元管理 | 稼働 |
| ドキュメント配信 | :8083 | 製品ドキュメントの静的サイト(nginx) | 稼働 |
| 記事公開の管理ツール(自作) | :8082 | 執筆済み記事・書籍の公開キューを消化するための内部ツール | 稼働 |
| アプリのWebデモ | :8091 | 開発中アプリの画面をブラウザで確認するための静的デモ | 稼働 |
| 開発基盤 | |||
| Forgejo(セルフホストGit) | :3000 / :2222 | 全リポジトリの正本。GitHub代替。CI も同居 | 稼働 |
| Forgejo Runner | — | CI の実行役(静的解析・テストなど) | 稼働 |
| 監視・通知 | |||
| Uptime Kuma | :3001 | 死活監視。各サービスの応答を一定間隔で確認 | 稼働 |
| Beszel | :8090 | CPU・メモリ・ディスクの資源監視 | 稼働 |
| Dockge | :5001 | Docker Compose の管理画面 | 稼働 |
| ntfy | :8092 | 異常や完了をスマホへプッシュ通知する自前サーバー | 稼働 |
| 共有・ゲーム | |||
| Samba | :445 | ファイル共有。PC・Mac・iPhone から同じフォルダを開ける | 稼働 |
| Minecraft + トンネル | :25565 | 友人と遊ぶためのサーバー。メモリを7GB使うので普段は落としている | 既定停止 |
- 中核は自作
- この構成でいちばん働くのは、既製品ではなく自作の進捗ハブです。もとはクラウド上のHTMLとメモアプリで管理していましたが、2026年7月にサーバー上のDB+APIへ全面移行し、「取ってきて・作り直して・上げ直す」手作業の同期を廃止しました。
- 見る
- ブラウザでダッシュボード・ガントチャート・端末別の状況・プロジェクト詳細を表示。数字はすべてDBから自動で描画されます。
- 書く
- 各PCのAIが curl でAPIに直接書き込みます。作業を始めたとき・大きく進んだとき・終わったときの3点で記録が残ります。
- 直す
- Git へ push すると、サーバーが2分以内に自分で取りに行き、ビルドして立ち上げ直します。どの端末からでも push だけで反映されます。
- 守る
- 毎晩、DBの中身をまるごと Git へ書き出します。サーバーが落ちている間はその書き出し先を直接編集し、復旧後に取り込む手順を用意しています。
/04 Automation
手を離しても、
回りつづける。
個人開発でいちばん続かないのは「記録」と「同期」です。だから人間が覚えていなくても走る側へ全部寄せました。 時刻で走る定期ジョブと、仕事があるときだけ目を覚ますAIセッションの二本立てです。
Git を見に行き、更新があれば取得→ビルド→起動し直す
自分宛の仕事があるか確認。無ければ数回の通信で終了する(費用はほぼゼロ)
サーバーと各端末のカード、作業キューの生死だけを更新
進捗ハブのDBを Git へ完全エクスポート(バックアップの直前に実行)
Git データ・共有フォルダ・ゲームデータ・DB・構成一式をクラウドへ。14世代を保持
リポジトリの状況を読み直し、入口ダッシュボードの索引を作り直す
1日2回、その時点の状況をまとめてスマホへ届ける
AIを起こさずに、各所の情報の鮮度だけを機械的に揃え直す
なぜ「起動時リフレッシュ」を足したか
このサーバーは常時稼働ではなく、多くの時間は電源が落ちています。すると定時ジョブは「たまたま電源が入っていた瞬間」しか走らず、 画面上の数字は静かに古くなり、しかも古いことが誰にも伝わらない状態になっていました。実際、あるスクリプトは4日間失敗し続けていたのに誰も気づけませんでした。 そこで電源が入るたび1回だけ、AIを起動せずに情報を揃え直す処理を入れ、失敗したステップは必ずスマホへ通知するようにしています(黙って失敗するのを禁止する、という考え方です)。
仕事があるときだけ起きるAI
- 置き場所を絞る。無人で走らせるのはサーバーとMacだけ。オーナーが日常的に使う私用PCには常駐タスクを一切置きません(勝手に動かれると困るため)。
- 自信ではなく、後戻りできるかで分ける。やり直せる作業(調査・編集・下書き・自宅Gitへのpush)は確認せず進め、不可逆・外向きの操作(公開・送信・削除・支出・アカウント操作)は必ず止まって承認を待ちます。
- 安全弁を先に用意する。停止用のファイルを置けば即座に止まり、1日の実行回数と1回あたりの実行時間にも上限があります。無人セッションは自分自身の起動設定を書き換えられません。
- 仕事に合わせてモデルを選ぶ。純粋な機械作業は軽量モデル、手順は決まっているが失敗時に判断が要る作業は中位、設計や文章生成は上位、と作業単位で指定します。
1日の流れ
- 始め: 設定リポジトリを取得 → ハブの未読メモを確認 → 開始を記録。
- 途中: 大きく進んだところで状態を更新。
- 締め: 意味のあるメッセージで commit&push → 実行ログをハブへ1行。
- 保険: AIの各ターン終了時にフックが走り、未コミットの変更を自動で拾って push(取りこぼし防止)。
- 夜: 書き出し → バックアップ → 索引再生成。
/05 Security
AIに任せるほど、
事故の形は決まってくる。
自動で commit と push をする以上、いちばん怖いのは秘密が外へ出ることです。そこで「気をつける」ではなく、 構造として出られないようにしています。7つの層に分けて対策を置きました。
L1ネットワーク
閉域VPN経由のみ。各サービスはVPNアドレスにだけ待ち受け、ファイアウォールもそのインターフェースだけを許可 — インターネットからの攻撃面はゼロ。
L2認証情報
APIトークンや実際のパス名は、各PCのローカル設定ファイル(Git同期の対象外)にだけ保存。「リポジトリに秘密を書かない」を規約として明文化。
L3自動pushの安全弁
自動コミットは、環境ファイル・鍵・認証情報・90MB超の巨大ファイルを自動で除外。push 先は自宅Gitのみに限定し、送信先ホストが一致しなければ実行しない。
L4公開範囲
外部(GitHub)へ出るのはサーバーからの一方向ミラーだけ。公開してよいリポジトリを明示的に指定する方式で、「何が外に出るか」をサーバー側の1箇所で管理。
L5データ境界
端末ごとに「扱ってよいデータの範囲」をプロファイルとして宣言し、用途の違う環境を混ぜない。リポジトリ・保管庫・AIのスキルまで系統ごと分けてあるので、別用途のデータが個人のAIセッションに流れ込まない。
L6可用性
死活監視+夜間バックアップ14世代+DBのGitミラー。サーバーが落ちている間も記録を止めない代替手順を用意し、復旧後に取り込む。
L7更新管理
コンテナイメージは版の指紋で固定し、更新は月次で手動。「知らないうちに上がって壊れる」「悪意ある新版を引く」の両方を防ぐ。
機械にチェックさせる
月に一度、読み取り専用の監査スクリプトを走らせています。外部に露出しているポート、公開設定になっているコンテナ、 秘密ファイルの権限、リポジトリへの秘密混入など8つの観点を機械が確認し、結果を一覧で出します。 自動 push の仕組みそのものも、実装後に多数のレビュー用エージェントで敵対的に検証し、見つかった不具合を修正してから運用に入れました。
/06 Build
同じものを組むなら、
この順番がいい。
全部で数週間かけて組みましたが、順番を間違えると後戻りが増えます。「先に土台、次に守り、最後に便利機能」で並べ直したのが以下です。 特別なハードは要りません。
-
余っているPCを1台決める
専用機を買う必要はありません。ここで使っているのは第6世代の Core i5 と16GBメモリという、10年近く前の構成のデスクトップです。 ゲームサーバーまで載せないなら、もっと非力な機体でも足ります。
-
長期サポートのUbuntuを入れる
OSは長期サポート版(LTS)を選びます。サポート期限が数年先まで決まっていること自体が、個人運用では大きな安心材料になります。 この機体は2029年5月まで面倒を見てもらえます。
-
先にVPNを通す
いちばん最初にVPNを入れて、サーバーと手持ちの全端末を同じ閉域網に入れてしまいます。 ここを最初にやると、以降「外に公開する」という選択肢を一度も検討せずに済みます。ポート開放も証明書の運用も不要になります。
-
穴を塞いでから、サービスを足す
ファイアウォールはVPNのインターフェースだけを許可し、各サービスもVPNのアドレスにだけ待ち受けさせます。
0.0.0.0で待ち受けているサービスが1つでもあると、そこだけ全世界に開くことになります。サービスを増やす前にこの型を決めるのが肝心です。 -
Docker Compose を「1サービス1ディレクトリ」で統一する
置き場所と書き方を最初に固定します。構成ファイルはサーバー上でGit管理し、イメージは版の指紋で固定。 試したいものは検証用ディレクトリで動かし、常設に格上げするときだけ本番の場所へ移す、という運用にすると散らかりません。
-
自前のGitを建てて、正本を引っ越す
セルフホストのGitサービスを立て、コードの正本をそこへ移します。外部サービスへは読み取り用のミラーだけを送ります。 「push すると同時にリポジトリが自動で作られる」設定にしておくと、新しいプロジェクトを始めるときに事前準備が一切なくなります。
-
監視とバックアップを、便利機能より先に作る
死活監視と資源監視、そして夜間バックアップ(クラウドへ世代を残す形)は、楽しい機能を足す前に用意します。 バックアップは取れているかを毎晩自分で確かめて、失敗したら通知するところまで作って初めて完成です。
-
最後に、記録と雑務をAIへ渡す
ここまで来て初めてAIの出番です。作業のたびに決まった手順書(スキル)を読ませ、状態の記録・実行ログ・commit と push を任せます。 人間側は「後戻りできるか」で線を引き、やり直せる作業は任せ、不可逆・外向きの操作だけ承認を残します。
つまずいたところ(実際に起きた失敗)
- 起動直後に定期ジョブが落ちる。VPNのアドレスが割り当たる前にジョブが走り、通信できずに失敗していました。今は「アドレスが載るまで待つ」処理を先頭に置いています。
- 失敗が黙って積もる。索引を作り直すスクリプトが4日間失敗し続けていたのに、誰も気づきませんでした。失敗は必ず通知へ出す、を原則にしました。
- 死んだ作業キューが見えない。「実行中」のまま止まった項目は、未着手だけを見る画面から永久に消えます。棚卸しして自動で差し戻す処理を足しました。
- AIが1件で時間を使い切る。重い1件が30分の持ち時間を丸ごと消費し、他が進まないことがありました。作業ごとにモデルを指定できるようにして解消しています。
- 承認の宛先違いで空振りする。Mac向けの承認をサーバーが拾って無駄に起動していました。宛先の端末で絞る条件を足して解決しました。
/07 Stack & Cost
土台は、ぜんぶ無料。
固定費はAIだけ。
中身は「①サーバー上のオープンソース(すべて自ホスト)」「②外部サービスの無料枠」「③AIのサブスクリプション」の3層です。 月々の固定費として払っているのは③だけで、インフラ側は電気代を除けばゼロ円で回っています。
| ソフトウェア | 役割 | ライセンス | 費用 |
|---|---|---|---|
| Forgejo | Git・CIの正本 | GPL-3.0+ | 無料 |
| Forgejo Runner | CIの実行 | MIT | 無料 |
| Dockge | コンテナ管理UI | MIT | 無料 |
| Uptime Kuma | 死活監視 | MIT | 無料 |
| Beszel | 資源監視 | MIT | 無料 |
| Homepage | 入口ダッシュボード | GPL-3.0 | 無料 |
| Samba | ファイル共有 | GPL-3.0 | 無料 |
| nginx | 静的サイトの配信 | BSD-2-Clause | 無料 |
| itzg/minecraft-server | ゲームサーバーの実行 | Apache-2.0(ゲーム本体は別途ライセンス) | 無料 |
| トンネルエージェント | ゲームの外部公開 | 提供元リポジトリ参照 | 無料枠 |
| 進捗ハブ | プロジェクト状況の一元管理 | 自作(Node 22 + SQLite) | 無料 |
| サービス | 用途 | プラン | 止まったらどうなるか |
|---|---|---|---|
| VPN(Tailscale) | 閉域網の土台 | 個人向け無料枠 | いちばん重い単一依存。無料枠が縮小されたら影響大。代替の選択肢(他社サービス/自前のWireGuard)は調べてある |
| GitHub | 公開用リポジトリとミラー先 | Free | ミラーは読み取り用のコピーなので、正本(自宅Git)は無傷 |
| クラウドストレージ | 文書の正本とバックアップ先 | 無料枠 | 容量が足りなくなったら有料化を検討。使用量は監視項目に入れている |
| トンネルサービス | ゲームの外部公開 | 無料枠 | 止まっても閉域内での接続は無傷。友人を呼べなくなるだけ |
AI(Claude Code)の使い方
- 全PCとサーバーで同じCLIを使い、作業内容ごとに手順書(スキル)を読ませて品質を揃えます。「毎回同じやり方で定型作業をさせる」ための仕組みが、この運用の生産性の核心です。
- 重い作業(大量生産・複数ファイルの実装・難しい設計)は上位モデルの工程分割モードへ切り替え、軽い機械作業は軽量モデルへ落とします。
- 料金は従量ではなく定額のサブスクリプション。実作業まで任せ切る使い方では上位プランが実質的な前提になります。これ以外の月額固定費はありません。
/08 Status
まだ終わっていない
ところの話。
完成品として見せたいところですが、まだ検証中・保留中の項目があります。隠すと参考にならないので、そのまま書いておきます。
- 遠隔での電源投入は物理検証待ち。ネットワーク越しに起動する仕組み(Wake-on-LAN)は設定済みですが、実機での確認がまだ終わっていません。
- 連続稼働とバックアップの実績は積算中。「30日連続稼働」と「夜間バックアップ30日成功」を判定条件にした最終フェーズがあり、2026年8月中旬に判定予定です。
- Windows機の情報は意図的に更新頻度が低い。私用PCには常駐タスクを置かない方針のため、画面上の表示が古く見えますが、これは仕様どおりの状態です。
このページの内容は、運用ハンドブック(閉域内で運用している内部文書)を公開向けに再構成したものです。 構成は随時変わるため、数値と稼働状況は2026年8月1日時点のものとしてお読みください。