Why Access Control Lists Matter for Nginx Hosting
Access control lists (ACLs) give you precise control over who can access your Nginx web server. Unlike basic firewall rules that work at the network level, Nginx ACLs operate at the application layer, letting you block specific IPs, allow certain networks, or restrict access to sensitive directories.
Most hosting providers see configuration requests for ACLs when customers face brute force attacks, want to restrict admin areas to office IPs, or need to block problematic traffic sources. The configuration happens in your Nginx server blocks and takes effect immediately without restarting the entire web server.
This tutorial walks through setting up comprehensive Nginx access control lists on your Ubuntu VPS, from basic IP blocking to advanced location-based restrictions.
Prerequisites and Server Preparation
You need a running Ubuntu VPS with Nginx installed and root or sudo access. We're working with Ubuntu 22.04 LTS and Nginx 1.18+, though these steps work on most current versions.
Check your Nginx version and status:
nginx -v
sudo systemctl status nginx
Verify you can edit your Nginx configuration. The main config file sits at /etc/nginx/nginx.conf, while site-specific configs live in /etc/nginx/sites-available/.
Before making changes, back up your current configuration:
sudo cp -r /etc/nginx /etc/nginx.backup.$(date +%Y%m%d)
This creates a dated backup you can restore if something goes wrong.
Basic IP Allow and Deny Rules
Nginx uses allow and deny directives to control access. These directives process in order, so placement matters. Once Nginx finds a matching rule, it stops processing additional rules.
Edit your site configuration file:
sudo nano /etc/nginx/sites-available/your-domain.com
Add basic access controls inside your server block:
server {
listen 80;
server_name your-domain.com;
# Allow specific IP
allow 203.0.113.45;
# Allow IP range
allow 192.168.1.0/24;
# Block specific IP
deny 198.51.100.67;
# Block all others (use carefully)
# deny all;
location / {
try_files $uri $uri/ =404;
}
}
Test your configuration before applying:
sudo nginx -t
If the test passes, reload Nginx:
sudo systemctl reload nginx
Configure Nginx Access Control Lists for Specific Locations
Different parts of your site need different access rules. Admin areas typically require stricter controls than public content.
Here's how to protect specific directories:
server {
listen 80;
server_name your-domain.com;
# General site access
location / {
try_files $uri $uri/ =404;
}
# Restrict admin area to office IPs
location /admin {
allow 203.0.113.0/24; # Office network
allow 198.51.100.45; # Remote admin
deny all;
try_files $uri $uri/ =404;
}
# Block access to sensitive files
location ~ \.(htaccess|htpasswd|ini|log|sh)$ {
deny all;
return 404;
}
}
This setup allows general access to most content while restricting the admin directory to specific IP addresses. The file extension block prevents access to sensitive configuration files.
Using IP Lists from External Files
Managing large IP lists directly in your Nginx config becomes unwieldy. Create separate files for allowed and blocked IPs instead.
Create an allowed IPs file:
sudo nano /etc/nginx/conf.d/allowed_ips.conf
Add your allowed IP ranges:
# Office networks
allow 203.0.113.0/24;
allow 198.51.100.0/26;
# CDN networks (if using)
allow 173.245.48.0/20;
allow 103.21.244.0/22;
Create a blocked IPs file:
sudo nano /etc/nginx/conf.d/blocked_ips.conf
Add problematic IP ranges:
# Known attack sources
deny 185.220.101.0/24;
deny 45.142.214.0/24;
# Specific problem IPs
deny 198.51.100.67;
deny 203.0.113.89;
Include these files in your server block:
server {
listen 80;
server_name your-domain.com;
include /etc/nginx/conf.d/blocked_ips.conf;
include /etc/nginx/conf.d/allowed_ips.conf;
location /admin {
include /etc/nginx/conf.d/allowed_ips.conf;
deny all;
}
}
Geographic Access Controls with GeoIP
Sometimes you need to block or allow entire countries. Nginx's GeoIP module handles geographic restrictions based on IP databases.
Install the GeoIP module and database:
sudo apt update
sudo apt install nginx-module-geoip geoip-database
Load the module in your main Nginx config:
sudo nano /etc/nginx/nginx.conf
Add this line at the top, outside the events block:
load_module modules/ngx_http_geoip_module.so;
Configure GeoIP in the http block:
http {
geoip_country /usr/share/GeoIP/GeoIP.dat;
map $geoip_country_code $allowed_country {
default no;
US yes;
CA yes;
AU yes;
NZ yes;
}
}
Apply geographic restrictions in your server block:
server {
listen 80;
server_name your-domain.com;
if ($allowed_country = no) {
return 403;
}
}
For customers running Hostperl VPS hosting, geographic controls help reduce unwanted traffic and improve security for region-specific applications.
Advanced ACL Patterns and Best Practices
Real-world access control often requires more sophisticated patterns than simple allow/deny rules.
Here's a production-ready configuration that combines multiple techniques:
server {
listen 80;
server_name your-domain.com;
# Set variables for complex logic
set $admin_allowed 0;
# Check if IP is in admin whitelist
if ($remote_addr ~ "^(203\.0\.113\.|192\.168\.1\.)") {
set $admin_allowed 1;
}
# Include global blocklist
include /etc/nginx/conf.d/blocked_ips.conf;
# Public content
location / {
try_files $uri $uri/ =404;
}
# Admin with dual protection
location /admin {
if ($admin_allowed = 0) {
return 403;
}
# Additional authentication can go here
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
try_files $uri $uri/ =404;
}
# API endpoints with rate limiting
location /api {
limit_req zone=api burst=10 nodelay;
# Allow API consumers
include /etc/nginx/conf.d/api_clients.conf;
deny all;
}
}
This configuration demonstrates several advanced patterns: variable-based logic, combining ACLs with authentication, and integrating access controls with rate limiting.
Monitoring and Troubleshooting Access Controls
Access control rules can block legitimate traffic if configured incorrectly. Set up monitoring to catch issues quickly.
Monitor your Nginx access logs for blocked requests:
sudo tail -f /var/log/nginx/access.log | grep "403"
Check error logs for configuration issues:
sudo tail -f /var/log/nginx/error.log
Create a log format that includes more detail about blocked requests:
log_format detailed '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'country:$geoip_country_code';
Use this format in your server block:
access_log /var/log/nginx/your-domain.access.log detailed;
For systematic monitoring, check out our server monitoring tutorials that cover log analysis and alerting.
Testing Your Access Control Configuration
Always test access controls thoroughly before putting them into production.
Test from allowed IP addresses:
curl -I http://your-domain.com/admin
Test from blocked addresses using a proxy or different server:
curl -I -x proxy-server:port http://your-domain.com/admin
Use online tools to test from different geographic locations and IP ranges. Services like GTmetrix or Pingdom can help verify your rules work correctly from various global locations.
Create a simple test page that shows the visitor's IP address:
<?php
echo "Your IP: " . $_SERVER['REMOTE_ADDR'];
?>
This helps confirm which IP address Nginx sees. This matters when you're behind load balancers or CDNs.
Maintenance and Updates
Access control lists require regular maintenance to stay effective.
Schedule monthly reviews of your blocked IP list:
# Create a maintenance script
sudo nano /root/acl_review.sh
#!/bin/bash
echo "Reviewing blocked IPs from access logs..."
awk '$9 == "403" {print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
Make the script executable and run it monthly:
sudo chmod +x /root/acl_review.sh
sudo crontab -e
Add this cron entry:
0 9 1 * * /root/acl_review.sh | mail -s "Monthly ACL Review" admin@your-domain.com
Keep your GeoIP databases updated if you use geographic restrictions:
sudo apt update && sudo apt upgrade geoip-database
Proper access control configuration is essential for VPS security and performance. Hostperl VPS hosting provides the flexibility and control you need to implement sophisticated access controls while maintaining excellent performance for your applications.
Frequently Asked Questions
Do Nginx access controls affect server performance?
Basic allow/deny rules have minimal performance impact since Nginx processes them efficiently. Complex regex patterns or extensive IP lists can add slight latency. Geographic restrictions require GeoIP database lookups, which add microseconds per request.
Can I use access controls with SSL/TLS sites?
Yes, access controls work identically for HTTPS sites. Place the same allow/deny directives in your SSL server blocks. The access control happens before SSL processing, so blocked requests don't consume encryption resources.
How do I handle dynamic IP addresses for remote users?
For users with changing IP addresses, consider allowing broader IP ranges from their ISP, implementing additional authentication layers, or using VPN access to a fixed IP range. You can also create a simple script that updates allowed IP lists based on successful authentication.
What happens if I accidentally block my own IP address?
If you lock yourself out, access your server through your hosting provider's console or emergency access methods. Remove the blocking rule and reload Nginx. Always test access controls from a secondary connection before applying restrictive rules.
Should I use Nginx ACLs or firewall rules for blocking?
Use firewall rules (iptables/ufw) for broad network-level blocking and Nginx ACLs for application-specific access control. Firewall rules consume fewer server resources for large IP ranges, while Nginx rules offer more granular control over specific locations and can integrate with application logic.

