nginx¶
nginx is the other common web server. Same job as Apache: if the README doesn't require it, sudo apt purge nginx nginx-common; if it does, stop it advertising itself and add the browser protections.
Where¶
/etc/nginx/nginx.conf (global http block), /etc/nginx/sites-available/default and sites-enabled/ (the sites), /etc/nginx/conf.d/*.conf. After changes: sudo nginx -t && sudo systemctl reload nginx.
The settings¶
| Setting | Where | Value | Why |
|---|---|---|---|
server_tokens |
http block in nginx.conf |
off |
Hides the version in the Server: header and error pages |
ssl_protocols |
nginx.conf or the site | TLSv1.2 TLSv1.3 |
No SSLv3, no TLS 1.0 or 1.1 |
add_header X-Frame-Options "SAMEORIGIN" always; |
server block |
present | Clickjacking |
add_header X-Content-Type-Options "nosniff" always; |
server block |
present | |
add_header Strict-Transport-Security "max-age=31536000" always; |
HTTPS server block |
present | |
autoindex |
any location |
off (the default; make sure nothing set it on) |
Directory listings |
client_max_body_size |
http or server |
a sane limit such as 10m |
Uploads can't be used to fill the disk |
location ~ /\. { deny all; } |
server block |
present | Hidden files (.git, .env, .htpasswd) aren't served |
Apply¶
sudo nano /etc/nginx/nginx.conf. Inside the http { … } block, find server_tokens (it ships as a comment, # server_tokens off;): remove the #. Find ssl_protocols and make it ssl_protocols TLSv1.2 TLSv1.3;. Every nginx directive ends with a semicolon; a missing one is the most common reason nginx -t fails.
The headers and upload limit go in a new file that the http block includes automatically:
sudo nano /etc/nginx/conf.d/hardening.conf
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Content-Type-Options "nosniff" always;
client_max_body_size 10m;
Then:
sudo nginx -t
sudo systemctl reload nginx
Note that add_header in a server or location block replaces all headers from the http level; if a site sets its own headers, add these there too. grep -r autoindex /etc/nginx finds any listing turned on.
Files¶
Same as Apache: the web root (/var/www/html or whatever root says) owned by root, readable by www-data, writable only where the application needs it, and searched for things that aren't the site.
Verify¶
grep -rE 'server_tokens|ssl_protocols|autoindex|X-Frame-Options' /etc/nginx/
curl -sI http://localhost | grep -iE 'server|x-frame'
sudo nginx -t
Example¶
curl -I localhost shows Server: nginx/1.24.0. nginx.conf has # server_tokens off; commented and ssl_protocols TLSv1 TLSv1.1 TLSv1.2 SSLv3;. Uncomment the first, fix the second to TLSv1.2 TLSv1.3, add the headers file, reload. No X-Frame-Options appears until the reload; after it does.
Try it¶
- Set
server_tokens offand comparecurl -Ioutput. - Leave a semicolon off and run
nginx -t.
Build it¶
An nginx-check.sh: grep the directives, nginx -t, curl -sI.