Какой self-hosted Git-сервер выбрать для VPS
Сравнение потребления RAM для Git-серверов. Узнайте, что лучше выбрать для VPS с 1 ГБ памяти: bare-репозитории, cgit, Forgejo, Gitea или тяжеловесный GitLab для команд.
Какой self-hosted Git-сервер выбрать
Self-hosted Git-сервер — это не один конкретный продукт, и объем RAM (оперативной памяти) на вашем VPS определяет, какую версию вы можете использовать. Git не требует собственного демона: «голый» (bare) репозиторий в сочетании с SSH (secure shell) аккаунтом — это уже полноценный сервер, который будет работать даже на самом слабом VPS. Всё, что выходит за рамки этого минимума, — это веб-приложение, которое вы запускаете дополнительно, и каждый следующий уровень требует объема памяти, которого может не быть на бюджетном VPS.
Существует четыре уровня. «Голый» репозиторий по SSH, не требующий запуска дополнительных сетевых служб. cgit — быстрый веб-интерфейс только для чтения, не требующий базы данных. Forgejo или Gitea — полноценная платформа с поддержкой аккаунтов, тикетов и pull requests, потребляющая несколько сотен мегабайт. GitLab — решение, требующее сервера, объем ресурсов которого в разы превышает требования остальных вариантов.
Выбирайте исходя из необходимых задач, а затем сопоставьте требования к памяти с характеристиками вашего тарифного плана.
Сколько оперативной памяти на самом деле нужно для каждого варианта
Только два из этих проектов публикуют требования к аппаратному обеспечению. Относитесь к опубликованным цифрам как к минимальному порогу, а не как к гарантии, и измеряйте потребление вашего экземпляра после запуска с помощью systemd-cgtop или ps -o rss= -C forgejo.
The data behind this chart
[
{
"label": "Gitea, small team",
"ram_gb": 1
},
{
"label": "GitLab, memory constrained",
"ram_gb": 8
},
{
"label": "GitLab, single node baseline",
"ram_gb": 16
}
]Gitea указывает 1 GB оперативной памяти и 2 ядра CPU как достаточный объем для небольших команд и проектов, а также упоминает Raspberry Pi 3 как устройство, подходящее для малых нагрузок. GitLab указывает 16 GB в качестве базового уровня для установки на одном узле и 8 GB как нижний предел для того, что на их собственной странице называется средой с ограниченным объемом памяти. Forgejo не публикует никаких требований к аппаратному обеспечению. Это форк Gitea, который ведет себя аналогичным образом, поэтому данные Gitea являются наиболее близким ориентиром из доступных.
Что это означает для VPS с 1 GB памяти: пустые репозитории и cgit поместятся с запасом, так как ни один из них не запускает резидентный сервис. Forgejo или Gitea запустятся и будут обслуживать небольшую команду при использовании SQLite, но вы будете находиться на грани документированного минимума, поэтому не запускайте PostgreSQL и CI (continuous integration) runner на этом же сервере. Если веб-интерфейс исчезает без ошибки, выполните sudo dmesg -T | grep -i oom и поищите строку наподобие Out of memory: Killed process 1181 (forgejo) — это означает, что процесс был завершен механизмом kernel out of memory killer. GitLab на сервере с 1 GB памяти — это не вопрос настройки. Он просто не будет работать.
Уровень 0: «голый» репозиторий по SSH
В Git нет сетевого демона, который нужно запускать. git push по SSH запускает git-receive-pack на удаленной стороне как обычный процесс Unix, поэтому любая учетная запись, к которой у вас есть доступ по ключу, уже является удаленным Git-репозиторием. Создайте отдельную учетную запись для репозиториев и храните их вне ее домашнего каталога, так как в Ubuntu 24.04 новые домашние каталоги имеют права 0750, и добавленный позже веб-интерфейс не сможет их прочитать.
sudo adduser --system --shell /bin/bash --gecos 'Git Version Control' \
--group --disabled-password --home /home/git git
sudo install -d -m 0755 -o git -g git /srv/git
sudo -u git git init --bare /srv/git/project.git--bare создает репозиторий без рабочей копии, что и требуется для сервера. Push в репозиторий, у которого есть рабочая копия, отклоняется с ошибкой refusing to update checked out branch: refs/heads/main — это самая распространенная ошибка на данном уровне.
Теперь добавьте ключ для этой учетной записи и выполните клонирование.
sudo -u git install -d -m 700 /home/git/.ssh
sudo -u git tee -a /home/git/.ssh/authorized_keys <<'EOF'
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptop
EOF
sudo -u git chmod 600 /home/git/.ssh/authorized_keysgit remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin mainПервый успешный push завершается сообщением * [new branch] main -> main. Если push завершается ошибкой git@vps.example.com: Permission denied (publickey), значит, аутентификация не была пройдена; в этом случае изучите лог сервера с помощью sudo journalctl -u ssh -n 20. Строка с Authentication refused: bad ownership or modes for file /home/git/.ssh/authorized_keys означает, что права доступа к файлу заданы неверно, так как sshd игнорирует файл ключа, если другие пользователи имеют права на запись в него.
Затем ограничьте доступ к оболочке (shell) для этой учетной записи.
command -v git-shell | sudo tee -a /etc/shells
sudo chsh -s "$(command -v git-shell)" gitgit-shell принимает только те немногие команды, которые Git отправляет по SSH, поэтому интерактивный вход в систему теперь будет прерываться сообщением вместо приглашения командной строки:
fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.Это весь сервер целиком. Здесь нет базы данных и нет веб-процесса, который нужно обновлять. Вы отказываетесь от всего, что предоставляет полноценная платформа для разработки: нет веб-интерфейса для просмотра кода, нет трекера задач, нет pull requests и нет разграничения прав доступа для пользователей. Каждый ключ в этом файле позволяет читать и записывать любой репозиторий, принадлежащий пользователю git.
Уровень 1: cgit предоставляет веб-интерфейс без использования базы данных
cgit — это CGI-программа (common gateway interface), написанная на C. Веб-сервер запускает её при каждом запросе, она считывает репозитории напрямую с диска и не хранит собственного состояния. В Ubuntu 24.04 она доступна в компоненте universe.
sudo apt update
sudo apt install -y cgit fcgiwrap nginx
sudo install -d -o www-data -g www-data /var/cache/cgitУкажите путь к каталогу с репозиториями в /etc/cgitrc:
root-title=Git on example.com
css=/cgit.css
logo=/cgit.png
cache-size=1000
cache-root=/var/cache/cgit
snapshots=tar.gz zip
scan-path=/srv/gitscan-path сканирует этот каталог и выводит список всех найденных репозиториев, поэтому новый «голый» (bare) репозиторий появляется в списке без дополнительной настройки. cache-size — это количество кэшируемых страниц; пока значение равно нулю, кэширование отключено. Ознакомьтесь с содержимым /etc/cgitrc перед добавлением новых строк, так как пакеты в Debian и Ubuntu уже содержат некоторые настройки по умолчанию.
Каждая запись отображает первую строку файла description репозитория, поэтому новый «голый» репозиторий будет отображаться как Unnamed repository; edit this file 'description' to name the repository.. Исправьте это для каждого репозитория:
echo 'Project X, internal tooling' | sudo -u git tee /srv/git/project.git/descriptionФайл конфигурации сайта nginx и проверка его работы
server {
listen 80;
server_name git.example.com;
root /usr/share/cgit;
try_files $uri @cgit;
location @cgit {
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /usr/lib/cgit/cgit.cgi;
fastcgi_param PATH_INFO $uri;
fastcgi_param QUERY_STRING $args;
fastcgi_param HTTP_HOST $server_name;
fastcgi_pass unix:/run/fcgiwrap.socket;
}
}sudo systemctl enable --now fcgiwrap.socket
sudo nginx -t && sudo systemctl reload nginx
systemctl show fcgiwrap.socket -p Listenroot /usr/share/cgit отдает cgit.css и cgit.png как обычные файлы, а try_files передает все остальные запросы CGI-скрипту по адресу /usr/lib/cgit/cgit.cgi. Ошибка 502, сопровождаемая записью connect() to unix:/run/fcgiwrap.socket failed (2: No such file or directory) в /var/log/nginx/error.log, означает, что сокет-юнит не запущен или слушает другой путь. Строка systemctl show выводит путь, который используется фактически.
Перед началом работы стоит учесть два ограничения. cgit работает только на чтение и не поддерживает авторизацию, поэтому всё содержимое scan-path является публичным: храните приватные репозитории вне этого каталога или настройте HTTP basic authentication для всего сайта. Поскольку CGI-скрипт выполняется от имени пользователя веб-сервера, этот пользователь должен иметь права на обход пути /srv/git и чтение каждого репозитория. Если каталог недоступен для чтения, он будет отображаться как пустой список, а не как ошибка.
Уровень 2: Forgejo или Gitea для задач и pull requests
Forgejo и Gitea основаны на одной идее: это один бинарный файл на языке Go, который предоставляет веб-интерфейс для управления репозиториями, пользователями, организациями, задачами (issues), pull requests, релизами, реестром пакетов и встроенной системой CI. Весь процесс установки сводится к бинарному файлу и базе данных SQLite, поэтому они работают на оборудовании, которое не потянет GitLab. Приведенный ниже файл Compose взят из документации Forgejo, с указанием тега образа, актуального на август 2026 года.
networks:
forgejo:
external: false
services:
server:
image: codeberg.org/forgejo/forgejo:16
container_name: forgejo
environment:
- USER_UID=1000
- USER_GID=1000
restart: always
networks:
- forgejo
volumes:
- ./forgejo:/data
- /etc/localtime:/etc/localtime:ro
ports:
- '3000:3000'
- '222:22'docker compose up -d
docker compose ps
curl -sI http://127.0.0.1:3000 | head -1Команда curl должна выводить строку статуса HTTP. До завершения первоначальной настройки это может быть редирект на /install, что также подтверждает работоспособность сервиса. Если контейнер завершает работу, частая причина кроется в правах доступа: каталог ./forgejo должен принадлежать UID (идентификатору пользователя), указанному в USER_UID, иначе процесс не сможет записывать данные в свой рабочий каталог. В Docker Compose на VPS подробно описана структура файлов и правила владения томами.
Два параметра на странице настройки определяют работоспособность URL для клонирования. Порт SSH должен быть 222, так как файл Compose пробрасывает порт 222 хоста на порт 22 контейнера, а домен должен соответствовать имени, которое пользователи будут вводить в браузере. Ошибка в любом из этих параметров приведет к тому, что на страницах всех репозиториев будут отображаться нерабочие команды для клонирования. В дальнейшем оба параметра находятся в секции [server] файла app.ini как SSH_PORT, SSH_DOMAIN и ROOT_URL.
Для публичного экземпляра публикуйте веб-порт только на адресе loopback ('127.0.0.1:3000:3000') и используйте nginx в качестве фронтенда для TLS (transport layer security). Gitea устанавливается аналогичным образом из образа gitea/gitea или как отдельный бинарный файл с одним юнитом systemd и одним файлом app.ini; текущий стабильный релиз на август 2026 года — 1.27.1.
Пока это возможно, используйте SQLite. Это позволяет ограничиться одним процессом и одним файлом, а также обеспечивает корректное восстановление после перезагрузки без необходимости контролировать дополнительные сервисы. PostgreSQL оправдывает свою сложность, когда несколько пользователей пишут в базу одновременно, так как SQLite сериализует операции записи, а длительные процессы CI выполняют запись постоянно. Оба проекта позволяют перенести существующий экземпляр на PostgreSQL позже, поэтому это решение не является окончательным.
Forgejo или Gitea: в чем реальные различия
У них общая история. Gitea отделилась от Gogs в 2016 году. В конце 2022 года контроль над доменом и торговой маркой Gitea перешел к компании Gitea Ltd, после чего несколько сопровождающих вместе с Codeberg запустили проект Forgejo. Forgejo публикуется некоммерческой ассоциацией Codeberg e.V., зарегистрированной в Германии, и в 2024 году проект перешел с лицензии MIT на GPLv3 (GNU general public license version 3). Gitea сохраняет лицензию MIT и развивается при коммерческой поддержке.
В повседневной работе наборы функций близки. Однако путь миграции между ними сложен. Forgejo v10.0, выпущенная в январе 2025 года, была последним релизом, способным напрямую работать с базой данных Gitea, причем только версии Gitea v1.22 или старше. По состоянию на август 2026 года Gitea имеет версию 1.27.1, поэтому для актуального экземпляра Gitea не существует поддерживаемого способа перехода на Forgejo «на месте». Выберите решение до того, как наполните его данными, и рассматривайте любой последующий перенос как экспорт и повторный импорт.
Краткое правило для выбора. Если для вас важно управление проектом или вы хотите, чтобы он оставался некоммерческим, используйте Forgejo. Если вам нужна более широкая база установок и возможность получения коммерческой поддержки, используйте Gitea. Оба проекта развиваются открыто и часто выпускают обновления: Forgejo выпускает стабильный релиз каждые три месяца и один LTS-релиз (long term support) в год; по состоянию на август 2026 года актуальными являются v16.0.2 и LTS-версия v15.0.6.
Уровень 3: стоимость GitLab до начала работы
GitLab CE относится к другому классу программного обеспечения. Один экземпляр представляет собой набор взаимодействующих сервисов: Puma для веб-приложения, Sidekiq для фоновых задач, PostgreSQL, Redis, Gitaly для доступа к репозиториям и nginx на фронтенде. Пакет Omnibus устанавливает их вместе, что упрощает инсталляцию, но устанавливает высокий порог потребления оперативной памяти.
На странице системных требований GitLab указано, что для установки на одном узле базовым уровнем являются 16 GB RAM и 8 vCPU, при этом 8 GB упоминаются как нижний предел для сред с ограниченными ресурсами. Та же страница рекомендует отключить swap, так как использование подкачки под нагрузкой критически снижает производительность экземпляра. Это официальные цифры по состоянию на август 2026 года, и с годами они только растут, поэтому перед выбором размера сервера ознакомьтесь с этой страницей повторно.
За этот бюджет вы получаете реальные инструменты: реестр контейнеров, реестр пакетов, гибкую систему прав доступа, функции комплаенса и аудита, а также CI, протестированный в масштабах крупных проектов. Если никто в вашей команде не может назвать ничего из этого списка, что им необходимо в текущем квартале, вы просто оплачиваете более дорогой VPS, не получая взамен никакой пользы.
Модель доступа по SSH: один пользователь git и множество ключей
На каждом уровне аутентификация происходит одинаково. Существует одна Unix-учетная запись с именем git, и все открытые ключи добавляются в файл ~/.ssh/authorized_keys этой учетной записи. Аутентификация выполняется с помощью ключа. Авторизация определяется параметрами, которые вы указываете перед ключом в той же строке.
Обычная строка с ключом предоставляет владельцу все права этой учетной записи. Принудительная команда (forced command) ограничивает их только Git:
restrict,command="git-shell -c \"$SSH_ORIGINAL_COMMAND\"" ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere alice@laptopПараметр restrict, доступный начиная с OpenSSH 7.2, отключает перенаправление портов, перенаправление агента, X11 и выделение PTY (псевдотерминала) одной командой. command= заменяет любой запрос клиента на указанную вами команду, при этом Git продолжает работать, так как он отправляет свой запрос в $SSH_ORIGINAL_COMMAND.
Система управления репозиториями (forge) записывает этот файл за вас, и в этом заключается основное различие между уровнем 0 и уровнем 2. Forgejo и Gitea перезаписывают authorized_keys, добавляя по одной строке на каждый зарегистрированный ключ, где каждая строка содержит принудительную команду, идентифицирующую ключ по его ID в базе данных:
command="/usr/local/bin/forgejo --config=/etc/forgejo/app.ini serv key-3",no-port-forwarding,no-x11-forwarding,no-agent-forwarding,no-pty ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIexamplekeyhere aliceЭта принудительная команда позволяет превратить одну общую Unix-учетную запись в систему с индивидуальными правами доступа: key-3 сообщает системе, какой пользователь подключается, и она проверяет права этого пользователя в отношении репозитория до начала передачи каких-либо объектов. Не редактируйте этот файл вручную на сервере, управляемом через forge, так как он перезаписывается из базы данных, и ваша строка будет удалена. Ключи развертывания (deploy keys) работают по тому же механизму: ключ развертывания — это обычный SSH-ключ, зарегистрированный для одного конкретного репозитория (обычно только для чтения), при этом проверка выполняется не в sshd, а в самой системе управления репозиториями.
Две привычки важнее, чем любая из описанных выше настроек. Выдавайте по одному ключу на человека или на машину, никогда не используйте общие ключи, так как отзыв общего ключа потребует его замены для всех пользователей сразу. Удаляйте ключи в день увольнения сотрудника, так как старый ключ в этом файле — это постоянный доступ, за которым никто не следит. В статье Грамотное управление SSH-ключами на сервере рассматриваются типы ключей и парольные фразы, и все эти рекомендации применимы здесь в полном объеме. Если сервер новый, перед размещением на нем репозиториев стоит ознакомиться с руководством первые десять минут на новом VPS.
Можно ли запускать GitHub Actions на собственном Git-сервере?
Вы можете запускать рабочие процессы (workflows), написанные с использованием синтаксиса GitHub Actions. Запустить сам GitHub нельзя. В Forgejo поддержка Forgejo Actions включена по умолчанию начиная с версии v1.21; система считывает файлы рабочих процессов из .forgejo/workflows в каждом репозитории. Gitea Actions работает аналогичным образом и считывает .gitea/workflows. Для обоих решений требуется дополнительная программа — runner, которую необходимо установить и зарегистрировать в вашем экземпляре с помощью токена из настроек администратора. Многие опубликованные действия (actions) работают без изменений; однако всё, что обращается к GitHub API или ожидает инфраструктуру, предоставляемую GitHub, работать не будет.
Учтите два последствия. Runner запускает контейнер для каждой задачи, поэтому ему требуется система контейнеризации и собственный запас оперативной памяти; именно поэтому его не следует размещать на том же сервере с 1 ГБ ОЗУ, где работает сама платформа. Кроме того, runner выполняет всё, что указано в файле рабочего процесса, о чём в документации Forgejo сказано прямо: runner выполняет удалённое исполнение кода (RCE). По возможности выделите для него отдельный хост или, как минимум, отдельного непривилегированного пользователя и токен регистрации, ограниченный одним репозиторием.
Если ваши репозитории остаются на GitHub, а вы хотите использовать для вычислений только собственное оборудование, это другая конфигурация с иными шагами: self-hosted GitHub Actions runner подключается к репозиторию на GitHub и не требует ничего из вышеперечисленного. Если вы всё ещё оцениваете стоимость перехода, статья что на самом деле дает вам GitHub поможет отделить Git-хостинг от сопутствующей сетевой инфраструктуры.
Резервное копирование: репозитории — это лишь половина состояния
Bare-репозиторий — это обычный каталог, поэтому его копирование сохраняет все содержимое. Mirror-клон с другого сервера является полноценной резервной копией, которую можно обновлять на месте:
git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote updateЭта команда загружает все ссылки и объекты. Она не копирует серверные хуки или файл description, поэтому, если вы используете хуки, сохраняйте также копию каталога на уровне файловой системы.
Системы управления репозиториями (forges) хранят тикеты, pull requests, пользователей, ключи и права доступа в своей базе данных, поэтому копирование одних лишь репозиториев приводит к потере этих данных. Оба проекта предоставляют команду для создания дампа, которая записывает базу данных, репозитории, конфигурацию и вложения в один архив:
sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zipВ Docker эта же команда выполняется внутри контейнера, а путь к конфигурации зависит от образа, поэтому уточните его перед вводом:
docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.iniЗапускайте команду от имени пользователя, которому принадлежат данные, и сохраняйте архив в каталог, доступный этому пользователю для записи. Затем скопируйте архив с сервера, так как резервная копия, существующая только на самом сервере, не является резервной копией. Восстановление — это этап, который часто пропускают: распакуйте один дамп на запасной машине прямо сейчас, чтобы изучить процедуру в спокойной обстановке, а не во время аварии.
Выбор по сценарию
Один пользователь с ноутбуком и VPS, просмотр через браузер не требуется: используйте bare-репозитории по SSH. Дополнительные сервисы не запускаются, обновлять нечего.
То же самое, но вы хотите просматривать код в браузере и отправлять на него ссылки: добавьте cgit. База данных по-прежнему не нужна, резидентные процессы отсутствуют.
Команда, которая проводит ревью кода и отслеживает задачи: Forgejo или Gitea, требуется от 2 GB RAM. Перенесите CI runner на отдельный сервер, когда нагрузка от задач станет ощутимой.
Организация, которой нужен реестр контейнеров и аудит действий, при наличии 16 GB RAM на сервере: GitLab. При меньшем объеме памяти развертывание не рекомендуется.
Переход между первыми тремя уровнями выполняется легко, так как во всех них репозитории представляют собой обычные Git-директории на диске. Начинайте с минимального уровня, который решает вашу задачу. Если вы определяете, какие еще сервисы разместить на этом же сервере, краткий список того, что стоит хостить самостоятельно поможет расположить Git-сервер рядом с другими приложениями, конкурирующими за оперативную память.
FAQ
Может ли VPS с 1 ГБ ОЗУ запустить Forgejo или Gitea?
Да, для небольшой команды при использовании SQLite и отсутствии других ресурсоемких приложений. Документация Gitea указывает, что 1 ГБ ОЗУ и 2 ядра CPU обычно достаточно для небольших команд и проектов; Forgejo — это форк Gitea с аналогичными требованиями. Не устанавливайте на такой сервер PostgreSQL или CI-раннер. Если сервис исчезает без записей в собственном логе, выполните sudo dmesg -T | grep -i oom: строка с названием процесса означает, что его завершил OOM killer ядра. В этом случае поможет только переход на более мощный тариф, а не настройка флагов.
В чем разница между Forgejo и Gitea?
У них общая история кодовой базы и большинство функций. Gitea отделилась от Gogs в 2016 году, а Forgejo отделилась от Gitea в конце 2022 года, после того как контроль над торговой маркой Gitea перешел к коммерческой компании. Forgejo выпускается некоммерческой организацией Codeberg e.V. из Германии под лицензией GPLv3; Gitea остается под лицензией MIT при коммерческой поддержке. Практическое различие заключается в пути миграции. Forgejo v10.0, вышедшая в январе 2025 года, стала последним релизом, способным напрямую использовать базу данных Gitea (только версий Gitea v1.22 и старше), поэтому для актуальных инстансов Gitea прямого поддерживаемого перехода не существует.
Можно ли запускать GitHub Actions на собственном Git-сервере?
Forgejo Actions и Gitea Actions выполняют рабочие процессы, написанные на синтаксисе YAML для GitHub Actions, которые считываются из .forgejo/workflows и .gitea/workflows. Вам необходимо установить отдельную программу-раннер и зарегистрировать её в своем инстансе. Многие опубликованные экшены работают без изменений, однако те, что обращаются к API GitHub, работать не будут. Раннер выполняет произвольный код из ваших репозиториев и запускает по одному контейнеру на задачу, поэтому выделите под него отдельный хост или хотя бы отдельного непривилегированного пользователя. Не запускайте его на сервере с 1 ГБ ОЗУ, где уже работает сам Git-сервер.
Как создать резервную копию собственного Git-сервера?
Для «голых» (bare) репозиториев команда git clone --mirror с другого компьютера копирует все ссылки и объекты, а git remote update внутри этого зеркала обновляет их. Для Forgejo или Gitea репозитории — это лишь часть состояния, так как тикеты, pull requests, пользователи и ключи хранятся в базе данных. Используйте встроенную утилиту дампа sudo -u git forgejo dump -c /etc/forgejo/app.ini (или ту же команду внутри контейнера при Docker-установке). Скопируйте архив с сервера и хотя бы раз выполните восстановление на резервной машине, чтобы убедиться в работоспособности процедуры.