Перейти к содержанию

nginx на VPS vm-mini (46.17.99.183) — все sites-enabled

Reverse-proxy на VPS. Проверено 05.08.2026. Три активных сайта, все с TLS от Let's Encrypt. HTTP автоматически редиректится в HTTPS.


Быстрая справка

Параметр Значение
Версия nginx 1.24.0 (Ubuntu)
Пользователь www-data
Worker processes auto
Worker connections 768
Активных сайтов 3
TLS-протоколы TLS 1.2 + TLS 1.3 (через certbot)
SSL cipher suite Modern (Mozilla intermediate)
Certbot renewal /.well-known/acme-challenge//var/www/html/
Общий error_log /var/log/nginx/error.log
Общий access_log /var/log/nginx/access.log (у каждого сайта — свой)
Модули include /etc/nginx/modules-enabled/*.conf (стандартный набор Ubuntu)
Проверено 05.08.2026

Список активных сайтов

Домен Тип Backend Порт nginx
alatyr-service.ru (+ www) Reverse-proxy Node.js Express 127.0.0.1:5000 80, 443
alatyr-taverna.ru Статика (SPA) /opt/alatyr/dist/ 80, 443
vault.alatyr-service.ru Reverse-proxy Vaultwarden Docker 127.0.0.1:8222 80, 443, 8443

rag.alatyr-service.ru живёт НЕ на VPS, а на ragserver (192.168.1.200) — резолвится в 176.99.153.164 (офисный роутер). Конфиг nginx для него лежит на ragserver, см. ragserver-workstation.md.


Общая структура

/etc/nginx/
├── nginx.conf                        # Главный конфиг (стандартный Ubuntu)
├── sites-available/                  # Все конфиги (активные + резерв)
│   ├── alatyr-service
│   ├── alatyr-taverna.ru
│   ├── vault.alatyr-service.ru
│   ├── vault.alatyr-service.ru.backup.1784924501  # certbot backup 25.07.2026
│   └── default                       # unused
├── sites-enabled/                    # Симлинки на активные
│   ├── alatyr-service → ../sites-available/alatyr-service
│   ├── alatyr-taverna.ru → ../sites-available/alatyr-taverna.ru
│   └── vault.alatyr-service.ru → ../sites-available/vault.alatyr-service.ru
├── modules-enabled/                  # системные (не трогаем)
└── conf.d/                           # общие сниппеты (пусто)

/etc/letsencrypt/
├── options-ssl-nginx.conf            # certbot настройки TLS/ciphers
├── ssl-dhparams.pem                  # DH params
└── live/
    ├── alatyr-service.ru/            # сертификат для alatyr-service.ru + www
    ├── alatyr-taverna.ru/            # сертификат для alatyr-taverna.ru
    └── vault.alatyr-service.ru/      # сертификат для vault.alatyr-service.ru

Сайт 1: alatyr-service.ru

Файл: /etc/nginx/sites-enabled/alatyr-servicesites-available/alatyr-service

Назначение: основной сайт (Node.js Express на Alatyr Service Platform).

Server blocks

  1. HTTP → HTTPS редирект (listen 80):
  2. www.alatyr-service.ru → 301 → https://alatyr-service.ru$request_uri (www в apex)
  3. alatyr-service.ru → 301 → https://alatyr-service.ru$request_uri

  4. HTTPS www → apex редирект (listen 443 ssl, server_name www.alatyr-service.ru):

  5. 301 → https://alatyr-service.ru$request_uri

  6. Основной HTTPS (listen 443 ssl, server_name alatyr-service.ru):

  7. Проксирует / на http://127.0.0.1:5000 (Express)
  8. .well-known/acme-challenge//var/www/html/ (certbot renewal)
  9. Логи: /var/log/nginx/alatyr-{access,error}.log
  10. client_max_body_size 10M

Proxy headers

proxy_http_version 1.1;
proxy_set_header Host              $host;
proxy_set_header X-Real-IP         $remote_addr;
proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host  $host;
proxy_set_header Upgrade           $http_upgrade;    # WebSocket ready
proxy_set_header Connection        "upgrade";

Таймауты

  • proxy_connect_timeout 60s
  • proxy_send_timeout 60s
  • proxy_read_timeout 60s

TLS

  • Certbot-managed: /etc/letsencrypt/live/alatyr-service.ru/{fullchain,privkey}.pem
  • Общие TLS-настройки из /etc/letsencrypt/options-ssl-nginx.conf

Сайт 2: alatyr-taverna.ru

Файл: /etc/nginx/sites-enabled/alatyr-taverna.rusites-available/alatyr-taverna.ru

Назначение: фэнтезийная таверна (статический SPA).

Server blocks

  1. HTTP → HTTPS (listen 80, server_name alatyr-taverna.ru www.alatyr-taverna.ru): 301 → https://alatyr-taverna.ru$request_uri

  2. HTTPS основной (listen 443 ssl, server_name alatyr-taverna.ru):

  3. root /opt/alatyr/dist
  4. index index.html

  5. HTTPS www → apex редирект (listen 443 ssl, server_name www.alatyr-taverna.ru): 301 → https://alatyr-taverna.ru$request_uri

  6. Сертификат тот же (SAN включает www.alatyr-taverna.ru)

Location правила (SPA-паттерн)

location Что делает
/ try_files $uri $uri/ /index.html — SPA fallback
/assets/ expires 1y, Cache-Control: public, immutable — для хэш-версионированных бандлов Vite
= /index.html Cache-Control: no-cache, no-store, must-revalidate — чтобы обновления сайта были видны сразу

Gzip

Включён для text/css, application/javascript, image/svg+xml. Минимум 1024 байта.

Логи

  • /var/log/nginx/alatyr-taverna.access.log
  • /var/log/nginx/alatyr-taverna.error.log

TLS

  • /etc/letsencrypt/live/alatyr-taverna.ru/{fullchain,privkey}.pem

Особенности

  • ⚠ Конфиг не содержит .well-known/acme-challenge/ — certbot использует standalone или webroot по общему /var/www/html/. Автообновление работает, т.к. HTTP-блок слушает 80/tcp
  • SAN сертификата: alatyr-taverna.ru, www.alatyr-taverna.ru (оба)
  • www редирект: настроен 05.08.2026 (было 404, стало 301 → apex)

Сайт 3: vault.alatyr-service.ru (Vaultwarden)

Файл: /etc/nginx/sites-enabled/vault.alatyr-service.rusites-available/vault.alatyr-service.ru

Назначение: веб-интерфейс и API Vaultwarden (self-hosted менеджер паролей).

Server blocks

  1. HTTP → HTTPS (listen 80): 301 → https://vault.alatyr-service.ru$request_uri

  2. HTTPS основной (listen 443 ssl + listen 8443 ssl — см. замечание ниже):

  3. Проксирует / на http://127.0.0.1:8222 (Docker Vaultwarden)
  4. .well-known/acme-challenge//var/www/html/

Proxy headers (обязательны для Vaultwarden)

proxy_http_version 1.1;
proxy_set_header Host              $host;
proxy_set_header X-Real-IP         $remote_addr;
proxy_set_header X-Forwarded-For   $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;    # ВАЖНО для Vaultwarden
proxy_set_header Upgrade           $http_upgrade;
proxy_set_header Connection        "upgrade";

X-Forwarded-Proto критично — Vaultwarden отказывается работать по HTTPS если не видит его через прокси.

Таймауты и размеры

  • proxy_read_timeout 90s, proxy_send_timeout 90s (больше стандартных)
  • client_max_body_size 128M — для загрузки аттачей в Vaultwarden

TLS

  • /etc/letsencrypt/live/vault.alatyr-service.ru/{fullchain,privkey}.pem

Двойное прослушивание портов (443 + 8443)

listen 443 ssl;
listen [::]:443 ssl;
listen 8443 ssl;
listen [::]:8443 ssl;

nginx слушает и 443, и 8443 (оба TCP). Не конфликтует с AmneziaWG — тот на 8443/udp.

Назначение 8443/tcp — резервный доступ к Vaultwarden прямо по IP, в обход DNS:

  • URL: https://46.17.99.183:8443/
  • Подтверждено в логах (05.08.2026): есть реальный клиент (Firefox/Linux, IP 64.227.102.176), зашёл, получил 200 OK
  • Полезен когда:
  • DNS-запись vault.alatyr-service.ru временно не работает (reg.ru DNS легал, не успело распространиться, локальный hosts)
  • Клиент режется по SNI (корпоративные фильтры)
  • Первоначальная настройка нового клиента

Оставляем как есть — полезный fallback, сертификат тот же (при входе по IP будет warning NET::ERR_CERT_COMMON_NAME_INVALID, но можно проломиться через Advanced).

Особенности

  • Комментарий "Временный HTTP-конфиг — certbot добавит HTTPS-блок автоматически" остался от начальной настройки, хотя HTTPS уже давно добавлен
  • Все certbot-generated строки помечены # managed by Certbot

Глобальный nginx.conf (сокращённо)

user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;

events {
    worker_connections 768;
}

http {
    sendfile on;
    tcp_nopush on;
    types_hash_max_size 2048;
    include /etc/nginx/mime.types;
    default_type application/octet-stream;

    # ⚠ Этот ssl_protocols переопределяется certbot options-ssl-nginx.conf
    ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3;
    ssl_prefer_server_ciphers on;

    access_log /var/log/nginx/access.log;
    gzip on;

    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

TLS-реальность

Что видит клиент (переопределяется include'ом options-ssl-nginx.conf в каждом сайте):

  • ssl_protocols TLSv1.2 TLSv1.3; ← актуально
  • ssl_prefer_server_ciphers off;
  • Modern cipher suites (ECDHE + AES-GCM / ChaCha20-Poly1305)
  • ssl_session_cache shared:le_nginx_SSL:10m
  • ssl_session_timeout 1440m (24 часа)
  • ssl_session_tickets off (защита от кражи session tickets)

TLS 1.0 и TLS 1.1 в глобальном nginx.conf не активны — переопределяются на уровне сайта. Но стоит убрать для чистоты.


SSL-сертификаты (Let's Encrypt)

Все сертификаты в /etc/letsencrypt/live/. Автообновление через certbot cron/systemd-timer. Подробности — в certbot.md.

Домен Certificate name SAN
alatyr-service.ru alatyr-service.ru + www.alatyr-service.ru
alatyr-taverna.ru alatyr-taverna.ru — (только apex)
vault.alatyr-service.ru vault.alatyr-service.ru

Команды на каждый день

Проверить синтаксис перед reload

sudo nginx -t

Reload без прерывания соединений

sudo systemctl reload nginx

Проверить, что слушает

sudo ss -tlnp | grep nginx

Смотреть логи в реальном времени

# все сайты вместе
sudo tail -f /var/log/nginx/error.log

# конкретный сайт
sudo tail -f /var/log/nginx/alatyr-error.log
sudo tail -f /var/log/nginx/alatyr-taverna.error.log

Обновить сертификат вручную (если нужно)

sudo certbot renew --dry-run    # тест
sudo certbot renew               # реально

Известные проблемы / TODO

  • Security headers не добавлены ни на одном сайте. Добавить в общий сниппет /etc/nginx/conf.d/security.conf:
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Referrer-Policy "strict-origin-when-cross-origin" always;
    # X-XSS-Protection устарел, можно не добавлять
    # CSP — отдельно на каждый сайт (сложнее)
    
    Потом на каждом сайте — include /etc/nginx/conf.d/security.conf;
  • HTTP/2 не включён — заменить listen 443 ssl на listen 443 ssl http2 во всех сайтах
  • Разобраться с listen 8443 ssl на Vaultwarden → fallback по IP, оставляем (проверено 05.08.2026: есть реальные клиенты)
  • Добавить access_log/error_log в vault.alatyr-service.ru — сейчас всё летит в общий /var/log/nginx/access.log, смешано с ботами
  • Удалить TLS 1.0/1.1 из глобального nginx.conf — переопределение работает, но visually confusing
  • Настроить log rotation для новых логов сайтов — проверить, что /etc/logrotate.d/nginx включает alatyr-*.log, alatyr-taverna.*.log
  • Rate limiting — сейчас нет. Для /api/, /login/ полезно
  • fail2ban jails для nginx-scan — уже настроено или нет? (см. TODO по vaultwarden fail2ban)
  • Удалить старый бэкап sites-available/vault.alatyr-service.ru.backup.1784924501 — он не нужен (можно, но необязательно)

Как добавить новый сайт (шпаргалка)

  1. Создать sites-available/<domain> (можно скопировать от одного из существующих)
  2. Симлинк: sudo ln -s /etc/nginx/sites-available/<domain> /etc/nginx/sites-enabled/
  3. sudo nginx -t — проверка синтаксиса
  4. sudo systemctl reload nginx
  5. sudo certbot --nginx -d <domain> — выдать сертификат и автоматически прописать в конфиг
  6. Проверить в браузере

Для webroot-режима certbot нужно, чтобы был location /.well-known/acme-challenge/ { root /var/www/html; } уже в конфиге.


Состояние безопасности (05.08.2026)

fail2ban

Сервис: fail2ban.service — active (running) since 2026-08-01, 3 jails.

Jail Filter source Total failed Total banned Currently banned
sshd journal _SYSTEMD_UNIT=sshd.service 8738 849 5
vaultwarden /opt/vaultwarden/data/vaultwarden.log 0 0 0
vaultwarden-admin /opt/vaultwarden/data/vaultwarden.log 0 0 0

Vaultwarden filter regex (/etc/fail2ban/filter.d/vaultwarden.conf):

^.*Username or password is incorrect\. Try again\. IP: <ADDR>\..*$

Почему vaultwarden = 0 events: лог работает (последняя запись 05.08.2026 06:42), в нём только WARN’ы от dotfile-сканеров (BadStart('.')), которые vaultwarden отклоняет через PathBuf guard. Реальных попыток брутфорса пароля не было. Filter regex корректный, просто не было triggers.

5 IP под баном на момент 05.08.2026 13:10 (для истории): - 195.66.79.15, 103.165.206.238, 27.71.230.31, 89.169.133.20, 45.148.10.147

Rate limiting

Нет. grep -rE "limit_req|limit_conn" /etc/nginx/ — пусто. Ни limit_req_zone, ни limit_conn_zone не определены.

Активные сканеры в логах (выборка из общего access.log)

  • Mirai/Mozi ботнет (напр. 204.76.203.18) — IoT-эксплойты /hiddenbin/*.spc, /hiddenbin/Space.arm|.mips|.ppc
  • WordPress сканеры (104.23.221.71 — Cloudflare exit) — /wp-admin/install.php (у нас нет WP)
  • Censys/Azure port scanners (20.221.66.246, 20.171.8.42) — MGLNDD_46.17.99.183_8443 bad requests
  • 8443/tcp — 146 записей в общем логе (почти всё — боты, один реальный клиент 04.08.2026)

Сейчас всё это ловится 404 на nginx, но IP не банятся — nginx-noscript jail отсутствует.

План Block 4 hardening (отложено)

  1. fail2ban jail nginx-noscript — бан IP по 404 на /wp-*, /hiddenbin/*, /xmlrpc.php, .env, .git/
  2. limit_req_zone в nginx.conf:
    limit_req_zone $binary_remote_addr zone=api_limit:10m rate=10r/s;
    limit_conn_zone $binary_remote_addr zone=addr:10m;
    
    Применение в сайтах (особенно /api/, /login/):
    limit_req zone=api_limit burst=20 nodelay;
    limit_conn addr 20;
    
  3. Security headers (HSTS, X-Frame-Options, X-Content-Type-Options, Referrer-Policy)
  4. HTTP/2 (listen 443 ssl http2)
  5. Аудит CSP (сложнее, каждый сайт отдельно)

История изменений

Дата Что
2026-08-05 Первая версия. Задокументированы 3 активных сайта, глобальный nginx.conf, TLS-настройки, TODO.
2026-08-05 Разобраны три вопроса: (1) 8443/tcp — fallback по IP для Vaultwarden, оставлен; (2) www.alatyr-taverna.ru — добавлен 301-редирект на apex; (3) безопасность — задокументировано текущее состояние fail2ban + rate limiting (отложено в Block 4).