В итоге мы получим домашний сервер с фейковым доменом, на поддомене которого мы развернём GitLab и настроим работу gitlab-runner'а для деплоя наших веб-проектов.

Я не буду долго разглагольствовать по поводу каждого шага, лишь в крайних случаях буду описывать моменты, с которыми вы можете столкнуться в процессе и пути их решения.

Установка

В качестве основной системы используется Ubuntu Server.

DNSMasq & NGINX

Ставим DNSMasq и NGINX.

sudo apt update
sudo apt install nginx, dnsmasq, dnsutils

Узнаём название нашего контроллера с помощью команды (тут - enp1s0):

ip address
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp1s0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether d8:9e:f3:92:aa:a8 brd ff:ff:ff:ff:ff:ff
    inet 10.13.9.242/24 metric 100 brd 10.13.9.255 scope global dynamic enp1s0
       valid_lft 45713sec preferred_lft 45713sec
    inet6 fe80::da9e:f3ff:fe92:aaa8/64 scope link 
       valid_lft forever preferred_lft forever

Настраиваем конфиг DNSMasq `/etc/dnsmasq.d/<имя_нашего_конфига>`. В качестве имени, можно использовать название нашего главного домена, чтобы было удобнее.
Открываем файл и исправляем наш конфиг по образу и подобию:

no-dhcp-interface=<controller> # Не перенастраиваем DHCP, а слушаем наш контроллер
bogus-priv # Запретить пересылать адреса в немаршрутизированные адресные пространства
domain=<domain> # Название домена
expand-hosts # Включаем поддомены
local=/<domain>/ # Локальное название домена
domain-needed # Использовать только полное доменное имя (FQDN)
address=/<domain>/<local_ip> # Запуск функции кеширования для ip-адресов локальных интерфейсов. Если этой опции нет, то для всех
no-resolv # Запрет в чтении файла /etc/resolv.conf или др.файла выполняющего его функцию.
no-poll # Тоже, что и no-resolv
no-hosts # Не использовать файл /etc/hosts для формирования таблицы адресов

# Отдельно стоит поговорить про эти строки,
# тк если ваша рабочая машина использует VPN,
# то у вас могут возникнуть небольшие сложности с подключением.
# Всё решается дополнительной настройкой DNS в вашем VPN-клиенте
server=8.8.8.8 # DNS-сервера для домена
server=8.8.4.4 # DNS-сервера для домена

Перезагружаем DNSMasq service:

sudo systemctl restart dnsmasq.service

Теперь вам нужно настроить использование нашего локального DNS на вашем компьютере. Я покажу, как это сделать для Debian 11.
Достаточно изменить два файла: `/etc/resolv.conf` и `/etc/NetworkManager/NetworkManager.conf`.

sudo nano /etc/resolv.conf
...
# Ваш локальный DNS должен идти самым первым в списке
nameserver <local_dns_ip>
nameserver 127.0.0.1
...
sudo nano /etc/NetworkManager/NetworkManager.conf
...
[main]
dns=none
...

Теперь настроим NGINX, чтобы он принимал наш новый домен. Для этого достаточно создать новый файл конфигурации в папке `/etc/nginx/sites-available`, проверить его, переместить в `/etc/nginx/sites-enabled` и перезапустить NGINX. Приступим!

Создаём новый файл конфигурации `<ваш_домен>.conf`. Да, весьма простая конфигурация, но нам больше и не нужно.

server {
 listen 80;
 listen [::]:80;
 server_name <ваш_домен> www.<ваш_домен>;
}

Проверяем корректность файла:

sudo nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful

Переносим файл.

чтож...
mv /etc/nginx/sites-available/<ваш_домен>.conf /etc/nginx/sites-enabled/

Перезапускаем NGINX:

sudo systemctl reload nginx

Теперь, если вы перейдёте в своём браузере по адресу http://<ваш_домен>, вы увидите стартовую страницу NGINX.

GitLab

Добавляем репозиторий в систему:

curl https://packages.gitlab.com/install/repositories/gitlab/gitlab-ee/script.deb.sh | sudo bash

Устанавливаем GitLab:

sudo apt install gitlab-ee

Настраиваем базовую конфигурацию `/`:

external_url 'example.domain' -> external_url 'http://gitlab.<ваш_домен>'
web_server['external_users'] = [] -> web_server['external_users'] = ['www-data']
nginx['enable'] = true -> nginx['enable'] = false

Скачиваем файл конфигурации GitLab для NGINX. Помещаем его в папку `/etc/nginx/sites-enabled`. В этом файле нужно поправить только строки:

listen 0.0.0.0:80 default_server; -> listen 0.0.0.0:7001;
listen [::]:80 default_server; -> listen [::]:7001;
server_name YOURSERVER_FQDN -> server_name www.<ваш_домен> <ваш_домен>;

Добавляем самые простые строки в базовый конфиг NGINX. (можно и не в него, а в отдельный файл в `/etc/nginx/sites-enabled`).

server {
  listen 80;
  client_max_body_size 50m;
  server_name gitlab.<ваш_домен> www.gitlab.<ваш_домен>;
  location / {
    proxy_pass http://127.0.0.1:7001;
  }
}

Реконфигурируем GitLab:

sudo gitlab-ctl reconfigure

Обновляем NGINX:

sudo systemctl reload nginx

Находим первичный root-пароль в файле `/etc/gitlab/initial_root_password`.

Заходим на нашу страницу, вводим логин root и пароль, который мы нашли до этого, и настраиваем аккаунт администратора.

GitLab Runner

Для начала нам нужно установить Runner. Добавляем репозиторий.

curl -L "https://packages.gitlab.com/install/repositories/runner/gitlab-runner/script.deb.sh" | sudo bash

Устанавливаем пакет.

sudo apt install gitlab-runner

Теперь получаем регистрационный токен для нашего runner'а. Заходим в админ-панель GitLab через аккаунт администратора в раздел Overview -> Runners и нажимаем Register an instance runner. Копируем токен.

Начинаем процесс регистрации runner'а. Вводим команду:

sudo gitlab-runner register
  1. Вводим url-адрес нашего gitlab'a.

  2. Вводим наш токен.

  3. Вводим краткое описание.

  4. Вводим тэги. Тут я советую создать два runner'a с разными тэгами: один с тэгом shell, который будет выполнять все операции, связанные с терминальными командами, и второй с тэгом docker, который будет отвечать за наши docker-контейнеры. Остальные тэги можно посмотреть в официальной документации.

Проверить наш runner можно на той же странице в админ-панели.

Теперь, чтобы runner мог участвовать в развёртывании веб-проектов на NGINX сервер, нужно сделать лишь пару штрихов: дать ему права на вызов NGINX под sudo и выдать доступ к папкам `sites-available` и `sites-enabled`.

Права выдаются путём создания дополнительного файла в папке `/etc/sudoers.d`, в ней создадим файл `gitlabrunner` и впишем такую строчку:

%gitlab-runner ALL=(ALL:ALL) NOPASSWD: /usr/sbin/nginx

Выдача прав вызова NGINX под sudo нужна, чтобы делать проверку конфигурации файлов при деплое. Вызов `nginx -t` возможен, но он будет заканчиваться всегда с ошибкой.

Далее прописываем команду, чтобы runner имел возможность взаимодействовать с файлами в папках NGINX:

sudo chown root:gitlab-runner -R /etc/nginx/sites-available /etc/nginx/sites-enabled

Вот и всё. Теперь у нас есть полноценная локальная среда разработки.

Вместо заключения скажу лишь, что здесь я попытался описать то, что сделал я, чтобы поднять подобное окружение для своей небольшой команды в закрытой сети для разработки. Текущее решение функционирует уже целый месяц без нареканий и проблем (за исключением GitLab wiki, но как только я решу эту проблему, обязательно дополню статью).

Для тех, кому интересно, что там с GitLab wiki

Не показываются статьи обычным пользователям. Проект виден, на статью отдельно по урлу тоже можно зайти, однако при переходе в раздел wiki из сайдбара показывается только экран добавления новой статьи.

UPD: Оказывается, чтобы GitLab wiki проекта работала корректно, всегда должна присутствовать home страница (а мы начали с красивых заголовков)...

Дополнительно могу сделать небольшую статью, как вся эта система работает на примере небольшого проекта на Django, где в качестве WSGI будет использоваться Gunicorn.

Комментарии (12)


  1. baldr
    24.11.2022 14:51
    +3

    А зачем dnsmasq если можно в /etc/hosts прописать домен?

    mv /etc/nginx/sites-available/<ваш_домен>.conf /etc/nginx/sites-enabled/

    Здесь нужен симлинк.


    1. eijawa Автор
      24.11.2022 17:20

      По поводу symlink: проблема в том, что если был отправлен неправильный конфиг, то NGINX не перезапустится или не запустится (в зависимости от его текущего состояния). В связи с этим, если сделать symlink, то будет всего два варианта развития событий (о деталях можно прочитать в официальной документации):
      1. NGINX уже был запущен. В таком случае, если тест провалится, то с сервером ничего не случится (поскольку на команду перезапуска он ответит ошибкой) и он продолжит работать на старом конфиге.
      2. NGINX не был запущен. В таком случае, он просто не запустится.
      Поэтому, это дело вкуса, но я хотел бы оставить за собой возможность безболезненного перезапуска.

      DNSMasq нужен, чтобы можно было после автоматически создавать тестовые стенды на основе конфигов и не прописывать каждый раз новые домены на каждом клиенте. Для этого нужно будет лишь добавить адрес нашего сервера в качестве дополнительного DNS на нашем компьютере (у нас это сделано путём модификации resolv.conf и отключением автоматической генерации конфига NetworkManager'ом).


      1. baldr
        24.11.2022 17:33
        +1

        Насколько я знаю, папка sites-available сделана исключительно для удобства пользователя и nginx ничего о ней не знает. В ней держат все конфиги, чтобы они были поближе к nginx.

        Папка sites-enabled используется внутри nginx.conf: "include /etc/nginx/sites-enabled/*;", поэтому при "nginx -t" он ее и проверяет. Смысл в симлинке - быстрое включение-выключение конфига.

        Про dnsmasq понятно - решение лучше hosts, конечно же. Еще очень бы советовал использовать TLS-сертификаты, хоть бы и самоподписанные - на продакшене у вас все равно с https все работает же? А многие сторонние сервисы типа google auth не разрешают даже редирект на http.


        1. kpmy
          25.11.2022 01:02
          +2

          Если говорить про https.
          Недавно писали про вот этот проектик https://github.com/Upinel/localhost.direct

          Кажется, идея неплохая.


      1. dinisoft
        25.11.2022 10:27

        Перед перезапуском nginx нужно проверять конфиги!

        nginx -t

        И по результату уже рестартить.


        1. baldr
          25.11.2022 10:30

          Именно это и делается в статье, но автор ошибочно считает что файл в sites-available проверяется, хотя по-умолчанию это не так.


      1. mayorovp
        25.11.2022 12:21

        По поводу symlink: проблема в том, что если был отправлен неправильный конфиг, то NGINX не перезапустится или не запустится (в зависимости от его текущего состояния). В связи с этим, если сделать symlink, то будет всего два варианта развития событий (о деталях можно прочитать в официальной документации)

        Так ведь если вы сделаете mv, то случится ровно то же самое. В чём вы видите именно дополнительные проблемы ссылок, которых не происходит при использовании вашего подхода?


  1. irony_iron
    24.11.2022 18:26

    кажется выглядит идеальным для упихивания в docker


  1. AndrewStephanoff
    24.11.2022 21:45

    Так, на всякий случай, современные браузеры резолвят домены *.localhost на 127.0.0.1, использую эту возможность+docker


  1. nickwaze
    25.11.2022 11:17
    +1

    "Дополнительно могу сделать небольшую статью, как вся эта система работает на примере небольшого проекта на Django, где в качестве WSGI будет использоваться Gunicorn."
    моги


  1. MyraJKee
    26.11.2022 12:32

    docker + traefik


  1. werter_l
    27.11.2022 12:21

    sudo nginx -t && sudo nginx -s reload

    /etc/nginx/sites-enabled не пользую - пользую /etc/nginx//conf.d/