Как установить и настроить GitLab CE на VPS
Когда команда вырастает из бесплатных лимитов GitHub или хочет держать код и CI/CD у себя, а не в чужом облаке, разговор быстро сводится к GitLab CE — это репозитории, issues, merge requests, CI/CD-пайплайны и реестр контейнеров в одном пакете, без ежемесячной платы за место. Ниже — рабочий маршрут установки на чистый VPS: от требований к железу до первого зелёного пайплайна, с теми граблями, которые обычно вылезают на втором часу настройки, а не в документации.
Содержание
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →Требования к серверу и подготовка
GitLab CE — не лёгкий сервис. Omnibus-сборка разворачивает сразу PostgreSQL, Redis, Puma, Sidekiq, Gitaly и встроенный Nginx, и всё это одновременно держится в памяти. По официальным рекомендациям GitLab для небольших команд (до ~20 пользователей) минимум — 4 vCPU и 4 ГБ RAM, но на практике с 4 ГБ сервер начинает подтормаживать уже при паре параллельных CI-джобов и веб-интерфейсе, открытом у нескольких разработчиков одновременно. Комфортный старт — 4 vCPU / 8 ГБ RAM, и это ориентир из практики, а не измеренный бенчмарк — у вас цифры могут отличаться в зависимости от числа проектов и активности Sidekiq-воркеров.
Что нужно подготовить заранее:
- Ubuntu 24.04 LTS или Debian 12 — Omnibus-пакет официально поддерживает оба дистрибутива;
- отдельный поддомен, например
git.example.com, с A-записью на IP сервера — GitLab жёстко привязывается кexternal_urlпри первой настройке, менять домен потом больно; - минимум 20-30 ГБ диска под систему плюс отдельное место под репозитории и артефакты CI — растёт быстро, если джобы собирают Docker-образы;
- своп-раздел на случай пиковой нагрузки Sidekiq — если вы ещё не настраивали его на сервере, это стоит сделать заранее.
Открытые порты: 80 и 443 для веба, 22 для SSH — но GitLab тоже использует 22 для git-операций по SSH, поэтому если на сервере уже есть свой SSH на 22, придётся либо вынести системный SSH на другой порт, либо перевесить GitLab SSH на нестандартный (об этом ниже).
Установка GitLab CE через Omnibus-пакет
Ставим зависимости и добавляем официальный репозиторий:
sudo apt update
sudo apt install -y curl openssh-server ca-certificates tzdata perl postfix
curl -fsSL https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
При установке Postfix спросит режим — выбирайте «Internet Site», если планируете, чтобы GitLab сам отправлял почтовые уведомления через локальный MTA; если будете настраивать внешний SMTP (Yandex, Mailgun и т.п.), можно взять «No configuration» и настроить всё через gitlab.rb.
Дальше ставим сам пакет, сразу указав будущий адрес:
sudo EXTERNAL_URL="https://git.example.com" apt install -y gitlab-ce
Установка сама вызовет gitlab-ctl reconfigure в конце — процесс собирает конфигурацию из gitlab.rb, накатывает миграции базы и поднимает все сервисы. На VPS с 4-8 ГБ RAM это занимает от 5 до 15 минут, торопиться не нужно.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНастройка gitlab.rb: домен, SSL, память
Основной файл конфигурации — /etc/gitlab/gitlab.rb. Он огромный и почти весь закомментирован, но реально нужный минимум укладывается в десяток строк:
external_url 'https://git.example.com'
# Встроенный Let's Encrypt — самый простой вариант для одиночного VPS
letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['admin@example.com']
# Явно переносим git-операции по SSH на нестандартный порт,
# если 22 занят системным SSH
gitlab_rails['gitlab_shell_ssh_port'] = 2222
# Ограничиваем аппетит Puma и Sidekiq под VPS-объём памяти
puma['worker_processes'] = 2
sidekiq['max_concurrency'] = 10
postgresql['shared_buffers'] = "256MB"
# Отключаем то, что не нужно на малом сервере
prometheus_monitoring['enable'] = false
Отключение prometheus_monitoring заметно снижает фоновую нагрузку — встроенный стек мониторинга (Prometheus, Node Exporter, Alertmanager) полезен на больших инсталляциях, но на VPS для команды из 5-15 человек чаще просто ест RAM без практической пользы. Если своя система метрик нужна — проще подключить внешний Uptime Kuma или Grafana, чем тащить полный Prometheus-стек GitLab.
После правки конфигурации всегда:
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
Reconfigure идемпотентен — его можно и нужно гонять после каждого изменения gitlab.rb, он применит только дельту.
HTTPS: встроенный Let's Encrypt или свой Nginx-прокси
Тут два рабочих пути, и выбор зависит от того, один ли GitLab живёт на сервере.
Вариант A — встроенный Nginx + Let's Encrypt (проще). Если VPS отдан целиком под GitLab, конфиг из предыдущего раздела с letsencrypt['enable'] = true — это всё, что нужно. Omnibus сам выпустит сертификат, положит его в /etc/gitlab/ssl и настроит автопродление через встроенный cron-джоб.
Вариант B — внешний Nginx как обратный прокси (если на сервере ещё что-то крутится). Тогда встроенный веб-сервер GitLab отключается, он слушает только локальный порт, а внешний Nginx проксирует на него и сам занимается TLS — это тот же паттерн, что описан в статье про настройку Nginx как reverse-proxy:
# в gitlab.rb
nginx['enable'] = false
gitlab_rails['gitlab_shell_ssh_port'] = 2222
unicorn['listen'] = '127.0.0.1'
puma['listen'] = '127.0.0.1'
puma['port'] = 8181
А внешний Nginx получает конфиг вида:
server {
listen 443 ssl http2;
server_name git.example.com;
ssl_certificate /etc/letsencrypt/live/git.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/git.example.com/privkey.pem;
client_max_body_size 500m; # иначе крупные git push будут падать
location / {
proxy_pass http://127.0.0.1:8181;
proxy_set_header Host $http_host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto https;
proxy_read_timeout 300;
}
}
Сертификат в этом случае выпускается стандартным certbot — процесс подробно разобран в статье про Let's Encrypt на VPS. Ключевой момент, который часто ломает git push больших коммитов, — client_max_body_size: значение по умолчанию (1 МБ) слишком мало для репозитория с бинарниками или крупными LFS-объектами.
Первый вход и базовая настройка
После успешного reconfigure пароль root-пользователя лежит в открытом виде:
sudo cat /etc/gitlab/initial_root_password
Файл живёт 24 часа после первой установки и потом самоуничтожается — если не успели, сбросить пароль можно через gitlab-rails console (user = User.find_by(username: 'root'); user.password = 'новый_пароль'; user.save!). Первым делом после входа под root@git.example.com:
- смените пароль на постоянный и включите 2FA для аккаунта администратора — это единственная учётка с полным доступом к серверу через веб;
- в Admin Area → Settings → Sign-up restrictions отключите открытую саморегистрацию (
Sign-up enabled), иначе любой, кто найдёт домен, сможет создать себе аккаунт; - настройте SMTP в
gitlab.rb(gitlab_rails['smtp_enable'] = trueи блок с хостом/портом/логином почтового провайдера) — без этого не будут приходить уведомления о merge request и не сработает сброс пароля по почте для остальных пользователей; - создайте группу и первый проект от имени обычного пользователя, а не root — рабочий процесс сразу пойдёт по правильным правам доступа.
Держите под рукой команду для проверки состояния сервисов — она первая, что нужно смотреть при любой странности:
sudo gitlab-ctl status
CI/CD: GitLab Runner и Container Registry
Сам GitLab CE только принимает и планирует пайплайны — выполняют джобы отдельные Runner'ы, и их лучше ставить не на том же VPS, что и сам GitLab, чтобы сборка проекта не отжирала память у веб-интерфейса. Runner устанавливается тем же принципом Omnibus-репозитория:
curl -fsSL https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh | sudo bash
sudo apt install -y gitlab-runner
sudo gitlab-runner register \
--url "https://git.example.com" \
--token "<токен_из_Settings→CI/CD→Runners>" \
--executor "docker" \
--docker-image "docker:24-dind"
Токен для регистрации Runner берётся в самом проекте или на уровне группы, в разделе Settings → CI/CD → Runners. Docker-executor — самый практичный выбор для большинства пайплайнов: каждая джоба выполняется в чистом контейнере, окружения не расползаются. Более детальная настройка Runner — параллелизм, кэш между джобами, теги для распределения нагрузки — разобрана отдельно в статье про установку GitLab CI Runner на VPS.
Встроенный Container Registry для хранения Docker-образов включается отдельным доменом (или поддоменом), потому что ему нужен собственный TLS-сертификат:
registry_external_url 'https://registry.example.com'
gitlab_rails['registry_enabled'] = true
После reconfigure пайплайн сможет пушить образы напрямую через docker login registry.example.com и переменные $CI_REGISTRY_USER / $CI_REGISTRY_PASSWORD, которые GitLab подставляет в CI-джобы автоматически.
Бэкапы и обслуживание
GitLab CE несёт полную историю кода команды, поэтому бэкап — не опция, а обязательный пункт настройки в первый же день. Штатная утилита создаёт архив с базой, репозиториями и артефактами (но не конфигами — их бэкапим отдельно):
sudo gitlab-backup create
sudo gitlab-ctl backup-etc # отдельно бэкапит /etc/gitlab (там ключи шифрования!)
Архивы по умолчанию складываются в /var/opt/gitlab/backups. Их обязательно нужно копировать за пределы сервера — на S3-совместимое хранилище, другой VPS или в отдельный бэкап-сервис, потому что локальная копия не спасает при потере самого VPS. Срок хранения и автоматическое удаление старых архивов настраиваются прямо в gitlab.rb:
gitlab_rails['backup_keep_time'] = 604800 # неделя, в секундах
и запускаются по cron:
sudo crontab -e
# 0 3 * * * /usr/bin/gitlab-backup create CRON=1
Отдельно стоит вопрос обновлений: GitLab CE выпускает мажорные версии с обязательным путём апгрейда — нельзя перепрыгнуть через несколько мажорных релизов за один apt upgrade, актуальную последовательность версий GitLab публикует в собственном Upgrade Path Tool на своём сайте перед каждым обновлением. Перед любым мажорным апгрейдом — обязательный gitlab-backup create и, в идеале, снапшот всего VPS на уровне хостинга.
Если по мере роста команды GitLab начнёт казаться избыточным для ваших задач, стоит заранее прикинуть, насколько оправдана его нагрузка на сервер по сравнению с более лёгкими альтернативами — сравнение разобрано в статье Gitea против GitLab: что выгоднее и когда.
Нужен сервер под эту задачу?
Разверните VPS MAATRIX за пару минут: NVMe, AMD EPYC, root-доступ, локации UK, США, Франция и РФ. Оплата картой РФ и по СБП.
Арендовать серверНужны сами нейросети для контента?
Генерируйте изображения, видео и озвучку нейросетями на falapi.io — десятки моделей в одном окне. Оплата картой РФ и по СБП.
Частые вопросы
Хватит ли 4 ГБ RAM для GitLab CE?
Формально сервис запустится и на 4 ГБ, но с первым же параллельным CI-пайплайном или активной работой нескольких разработчиков сервер начнёт уходить в своп. Для стабильной работы небольшой команды закладывайте 8 ГБ — это снимает большинство проблем с медленным откликом веб-интерфейса.
Можно ли перенести GitLab на другой домен после установки?
Технически да — правится external_url в gitlab.rb и перевыпускается сертификат, но все существующие клонированные репозитории у пользователей продолжат ссылаться на старый remote, и им придётся вручную поправить git remote set-url. Лучше сразу закладывать постоянный домен.
Нужен ли отдельный сервер под Runner?
Не обязательно для старта, но настоятельно рекомендуется при регулярных CI-сборках: джобы Runner могут кратковременно съедать всю доступную память и CPU, конкурируя с самим GitLab за ресурсы на одном VPS.
Как включить SSH git-операции, если порт 22 занят системным SSH?
Именно для этого в gitlab.rb есть gitlab_shell_ssh_port — переносите GitLab SSH на нестандартный порт (например, 2222) и сообщайте его пользователям в инструкции по клонированию (ssh://git@git.example.com:2222/group/project.git).
Что делать, если после reconfigure сервисы не поднимаются?
Первым делом sudo gitlab-ctl status — покажет, какой именно компонент упал. Дальше логи конкретного сервиса в /var/log/gitlab/<имя_сервиса>/current почти всегда дают прямой ответ, часто это нехватка памяти для PostgreSQL или Sidekiq.
Обсудить статью, задать вопрос или начать новую тему
Есть вопрос по этой статье, идея для обсуждения или просто хотите поделиться опытом? Сообщество MAATRIX ждёт. Для общения, пожалуйста, зарегистрируйтесь в нашем личном кабинете.
Перейти в сообщество →