Lesson 20 / 25
Access Control, Authentication and Security Headers
Restrict access and add protective response headers.
Layers of protection at the edge
allow and deny restrict locations by IP address or CIDR range, ideal for admin panels and internal endpoints (allow 10.0.0.0/8; deny all;). auth_basic with an htpasswd file adds simple password protection, acceptable for internal tools over HTTPS. auth_request delegates authentication to a subrequest: NGINX calls an internal auth service and allows the request only if it returns 2xx, which is how many setups integrate single sign-on proxies such as oauth2-proxy. Security headers reduce browser-side attacks: X-Content-Type-Options: nosniff, Referrer-Policy, a Content-Security-Policy tailored to your app, X-Frame-Options or CSP frame-ancestors against clickjacking, and HSTS. Use the always parameter so headers are added to error responses too. server_tokens off; hides the NGINX version in headers and error pages. Block access to hidden files such as .git and .env, which are frequently exposed by mistake.
Protecting admin, hiding secrets and adding headers
A reusable security snippet plus location-level rules.
# /etc/nginx/snippets/security-headers.conf
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header X-Frame-Options "DENY" always;
add_header Content-Security-Policy "default-src 'self'; img-src 'self' data:" always;
server {
server_tokens off;
include snippets/security-headers.conf;
location ~ /\.(?!well-known) { deny all; } # .git, .env, .htpasswd ...
location /admin/ {
allow 10.0.0.0/8;
deny all;
auth_basic "Admin";
auth_basic_user_file /etc/nginx/.htpasswd;
include snippets/security-headers.conf; # repeat: add_header is not merged
proxy_pass http://app_backend;
}
location /internal-dashboard/ {
auth_request /oauth2/auth; # SSO via an auth subrequest
proxy_pass http://dashboard;
}
location = /oauth2/auth {
internal;
proxy_pass http://oauth2_proxy;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
}Security guards at different doors
The front door checks bags (headers), the staff entrance checks ID badges (allow/deny), the server room asks for a PIN (auth_basic) and the executive floor phones head office to confirm (auth_request).
Quick check: Why add the `always` parameter to add_header for security headers?
- To make the header apply to all servers
- To make the header case-insensitive
- To disable caching
- So the header is also added to error responses such as 404 and 500
Answer
So the header is also added to error responses such as 404 and 500 — Without always, add_header applies only to successful and redirect responses.