This article wasn't updated in the last 4 years. Please double check if the content is still up-to-date.
If you find any error, please send me a quick heads-up.
If you find any error, please send me a quick heads-up.
This is my commonly used config for nginx
. It may be out of date, so just use it as a more general guide.
First set up DH params
mkdir -p /etc/nginx/ssl
cd /etc/nginx/ssl
openssl dhparam -out dhparam.pem 2048
Main Config (nginx.conf
)
user www-data;
worker_processes auto;
pid /run/nginx.pid;
events {
worker_connections 768;
# multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
server_names_hash_bucket_size 64;
server_names_hash_max_size 512;
# server_name_in_redirect off;
client_max_body_size 128M;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1.3 TLSv1.2;
ssl_prefer_server_ciphers on;
ssl_ciphers "EECDH+AESGCM:EDH+AESGCM";
ssl_ecdh_curve secp384r1;
ssl_dhparam /etc/nginx/ssl/dhparam.pem;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 5m;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
# every HTTPS host needs to configure its `ssl_trusted_certificate`
##
# Logging Settings
##
error_log /var/log/nginx/error.log;
access_log off;
##
# Gzip Settings
##
gzip on;
gzip_comp_level 2;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript image/svg+xml;
##
# Application Security
##
include snippets/security.conf;
##
# Virtual Host Configs
##
# default config
server {
listen 80 default_server;
listen [::]:80 default_server;
server_name _;
log_not_found off;
# either show splash screen
# index index.html;
# root /var/www/__default;
# or redirect to server main URL
# return 303 https://main-domain.com;
}
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/servers/*;
}
PHP-FPM Snippet (snippets/php-fpm.conf
)
fastcgi_buffer_size 128k;
fastcgi_buffers 4 256k;
fastcgi_busy_buffers_size 256k;
fastcgi_temp_file_write_size 256k;
fastcgi_intercept_errors on;
# Symfony-specific config
fastcgi_param APP_ENV "prod";
# prevent httpoxy vulnerability
fastcgi_param HTTP_PROXY "";
include snippets/fastcgi-php.conf;
Security-Snippet (snippets/security.conf
)
Warning: you need to include this file everywhere, where you want to load additional headers via add_header. See for example the /assets/
location in the file below.
add_header X-Frame-Options SAMEORIGIN;
add_header X-Content-Type-Options nosniff;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
Project Config (servers/example.org.conf
)
# redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.org www.example.org;
return 301 https://www.example.org$request_uri;
}
# redirect non-WWW to WWW
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.org;
ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.org/chain.pem;
return 301 https://www.example.org$request_uri;
}
# actual server block
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name www.example.org;
root /var/www/example.org/public;
ssl_certificate /etc/letsencrypt/live/example.org/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.org/privkey.pem;
ssl_trusted_certificate /etc/letsencrypt/live/example.org/chain.pem;
error_log /var/log/nginx/example.org-error.log;
location / {
index index.php;
try_files $uri /index.php$is_args$args;
}
location ~ ^/index.php {
include snippets/php-fpm.conf;
fastcgi_pass 127.0.0.1:9100;
internal;
}
location ~ ^/assets/ {
include snippets/security.conf;
add_header Cache-Control "public, max-age=31536000, immutable";
add_header Vary "Accept-Encoding";
log_not_found off;
}
location ~ \.php$ {
return 404;
}
location ~ /\. {
deny all;
log_not_found off;
}
}
Additional Config / Comments
Additional Headers
You can set additional headers
# This header enables the Cross-site scripting (XSS) filter built into most recent web browsers.
# It's usually enabled by default anyway, so the role of this header is to re-enable the filter for
# this particular website if it was disabled by the user.
# https://www.owasp.org/index.php/List_of_useful_HTTP_headers
add_header X-XSS-Protection "1; mode=block";
# with Content Security Policy (CSP) enabled(and a browser that supports it(http://caniuse.com/#feat=contentsecuritypolicy),
# you can tell the browser that it can only download content from the domains you explicitly allow
# http://www.html5rocks.com/en/tutorials/security/content-security-policy/
# https://www.owasp.org/index.php/Content_Security_Policy
# I need to change our application code so we can increase security by disabling 'unsafe-inline' 'unsafe-eval'
# directives for css and js(if you have inline css or js, you will need to keep it too).
# more: http://www.html5rocks.com/en/tutorials/security/content-security-policy/#inline-code-considered-harmful
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://ssl.google-analytics.com https://assets.zendesk.com https://connect.facebook.net; img-src 'self' https://ssl.google-analytics.com https://s-static.ak.facebook.com https://assets.zendesk.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com https://assets.zendesk.com; font-src 'self' https://themes.googleusercontent.com; frame-src https://assets.zendesk.com https://www.facebook.com https://s-static.ak.facebook.com https://tautt.zendesk.com; object-src 'none'";
# config to enable HSTS(HTTP Strict Transport Security) https://developer.mozilla.org/en-US/docs/Security/HTTP_Strict_Transport_Security
# to avoid ssl stripping https://en.wikipedia.org/wiki/SSL_stripping#SSL_stripping
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload";
Cipherlist
Use the cipherlist from https://cipherlist.eu/
OCSP stapling with DigiCert
OCSP stapling with the root certificate from DigiCert: https://www.digitalocean.com/community/tutorials/how-to-configure-ocsp-stapling-on-apache-and-nginx
wget -O - https://www.digicert.com/CACerts/DigiCertHighAssuranceEVRootCA.crt | openssl x509 -inform DER -outform PEM | tee -a ca-certs.pem> /dev/null
wget -O - https://www.digicert.com/CACerts/DigiCertHighAssuranceEVCA-1.crt | openssl x509 -inform DER -outform PEM | tee -a ca-certs.pem> /dev/null