Статьи Nazara
Как разместить статический сайт на VPS с Nginx и HTTPS
Как опубликовать статический сайт на VPS: загрузить сборку, настроить Nginx и домен, подключить HTTPS, закрыть служебные файлы и подготовить откат.
Чтобы разместить статический сайт на VPS, подготовьте готовую сборку, загрузите её в отдельный каталог, настройте Nginx на этот каталог, направьте домен на сервер и только после проверки HTTP подключайте HTTPS. Публикация считается завершённой, когда по публичному адресу открываются страницы и ресурсы, неизвестные пути возвращают 404, сертификат обновляется автоматически, а предыдущую версию можно быстро вернуть.
Инструкция рассчитана на Ubuntu или Debian и сайт из HTML, CSS, JavaScript, изображений и других готовых файлов. Для приложения с серверным рендерингом, API, PHP или Node.js одной раздачи файлов недостаточно: понадобится отдельный процесс приложения и reverse proxy. Команды ниже служат образцом порядка действий; домен, пользователя и каталоги замените на свои.
Что подготовить до загрузки сайта
Начните не с установки программ, а с проверки исходных условий. Нужны VPS с административным доступом, домен, возможность менять DNS-записи и готовая production-сборка сайта. Если проект собирается командой вроде npm run build, на сервер следует передавать результат сборки, а не dev-сервер и не весь рабочий каталог.
Откройте локальный файл index.html через небольшой HTTP-сервер и пройдите основные страницы. Проверьте относительные пути, изображения, шрифты, формы и ссылки. Ошибку сборки лучше увидеть до загрузки: Nginx исправно отдаст и неправильно собранный сайт, но не сможет восстановить отсутствующий файл или неверный адрес ресурса.
Убедитесь, что в публикацию не попадают .env, ключи, исходные карты с чувствительными данными, архивы, заметки разработчика, .git и служебные инструкции. Статический каталог доступен посетителю напрямую, поэтому файл нельзя считать закрытым только потому, что на него нет ссылки в меню.
Перед работой с публичным сервером настройте безопасный вход по инструкции как настроить SSH на VPS. Общие обновления, firewall, резервные копии и контроль после перезагрузки собраны в материале что настроить на VPS после покупки.
Как организовать каталоги и загрузить файлы
Для сайта выделите собственный каталог вне домашней папки администратора. Удобная схема состоит из папки проекта, каталога выпусков и ссылки current на активную версию:
/var/www/example-site/
├── releases/
│ ├── 20261008-0900/
│ └── 20261008-1130/
└── current -> releases/20261008-1130
Каждый выпуск загружается в новую папку. Nginx читает файлы через current, поэтому при обновлении не приходится смешивать старую и новую сборку. Предыдущий выпуск остаётся рядом как короткий путь отката. Количество сохранённых версий ограничьте заранее, но не удаляйте рабочую копию до завершения проверки.
Передавайте сборку по SSH с помощью scp, rsync или проверенного процесса деплоя. Сначала создайте новый каталог, затем загрузите файлы и только после этого меняйте активную ссылку. Не распаковывайте неизвестный архив сразу в /var/www: проверьте список файлов, отсутствие абсолютных путей и символических ссылок на каталоги вне проекта.
Владелец файлов должен быть понятен. Nginx обычно достаточно права чтения; давать его рабочему процессу право изменять HTML и JavaScript не требуется. Администратор или отдельный пользователь деплоя загружает выпуск, а веб-сервер читает его. Права 777 не решают проблему владения и открывают ненужную запись всем локальным процессам.
После загрузки убедитесь, что в корне выпуска есть index.html, а все файлы ресурсов читаются пользователем Nginx. Сравните количество и контрольные суммы важных файлов с локальной сборкой. Так можно отличить ошибку передачи от ошибки конфигурации веб-сервера.
Как настроить Nginx для статического сайта
Установите Nginx штатным способом для выбранной системы и создайте отдельный server block для домена. Официальное руководство Nginx объясняет, как директива root связывает адрес запроса с файлом и почему перед применением конфигурации нужно проверить её синтаксис.
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example-site/current;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
server_name определяет домены этого блока, root указывает на активный выпуск, а try_files проверяет существование файла или каталога. Вариант с =404 подходит обычному многостраничному статическому сайту: несуществующий адрес не превращается в главную страницу.
Для одностраничного приложения с маршрутизацией в браузере иногда используют try_files $uri $uri/ /index.html;. Это отдельное решение, а не универсальная настройка. При таком fallback служебный путь вроде /.env тоже может получить HTML с кодом 200, если его не заблокировать отдельным правилом до общего location /.
Перед применением выполните проверку и только затем перечитайте конфигурацию:
sudo nginx -t
sudo systemctl reload nginx
sudo systemctl status nginx
Если nginx -t сообщает об ошибке, не перезапускайте службу в надежде, что она исчезнет. Исправьте указанный файл и строку, повторите тест и сохраните работающую конфигурацию. Для диагностики проверяйте код ответа, access log и error log, а не только внешний вид главной страницы.
Как направить домен на VPS и проверить ответ
Создайте A-запись домена с публичным IPv4-адресом VPS. AAAA-запись добавляйте только тогда, когда на сервере действительно настроен IPv6 и Nginx принимает соединения по нему. Ошибочная AAAA-запись может направить часть посетителей на неработающий адрес, хотя проверка по IPv4 будет успешной.
До изменения DNS можно проверить server block локально, подставив домен и IP в запрос:
curl --resolve example.com:80:203.0.113.10 http://example.com/
curl --resolve example.com:80:203.0.113.10 -I http://example.com/
Затем проверьте фактические записи командами dig +short example.com A и, если используется IPv6, dig +short example.com AAAA. Ответ должен содержать адрес нужного сервера. Время обновления зависит от предыдущего TTL, кэша резолверов и настроек DNS-провайдера, поэтому не обещайте точный срок переключения без проверки.
По публичному HTTP-адресу откройте главную, вложенную страницу, CSS, JavaScript и изображение. Отдельно запросите несуществующий путь и служебный файл. Успешная главная страница не подтверждает, что все ресурсы загружены и закрытые адреса возвращают 403 или 404.
Как подключить HTTPS и проверить продление сертификата
Выпускайте сертификат после того, как домен уже указывает на сервер и сайт отвечает по HTTP. Certbot может получить сертификат и дополнить конфигурацию Nginx. Актуальную команду установки выбирайте на странице официальных инструкций Certbot для Nginx, потому что рекомендуемый способ зависит от системы и способа установки.
Для HTTP-01 проверки центр сертификации запрашивает специальный файл на домене через порт 80. Документация Let’s Encrypt о HTTP-01 прямо указывает, что этот тип проверки выполняется только через порт 80. Значит, DNS, входящий HTTP и маршрут /.well-known/acme-challenge/ должны работать до выпуска сертификата.
sudo certbot --nginx -d example.com -d www.example.com
sudo certbot renew --dry-run
Не добавляйте имя www, если для него нет DNS-записи и сайт не должен по нему открываться. После выпуска проверьте оба заявленных имени, перенаправление с HTTP на HTTPS, дату сертификата и отсутствие предупреждений браузера. Команда renew --dry-run проверяет механизм продления; одного установленного сертификата недостаточно.
Не включайте HSTS до устойчивой работы HTTPS на всех нужных поддоменах. Этот заголовок заставляет браузер обращаться только по HTTPS, поэтому преждевременная настройка усложнит восстановление. Сначала подтвердите сертификат и автоматическое продление, затем вводите HSTS осознанно.
Какие сетевые и файловые ограничения добавить
Публичному статическому сайту обычно нужны входящие соединения к SSH, HTTP и HTTPS. Сначала сохраните проверенный доступ по SSH, затем разрешайте веб-порты и включайте firewall. В документации Ubuntu по UFW показано, как просматривать правила и открывать конкретные порты. Не копируйте правила вслепую, если SSH работает на другом порту или доступ ограничен сетью.
На уровне Nginx явно закройте dotfiles, архивы, конфигурацию и рабочие документы. Запрет должен находиться до SPA fallback и возвращать 403 или 404 без передачи запроса приложению. Проверьте как минимум /.env, /.git/config, /AGENTS.md и тестовый архив.
location ~ /\. {
deny all;
}
location ~* \.(?:zip|tar|tgz|sql|bak)$ {
deny all;
}
Добавьте базовые заголовки: X-Content-Type-Options: nosniff, разумный Referrer-Policy и запрет встраивания через CSP frame-ancestors либо X-Frame-Options. Полную Content Security Policy нельзя безопасно скопировать из чужого примера: она зависит от аналитики, шрифтов, форм и внешних API. Сначала включите её в тестовой среде и проверьте консоль браузера.
Не храните deploy-архивы в web-root даже при запрете расширений. Конфигурация со временем меняется, а файл может получить другое имя. В публичном каталоге должны находиться только файлы, которые посетителю разрешено скачать.
Как обновлять сайт и быстро возвращать рабочую версию
Каждое обновление собирайте и проверяйте локально, затем загружайте в новый каталог выпуска. Не копируйте файлы поверх активной версии по одному: во время передачи посетитель может получить новый HTML со старым JavaScript или наоборот. После полной загрузки переключите ссылку current на новый выпуск одной операцией.
После переключения запросите главную и ключевые страницы по публичному HTTPS-адресу, проверьте ресурсы, формы, аналитику, canonical и код 404. Если обнаружена ошибка, верните current на предыдущий каталог и повторите проверку. Наличие старой папки ещё не является планом отката: команда переключения и контрольный список должны быть записаны заранее.
Резервная копия нужна отдельно от выпусков. Версии сайта помогают вернуть код, но не спасают при потере диска VPS и не содержат внешние данные формы или настройки DNS. План копирования и тест восстановления разобран в статье как настроить резервное копирование VPS.
Добавьте внешний контроль HTTPS-страницы и срока сертификата. После каждого релиза полезна короткая smoke-проверка, а постоянное наблюдение должно сообщать о недоступности независимо от самого сервера. Подход к сигналам и уведомлениям описан в статье как настроить мониторинг VPS.
Интерактивный чек-лист
Проверка публикации статического сайта
Отмечайте пункты после фактической проверки. Прогресс сохранится в этом браузере.
Если нужно проверить Вашу сборку, домен и план публикации до изменений на сервере, опишите задачу в Умной форме. В сообщении достаточно указать тип сайта, текущий адрес и что уже настроено.
Частые вопросы
Нужно ли устанавливать Node.js на VPS для статического сайта
Нет, если на сервер загружается уже готовая сборка из HTML, CSS, JavaScript и изображений. Node.js нужен на сервере только тогда, когда сборка выполняется там или проект содержит работающий серверный процесс.
Почему главная открывается, а вложенная страница возвращает 404
Проверьте, существует ли соответствующий файл или каталог в сборке и какой режим маршрутизации использует проект. Для обычного сайта нужен реальный файл, а SPA может требовать fallback на index.html.
Можно ли выпустить сертификат до настройки DNS
Для обычной HTTP-01 проверки домен должен вести на сервер, а порт 80 — быть доступен центру сертификации. Сначала добейтесь корректного HTTP-ответа по домену, затем запускайте Certbot.
Зачем оставлять порт 80 после включения HTTPS
Он используется для перенаправления посетителей на HTTPS и может участвовать в HTTP-01 продлении сертификата. Не закрывайте его, пока не подтвержден другой способ проверки и продления.
Почему нельзя хранить архив деплоя рядом с index.html
Файл в web-root может стать доступным по прямому адресу и раскрыть исходники, конфигурацию или старые данные. Архивы храните вне публичного каталога, даже если сейчас Nginx запрещает их расширение.
Как понять, что обновление прошло успешно
Проверьте публичный HTTPS-адрес, ключевые страницы и ресурсы, форму, аналитику, 404, заголовки и журналы Nginx. Затем убедитесь, что внешний мониторинг видит новую версию, а возврат на предыдущий выпуск остаётся возможным.