MAATRIX / Блог / Как установить и настроить Forgejo на VPS

Как установить и настроить Forgejo на VPS

MAATRIX

В конце 2022 года часть команды Gitea ушла в отдельный проект после спора о том, кто и как управляет разработкой — так появился Forgejo, форк с тем же кодом, но с открытым процессом принятия решений. Для тех, кто хочет свой Git-хостинг без GitHub и без платы за место в организации, на старте разница почти незаметна — тот же лёгкий бинарник на Go, только другое название. Разберём установку с нуля: Docker Compose, HTTPS через Caddy, SSH-доступ, CI через Forgejo Actions и бэкапы, которые реально можно восстановить.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →

Почему Forgejo, а не Gitea или GitLab

Forgejo и Gitea физически произошли из одной кодовой базы, и в потреблении ресурсов вы разницы не заметите — оба кладут в память порядка 150–250 МБ в покое при нескольких активных пользователях. Разница не в производительности, а в том, кому проект подотчётен: Forgejo развивается под некоммерческой Codeberg e.V. с публичным голосованием по важным изменениям, тогда как Gitea управляется коммерческой структурой Gitea Ltd — подробнее о таком разделении и о том, зачем вообще нужен self-hosted Git, в статье Gitea против GitLab.

Если вы уже развернули Gitea и раздумываете о переезде — форматы баз и репозиториев совместимы, миграция технически возможна через дамп базы и копирование repositories/, но затевать её стоит по идейным причинам (открытость сообщества, лицензия) или ради конкретной фичи вроде встроенных Forgejo Actions. Для новой установки выбор в пользу Forgejo сегодня оправдан почти всегда.

Сравнивая с GitLab: там, где GitLab CE требует от 4 ГБ RAM и десятков процессов (Sidekiq, Redis, PostgreSQL, Puma), Forgejo обходится одним контейнером и внешней базой на выбор — SQLite для личного проекта или PostgreSQL, если команда больше 3–5 человек и есть параллельные CI-джобы.

Что подготовить на VPS до установки

Минимальные требования для комфортной работы:

РесурсМинимумКомфортно (команда 5-10 чел + Actions)
CPU1 vCPU2 vCPU
RAM512 МБ2 ГБ
Диск10 ГБ40+ ГБ (зависит от размера репозиториев)
ОСUbuntu 24.04 / Debian 12Ubuntu 24.04

Если планируете Forgejo Actions, закладывайте память с запасом: раннер поднимает отдельный процесс, а джобы часто разворачивают ещё и контейнеры под сборку.

Перед установкой понадобится:

  1. Домен с A-записью на IP сервера. Проверка: dig +short git.example.com должна вернуть тот же IP, что и curl -s ifconfig.me на сервере.
  2. Docker и Docker Compose. Если ещё не установлены — сначала базовая установка Docker, там же разбираются типовые ошибки вроде "permission denied" на /var/run/docker.sock.
  3. Открытые порты 80 и 443 для сертификата и веб-интерфейса, плюс порт для Git по SSH — учтите это в правилах фаервола (UFW или его аналог).
  4. SSH-ключ вместо пароля для входа на сам сервер — база гигиены для любого продакшен-хоста, отдельная от настройки самого Forgejo.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Установка Forgejo через Docker Compose

Официальный образ публикуется под именем codeberg.org/forgejo/forgejo. Разворачиваем с PostgreSQL — это снимает ограничения SQLite при параллельных операциях (SQLite блокирует базу на запись, что заметно при нескольких одновременных git push или активной работе Actions).

mkdir -p /opt/forgejo/{data,postgres}
cd /opt/forgejo

docker-compose.yml:

services:
  forgejo-db:
    image: postgres:16-alpine
    restart: unless-stopped
    environment:
      POSTGRES_USER: forgejo
      POSTGRES_PASSWORD: "замените-на-свой-пароль"
      POSTGRES_DB: forgejo
    volumes:
      - ./postgres:/var/lib/postgresql/data
    networks: [forgejo]

  forgejo:
    image: codeberg.org/forgejo/forgejo:9
    restart: unless-stopped
    depends_on: [forgejo-db]
    environment:
      USER_UID: 1000
      USER_GID: 1000
      FORGEJO__database__DB_TYPE: postgres
      FORGEJO__database__HOST: forgejo-db:5432
      FORGEJO__database__NAME: forgejo
      FORGEJO__database__USER: forgejo
      FORGEJO__database__PASSWD: "замените-на-свой-пароль"
      FORGEJO__server__DOMAIN: git.example.com
      FORGEJO__server__ROOT_URL: https://git.example.com/
      FORGEJO__server__SSH_DOMAIN: git.example.com
      FORGEJO__server__SSH_PORT: 2222
    volumes:
      - ./data:/data
    ports:
      - "127.0.0.1:3000:3000"
      - "2222:22"
    networks: [forgejo]

networks:
  forgejo:

Пара моментов, на которых спотыкаются на этом шаге:

  • Тег :9 фиксирует мажорную ветку — на конец августа 2026 это актуальная линия релизов, но перед запуском стоит свериться со страницей релизов на codeberg.org, номера версий двигаются быстрее статей.
  • SSH-порт контейнера 2222, а не 22, чтобы не конфликтовать с SSH-демоном самого сервера — при клонировании по SSH это придётся указывать явно (ssh://git@git.example.com:2222/user/repo.git) либо переопределять в ~/.ssh/config.
  • Веб-порт 3000 привязан только к 127.0.0.1 — наружу Forgejo будет смотреть через реверс-прокси, напрямую из интернета порт недоступен.

Запуск:

docker compose up -d
docker compose logs -f forgejo

Дождитесь строки Listen: http://0.0.0.0:3000 — сервис поднялся и накатил миграции базы.

HTTPS через Caddy и первичная настройка

Проще всего закрыть Forgejo сертификатом через Caddy — он выпускает и продлевает Let's Encrypt автоматически, без отдельного certbot и cron-задач. Конфиг под конкретно Forgejo:

/etc/caddy/Caddyfile:

git.example.com {
    reverse_proxy 127.0.0.1:3000

    request_body {
        max_size 512MB
    }
}

Директива max_size важна отдельно: по умолчанию у прокси часто стоит ограничение в единицы мегабайт, и первый же git push с бинарным файлом упадёт с 413 Request Entity Too Large. Если вместо Caddy используется Nginx, аналог — client_max_body_size 512m; в блоке server.

Перезапуск и проверка:

systemctl reload caddy
curl -I https://git.example.com

Ответ 200 OK или редирект на /user/login означает, что прокси и сертификат отработали. Дальше открываем https://git.example.com в браузере: при первом запуске Forgejo показывает установочный мастер, где параметры базы уже подставлены из переменных окружения — остаётся создать первого администратора. Первый зарегистрированный через мастер пользователь автоматически получает права администратора — не откладывайте этот шаг и не публикуйте домен в поиске раньше, чем создадите свой аккаунт.

Сразу после установки стоит отключить открытую регистрацию, если сервис не публичный: FORGEJO__service__DISABLE_REGISTRATION: true в переменных окружения compose-файла (эквивалент DISABLE_REGISTRATION = true в app.ini), иначе форму регистрации найдут боты в течение первых же дней.

SSH-доступ и клонирование репозиториев

Поскольку контейнер слушает SSH на 2222, а не на стандартном 22, есть два пути. Первый — оставить как есть и прописать алиас в ~/.ssh/config на машине разработчика:

Host git.example.com
    Port 2222
    User git

Тогда git clone git@git.example.com:user/repo.git заработает без дополнительных флагов.

Второй — пробросить порт 22 напрямую в контейнер, если системный SSH-демон сервера уже переведён на другой порт при настройке безопасности (тогда в compose меняем "2222:22" на "22:22"). Здесь важно не остаться без доступа к самому серверу при смене портов — прежде чем трогать SSH-конфиг хоста, убедитесь, что подключение по ключу уже настроено и протестировано в отдельной сессии.

Добавление ключа в Forgejo: Settings → SSH / GPG Keys → Add Key, вставляете публичный ключ (cat ~/.ssh/id_ed25519.pub). После этого ssh -T -p 2222 git@git.example.com должен ответить приветствием Forgejo с именем пользователя — подтверждение, что ключ принят и связка домен/порт/контейнер настроена верно.

Forgejo Actions: свой CI/CD без внешних сервисов

Forgejo Actions — встроенный аналог GitHub Actions с почти идентичным синтаксисом .forgejo/workflows/*.yml (для совместимости также читается .github/workflows/). Из коробки Actions выключены — нужно явно включить в конфиге и поднять хотя бы один раннер.

Включение в переменных окружения основного сервиса:

    environment:
      # ...остальные переменные как выше
      FORGEJO__actions__ENABLED: true

После docker compose up -d в веб-интерфейсе появится Site Administration → Actions → Runners с кнопкой регистрации раннера и токеном.

Сам раннер (forgejo-runner) удобно поднять отдельным сервисом в том же compose-файле:

  forgejo-runner:
    image: code.forgejo.org/forgejo/runner:6
    restart: unless-stopped
    depends_on: [forgejo]
    environment:
      FORGEJO_INSTANCE_URL: "https://git.example.com"
      FORGEJO_RUNNER_REGISTRATION_TOKEN: "токен-из-админки"
    volumes:
      - ./runner-data:/data
      - /var/run/docker.sock:/var/run/docker.sock
    networks: [forgejo]

Проброс docker.sock даёт раннеру запускать джобы в отдельных контейнерах (как это делает GitHub Actions), а не в самом раннере — так изоляция между джобами и хостом остаётся адекватной. Учтите нюанс с ресурсами: если джобы CI собирают образы или гоняют тесты с базой данных, 512 МБ RAM на весь сервер уже не хватит — для сервера с активным CI комфортнее чувствуют себя конфигурации от 2 ГБ RAM и 2 vCPU.

Бэкапы и обновление

У Forgejo есть встроенная команда дампа, которая архивирует базу, репозитории, конфиг и вложения в один файл:

docker compose exec -u 1000 forgejo forgejo dump -c /data/gitea/conf/app.ini -f /data/forgejo-dump-$(date +%F).zip

Дамп ложится внутрь volume ./data, поэтому его нужно ещё вынести за пределы сервера — иначе при потере диска потеряется и сам архив. Простой cron на хосте с ротацией за 7 дней:

0 3 * * * cd /opt/forgejo && docker compose exec -T -u 1000 forgejo forgejo dump -c /data/gitea/conf/app.ini -f /data/backup-$(date +\%F).zip && find ./data -name 'backup-*.zip' -mtime +7 -delete

Это решает ротацию на самом сервере, но не защищает от полной его потери — архивы стоит копировать во внешнее хранилище (S3-совместимое, другой сервер) через rclone или restic. Если уже настроены бэкапы других Docker-томов на этом хосте, логично применить тот же подход и к каталогу data Forgejo — см. бэкап Docker volume на VPS.

Обновление версии — замена тега образа и пересоздание контейнера:

docker compose pull forgejo
docker compose up -d forgejo

Перед обновлением на мажорную версию (например, с :8 на :9) обязательно делайте дамп — миграции схемы базы в редких случаях необратимы без отката к бэкапу, а changelog Forgejo стоит прочитать хотя бы по диагонали на предмет breaking changes.

Нужен сервер под эту задачу?

Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.

Арендовать сервер

Нужны сами нейросети для контента?

Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.

Частые вопросы

Чем Forgejo принципиально отличается от Gitea для конечного пользователя?

На уровне интерфейса и функций — почти ничем на момент установки; ключевая разница в модели управления проектом, а не в технических возможностях сервера.

Можно ли перенести существующий репозиторий с GitHub или GitLab?

Да, через Migrate Repository в веб-интерфейсе — указываете URL исходного репозитория и токен доступа, сервис клонирует историю, issues и pull request'ы (не всё переносится один в один — например, reviews GitLab переносятся с оговорками).

Нужна ли отдельная база данных или хватит SQLite?

Для одного пользователя или маленькой команды без активного CI SQLite достаточно и упрощает бэкап до копирования одного файла. Как только появляются параллельные операции записи — переходите на PostgreSQL, блокировки SQLite станут заметны в задержках.

Как ограничить создание аккаунтов только приглашёнными людьми?

DISABLE_REGISTRATION = true, а новых пользователей создавать вручную через Site Administration → Users или выдавать инвайт-ссылку, если она включена в вашей версии.

Работает ли Git LFS для больших файлов из коробки?

Да, поддерживается нативно, но убедитесь, что max_size в реверс-прокси и лимит LFS_MAX_FILE_SIZE в конфиге выставлены под реальный размер файлов, иначе крупные бинарники будут обрываться при пуше.

Обсудить статью, задать вопрос или начать новую тему

Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.

Перейти в сообщество →