- Зачем: - стандартный nginx-vhost отдавал welcome page по IP, а HTTPS по IP получал сертификат de.dementev.space. - Что: - default vhost настроен на HTTP 404 и отказ TLS для IP и неизвестного SNI. - runbook дополнен точной процедурой Certbot, восстановлением и проверками. - завершённая задача публикации перенесена в раздел «Сделано». - Проверка: - live и bootstrap-конфигурации прошли nginx -t; доменный HTTPS отдаёт 200, неизвестный Host — 404, TLS по IP отклоняется. - mkdocs build --strict выполнен через persistent venv пользователя gitea-runner.
8.8 KiB
Эксплуатация публикации de.dementev.space
Этот runbook реализует спецификацию
2026-08-04-gitea-vps-site-publishing.md.
Команды рассчитаны на Ubuntu 26.04 и Gitea 1.27.
Зафиксированные параметры
- Gitea Runner:
2.3.0, Linux amd64. - SHA256:
1e9fb1bea022fdf40993ecbc1a13e87db1bfd3d7f42666e37f15f71d840d53b3. - Runner: repository-scoped, метка
de-roadmap-host:host. - Пользователь сервиса:
gitea-runner, безsudoи Docker. - Корень публикации:
/srv/de-roadmap. - Хранение: текущий релиз и две предыдущие версии.
- Окружение сборки:
/var/lib/gitea-runner/venvs/site. - Публичный IPv4 VPS:
167.224.64.252.
Подготовка VPS
Установить HTTP-сервер и Certbot:
sudo apt-get update
sudo apt-get install nginx certbot python3-certbot-nginx python3-venv
Создать пользователя и каталоги:
sudo useradd \
--system \
--home-dir /var/lib/gitea-runner \
--create-home \
--shell /usr/sbin/nologin \
gitea-runner
sudo install -d -o gitea-runner -g gitea-runner -m 0755 \
/var/lib/gitea-runner/workspaces \
/srv/de-roadmap \
/srv/de-roadmap/releases
sudo install -d -o root -g root -m 0755 /etc/gitea-runner
Скачать runner во временный каталог, сверить checksum и установить root-owned
бинарник в /usr/local/bin/gitea-runner:
runner_tmp_dir=$(mktemp -d /tmp/de-roadmap-runner.XXXXXX)
curl -fsSLo "${runner_tmp_dir}/gitea-runner" \
https://dl.gitea.com/gitea-runner/2.3.0/gitea-runner-2.3.0-linux-amd64
printf '%s %s\n' \
'1e9fb1bea022fdf40993ecbc1a13e87db1bfd3d7f42666e37f15f71d840d53b3' \
"${runner_tmp_dir}/gitea-runner" \
| sha256sum --check
sudo install -o root -g root -m 0755 \
"${runner_tmp_dir}/gitea-runner" /usr/local/bin/gitea-runner
rm "${runner_tmp_dir}/gitea-runner"
rmdir "$runner_tmp_dir"
Из корня репозитория установить конфигурацию и unit:
sudo install -o root -g root -m 0644 \
project/ops/gitea-vps-site/gitea-runner.yaml \
/etc/gitea-runner/config.yaml
sudo install -o root -g root -m 0644 \
project/ops/gitea-vps-site/gitea-runner.service \
/etc/systemd/system/gitea-runner.service
sudo systemd-analyze verify /etc/systemd/system/gitea-runner.service
Регистрация runner
Repository registration token получают в Gitea:
ddmitry/de-roadmap → Settings → Actions → Runners. Токен не сохраняют в Git
или shell history. Временный файл с токеном создают с владельцем
gitea-runner:gitea-runner и режимом 0600. После регистрации файл
/var/lib/gitea-runner/.runner должен принадлежать тому же пользователю и
иметь режим 0600.
Token-file должен содержать ровно 40 символов без завершающего перевода строки.
При извлечении JSON-ответа через jq использовать jq --join-output '.token',
а не jq --raw-output, который добавляет newline.
sudo -u gitea-runner \
/usr/local/bin/gitea-runner \
--config /etc/gitea-runner/config.yaml \
register \
--no-interactive \
--instance https://git.dementev.space \
--token-file /var/lib/gitea-runner/.registration-token \
--name de-roadmap-vps
sudo rm /var/lib/gitea-runner/.registration-token
sudo chmod 0600 /var/lib/gitea-runner/.runner
sudo systemctl daemon-reload
sudo systemctl enable --now gitea-runner
Временный файл с токеном удаляют сразу после успешной регистрации.
Nginx и первичная публикация
Из корня репозитория установить bootstrap-конфигурацию nginx, создать ссылку, отключить стандартный сайт Ubuntu и только затем перечитать проверенную конфигурацию:
sudo install -o root -g root -m 0644 \
project/ops/gitea-vps-site/nginx.conf \
/etc/nginx/sites-available/de-roadmap
sudo ln -s \
/etc/nginx/sites-available/de-roadmap \
/etc/nginx/sites-enabled/de-roadmap
sudo unlink /etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
Первый server block в nginx.conf возвращает 404 для неизвестных HTTP Host,
не раскрывает версию nginx и отклоняет TLS handshake для IP или неизвестного
SNI. Поэтому сертификат de.dementev.space не выдаётся при обращении к VPS по
IP. Если проверка конфигурации не прошла, отключить новый virtual host,
восстановить стандартный сайт и перечитать проверенную конфигурацию:
sudo unlink /etc/nginx/sites-enabled/de-roadmap
sudo ln -s \
/etc/nginx/sites-available/default \
/etc/nginx/sites-enabled/default
sudo nginx -t
sudo systemctl reload nginx
До первого workflow можно собрать сайт вручную и опубликовать его тем же скриптом с тестовым release id. Проверка до переключения DNS:
curl --header 'Host: de.dementev.space' http://127.0.0.1/
После локальной проверки разрешить профили Nginx Full в UFW. До этого
публичные порты 80/tcp и 443/tcp должны оставаться закрытыми.
Файл project/ops/gitea-vps-site/nginx.conf предназначен только для запуска до
выпуска сертификата. После выпуска сертификата Certbot изменяет установленный
virtual host. Повторная установка bootstrap-файла поверх рабочего конфига
удалит TLS-директивы.
Окружение сборки
Скрипт .gitea/scripts/build-site.sh создаёт persistent venv при первом запуске
и переиспользует его в следующих сборках. pip install выполняется каждый раз,
чтобы применить изменения .gitea/requirements-site.txt, но уже установленные
версии пакетов не переустанавливаются.
DNS и TLS
-
Уменьшить TTL записи
de.dementev.space. -
Направить
Aна VPS; удалить или корректно направитьAAAA. -
Убедиться, что сайт доступен извне по HTTP.
-
Выпустить сертификат и включить перенаправление HTTP на HTTPS:
sudo certbot --nginx \ --non-interactive \ --agree-tos \ --email me@dementev.space \ --redirect \ -d de.dementev.space -
В созданном Certbot HTTP-блоке для
de.dementev.spaceдобавитьserver_tokens off;, затем проверить и перечитать конфигурацию:sudoedit /etc/nginx/sites-available/de-roadmap sudo nginx -t sudo systemctl reload nginx -
Проверить перенаправление, HTTPS, сертификат и автоматическое продление:
curl --head http://de.dementev.space/ curl --fail --head https://de.dementev.space/ ! curl --insecure --head https://167.224.64.252/ sudo certbot certificates systemctl is-enabled certbot.timer systemctl is-active certbot.timerОжидаются
301 Moved Permanently, затем200 OK, отказ TLS по IP, действующий сертификат и состояния таймераenabledиactive. -
Вернуть обычный DNS TTL.
Проверка и откат
Активная версия определяется ссылкой /srv/de-roadmap/current. Для ручного
отката создать временную ссылку на нужный каталог в releases/ и атомарно
заменить current через mv -Tf. Перед удалением релиза всегда проверять
результат readlink -f /srv/de-roadmap/current.
Диагностика:
systemctl status gitea-runner
journalctl -u gitea-runner
nginx -t
curl --header 'Host: de.dementev.space' http://127.0.0.1/