refactor(nginx): relocate templates to templates/ and harden proxy configuration

- Unify unix socket path to %docroot%/gunicorn.sock

- Add ^~ priority modifier for /static/ and /media/ locations

- Add complete proxy headers including X-Forwarded-Proto for CSRF compatibility

- Clean up root directory by placing templates in dedicated templates/ folder
This commit is contained in:
2026-09-14 13:53:31 +03:30
parent c35aa06b99
commit c64742cf8b
2 changed files with 84 additions and 45 deletions

View File

@@ -1,6 +1,9 @@
#=========================================================================# #=========================================================================#
# Django + Gunicorn Socket SSL Template for HestiaCP # Django + Gunicorn Socket SSL Template for HestiaCP (HTTPS)
# Auto-generated by hestia-django-gunicorn deployment engine
# Socket path: %docroot%/gunicorn.sock
#=========================================================================# #=========================================================================#
server { server {
listen %ip%:%proxy_ssl_port% ssl http2; listen %ip%:%proxy_ssl_port% ssl http2;
server_name %domain_idn% %alias_idn%; server_name %domain_idn% %alias_idn%;
@@ -17,40 +20,57 @@ server {
access_log /var/log/%web_system%/domains/%domain%.bytes bytes; access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
error_log /var/log/%web_system%/domains/%domain%.error.log error; error_log /var/log/%web_system%/domains/%domain%.error.log error;
# Block access to hidden files (except .well-known for ACME)
location ~ /\.(?!well-known\/) { location ~ /\.(?!well-known\/) {
deny all; deny all;
return 404; return 404;
} }
# Static files — priority match prevents regex collision
location ^~ /static/ {
alias %docroot%/staticfiles/;
try_files $uri %docroot%/static/$uri =404;
expires 30d;
access_log off;
add_header Cache-Control "public, immutable";
}
# Media files (user uploads)
location ^~ /media/ {
alias %docroot%/media/;
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# Proxy known static extensions directly (HestiaCP convention)
location ~* ^.+\.(%proxy_extensions%)$ {
try_files $uri @fallback;
root %docroot%;
expires max;
access_log off;
}
# Fallback to Gunicorn for unresolved static extension requests
location @fallback {
proxy_pass http://unix:%docroot%/gunicorn.sock;
}
# Main application — reverse proxy to Gunicorn unix socket
location / { location / {
proxy_pass http://unix:/home/%user%/web/%domain%/gunicorn.sock; proxy_pass http://unix:%docroot%/gunicorn.sock;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto https;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Host $host;
} proxy_redirect off;
location ~* ^.+\.(%proxy_extensions%)$ { # Timeouts for long-running requests
try_files $uri @fallback; proxy_connect_timeout 300s;
root %sdocroot%; proxy_read_timeout 300s;
expires max;
}
location @fallback {
proxy_pass http://unix:/home/%user%/web/%domain%/gunicorn.sock;
}
location /static/ {
alias %docroot%/static/;
expires 30d;
}
location /media/ {
alias %docroot%/media/;
expires 30d;
} }
include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*; include %home%/%user%/conf/web/%domain%/nginx.hsts.conf*;
include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*; include %home%/%user%/conf/web/%domain%/nginx.ssl.conf_*;
} }

View File

@@ -1,5 +1,7 @@
#=========================================================================# #=========================================================================#
# Django + Gunicorn Socket Template for HestiaCP # Django + Gunicorn Socket Template for HestiaCP (HTTP)
# Auto-generated by hestia-django-gunicorn deployment engine
# Socket path: %docroot%/gunicorn.sock
#=========================================================================# #=========================================================================#
server { server {
@@ -13,39 +15,56 @@ server {
access_log /var/log/%web_system%/domains/%domain%.bytes bytes; access_log /var/log/%web_system%/domains/%domain%.bytes bytes;
error_log /var/log/%web_system%/domains/%domain%.error.log error; error_log /var/log/%web_system%/domains/%domain%.error.log error;
# Block access to hidden files (except .well-known for ACME)
location ~ /\.(?!well-known\/) { location ~ /\.(?!well-known\/) {
deny all; deny all;
return 404; return 404;
} }
# Static files — priority match prevents regex collision
location ^~ /static/ {
alias %docroot%/staticfiles/;
try_files $uri %docroot%/static/$uri =404;
expires 30d;
access_log off;
add_header Cache-Control "public, immutable";
}
# Media files (user uploads)
location ^~ /media/ {
alias %docroot%/media/;
expires 30d;
access_log off;
add_header Cache-Control "public";
}
# Proxy known static extensions directly (HestiaCP convention)
location ~* ^.+\.(%proxy_extensions%)$ {
try_files $uri @fallback;
root %docroot%;
expires max;
access_log off;
}
# Fallback to Gunicorn for unresolved static extension requests
location @fallback {
proxy_pass http://unix:%docroot%/gunicorn.sock;
}
# Main application — reverse proxy to Gunicorn unix socket
location / { location / {
proxy_pass http://unix:/home/%user%/web/%domain%/gunicorn.sock; proxy_pass http://unix:%docroot%/gunicorn.sock;
proxy_set_header Host $host; proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Host $host;
} proxy_redirect off;
location ~* ^.+\.(%proxy_extensions%)$ { # Timeouts for long-running requests
try_files $uri @fallback; proxy_connect_timeout 300s;
root %sdocroot%; proxy_read_timeout 300s;
expires max;
}
location @fallback {
proxy_pass http://unix:/home/%user%/web/%domain%/gunicorn.sock;
}
location /static/ {
alias %docroot%/static/;
expires 30d;
}
location /media/ {
alias %docroot%/media/;
expires 30d;
} }
include %home%/%user%/conf/web/%domain%/nginx.conf_*; include %home%/%user%/conf/web/%domain%/nginx.conf_*;
} }