Локальный GitHub в контейнере: Forgejo, Gitea, GitLab или обычный git

Зачем сервер на своей машине

GitHub — место, где код публикуют. Сервер на своей машине нужен для работы до публикации: ветки от ИИ-агентов или от вас самих, просмотр и слияние в виде pull request в браузере, и всё это не покидает компьютер. В репозитории aredel так и смотрят ветки агентов, см. Claude Code, OpenCode и человек в одном репозитории. Как вообще устроены удалённые репозитории, push и pull, рассказано в статье GitLab и GitHub как удалённые репозитории.

Варианты

ВариантЧто получаетеЦена
Голый репозиторий на дискеудалённый репозиторий, куда можно отправлять и откуда можно забирать; ни веб-страницы, ни pull requestничего: git init --bare
Forgejoвеб-интерфейс, задачи, pull request с просмотром и слиянием; CI через Forgejo Actions с отдельным runnerпроверено здесь: образ 206 МБ, около 100 МиБ памяти в покое, SQLite внутри контейнера
Giteaпроект, от которого отделился Forgejo, с такими же возможностямипримерно как Forgejo; в 2026 году нумерация версий сменилась с 1.x на 28.x, поэтому перед закреплением тега проверьте его на Docker Hub
GitLab Community Editionполная платформа со встроенным CI и многим другимтяжёлая: руководство GitLab для машин с малым объёмом памяти просит не меньше 2 ГБ памяти плюс 1 ГБ swap на пятерых разработчиков

Голого репозитория достаточно, когда один человек забирает работу у агентов и страница просмотра никому не нужна. Для pull request на одной машине Forgejo — самый лёгкий из трёх серверов; GitLab окупается только тогда, когда нужны его CI и проектные возможности.

Запуск Forgejo в Docker

Forgejo 17.0 вышел 2026-10-15; линия долгой поддержки — 15.x. Тега latest у образа нет, поэтому версию закрепляют. Эта команда поднимает сервер только на 127.0.0.1, с данными в именованном томе, без веб-установщика и с закрытой самостоятельной регистрацией:

docker run -d --name forgejo --restart unless-stopped -p 127.0.0.1:3000:3000 -e USER_UID=1000 -e USER_GID=1000 -e FORGEJO__security__INSTALL_LOCK=true -e FORGEJO__server__ROOT_URL=http://127.0.0.1:3000/ -e FORGEJO__service__DISABLE_REGISTRATION=true -v forgejo-data:/data codeberg.org/forgejo/forgejo:17.0.0

Он ответил через шесть секунд:

curl -s http://127.0.0.1:3000/api/v1/version

{"version":"17.0.0+gitea-1.22.0"}

А страница регистрации теперь говорит:

Registration is disabled. Please contact your site administrator.

Аккаунт и токен

Первый аккаунт, администратора, создают командной строкой Forgejo внутри контейнера, от его пользователя git. С --random-password пароль печатается один раз, и Forgejo попросит новый при первом входе:

docker exec -u git forgejo forgejo admin user create --username demo --email demo@example.com --random-password --admin

New user 'demo' has been successfully created!

Для скриптов и API нужен токен доступа; --raw печатает только токен, а это пароль, и место ему в менеджере паролей:

docker exec -u git forgejo forgejo admin user generate-access-token --username demo --token-name agents --scopes all --raw

Репозиторий и первый push

Пустой репозиторий создают в веб-интерфейсе или через API:

curl -s -o /dev/null -w "%{http_code}\n" -H "Authorization: token $FORGEJO_TOKEN" -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/api/v1/user/repos -d '{"name":"site","default_branch":"main"}'

201

Добавьте его вторым удалённым репозиторием рядом с GitHub и отправьте ветки. Git спросит имя пользователя и пароль; токен подходит как пароль:

git remote add local http://127.0.0.1:3000/demo/site.git

git push local main claude/readme

To http://127.0.0.1:13000/demo/site.git * [new branch] main -> main * [new branch] claude/readme -> claude/readme

Pull request: открыть и слить

В веб-интерфейсе: New pull request, база main, сравнение claude/readme, просмотр диффа, Merge. То же самое через API, чем и пользовалась проверка:

curl -s -H "Authorization: token $FORGEJO_TOKEN" -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/api/v1/repos/demo/site/pulls -d '{"base":"main","head":"claude/readme","title":"Extends the README"}'

curl -s -H "Authorization: token $FORGEJO_TOKEN" -H "Content-Type: application/json" -X POST http://127.0.0.1:3000/api/v1/repos/demo/site/pulls/1/merge -d '{"Do":"merge"}'

Результаты, прочитанные из API: pull request 1 был открыт, единственным изменённым файлом был README.md с одной добавленной строкой, и Forgejo сообщал, что его можно сливать; после вызова слияния (HTTP 200) он стал закрыт и слит, а main на сервере начинался с:

1819d84 Merge pull request 'Extends the README' (#1) from claude/readme into main

Проверено 2026-10-23 на Forgejo 17.0.0 во временном контейнере на порту 13000 и на пустом репозитории; команды выше используют порт 3000, как в той настройке, что работает для aredel сейчас. Push выполнял человек: запреты репозитория не дают ИИ-агентам запускать git push даже на сервер на той же машине.

Ежедневная работа с ИИ-агентами

Остановить, обновить, сохранить копию, удалить

docker stop forgejo

docker start forgejo

Для обновления сначала прочитайте заметки о выпуске: новая мажорная версия может требовать ручных шагов. Затем удалите контейнер и выполните ту же команду с новым тегом; данные останутся в томе. Для резервной копии скопируйте том, например в tar-архив в текущей папке (здесь не проверялось):

docker run --rm -v forgejo-data:/data -v "$PWD":/backup debian:bookworm tar czf /backup/forgejo-data.tgz -C /data .

Чтобы удалить всё, контейнер и данные:

docker rm -f forgejo && docker volume rm forgejo-data

Чек-лист

Официальные источники:

Автор статьи: Arthur Isaev

Изображение баннера