# Runbook: перенос git-хостинга на self-hosted Gitea в Yandex Cloud

**Цель:** поднять собственный Gitea в Yandex Cloud, залить туда локальные ветки/теги (резервная
копия работы, которой сейчас нет нигде кроме одной машины) и настроить off-box зеркало.

**Дизайн:** `docs/superpowers/specs/2026-06-15-gitea-yc-migration-design-3.md`.
**Сопутствующие файлы комплекта:** `docker-compose.yml` (этот же каталог), `push-mirror-setup.md`,
`owner-checklist.md`.

**Условные обозначения исполнителя:**

- 🧑‍💼 **владелец** — нужны облачные доступы / ключи / деньги, делает только владелец;
- 📋 **по комплекту** — копипаст готовой команды, может выполнить кто угодно с доступом к серверу;
- ⚠️ **проверить** — факт не подтверждён вживую, сверить перед выполнением.

---

## Итог, который получаем

1. Виртуальная машина в Yandex Cloud с работающим Gitea по HTTPS (напр. `https://git.liderra.ru`).
2. Все локальные ветки и теги залиты в Gitea → **резервная копия есть**.
3. Push-зеркало на сторонний российский хостинг (GitVerse / GitFlic) → **второй бэкап off-box**.

> Коммиты, которых нет локально (остались на заблокированном GitHub), этим runbook'ом **не**
> спасаются — их забрать нельзя, пока доступ к GitHub не восстановлен. Спасаем то, что есть локально.

---

## Шаг 0. Предпосылки (🧑‍💼 владелец)

- Аккаунт Yandex Cloud с биллингом и каталогом (folder) проекта.
- Право создавать ВМ и сетевые правила в той же сети, где живёт боевой сервер.
- Домен/поддомен под Gitea (напр. `git.liderra.ru`) и доступ к его DNS.
- Полный чек-лист действий владельца — в `owner-checklist.md`.

---

## Шаг 1. Создать виртуальную машину (🧑‍💼 владелец)

Ориентир по размеру (⚠️ проверить актуальные цены в калькуляторе Yandex Cloud, регион
`ru-central1`):

| Параметр | Значение | Примечание |
|---|---|---|
| vCPU / RAM | 2 vCPU / 2–4 ГБ | Gitea лёгкий; старт с нижней границы |
| Диск | SSD 30–50 ГБ | репозитории + БД + запас под бэкапы/LFS |
| ОС | Ubuntu LTS (22.04/24.04) | ⚠️ проверить актуальный LTS-образ |
| Сеть | **та же сеть/folder, что и боевой сервер** | для будущего внутреннего доступа к проду (см. дизайн D2) |
| Публичный IP | да (статический) | для DNS и доступа извне |

**Контроль расходов:** начинать минимально (2 vCPU / 2 ГБ). ВМ в YC **ресайзится** и
**останавливается** (у остановленной плата в основном за диск) — ошибка размера обратима, пере-
конфигурируется без пересоздания.

⚠️ **проверить (дизайн D2):** что боевой `111.88.246.137` действительно в Yandex Cloud и достижим
по внутренней сети. На задачу бэкапа это не влияет — важно для будущего этапа канала к проду.

---

## Шаг 2. Привязать домен (🧑‍💼 владелец)

В DNS домена создать A-запись поддомена (напр. `git.liderra.ru`) → публичный IP новой ВМ.
Дождаться распространения (`ping git.liderra.ru` показывает нужный IP).

---

## Шаг 3. Установить Docker и положить конфиг (📋 по комплекту)

Зайти на ВМ по SSH под `ubuntu` и выполнить:

```bash
sudo apt-get update && sudo apt-get install -y docker.io docker-compose-plugin git
sudo systemctl enable --now docker
sudo mkdir -p /opt/gitea && cd /opt/gitea
# Скопировать сюда docker-compose.yml из комплекта (docs/ops/gitea/docker-compose.yml).
```

Перед запуском открыть `docker-compose.yml` и подставить значения вместо плейсхолдеров
(`<DOMAIN>`, `<DB_PASSWORD>` — придумать надёжный пароль БД). HTTPS поднимается автоматически
(Caddy в составе compose получает сертификат Let's Encrypt по домену из шага 2).

---

## Шаг 4. Поднять Gitea (📋 по комплекту)

```bash
cd /opt/gitea
sudo docker compose up -d
sudo docker compose ps          # все сервисы healthy/running
sudo docker compose logs -f caddy   # дождаться выдачи сертификата, затем Ctrl-C
```

Открыть `https://<DOMAIN>` в браузере — должна открыться страница установки/входа Gitea.

---

## Шаг 5. Первичная настройка Gitea (🧑‍💼 владелец)

1. На странице установки подтвердить параметры БД (уже заданы через compose), задать URL сайта =
   `https://<DOMAIN>`.
2. Создать **первого пользователя** — он станет администратором.
3. В настройках пользователя → «Применения» (Applications) создать **токен доступа** с правами на
   запись в репозитории — понадобится для заливки и зеркала. Сохранить токен надёжно (это секрет).
4. Создать организацию/пользователя-владельца и **пустой репозиторий** под проект (напр.
   `liderra/portal`). НЕ инициализировать его README — он должен быть пустым под заливку.

---

## Шаг 6. Проверить Git LFS (📋 по комплекту, на dev-машине)

В каталоге локального репозитория:

```bash
git lfs version            # установлен ли клиент LFS
grep -R "filter=lfs" .gitattributes 2>/dev/null   # использует ли репо LFS
```

- Если LFS **используется** — на стороне Gitea LFS включён по умолчанию; на шаге 7 добавить
  `git lfs push --all`.
- Если вывод пуст / LFS нет — шаг с `git lfs push` **пропустить** (неприменимо).

---

## Шаг 7. Залить локальные ветки и теги (📋 по комплекту, на dev-машине)

```bash
# В каталоге локального репозитория. <DOMAIN>, <OWNER>, <REPO>, <TOKEN> — из шага 5.
git remote add gitea https://<OWNER>:<TOKEN>@<DOMAIN>/<OWNER>/<REPO>.git
git push gitea --all          # все локальные ветки
git push gitea --tags         # все теги
git lfs push --all gitea      # ТОЛЬКО если шаг 6 показал LFS
```

Заливка **идемпотентна**: повтор не разрушает уже залитое (доливает недостающее).
⚠️ если токен виден в `git remote -v` и это нежелательно — после заливки заменить URL на чистый
(`git remote set-url gitea https://<DOMAIN>/<OWNER>/<REPO>.git`) и хранить токен в credential-хелпере.

---

## Шаг 8. Проверить, что бэкап реально лёг (📋 по комплекту)

```bash
# Сравнить число веток/тегов локально и на Gitea:
git for-each-ref --format='%(refname)' refs/heads refs/tags | wc -l
git ls-remote gitea | wc -l
```

И визуально: открыть репозиторий в веб-интерфейсе Gitea — ветки и последние коммиты на месте,
число коммитов в `main` совпадает с локальным (`git rev-list --count main`). Только после этого
считать резервную копию состоявшейся.

---

## Шаг 9. Настроить off-box зеркало (🧑‍💼 владелец + 📋)

Подробная инструкция — в `push-mirror-setup.md`. Кратко: завести аккаунт на GitVerse или GitFlic,
создать там пустой репозиторий, в Gitea (Настройки репозитория → Зеркала) добавить **push-mirror**
на него с токеном стороннего хостинга.

---

## Шаг 10. Проверить синхронизацию зеркала (📋 по комплекту)

После настройки зеркала **дождаться/запустить** первую синхронизацию и **убедиться**, что
репозиторий реально появился на стороне зеркала с теми же ветками и последними коммитами (не
только сохранилась настройка). Открыть репозиторий на GitVerse/GitFlic и сверить `main`.

---

## Откат и траблшутинг

- **Сертификат не выдаётся** — проверить, что A-запись (шаг 2) указывает на IP ВМ и порты 80/443
  открыты в сетевых правилах; смотреть `docker compose logs caddy`.
- **Полностью снести и начать заново** — `cd /opt/gitea && sudo docker compose down`; данные лежат
  в томах (см. compose) — `down -v` удалит и данные (осторожно).
- **ВМ умерла** — поднять новую по этому runbook'у и восстановить из off-box зеркала (шаг 9–10).
- **Заливка отвергнута (auth)** — проверить токен (шаг 5.3) и права на запись в репозиторий.
