SSD Nodes Learn 🎉 VPS $5.50/月〜
ガイド Matt Connor著者 Matt Connor ・更新日 2026-08-13

自宅サーバーのGitはForgejo、Gitea、cgitのどれ?

RAM別にGitサーバーの4構成を比較します。SSHのbare repository、cgit、ForgejoまたはGitea、GitLabの違いと、1 GBのVPSで動かせる範囲が分かります。

運用するセルフホスト Git サーバーの選び方

セルフホスト Git サーバーは単一の製品ではありません。VPS の RAM(random access memory)容量によって、利用できる構成が決まります。Git 自体に専用のデーモンは必要ありません。bare repository と SSH(secure shell)アカウントがあれば、レンタルできる最小構成のサーバーでも、すでに動作するサーバーになります。それ以上の機能は、そのサーバーと併用する Web アプリケーションです。構成を高機能にするほど、容量の小さい VPS では確保できないメモリが必要になります。

選択肢は4段階あります。SSH 経由の bare repository なら、既存の待ち受け以外に待ち受けるプロセスはありません。cgit はデータベースを使用しない、高速な読み取り専用 Web ビューです。Forgejo または Gitea は、アカウント、issue、pull request を数百 MB で提供する、フル機能の forge です。GitLab は、他の構成より何倍も大きなサーバーを前提とします。

必要な作業を基準に選び、必要なメモリ容量を契約中のプランと照合してください。

各選択肢に実際に必要な RAM

これらのプロジェクトのうち、ハードウェア要件を公開しているのは 2 つだけです。公開された値は保証ではなく下限と考えてください。実際に起動したら、systemd-cgtop または ps -o rss= -C forgejo を使って自分のインスタンスを測定してください。

ChartRAM the projects document, official docs, August 2026
The data behind this chart
[
  {
    "label": "Gitea, small team",
    "ram_gb": 1
  },
  {
    "label": "GitLab, memory constrained",
    "ram_gb": 8
  },
  {
    "label": "GitLab, single node baseline",
    "ram_gb": 16
  }
]

Gitea は、小規模なチームやプロジェクトには 1 GB の RAM と 2 個の CPU コアで通常は十分だと説明しており、小規模なワークロードには Raspberry Pi 3 で足りるとしています。GitLab は、シングルノード構成のベースラインとして 16 GB を示し、自身のページで「メモリ制約環境」と呼ぶ構成の下限として 8 GB を示しています。Forgejo はハードウェア要件を一切公開していません。Forgejo は Gitea のフォークであり、動作も Gitea に似ているため、利用できる最も近い公開目安は Gitea の値です。

1 GB の VPS での意味は次のとおりです。ベアリポジトリと cgit は常駐サービスを実行しないため、余裕を残して収まります。Forgejo または Gitea は起動し、SQLite で小規模なチームにサービスを提供できます。ただし、文書化された下限に達しているため、そのホストでは PostgreSQL と CI(継続的インテグレーション)runner を停止しておいてください。Web インターフェースがエラーを表示せずに消えた場合は、sudo dmesg -T | grep -i oom を実行し、Out of memory: Killed process 1181 (forgejo) のような行を探してください。これは kernel の out of memory killer がプロセスを終了したことを示します。1 GB のホストで GitLab を動かす場合、チューニングで解決できる問題ではありません。動作しません。

Tier 0: SSH 経由の bare リポジトリ

Git には、起動が必要なネットワークデーモンがありません。git push は SSH 経由で接続先の git-receive-pack を通常の Unix プロセスとして実行するため、鍵で接続できるアカウントはすでに Git リモートとして利用できます。リポジトリ用のアカウントを作成し、リポジトリはそのホームディレクトリの外部に置いてください。Ubuntu 24.04 では新しいホームディレクトリのモードが 0750 であり、後から追加する Web ビューがその中を読み取れないためです。

sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \
  --group --disabled-password --home /home/git git
sudo install -d -m 0755 -o git -g git /srv/git
sudo -u git git init --bare /srv/git/project.git

--bare は作業コピーを持たないリポジトリを作成します。これはサーバーに置くリポジトリの形式です。作業コピーを持つリポジトリへの push は refusing to update checked out branch: refs/heads/main で拒否されます。この問題は、この構成で最もよくあるミスです。

次に、アカウントに鍵を設定して clone します。

sudo -u git install -d -m 700 /home/git/.ssh
sudo -u git tee -a /home/git/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop
EOF
sudo -u git chmod 600 /home/git/.ssh/authorized_keys
git remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin main

最初の push が成功すると、最後に * [new branch] main -> main が表示されます。git@vps.example.com: Permission denied (publickey) で終わる場合は認証されていません。sudo journalctl -u ssh -n 20 でサーバーのログを確認してください。Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys と表示される行がある場合は、ファイルモードが誤っています。ほかのユーザーが書き込める鍵ファイルは sshd が無視するためです。

次に、アカウントからシェルを取り上げます。

command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" git

git-shell は、Git が SSH 経由で送信する限られたコマンドだけを受け付けます。そのため、対話型ログインを試みるとプロンプトは表示されず、代わりに次のメッセージで終了します。

fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.

これでサーバーの構成はすべてです。データベースはなく、更新が必要な Web プロセスもありません。一方で、forge が提供する機能はすべて失います。リポジトリの閲覧、Issue トラッカー、pull request、ユーザー単位の権限管理はありません。そのファイルに登録されたすべての鍵が、git ユーザーの所有するすべてのリポジトリを読み書きできます。

Tier 1: cgit でデータベースなしの Web ビューを提供する

cgit は C で書かれた CGI(Common Gateway Interface)プログラムです。Web サーバーはリクエストごとに cgit を 1 回実行します。cgit はディスクからリポジトリを直接読み取り、自身の状態を保存しません。Ubuntu 24.04 では universe コンポーネントに含まれています。

sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgit

/etc/cgitrc 内のリポジトリディレクトリを指定します。

root-title=Git on example.com
css=/cgit.css
logo=/cgit.png
cache-size=1000
cache-root=/var/cache/cgit
snapshots=tar.gz zip
scan-path=/srv/git

scan-path はそのディレクトリを走査し、見つかったすべてのリポジトリを一覧表示します。そのため、新しい bare リポジトリは追加設定なしで表示されます。cache-size はキャッシュするページ数です。0 の間はキャッシュが無効です。行を追加する前に、パッケージが /etc/cgitrc に配置した内容を確認してください。Debian と Ubuntu のパッケージには、独自のデフォルト設定が含まれている場合があります。

各エントリには、リポジトリの description ファイルの先頭行が表示されます。そのため、新しい bare リポジトリは Unnamed repository; edit this file 'description' to name the repository. と表示されます。リポジトリごとに 1 回、これを修正します。

echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/description
nginx のサイトファイルと確認方法
server {
    listen 80;
    server_name git.example.com;
    root /usr/share/cgit;

    try_files $uri @cgit;

    location @cgit {
        include fastcgi_params;
        fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
        fastcgi_param PATH_INFO $uri;
        fastcgi_param QUERY_STRING $args;
        fastcgi_param HTTP_HOST $server_name;
        fastcgi_pass unix:/run/fcgiwrap.socket;
    }
}
sudo systemctl enable --now fcgiwrap.socket
sudo nginx -t && sudo systemctl reload nginx
systemctl show fcgiwrap.socket -p Listen

root /usr/share/cgitcgit.csscgit.png を通常のファイルとして提供し、それ以外のすべてを /usr/lib/cgit/cgit.cgi の CGI に try_files します。/var/log/nginx/error.logconnect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) が表示された 502 ページは、socket unit が起動していないか、別のパスで待ち受けていることを示します。systemctl show の行に、実際に使用しているパスが表示されます。

構築を進める前に、2 つの制限を把握しておく必要があります。cgit は読み取り専用で、ログイン機能もありません。そのため、scan-path 以下はすべて公開されます。非公開リポジトリはそのディレクトリの外に置くか、サイト全体の前段に HTTP Basic 認証を設定してください。また、CGI は Web サーバーのユーザーとして実行されます。そのため、そのユーザーには /srv/git を通過し、各リポジトリを読み取る権限が必要です。入れないディレクトリは、エラーではなく空のインデックスとして表示されます。

課題とプルリクエスト向けの Tier 2: Forgejo または Gitea

Forgejo と Gitea は同じ構成です。ユーザー、組織、課題、プルリクエスト、リリース、パッケージレジストリ、組み込み CI システムを備えた Web forge を、1 つの Go バイナリで提供します。インストールに必要なのはバイナリと SQLite だけです。そのため、GitLab を実行できないハードウェアにも適しています。以下の Compose ファイルは Forgejo のドキュメントに掲載されているものです。イメージタグは 2026 年 8 月時点で指定されているものです。

networks:
  forgejo:
    external: false

services:
  server:
    image: codeberg.org/forgejo/forgejo:16
    container_name: forgejo
    environment:
      - USER_UID=1000
      - USER_GID=1000
    restart: always
    networks:
      - forgejo
    volumes:
      - ./forgejo:/data
      - /etc/localtime:/etc/localtime:ro
    ports:
      - '3000:3000'
      - '222:22'
docker compose up -d
docker compose ps
curl -sI http://127.0.0.1:3000 | head -1

curl の行には、HTTP ステータス行が表示されます。初回セットアップを完了する前は /install へのリダイレクトになることがありますが、それでもサービスは起動しています。コンテナが終了する場合、通常の原因は所有者設定です。./forgejo ディレクトリは USER_UID に指定された UID (user id) の所有にする必要があります。そうしないと、プロセスは自身のデータディレクトリに書き込めません。VPS 上の Docker Compose では、このファイル構成とボリュームの所有者設定について詳しく説明しています。

セットアップページにある 2 つの項目が、clone URL を使用できるかどうかを決めます。SSH ポートは 222 にする必要があります。Compose ファイルがホストのポート 222 をコンテナのポート 22 にマッピングしているためです。ドメインには、利用者が実際に入力する名前を指定します。どちらかを間違えると、すべてのリポジトリページに表示される clone コマンドが、それをコピーした全員に対して失敗します。セットアップ後は、両方とも app.ini[server] セクションに、SSH_PORTSSH_DOMAINROOT_URL として保存されます。

公開インスタンスでは、Web ポートをループバックアドレスだけで公開し ('127.0.0.1:3000:3000')、その前段に nginx を置いて TLS (transport layer security) を処理します。Gitea も gitea/gitea イメージから同じ方法でインストールできます。または、1 つの systemd unit と 1 つの app.ini を使用して、単一バイナリとして実行できます。2026 年 8 月時点での現在の安定版は 1.27.1 です。

可能な限り SQLite を使い続けてください。インスタンスを 1 つのプロセスと 1 つのファイルだけで構成でき、監視する追加サービスなしで再起動にも対応できます。複数のユーザーが同時に書き込む場合は、PostgreSQL の導入コストに見合います。SQLite は書き込みを直列化し、CI の長時間実行中は継続的に書き込みが発生するためです。どちらのプロジェクトも、既存のインスタンスを後から PostgreSQL に移行できます。そのため、後戻りできない選択ではありません。

Forgejo と Gitea: 実際の違い

両者の系譜は共通しています。Gitea は 2016 年に Gogs からフォークされました。2022 年後半、Gitea のドメインと商標の管理権が Gitea Ltd という企業に移りました。その後、複数のメンテナーが Codeberg とともに Forgejo を立ち上げました。Forgejo は、ドイツで登録された非営利団体である Codeberg e.V. が公開しています。また、2024 年に MIT ライセンスから GPLv3 (GNU general public license version 3) へ移行しました。Gitea は MIT ライセンスを維持しており、商業的な支援を受けて開発されています。

日常的な機能は近いものの、両者の移行経路は異なります。2025 年 1 月の Forgejo v10.0 は、Gitea のデータベースを直接利用できる最後のリリースでした。ただし、対応するのは Gitea v1.22 以前だけです。2026 年 8 月時点で Gitea は 1.27.1 であるため、現在の Gitea インスタンスを Forgejo にそのまま切り替える方法はサポートされていません。データを投入する前にどちらかを選択してください。その後に移行する場合は、エクスポートと再インポートとして扱ってください。

選択の簡単な目安を示します。ガバナンスを重視する場合、またはプロジェクトを非営利団体の下で運用したい場合は、Forgejo を選択してください。より多くの導入実績と商用サポートの選択肢を求める場合は、Gitea を選択してください。どちらもオープンに保守され、頻繁にリリースされています。Forgejo は 3 か月ごとに安定版をリリースし、毎年 LTS (long term support) リリースも提供しています。2026 年 8 月時点では、現行版は v16.0.2、LTS は v15.0.6 です。

Tier 3: GitLab が何もしなくても必要とするコスト

GitLab CE は、別の種類のソフトウェアです。1 つのインスタンスは、連携して動作する複数のサービスで構成されます。Web アプリケーションには Puma、バックグラウンドジョブには Sidekiq、データベースには PostgreSQL、インメモリデータストアには Redis、リポジトリへのアクセスには Gitaly、前段には nginx を使用します。Omnibus パッケージはこれらをまとめてインストールするため、インストールは簡単ですが、必要なメモリ量は大きくなります。

GitLab の要件ページでは、単一ノード構成の基準として 16 GB の RAM と 8 vCPU が示されています。また、メモリに制約がある環境では、下限として 8 GB が示されています。同じページでは、負荷時のスワップによってインスタンスの性能が大きく低下するため、swap を無効にするよう案内しています。これらは 2026 年 8 月時点で公開されている数値です。要件は長年にわたって増加しているため、サーバーの容量を決める前に、もう一度このページを確認してください。

この予算で、実際に利用できる機能が得られます。コンテナレジストリ、パッケージレジストリ、細かな権限設定、コンプライアンスおよび監査機能、大規模環境でテストされた CI などです。チーム内の誰も、その一覧から今四半期に必要な機能を 1 つも挙げられないなら、何も得られないまま、より大きな VPS の料金を支払うことになります。

SSH アクセスモデル: 1 つの git ユーザーと複数の鍵

ここで扱うすべての階層は、同じ方法で認証します。git という名前の Unix アカウントが 1 つあり、すべての公開鍵をそのアカウントの ~/.ssh/authorized_keys に登録します。認証に使うのは鍵です。同一行で鍵の前に指定するオプションが、認可の内容を決めます。

通常の鍵の行では、そのアカウントが実行できる操作をすべて保有者に許可します。強制コマンドを指定すると、Git に限定できます。

restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop

OpenSSH 7.2 以降で利用できる restrict は、ポートフォワーディング、エージェントフォワーディング、X11、PTY(疑似端末)の割り当てを 1 つの指定で無効にします。command= は、クライアントが要求したコマンドを、指定したコマンドに置き換えます。Git は要求を $SSH_ORIGINAL_COMMAND で送信するため、引き続き動作します。

Forge はこのファイルを自動的に作成します。これが tier 0 と tier 2 の本質的な違いです。Forgejo と Gitea は、登録済みの鍵ごとに 1 行を持つ形で authorized_keys を書き換えます。各行には、その鍵をデータベース上の ID で識別する強制コマンドが含まれます。

command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice

この強制コマンドによって、1 つの共有 Unix アカウントをユーザー単位の権限に分けられます。key-3 により Forge は接続元のユーザーを識別し、オブジェクトが転送される前に、そのユーザーがリポジトリへアクセスできるかを確認します。Forge が管理するサーバーでは、このファイルを手動で編集しないでください。ファイルはデータベースから再生成されるため、追加した行は消えます。デプロイキーも同じ仕組みで処理されます。デプロイキーは単一のリポジトリに登録する通常の SSH 鍵で、通常は読み取り専用です。アクセスチェックは sshd ではなく Forge が実行します。

上記の設定より重要な習慣が 2 つあります。1 人または 1 台につき 1 つの鍵を発行し、共有鍵は使わないでください。共有鍵を無効にすると、全員分の鍵を同時に交換する必要があるためです。また、ユーザーが離職または利用を終了した日には鍵を削除してください。そのファイルに残った古い鍵は、誰も監視していない恒久的なログイン手段になります。サーバーでの適切な SSH 鍵管理では、鍵の種類とパスフレーズを説明しています。ここでの内容にも、そのまま適用できます。サーバーが新しい場合は、リポジトリを配置する前に 新しい VPS で最初の 10 分間に行うことを実施してください。

自分の Git サーバーで GitHub Actions を実行できますか?

GitHub Actions の構文で記述したワークフローは実行できます。GitHub 自体を実行することはできません。Forgejo Actions は Forgejo v1.21 以降、デフォルトで有効になっており、各リポジトリの .forgejo/workflows からワークフローファイルを読み取ります。Gitea Actions も同じ仕組みで、.gitea/workflows を読み取ります。どちらも、runner という別のプログラムをインストールし、管理者設定にある token でインスタンスに登録する必要があります。公開されている action の多くは変更せずに実行できます。ただし、GitHub API を呼び出すものや、GitHub がホストするインフラストラクチャを前提とするものは実行できません。

2 つの点を想定してください。runner はジョブごとにコンテナを起動するため、独自のコンテナエンジンとメモリ割り当てが必要です。そのため、forge と同じ 1 GB のサーバーに配置するべきではありません。また、runner はワークフローファイルに記述された処理をそのまま実行します。Forgejo のドキュメントにも、runner はリモートコード実行を行うと明記されています。可能であれば専用のホストに配置してください。少なくとも、専用の非特権ユーザーと、1 つのリポジトリに限定した registration token を使用してください。

リポジトリを GitHub に残し、管理下のハードウェアだけで処理を実行したい場合は、別の構成になり、手順も異なります。self-hosted GitHub Actions runner は GitHub のリポジトリに接続するため、ここで説明した設定は必要ありません。離脱によって何を失うのかをまだ検討している場合は、GitHub が実際に提供するもので Git ホスティングと、その周辺のネットワークを分けて確認できます。

バックアップ: リポジトリは状態の半分にすぎません

bare リポジトリはディレクトリなので、コピーすると中身がすべてコピーされます。別のマシンから mirror clone を作成する方法は、実際のバックアップになります。既存のコピーを更新することもできます。

git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote update

これにより、すべての ref とすべてのオブジェクトが取得されます。ただし、サーバー側の hooks と description ファイルは取得されません。hooks を使用する場合は、ディレクトリのファイルレベルのコピーも保持してください。

forge は、issues、pull requests、users、keys、permissions をデータベースに保持します。リポジトリだけをコピーすると、それらはすべて失われます。両方のプロジェクトには dump command があり、データベース、リポジトリ、設定、attachments を 1 つの archive に書き出せます。

sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zip

Docker では、同じ command を container 内で実行します。configuration path は image によって異なるため、入力する前に確認してください。

docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.ini

データを所有する user として実行し、その user が書き込める directory に archive を保存します。次に、archive をサーバーの外部へコピーしてください。バックアップ対象のマシンにしか存在しないバックアップは、バックアップではないためです。復元は省略されがちな手順です。今のうちに spare box へ 1 つの dump を展開し、障害発生中ではなく、落ち着いているときに手順を確認してください。

シナリオ別の選び方

ノート PC と VPS を 1 台ずつ使い、ブラウザーでの閲覧が不要な場合は、SSH 経由の bare repository を使用します。追加のサービスは動作せず、アップグレード対象もありません。

同じ構成で、ブラウザーからコードを読んだり、コードへのリンクを共有したりする場合は、cgit を追加します。データベースは不要で、常駐プロセスも増えません。

チームで相互にコードレビューを行い、issue を管理する場合は、2 GB 以上の RAM で Forgejo または Gitea を使用します。ジョブが本格的に動き始めたら、CI runner を 2 台目のサーバーへ移します。

コンテナレジストリと監査証跡が必要で、サーバーに 16 GB の RAM を割り当てられる組織には GitLab が適しています。その容量を確保できない場合は、導入を開始しないでください。

最初の 3 段階の間で上位へ移行するのは容易です。いずれも、リポジトリがディスク上の通常の Git ディレクトリだからです。要件を満たす最も低い段階から始めてください。同じサーバー上で他に何へ容量を割り当てるべきか検討している場合は、セルフホストする価値があるサービスの候補で、同じ RAM を競合する他のサービスと Git サーバーを比較できます。

FAQ

1 GB VPS で Forgejo または Gitea を実行できますか?

小規模なチームで、SQLite を使用し、そのサーバー上で他の負荷の高い処理を実行しない場合は可能です。Gitea のドキュメントでは、小規模なチームやプロジェクトには通常 1 GB の RAM と 2 個の CPU コアで十分とされています。Forgejo は Gitea のフォークであり、必要なリソースも同程度です。このマシンに PostgreSQL や CI runner を追加しないでください。サービスが自身のログにエラーを残さず停止した場合は sudo dmesg -T | grep -i oom を実行してください。強制終了されたプロセスを示す行があれば、kernel の out-of-memory killer がプロセスを終了させています。その場合はチューニング用のフラグではなく、より大きなプランが必要です。

Forgejo と Gitea の違いは何ですか?

両者には共通するコードベースの歴史があり、機能の大部分も共通しています。Gitea は 2016 年に Gogs からフォークされました。Forgejo は、Gitea の商標の管理権が企業に移った後の 2022 年後半に Gitea からフォークされました。Forgejo はドイツの非営利団体 Codeberg e.V. によって GPLv3 で公開されています。Gitea は MIT ライセンスのままで、商業的な支援を受けています。実際の違いは移行経路です。2025 年 1 月の Forgejo v10.0 は、Gitea のデータベースを直接受け入れられる最後のリリースでした。ただし、対応するのは Gitea v1.22 以前からの移行だけです。そのため、現在の Gitea インスタンスには、サポートされたインプレース切り替え方法がありません。

自己ホスト型 Git サーバーで GitHub Actions の workflow を実行できますか?

Forgejo Actions と Gitea Actions はどちらも、GitHub Actions の YAML 構文で記述された workflow を実行します。workflow は .forgejo/workflows.gitea/workflows から読み込まれます。別の runner プログラムをインストールし、インスタンスに登録してください。公開されている多くの action は変更せずに動作しますが、GitHub API を呼び出すものは動作しません。runner はリポジトリ内の任意のコードを実行し、job ごとにコンテナを起動します。そのため、runner 専用のホストを用意するか、少なくとも専用の非特権ユーザーで実行してください。すでに forge を実行している 1 GB のサーバー上では実行しないでください。

自己ホスト型 Git サーバーをバックアップするにはどうすればよいですか?

bare repository では、別のマシンから git clone --mirror を実行すると、すべての ref と object がコピーされます。git remote update をその mirror 内で実行すると、mirror が更新されます。Forgejo または Gitea では、repository だけが状態の一部です。issue、pull request、ユーザー、key はデータベースに保存されているためです。組み込みの dump 機能である sudo -u git forgejo dump -c /etc/forgejo/app.ini を使用してください。Docker install の場合は、コンテナ内で同じ command を実行します。archive をサーバー外へコピーし、手順が機能することを確認するため、予備のマシンに一度 restore してください。

#git#self-hosting#forgejo#gitea#ssh