Чек-лист безопасного деплоя
Это более подробная версия быстрого старта.
Используйте её, когда изменения не хочется выкладывать “на глаз”: обновили структуру, добавили несколько страниц, поменяли 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’ы изменились без причины.
Безопасный деплой — это не сложный деплой. Это деплой, где есть проверка до, проверка после и понятный путь назад.