How to configure Nginx web server on Linux

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.