How to Configure Nginx Web Server on Linux
Nginx (pronounced "engine-x") is one of the most popular web servers in the world, powering millions of websites with its high performance, stability, and low resource consumption. Whether you're hosting a simple website, running a complex web application, or setting up a reverse proxy, understanding how to properly configure Nginx on Linux is an essential skill for developers, system administrators, and DevOps professionals.
This comprehensive guide will walk you through the complete process of installing, configuring, and optimizing Nginx on Linux systems, from basic setup to advanced configurations.
What is Nginx and Why Use It?
Nginx is an open-source web server that can also function as a reverse proxy, load balancer, mail proxy, and HTTP cache. Created by Igor Sysoev in 2004, Nginx was designed to solve the C10K problem – handling 10,000+ concurrent connections efficiently.
Key Benefits of Nginx:
- High Performance: Can handle thousands of concurrent connections with minimal memory usage
- Lightweight: Uses an event-driven, asynchronous architecture
- Flexible Configuration: Supports various deployment scenarios
- SSL/TLS Support: Built-in HTTPS and certificate management
- Load Balancing: Distribute traffic across multiple backend servers
- Reverse Proxy Capabilities: Forward requests to application servers
- Static Content Serving: Efficiently serves static files, images, and assets
Prerequisites
Before installing Nginx, ensure your Linux system meets these requirements:
- A Linux distribution (Ubuntu, CentOS, Debian, RHEL, etc.)
- Root or sudo privileges
- Basic command-line knowledge
- Internet connection for package downloads
- At least 512MB RAM (1GB+ recommended)
Installing Nginx on Different Linux Distributions
Ubuntu/Debian Installation
```bash
Update package repository
sudo apt update
Install Nginx
sudo apt install nginx
Start and enable Nginx service
sudo systemctl start nginx
sudo systemctl enable nginx
Check Nginx status
sudo systemctl status nginx
```
CentOS/RHEL/Rocky Linux Installation
```bash
Install EPEL repository (if not already installed)
sudo yum install epel-release
Install Nginx
sudo yum install nginx
For CentOS 8/RHEL 8/Rocky Linux 8+
sudo dnf install nginx
Start and enable Nginx service
sudo systemctl start nginx
sudo systemctl enable nginx
Check Nginx status
sudo systemctl status nginx
```
Fedora Installation
```bash
Install Nginx
sudo dnf install nginx
Start and enable Nginx service
sudo systemctl start nginx
sudo systemctl enable nginx
```
Verifying Installation
After installation, verify Nginx is running by checking the default page:
```bash
Check if Nginx is listening on port 80
sudo netstat -tlnp | grep :80
Test with curl
curl http://localhost
Or check your server's IP address in a browser
curl http://your-server-ip
```
Understanding Nginx Directory Structure
Nginx organizes its files in a specific directory structure:
```
/etc/nginx/ # Main configuration directory
├── nginx.conf # Main configuration file
├── sites-available/ # Available site configurations
├── sites-enabled/ # Enabled site configurations (symlinks)
├── conf.d/ # Additional configuration files
├── snippets/ # Reusable configuration snippets
└── modules-enabled/ # Enabled modules
/var/log/nginx/ # Log files directory
├── access.log # Access logs
└── error.log # Error logs
/var/www/html/ # Default document root
/usr/share/nginx/html/ # Alternative document root (some distributions)
```
Basic Nginx Configuration
Main Configuration File (nginx.conf)
The main configuration file `/etc/nginx/nginx.conf` contains global settings:
```nginx
/etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
include /etc/nginx/modules-enabled/*.conf;
events {
worker_connections 1024;
use epoll;
multi_accept on;
}
http {
##
# Basic Settings
##
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
types_hash_max_size 2048;
server_tokens off;
include /etc/nginx/mime.types;
default_type application/octet-stream;
##
# SSL Settings
##
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
##
# Logging Settings
##
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log;
##
# Gzip Settings
##
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript
application/x-javascript application/xml+rss
application/javascript application/json;
##
# Virtual Host Configs
##
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
```
Creating Your First Virtual Host
Create a new server block configuration for your website:
```bash
Create a new configuration file
sudo nano /etc/nginx/sites-available/example.com
```
```nginx
/etc/nginx/sites-available/example.com
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.htm index.php;
# Logging
access_log /var/log/nginx/example.com.access.log;
error_log /var/log/nginx/example.com.error.log;
# Main location block
location / {
try_files $uri $uri/ =404;
}
# PHP processing (if needed)
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
}
# Security headers
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
# Static file caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
# Deny access to hidden files
location ~ /\. {
deny all;
}
}
```
Enabling the Virtual Host
```bash
Create document root directory
sudo mkdir -p /var/www/example.com/html
Set proper ownership
sudo chown -R www-data:www-data /var/www/example.com/html
Set permissions
sudo chmod -R 755 /var/www/example.com
Create a test index file
echo "
Welcome to example.com!
" | sudo tee /var/www/example.com/html/index.html
Enable the site by creating a symlink
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
Test the configuration
sudo nginx -t
Reload Nginx
sudo systemctl reload nginx
```
SSL/HTTPS Configuration
Using Let's Encrypt (Recommended)
Install Certbot for free SSL certificates:
```bash
Ubuntu/Debian
sudo apt install certbot python3-certbot-nginx
CentOS/RHEL
sudo yum install certbot python3-certbot-nginx
Obtain and install SSL certificate
sudo certbot --nginx -d example.com -d www.example.com
```
Manual SSL Configuration
If you have your own SSL certificates:
```nginx
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/html;
# SSL Configuration
ssl_certificate /path/to/your/certificate.crt;
ssl_certificate_key /path/to/your/private.key;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
# HSTS Header
add_header Strict-Transport-Security "max-age=63072000" always;
# Rest of your configuration...
}
Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
```
Advanced Configuration Examples
Load Balancing
Configure Nginx as a load balancer:
```nginx
Define upstream servers
upstream backend {
server 192.168.1.10:8080 weight=3;
server 192.168.1.11:8080 weight=2;
server 192.168.1.12:8080 weight=1 backup;
}
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
```
Reverse Proxy for Node.js Application
```nginx
server {
listen 80;
server_name app.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection 'upgrade';
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_cache_bypass $http_upgrade;
}
}
```
Rate Limiting
Implement rate limiting to prevent abuse:
```nginx
Define rate limiting zones
http {
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
}
server {
listen 80;
server_name example.com;
# Rate limit login attempts
location /login {
limit_req zone=login burst=5 nodelay;
# Your login handling...
}
# Rate limit API calls
location /api/ {
limit_req zone=api burst=20 nodelay;
# Your API handling...
}
}
```
Security Best Practices
Basic Security Headers
```nginx
Add these to your server block
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;
```
Hiding Nginx Version
```nginx
In http block of nginx.conf
server_tokens off;
```
Restricting Access by IP
```nginx
location /admin {
allow 192.168.1.0/24;
allow 127.0.0.1;
deny all;
# Your admin configuration...
}
```
Basic Authentication
```bash
Install apache2-utils for htpasswd
sudo apt install apache2-utils
Create password file
sudo htpasswd -c /etc/nginx/.htpasswd username
```
```nginx
location /protected {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
# Your protected content...
}
```
Performance Optimization
Caching Configuration
```nginx
Browser caching for static content
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header Vary Accept-Encoding;
}
Cache HTML files for a short time
location ~* \.(html|htm)$ {
expires 1h;
add_header Cache-Control "public";
}
```
Gzip Compression Optimization
```nginx
Enhanced gzip configuration
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied any;
gzip_comp_level 6;
gzip_types
text/plain
text/css
text/xml
text/javascript
application/javascript
application/xml+rss
application/json
image/svg+xml;
```
Worker Process Optimization
```nginx
In main context of nginx.conf
worker_processes auto;
worker_connections 1024;
worker_rlimit_nofile 2048;
events {
use epoll;
multi_accept on;
}
```
Managing Nginx Service
Common Service Commands
```bash
Start Nginx
sudo systemctl start nginx
Stop Nginx
sudo systemctl stop nginx
Restart Nginx
sudo systemctl restart nginx
Reload configuration without stopping
sudo systemctl reload nginx
Check status
sudo systemctl status nginx
Enable auto-start on boot
sudo systemctl enable nginx
Disable auto-start
sudo systemctl disable nginx
```
Testing Configuration
```bash
Test configuration syntax
sudo nginx -t
Test and show configuration
sudo nginx -T
Show Nginx version and configuration options
nginx -V
```
Troubleshooting Common Issues
Port Already in Use
```bash
Check what's using port 80
sudo netstat -tlnp | grep :80
sudo lsof -i :80
Kill the process if needed
sudo killall -9 apache2 # If Apache is running
```
Permission Denied Errors
```bash
Check file permissions
ls -la /var/www/example.com/html/
Fix ownership
sudo chown -R www-data:www-data /var/www/example.com/
Fix permissions
sudo chmod -R 755 /var/www/example.com/
```
Configuration Syntax Errors
```bash
Always test configuration before reloading
sudo nginx -t
Check error logs for specific issues
sudo tail -f /var/log/nginx/error.log
```
502 Bad Gateway Errors
Common causes and solutions:
```bash
Check if upstream service is running
sudo systemctl status php7.4-fpm
For Node.js applications
sudo systemctl status your-app-name
Check if socket files exist and have correct permissions
ls -la /var/run/php/
Verify proxy_pass URLs are correct
curl http://localhost:3000 # Test backend directly
```
404 Not Found Errors
```bash
Check document root path
ls -la /var/www/example.com/html/
Verify index files exist
ls -la /var/www/example.com/html/index.html
Check try_files directive in configuration
```
SSL Certificate Issues
```bash
Test SSL certificate
openssl x509 -in /path/to/certificate.crt -text -noout
Check certificate expiration
openssl x509 -enddate -noout -in /path/to/certificate.crt
Verify certificate chain
openssl verify -CAfile /path/to/ca-bundle.crt /path/to/certificate.crt
```
Log Analysis and Monitoring
Understanding Nginx Logs
Access log format explanation:
```
192.168.1.100 - - [25/Dec/2023:10:00:00 +0000] "GET /index.html HTTP/1.1" 200 1024 "-" "Mozilla/5.0..."
IP User Timestamp Request Method/Path/Protocol Status Size Referer User-Agent
```
Useful Log Analysis Commands
```bash
View real-time access logs
sudo tail -f /var/log/nginx/access.log
Count requests by IP address
awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -nr
Find 404 errors
grep "404" /var/log/nginx/access.log
Monitor error logs
sudo tail -f /var/log/nginx/error.log
Find most requested pages
awk '{print $7}' /var/log/nginx/access.log | sort | uniq -c | sort -nr | head -10
Check bandwidth usage by IP
awk '{sum[$1] += $10} END {for (ip in sum) print ip, sum[ip]}' /var/log/nginx/access.log | sort -k2 -nr
```
Setting Up Log Rotation
Create a logrotate configuration:
```bash
sudo nano /etc/logrotate.d/nginx
```
```
/var/log/nginx/*.log {
daily
missingok
rotate 52
compress
delaycompress
notifempty
create 644 www-data adm
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
```
Backup and Migration
Backing Up Nginx Configuration
```bash
Create backup directory
sudo mkdir -p /backup/nginx/$(date +%Y%m%d)
Backup configuration files
sudo tar -czf /backup/nginx/$(date +%Y%m%d)/nginx-config.tar.gz /etc/nginx/
Backup website files
sudo tar -czf /backup/nginx/$(date +%Y%m%d)/www-data.tar.gz /var/www/
Create automated backup script
sudo nano /usr/local/bin/nginx-backup.sh
```
```bash
#!/bin/bash
/usr/local/bin/nginx-backup.sh
BACKUP_DIR="/backup/nginx"
DATE=$(date +%Y%m%d_%H%M%S)
mkdir -p $BACKUP_DIR/$DATE
Backup configuration
tar -czf $BACKUP_DIR/$DATE/nginx-config.tar.gz /etc/nginx/
Backup websites
tar -czf $BACKUP_DIR/$DATE/www-data.tar.gz /var/www/
Remove backups older than 30 days
find $BACKUP_DIR -type d -mtime +30 -exec rm -rf {} +
echo "Backup completed: $BACKUP_DIR/$DATE"
```
```bash
Make script executable and schedule it
sudo chmod +x /usr/local/bin/nginx-backup.sh
Add to crontab for daily backups at 2 AM
echo "0 2 * /usr/local/bin/nginx-backup.sh" | sudo crontab -
```
Best Practices and Professional Tips
Configuration Organization
1. Use include directives to organize configurations:
```nginx
/etc/nginx/nginx.conf
http {
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
```
2. Create reusable snippets:
```bash
/etc/nginx/snippets/ssl-params.conf
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers off;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
```
Performance Tuning Guidelines
1. Worker process configuration:
- Set `worker_processes` to the number of CPU cores
- Adjust `worker_connections` based on available memory
- Use `worker_rlimit_nofile` to increase file descriptor limit
2. Buffer sizes optimization:
```nginx
client_body_buffer_size 128k;
client_max_body_size 10m;
client_header_buffer_size 1k;
large_client_header_buffers 4 4k;
output_buffers 1 32k;
postpone_output 1460;
```
3. Enable HTTP/2 for better performance:
```nginx
listen 443 ssl http2;
listen [::]:443 ssl http2;
```
Security Hardening Checklist
- [ ] Hide Nginx version information
- [ ] Implement proper SSL/TLS configuration
- [ ] Set up security headers
- [ ] Configure rate limiting
- [ ] Restrict access to sensitive locations
- [ ] Use strong SSL ciphers and protocols
- [ ] Implement fail2ban for additional protection
- [ ] Regular security updates
Monitoring and Alerting
Set up monitoring for:
- Server response times
- Error rates (4xx, 5xx responses)
- SSL certificate expiration
- Disk space usage
- Memory and CPU utilization
Conclusion
Nginx is a powerful and flexible web server that excels in various scenarios, from simple static websites to complex applications requiring load balancing and reverse proxying. This comprehensive guide has covered everything from basic installation to advanced configurations, security hardening, and performance optimization.
Key takeaways for successful Nginx deployment:
1. Start Simple: Begin with basic configurations and gradually add complexity
2. Test Thoroughly: Always test configurations before applying them to production
3. Monitor Actively: Implement proper logging and monitoring from the start
4. Security First: Apply security best practices from day one
5. Document Everything: Keep detailed documentation of your configurations
6. Plan for Scale: Design your configuration with future growth in mind
Remember that Nginx configuration is highly flexible, and the examples provided can be adapted to your specific needs. Regular maintenance, monitoring, and updates are essential for maintaining a secure and performant web server environment.
Whether you're deploying a single website or managing a complex microservices architecture, Nginx provides the tools and flexibility needed to handle modern web traffic efficiently and securely.