Nginx — конфиги под задачу
Приветствую! Здесь вы наверняка найдете, что ищете. Примеры в лаборатории рассчитаны на то, что мы разбираем что-то конкретное.
Текущая статья посвящена примерам: nginx.conf для статики, reverse proxy, React/Vue SPA, PHP, SSL и балансировки.
Поэтому за теорией по текущей теме вам — в энциклопедию. Если ещё не погружались, то маршрут прост:
- Основы
- Система и сеть
- Данные и разметка
- Код и разработка
- Языки
- Искусственный интеллект
- Проект
- Инфраструктура и безопасность
- Спин-офф
Обязательно пройдитесь.
А теперь приступим к нашему предмету.
Полный справочник директив — Nginx.
Как веб-сервер вписан в цепочку «DNS → HTTP → приложение» — веб-серверы.
Nginx в Docker — готовые стеки Compose.
Проверка ответов — curl.
Разбор конфига по частям
Nginx читает конфиг сверху вниз. Директива заканчивается ;, блок — { }. Запрос попадает в один блок server (по порту и домену), затем nginx выбирает один location (по URL).
Блоки (контексты)
| Блок | Зачем нужен |
|---|---|
events { } |
Сколько соединений держит один рабочий процесс |
http { } |
Всё про HTTP — MIME, gzip, upstream, include сайтов |
server { } |
Один «виртуальный хост» — домен + порт + корень сайта |
location /path { } |
Правило для URL, начинающегося с /path |
upstream имя { } |
Список бэкендов для балансировки и proxy |
Частые директивы
| Директива | Смысл простыми словами |
|---|---|
listen 80 |
Слушать порт 80 (обычный HTTP) |
listen 443 ssl |
Слушать HTTPS |
server_name example.com |
Этот блок срабатывает, если в запросе Host: example.com |
root /var/www/site |
Папка на диске: URL /img/a.png → файл /var/www/site/img/a.png |
index index.html |
Если URL — каталог, отдать этот файл |
try_files $uri … |
Порядок «найти файл на диске или сделать fallback» |
proxy_pass http://… |
Не искать файл — отправить запрос другому серверу |
return 301 URL |
Сразу ответ «перейди по другому адресу» |
include файл |
Подключить ещё один конфиг |
Переменные — «подстановки» в конфиге
| Переменная | Откуда берётся | Пример значения |
|---|---|---|
$uri |
Путь запроса без query | /api/users |
$request_uri |
Путь и query | /api/users?page=1 |
$host |
Заголовок Host |
shop.example.com |
$remote_addr |
IP клиента | 203.0.113.5 |
$scheme |
http или https |
https |
$document_root |
Значение root |
/var/www/site |
Два адреса для proxy_pass — самая частая путаница на лабораторных:
| Ситуация | Пишите в proxy_pass |
|---|---|
| Nginx и app на одной Linux-машине | http://127.0.0.1:3000 |
| Nginx в Docker, app — другой контейнер | http://api:3000 (имя сервиса из compose) |
127.0.0.1 внутри контейнера nginx — это сам контейнер, не ваш ПК и не соседний сервис.
Порядок действий
- Конфиги на Ubuntu/Debian —
/etc/nginx/, главныйnginx.conf, сайты вconf.d/*.confилиsites-enabled/. - Сохраните фрагмент, например
/etc/nginx/conf.d/my-site.conf. - Проверка и перезагрузка:
sudo nginx -t
sudo systemctl reload nginx
- Смотрите ответ:
curl -I http://localhost
curl -I -H "Host: shop.local" http://127.0.0.1
- Логи: ошибки —
/var/log/nginx/error.log, все запросы —access.log.
Правка /etc/nginx/ — через sudo. Ключ TLS (ssl_certificate_key) не кладите в Git. Домены и пути в примерах замените на свои.
Обязательный каркас
Перед любым примером ниже — минимальный nginx.conf (или один файл в conf.d/, если в главном уже есть include /etc/nginx/conf.d/*.conf;):
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# server { } из примеров — сюда или в conf.d/
}
| Строка | Что делает |
|---|---|
events { worker_connections 1024; } |
Без блока events nginx не запустится |
include mime.types |
Сопоставляет .css → text/css, .js → application/javascript |
default_type application/octet-stream |
Если расширение неизвестно — отдать как «сырые байты» |
sendfile on |
Ядро ОС отдаёт файл с диска быстрее, без лишнего копирования в память |
keepalive_timeout 65 |
Держать HTTP-соединение открытым до 65 с (меньше рукопожатий TCP) |
Что делает команда проверки:
sudo nginx -t
- Nginx читает все
includeи склеивает конфиг в памяти. - Проверяет синтаксис (скобки, точки с запятой, директивы в правильном блоке).
- Печатает
syntax is okиtest is successful— только после этого безопасенreload.
Стартовые конфиги
Пять сценариев, которые чаще всего ищут на первых курсах — от HTML на диске до прокси на backend.
1. Статический сайт — «Hello»
Задача: отдать готовый index.html с диска. Подходит для лабораторной «поднять веб-сервер», для простой визитки или папки dist/ после сборки фронта без client-side роутинга.
Когда искать этот конфиг: «nginx отдача статики», «nginx index.html», «nginx root try_files».
server {
listen 80;
server_name localhost;
root /var/www/hello;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
| Строка | Смысл |
|---|---|
server { … } |
Один виртуальный хост — набор правил для домена |
listen 80 |
Принимать HTTP на порту 80 |
server_name localhost |
Блок выбирается, если браузер шлёт Host: localhost |
root /var/www/hello |
URL /logo.png → файл /var/www/hello/logo.png |
index index.html |
Запрос / или /about/ → попробовать index.html в каталоге |
location / |
Правило для любого пути (префикс /) |
try_files $uri $uri/ =404 |
1) файл как есть 2) каталог + index 3) иначе ошибка 404 |
Что происходит по шагам (запрос GET /):
- Nginx выбирает этот
server(порт 80,Host: localhost). - Путь
/попадает вlocation /. try_files: ищет файл/— нет; ищет каталог/var/www/hello/— есть.- Из-за
index index.htmlотдаёт/var/www/hello/index.htmlсо статусом 200.
Что происходит (запрос GET /missing.txt):
- Файла
/var/www/hello/missing.txtнет, каталога/var/www/hello/missing.txt/тоже нет. =404— nginx отвечает 404 Not Found.
| URL | Файл на диске | Ответ |
|---|---|---|
/ |
index.html есть |
200, HTML |
/style.css |
style.css есть |
200, CSS |
/nope |
ничего нет | 404 |
Подготовка и проверка:
sudo mkdir -p /var/www/hello
echo '<h1>Hello from Nginx</h1>' | sudo tee /var/www/hello/index.html
sudo nginx -t && sudo systemctl reload nginx
curl -i http://localhost/
Что делает код:
mkdir -p— создаёт каталог для файлов сайта.tee— записывает HTML (от root, если нет прав у обычного пользователя).nginx -t— проверка конфига до reload.curl -i— показывает заголовки и тело; в теле должен быть ваш<h1>.
Частая ошибка: забыли index index.html — для / nginx вернёт 403 Forbidden (каталог есть, но «листинг» по умолчанию запрещён).
2. Редирект HTTP → HTTPS
Задача: весь трафик с порта 80 перенаправить на HTTPS. Браузер сам откроет https://…, пользователь не вводит протокол вручную.
Когда искать: «nginx redirect http to https», «nginx return 301 ssl».
server {
listen 80;
server_name example.com www.example.com;
return 301 https://$host$request_uri;
}
| Строка | Смысл |
|---|---|
server_name example.com www.example.com |
Оба домена — с www и без |
return 301 https://… |
Ответ без тела: «навсегда переехали» (код 301) |
$host |
Подставится домен из запроса (example.com или www.example.com) |
$request_uri |
Путь и ?query=… сохраняются |
Что происходит по шагам (GET http://example.com/old-page?q=1):
- Запрос приходит на порт 80.
- Nginx не ищет файлы — сразу
return 301. - В заголовке
Location: https://example.com/old-page?q=1. - Браузер повторяет запрос уже на порт 443 (нужен отдельный блок с SSL — пример №8).
| Запрос | Заголовок Location |
|---|---|
http://example.com/ |
https://example.com/ |
http://www.example.com/blog/1 |
https://www.example.com/blog/1 |
Проверка:
curl -I http://example.com/old-page?q=1
В выводе ищите строку HTTP/1.1 301 и Location: https://….
Частая ошибка: есть редирект с 80, но нет server { listen 443 ssl; … } — браузер после редиректа получит «connection refused» или ошибку сертификата.
3. SPA — fallback на index.html
Задача: React, Vue, Angular, Vite после npm run build — при обновлении страницы по адресу /users/42 nginx отдаёт index.html, а маршрутизацию делает JavaScript в браузере.
Когда искать: «nginx react router», «nginx vue history mode», «try_files index.html spa».
| Строка | Смысл |
|---|---|
root …/dist |
Сюда копируют результат npm run build (папка dist/ или build/) |
try_files … /index.html |
Нет файла для пути — отдать один index.html (shell приложения) |
| `location ~* .(js | css…)$` |
~* |
Регистронезависимое совпадение (.PNG тоже) |
expires 7d |
Браузер может кэшировать файл 7 дней |
Cache-Control "public, immutable" |
Файлы с хешем в имени (app.a1b2c3.js) не перезапрашивать зря |
Что происходит по шагам (GET /dashboard после F5):
- Nginx ищет файл
/var/www/spa/dist/dashboard— нет. - Ищет каталог
dashboard/— нет. - Внутренний переход на
/index.html— отдаёт SPA, статус 200 (это важно: SPA ожидает 200, а не 404).
Что происходит (GET /assets/index-a1b2.js):
- Совпадает второй
location(расширение.js). - Отдаётся реальный файл из
dist/assets/с заголовками кэша.
| URL | Есть файл в dist? | Ответ |
|---|---|---|
/ |
index.html |
200, HTML |
/dashboard |
только index.html |
200, тот же HTML |
/assets/app.js |
да | 200, JS + Cache-Control |
Проверка:
curl -I http://app.local/dashboard
curl -I http://app.local/assets/index.js
Первый запрос — 200 и Content-Type: text/html. Второй — 200 и длинный Cache-Control.
Частая ошибка: забыли /index.html в try_files — F5 на /profile даёт 404, хотя в приложении страница открывалась по клику.
4. Reverse proxy на Node.js / Python / Go
Задача: снаружи пользователь ходит на порт 80, nginx передаёт запрос приложению на 127.0.0.1:3000 (Express, FastAPI, Flask, Gin и т.д.).
Когда искать: «nginx reverse proxy nodejs», «nginx proxy_pass localhost 3000», «nginx fastapi».
| Строка | Смысл |
|---|---|
upstream app_backend |
Именованная группа бэкендов (позже добавите второй server для балансировки) |
keepalive 32 |
До 32 idle-соединений nginx → app (меньше накладных расходов TCP) |
proxy_pass http://app_backend |
Запрос уходит на app, ответ nginx отдаёт клиенту |
proxy_http_version 1.1 |
HTTP/1.1 нужен для keepalive к бэкенду |
Host $host |
App видит реальный домен (api.local), а не 127.0.0.1 |
X-Real-IP |
IP клиента (для логов и rate limit в приложении) |
X-Forwarded-For |
Цепочка IP через прокси |
X-Forwarded-Proto |
http или https — app строит правильные ссылки |
Connection "" |
Сброс Connection: close — иначе keepalive к upstream ломается |
Что происходит по шагам (GET http://api.local/api/users):
- Nginx принимает запрос на :80.
location /— проксирует весь путь на127.0.0.1:3000/api/users.- Node/Python отвечает JSON.
- Nginx возвращает тот же статус и тело клиенту.
Схема:
Браузер → :80 nginx → :3000 приложение
↑ proxy_set_header добавляет заголовки
Проверка (app уже слушает 3000):
# Терминал 1 — простой backend
python -m http.server 3000
# Терминал 2 — через nginx
curl -i http://api.local/
Что делает код:
python -m http.server 3000— временный HTTP-сервер для проверки (на лабораторной вместо него — ваш Express/FastAPI).curl -i— если nginx настроен, увидите ответ app через прокси (в access.log nginx — запись запроса).
API под префиксом /api/ — отдельный location и слэш в конце proxy_pass:
location /api/ {
proxy_pass http://127.0.0.1:3000/;
proxy_set_header Host $host;
}
| Запрос клиента | Что получит backend |
|---|---|
/api/users |
/users |
/api/health |
/health |
Слэш после 3000/ отрезает префикс /api/ — это самый частый «тихий» баг на лабораторных (backend ждёт /api/users, а приходит /users или наоборот).
Частая ошибка: 502 Bad Gateway — app не запущен или слушает другой порт. Проверка: curl http://127.0.0.1:3000 минуя nginx.
5. PHP через PHP-FPM
Задача: .html и картинки — как файлы, .php — выполнить через PHP-FPM (Laravel, Symfony, WordPress, учебные скрипты).
Когда искать: «nginx php-fpm config», «nginx laravel public», «fastcgi_pass unix sock».
| Строка | Смысл |
|---|---|
root …/public |
У Laravel/Symfony открыт только каталог public/ — там index.php |
index index.php index.html |
Сначала PHP, потом HTML |
try_files … /index.php?$query_string |
Front controller — все «красивые» URL идут в index.php |
location ~ \.php$ |
Любой URL, заканчивающийся на .php |
include fastcgi_params |
Стандартный набор параметров для PHP |
fastcgi_pass unix:…sock |
Сокет процесса PHP-FPM (путь зависит от версии PHP и ОС) |
SCRIPT_FILENAME |
Полный путь к скрипту на диске — обязательная строка |
fastcgi_intercept_errors on |
Ошибки PHP можно обработать через error_page в nginx |
location ~ /\. |
Запрет .env, .git, .htaccess по HTTP |
Что происходит по шагам (GET /index.php):
- Совпадает
location ~ \.php$. - Nginx не отдаёт файл как текст — передаёт в FPM через сокет.
- FPM выполняет PHP, возвращает HTML.
- Nginx отдаёт HTML клиенту.
Что происходит (GET /users/list в Laravel):
location /→try_filesне находит файл.- Внутренний запрос
/index.php?(query из$query_string). - Laravel роутит
/users/listвнутри приложения.
| URL | Результат |
|---|---|
/index.php |
Выполнение PHP |
/style.css |
Статический файл |
/.env |
403 Forbidden (блок ~ /\.) |
/index.php скачивается как файл |
Сломан location ~ \.php$ или FPM не запущен |
Проверка:
sudo systemctl status php8.3-fpm
curl -i http://php.local/index.php
ls -la /run/php/php8.3-fpm.sock
Частая ошибка: root указывает на корень репозитория, а не на public/ — в браузере открывается структура проекта, .env может стать доступен без правильного location ~ /\..
Конфиги для типовых задач
Сценарии для VPS, нескольких сайтов, HTTPS, WebSocket и защиты.
6. Два сайта на одном IP
Задача: один сервер, один IP, разные домены — shop.local и blog.local с разными папками.
Когда искать: «nginx несколько сайтов», «nginx virtual host», «nginx server_name».
| Строка | Смысл |
|---|---|
Два блока server |
Два «сайта» на одном порту 80 |
Разный server_name |
Nginx смотрит заголовок Host и выбирает блок |
Разный root |
Файлы магазина и блога не смешиваются |
Что происходит по шагам:
- Оба блока слушают
:80. - Запрос с
Host: shop.local→ первыйserver, файлы из/var/www/shop. - Запрос с
Host: blog.local→ второйserver.
Проверка без DNS (с /etc/hosts или просто curl):
curl -H "Host: shop.local" http://127.0.0.1/
curl -H "Host: blog.local" http://127.0.0.1/
Частая ошибка: оба домена показывают один сайт — в /etc/hosts на клиенте неверный IP или сработал default_server (первый listen 80 default_server ловит чужие Host).
7. Балансировка между двумя app-серверами
Задача: распределить нагрузку между app1:8080 и app2:8080, временно отключать «упавший» инстанс.
| Строка | Смысл |
|---|---|
least_conn |
Запрос на сервер с меньшим числом активных соединений |
max_fails=3 |
После 3 неудачных попыток сервер считается недоступным |
fail_timeout=30s |
30 с не слать на него трафик, потом проверить снова |
proxy_next_upstream … |
При 502/503 повторить запрос на другом сервере из pool |
Что происходит: nginx по очереди или по least_conn выбирает backend; если app1 вернул 502, клиент может получить ответ от app2 (если включён proxy_next_upstream).
8. HTTPS с Let's Encrypt (Certbot)
Задача: шифрование TLS после получения сертификата (certbot certonly или certbot --nginx).
| Строка | Смысл |
|---|---|
listen 443 ssl http2 |
HTTPS + мультиплексирование HTTP/2 |
fullchain.pem |
Сертификат сайта + промежуточные CA |
privkey.pem |
Закрытый ключ (доступ только root/nginx) |
ssl_protocols TLSv1.2 TLSv1.3 |
Старые небезопасные версии SSL отключены |
Сертификат Let's Encrypt живёт ~90 дней; certbot ставит timer для продления. После продления: sudo nginx -t && sudo systemctl reload nginx.
Проверка:
curl -I https://example.com
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -dates
9. WebSocket через reverse proxy
Задача: чат, live-лenta, Socket.io — соединение «апгрейдится» с HTTP до WebSocket.
| Строка | Смысл |
|---|---|
map $http_upgrade … |
Если клиент шлёт Upgrade: websocket → Connection: upgrade, иначе close |
Upgrade / Connection |
Обязательные заголовки для WebSocket handshake |
proxy_read_timeout 86400 |
24 ч — прокси не рвёт «висящее» WS-соединение по умолчанию (60 с) |
Что происходит: обычный GET с Upgrade: websocket nginx проксирует на backend; дальше идёт двусторонний поток сообщений.
10. Rate limit — защита от флуда
Задача: ограничить число запросов с одного IP на /login (brute-force, DDoS на уровне приложения).
# Эту строку — один раз внутри http { }, не внутри server { }
limit_req_zone $binary_remote_addr zone=login_limit:10m rate=10r/s;
server {
listen 80;
server_name secure.local;
location /login {
limit_req zone=login_limit burst=20 nodelay;
proxy_pass http://127.0.0.1:3000;
}
}
| Строка | Смысл |
|---|---|
limit_req_zone |
Создаёт «карту» лимитов в памяти (10 МБ под IP) |
$binary_remote_addr |
Ключ — IP клиента в компактном виде |
rate=10r/s |
В среднем 10 запросов в секунду с IP |
burst=20 nodelay |
Разрешить «всплеск» до 20, без очереди |
limit_req zone=… |
Применить лимит в конкретном location |
При превышении — 503 (можно сменить на 429: limit_req_status 429; в location).
Частая ошибка: limit_req_zone внутри server — nginx -t выдаст directive is not allowed here.
11. Gzip и заголовки безопасности
Задача: уменьшить размер HTML/JSON/CSS и добавить базовые заголовки защиты браузера.
| Строка | Смысл |
|---|---|
gzip on |
Сжимать ответы, если клиент шлёт Accept-Encoding: gzip |
gzip_min_length 256 |
Мелкие ответы не сжимать (накладные расходы) |
X-Frame-Options SAMEORIGIN |
Запрет встраивать сайт в <iframe> на чужих доменах (clickjacking) |
X-Content-Type-Options nosniff |
Браузер не «угадывает» MIME |
add_header … always |
Заголовок даже при 404/500 |
Проверка gzip:
curl -H "Accept-Encoding: gzip" -I http://safe.local/
В ответе должно быть Content-Encoding: gzip (для достаточно большого HTML).
12. Nginx в Docker — свой conf через volume
Задача: свой default.conf без пересборки образа. Дополнение к стекам Compose.
nginx-proxy/
compose.yaml
conf/
default.conf
html/
index.html
compose.yaml:
services:
web:
image: nginx:1.27-alpine
ports:
- "8080:80"
volumes:
- ./conf/default.conf:/etc/nginx/conf.d/default.conf:ro
- ./html:/usr/share/nginx/html:ro
| Строка | Смысл |
|---|---|
"8080:80" |
localhost:8080 на ПК → порт 80 в контейнере |
./conf/default.conf:…:ro |
Ваш конфиг поверх дефолтного в образе |
./html:…:ro |
Статика с хоста, read-only |
conf/default.conf:
server {
listen 80;
server_name localhost;
root /usr/share/nginx/html;
index index.html;
location / {
try_files $uri $uri/ =404;
}
}
Что делает код:
docker compose up -d
curl -I http://localhost:8080/
docker compose exec web nginx -t
- Поднимается контейнер с вашим conf и html.
curlпроверяет проброс порта.exec web nginx -t— синтаксис внутри контейнера (удобно при отладке mount).
Шпаргалка — слэш в proxy_pass
Самый частый вопрос на Stack Overflow и лабораторных:
location |
proxy_pass |
Запрос клиента | URI на backend |
|---|---|---|---|
/api/ |
http://127.0.0.1:3000/ |
/api/users |
/users |
/api/ |
http://127.0.0.1:3000 |
/api/users |
/api/users |
/ |
http://127.0.0.1:3000 |
/users |
/users |
Правило: если в proxy_pass есть URI (хотя бы / в конце) — nginx заменяет совпавший префикс location на этот URI. Если URI в proxy_pass нет — на backend уходит полный путь клиента.
Шпаргалка — root и alias
| Директива | URL | Путь на диске |
|---|---|---|
root /var/www; + location /img/ |
/img/a.png |
/var/www/img/a.png |
alias /var/static/; + location /img/ |
/img/a.png |
/var/static/a.png |
alias отрезает префикс location из пути; для /static/ часто пишут именно alias, а не root.
Каркас проверки — скрипт для лабораторной
Сохраните и подставляйте свой домен:
#!/bin/bash
DOMAIN="${1:-localhost}"
URL="http://${DOMAIN}/"
echo "=== nginx -t ==="
sudo nginx -t || exit 1
echo "=== HTTP HEAD ==="
curl -sI "$URL" | head -n 15
echo "=== последние ошибки ==="
sudo tail -n 5 /var/log/nginx/error.log
Что делает код:
$1— домен из аргумента (./check.sh shop.local) илиlocalhost.nginx -t— выход с ошибкой, если конфиг битый.curl -sI— только заголовки, первые 15 строк (статус,Content-Type,Location).tail error.log— последние причины 502/403/permission denied.
Шпаргалка команд
| Задача | Команда | Пояснение |
|---|---|---|
| Проверка синтаксиса | sudo nginx -t |
Обязательно перед reload |
| Перезагрузка | sudo systemctl reload nginx |
Без обрыва текущих соединений |
| Статус | systemctl status nginx |
active (running) / failed |
| Ошибки | sudo tail -f /var/log/nginx/error.log |
502, permission denied, unknown directive |
| Запросы | sudo tail -f /var/log/nginx/access.log |
IP, код, URL, User-Agent |
| Весь конфиг | sudo nginx -T 2>/dev/null | less |
С комментариями # configuration file |
| Виртуальный Host | curl -H "Host: shop.local" http://127.0.0.1/ |
Тест vhost без DNS |
| Заголовки HTTPS | curl -I https://example.com |
Сертификат, редиректы, HSTS |
Типичные ошибки новичка
| Ошибка | Симптом | Как исправить |
|---|---|---|
Пропустили nginx -t |
reload failed, сайт «старый» или down | всегда -t, читать stderr |
Слэш в proxy_pass |
404 на backend, «route not found» | таблица выше, сверить с API |
root вместо alias |
/static/static/app.js |
alias для префикса или поправить путь |
| PHP скачивается | браузер предлагает сохранить .php |
location ~ \.php$, запущен php-fpm |
| 502 Bad Gateway | белая страница nginx | curl напрямую на backend-порт |
| Permission denied | 403, в error.log «permission denied» | www-data должен читать root |
| Два default_server | по IP открывается «чужой» сайт | один listen 80 default_server |
limit_req_zone в server |
nginx -t падает | зона только в http { } |
| SPA без fallback | F5 на /page → 404 |
try_files … /index.html |
127.0.0.1 в Docker |
502 из контейнера nginx | имя сервиса compose |
Практика — три мини-задания
- Статика. Пример №1: свой
index.html,curl -i, в access.log должна появиться строка с кодом 200. - Proxy. Python
http.server 3000+ пример №4: сравнитеcurl :3000иcurl через nginx— тело одинаковое, в proxy-варианте в access.log nginx есть запись. - SPA. Положите
dist/Vite/React, пример №3:curl -I /random/path— 200 иtext/html.
Подробный справочник директив — Nginx.
Чек-лист перед сдачей лабораторной
-
nginx -t— ok. - Для proxy есть
Host,X-Real-IP,X-Forwarded-For(иProtoпри HTTPS). - PHP —
rootнаpublic/,.envзакрыт. - Сертификаты на месте, ключ не в репозитории.
- В отчёте — скрин или вывод
curl -I, фрагмент конфига, что делает каждый блок.
Связанные материалы
| Материал | Зачем открыть |
|---|---|
| Справочник по Nginx | все директивы, кэш, FastCGI |
| Веб-серверы | HTTP, виртуальные хосты |
| Docker Compose — готовые стеки | nginx + volumes + proxy |
| curl | заголовки, POST, отладка API |
| SPA | client-side routing |
| Шаблоны | каркасы для других инструментов |