MAATRIX / Блог / GitLab CE на сервере: частые ошибки и решения

GitLab CE на сервере: частые ошибки и решения

MAATRIX

GitLab CE выглядит как одна установка одной пачкой — apt install gitlab-ce, подождать, открыть в браузере. На практике это десяток служб внутри одного дистрибутива (Puma, Sidekiq, PostgreSQL, Redis, Gitaly, Workhorse, Registry, Nginx), и любая из них может упасть по своей причине. Ниже — реальные проблемы, с которыми сталкиваются при развёртывании GitLab CE на собственном сервере, и рабочие решения без переустановки с нуля.

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

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

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

Сколько ресурсов реально нужно GitLab CE

Первая ошибка закладывается ещё на этапе выбора сервера. GitLab в официальной документации указывает ориентировочный минимум для CE на небольшую команду — около 4 ядер CPU и 4 ГБ RAM, но это именно нижняя граница, при которой сервис заводится, а не работает комфортно под нагрузкой. Цифры периодически меняются от версии к версии, поэтому перед установкой стоит свериться с актуальной документацией на момент разворачивания, а не с тем, что писали два года назад.

На практике 4 ГБ хватает для одного-двух разработчиков без активного CI. Как только подключаются раннеры, добавляются мержреквесты с автотестами и растёт число репозиториев — начинает душить память Sidekiq и Puma одновременно. Рабочий ориентир для небольшой команды из 5-15 человек с активным CI/CD — 8 ГБ RAM и 4 vCPU, для реестра контейнеров и крупных монорепо — больше, плюс отдельный диск под /var/opt/gitlab.

Проверить, во что реально упирается сервер, можно так:

sudo gitlab-ctl status
free -h
sudo gitlab-ctl top

gitlab-ctl top показывает потребление по каждому внутреннему сервису отдельно — обычно виновник OOM либо Puma (веб-запросы), либо Sidekiq (фоновые задачи вроде переиндексации).

OOM и зависание при первом запуске

Классика: после apt install gitlab-ce и первого gitlab-ctl reconfigure сервер зависает на 100% CPU, а потом ядро убивает процесс по OOM. Причина почти всегда одна — Omnibus-сборка по умолчанию рассчитывает количество воркеров Puma и Sidekiq исходя из числа ядер CPU, не учитывая объём RAM. На сервере с 2-4 ГБ это перебор.

Правится вручную в /etc/gitlab/gitlab.rb:

puma['worker_processes'] = 2
puma['per_worker_max_memory_mb'] = 850

sidekiq['max_concurrency'] = 10

postgresql['shared_buffers'] = "256MB"
postgresql['max_connections'] = 100

prometheus_monitoring['enable'] = false

Отключение встроенного Prometheus (prometheus_monitoring['enable'] = false) экономит заметную часть памяти на маленьких серверах — своя система мониторинга внутри GitLab на 2-4 ГБ RAM избыточна, особенно если у вас уже настроен внешний мониторинг.

После правки:

sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart

Если сервер уходит в своп в момент reconfigure — временно добавьте swap-файл, чтобы процесс просто не убился ядром, а потом уже подгоняйте конфиг под реальные ресурсы. Как правильно настроить своп под нагрузку такого рода, разобрано в статье про настройку swap и производительности.

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

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

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

gitlab-ctl reconfigure падает с ошибкой

reconfigure — это Chef-скрипт, который применяет /etc/gitlab/gitlab.rb к живой системе. Он падает по трём типичным причинам:

Синтаксическая ошибка в gitlab.rb. Файл — валидный Ruby, отсутствующая кавычка или запятая ломает весь прогон. Проверить синтаксис до применения:

sudo gitlab-ctl reconfigure --dry-run

Если dry-run недоступен в вашей версии — минимум прогоните файл через ruby -c /etc/gitlab/gitlab.rb.

Нехватка места на диске. Chef пишет временные файлы и кэш в /opt/gitlab, и если диск заполнен, reconfigure падает с невнятной ошибкой доступа, а не с прямым «нет места». Проверка:

df -h /opt /var

Что делать, если место закончилось прямо на боевом сервере, подробно расписано в статье «Закончилось место на диске VPS» — там же про безопасную очистку логов и кэшей без риска что-то сломать.

Конфликт версии Omnibus и уже накаченных данных PostgreSQL. Встроенный PostgreSQL в GitLab CE обновляется миграциями внутри reconfigure, и если между версиями образовался слишком большой скачок (например, апгрейд через 3-4 минора сразу), миграция падает на середине. Лечится только последовательным апгрейдом — об этом ниже, в разделе про обновления.

Полезная команда для диагностики любого сбоя — посмотреть живые логи всех служб разом:

sudo gitlab-ctl tail

и логи конкретной службы, если понятно, где именно рвётся:

sudo gitlab-ctl tail postgresql
sudo gitlab-ctl tail sidekiq

502 Bad Gateway и проблемы с SSL

502 после успешного reconfigure обычно значит, что встроенный Nginx поднялся, а Puma (веб-процесс Rails) — ещё нет или уже упал. Проверка:

sudo gitlab-ctl status
sudo gitlab-rails runner "puts Gitlab::Runtime.puma?"

Если Puma в статусе down — смотрите на память (см. раздел про OOM выше) или на ошибку конкретно в его логе: /var/log/gitlab/puma/puma_stderr.log.

С SSL основная ошибка — несовпадение external_url в /etc/gitlab/gitlab.rb с реальным доменом, на который смотрит браузер. GitLab жёстко привязывает внутренние ссылки, вебхуки и OAuth-редиректы к этому значению:

external_url 'https://git.example.com'

letsencrypt['enable'] = true
letsencrypt['contact_emails'] = ['admin@example.com']

Если используете встроенный Let's Encrypt через Omnibus — не ставьте параллельно свой Certbot или Nginx-прокси перед GitLab, они начинают конфликтовать за 80/443 порт и за файл сертификата. Если же перед GitLab уже стоит внешний reverse-proxy (например, для нескольких сервисов на одном сервере) — отключайте встроенный Nginx GitLab и letsencrypt, терминируйте TLS на внешнем прокси, а на GitLab пробрасывайте http с корректным заголовком X-Forwarded-Proto. Частые причины, по которым не проходит валидация Let's Encrypt в такой связке, разобраны в статье про ошибки Let's Encrypt SSL на сервере.

Container Registry не работает или не пушится

Встроенный Container Registry — отдельный HTTP-сервис на своём поддомене, и его нельзя просто «включить» без домена:

registry_external_url 'https://registry.example.com'
gitlab_rails['registry_enabled'] = true

Типичная ошибка — docker login или docker push падает с x509: certificate signed by unknown authority или no such host. Причины почти всегда:

  • поддомен registry.example.com не заведён в DNS отдельной A-записью (алиас на основной домен GitLab не подходит — нужен отдельный TLS-сертификат под этот хост);
  • забыли reconfigure после добавления registry_external_url — registry не запускается, пока Chef не применит новый конфиг;
  • Docker-демон на клиентской машине не доверяет самоподписанному сертификату (если используете не Let's Encrypt, а свой CA) — тогда нужно добавлять сертификат в /etc/docker/certs.d/registry.example.com/ca.crt на каждой машине, которая пушит образы.

Проверка, что реестр вообще жив:

sudo gitlab-ctl status registry
curl -I https://registry.example.com/v2/

Валидный ответ — 401 Unauthorized (это нормально, значит эндпоинт есть и требует авторизации), а не таймаут или Connection refused.

Бэкапы: что реально сохраняется и как восстановить

Штатный бэкап GitLab CE:

sudo gitlab-backup create

Файл падает в /var/opt/gitlab/backups/. Проблема, которую регулярно упускают: этот бэкап не включает /etc/gitlab/gitlab.rb и /etc/gitlab/gitlab-secrets.json. Без секретов восстановленный бэкап не расшифрует существующие данные (токены CI/CD, SSH-ключи раннеров, зашифрованные переменные) — они привязаны именно к этому файлу секретов. Копируйте их отдельно и регулярно:

sudo cp /etc/gitlab/gitlab.rb /etc/gitlab/gitlab-secrets.json /path/to/backup-storage/

Восстановление на новом сервере — сначала ставится та же мажорно-минорная версия GitLab, что была на источнике, потом секреты и конфиг, потом сам бэкап:

sudo gitlab-ctl stop puma
sudo gitlab-ctl stop sidekiq
sudo gitlab-backup restore BACKUP=<timestamp>
sudo gitlab-ctl reconfigure
sudo gitlab-ctl restart
sudo gitlab-rake gitlab:check SANITIZE=true

Если версия сервера-приёмника новее версии бэкапа больше чем на несколько миноров — восстановление может упасть на миграциях, аналогично проблеме с reconfigure выше. Общие принципы бэкапа и восстановления баз данных на сервере — в статье «Резервное копирование БД на сервере: частые ошибки и решения», но для GitLab всегда используйте именно gitlab-backup, а не сырой pg_dump по отдельности — штатный механизм синхронизирует базу, репозитории Git и Container Registry в одном снапшоте.

Обновление версии ломает GitLab

Самая частая причина «GitLab упал после апдейта» — попытка перескочить через несколько минорных версий одной командой apt upgrade. GitLab поддерживает миграции только последовательно, версия за версией, и если пропустить промежуточный шаг, база данных остаётся в несовместимом состоянии, а reconfigure падает на середине миграции — откатить такое просто apt downgrade не получится, нужен бэкап.

Правильный путь — свериться с официальным путём обновления GitLab под вашу текущую версию, и накатывать по одной версии за раз:

sudo apt update
sudo apt-cache madison gitlab-ce
sudo apt install gitlab-ce=<конкретная-версия>
sudo gitlab-ctl reconfigure

Перед любым апгрейдом — обязательный gitlab-backup create, это дешевле, чем восстанавливать сервер вручную из снапшота диска. И проверяйте свободное место заранее: миграции пишут временные данные, а на забитом диске сама миграция может прерваться на середине, оставив базу в промежуточном состоянии.

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

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

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

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

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

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

GitLab CE и GitLab EE — можно ли перейти обратно с Enterprise на Community?

Технически можно установить пакет gitlab-ce поверх gitlab-ee, лицензионные функции просто перестанут работать, а данные останутся. Но обратный переход официально не поддерживается как штатный сценарий — делайте это только после полного бэкапа.

Сколько диска реально нужно под GitLab с активным CI?

Помимо самих репозиториев быстро растут артефакты CI/CD и кэш раннеров — они не чистятся автоматически без настроенных политик expire_in в .gitlab-ci.yml. Ориентир по запасу места для сервера под такую нагрузку разобран в статье «Сколько дискового пространства закладывать с запасом».

Gitea вместо GitLab CE — стоит ли рассматривать для маленькой команды?

Если нужны только репозитории, issues и базовый CI без Container Registry и сложных пайплайнов — Gitea заметно легче по ресурсам. Сравнение по функциям и требованиям к серверу — в статье «Gitea против GitLab: что выгоднее и когда».

Можно ли развернуть GitLab CE в Docker вместо Omnibus-пакета?

Да, официальный образ gitlab/gitlab-ce работает через docker-compose и даёт немного более гибкий контроль над ресурсами и volume, но диагностика проблем почти идентична — те же gitlab-ctl команды работают внутри контейнера через docker exec.

Как понять, что раннер CI/CD настроен неправильно, а не сам GitLab?

Если веб-интерфейс GitLab открывается нормально, а пайплайны просто не запускаются или висят в pending — проблема почти всегда в раннере, а не в самом GitLab. Разбор типичных ошибок — в статье про GitLab CI Runner на сервере.

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

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

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