mirror of
https://gitverse.ru/kpa39l/git-forge-management.git
synced 2026-09-29 09:15:05 +00:00
89 lines
6.5 KiB
Markdown
89 lines
6.5 KiB
Markdown
# Gitea pull-mirror из GitVerse — сессия 2026-08-30
|
||
|
||
Цель: зеркалировать репозиторий с gitverse.ru в локальный Gitea для
|
||
катастрофоустойчивости (на случай поломки bigbox).
|
||
|
||
## Контекст
|
||
- Gitea 1.26.2 (docker, /opt/gitea.nixg.ru), API http://127.0.0.1:3000/api/v1, домен gitea.nixg.ru.
|
||
- GitVerse: только SSH (`git@gitverse.ru:kpa39l/<repo>.git`), REST-API не открыт анонимно,
|
||
https-клон требует PAT (которого нет). SSH-ключ ~/.ssh/gitverse аутентифицирует как kpa39l.
|
||
- Стек gitea: gitea-db (postgres), gitea-redis, gitea, act-runner.
|
||
|
||
## Что РАБОТАЕТ (проверено)
|
||
|
||
### 1. Токен Gitea API без пароля (CLI от имени git)
|
||
Gitea в docker НЕ запускается от root: `docker exec gitea gitea ...` падает с
|
||
"Gitea is not supposed to be run as root". Но есть системный пользователь `git` (uid 1000):
|
||
```
|
||
docker exec -u 1000 gitea gitea admin user list
|
||
docker exec -u 1000 gitea gitea admin user generate-access-token \
|
||
--username estorozhenko --token-name monitoring-mirror \
|
||
--scopes "read:repository,write:repository,read:user,write:user"
|
||
# → "Access token was successfully created: <token>"
|
||
```
|
||
Это обходит неизвестный пароль пользователя целиком.
|
||
|
||
### 2. Дать контейнеру gitea SSH-ключ для внешнего git-хоста
|
||
Volume gitea: `/opt/gitea.nixg.ru/gitea -> /data`. Ключ кладётся в home пользователя git:
|
||
```
|
||
mkdir -p /opt/gitea.nixg.ru/gitea/git/.ssh
|
||
cp ~/.ssh/gitverse /opt/gitea.nixg.ru/gitea/git/.ssh/id_rsa
|
||
chown -R 1000:1000 /opt/gitea.nixg.ru/gitea/git/.ssh && chmod 600 .../id_rsa
|
||
docker exec -u 1000 gitea ssh -o BatchMode=yes -T git@gitverse.ru
|
||
# → "Hi there, kpa39l! You've successfully authenticated..."
|
||
```
|
||
Gitea зеркалит от имени владельца SSH-ключа (kpa39l).
|
||
|
||
### 3. Разрешить SSH-протокол для миграций
|
||
По умолчанию Gitea отклоняет SSH в migrate. В docker-compose gitea добавить:
|
||
```
|
||
- GITEA__service__MIGRATIONS_ALLOWED_PROTOCOLS=ssh,git,http,https
|
||
```
|
||
Затем пересоздать КОНТЕЙНЕР (env-переменные пишутся в app.ini при старте):
|
||
`docker compose up -d --force-recreate gitea` (простой `restart`/`up -d` может не перечитать).
|
||
|
||
## РАБОЧИЙ РЕЦЕПТ: HTTPS + oauth2 PAT (проверено 2026-08-30, 13 репо мигрировано)
|
||
|
||
Штатный migrate API работает, если clone_addr — **https с PAT gitverse**:
|
||
```
|
||
git ls-remote "https://oauth2:<PAT>@gitverse.ru/kpa39l/<repo>.git" HEAD # тест PAT
|
||
curl -X POST http://127.0.0.1:3000/api/v1/repos/migrate \
|
||
-H "Authorization: token <GITEA_TOKEN>" -H "Content-Type: application/json" \
|
||
-d '{"clone_addr":"https://oauth2:<PAT>@gitverse.ru/kpa39l/<repo>.git",
|
||
"repo_name":"<repo>","repo_owner":"estorozhenko","service":"git",
|
||
"mirror":true,"mirror_interval":"8h"}'
|
||
# 201 = создан; затем POST /api/v1/repos/<owner>/<repo>/mirror-sync (200 = принято)
|
||
```
|
||
- PAT gitverse лежит в URL уже существующего mirror: `docker exec gitea cat /data/git/repositories/estorozhenko/monitoring.git/config`
|
||
→ `https://oauth2:<GITVERSE_PAT>@gitverse.ru/kpa39l/monitoring.git` (значение — из `/opt/hermes/.hermes/secrets/git-tokens.env`)
|
||
- Проверка синхронизации: `git ls-remote git@gitverse.ru:kpa39l/<repo>.git HEAD` vs
|
||
`docker exec gitea git --git-dir=/data/git/repositories/estorozhenko/<repo>.git rev-parse HEAD`.
|
||
- PAT gitverse в URL уже существующего mirror: `docker exec gitea cat /data/git/repositories/estorozhenko/<существующий-repo>.git/config`
|
||
→ `https://oauth2:<GITVERSE_PAT>@gitverse.ru/kpa39l/<repo>.git` (токен в secrets)
|
||
- Gitea-токен без пароля: `docker exec -u 1000 gitea gitea admin user generate-access-token
|
||
--username estorozhenko --token-name X --scopes "read:repository,write:repository,read:user,write:user" --raw`
|
||
|
||
## НЕ РАБОТАЕТ / НЕ РЕШЕНО (проверено, потрачено много шагов)
|
||
- `POST /api/v1/repos/migrate` с `clone_addr: "git@host:path"` → 422 "the provided url is invalid".
|
||
- `POST /api/v1/repos/migrate` с `clone_addr: "ssh://git@host/path"` → 422
|
||
"the provided url protocol is not allowed" — даже после добавления ssh в
|
||
MIGRATIONS_ALLOWED_PROTOCOLS и --force-recreate. Это РАСХОЖДЕНИЕ: конфиг в app.ini
|
||
показывает `ssh,git,http,https`, но migrate всё равно режет. Дальнейшее копание в
|
||
бинаре (strings), swagger, UI-форме `/repo/migrate` (требует сессионную cookie, не токен)
|
||
успеха не дало. ВАЖНО: признать тупик и не листать это заново вслепую.
|
||
Вывод: для pull-mirror использовать HTTPS+PAT (см. выше), ssh:// не трогать.
|
||
- `POST /user/repos` с полями mirror/clone_addr — НЕ создаёт пулл-миро: CreateRepoOption
|
||
таких полей не имеет, репозиторий создаётся обычным (mirror=False, empty=True).
|
||
- Пароль пользователя gitea неизвестен — Basic auth в API не работает.
|
||
|
||
## Обходные пути, проверенные частично
|
||
- Локальная копия через git-remote: создать обычный repo в gitea, добавить в его bare
|
||
remote на gitverse и гонять `git fetch` по cron (вместо штатного mirror-механизма).
|
||
Надёжный, уродливый, но не требует migrate API. НЕ доведён до конца в сессии.
|
||
- PAT GitVerse по https — если у пользователя появится, migrate с
|
||
`https://<token>@gitverse.ru/...` должен сработать штатно.
|
||
|
||
## Правило для агента
|
||
Если `POST /repos/migrate` с ssh:// вернул 422 протокол — НЕ перезапускать gitea ещё раз
|
||
и не копать strings: сообщить о блокаде и предложить обходной путь (локальный remote+cron
|
||
или PAT). Повторение уже проверенных тупиков — потеря времени. |