GitLab self-hosted для малой команды разработки: установка, CI/CD и миграция с GitHub
Привет! Я Евгений Семёнов, директор ITFresh. С 2022 года мы видим, как доступ к GitHub для российских компаний превратился в настоящую головную боль. То аккаунты наших клиентов блокируются, то CI/CD падает в самый неподходящий момент, а про санкционные риски и говорить нечего. Неудивительно, что ко мне всё чаще приходят с одним и тем же вопросом: «Евгений, нам нужен свой GitLab на своём сервере!» Если у вас команда из 10-30 разработчиков, эту проблему мы решаем буквально за пару недель. Стоимость? Около 100 тысяч рублей. В этой статье я поделюсь нашим опытом: расскажу, как собрать GitLab под ключ, сколько будет стоить его дальнейшая поддержка и к каким нюансам нужно быть готовым.
Зачем свой GitLab
Три причины:
- Независимость. Исходный код — главный актив разработческой компании. Держать его на чужом сервере в зависимости от чужих политик — риск.
- Стоимость. GitHub Team — от 4$ за пользователя/мес, Enterprise — 21$. Для 25 разработчиков это 1200-6300$/год (~100-550 тыс руб). Свой GitLab CE — бесплатный.
- Интеграция. С корпоративным SSO (Keycloak), внутренними сервисами, Jira-аналогами, CI раннерами на своих мощностях.
Какую редакцию выбрать
| Edition | Цена | Фишки | Для кого |
|---|---|---|---|
| CE (Community) | Бесплатно | Git, MR, Issues, CI/CD, Registry, Pages | Команды до 50 разработчиков |
| EE Premium | $29/user/мес | SAML SSO, Merge approvals, Portfolio | Команды 50+, формальные процессы |
| EE Ultimate | $99/user/мес | SAST/DAST/DEPs/Fuzzing сканеры, Compliance | Enterprise с требованиями security |
Для наших клиентов из малого и среднего бизнеса (МСБ) версии GitLab CE обычно хватает с лихвой. Серьёзно, там есть всё необходимое: двухфакторная аутентификация (2FA), единый вход через OIDC/SAML (SSO), и даже approvals для мерж-реквестов, которые можно настроить прямо через Push Rules. А вот о версии Ultimate стоит задуматься, только если вам кровь из носу нужна автоматическая проверка security-уязвимостей на самом высоком, compliance-уровне.
Установка GitLab CE
GitLab предлагает несколько вариантов установки: Omnibus (это когда всё в одном пакете), стандартный docker-образ или Helm chart для Kubernetes. На практике, если у вас команда до 50 человек, мы обычно ставим Omnibus на Debian 12. Это самый простой и надёжный путь.
# Добавляем репозиторий
curl -sS https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh | sudo bash
# Устанавливаем
EXTERNAL_URL="https://git.example.ru" apt install gitlab-ce
# После установки — первый вход через reset password:
gitlab-rake "gitlab:password:reset[root]"
# Вводите новый пароль
Сертификат Let's Encrypt Omnibus настраивает сам, если в конфиге указан https URL и 80/443 порты свободны. Дальше редактируем /etc/gitlab/gitlab.rb:
# Главные настройки
external_url 'https://git.example.ru'
gitlab_rails['smtp_enable'] = true
gitlab_rails['smtp_address'] = "mail.example.ru"
gitlab_rails['smtp_port'] = 587
gitlab_rails['smtp_user_name'] = "gitlab@example.ru"
gitlab_rails['smtp_password'] = "[...]"
# Backup
gitlab_rails['backup_path'] = "/var/opt/gitlab/backups"
gitlab_rails['backup_keep_time'] = 604800 # 7 дней
# Registry для Docker-образов
registry_external_url 'https://registry.example.ru'
# Применить
gitlab-ctl reconfigure
GitLab Runner — обязательно отдельно
А вот типичная ошибка, которую многие допускают: запускать GitLab Runner прямо на одном сервере с самим GitLab. Делать так не советуем! Стоит запустить хоть один тяжёлый пайплайн, как он тут же съест всю оперативку и процессор, а ваш сервер GitLab просто «ляжет».
Как мы делаем правильно? Настраиваем runner на отдельной виртуальной машине. Вот наша стандартная конфигурация: Debian 12, 2 vCPU и 4 ГБ оперативной памяти.
# Установка
curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | bash
apt install gitlab-runner
# Регистрация
gitlab-runner register \
--url https://git.example.ru \
--registration-token abc123def456 \
--executor docker \
--docker-image alpine:latest \
--description "docker-runner-01" \
--tag-list "docker,linux"
Для параллельных сборок — параметр concurrent = 4 в /etc/gitlab-runner/config.toml. Несколько runner-ов с разными tags:
docker— для контейнерных сборок.linux-native— для сборок без Docker (быстрее для простых задач).windows— runner на Windows Server для .NET-проектов.gpu— runner с GPU для ML-пайплайнов.
Миграция с GitHub
Хорошая новость: GitLab умеет импортировать данные напрямую, используя GitHub Personal Access Token.
# В GitLab: Admin → Settings → General → Import and export settings
# Включить: GitHub
# Пользователь: New Project → Import → GitHub
# Вставляет PAT с правами repo + admin:org + read:user
# Выбирает проекты для импорта
Что переносится:
- Репозитории со всей историей коммитов.
- Все Issues — открытые, закрытые, а также комментарии к ним — переносятся без проблем.
- Pull requests → Merge requests.
- Milestones.
- Labels.
- Wiki (если есть).
- Releases.
Что НЕ переносится:
- GitHub Actions — нужно переписать как
.gitlab-ci.yml. - А вот с Secrets придётся немного поработать вручную: их нужно будет перенести в GitLab Settings, затем в CI/CD и далее в Variables.
- Deploy keys — перенести вручную.
- Что касается Projects boards, их придётся настроить заново уже в GitLab Boards.
Базовый .gitlab-ci.yml
Пример для typical Python-проекта:
stages:
- lint
- test
- build
- deploy
variables:
PIP_CACHE_DIR: "$CI_PROJECT_DIR/.pip-cache"
cache:
paths:
- .pip-cache/
lint:
stage: lint
image: python:3.12
script:
- pip install ruff mypy
- ruff check .
- mypy .
only:
- merge_requests
- main
test:
stage: test
image: python:3.12
services:
- postgres:16
variables:
POSTGRES_DB: test
POSTGRES_PASSWORD: testpass
script:
- pip install -r requirements.txt -r requirements-dev.txt
- pytest --cov=./ --cov-report=xml
coverage: '/TOTAL.*\s+(\d+%)$/'
build:
stage: build
image: docker:25
services:
- docker:25-dind
script:
- docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA .
- docker push $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA
only:
- main
deploy:
stage: deploy
image: alpine
script:
- apk add --no-cache openssh
- ssh deploy@prod "docker pull $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA && docker-compose up -d"
only:
- main
when: manual # только по кнопке
Интеграция с Keycloak SSO
В /etc/gitlab/gitlab.rb:
gitlab_rails['omniauth_enabled'] = true
gitlab_rails['omniauth_auto_sign_in_with_provider'] = 'openid_connect'
gitlab_rails['omniauth_allow_single_sign_on'] = ['openid_connect']
gitlab_rails['omniauth_block_auto_created_users'] = false
gitlab_rails['omniauth_providers'] = [
{
name: 'openid_connect',
label: 'Corp SSO',
args: {
name: 'openid_connect',
scope: ['openid','profile','email'],
response_type: 'code',
issuer: 'https://sso.example.ru/realms/corp',
discovery: true,
client_auth_method: 'query',
uid_field: 'preferred_username',
send_scope_to_token_endpoint: 'true',
client_options: {
identifier: 'gitlab',
secret: 'your-client-secret-from-keycloak',
redirect_uri: 'https://git.example.ru/users/auth/openid_connect/callback'
}
}
}
]
gitlab-ctl reconfigure
Бэкапы и восстановление
Встроенный инструмент:
# Ежедневный бэкап в cron
0 2 * * * /opt/gitlab/bin/gitlab-backup create CRON=1
# Отдельно — конфигурация
0 3 * * * tar -czf /var/opt/gitlab/config-$(date +%F).tgz /etc/gitlab
# Восстановление
systemctl stop gitlab-runner
gitlab-ctl stop unicorn
gitlab-ctl stop sidekiq
gitlab-backup restore BACKUP=1698000000_2025_12_03_17.4.0
gitlab-ctl reconfigure
gitlab-ctl start
Обязательно копия конфигов /etc/gitlab/gitlab-secrets.json и /etc/gitlab/gitlab.rb отдельно — без них восстановление невозможно.
А как быть с резервными копиями Off-site? Для их создания мы обычно используем borgbackup с хранением в MinIO S3 или syncoid для синхронизации на второй сервер.
Кейс: студия на 18 разработчиков
В ноябре 2025 к нам пришла одна веб-студия. Команда: 18 разработчиков, 4 дизайнера и 3 проджект-менеджера. Все их проекты (12 активных и 35 архивных) жили в GitHub. Причина обращения была проста и понятна: надоела нестабильность доступа к GitHub, да и стоимость Team-подписки росла, как на дрожжах. Решили, что пора переезжать на свой GitLab.
Что сделали за 11 рабочих дней:
- Итак, что мы делаем в первые два дня? Разворачиваем VPS в Selectel: 4 vCPU, 16 ГБ оперативной памяти и 200 ГБ NVMe-диска. Сразу же ставим GitLab CE 17 на чистый Debian 12.
- На третий и четвёртый день занимаемся настройками. Это включает SMTP для отправки уведомлений (обычно через Postfix клиента), подключение Keycloak SSO и разворачивание GitLab Registry, но уже на отдельном VPS.
- Что мы делали на пятый и шестой день? Активно разворачивали инфраструктуру: установили сразу три runner-а – Docker, нативный и Windows – каждый на отдельной виртуальной машине. А потом, конечно, приступили к первым тестам сборок. Важно было убедиться, что всё работает, как задумано.
- Следующие три дня, с седьмого по девятый, были посвящены большой миграции. Представьте, мы перенесли 47 репозиториев! Для этого использовали GitHub Import, что позволило автоматически сохранить абсолютно все коммиты, issues и merge-реквесты. Но ведь не всё можно сделать кнопкой. Ещё 24 workflow-файла из GitHub Actions пришлось переписывать вручную под GitLab CI. Это была настоящая ювелирная работа.
- На десятый день мы собрали команду. Провели трёхчасовое обучение. Ведь что толку от новой системы, если никто не знает, как ей пользоваться? Детально объяснили, как правильно делать коммиты, как устроен MR-процесс, как запускать пайплайны и эффективно работать с Registry. За три часа мы убедились, что каждый участник команды готов к работе с новыми инструментами.
- Одиннадцатый день — время финальных штрихов для максимальной надёжности. Мы настроили ежедневные бэкапы, а также обеспечили их off-site хранение на MinIO. Это значит, что ваши данные будут в безопасности, что бы ни произошло. Конечно, не забыли про Zabbix-мониторинг для круглосуточного контроля системы. И, что не менее важно, подготовили подробнейшую документацию – чтобы любому новому администратору было легко войти в курс дела.
Что же получила студия в итоге? Во-первых, заметную экономию: целых 112 тысяч рублей в год, если сравнивать с платной GitHub Team-подпиской на 25 пользователей. Во-вторых, полный контроль над своим кодом. И, конечно же, полную независимость от любых санкционных рисков! Сам проект обошёлся в 115 тысяч рублей плюс 14 тысяч рублей ежемесячно за VPS и runners. Вложения, кстати, окупаются меньше чем за год.
Типовые проблемы эксплуатации
- GitLab жрёт память. Дефолтные воркеры Sidekiq+Puma занимают 8-10 ГБ. Если RAM 8 ГБ — будет падать. Выделяйте 16+ ГБ.
- Обновления часто ломают вещи. Всегда читайте upgrade notes, минорные версии тоже могут иметь сюрпризы. Делайте бэкап ДО
gitlab-ctl upgrade. - Registry растёт. Docker-образы копятся в registry без лимита — диск заканчивается через полгода. Обязательно настройте
registry garbage collectв cron. - Gitaly cluster для HA сложный. Если нужен HA — лучше платный EE-подписка, либо принимаете простой при сбое.
- Пайплайны на docker-in-docker. DinD работает, но медленно. Лучше kaniko или rootless BuildKit.
Развернём GitLab для вашей команды — от 95 000 руб.
Я лично проектирую и разворачиваю self-hosted GitLab для команд разработки 5-50 человек в Москве и области. Установка, миграция с GitHub / Bitbucket, настройка CI/CD runners, интеграция с Keycloak SSO, Registry, бэкапы. Типовой проект — 1-2.5 недели. Первичный аудит текущей инфраструктуры и план миграции — бесплатно.
Телефон: +7 903 729-62-41
Telegram: @ITfresh_Boss
Семёнов Евгений Сергеевич, директор АйТи Фреш
FAQ — GitLab self-hosted
- GitLab CE или EE?
- CE (Community Edition) — бесплатный навсегда, покрывает 95% задач малой и средней команды: issues, merge requests, CI/CD, registry, pages. EE (Enterprise) — дополнительно DORA-метрики, Secure-сканеры, SAML SSO (есть и в CE через OIDC), audit log. Для команд до 30 разработчиков — CE достаточно.
- Какое железо нужно?
- Для команды 10-30 разработчиков: 4 vCPU / 16 ГБ RAM / 100 ГБ SSD для самого GitLab + 2 vCPU / 4 ГБ RAM на каждый runner. GitLab довольно прожорлив к RAM — Sidekiq, Puma, PostgreSQL, Redis, Gitaly. На 8 ГБ будет тормозить.
- Нужны ли отдельные серверы для runners?
- Да, всегда. Никогда не запускайте runners на том же сервере, что сам GitLab. Пайплайны могут съесть все ресурсы и положить GitLab. Минимум — отдельная VM на 2 vCPU / 4 ГБ RAM. Для частых сборок — несколько runners с tags (docker, linux, windows).
- Можно ли мигрировать с GitHub?
- Да. GitLab имеет встроенный импорт с GitHub — проекты, issues, pull requests (становятся MR), комментарии, релизы. Типовая миграция 10-30 репозиториев — 1-3 дня. Переменные CI/CD и секреты переносятся вручную. GitHub Actions → GitLab CI требует переписывания workflow-файлов.
- Сколько стоит self-hosted GitLab под ключ?
- Для команды 15-25 разработчиков: VPS для GitLab — 10-15 тыс руб/мес, 2-3 runner-а — ещё 5-8 тыс/мес, работа по установке + миграция с GitHub + настройка CI/CD + интеграция с Keycloak/AD — от 95 тыс руб разово. Окупается против GitHub Team за 6-14 месяцев (в зависимости от числа пользователей).
