Настройка nginx
На этой странице вручную пишутся файлы nginx, которые создаёт orionplace domain add: сайт на порту 80 для проверки сертификата, сертификат Let's Encrypt и HTTPS-сайт, который передаёт запросы службе витрины. В примерах — домен shop.example.com и витрина на порту 3000.
Как это работает
nginx принимает публичные запросы на портах 80 и 443. Порт 80 только отвечает на проверки сертификата и перенаправляет на HTTPS. HTTPS-сайт передаёт всё витрине на 127.0.0.1 и сообщает ей домен и адрес покупателя в заголовках запроса. Новые файлы лежат рядом с вашими сайтами и ни один из них не меняют.
1 Требования
Нужны nginx с поддержкой HTTPS, certbot и запущенная служба витрины, см. «Запуск витрины как службы». DNS-запись A домена, а также AAAA, если у сервера есть IPv6, должна указывать на этот сервер, а порты 80 и 443 должны быть открыты в файрволе сервера и в файрволе облачного провайдера.
Проверьте, что nginx поддерживает HTTPS, и посмотрите, какие файлы и папки он подключает:
nginx -V 2>&1 | grep -o http_ssl_module
nginx -T 2>/dev/null | grep -E "^ *include"Кладите файлы в папку, которую подключает блок http: /etc/nginx/conf.d на Debian, Ubuntu, семействе RHEL, Fedora, Amazon Linux и openSUSE, /etc/nginx/http.d на Alpine. В примерах — conf.d.
Arch Linux по умолчанию не подключает ни одной папки. Добавьте эту строку внутрь блока http в /etc/nginx/nginx.conf:
include /etc/nginx/conf.d/*.conf;2 Общие настройки
Один раз на сервер, на уровне http: этот map пропускает к витрине соединения, которые просят upgrade (WebSocket). Если в другом вашем файле уже есть такой map под другим именем, можно указать в сайте его.
map $http_upgrade $storefront_connection_upgrade {
default upgrade;
'' close;
}
Длинные имена доменов могут остановить nginx с ошибкой could not build server_names_hash. Тогда добавьте эту строку один раз в тот же файл, если её ещё не задаёт другой ваш файл: дважды nginx её не принимает.
server_names_hash_bucket_size 128;3 Сайт на порту 80
Создайте папку, куда certbot кладёт файлы проверки:
sudo mkdir -p /var/www/letsencrypt/.well-known/acme-challengeЗатем сохраните файл сайта. Он отвечает на проверки сертификата и показывает короткое уведомление, пока HTTPS не готов:
server {
listen 80;
listen [::]:80;
server_name shop.example.com www.shop.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
default_type text/plain;
}
location / {
default_type text/plain;
return 503 "The storefront for shop.example.com is being set up.";
}
}
Проверьте конфигурацию и загрузите её (на Alpine: sudo rc-service nginx reload):
sudo nginx -t
sudo systemctl reload nginx4 Сертификат
Получите один сертификат для домена и его имени с www. certbot кладёт файлы проверки в папку выше, поэтому nginx продолжает работать:
sudo certbot certonly --webroot -w /var/www/letsencrypt \
--cert-name shop.example.com -d shop.example.com -d www.shop.example.com \
--agree-tos --email you@example.comСертификат действует 90 дней. Пакет certbot продлевает его по таймеру; на Alpine добавьте ежедневное задание cron с certbot renew --quiet. После продления nginx нужно перезагрузить, чтобы он взял новый сертификат: добавьте deploy-хук (на Alpine с rc-service nginx reload), проверьте таймер и пробное продление:
sudo mkdir -p /etc/letsencrypt/renewal-hooks/deploy
printf '#!/bin/sh\nnginx -t && systemctl reload nginx\n' | sudo tee /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
sudo chmod 755 /etc/letsencrypt/renewal-hooks/deploy/reload-nginx
systemctl list-timers | grep -i certbot
sudo certbot renew --dry-run5 HTTPS-сайт
Замените файл сайта полной версией. Порт 80 теперь перенаправляет на HTTPS, www.shop.example.com — на shop.example.com, а HTTPS-сайт передаёт запросы витрине:
server {
listen 80;
listen [::]:80;
server_name shop.example.com www.shop.example.com;
location ^~ /.well-known/acme-challenge/ {
root /var/www/letsencrypt;
default_type text/plain;
}
location / {
return 301 https://shop.example.com$request_uri;
}
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name www.shop.example.com;
ssl_certificate /etc/letsencrypt/live/shop.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/shop.example.com/privkey.pem;
return 301 https://shop.example.com$request_uri;
}
server {
listen 443 ssl;
listen [::]:443 ssl;
http2 on;
server_name shop.example.com;
ssl_certificate /etc/letsencrypt/live/shop.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/shop.example.com/privkey.pem;
client_max_body_size 64m;
location / {
proxy_pass http://127.0.0.1:3000;
proxy_http_version 1.1;
proxy_set_header Host $host;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Front-Domain $host;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Init-Ip $remote_addr;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $storefront_connection_upgrade;
proxy_buffering off;
proxy_buffer_size 32k;
proxy_buffers 8 32k;
proxy_busy_buffers_size 64k;
proxy_read_timeout 120s;
}
}
| Строка | Что делает |
|---|---|
Host, X-Forwarded-Host | Домен, который открыл покупатель. |
X-Front-Domain | По этому домену витрина выбирает ваш персональный бэкенд. nginx всегда перезаписывает его запрошенным доменом, поэтому покупатель не может прислать другое значение. |
X-Forwarded-Proto | Сообщает витрине, что страница открыта по HTTPS. |
X-Real-IP, X-Forwarded-For, X-Init-Ip | Адрес покупателя; витрина передаёт его вашему бэкенду. |
Upgrade, Connection | Пропускает соединения, которые просят upgrade (WebSocket), вместе с map из «Общих настроек». |
proxy_buffering off | Отдаёт ответ покупателю по мере поступления, не дожидаясь всей страницы. |
proxy_buffer_size 32k | Место для больших заголовков ответа. Витрина на SvelteKit передаёт предзагрузку скриптов одним длинным заголовком; с размером по умолчанию 4 КБ nginx отвечает 502. |
proxy_read_timeout 120s | Ждёт медленный ответ до 120 секунд. |
client_max_body_size 64m | Принимает загрузки до 64 МБ, например фото к отзывам и аватары; по умолчанию у nginx 1 МБ. |
nginx старше 1.25.1 не знает http2 on;: удалите эти строки и допишите http2 в строки listen порта 443. nginx, собранному без HTTP/2, не нужно ни то, ни другое.
listen 443 ssl http2;
listen [::]:443 ssl http2;6 Рядом с существующими сайтами
Перед загрузкой сайта посмотрите, какие имена и адреса используют ваши другие сайты:
sudo nginx -T 2>/dev/null | grep -nE "server_name|listen|# configuration file"Каждый домен может обслуживать только один сайт. Если другой файл перечисляет shop.example.com или www.shop.example.com, nginx предупреждает conflicting server name и использует только один из них: уберите имя из одного из файлов. Маску вроде *.example.com в другом сайте менять не нужно: точные имена важнее неё.
Если другой сайт слушает конкретный адрес, например listen 203.0.113.5:443 ssl;, запросы на этот адрес nginx отдаёт только сайтам с такой же строкой listen: добавьте её и в эти блоки server. Если у другого сайта есть listen [::]:80 ipv6only=off;, удалите здесь listen 80;: та строка уже принимает и IPv4.
7 Проверка
Проверьте конфигурацию, загрузите её и откройте витрину:
sudo nginx -t
sudo systemctl reload nginx
curl -I https://shop.example.com/Ответ со статусом 200 означает, что витрина в сети. 502 — nginx не достучался до витрины: проверьте службу и её порт. 503 от витрины — домен не добавлен в проект.