Introduction to Web Server Configuration

Web server configuration is a critical aspect of system administration that directly impacts website performance, security, and reliability. Apache HTTP Server and Nginx are the two most popular web servers powering the modern internet, each offering unique advantages for different use cases.

This comprehensive guide will walk you through the complete setup and configuration of both Apache and Nginx web servers, providing practical examples and best practices for production environments.

Web Server Configuration: Complete Guide to Apache and Nginx Setup

Apache HTTP Server Configuration

Installing Apache

Apache installation varies by operating system. Here are the commands for popular distributions:

Ubuntu/Debian:

sudo apt update
sudo apt install apache2
sudo systemctl enable apache2
sudo systemctl start apache2

CentOS/RHEL:

sudo yum install httpd
sudo systemctl enable httpd
sudo systemctl start httpd

Apache Directory Structure

Understanding Apache’s directory structure is essential for effective configuration:

  • /etc/apache2/ – Main configuration directory
  • /etc/apache2/apache2.conf – Main configuration file
  • /etc/apache2/sites-available/ – Virtual host configuration files
  • /etc/apache2/sites-enabled/ – Active virtual host links
  • /etc/apache2/mods-available/ – Available modules
  • /etc/apache2/mods-enabled/ – Active modules
  • /var/www/html/ – Default document root

Basic Apache Configuration

The main Apache configuration file contains global settings. Here’s a basic configuration example:

# /etc/apache2/apache2.conf

# Server Root
ServerRoot /etc/apache2

# Process ID file
PidFile ${APACHE_PID_FILE}

# Timeout settings
Timeout 300
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

# User and Group
User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

# Host name and port
ServerName example.com:80

# Directory permissions
<Directory />
    Options FollowSymLinks
    AllowOverride None
    Require all denied
</Directory>

<Directory /var/www/>
    Options Indexes FollowSymLinks
    AllowOverride None
    Require all granted
</Directory>

Virtual Host Configuration

Virtual hosts allow hosting multiple websites on a single server. Create a new virtual host configuration:

# /etc/apache2/sites-available/example.com.conf

<VirtualHost *:80>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/example.com_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_access.log combined
    
    # Directory configuration
    <Directory /var/www/example.com/public_html>
        Options -Indexes +FollowSymLinks
        AllowOverride All
        Require all granted
    </Directory>
</VirtualHost>

Enable the virtual host:

sudo a2ensite example.com.conf
sudo systemctl reload apache2

SSL Configuration for Apache

Enable SSL module and configure HTTPS:

sudo a2enmod ssl
sudo a2enmod rewrite
# /etc/apache2/sites-available/example.com-ssl.conf

<VirtualHost *:443>
    ServerName example.com
    ServerAlias www.example.com
    DocumentRoot /var/www/example.com/public_html
    
    # SSL Configuration
    SSLEngine on
    SSLCertificateFile /path/to/certificate.crt
    SSLCertificateKeyFile /path/to/private.key
    SSLCertificateChainFile /path/to/chain.crt
    
    # Security headers
    Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
    Header always set X-Content-Type-Options nosniff
    Header always set X-Frame-Options DENY
    
    # Logging
    ErrorLog ${APACHE_LOG_DIR}/example.com_ssl_error.log
    CustomLog ${APACHE_LOG_DIR}/example.com_ssl_access.log combined
</VirtualHost>

Web Server Configuration: Complete Guide to Apache and Nginx Setup

Nginx Configuration

Installing Nginx

Ubuntu/Debian:

sudo apt update
sudo apt install nginx
sudo systemctl enable nginx
sudo systemctl start nginx

CentOS/RHEL:

sudo yum install nginx
sudo systemctl enable nginx
sudo systemctl start nginx

Nginx Directory Structure

Nginx follows a different organizational structure:

  • /etc/nginx/ – Main configuration directory
  • /etc/nginx/nginx.conf – Main configuration file
  • /etc/nginx/sites-available/ – Virtual host configurations
  • /etc/nginx/sites-enabled/ – Active virtual host links
  • /etc/nginx/conf.d/ – Additional configuration files
  • /var/www/html/ – Default document root

Basic Nginx Configuration

The main Nginx configuration file structure:

# /etc/nginx/nginx.conf

user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;

events {
    worker_connections 1024;
    use epoll;
    multi_accept on;
}

http {
    # MIME types
    include /etc/nginx/mime.types;
    default_type application/octet-stream;
    
    # Logging format
    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;
    
    # Performance settings
    sendfile on;
    tcp_nopush on;
    tcp_nodelay on;
    keepalive_timeout 65;
    types_hash_max_size 2048;
    
    # Gzip compression
    gzip on;
    gzip_vary on;
    gzip_min_length 10240;
    gzip_proxied expired no-cache no-store private must-revalidate max-age=0;
    gzip_types text/plain text/css text/xml text/javascript 
               application/x-javascript application/xml+rss;
    
    # Include virtual hosts
    include /etc/nginx/conf.d/*.conf;
    include /etc/nginx/sites-enabled/*;
}

Nginx Virtual Host Configuration

Create a new server block for your website:

# /etc/nginx/sites-available/example.com

server {
    listen 80;
    listen [::]:80;
    server_name example.com www.example.com;
    root /var/www/example.com/public_html;
    index index.html index.htm index.php;
    
    # Access and error logs
    access_log /var/log/nginx/example.com.access.log;
    error_log /var/log/nginx/example.com.error.log;
    
    # Location blocks
    location / {
        try_files $uri $uri/ =404;
    }
    
    # PHP processing
    location ~ \.php$ {
        include snippets/fastcgi-php.conf;
        fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        include fastcgi_params;
    }
    
    # Deny access to hidden files
    location ~ /\. {
        deny all;
    }
    
    # Static file caching
    location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
        expires 1y;
        add_header Cache-Control "public, immutable";
    }
}

Enable the site:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Nginx SSL Configuration

# /etc/nginx/sites-available/example.com-ssl

server {
    listen 443 ssl http2;
    listen [::]:443 ssl http2;
    server_name example.com www.example.com;
    root /var/www/example.com/public_html;
    
    # SSL certificates
    ssl_certificate /path/to/certificate.crt;
    ssl_certificate_key /path/to/private.key;
    
    # SSL configuration
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384;
    ssl_prefer_server_ciphers off;
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    
    # Security headers
    add_header Strict-Transport-Security "max-age=63072000" always;
    add_header X-Content-Type-Options nosniff always;
    add_header X-Frame-Options DENY always;
    
    # OCSP stapling
    ssl_stapling on;
    ssl_stapling_verify on;
    
    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;
}

Performance Optimization

Apache Performance Tuning

Configure Apache’s Multi-Processing Module (MPM):

# /etc/apache2/mods-available/mpm_prefork.conf

<IfModule mpm_prefork_module>
    StartServers             8
    MinSpareServers          5
    MaxSpareServers         20
    ServerLimit            256
    MaxRequestWorkers      256
    MaxConnectionsPerChild   0
</IfModule>

Enable compression:

# Enable mod_deflate
LoadModule deflate_module modules/mod_deflate.so

<Location />
    SetOutputFilter DEFLATE
    SetEnvIfNoCase Request_URI \
        \.(?:gif|jpe?g|png)$ no-gzip dont-vary
    SetEnvIfNoCase Request_URI \
        \.(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
</Location>

Nginx Performance Tuning

Optimize worker processes and connections:

# Performance optimization in nginx.conf

worker_processes auto;
worker_rlimit_nofile 65535;

events {
    worker_connections 4096;
    use epoll;
    multi_accept on;
}

http {
    # Buffer sizes
    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;
    
    # Connection processing
    keepalive_timeout 65;
    keepalive_requests 100000;
    reset_timedout_connection on;
}

Web Server Configuration: Complete Guide to Apache and Nginx Setup

Load Balancing Configuration

Nginx as Load Balancer

Configure Nginx to distribute traffic across multiple backend servers:

# /etc/nginx/nginx.conf

http {
    # Upstream backend servers
    upstream backend_servers {
        least_conn;
        server 192.168.1.10:80 weight=3;
        server 192.168.1.11:80 weight=2;
        server 192.168.1.12:80 weight=1 backup;
        
        # Health check
        keepalive 32;
    }
    
    server {
        listen 80;
        server_name example.com;
        
        location / {
            proxy_pass http://backend_servers;
            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 timeouts
            proxy_connect_timeout 30s;
            proxy_send_timeout 30s;
            proxy_read_timeout 30s;
        }
    }
}

Apache with mod_proxy_balancer

# Enable required modules
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_balancer_module modules/mod_proxy_balancer.so
LoadModule lbmethod_byrequests_module modules/mod_lbmethod_byrequests.so

# Load balancer configuration
<Proxy balancer://mycluster>
    BalancerMember http://192.168.1.10:80
    BalancerMember http://192.168.1.11:80
    BalancerMember http://192.168.1.12:80 status=+H
    ProxySet lbmethod=byrequests
</Proxy>

<VirtualHost *:80>
    ServerName example.com
    ProxyPass / balancer://mycluster/
    ProxyPassReverse / balancer://mycluster/
</VirtualHost>

Web Server Configuration: Complete Guide to Apache and Nginx Setup

Security Configuration

Apache Security Hardening

# Security configuration in apache2.conf

# Hide server information
ServerTokens Prod
ServerSignature Off

# Prevent access to .htaccess files
<FilesMatch "^\.ht">
    Require all denied
</FilesMatch>

# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options SAMEORIGIN
Header always set X-XSS-Protection "1; mode=block"
Header always set Referrer-Policy "strict-origin-when-cross-origin"

# Disable unnecessary HTTP methods
<Directory />
    <LimitExcept GET POST HEAD>
        Require all denied
    </LimitExcept>
</Directory>

Nginx Security Hardening

# Security configuration in nginx.conf

# Hide server information
server_tokens off;

# 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;
add_header Content-Security-Policy "default-src 'self' http: https: data: blob: 'unsafe-inline'" always;

# Rate limiting
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

server {
    # Apply rate limiting
    limit_req zone=one burst=10 nodelay;
    
    # Disable unwanted HTTP methods
    if ($request_method !~ ^(GET|HEAD|POST)$ ) {
        return 405;
    }
}

Monitoring and Logging

Apache Monitoring

Enable server status module:

# Enable mod_status
LoadModule status_module modules/mod_status.so

<Location "/server-status">
    SetHandler server-status
    Require local
    Require ip 192.168.1
</Location>

<Location "/server-info">
    SetHandler server-info
    Require local
    Require ip 192.168.1
</Location>

Nginx Monitoring

Configure status module:

server {
    listen 8080;
    server_name localhost;
    
    location /nginx_status {
        stub_status on;
        access_log off;
        allow 127.0.0.1;
        allow 192.168.1.0/24;
        deny all;
    }
}

Log Analysis

Configure detailed logging for both servers:

# Custom Nginx log format
log_format detailed '$remote_addr - $remote_user [$time_local] '
                   '"$request" $status $bytes_sent '
                   '"$http_referer" "$http_user_agent" '
                   '$request_time $upstream_response_time';

access_log /var/log/nginx/detailed.log detailed;

Web Server Configuration: Complete Guide to Apache and Nginx Setup

Best Practices and Troubleshooting

Configuration Best Practices

  • Regular Backups: Always backup configuration files before making changes
  • Version Control: Use Git to track configuration changes
  • Testing: Test configurations in staging environments
  • Documentation: Document all custom configurations
  • Security Updates: Keep servers updated with latest security patches
  • Monitoring: Implement comprehensive monitoring and alerting

Common Troubleshooting Commands

Apache diagnostics:

# Test configuration syntax
sudo apache2ctl configtest

# Check enabled modules
apache2ctl -M

# View error logs
sudo tail -f /var/log/apache2/error.log

# Check virtual host configuration
apache2ctl -S

Nginx diagnostics:

# Test configuration syntax
sudo nginx -t

# Reload configuration
sudo nginx -s reload

# View error logs
sudo tail -f /var/log/nginx/error.log

# Check configuration
nginx -T

Performance Monitoring

Use these tools to monitor server performance:

  • htop/top: System resource monitoring
  • iotop: Disk I/O monitoring
  • netstat: Network connection monitoring
  • apache2buddy.pl: Apache performance analysis
  • nginx-amplify: Nginx monitoring service

Conclusion

Proper web server configuration is crucial for maintaining secure, performant, and reliable web applications. Apache excels in environments requiring extensive module support and .htaccess flexibility, while Nginx shines in high-concurrency scenarios and as a reverse proxy.

Both servers can be configured to handle modern web application demands effectively. Regular monitoring, security updates, and performance optimization ensure your web infrastructure remains robust and scalable as your applications grow.

Remember to always test configurations in staging environments, maintain backups, and implement comprehensive monitoring to catch issues before they impact production systems.