Configure Nginx Access Control Lists on Ubuntu VPS: Complete Tutorial

By Raman Kumar

Share:

Updated on May 21, 2026

Configure Nginx Access Control Lists on Ubuntu VPS: Complete Tutorial

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.