SSD Nodes Learn 🎉 VPS від $5.50/міс
Посібники Matt ConnorВід Matt Connor · Оновлено 2026-08-13

Git-сервер на VPS: Forgejo, Gitea, cgit чи GitLab

Порівняйте 4 способи запустити self-hosted Git-сервер за обсягом RAM: bare repos через SSH, cgit, Forgejo або Gitea та GitLab. Дізнайтеся, що вмістить VPS на 1 GB.

Який self-hosted Git-сервер варто запустити

Self-hosted Git-сервер — це не один продукт, а обсяг RAM (оперативної пам’яті) на вашому VPS визначає, яку його версію можна розгорнути. Git не потребує власного daemon: bare repository і обліковий запис SSH (secure shell) вже утворюють робочий сервер на найменшому доступному VPS. Усе, що виходить за ці межі, — це web-застосунок, який ви додатково запускаєте поруч із ним. Кожен наступний рівень потребує більше пам’яті, якої може не вистачити малому VPS.

Є чотири рівні. Bare repository через SSH, без жодного додаткового процесу, що приймає з’єднання. cgit — швидкий web-інтерфейс лише для читання без бази даних. Forgejo або Gitea — повноцінна forge-платформа з обліковими записами, issues і pull requests, якій достатньо кількох сотень мегабайт. GitLab — система, для якої потрібен сервер у багато разів потужніший за інші варіанти.

Виберіть варіант відповідно до потрібних завдань, а потім порівняйте вимоги до пам’яті з параметрами тарифного плану, за який ви платите.

Скільки оперативної пам’яті насправді потрібно кожному варіанту

Лише два з цих проєктів публікують вимоги до апаратного забезпечення. Сприймайте опубліковане значення як мінімальний поріг, а не як гарантію, і виміряйте споживання у власному екземплярі після запуску за допомогою systemd-cgtop або ps -o rss= -C forgejo.

ChartRAM the projects document, official docs, August 2026
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: bare repositories і 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: bare-репозиторій через SSH

Git не має мережевого демона, який потрібно запускати. git push через SSH запускає git-receive-pack на віддаленому кінці як звичайний процес Unix, тому будь-який обліковий запис, до якого можна підключитися за ключем, уже є Git remote. Створіть окремий обліковий запис для репозиторіїв і зберігайте репозиторії поза його домашнім каталогом, оскільки в 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 створює репозиторій без робочої копії, саме такий репозиторій зберігається на сервері. Надсилання змін до репозиторію, який має робочу копію, завершується відмовою з 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_keys
git remote add origin git@vps.example.com:/srv/git/project.git
git push -u origin main

Успішне перше надсилання змін завершується повідомленням * [new branch] main -> main. Якщо операція завершується повідомленням 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)" git

git-shell приймає лише кілька команд, які Git надсилає через SSH. Тому інтерактивний вхід тепер завершується повідомленням замість запрошення командного рядка:

fatal: Interactive git shell is not enabled.
hint: ~/git-shell-commands should exist and have read and execute access.

Це весь сервер. Бази даних немає, як і вебпроцесу, який потрібно оновлювати. Ви відмовляєтеся від усіх можливостей forge: немає перегляду репозиторіїв, трекера завдань, pull request і окремих дозволів для користувачів. Кожен ключ у цьому файлі може читати й змінювати кожен репозиторій, власником якого є користувач 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/git

scan-path обходить цей каталог і перелічує всі знайдені репозиторії, тому новий bare-репозиторій з’являється без додаткової конфігурації. cache-size — це кількість кешованих сторінок. Кешування вимкнене, якщо значення дорівнює нулю. Перед додаванням рядків прочитайте вміст /etc/cgitrc, який уже встановив ваш пакет, оскільки пакет Debian і Ubuntu додає власні значення за замовчуванням.

Кожен запис показує перший рядок файлу description репозиторію, тому новий bare-репозиторій відображається як 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 Listen

root /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, означає, що socket unit не запущений або прослуховує інший шлях. Рядок systemctl show виводить фактичний шлях, який він використовує.

Перед подальшим використанням варто знати про два обмеження. cgit працює лише на читання й не має входу в систему, тому все в scan-path є публічним. Не зберігайте приватний репозиторій у цьому каталозі або встановіть HTTP basic authentication перед усім сайтом. CGI працює від імені користувача вебсервера, тому цей користувач має мати змогу перейти до /srv/git і читати кожен репозиторій. Каталог, до якого він не може увійти, відображається як порожній список, а не як помилка.

Рівень 2: Forgejo або Gitea для issues і pull requests

Forgejo і Gitea реалізують одну ідею: один бінарний файл на Go, який надає web forge з користувачами, організаціями, issues, pull requests, releases, package registry та вбудованою CI-системою. Для встановлення достатньо бінарного файла та SQLite, тому ці рішення працюють на обладнанні, на якому GitLab не запуститься. Наведений нижче Compose-файл взято з документації Forgejo, з тегом образу, указаним у ній станом на August 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.

Для публічного екземпляра опублікуйте web-порт лише на loopback-адресі ('127.0.0.1:3000:3000'), а перед ним розмістіть nginx для TLS (безпеки транспортного рівня). Gitea встановлюється так само з образу gitea/gitea або як один бінарний файл з одним unit-файлом systemd і одним app.ini; станом на August 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 році Forgejo змінила ліцензію 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, оскільки використання swap під навантаженням значно погіршує роботу екземпляра. Це опубліковані показники станом на August 2026. Вони зростали протягом років, тому перед вибором конфігурації сервера ще раз перевірте цю сторінку.

За ці ресурси ви отримуєте конкретні можливості: container registry, package registry, детальні дозволи, функції compliance й аудиту та CI, протестований у великих середовищах. Якщо ніхто у вашій команді не може назвати функцію з цього списку, яка потрібна їм цього кварталу, ви платите за потужніший VPS без практичної користі.

Модель доступу SSH: один користувач git і багато ключів

У кожному варіанті використовується однакова автентифікація. Є один Unix-акаунт із назвою git, а всі відкриті ключі додаються до ~/.ssh/authorized_keys цього акаунта. Ключ забезпечує автентифікацію. Авторизація визначається параметрами, які вказано перед ключем у тому самому рядку.

Звичайний рядок із ключем надає його власнику всі можливості цього акаунта. Примусова команда обмежує їх роботою з 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 автоматично записує цей файл. Саме це є основною відмінністю tier 0 від tier 2. Forgejo і Gitea перезаписують authorized_keys, додаючи по одному рядку для кожного зареєстрованого ключа. Кожен рядок містить примусову команду, яка ідентифікує ключ за його ідентифікатором у базі даних:

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, який користувач підключається, а forge перевіряє цього користувача щодо репозиторію до початку передавання будь-яких об’єктів. Не редагуйте цей файл вручну на сервері, яким керує forge. Файл генерується з бази даних повторно, тому ваш рядок буде видалено. Deploy keys працюють за тим самим принципом: deploy key — це звичайний SSH-ключ, зареєстрований для одного репозиторію, зазвичай лише для читання. Перевірку виконує forge, а не sshd.

Два правила важливіші за всі наведені вище параметри. Створюйте окремий ключ для кожної людини або кожної машини. Не використовуйте спільні ключі, оскільки відкликання спільного ключа означає його одночасну заміну для всіх. Видаляйте ключі в день звільнення або припинення доступу користувача. Старий ключ у цьому файлі забезпечує постійний вхід, за яким ніхто не стежить. У статті Належне керування SSH-ключами на сервері описано типи ключів і парольні фрази. Усе це без змін застосовується і тут. Якщо сервер новий, перед розміщенням на ньому репозиторіїв виконайте рекомендації зі статті Перші десять хвилин на новому VPS.

Чи можна запускати GitHub Actions на власному Git-сервері?

Ви можете запускати workflow, написані в синтаксисі GitHub Actions. Але запустити GitHub не можна. Forgejo Actions увімкнено за замовчуванням, починаючи з Forgejo v1.21, і воно читає файли workflow з .forgejo/workflows у кожному репозиторії. Gitea Actions працює так само й читає .gitea/workflows. Для обох потрібна окрема програма — runner, яку потрібно встановити та зареєструвати у вашому екземплярі за допомогою токена з налаштувань адміністратора. Багато опублікованих actions працюють без змін. Але actions, які викликають GitHub API або очікують інфраструктуру, розміщену GitHub, не працюють.

Врахуйте два наслідки. Runner запускає контейнер для кожного завдання. Тому йому потрібні container engine і власний запас оперативної пам’яті. Саме тому його не слід розміщувати на тому самому сервері з 1 GB RAM, що й forge. Runner виконує все, що вказано у файлі workflow. У документації Forgejo це сформульовано прямо: runner виконує віддалене виконання коду. Якщо можливо, розмістіть його на окремому хості. Як мінімум, використовуйте окремого непривілейованого користувача та registration token, обмежений одним репозиторієм.

Якщо ваші репозиторії залишаються на GitHub, а обчислення потрібно виконувати на обладнанні під вашим контролем, це інша конфігурація з іншими кроками: власний runner GitHub Actions підключається до репозиторію GitHub і не потребує нічого з описаного вище. Якщо ви ще оцінюєте, чого коштує перехід з GitHub, у матеріалі що насправді надає GitHub розмежовано Git-хостинг і мережу сервісів навколо нього.

Резервні копії: репозиторії містять лише частину стану

Bare-репозиторій — це каталог, тому його копіювання копіює все, що в ньому міститься. Дзеркальний клон з іншої машини — це повноцінна резервна копія, яку можна оновлювати на місці:

git clone --mirror git@vps.example.com:/srv/git/project.git
cd project.git && git remote update

Ця команда отримує всі ref і всі об’єкти. Вона не отримує серверні hooks або файл description, тому, якщо ви використовуєте hooks, також зберігайте копію каталогу на рівні файлової системи.

Forge зберігає issues, pull requests, користувачів, ключі та дозволи у своїй базі даних. Одна лише копія репозиторіїв не містить цих даних. Обидва проєкти постачають команду dump, яка записує базу даних, репозиторії, конфігурацію та вкладення в один archive:

sudo -u git forgejo dump -c /etc/forgejo/app.ini -f /var/backups/forgejo-dump.zip

У Docker та сама команда запускається всередині контейнера, а шлях до конфігурації залежить від image, тому перевірте його перед введенням команди:

docker compose exec server ls /data/gitea/conf
docker compose exec -u git server forgejo dump -c /data/gitea/conf/app.ini

Запускайте команду від імені користувача, якому належать дані, і записуйте archive до каталогу, доступного цьому користувачу для запису. Потім скопіюйте archive за межі сервера, оскільки резервна копія, яка існує лише на машині, що резервується, не є резервною копією. Відновлення — це крок, який часто пропускають: уже зараз розпакуйте один dump на запасній машині, щоб спокійно відпрацювати процедуру, а не вивчати її під час аварії.

Вибір за сценарієм

Одна людина з ноутбуком і VPS, без потреби переглядати код у браузері: bare-репозиторії через SSH. Додаткові сервіси не працюють, оновлювати нічого.

Те саме, але вам потрібно переглядати код у браузері та надсилати на нього посилання: додайте cgit. База даних не потрібна, постійно запущених процесів також немає.

Команда, яка переглядає код одне одного та відстежує завдання: Forgejo або Gitea, на сервері з 2 GB RAM або більше. Коли CI-джоби стають реальними, перенесіть runner на другий сервер.

Організація, якій потрібні реєстр контейнерів і журнали аудиту, із 16 GB RAM для сервера: GitLab. Якщо доступного обсягу менше, не запускайте його.

Перехід між першими трьома рівнями не потребує значних ресурсів, оскільки в усіх випадках репозиторії є звичайними Git-каталогами на диску. Почніть із найнижчого рівня, який вирішує ваше завдання. Якщо ви визначаєте, яким іншим сервісам варто виділити місце на тому самому сервері, короткий список сервісів, які варто розміщувати самостійно показує Git-сервер поруч з іншими сервісами, що конкурують за цей обсяг RAM.

FAQ

Чи може VPS із 1 GB запустити Forgejo або Gitea?

Так, для невеликої команди, на SQLite і без інших ресурсоємних служб на сервері. У документації Gitea зазначено, що для невеликих команд і проєктів зазвичай достатньо 1 GB RAM і 2 ядер CPU; Forgejo є форком Gitea з аналогічними вимогами. Не встановлюйте на цей сервер PostgreSQL або CI runner. Якщо сервіс зникає без помилки у власному журналі, виконайте sudo dmesg -T | grep -i oom: рядок із назвою завершеного процесу означає, що його завершив механізм kernel out of memory killer. У такому разі потрібен тариф із більшими ресурсами, а не додатковий прапорець налаштування.

У чому різниця між Forgejo і Gitea?

Вони мають спільну історію кодової бази та більшість функцій. Gitea була відгалужена від Gogs у 2016 році, а Forgejo — від Gitea наприкінці 2022 року після передання контролю над торговельною маркою Gitea компанії. Forgejo публікує Codeberg e.V., некомерційна організація з Німеччини, за ліцензією GPLv3; Gitea залишається під ліцензією MIT і має комерційну підтримку. Практична різниця полягає в можливості міграції. Forgejo v10.0, випущена в January 2025, була останнім релізом, який міг безпосередньо використовувати базу даних Gitea, і лише з Gitea v1.22 або старішої версії. Тому для поточного екземпляра Gitea підтримуваного перемикання безпосередньо на місці немає.

Чи можна запускати workflow GitHub Actions на self-hosted Git-сервері?

Forgejo Actions і Gitea Actions запускають workflow, написані в синтаксисі YAML GitHub Actions, із .forgejo/workflows і .gitea/workflows. Потрібно встановити окрему програму runner і зареєструвати її у своєму екземплярі. Багато опублікованих actions працюють без змін, але все, що викликає GitHub API, не працюватиме. Runner виконує довільний код із ваших репозиторіїв і запускає окремий контейнер для кожної job. Тому розмістіть його на окремому хості або принаймні використовуйте окремого непривілейованого користувача. Не запускайте його на сервері з 1 GB, де вже працює forge.

Як створити резервну копію self-hosted Git-сервера?

Для bare-репозиторіїв команда git clone --mirror з іншої машини копіює всі ref і object, а git remote update усередині цього mirror оновлює його. Для Forgejo або Gitea репозиторії є лише частиною стану, оскільки issues, pull requests, користувачі та ключі зберігаються в базі даних. Використовуйте вбудований dump, sudo -u git forgejo dump -c /etc/forgejo/app.ini, або ту саму команду всередині контейнера під час встановлення через Docker. Скопіюйте архів із сервера, а потім один раз відновіть його на резервній машині, щоб перевірити працездатність процедури.

#git#self-hosting#forgejo#gitea#ssh