Gitea サーバーのバックアップとリストア
Giteaのバックアップとリストアを、正しい方法で
Giteaのバックアップは、DB、Gitリポジトリ、アプリファイルという3つの動くパーツにまたがります。2024年以降、組み込みの gitea dump コマンドがこれらをまとめて一度に処理してくれます。

Giteaのテスト という投稿では、Giteaサーバーをインストールしました。この記事はその続きです。実際にバックアップを取り、何か問題が起きた際にどのように復元するかを説明します。
GitのワークフローやDocker管理を含む完全な開発ツールコレクションについては、開発ツール:モダンな開発ワークフローの完全ガイド をご覧ください。
Giteaを初めてセットアップする場合は、インストールの詳細については 無料のオンプレミスGitサーバーの選択 - Giteaが勝者!、セキュアなデプロイについては Apacheをリバースプロキシとして使用するGitea SSL を確認してください。
練習すべきタイミング
最悪の事態に対する予防策として、バックアップと復元の手順を練習するのは今がよいタイミングです。ディスクが壊れてからではなく、実際に必要になる前にやるべきです。
念には念を、というわけです。
データが置かれている場所
Giteaインスタンスは、同期を維持する必要がある3つのコンポーネントから構成されています。
- コード(Gitリポジトリ)
- ファイルストア(添付ファイル、アバター、LFSオブジェクト、インデクサー)
- DB(ユーザー、イシュー、PR、設定)
私たちのテスト環境では、これら全体で700MBを少し超えています。

これら3つのパーツはお互いを参照しているため、Giteaの公式ドキュメントはバックアップの一貫性について明確に述べています。バックアップの間はインスタンスを停止すべきであり、そうでなければ、マイグレーション中にコピーされたリポジトリが、データベースが認識している状態と一致しなくなる可能性があります。復元も同じ理由から、単一のトランザクションとして行われる必要があります。
簡単な方法 - gitea dump
この記事の以前のバージョンから変わった点です。pg_dump、tar、および別々のフォルダを手動で扱う代わりに、Giteaはデータベース、リポジトリ、LFSデータ、添付ファイル、設定を1つのアーカイブにまとめる単一の dump コマンドを提供します。
gitea dump -c /path/to/app.ini
これにより、gitea-dump-1610949662.zip のようなタイムスタンプ付きファイルが生成されます。内容は以下の通りです。
app.ini- 設定ファイルのコピーcustom/-custom/以下のカスタマイズdata/- 添付ファイル、アバター、LFSオブジェクト、インデクサー(DBがSQLiteの場合はそのファイルも)repos/- リポジトリディレクトリの完全なコピーgitea-db.sql- データベースのSQLダンプlog/- ログ(復元には不要)
知っておくと便利なフラグ:
--file name/-f name- 出力ファイル名(-は標準出力、scpやオブジェクトストレージへ直接パイプする際に便利)--type- 出力形式:zip(デフォルト)、tar、tar.gz、tar.xz、tar.zstなど--database/-d-gitea-db.sqlのSQL方言を強制する(sqlite3、mysql、mssql、postgres)- データベースエンジン間の移行に便利です--skip-repository/-R、--skip-lfs-data、--skip-attachment-data、--skip-package-data、--skip-log、--skip-db- ダンプを必要な部分だけに見込む--tempdir/-t- 中間ファイルをステージングする場所(デフォルトは/tmpまたは$TMPDIR)- インスタンス全体に十分な空き容量があることを確認してください
Dockerで gitea dump を実行する
ほとんどのセルフホスト環境では docker-compose 経由でGiteaを実行しているため、コマンドはコンテナ内で、git ユーザーとして、コンテナの一時ディレクトリから実行する必要があります。
cd ~/gitea-srv-local
# 実行中のコンテナ内でダンプを作成
sudo docker exec -u git -it -w /tmp gitea bash -c \
'/usr/local/bin/gitea dump -c /data/gitea/conf/app.ini'
# 生成されたzipファイルをコンテナからコピー
sudo docker cp gitea:/tmp/gitea-dump-*.zip ./gitea-backups/
-w /tmp が重要です:dump は一時作業ディレクトリに書き込み、zip化する必要があるため、書き込み権限のない場所から実行するとパーミッションエラーで失敗します。
それでは、いつものようにアーカイブをマシンから外に出します。
scp uname@gitea-srv-ip-addr:~/gitea-srv-local/gitea-backups/gitea-dump-*.zip ~/gitea-backups/
ネイティブツールでデータベースをダンプしたい場合は(gitea dump の内部にあるXORMベースのSQLダンプには復元時の既知のエッジケースがあるため、MySQL/PostgreSQLについてはGiteaの公式ドキュメントでも推奨されています)、並行して実行できます。
sudo docker exec -t gitea-srv-local_db_1 bash -c \
'pg_dump gitea -U gitea --file=/var/lib/postgresql/backups/gitea-db-$(date +%Y-%m-%d).sql'
pg_dump/pg_restore のオプションについて詳しくは PostgreSQLチートシート を、上記の docker exec/docker cp の構文に不慣れな場合は Docker Composeチートシート を参照してください。
方法 - 復元
依然として1コマンドでの復元はありません。Giteaのドキュメントも、これはファイルを元の場所に戻し、データベースダンプを復元する手動のプロセスであることを率直に述べています。ただし!リリースごとにパスやコンテナのレイアウトが変わるため、まず 公式ドキュメント を確認してください。
# 新しいgitea(バックアップと同じバージョン)をインストール/開始し、その後停止する
sudo docker-compose down
# ダンプを展開
unzip gitea-dump-1610949662.zip -d gitea-restore
cd gitea-restore
# リポジトリとデータをgiteaが使用するボリュームに復元
sudo cp -r repos/* ../gitea/git/
sudo cp -r data/* ../gitea/gitea/
sudo chown -R 1000:1000 ../gitea/git ../gitea/gitea
# giteaを起動
sudo docker-compose up -d
# データベースを復元
sudo docker exec -i gitea-srv-local_db_1 psql -U gitea gitea < gitea-db.sql
代わりに pg_dump/pg_restore でDBを個別にダンプした場合は、他のPostgresインスタンスと同じ方法でそのダンプを復元します。正確なコマンドについては PostgreSQLチートシート を参照してください。
復元後のフック再生成
異なるインストール方法(バイナリ vs Docker)や異なるパスに復元した場合、各リポジトリに組み込まれたGitフックは古いパスを指し続けています。これには以下で対処します。
sudo docker exec -u git -it gitea bash -c '/usr/local/bin/gitea admin regenerate hooks'
このステップをスキップすると、UIには明らかなエラーが表示されないまま、復元直後に push が失敗する典型的な原因になります。
復元の検証
完了と判断する前に:
- UIにログインし、ユーザー、イシュー、設定が正しく表示されることを確認します。
- 1つのリポジトリをクローンし、自明なコミットをpushしてフックが機能することを確認します。
gitea doctor check(問題があれば--fixを追加)を実行し、パスやパーミッションの不整合を早期に検出します。
単一リポジトリの復元 - restore-repo
この記事の以前のバージョンから、もう1つの本物の新機能は、リポジトリレベルのバックアップと復元用の2つのコマンドです。これは上記のインスタンス全体の dump/復元ワークフローとは別物です。サーバー全体をロールバックする代わりに、1つのプロジェクトの回復だけが必要な場合に便利です(例:誰かがリポジトリを強制削除した場合)。
dump-repo は単一のリポジトリ(および、任意で、イシュー、PR、ウィキ、他のメタデータ)をローカルディレクトリに書き出します:
gitea dump-repo \
--git_service gitea \
--clone_addr https://gitea.example.com/owner/repo.git \
--auth_token <token> \
--repo_dir /backup/repos/owner/repo \
--units wiki,issues,labels,releases,milestones,pull_requests,comments
restore-repo はその後、そのディレクトリをインスタンス内の選択したowner/repoに再生成します:
gitea restore-repo \
--repo_dir /backup/repos/owner/repo \
--owner_name owner \
--repo_name repo \
--units issues,labels,milestones,pull_requests,comments
両方の --units リストは任意です - 省略すると、サポートされているすべてが移行されます。このペアは本質的に移行ツールです(--git_service 経由でGitHub/GitLabをソースとしても動作します)が、完全な gitea dump が大げさな場合の、軽量なリポジトリ単位の代替手段としても機能します。
自動化
上記の手動手順が動作すれば、日常的なダンプとオフボックスコピーは2行のcronジョブで済みます:
# /etc/cron.d/gitea-backup
0 2 * * * root docker exec -u git -w /tmp gitea gitea dump -c /data/gitea/conf/app.ini -f - > /home/uname/gitea-backups/gitea-dump-$(date +\%F).zip 2>> /var/log/gitea-backup.log
これを保持期間のクリーンアップ(find ~/gitea-backups -mtime +14 -delete)と scp/rsync によるオフサイトコピーと組み合わせ、単一ホストの故障でバックアップまで失わないようにしてください。
トラブルシューティング
dump中のpermission denied-gitユーザーとして実行していないか、--tempdir/-wがコンテナユーザーが書き込みできないディレクトリを指しています。- 復元は成功したが
git pushが失敗する - フックが再生成されていないため、gitea admin regenerate hooksを実行してください。 - 大規模なインスタンスでのデータベース復元エラー -
gitea dumpのzipに埋め込まれたSQLよりも、ネイティブのpg_dump/mysqldumpを優先してください。大規模または特殊なスキーマでの復元時に、既知の粗い点があります。 - 新しいメジャーバージョンへの復元 -
gitea doctor check --all --fixを実行し、復元が完了したと仮定する前に、そのバージョンのリリースノートで移行手順を確認してください。
Gitコマンドのクイックリファレンスについては、GITチートシート:最も有用なGITコマンド を参照してください。