My NGINX configuration
Posted on 14 May 2025 by Mino — 3 min

After deploying my own certificate authority (previous post) I updated all my NGINX configurations to be almost exactly the same, with a few exceptions. Detailed config along with explanation of required changes please find in the post.
To use this template just replace the following lines and enjoy (hopefully) secure NGINX configuration:
<SERVERNAME>
, f.e.test.com
<HOSTNAME>
, f.e.test
<PROXYPASS>
, f.e.127.0.0.1:3000
In order to create dhparam
file, you can run following command to make your secure connection even more secure ;).
openssl dhparam -out static-dhparam.pem 4096
map $http_upgrade $connection_upgrade {
default upgrade;
'' '';
}
server {
listen 80;
server_name <SERVERNAME>;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
listen 443 quic reuseport;
server_name <SERVERNAME>;
http2 on;
http3 on;
quic_gso on;
quic_retry on;
#quic_bpf on;
add_header X-Frame-Options DENY;
add_header Alt-Svc 'h3=":443"; ma=86400';
add_header Strict-Transport-Security max-age=63072000;
add_header X-XSS-Protection "0";
add_header X-Content-Type-Options "nosniff";
add_header Permissions-Policy "accelerometer=(), ambient-light-sensor=(), battery=(), bluetooth=(), camera=(), clipboard-read=(), display-capture=(), document-domain=(), encrypted-media=(), gamepad=(), geolocation=(), gyroscope=(), hid=(), idle-detection=(), interest-cohort=(), keyboard-map=(), local-fonts=(), magnetometer=(), microphone=(), payment=(), publickey-credentials-get=(), serial=(), sync-xhr=(), usb=(), xr-spatial-tracking=()" always;
add_header Content-Security-Policy "default-src https: data: blob: ; img-src 'self' https://* ; style-src 'self' 'unsafe-inline'; script-src 'self' 'unsafe-inline' https://www.gstatic.com https://www.youtube.com blob:; worker-src 'self' blob:; connect-src 'self'; object-src 'none'; frame-ancestors 'self'";
server_tokens off;
proxy_buffering off;
proxy_request_buffering off;
client_max_body_size 0;
client_body_buffer_size 512k;
http3_stream_buffer_size 512k;
proxy_read_timeout 86400s;
ssl_dhparam /etc/nginx/ssl/<HOSTNAME>-dhparam.pem;
ssl_certificate /etc/nginx/ssl/<HOSTNAME>-fullchain.pem;
ssl_certificate_key /etc/nginx/ssl/<HOSTNAME>-privkey.pem;
ssl_early_data on;
ssl_session_timeout 1d;
ssl_session_cache shared:SSL:10m;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ecdh_curve x25519:x448:secp521r1:secp384r1:secp256r1;
ssl_prefer_server_ciphers on;
ssl_conf_command Options PrioritizeChaCha;
ssl_ciphers TLS_AES_256_GCM_SHA384:TLS_CHACHA20_POLY1305_SHA256:TLS_AES_128_GCM_SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-CHACHA20-POLY1305:ECDHE-RSA-AES128-GCM-SHA256;
location / {
proxy_pass http://<PROXYPASS>;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header X-Forwarded-Scheme $scheme;
proxy_set_header Early-Data $ssl_early_data;
proxy_set_header X-Forwarded-Port $server_port;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
}
}
Variants
Static server
I have a static webserver, which only purpose is to give me icons for my vaultwarden server and to store public key for certificate authority in case new device is added to my collection. For this I only modify the http
server and add autoindex on;
to https
/location
.
...
server {
listen 80;
server_name static.test.com;
root /var/www/static;
location / {
autoindex on;
}
}
...
root /var/www/static;
location / {
autoindex on;
}
...
Useful script
Script for editing multiple configurations at once. There is one small issue with the script below, such as I have to manually edit / add port if the service behind the reverse proxy uses nonstandard port.
#!/bin/bash
sites=("static" "vaultwarden")
mkdir -p ./updated
for site in "${sites[@]}"
do
rm ./updated/$site.conf &>/dev/null
cp ./template.conf ./updated/$site.conf
sed -i "s/<SERVERNAME>/$site.test.com/g" ./updated/$site.conf
sed -i "s/<HOSTNAME>/$site/g" ./updated/$site.conf
sed -i "s/<PROXYPASS>/$site/g" ./updated/$site.conf
done
This post was written without the help of AI.