NGINX Web Server
nginx ("engine x") is an HTTP web server, reverse proxy, content cache, load balancer, TCP/UDP proxy server, and mail proxy server.
Nginx official documentation: https://nginx.org/en/docs/
Setup NGINX
For a website severved from /var/www/example.com/
sudo apt update
sudo apt install nginx -y
# After installation, confirm it’s running:
systemctl status nginx
Create the Web Root Directory
If you haven’t already:
Add a test index file:
Set Permissions
Give ownership to your user (assume your user is yourusername):
sudo chown -R yourusername:yourusername /var/www/example.com
# Set proper permissions:
sudo chmod -R 755 /var/www
Create an Nginx Server Block
Create the config file:
Paste this configuration:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.htm;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
location / {
try_files $uri $uri/ =404;
}
}
Save and exit.
Enable the Server Block
Create a symlink from sites-available to sites-enabled:
Test nginx configuration:
If you see syntax is ok and test is successful, reload nginx:
Disable the Default Server Block (optional, recommended)
The default site may conflict with yours. Disable it:
Adjust Firewall (if UFW is enabled)
Check if UFW is installed:
If UFW is active, allow Nginx:
Add HTTPS
If you have a domain pointing to the server, install Certbot:
Run:
Certbot will automatically modify the Nginx config for SSL.
Quick Files Summary
| Path | Description |
|---|---|
/var/www/example.com |
Your website root directory |
/etc/nginx/sites-available/example.com |
Your nginx config file |
/etc/nginx/sites-enabled/example.com |
Symlink enabled config |
/var/log/nginx/ |
Access and error logs |
Troubleshooting Tips
If 403 Forbidden:
- Permission issue → ensure directory is owned by correct user
- Check folder has execute permissions:
If 404 Not Found:
- Confirm your index.html file exists
- Check server block root path is correct
Add Support for PHP
Install PHP-FPM & Extensions
Install PHP, PHP-FPM, and some common extensions:
Check PHP-FPM is running:
On some Debian versions, the service may be named php8.2-fpm or similar:
Create Nginx Server Block for Static + PHP
Edit or create:
Use this config:
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com;
index index.php index.html index.htm;
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# Serve static files directly
location / {
try_files $uri $uri/ /index.php?$args;
}
# Pass PHP scripts to PHP-FPM
location ~ \.php$ {
include snippets/fastcgi-php.conf;
# Adjust socket path if needed:
fastcgi_pass unix:/run/php/php-fpm.sock;
# or on some systems:
# fastcgi_pass unix:/run/php/php8.2-fpm.sock;
}
# Deny access to .ht* files (leftovers from Apache setups)
location ~ /\.ht {
deny all;
}
}
NOTE: All the other steps are the same as mentioned in the general NGINX setup above.
NGINX Access Log and Monitoring Tools
# Realtime
tail -f /var/log/nginx/access.log
# Highest count
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -20
# Today
grep "$(date '+%d/%b/%Y:%H')" /var/log/nginx/access.log | awk '{print $1}' | sort | uniq -c | sort -nr | head
NGINX Specific Fail2Ban Actions
Quick “who are they?” (country/ASN)
sudo apt update && sudo apt install geoip-bin -y
# Lookup top 10 IPs and their location
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10 | awk '{print $2}' | xargs -I{} geoiplookup {}
Friendly TUI report (GoAccess)
sudo apt install goaccess -y
goaccess /var/log/nginx/access.log --log-format=COMBINED --ignore-crawlers -a
Calcualte Number of Hits from a Specific Country
sudo apt update
sudo apt install geoip-bin geoip-database
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr > /tmp/ip_counts.txt
while read count ip; do
if geoiplookup "$ip" | grep -q "Singapore"; then
echo "$count $ip"
fi
done < /tmp/ip_counts.txt
Block Bad User Agents
Edit or create:
Put the following content:
map $http_user_agent $block_bad_ua {
default 0;
# Known malicious OS junk
~*windows\ nt(?!\ 10\.0|\ 6\.3|\ 6\.2|\ 6\.1) 1;
~*windows\ 95 1;
~*windows\ 98 1;
~*windows\ me 1;
~*windows\ xp 1;
~*windows\ vista 1;
~*windows\ 2000 1;
# CLI tools (safe to block)
~*httpie 1;
~*powershell 1;
~*python-requests 1;
~*python-urllib 1;
~*perl 1;
~*ruby 1;
~*go-http-client 1;
~*aiohttp 1;
~*okhttp 1;
~*scrapy 1;
# Exploit scanners (safe)
~*nmap 1;
~*masscan 1;
~*nikto 1;
~*sqlmap 1;
~*acunetix 1;
~*nessus 1;
~*openvas 1;
~*zgrab 1;
~*dirbuster 1;
~*dirb 1;
~*gobuster 1;
~*wfuzz 1;
# Bad crawlers - SEO scrapers (safe to block)
~*ahrefs 1;
~*semrush 1;
~*mj12bot 1;
~*dotbot 1;
~*serpstat 1;
~*rogerbot 1;
~*linkpadbot 1;
# AI / LLM scrapers (OK to block)
~*amazonbot 1;
~*gptbot 1;
~*chatgpt 1;
~*chatgpt-user 1;
~*ccbot 1;
~*anthropic 1;
~*claudebot 1;
~*bytespider 1;
~*commoncrawl 1;
}
Enable the Block on Your Website
Edit
Add near the top of server {}:
Block these exploit paths in Nginx (fast + safe)
Add this to your HTTPS server block (and optionally the HTTP one too) above your normal location /:
Common exploit probing paths (drop immediately)