オチツカレサマ 〜 Forgejoが立ち上がった朝の記録
オチツカレサマ 〜 Forgejoが立ち上がった朝の記録
はじめに
3日前、Garageが立ち上がった朝に、こう書いた。
ainsoph.xyz、最初の住人はGarage
その時に並べた未来図は、こう。
ainsoph.xyz
├── garage.ainsoph.xyz ← 完了
├── ocr.ainsoph.xyz ← 後日
├── notes.ainsoph.xyz ← 後日
└── lab.ainsoph.xyz ← 実験用
しかし朝になって、この図は少し書き換わることになった。
きっかけは、Vault を git 管理し始めたことだった。
なぜ git だったか
ainsoph-pipelines(OCR 知性パイプライン)のソースコードは GitHub のプライベートリポジトリで管理している。コードはそれでいい。
問題は、Vault そのものを git 管理したいと思い始めたことだった。
Vault は、私の知性の延長そのものだ。
- 仏教史と古典の研究素材
- バガヴァンダルシャンの記録
- 夢分析プロジェクト
- IGREK の議事録、東洋テックの議事録、両替商の設計
- パートナーとの旅行計画
- 健康にまつわる悩み
- 朝の思考整理
これを GitHub に置く違和感が、どうしても拭えなかった。
「置く場所そのものが内容と矛盾しないこと」が、Vault には大事だった。Garage と同じだ。自分の知性は自分のインフラの上に置く、という思想を、ここでも貫きたかった。
ということで、ainsoph.xyz の二人目の住人が決まった。
ainsoph.xyz
├── garage.ainsoph.xyz ← 4/26 朝
└── git.ainsoph.xyz ← 今朝
どれを選ぶか
セルフホストできる Git ホスティングは大きく3つ。
| メモリ | 特徴 | |
|---|---|---|
| GitLab Omnibus | 4GB+ | CI/CD強力、社内向け、重い |
| Gitea | 200-400MB | GitHub UI似、軽い |
| Forgejo | 200-400MB | Gitea forkでコミュニティ運営 |
GitLab はオーバーキル。1人で使うのに4GBはもったいない。
Gitea と Forgejo は実態ほぼ同等。コードベースは ほぼ共通で、定期的に同期している。
判断ポイントはガバナンスだった。
Gitea は2022年に商用会社(Gitea Ltd)が立ち上がってライセンス周りでコミュニティと衝突。創設メンバーの一部が Forgejo をフォークして、Codeberg e.V.(ドイツの非営利)の傘下でコミュニティ運営の路線を堅持した。
Garage が CHATONS 系(フランスの非営利コミュニティ)で開発されているのと同じ系譜。思想的に一貫する。
Forgejo に決めた。
ポート3000の確認
Forgejo のデフォルトポートは 3000。
しかし、Grafana のデフォルトポートも 3000。Grafana は「セルフホストで真っ先に狙われる」サービスとして名高く、過去にチャットでも話題になっていた。
「3000、何かに使ってないか?」
念のため確認する。
sudo ss -tlnp | grep -E ':300[0-9]\s'
何も返ってこない。
sudo docker ps --format "table {{.Names}}\t{{.Ports}}" | grep -E ':300[0-9]'
何も返ってこない。
完全に空いている。Garage は 3900/3901/3903 を使っていて、3000台前半は無人だった。Grafana を入れていなかった過去の自分、ありがとう。
docker-compose の組み立て
Garage の構築記をなぞる。形式は完全に同じ。
/root/forgejo/docker-compose.yaml:
services:
forgejo:
image: codeberg.org/forgejo/forgejo:9
container_name: forgejo
restart: always
environment:
- USER_UID=1000
- USER_GID=1000
- FORGEJO__server__DOMAIN=git.ainsoph.xyz
- FORGEJO__server__SSH_DOMAIN=git.ainsoph.xyz
- FORGEJO__server__SSH_PORT=2222
- FORGEJO__server__ROOT_URL=https://git.ainsoph.xyz/
- FORGEJO__service__DISABLE_REGISTRATION=true
- FORGEJO__service__REQUIRE_SIGNIN_VIEW=true
- FORGEJO__database__DB_TYPE=sqlite3
volumes:
- ./data:/data
- /etc/timezone:/etc/timezone:ro
- /etc/localtime:/etc/localtime:ro
ports:
- "127.0.0.1:3000:3000"
- "0.0.0.0:2222:22"
deploy:
resources:
limits:
memory: 1G
ポイントは2つ:
SSH_PORT=2222: ホスト OS の sshd が22番を使っているので、Forgejo の Git SSH は2222番にするDISABLE_REGISTRATION=true+REQUIRE_SIGNIN_VIEW=true: 公開Forgejoではないので、誰でも登録できないようにし、未ログインでは何も見えないようにする
起動する。
cd /root/forgejo
docker compose up -d
10秒待って状態確認:
$ docker stats --no-stream forgejo
CONTAINER ID NAME CPU % MEM USAGE / LIMIT PIDS
683eb78aae54 forgejo 0.01% 109.4MiB / 1GiB 14
109MB。Garage の5.7MBには及ばないが、Go ランタイムと SQLite と Git を内包していることを考えれば妥当な軽さ。
SSHトンネルで初期セットアップ
DNS反映を待たずに、Mac から直接初期セットアップに入る。Garage の時と同じ手口。
# Mac側で別ターミナルを開いて
ssh -L 3000:localhost:3000 xvps -N
このまま開きっぱなし。
ブラウザで http://localhost:3000 を開く。
Forgejo の 初期セットアップ画面 が現れる。項目が多くて圧倒される。
Database settings, General settings, Email settings, Server and third-party service settings, Administrator account settings...
しかし、ほとんどはデフォルトで通る。変えるべきは数項目だけだった。
| 項目 | 値 |
|---|---|
| Database type | SQLite3 |
| Server domain | git.ainsoph.xyz |
| SSH server port | 2222 |
| Base URL | https://git.ainsoph.xyz/ |
| Disable Self-Registration | ✅ |
| Require Sign-In to View Pages | ✅ |
| Administrator username | foresthill |
管理者パスワードは 1Password で生成して保管してから「Install Forgejo」を押す。
数十秒で処理が走り、ログイン画面に遷移した。
foresthill でログインすると、Dashboard が出た。
お、入れた!dashboard 出ました。
軽く声が出た。
SSH鍵の準備
将来 git push するための鍵を作る。
ssh-keygen -t ed25519 -C "forgejo-ainsoph" -f ~/.ssh/id_ed25519_forgejo
-C の Comment を何にするか少し迷った。「foresthill@ainsoph か、別の何か」。世界観で攻めるなら ein-sof-key という案もあったが、実用性で forgejo-ainsoph に着地した。
公開鍵を Forgejo の Settings → SSH Keys に登録。Key Name は Macbook Pro (forgejo-ainsoph)。
設定ファイルの罠
~/.ssh/config に Forgejo 用の設定を追記する。
cat >> ~/.ssh/config <<'EOF'
Host git.ainsoph.xyz
HostName git.ainsoph.xyz
Port 2222
User git
IdentityFile ~/.ssh/id_ed25519_forgejo
IdentitiesOnly yes
EOF
実行して、SSH接続テスト。
$ ssh -T git@git.ainsoph.xyz
/Users/foresthill/.ssh/config line 17: no argument after keyword "eof"
/Users/foresthill/.ssh/config: terminating, 1 bad configuration options
エラー。
ヒアドキュメントの終端マーカー EOF が、ファイルにそのまま書き込まれてしまっていた。SSH config はその EOF を未知のキーワードとして解釈し、起動を拒否している。
sed -i '' '/^EOF$/d' ~/.ssh/config
macOS 版 sed の罠(-i の後ろに空文字列が必要)も思い出しながら、余分な行を削除する。
再度テスト。
$ ssh -T git@git.ainsoph.xyz
The authenticity of host '[git.ainsoph.xyz]:2222 ([210.131.212.67]:2222)' can't be established.
ED25519 key fingerprint is SHA256:xxx.
Are you sure you want to continue connecting (yes/no/[fingerprint])?
「初めて会うサーバーだけど、本物?」と SSH が聞いてくる。これは正常なプロンプト。
3つ同時に確認できた瞬間だった。
- DNS は反映している(
210.131.212.67を引けている) - ポート2222 は届いている(Forgejo の SSH に到達できている)
- ssh config の修正が効いている
yes を打つ。
Hi there, foresthill! You've successfully authenticated with the key named Macbook Pro(forgejo-ainsoph), but Forgejo does not provide shell access.
🎉
Hi there, foresthill! の一行が、本当に嬉しい。Forgejo がユーザーを認識し、鍵で認証し、その鍵の名前まで覚えてくれている。
お、できたかな!?
SSL証明書 — 3日前と同じ手順、迷いなく
Garage の時と一字一句同じコマンドを叩く。
docker exec docker-certbot-1 certbot certonly \
--webroot -w /var/www/html \
-d git.ainsoph.xyz \
--email <Gmail> --agree-tos --no-eff-email --non-interactive
Successfully received certificate.
Certificate is saved at: /etc/letsencrypt/live/git.ainsoph.xyz/fullchain.pem
This certificate expires on 2026-07-28.
3日前は緊張しながら叩いた同じコマンドが、今朝は型のように手から出てきた。学びが型になっていく瞬間がここにあった。
Nginx — 同じ型、別の住人
/root/dify/docker/nginx/conf.d/forgejo.conf を Garage の garage.conf を雛形にして作る。違うのは:
server_name:garage.ainsoph.xyz→git.ainsoph.xyzproxy_passのポート:3900→3000client_max_body_size: PDF用の5G→ Vault git push用の2G
それ以外は同じ。
構文チェック。
$ docker exec docker-nginx-1 nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
OK。
ひとつ罠があった
Nginx をリロードする前に、内部からの疎通テスト。
$ docker exec docker-nginx-1 curl -I http://210.131.212.67:3000/
curl: (7) Failed to connect to 210.131.212.67 port 3000 after 0 ms
Connection refused。
原因は分かっていた。docker-compose.yaml で 127.0.0.1:3000:3000 とバインドしていたから、Nginx コンテナから VPS の IP 210.131.212.67:3000 には届かない。コンテナは Docker のネットワーク空間にいて、ホストの localhost は見えない。
「localhost で繋がっているのに変えるの?」と一瞬迷う。
しかし答えは Yes。Nginx 経由で正規ルートに乗せるには、0.0.0.0:3000 にバインドする必要がある。
ただし「外部から3000に直接届いたら危険」という懸念がある。Xserver のパケットフィルタが3000を塞いでいるかを先に確認する。
# Mac側、つまり外部から
$ curl --connect-timeout 5 -I http://210.131.212.67:3000/
curl: (28) Failed to connect to 210.131.212.67 port 3000 after 5004 ms: Timeout was reached
Timeout。完璧。Xserver パケットフィルタが3000を塞いでいる。Nginx 経由(443)でのみ Forgejo に届く構図ができている。
安心して docker-compose.yaml を書き換える。
ports:
- "0.0.0.0:3000:3000" # 127.0.0.1 → 0.0.0.0
- "0.0.0.0:2222:22"
再起動して、再テスト。
$ docker exec docker-nginx-1 curl -I http://210.131.212.67:3000/
HTTP/1.1 200 OK
Date: Wed, 29 Apr 2026 10:18:39 GMT
✅ 内部から: 200 OK
✅ 外部から: Timeout
二層防御が効いている。Nginx からは届く、外部からは届かない。これが望ましい。
完全勝利
Nginx をリロードし、HTTPS で叩く。
$ curl -I https://git.ainsoph.xyz/
HTTP/1.1 200 OK
Server: nginx/1.29.7
Date: Wed, 29 Apr 2026 10:19:44 GMT
Connection: keep-alive
ブラウザで https://git.ainsoph.xyz を開く。
Forgejo のログイン画面が、本番URLで現れる。鍵マークは緑。
foresthill でログインすると、Dashboard が出た。
でた!
できたぁああああ!!!
軽く叫んだ。
通信経路、完成図
Mac (Obsidian Vault, git push)
→ DNS解決 (git.ainsoph.xyz → 210.131.212.67)
→ VPS の 443 (HTTPS) または 2222 (Git SSH)
→ 443 の場合: nginx → 210.131.212.67:3000 → Forgejo
→ 2222 の場合: 直接 Forgejo container :22
→ /data/git/repositories/ (SQLite + git bare repos)
シンプルで、美しい。Garage の時と同じ感想を持った。
3日で2人
ainsoph.xyz ← トップ
├── garage.ainsoph.xyz ← 4/26 朝に立った(PDF倉庫、S3互換)
└── git.ainsoph.xyz ← 今朝立った(Vault知識管理、Forgejo)
3日でこれだけ拡張できたのは、1人目(Garage)で型が手に入っていたからだ。
- DNSを先に仕掛けて反映待ちの間に他を進める
- SSHトンネルで DNS 反映前にバイパスして初期セットアップ
- Let's Encrypt の同じコマンドを一字違いで叩く
- Nginx の
garage.confを雛形にforgejo.confを作る - ports を
127.0.0.1:か0.0.0.0:か、Xserver パケットフィルタとの兼ね合いで判断する
これら全部、3日前は「初めて」だったものが、今朝は型になっていた。1回目は学び、2回目は型の獲得。次の住人(OCR API、Obsidian Publish、その他)は、もっと早く立つ。
なぜ Vault を Forgejo に置きたいか
Vaultの中身を改めて見ると、Inboxだけで300ファイル以上。
- 議事録(DENSO、東洋テック、IGREK、hhms、両替商)
- 霊性の実践(バガヴァンダルシャン、ホーマ、ディクシャ)
- ビジネス計画と要件定義
- 個人の悩みや夢分析の素材
これを GitHub に置くのは、内容と置き場所が矛盾する。GitHub は素晴らしいサービスだが、米国企業のサーバーに、自分の最も内側の素材を置くという構図には、どうしても違和感が残る。
ainsoph-pipelines のソースコードは GitHub でいい。コードは公共財に近い。
しかし Vault は、私自身の延長だ。これを置く場所は、ainsoph.xyz の上でなければ整合しない。
五蘊との対応
- 色(rūpa) : Garage(PDF素材の倉庫)
- 受(vedanā): OCRパイプライン(読み取り)
- 想(saññā): Vault Inbox/Sources(テキスト化された素材)
- 行(saṅkhāra): Vault Active/Knowledge(編集・統合) ← ここがForgejoに乗る
- 識(viññāṇa): Publish(Digital Garden、世界へ)
「行」(saṅkhāra)= 意思を持って世界を編集する行為。それを git で履歴管理する。これは思想と実装が完全に整合する状態だ。
オチツカレサマ
3日前の朝、Garageが立ち上がった時に「ainsoph.xyzの最初の住人はGarage」と書いた。
今朝、二人目が来た。
驚いたのは、それがこんなに速く、こんなに迷いなく進んだことだ。Garageの構築記を読み返しながら作業していたが、途中からほぼ見なくても手が動くようになっていた。型は2回目で身につく、という学びそのものを、構築の時間そのもので体験した朝だった。
今朝の達成
残るもの
- テストリポジトリでの clone/push 動作確認(最終チェック)
- Vault git化(
.gitignore設計、PDF分離、初回push) ← 別日に慎重に - Obsidian Git プラグインの設定
- 寝る前 commit 習慣化
- 自動更新(Let's Encrypt 90日サイクル)の確認
学び
型は2回目で手に入る。
Garage の時、SSHトンネル・SSL取得・Nginx設定の各段階で「これで合っているか?」と何度も立ち止まった。今朝は迷わなかった。コマンドが手から出てきた。「学び」と「型」は別物で、型まで進めるには「2回目」が要る。1回目は学び、2回目は型、3回目は応用。Forgejo の次の住人(OCR API、Publish)は、応用フェーズに入る。
置き場所は内容と矛盾してはいけない。
GitHubは素晴らしいサービスだ。仕事のリポジトリ、OSS のコード、それは GitHub でいい。しかし Vault のような「自分自身の延長」と呼べる素材は、GitHub に置くと内容と矛盾する。霊性の記録、内面の悩み、人間関係の機微。これらは自分のドメインに置くことで、初めて内容と整合する。技術選定はしばしば思想の問題だ。
罠は2回目でも来る。
ヒアドキュメントの EOF 混入、127.0.0.1 バインドで Nginx から届かない問題、これらは初心者向けの罠ではなく、「2回目だからこそ」発生する罠だ。Garage の時と少し違うシチュエーション(鍵を新規作成する、SSH config を初めて触る)が混ざるたびに、新しい罠が顔を出す。型の獲得は罠の予防にはならない。罠が来たら淡々と対処する、という態度のほうが大事。
オチツカレサマ。
3日前の朝とは違う朝で、しかし同じ感覚で、また一つの住人が立ち上がった。
これからもぼちぼち、ainsoph.xyz に住人が増えていく。
明日も、ぼちぼち。
関連記事
- 2026-04-26-オチツカレサマGarageが立ち上がった朝の記録 - シリーズ第1夜、Garageが立ち上がった朝
- 2026-04-27-オチツカレサマ12倍に膨れたOCR結果と容量設計の罠 - シリーズ第2夜、OCR容量設計の発見
参考リンク
- Forgejo 公式
- Codeberg e.V. - Forgejoのホスティング元
- Gitea vs Forgejo: なぜフォークが起きたか
- Let's Encrypt certbot ドキュメント