• 作成:

自宅サーバにForgejoでGitのホスティングサーバを立ててCloudflare Tunnel経由でアクセスする

背景

昔、ファイルは月別に分けて~/Documentsに置いてgitで管理しています - ncaq に書いたように、私はいろいろなファイルを雑に~/Documentsディレクトリに突っ込んでGitで管理しています。

publicリポジトリに置くことに問題がないか判別が難しいけど、必要かすらよく分からないのでKeePassとかでいちいち管理するほどではないし、保存する必然性があるとは限らないものを雑に置きたいのです。

Google Driveとかは一瞬オフラインだったりして競合が起きたときの挙動を明示的に制御するのが難しいので、ファイルが壊れないGit管理にしたほうが安心です。

こういうファイルはGitHub(Microsoft)に見えるようにして良いのか今ひとつ自信が持てないので、一応自宅サーバで管理しています。単純にファイルサイズが大きすぎるし開発関係ないから、 GitHubのprivateリポジトリに置いたら制限とか食らいそうな気がしますし。

これまでは古い自宅サーバにGitのbareディレクトリを置いてsshでpushとpullをすることで管理していたのですが、引っ越した際に自宅サーバをリプレースして古い自宅サーバは退役させました。

そして、 NixOSの自宅サーバにCloudflare TunnelでHTTPリクエストを通す - ncaq に書いたように新しい自宅サーバは直接IPアドレスを公開せずにCloudflare Tunnel経由でアクセスできるようにしました。

なのでこれまでのようにsshクライアントで直接Gitリポジトリにアクセスするのは難しくなりました。新しくちゃんと解決策を考える必要があります。

また昔から、 sshクライアントがないとGitリポジトリにアクセスできないのは不便だと感じていました。特にモバイル端末などからさっとアクセスしづらいです。サッと外で年末調整のデータを確認したりしたい。よってある程度webブラウザなどからもアクセスできるGitのホスティングサーバを立てたいと考えていました。

Gitのホスティングサーバをどのソフトウェアで立てるか

そういうオープンソースのGitのホスティングサーバのソフトウェアとしてはGitLabが最も有名ですが、 GitLabは商売のため仕方ないんですが全部をオープンソースにはしていないので、どこまでオンプレミスで使えるのか今ひとつ分からないので、ちょっと自宅サーバ上に立てたいだけの用途では考えることが多すぎて面倒です。

そこでForgejo – Beyond coding. We forge.を使うことにしました。これはGitea Official WebsiteからOwnCloudに対するNextCloudみたいに分かれて作ったフォークプロジェクトで、 Codeberg.orgなどで使われている実績もあります。個人的にはxmobar/xmobar: A minimalist status bar - Codeberg.orgの情報を見る時にCodebergはよく使いますね。あとはアメリカの権威に屈したくない人がよく使っているイメージです。

Cloudflare Tunnelでサーバへのアクセスポイントを通す

feat(cloudflare): forgejo用のアクセスポイントを追加 by ncaq · Pull Request #14 · ncaq/infra.ncaq.net に書いたようにDNS recordを追記してアクセスポイントを追加します。

メインのポイント名はforgejo.ncaq.netにすることにしました。役割を考えるとgit.ncaq.netみたいにするのと悩みました。実際forgejoは一回giteaからforkしたので、もしももう一度forkしたら名前を変える必要があります。しかし理屈上はGitLabを別途立てるということもありえなくはないので(ほぼないけど)、単純にソフトウェアの名前をドメイン名にすることにしました。

無料版のCloudflare Tunnelは一回のHTTPSリクエストに対して割と厳しいサイズ制限をしているので、 cloneやpushにはssh接続を使うことで回避します。アクセス制御も簡単になりますし。

本当はssh.forgejo.ncaq.netみたいにサブドメインを分けたかったのですが、 Cloudflare Tunnelの無料版では多段のサブドメイン分けをするとTLSの解決が困難なので、妥協してssh接続のエンドポイントはforgejo-ssh.ncaq.netにしました。そもそもドメインを分けたくないのですが、それも制約上仕方がない。

Forgejoをセットアップする

feat(seminar): add Forgejo service and Cloudflare ingress by ncaq · Pull Request #342 · ncaq/dotfiles に書いたようにNixを使ってForgejoをセットアップしていきます。

ほぼデフォルトのままです。 nixpkgsがありがたい。

一応変更しておいた箇所をメモします。

データベースにはPostgreSQLを使用

デフォルトのservices.forgejo.database.typesqlite3ですが、サーバが分かれていないデータベースはメンテナンスなどが後々面倒になりがちなことを知っているので、 PostgreSQLを使うようにしました。もともとこのサーバではPostgreSQLが動いていますし、 Nixの宣言的な記述で自動でユーザなどもセットアップされます。

SSH_DOMAINを設定

ssh接続のエンドポイントが別ドメインになっているので、 SSH_DOMAINは別途設定しています。

個人専用向けに登録と閲覧を制限

今回は自分一人しか使わないことがはっきりとしているので、アカウント登録は無効化し、閲覧にもログインを必須化しました。

service = {
   # 個人専用向けにふさわしい設定。
   DISABLE_REGISTRATION = true; # 新規登録を無効化。
   REQUIRE_SIGNIN_VIEW = true; # サイト閲覧にログインを必須化。
 };

デフォルトブランチ名をmasterに変更

意味のわからない変更はしたくないので、 DEFAULT_BRANCHmasterに変更しました。

サーバ側でアカウントの設定

web画面からのアカウント登録は無効化しているので、サーバ側でアカウントを発行する必要があります。 forgejoのサーバ用のCLIコマンドをインストールするように設定します。

environment.systemPackages = [
  config.services.forgejo.package # サーバ上で管理CLIコマンドを使えるようにします。
];

ちなみにforgejo-cliパッケージはGitHub CLIのようなコマンドのようで、サーバ側の管理とは少し離れています。

nixpkgsでforgejoforgejo-ltsでインストールするソフトウェアの実行コマンドはforgejoコマンドではなく、名前がgiteaのままになっていることに注意が必要です。

以下のようなコマンドでアカウントを生成できます。

sudo -u forgejo gitea admin user create --username あなたのユーザー名 --password 'あなたのパスワード' --email 'your@example.com' --admin --config /var/lib/forgejo/custom/conf/app.ini

シェルの履歴にパスワードを残さないように注意してください。私の環境だと先頭にスペースを入れることで回避できます。

クライアントがcloudflare tunnel経由でssh接続するように設定

ssh接続をcloudflare tunnelを通さないといけないというのを知らずに結構はまりました。以下のようにhome-managerの設定を追記して~/.ssh/configに設定を追加しました。

{ pkgs, ... }:
{
  programs.ssh = {
    enable = true;
    matchBlocks = {
      "forgejo-ssh.ncaq.net" = {
        proxyCommand = ''
          ${pkgs.cloudflared}/bin/cloudflared access ssh --hostname %h
        '';
      };
    };
  };
}