Files
pvemanager/nginx/conf.d/pvemanager-nossl.conf.template
Dilshod Rasulov 935c80427f fix(nginx): stop rate-limiting the frontend bundle into a blank page
Loading the panel over the domain produced a white page while the same
panel served directly from the frontend container rendered fine. The built
SPA requests 86 files on a cold load — one entry module plus 85 preloaded
chunks — and the server-level

    limit_req zone=general burst=20 nodelay;   # general = 10r/s

applies to those static assets too. Measured against the live site, 60 of
the 86 came back 503 and nginx logged "limiting requests ... by zone
general" for each. The entry module was among the casualties, so React
never booted and the document stayed empty.

Give static assets their own zone and restate the limit in a location that
matches them. The limit has to be restated rather than omitted: nginx
inherits limit_req from the enclosing level only when a location declares
none, and there is no `limit_req off`.

Both templates get the block, since the non-SSL config serves the same
bundle. Verified on the live deployment: 86/86 assets now return 200 and
the login page renders with no console errors.
2026-08-11 21:05:30 +05:00

104 lines
3.6 KiB
Plaintext

# NGINX Configuration Template for Server Panel (HTTP only, no SSL)
# Replace DOMAIN_NAME with your actual domain or server IP
server {
listen 80;
listen [::]:80;
server_name DOMAIN_NAME;
# Logging
access_log /var/log/nginx/pvemanager_access.log;
error_log /var/log/nginx/pvemanager_error.log;
# Let's Encrypt challenge (needed for SSL certificate obtaining)
location /.well-known/acme-challenge/ {
root /var/www/certbot;
try_files $uri =404;
}
# Rate limiting
limit_req zone=general burst=20 nodelay;
limit_conn addr 10;
# Health check endpoint
location /health {
proxy_pass http://pvemanager-app:8000;
access_log off;
}
# API proxy
location /api/ {
limit_req zone=api burst=50 nodelay;
proxy_pass http://pvemanager-app:8000;
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;
}
# Proxmox API proxy
location /proxmox/ {
proxy_pass http://pvemanager-app:8000;
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;
# Загрузка ISO/образов: файлы многогигабайтные, дефолтный
# client_max_body_size 100M и короткие таймауты им не подходят.
client_max_body_size 20g;
proxy_read_timeout 300s;
proxy_send_timeout 300s;
client_body_timeout 3600s;
}
# WebSocket support — tasks и terminal
location ~ ^/(ws|proxmox/ws)/ {
proxy_pass http://pvemanager-app:8000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
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_read_timeout 86400;
proxy_send_timeout 86400;
}
# Frontend build output. A cold load of the SPA requests ~86 files at once,
# which the server-level limit_req rejects with 503 — leaving a blank page.
# The limit has to be restated here rather than omitted: nginx inherits
# limit_req from the server level only when a location declares none.
location ~ ^/(assets/|favicon\.|icons\.svg|logo\.png) {
limit_req zone=static burst=200 nodelay;
proxy_pass http://pvemanager-frontend:80;
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;
expires 1y;
add_header Cache-Control "public, immutable";
}
# Backend static files (legacy, logo, etc.)
location /static/ {
proxy_pass http://pvemanager-app:8000;
proxy_cache_valid 200 1d;
expires 1d;
add_header Cache-Control "public, immutable";
}
# SPA frontend — all other routes
location / {
proxy_pass http://pvemanager-frontend:80;
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;
}
}