Выполним установку и настройку Gitlab Community Edition через установку Omnibus-пакета
1. Установка зависимостей для Gitlab-пакета с предварительным обновлением локального кеша пакетов
1 |
# apt-get update && apt-get install curl openssh-server ca-certificates postfix |
2. Добавление Gitlab репозитария, из которого будет установлен пакет Gitlab Community Edition
1 |
# curl -L -o /tmp/script.deb.sh https://packages.gitlab.com/install/repositories/gitlab/gitlab-ce/script.deb.sh |
1 |
# bash /tmp/script.deb.sh |
3. Установка Gitlab
1 |
# apt-get install gitlab-ce -y |
1 2 3 4 5 6 7 8 9 |
Thank you for installing GitLab! GitLab was unable to detect a valid hostname for your instance. Please configure a URL for your GitLab instance by setting `external_url` configuration in /etc/gitlab/gitlab.rb file. Then, you can start your GitLab instance by running the following command: sudo gitlab-ctl reconfigure For a comprehensive list of configuration options please see the Omnibus GitLab readme https://gitlab.com/gitlab-org/omnibus-gitlab/blob/master/README.md |
4. Настройка домен/урл по которому будет доступен Gitlab снаружи
Если не используется SSL, тогда указываем протокол http в параметре
external_url в файле /etc/gitlab/gitlab.rb
1 |
external_url 'http://gitlab.mydomain.com' |
Для фактического применения сделанных настроек необходимо выполнить команду:
1 |
gitlab-ctl reconfigure |
5. Настройка Gitlab на работу с SSL
Получение бесплатного Let’sEncrypt-сертификата
Gitlab поддерживает два способа работы с SSL:
1.Автоматическое генерирование самим Gitlab-ом сертификатов Let’sEncrypt(c их поселедующим ручным (с помощью команды gitlab-ctl renew-le-certs) или автоматическим обновлением)
https://docs.gitlab.com/omnibus/settings/ssl.html#lets-encrypt-integration
2.Ручная настройка HTTPS со своими собственными сертификатами
https://docs.gitlab.com/omnibus/settings/nginx.html#manually-configuring-https
Будем использовать второй способ, в котором получим бесплатный Let’sEncrypt-сертификат и установим автообновление этого сертификата
1 |
# apt-get install software-properties-common |
1 |
# add-apt-repository ppa:certbot/certbot |
1 |
# apt-get update && apt-get install certbot |
1 |
# gitlab-ctl stop nginx |
1 |
# certbot certonly --standalone gitlab.mydomain.com --no-eff-email --non-interactive --agree-tos --email myemail@mydomain.com |
1 |
# gitlab-ctl start nginx |
Сгенерируем Диффи-Хелмана ключ
1 2 3 |
# mkdir -p /etc/gitlab/ssl/ && \ openssl dhparam -out /etc/gitlab/ssl/dhparams.pem 2048 && \ chmod 600 /etc/gitlab/ssl/* |
Настройка Gitlab на поддержку SSL
https://docs.gitlab.com/omnibus/settings/ssl.html
https://docs.gitlab.com/omnibus/settings/nginx.html#manually-configuring-https
Протокол изменяем с http на https
1 |
# nano /etc/gitlab/gitlab.rb |
1 |
external_url 'https://gitlab.mydomain.com' |
Включаем принудительный редирект http->https
1 |
nginx['redirect_http_to_https'] = true |
Указываем пути к сертификату, приватному ключу и к ключу Дифи-Хелмана
1 2 3 |
nginx['ssl_certificate'] = "/etc/letsencrypt/live/gitlab.mydomain.com/fullchain.pem" nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/gitlab.mydomain.com/privkey.pem" nginx['ssl_dhparam'] = "/etc/gitlab/ssl/dhparams.pem" |
Обязательно отключаем поддержку letsencrypt, встроенную в Gitlab
Чтобы при выполнении команды gitlab-ctl reconfigure
Gitlab не пытался самостоятельно обновить сертификаты Let’sEncrypt и тем самым перезаписать уже действующие сертификаты
1 |
letsencrypt['enable'] = false |
Перенастраиваем/переконфигурируем Gitlab после внесений изменений в файл /etc/gitlab/gitlab.rb
1 |
# gitlab-ctl reconfigure |
Настройка автообновления Let’sEncrypt-сертификата с последующим перечитыванием nginx-ом своей конфигурации и нового сертификата/ключа
https://docs.gitlab.com/omnibus/settings/nginx.html#update-the-ssl-certificates
Для получение сертификата добавляем в cron-скрипт для запуска каждые 2 месяца, который
1 2 3 |
- Останавливает Nginx как сервис в Gitlab - Запрашивает принудительное получение/обновление Let'sEncrypt-сертификата - Запускает Nginx как сервис в Gitlab |
1 |
# crontab -e |
1 |
0 3 1 1,3,5,7,9,11 * /usr/local/bin/ssl-renew.sh >> /var/log/letsencrypt/gitlab.mydomain.com-renew.log |
1 |
# cat /usr/local/bin/ssl-renew.sh |
1 2 3 4 |
#!/usr/bin/env bash gitlab-ctl stop nginx && \ /usr/bin/certbot certonly --standalone -d gitlab.mydomain.com --non-interactive --force-renewal gitlab-ctl start nginx |
1 |
# chmod +x /usr/local/bin/ssl-renew.sh |
6. Базовая настройка Gitlab после его установки
Установка пароля:
Логинимся в Gitlab (предварительно в WEB-интерфейсе устанавливаем пароль)
1 2 |
Login: root Password: который указали |
Отключение авторегистрации:
1 |
Settings-General->Sign-up enabled |
Указание корректного Email-адреса:
1 |
Settings->Profile->Email |
Изменение дефолтного имени пользователя с админискими правми с root на свое имя:
1 |
Settings->Account-Change Username |
Настройка Gitlab Shell на нестандартный порт SSH(если SSH-сервер запущен не на стандартном порту)
1 |
# nano /etc/gitlab/gitlab.rb |
1 2 |
### GitLab Shell settings for GitLab gitlab_rails['gitlab_shell_ssh_port'] = 2222 |
1 |
# gitlab-ctl reconfigure |
Настройка SMTP-сервера
В качестве SMTP-сервера используем локально запущеннный postfix без поддержки SSL, слушающий запросы на localhost
1 |
# nano /etc/gitlab/gitlab.rb |
1 2 3 4 5 6 7 8 9 |
gitlab_rails['smtp_enable'] = true gitlab_rails['smtp_address'] = 'localhost' gitlab_rails['smtp_port'] = 25 gitlab_rails['smtp_domain'] = 'localhost' gitlab_rails['smtp_tls'] = false gitlab_rails['smtp_openssl_verify_mode'] = 'none' gitlab_rails['smtp_enable_starttls_auto'] = false gitlab_rails['smtp_ssl'] = false gitlab_rails['smtp_force_ssl'] = false |
Перенастраиваем/переконфигурируем Gitlab после внесений изменений в файл /etc/gitlab/gitlab.rb
1 |
# gitlab-ctl reconfigure |
Тестирование SMTP-кнфигурации путем отправки тестового сообщения из консоли Gitlab
https://docs.gitlab.com/omnibus/settings/smtp.html#testing-the-smtp-configuration
Заходим в Gitlab консоль
1 |
# gitlab-rails console |
Выполняем команду по отправке тестового сообщения
1 |
Notify.test_email('myemail@mydomain.com', 'Message Subject', 'Message Body').deliver_now |
Если необходимо отключить отправку всех типов сообщений
https://docs.gitlab.com/omnibus/settings/smtp.html#disable-all-outgoing-email
1 |
# nano /etc/gitlab/gitlab.rb |
1 |
# gitlab_rails['gitlab_email_enabled'] = true |
1 |
# gitlab-ctl reconfigure |
Отключение неиспользуемых сервисов
Отключение Prometheus (который включен по умолчанию)
1 2 |
# To completely disable prometheus, and all of it's exporters, set to false prometheus_monitoring['enable'] = false |
Отключение Grafana
1 2 3 |
## Grafana Dashboards ##! Docs: https://docs.gitlab.com/ee/administration/monitoring/prometheus/#prometheus-as-a-grafana-data-source grafana['enable'] = false |
1 |
# gitlab-ctl status | grep -E 'prometheus|grafana' |
1 2 |
run: grafana: (pid 15895) 502269s; run: log: (pid 28053) 504628s run: prometheus: (pid 16026) 502267s; run: log: (pid 27442) 504681s |
При отключении сервиса Prometheus fвтоматически также будут отключены такие сервисы,которые использует prometheus
1 2 |
node-exporter redis-exporter |
Применяем настройки
1 |
# gitlab-ctl reconfigure |
Проверяем отсутствие запущенных Prometheus и Grafana-сервисов
1 2 |
# gitlab-ctl status | grep -E 'prometheus|grafana' # |
Настройка Nginx статусной страницы
1 2 3 4 5 6 7 8 9 10 11 12 |
### Nginx status nginx['status'] = { "enable" => true, "listen_addresses" => ["127.0.0.1"], "port" => 9999, "options" => { "server_tokens" => "off", # Don't show the version of NGINX "access_log" => "off", # Disable logs for stats "allow" => "127.0.0.1", "deny" => "all" # Deny access to anyone else } } |
1 |
# gitlab-ctl reconfigure |
1 |
# curl http://localhost:9999/nginx_status |
1 2 3 4 |
Active connections: 1 server accepts handled requests 11 11 24 Reading: 0 Writing: 1 Waiting: 0 |
Конфигурация, которая создается после изменений в файле /etc/gitlab/gitlab.rb
и выполнению команды для применения изменений (gitlab-ctl reconfigure)
1 |
# cat /var/opt/gitlab/nginx/conf/nginx-status.conf |
Error-логи Nginx
1 |
# cat /var/log/gitlab/nginx/error.log |
Все конфигурационные файлы/файлы виртуальных хостов/статусной страницы и т.д. для Nginx распологаются в каталоге /var/opt/gitlab/nginx/conf:
1 2 3 4 5 |
# ls -l /var/opt/gitlab/nginx/conf/*.conf -rw-r--r-- 1 root root 902 Nov 29 22:09 /var/opt/gitlab/nginx/conf/gitlab-health.conf -rw-r--r-- 1 root root 5657 Dec 5 18:22 /var/opt/gitlab/nginx/conf/gitlab-http.conf -rw-r--r-- 1 root root 3104 Dec 5 17:27 /var/opt/gitlab/nginx/conf/nginx.conf -rw-r--r-- 1 root root 611 Dec 13 15:19 /var/opt/gitlab/nginx/conf/nginx-status.conf |
Настройка ротации логов
https://docs.gitlab.com/omnibus/settings/logs.html
GitLab включает расширенную систему журналов, в которой все службы и компоненты GitLab будут записывать в системные логи
Дефолтное месторасположение логов всех сервисов/компонентов доступно по команде:
1 |
# grep log_directory /etc/gitlab/gitlab.rb |
1 |
# nano /etc/gitlab/gitlab.rb |
Runit-управляемые сервисы генерируют логи испольхуя svlogd
Ротацию логов таких сервисов настраиваем через параметры
1 |
logging['svlogd |
Например, настроим ротацию с такой логикой
Ротировать только по времени(раз в сутки), ротация по размеру отключена
Хранить 7 ротированных файлов, при ротации сжимать старый лог-файл
Logrotate-сервис,который встроен в Gitlab управляет всеми логами кроме логов для Runit-управляемых сервисов
Аналогично, как и для логов runit-сервисов, настроим ротацию всех остальных
логов средствами встроенного в Gitlab logrotate-сервиса, а именно:
Ежесуточная ротация по времени(не по рамзмеру), с хранением 7 посоледних ротированных копий/лог-файлов, с сжатием ротированных файлов
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
################################################################################ ## GitLab Logging ##! Docs: https://docs.gitlab.com/omnibus/settings/logs.html ################################################################################ # logging['svlogd_size'] = 200 * 1024 * 1024 # rotate after 200 MB of log data logging['svlogd_size'] = nil # do not rotate by size logging['svlogd_num'] = 7 # keep 7 rotated log files logging['svlogd_timeout'] = 24 * 60 * 60 # rotate after 24 hours logging['svlogd_filter'] = "gzip" # compress logs with gzip # logging['svlogd_udp'] = nil # transmit log messages via UDP # logging['svlogd_prefix'] = nil # custom prefix for log messages logging['logrotate_frequency'] = "daily" # rotate logs daily logging['logrotate_maxsize'] = nil # rotate logs when they grow bigger than size bytes even before the specified time interv$ logging['logrotate_size'] = nil # do not rotate by size by default logging['logrotate_rotate'] = 7 # keep 7 rotated logs logging['logrotate_compress'] = "compress" # see 'man logrotate' logging['logrotate_method'] = "copytruncate" # see 'man logrotate' logging['logrotate_postrotate'] = nil # no postrotate command by default ################################################################################ ## Logrotate ##! Docs: https://docs.gitlab.com/omnibus/settings/logs.html#logrotate ##! You can disable built in logrotate feature. ################################################################################ logrotate['enable'] = true logrotate['log_directory'] = "/var/log/gitlab/logrotate" |
Применяем сделанные настройки
1 |
# gitlab-ctl reconfigure |
При необходимости можно выполнить ручной запуск ротации(по дефолту ротация выполняется по расписанию)
1 |
/opt/gitlab/embedded/sbin/logrotate -fv -s /var/opt/gitlab/logrotate/logrotate.status /var/opt/gitlab/logrotate/logrotate.conf |
Несколько команд для просмотра логов средствами утилиты gitlab-ctl
Просмотр логов всех сервисов в online-режиме
1 |
# gitlab-ctl tail |
Просмотр всех логов в конкретном подкаталоге(например, в подкаталоге gitlab-rails)
1 |
# gitlab-ctl tail gitlab-rails |
Просмотр лога конкретного файла(например, access-лога Gitlab-сервиса)
1 |
# gitlab-ctl tail nginx/gitlab_access.log |
Настройка лимитов на подключение к Gitlab
Enabling/Disabling Rack Attack and setting up basic auth throttling
https://docs.gitlab.com/omnibus/settings/configuration.html#enablingdisabling-rack-attack-and-setting-up-basic-auth-throttling
https://docs.gitlab.com/ee/security/rack_attack.html
3 неуспешные попытки за 10 минут — блокировка на 3 часа
1 2 3 4 5 6 7 |
gitlab_rails['rack_attack_git_basic_auth'] = { 'enabled' => true, 'ip_whitelist' => ["127.0.0.1"], 'maxretry' => 3, 'findtime' => 600, 'bantime' => 10800 } |
1 |
# gitlab-ctl reconfigure |
Rate Limit/Throttling
Более 5 запросов незарегистрированным пользователем — троттлинг на 120 секунд
с кодом ответа 429 и ответом Too Many Requests
https://docs.gitlab.com/ee/security/rate_limits.html
1 2 3 4 |
Settings->Network->User and IP Rate Limits Enable unauthenticated request rate limit->true Max requests per period per IP - 5 Rate limit period in seconds - 120 |
1 |
# for i in {1..6}; do curl -I https://gitlab.mydomain.com/users/sign_in; done |
6-й запрос
1 2 3 4 5 6 7 8 |
HTTP/1.1 429 Too Many Requests Server: nginx Date: Sun, 06 Dec 2020 18:24:31 GMT Content-Type: text/plain Connection: keep-alive Cache-Control: no-cache X-Request-Id: Z4uA5ooQ1V5 X-Runtime: 0.003721 |
Проверка наличия IP-адрса в заблокаированных:
1 |
# grep "Rack_Attack" /var/log/gitlab/gitlab-rails/auth.log |
1 |
{"severity":"ERROR","time":"2020-12-06T17:32:35.845Z","correlation_id":"IozXXnHoYz6","message":"Rack_Attack","env":"throttle","remote_ip":"159.XXX.YYY.ZZZ","request_method":"GET","path":"/favicon.ico","matched":"throttle_unauthenticated"} |
Дефолтное место хранения репозитариев
https://docs.gitlab.com/omnibus/settings/configuration.html#configuring-the-external-url-for-gitlab
1 |
/var/opt/gitlab/git-data/repositories/ |
Storage-директории
1 |
# ls -l /var/opt/gitlab/gitlab-rails/shared/ |
1 2 3 4 5 6 7 8 9 10 |
total 40 drwx------ 2 git root 4096 Nov 29 22:08 artifacts drwx------ 2 git root 4096 Nov 29 22:08 cache drwx------ 2 git root 4096 Nov 29 22:08 dependency_proxy drwx------ 2 git root 4096 Nov 29 22:08 external-diffs drwx------ 2 git root 4096 Nov 29 22:08 lfs-objects drwx------ 2 git root 4096 Nov 29 22:08 packages drwxr-x--- 2 git gitlab-www 4096 Nov 29 22:08 pages drwx------ 2 git root 4096 Nov 29 22:08 terraform_state drwx------ 2 git root 4096 Nov 29 22:08 tmp |
Полезные команды для работы с Gitlab-сервисами через утилиту gitlab-ctl
1 2 3 4 5 |
gitlab-ctl -help gitlab-ctl service-list gitlab-ctl stop gitlab-ctl start gitlab-ctl status |
1 |
# gitlab-ctl status |
1 2 3 4 5 6 7 8 |
run: gitaly: (pid 15842) 503100s; run: log: (pid 26615) 505619s run: gitlab-workhorse: (pid 15879) 503100s; run: log: (pid 26956) 505561s run: logrotate: (pid 28497) 2631s; run: log: (pid 27042) 505542s run: nginx: (pid 13266) 713s; run: log: (pid 27008) 505553s run: postgresql: (pid 16017) 503097s; run: log: (pid 26785) 505613s run: puma: (pid 13249) 721s; run: log: (pid 26923) 505572s run: redis: (pid 16050) 503096s; run: log: (pid 26572) 505625s run: sidekiq: (pid 13225) 728s; run: log: (pid 26936) 505567s |
Послать команду на nginx-сервис для перечитывания им своей конфигурации при обновлении
1 |
# gitlab-ctl hup nginx |
Включение Container Registry в Gitlab
Получение Let’sEncrypt-сертификата для домена registry.mydomain.com
1 2 3 |
# gitlab-ctl stop nginx # certbot certonly --standalone -d registry.mydomain.com --no-eff-email --non-interactive # gitlab-ctl start nginx |
Для автоматического продления сертификата добавим в ранее созданный скрипт /usr/local/bin/ssl-renew.sh после строки с командой по запуску certbot
команду для обновления сертификата для домена registry.mydomain.com
1 |
/usr/bin/certbot certonly --standalone -d registry.mydomain.com --non-interactive --force-renewal |
И в конеце скрипта последней строкой добавляем перезапуск сервиса registry
1 |
gitlab-ctl restart registry |
Итого скрипт по обновлению сертификатов(как для gitlab, так и для registry) имеет вид:
1 2 3 4 5 6 7 |
#!/usr/bin/env bash gitlab-ctl stop nginx && \ /usr/bin/certbot certonly --standalone -d gitlab.mydomain.com --non-interactive --force-renewal /usr/bin/certbot certonly --standalone -d registry.mydomain.com --non-interactive --force-renewal gitlab-ctl start nginx gitlab-ctl restart registry |
1 |
# nano /etc/gitlab/gitlab.rb |
1 2 3 |
registry_external_url 'https://registry.mydomain.com' registry_nginx['ssl_certificate'] = "/etc/letsencrypt/live/registry.mydomain.com/fullchain.pem" registry_nginx['ssl_certificate_key'] = "/etc/letsencrypt/live/registry.mydomain.com/privkey.pem" |
1 |
# gitlab-ctl reconfigure |
По умолчанию registry запускается на порту 5000
1 |
# netstat -nlptu | grep 5000 |
1 |
tcp 0 0 127.0.0.1:5000 0.0.0.0:* LISTEN 15272/registry |
1 |
# gitlab-ctl status registry |
1 |
run: registry: (pid 15272) 10s; run: log: (pid 15271) 10s |
Взаимодействие Gitlab и Registry
https://docs.gitlab.com/omnibus/architecture/registry/README.html
1 |
/var/opt/gitlab/registry/config.yml |
Процес аутентификации в Container Registry в Gitlab(docker login…)
1.Docker client->Docker daemon->registry.mydomain.com->
2.Реджистри возвращает код ответа 401 т.к. не был предоставлен валидный токен
Вместе с кодом ответа 401 реджистри отправляет клиенту(который попытался залогиниться в реджистри с помощью команды docker login https://registry.mydomain.com)
token_realm (который указан в конфигурации реджистри в файле /var/opt/gitlab/registry/config.yml)
1 |
# grep -E 'token|realm' /var/opt/gitlab/registry/config.yml |
1 2 |
token: realm: https://gitlab.mydomain.com/jwt/auth |
Этот token_realm как раз и указывает клиенту, где он может получить токен т.е.
обратиться за токеном на Gitlab (https://gitlab.mydomain.com) по указанному роуту
1 |
/jwt/auth |
3.Docker клиент подключается к Gitlab API и получает токен
Этот токен Gitlab подписывает приватным ключем РЕДЖИСТРИ, а сертификат РЕДЖИСТРИ, которым будет
проверяться подписанный Gitlab-ом приватным ключем токен, прописан в конфиг.файла registry
1 |
# grep rootcertbundle /var/opt/gitlab/registry/config.yml |
1 |
rootcertbundle: /var/opt/gitlab/registry/gitlab-registry.crt |
Эта пара приватный ключ и сертификат для Реджистри является самоподписными и автоматически
выпускается Gitlab-ом при включении/настройке Registry
И эта пара никакого не имеет отношения к сертификату/ключу, который использует клиент при подключении к Registry снаружи(который мы выпускали средствами Let’sEncrypt)
4.Docker клиент подключается снова к Registry, но уже с валидным токеном, который он получил от Gitlab API и
успешно аутентифицируется в Docker-реджистри
Увеличение времени жизни токена(по дефолту 5 минут)
https://docs.gitlab.com/13.6/ee/administration/packages/container_registry.html#container-registry-domain-configuration
Полезно,если в хранилище загружается большой по размеру образ, который не успевает загрузиться за 5 минут
1 |
Admin area->Settings->CI/CD->Container Registry->Authorization token duration (minutes) |
Тегирование, загрузка, скачивание образов с Container Registry
https://docs.gitlab.com/ee/user/packages/container_registry/
Залогиниться пользователем,который создан в Gitlab, в Registry( например, my-gitlab-user-name)
1 |
# docker login -u my-gitlab-user-name registry.mydomain.com |
Перетегировать образ в формат, поддерживаемый Gitlab-ом
1 2 3 |
registry.example.com/mynamespace/myproject:some-tag registry.example.com/mynamespace/myproject/image:latest registry.example.com/mynamespace/myproject/my/image:rc1 |
1 |
# docker tag alpine:3.7 registry.mydomain.com/my-gitlab-user-name/my-project-name/alpine:3.7 |
Загрузить образ в Registry
1 |
# docker push registry.mydomain.com/my-gitlab-user-name/my-project-name/alpine:3.7 |
Удалить локальный образ
1 |
# docker rmi registry.mydomain.com/my-gitlab-user-name/my-project-name/alpine:3.7 |
Загрузить образ с Registry
1 |
# docker pull registry.mydomain.com/my-gitlab-user-name/my-project-name/alpine:3.7 |
Troubleshooting Registry
https://docs.gitlab.com/13.6/ee/administration/packages/container_registry.html#troubleshooting
Лог файл Registry
1 |
/var/log/gitlab/registry/current |
Лог файл Gitlab
1 |
/var/log/gitlab/gitlab-rails/production.log |
Источник:
Установка
https://docs.gitlab.com/13.6/omnibus/installation
Настройка
https://docs.gitlab.com/omnibus/settings/configuration.html
https://docs.gitlab.com/13.6/omnibus/README.html#configuring
Nginx
https://docs.gitlab.com/13.6/omnibus/settings/nginx.html