Обновлено:

Чек-лист безопасного деплоя

Это более подробная версия быстрого старта.
Используйте её, когда изменения не хочется выкладывать “на глаз”: обновили структуру, добавили несколько страниц, поменяли layout, стили или клиентские скрипты.

Главное правило: сначала проверяем сборку, потом деплоим, потом проверяем production.

0. Что мы обновляем

Для контентного обновления трогаем только:

~/getsrv-static-src
/var/www/getsrv.app

Не меняем:

/etc/nginx/
/etc/haproxy/
systemd services
публичные listener'ы
TLS-сертификаты

Если задача не про инфраструктуру, не надо случайно превращать её в инфраструктурную.

1. Сделать backup исходников

cd ~/getsrv-static-src

STAMP="$(date +%F-%H%M%S)"
BACKUP_DIR="$HOME/getsrv-static-backups/deploy-$STAMP"
mkdir -p "$BACKUP_DIR"

rsync -a --delete \
  --exclude node_modules \
  --exclude dist \
  --exclude .astro \
  ~/getsrv-static-src/ "$BACKUP_DIR/getsrv-static-src/"

2. Сделать backup production web-root

sudo rsync -a --delete /var/www/getsrv.app/ "$BACKUP_DIR/getsrv.app-www/"

Теперь есть две точки возврата:

$BACKUP_DIR/getsrv-static-src/
$BACKUP_DIR/getsrv.app-www/

3. Собрать проект

npm run build

Нормальный результат:

[build] Complete!

Стоп-условие: если build упал, не запускать rsync dist/.

4. Проверить обязательные страницы

test -f dist/index.html
test -f dist/ru/index.html
test -f dist/ru/docs/index.html
test -f dist/ru/tools/index.html
test -f dist/ru/docs/quickstart/index.html
test -f dist/ru/tools/headers-inspector/index.html

Если какой-то test -f упал, значит сборка неполная или путь изменился.

5. Проверить количество страниц

find dist -type f -name '*.html' | wc -l

Количество само по себе не гарантирует качество, но помогает заметить грубую ошибку.
Если вчера было 44, а сегодня стало 5 — деплой останавливаем.

6. Проверить ассеты

find dist/assets -maxdepth 1 -type f | sort

Нормально, если CSS/JS лежат в /assets/ и имеют хэшированные имена.

7. Проверить внешние runtime URL

grep -RInE 'https?://' dist --exclude='sitemap*.xml' --exclude='robots.txt' | grep -v 'https://getsrv.app' || true

Для автономного статического сайта нормальный вывод — пустой.

Если команда нашла сторонний URL, проверьте:

  • это ссылка в документации или runtime-зависимость;
  • не появился ли CDN;
  • не подключился ли внешний шрифт;
  • не появилась ли аналитика.

8. Выложить сборку

sudo rsync -a --delete dist/ /var/www/getsrv.app/
sudo find /var/www/getsrv.app -type d -exec chmod 755 {} \;
sudo find /var/www/getsrv.app -type f -exec chmod 644 {} \;
sudo chown -R www-data:www-data /var/www/getsrv.app

9. Проверить Nginx

sudo nginx -t

Если результат не syntax is ok и test is successful, reload не делаем.

10. Перечитать Nginx

sudo systemctl reload nginx

Для статического сайта reload достаточно. Полный restart обычно не нужен.

11. Проверить основные URL

curl -kI https://getsrv.app/
curl -kI https://getsrv.app/ru/
curl -kI https://getsrv.app/ru/docs/
curl -kI https://getsrv.app/ru/tools/
curl -kI https://getsrv.app/sitemap-index.xml
curl -kI https://getsrv.app/no-such-page

Ожидаемо:

/                      200
/ru/                   200
/ru/docs/              200
/ru/tools/             200
/sitemap-index.xml     200
/no-such-page          404

12. Проверить заголовки

HTML:

curl -kI https://getsrv.app/

Ожидаемо:

Cache-Control: public, must-revalidate
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
Referrer-Policy: strict-origin-when-cross-origin
Content-Security-Policy: ...

Asset:

ASSET="$(find /var/www/getsrv.app/assets -maxdepth 1 -type f | head -n 1 | sed 's#^/var/www/getsrv.app##')"
curl -kI "https://getsrv.app$ASSET"

Ожидаемо:

Cache-Control: public, max-age=31536000, immutable

13. Проверить listener’ы

sudo ss -lntp | grep -E ':(443|7443|10443|11443)\b'

При контентном обновлении listener’ы не должны измениться.

14. Быстрый rollback web-root

Если после выкладки сайт явно сломан, а backup уже сделан:

sudo rsync -a --delete "$BACKUP_DIR/getsrv.app-www/" /var/www/getsrv.app/
sudo chown -R www-data:www-data /var/www/getsrv.app
sudo nginx -t
sudo systemctl reload nginx

После rollback снова выполнить smoke-test.

15. Когда не продолжать

Остановитесь, если:

  • build не завершился;
  • dist/ пустой;
  • пропали обязательные страницы;
  • появились неожиданные внешние runtime URL;
  • nginx -t не прошёл;
  • production отдаёт 403 или 404 на главную;
  • headers отличаются от ожидаемых;
  • listener’ы изменились без причины.

Безопасный деплой — это не сложный деплой. Это деплой, где есть проверка до, проверка после и понятный путь назад.