GitLab self-hosted для малой команды разработки: установка, CI/CD и миграция с GitHub
Меня зовут Семёнов Евгений Сергеевич, директор АйТи Фреш. С 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 |
Для моих клиентов (МСБ) почти всегда достаточно CE. 2FA есть, SSO через OIDC/SAML есть, MR-approvals через Push Rules есть. Ultimate имеет смысл только если нужна автоматическая проверка security-уязвимостей на compliance-уровне.
Установка GitLab CE
Официально поддерживается 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 — обязательно отдельно
Самая частая ошибка новичков — запускать runner на том же сервере, что и GitLab. Тяжёлые пайплайны съедают RAM/CPU и сервер GitLab перестаёт отвечать.
Настройка runner на отдельной VM (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 PM. Проекты в GitHub (12 активных + 35 архивных). Решили уйти на свой GitLab из-за нестабильности доступа к GitHub и роста стоимости Team-подписки.
Что сделали за 11 рабочих дней:
- Дни 1-2: VPS 4 vCPU / 16 ГБ / 200 ГБ NVMe в Selectel. Установка GitLab CE 17 на Debian 12.
- Дни 3-4: Настройка SMTP (отправка уведомлений через их Postfix), Keycloak SSO, GitLab Registry на отдельный VPS.
- Дни 5-6: Развёртывание 3 runner-ов (docker, native, windows) на отдельных VM. Первые тесты сборок.
- Дни 7-9: Миграция 47 репозиториев через GitHub Import. Автоматическое сохранение всех коммитов, issues, MR. Ручная миграция 24 workflow-файлов GitHub Actions → GitLab CI.
- День 10: Обучение команды: коммит, MR-процесс, запуск pipelines, работа с Registry. 3 часа.
- День 11: Бэкапы (ежедневный + off-site на MinIO), Zabbix-мониторинг, документация для нового админа.
Результат: экономия 112 тыс руб/год (vs 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 месяцев (в зависимости от числа пользователей).