Резервное копирование и восстановление сервера Gitea

Резервное копирование и восстановление Gitea правильным способом

Содержимое страницы

Резервные копии Gitea затрагивают три подвижные части — базу данных, git-репозитории и файлы приложения — и с 2024 года встроенная команда gitea dump обрабатывает все их одним разом.

очень красивое фото открытого hdd

В статье Тестирование Gitea мы установили сервер gitea. Это продолжение: как именно создать резервную копию и, что более важно, восстановить её, когда что-то пойдёт не так.

Для полного сбора инструментов для разработчиков, включая рабочие процессы Git и управление Docker, см. Инструменты разработчика: Полное руководство по современным рабочим процессам разработки.

Если вы устанавливаете Gitea впервые, ознакомьтесь со статьёй Выбор бесплатного git-сервера для локального размещения — Gitea побеждает! для деталей установки и Gitea SSL с Apache в качестве reverse proxy для безопасного развертывания.

Когда стоит отрепетировать это

Теперь, в качестве меры предосторожности от неприятностей, — подходящее время, чтобы отрепетировать процедуру создания резервной копии и восстановления — до того, как вы действительно в этом нуждаетесь, а не после того, как выйдет из строя диск.

Лучше перестраховаться, чем сожалеть.

Где хранятся данные

Инстанс Gitea по сути состоит из трёх компонентов, которые должны оставаться синхронизированными:

  • код (git-репозитории)
  • файловое хранилище (вложения, аватары, объекты LFS, индексаторы)
  • база данных (пользователи, задачи, PR, настройки)

В нашей тестовой среде вместе они занимают чуть более 700 МБ:

использование диска gitea

Поскольку эти три части ссылаются друг на друга, собственные документация Gitea чётко указывает на согласованность резервного копирования: инстанс должен быть остановлен на время создания резервной копии, иначе репозиторий, скопированный во время миграции, может оказаться несинхронизированным с тем, что, по мнению базы данных, произошло. Восстановление, по той же причине, тоже должно происходить как одна транзакция.

Простой способ — gitea dump

Это та часть, которая изменилась с предыдущей версии данной статьи: вместо ручной манипуляции с pg_dump, tar и отдельными папками, Gitea предоставляет единственную команду dump, которая упаковывает базу данных, репозитории, данные LFS, вложения и конфигурацию в один архив.

gitea dump -c /path/to/app.ini

Это создаёт файл с меткой времени, например gitea-dump-1610949662.zip, содержащий:

  • app.ini — копия файла конфигурации
  • custom/ — пользовательские настройки в custom/
  • data/ — вложения, аватары, объекты LFS, индексаторы (и файл SQLite, если это ваша база данных)
  • repos/ — полная копия каталога репозиториев
  • gitea-db.sql — SQL-дамп базы данных
  • log/ — логи (не нужны для восстановления)

Полезные флаги, о которых стоит знать:

  • --file name / -f name — имя выходного файла (- для stdout, удобно для прямой передачи через scp или в объектное хранилище)
  • --type — формат вывода: zip (по умолчанию), tar, tar.gz, tar.xz, tar.zst и т. д.
  • --database / -d — принудительное задание SQL-диалекта в gitea-db.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) — убедитесь, что там достаточно свободного места для всего инстанса

Запуск gitea dump в Docker

Поскольку большинство self-hosted установок запускают Gitea через docker-compose, команда должна выполняться внутри контейнера, от пользователя 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 должен писать и упаковывать свой временный рабочий каталог, и запуск его в любом месте без прав на запись приведёт к ошибке доступа.

Затем, как и раньше, заберите архив с машины:

scp uname@gitea-srv-ip-addr:~/gitea-srv-local/gitea-backups/gitea-dump-*.zip ~/gitea-backups/

Если вы предпочитаете дампировать базу данных с помощью нативных инструментов (собственная документация Gitea рекомендует это для MySQL/PostgreSQL, так как SQL-дамп на базе XORM внутри gitea dump имеет известные пограничные случаи при восстановлении), вы всё ещё можете сделать это параллельно:

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'

См. Шпаргалка по PostgreSQL для дополнительных вариантов pg_dump/pg_restore, а Шпаргалка по Docker Compose, если какой-либо из синтаксиса docker exec/docker cp выше кажется вам незнакомым.

Как — Восстановление

По-прежнему нет однокомандного восстановления — документация 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, восстановите этот дамп так же, как для любого другого инстанса Postgres — см. Шпаргалка по PostgreSQL для точных команд.

Пересоздание хуков после восстановления

Если вы восстановили данные в другую систему установки (бинарный файл против Docker) или в другой путь, git-хуки, встроенные в каждый репозиторий, всё ещё будут указывать на старые пути. Исправьте это с помощью:

sudo docker exec -u git -it gitea bash -c '/usr/local/bin/gitea admin regenerate hooks'

Пропуск этого шага — классическая причина того, что push начинает работать после восстановления без очевидной ошибки в интерфейсе.

Проверка восстановления

Прежде чем считать работу выполненной:

  1. Войдите в интерфейс и подтвердите, что пользователи, задачи и настройки выглядят правильно.
  2. Клонируйте один репозиторий и отправьте простой коммит, чтобы убедиться, что хуки работают.
  3. Запустите gitea doctor check (добавьте --fix, если он укажет на что-то), чтобы заранее обнаружить несовпадения путей или прав.

Восстановление отдельного репозитория — restore-repo

Другая по-настоящему новая часть с последней версии данной статьи — это пара команд для резервного копирования и восстановления на уровне репозитория, отдельно от рабочего процесса dump/восстановления всего инстанса выше. Они полезны, когда вам нужно восстановить только один проект — например, кто-то принудительно удалил репозиторий — вместо отката всего сервера.

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 необязательны — если их опустить, будет перемещено всё поддерживаемое. По сути, эта пара является инструментом миграции (она также работает с GitHub/GitLab в качестве источника через --git_service), но прекрасно служит лёгкой альтернативой полному gitea dump на уровне отдельного репозитория, когда полное восстановление было бы избыточным.

Автоматизация

Ежедневный дамп плюс копия на другой машине — это двухстрочный 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, чтобы отказ одного хоста не уничтожил резервные копии.

Устранение неполадок

  • permission denied при выполнении dump — вы не выполняете команду от пользователя git, либо --tempdir/-w указывает на каталог, в который пользователь контейнера не может писать.
  • Восстановление удалось, но git push не работает — хуки не были пересозданы; выполните gitea admin regenerate hooks.
  • Ошибки восстановления базы данных на большом инстансе — предпочитайте нативные pg_dump/mysqldump вложенному SQL в zip-файле gitea dump; известно, что он имеет шероховатости при восстановлении для больших или необычных схем.
  • Восстановление в новую основную версию — выполните gitea doctor check --all --fix и проверьте примечания к выпуску для шагов миграции той версии, прежде чем считать восстановление завершённым.

Для быстрого справочника по командам Git, см. Шпаргалка по GIT: Наиболее полезные команды GIT.

Полезные ссылки

Подписаться

Получайте новые материалы про системы, инфраструктуру и AI engineering.