userwww-data;# Create as many workers as CPU cores.
worker_processesauto;# Set the limit of open files for workers processes. The OS defaults to 2000.
worker_rlimit_nofile100000;# Only log critical errors.
error_log/var/log/nginx/error.logcrit;events{# Enabling this setting may increase performance in some cases, but it also risks overflowing the workers, degrading performance.
multi_acceptoff;# Maximum number of connections per worker.
worker_connections4096;# Nginx should default to this, but better safe than sorry.
# Probably a good idea to use io_uring instead if Nginx ever decides to support it.
useepoll;}http{# Security by obscurity offers no real defense, but there is no need to tell the world which version of Nginx we are using.
server_tokensoff;# More obscurity.
proxy_hide_headerX-Powered-By;proxy_hide_headerServer;proxy_hide_headerX-AspNetMvc-Version;proxy_hide_headerX-AspNet-Version;# cache information about FDs, frequently accessed files
# can boost performance, but you need to test those values
open_file_cachemax=200000inactive=20s;open_file_cache_valid30s;open_file_cache_min_uses2;open_file_cache_errorson;# Disabling access log boots HDD I/O performance
access_logoff;# Use Linux sendfile syscall when possible. Boost performance.
sendfileon;# Limits the amount of data that can be transferred in a single sendfile call. Without the limit, one fast connection may seize the worker process entirely.
# Nginx 1.21.4+ already set this to 2m, by default older version impose no limit by default.
sendfile_max_chunk2m;# Tries to send headers and files in the minimum number of packets (aka uses full packets).
# Reduces network overhead and improves performance.
tcp_nopushon;# Enable gzip compression. The CPU time spent is normally a good tradeoff for the reduced network transfer times.
gzipon;# Compressing files too small produce no benefit.
gzip_min_length10240;# Turning off this setting makes the HTTP response one header smaller at the expense of breaking clients without gzip support if a pull CDN is in use.
gzip_varyon;# Compress proxied responses.
gzip_proxiedexpiredno-cacheno-storeprivateauth;# Only compress text-based files as those are the ones that benefit the most.
# Nginx always compress HTML and adding it to the list generates a warning.
gzip_typestext/csstext/javascripttext/xmltext/plaintext/x-componentapplication/javascriptapplication/x-javascriptapplication/jsonapplication/xmlapplication/rss+xmlapplication/atom+xmlfont/truetypefont/opentypeapplication/vnd.ms-fontobjectimage/svg+xml;# Eagerly free timed out sockets' buffers.
reset_timedout_connectionon;# Close connection if the client takes too long between sent body packages. default is 60.
client_body_timeout10s;# Close connection if the client does ACK received content in 5 seconds. Default is 60.
send_timeout5s;# Close keepalive connections after a minute.
keepalive_timeout60s;# Redirect HTTP traffic to HTTPS by default.
server{listen80default_serverreuseport;return301https://$host$request_uri;}# Answer unrecognized domain with a 403.
# it's also a great place to put "reuseport" as it can only be stated
# once for each address:port pair, as once it is activated for said pair
# it will affect all listen directives that use that pair.
# 'reuseport' enables socket sharding, increasing performance.
server{listen443sslreuseporthttp2;listen[::]:443sslreuseporthttp2;ssl_certificate/path/to/signed_cert_plus_intermediates;ssl_certificate_key/path/to/private_key;return403;}# Set apppiate mime-type based on the extension
include/etc/nginx/mime.types;# octet-stream is the mime type any generic binary data.
default_typeapplication/octet-stream;# Reuse the tls session for a day. Reduce TLS handshake of future connections, increasing performance.
ssl_session_timeout1d;# 50MiB cache. About 200000 sessions.
ssl_session_cacheshared:SSL:50m;# SSL session cache is better than tickets in any way possible.
ssl_session_ticketsoff;# Anything older than TLSv1.2 is insecure.
ssl_protocolsTLSv1.2TLSv1.3;# generate with openssl dhparam -out /etc/ssl/certs/dhparam.pem 2048
ssl_dhparam/etc/ssl/certs/dhparam.pem;# Use secure TLSv1.2 cipher (TLS1.3 ignores this directive).
# These cipher does not support RSA certificates, this is by design.
# If you want security and performance and use RSA certificates you are doing something wrong.
ssl_ciphersECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305;# The client tends to have a weaker CPU thant the server (yes I know that a server handles multiples clients), so choosing a cipher that favors it can speed up things, especially with low-end mobile phones.
ssl_prefer_server_ciphersoff;# Load extra sites
include/etc/nginx/sites/*.conf;}
secure-headers.conf
1
2
3
4
5
6
7
8
9
10
11
12
13
# Add HSTS for 2 years.
add_headerStrict-Transport-Security"max-age=63072000"always;# Only allow the site to be in iframes in the same domain. Prevents Click-jacking attacks.
add_headerX-Frame-Options"SAMEORIGIN";# Force browsers to respect server mimetype.
add_headerX-Content-Type-Options"nosniff";# Prevents leaks of GET params to other sites.
add_headerReferrer-Policy"origin-when-cross-origin";# Be cautious as this may break some sites.
# CSP is a great security tool, but it should fine tubed in a per site basis.
# add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval'; img-src 'self' data:; style-src 'self' 'unsafe-inline'; font-src 'self'; object-src 'none'";
Just don’t, it’s not worth it.
OCSP without OCSP must-staple is worthless, but if you want to use must-staple with Nginx’s horrendous OCSP sampling ways, well… I wish you good luck. And even if you get it to work, it’s still worthless as Chromium browsers (aka most of the clients) do not honor the must-staple extension.
If you want to protect your site against the possibility of stolen certificates, it’s better to just use short-lived certificates.