Nginx Web Server on Ubuntu
Trademark Notice
NGINX® is a registered trademark of F5, Inc. All trademarks are used for representation purposes only. This content is for educational purposes only.
Complete guide to installing and configuring Nginx on Ubuntu Server.
Installation
# Update package list
sudo apt update
# Install Nginx
sudo apt install -y nginx
# Start and enable Nginx
sudo systemctl start nginx
sudo systemctl enable nginx
# Check status
sudo systemctl status nginx
# Verify installation
nginx -v
Firewall Configuration
# Allow Nginx through firewall
sudo ufw allow 'Nginx Full'
# Or allow specific ports
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Check status
sudo ufw status
Directory Structure
/etc/nginx/
├── 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/www/html/ # Default document root
/var/log/nginx/ # Log files
Basic Configuration
Main Configuration
# Edit main config
sudo nano /etc/nginx/nginx.conf
user www-data;
worker_processes auto;
pid /run/nginx.pid;
error_log /var/log/nginx/error.log;
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;
# Buffer Settings
client_body_buffer_size 10K;
client_header_buffer_size 1k;
client_max_body_size 8m;
large_client_header_buffers 2 1k;
include /etc/nginx/mime.types;
default_type application/octet-stream;
# SSL Settings
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
# Logging
access_log /var/log/nginx/access.log;
# Gzip Compression
gzip on;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
# Virtual Host Configs
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Server Blocks (Virtual Hosts)
Create Server Block
# Create document root
sudo mkdir -p /var/www/example.com/html
# Set permissions
sudo chown -R $USER:$USER /var/www/example.com/html
sudo chmod -R 755 /var/www
# Create sample page
echo "<h1>Welcome to example.com</h1>" | sudo tee /var/www/example.com/html/index.html
Server Block Configuration
# Create server block file
sudo nano /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
location / {
try_files $uri $uri/ =404;
}
# 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;
add_header Referrer-Policy "no-referrer-when-downgrade" always;
# Deny access to hidden files
location ~ /\. {
deny all;
}
}
# Enable server block
sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
# Test configuration
sudo nginx -t
# Reload Nginx
sudo systemctl reload nginx
SSL/TLS Configuration
Install Certbot (Let's Encrypt)
# Install Certbot
sudo apt install -y certbot python3-certbot-nginx
# Obtain certificate
sudo certbot --nginx -d example.com -d www.example.com
# Certificate auto-renewal
sudo systemctl status certbot.timer
# Test renewal
sudo certbot renew --dry-run
Manual SSL Configuration
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com/html;
index index.html index.php;
# SSL certificates
ssl_certificate /etc/ssl/certs/example.com.crt;
ssl_certificate_key /etc/ssl/private/example.com.key;
# SSL configuration
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers off;
# HSTS
add_header Strict-Transport-Security "max-age=63072000" always;
# OCSP stapling
ssl_stapling on;
ssl_stapling_verify on;
ssl_trusted_certificate /etc/ssl/certs/ca-bundle.crt;
# Session cache
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
location / {
try_files $uri $uri/ =404;
}
}
# Redirect HTTP to HTTPS
server {
listen 80;
listen [::]:80;
server_name example.com www.example.com;
return 301 https://$server_name$request_uri;
}
Reverse Proxy Configuration
server {
listen 80;
server_name api.example.com;
location / {
proxy_pass http://localhost:3000;
proxy_http_version 1.1;
# Proxy headers
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;
# Timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# Caching
proxy_cache_bypass $http_upgrade;
}
}
Load Balancing
upstream backend {
least_conn; # or ip_hash, hash, random
server 192.168.1.101:8080 weight=3;
server 192.168.1.102:8080;
server 192.168.1.103:8080 backup;
keepalive 32;
}
server {
listen 80;
server_name lb.example.com;
location / {
proxy_pass http://backend;
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
PHP-FPM Integration
# Install PHP-FPM
sudo apt install -y php-fpm php-mysql php-curl php-gd php-mbstring php-xml
# Check PHP-FPM socket
ls -la /run/php/
server {
listen 80;
server_name example.com;
root /var/www/example.com/html;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
# PHP-FPM configuration
location ~ \.php$ {
include snippets/fastcgi-php.conf;
fastcgi_pass unix:/run/php/php8.1-fpm.sock;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to .htaccess
location ~ /\.ht {
deny all;
}
}
Caching Configuration
# Define cache path
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m use_temp_path=off;
server {
listen 80;
server_name cache.example.com;
location / {
proxy_cache my_cache;
proxy_cache_valid 200 60m;
proxy_cache_valid 404 10m;
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
proxy_cache_lock on;
add_header X-Cache-Status $upstream_cache_status;
proxy_pass http://backend;
}
}
Static File Serving
server {
listen 80;
server_name static.example.com;
root /var/www/static;
# Browser caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
expires 1y;
add_header Cache-Control "public, immutable";
access_log off;
}
# Gzip compression
gzip on;
gzip_types text/css application/javascript image/svg+xml;
gzip_min_length 256;
}
Security Configuration
Rate Limiting
# Define rate limit zone
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=10r/s;
server {
listen 80;
server_name example.com;
location /api/ {
limit_req zone=mylimit burst=20 nodelay;
proxy_pass http://backend;
}
}
IP Whitelisting
location /admin {
allow 192.168.1.0/24;
allow 10.0.0.0/8;
deny all;
try_files $uri $uri/ =404;
}
Basic Authentication
# Install htpasswd utility
sudo apt install -y apache2-utils
# Create password file
sudo htpasswd -c /etc/nginx/.htpasswd admin
# Add more users
sudo htpasswd /etc/nginx/.htpasswd user2
location /admin {
auth_basic "Restricted Area";
auth_basic_user_file /etc/nginx/.htpasswd;
}
Performance Tuning
# Worker processes
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
# File cache
open_file_cache max=200000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
# Buffers
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;
# Timeouts
client_header_timeout 3m;
client_body_timeout 3m;
send_timeout 3m;
# TCP optimizations
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;
reset_timedout_connection on;
}
Logging
Custom Log Format
http {
log_format custom '$remote_addr - $remote_user [$time_local] '
'"$request" $status $body_bytes_sent '
'"$http_referer" "$http_user_agent" '
'$request_time';
access_log /var/log/nginx/access.log custom;
error_log /var/log/nginx/error.log warn;
}
Conditional Logging
map $status $loggable {
~^[23] 0;
default 1;
}
server {
access_log /var/log/nginx/access.log combined if=$loggable;
}
Monitoring & Troubleshooting
# Check Nginx status
sudo systemctl status nginx
# Test configuration
sudo nginx -t
# Reload configuration
sudo systemctl reload nginx
# View error logs
sudo tail -f /var/log/nginx/error.log
# View access logs
sudo tail -f /var/log/nginx/access.log
# Check active connections
sudo ss -tunlp | grep nginx
# Monitor requests in real-time
sudo tail -f /var/log/nginx/access.log | grep --line-buffered "200"
Enable Nginx Status
server {
listen 127.0.0.1:80;
server_name localhost;
location /nginx_status {
stub_status on;
access_log off;
allow 127.0.0.1;
deny all;
}
}
# View status
curl http://127.0.0.1/nginx_status
Backup Configuration
# Backup Nginx configuration
sudo tar -czf nginx-backup-$(date +%Y%m%d).tar.gz \
/etc/nginx/ \
/var/www/
# Backup to remote
sudo rsync -avz /etc/nginx/ user@backup:/backup/nginx/
Best Practices
- Use Include Files: Organize configuration with includes
- Enable SSL/TLS: Use modern protocols and ciphers
- Implement Caching: Reduce backend load
- Rate Limiting: Protect against abuse
- Security Headers: Add security headers to all responses
- Logging: Monitor access and error logs regularly
- Performance: Tune worker processes and connections
- Testing: Always test configuration before reloading
- Updates: Keep Nginx updated
- Documentation: Document custom configurations
Resources
- Official Documentation: https://nginx.org/en/docs/
- Ubuntu Nginx Guide: https://ubuntu.com/server/docs/web-servers-nginx
- Nginx Config Generator: https://nginxconfig.io/
- Testing Tool: https://github.com/yandex/gixy