Nginx For Beginners
Security
Demo Blocking Traffic
In this guide, you’ll learn how to:
- Configure NGINX to serve
example.comover HTTP/HTTPS - Use
allow/denydirectives for static IP filtering - Automate bans on repeated auth failures with Fail2Ban
We’ll use:
- An NGINX server on ports 80 & 443
- Two clients: node01 (
192.231.128.12) and node02 (192.231.128.3)

Prerequisites
- Ubuntu Server with NGINX installed
- Root or sudo access to
/etc/nginxand/etc/fail2ban - A self‐signed or valid SSL certificate for
example.com
1. Configure NGINX for HTTPS and Basic Auth
Create or edit /etc/nginx/sites-available/example-https:
server {
listen 80;
server_name example.com;
return 301 https://$host$request_uri;
}
server {
listen 443 ssl;
server_name example.com;
ssl_certificate /etc/ssl/certs/example.com.pem;
ssl_certificate_key /etc/ssl/certs/example.com-key.pem;
root /var/www/html;
index index.html index.htm;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains; preload";
add_header X-Frame-Options "SAMEORIGIN";
add_header Content-Security-Policy "default-src 'self'";
add_header Referrer-Policy origin;
location / {
try_files $uri $uri =404;
}
location /admin {
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
}
}
Reload NGINX:
sudo nginx -t && sudo systemctl reload nginx
2. Test Connectivity from Clients
On the NGINX server, find its IP:
ip a # e.g., eth0: inet 192.231.128.10/24On node01 and node02, add to
/etc/hosts:192.231.128.10 example.comNote
Make sure no conflicting DNS entries exist for
example.com.Run these tests on each node:
| Test | Command | Expected Response |
|---|---|---|
| HTTP → HTTPS redirect | curl http://example.com | 301 Moved Permanently |
| HTTPS (self-signed) | curl https://example.com | SSL certificate error |
| Skip cert validation | curl -k https://example.com | HTML of index.html |
Access /admin header | curl -k --head https://example.com/admin | HTTP/1.1 401 Unauthorized |
3. Block a Single IP with deny
To block node02 globally, edit the / location:
location / {
deny 192.231.128.3/32; # node02
try_files $uri $uri =404;
}
Reload and verify:
- node01 (
192.231.128.12):curl -k --head https://example.com # HTTP/1.1 200 OK - node02:
curl -k --head https://example.com # HTTP/1.1 403 Forbidden
4. Restrict /admin to a Single Host
Allow only node01 to hit /admin:
location /admin {
allow 192.231.128.12/32; # node01
deny all;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
}
Reload and test:
- node02 →
403 Forbidden - node01 →
401 Unauthorized(prompt for credentials)
5. Allow a CIDR Range
To permit both nodes (in 192.231.128.0/24) and block everyone else:
location / {
allow 192.231.128.0/24;
deny all;
try_files $uri $uri =404;
}
location /admin {
allow 192.231.128.0/24;
deny all;
auth_basic "Restricted Access";
auth_basic_user_file /etc/nginx/conf.d/.htpasswd;
}
Reload NGINX:
sudo nginx -t && sudo systemctl reload nginx
External clients will now see:

6. Automate Banning with Fail2Ban
Replace manual IP lists with automatic bans on repeated auth failures.
Install Fail2Ban:
sudo apt update sudo apt install fail2ban -yWarning
If prompted to restart due to outdated libraries, choose Ok.

Copy the default jail configuration:
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.localEnable the nginx-http-auth jail in
/etc/fail2ban/jail.local:[nginx-http-auth] enabled = true port = http,https filter = nginx-http-auth logpath = %(nginx_error_log)s maxretry = 1 bantime = 600Restart Fail2Ban:
sudo systemctl restart fail2banVerify the jail status:
sudo fail2ban-client status nginx-http-authYou should see the jail enabled with no banned IPs initially.
Trigger a ban by entering incorrect credentials in your browser:

Then check:
sudo fail2ban-client status nginx-http-authYour client IP will appear in the “Banned IP list.”
With NGINX’s static allow/deny and Fail2Ban’s dynamic banning, you have a robust defense against unwanted access and brute-force attempts.
Links and References
Watch Video
Watch video content
Practice Lab
Practice lab