๐ AlmaLinux Web Server Setup: Nginx & Apache Complete Guide
Ready to build lightning-fast, bulletproof web servers? โก This comprehensive guide will transform you into a web server master, covering both Nginx and Apache configurations that can handle millions of requests while keeping your websites secure and blazingly fast!
Web server mastery isnโt just about serving web pages โ itโs about creating a robust, scalable foundation that delivers exceptional user experiences while maintaining enterprise-grade security and performance. Letโs build web infrastructure that never sleeps! ๐
๐ค Why Master Web Server Configuration?
Think of web servers as the digital doorways to your online empire! ๐ฐ Hereโs why mastering both Nginx and Apache is absolutely crucial:
- โก Lightning Performance: Properly configured servers handle thousands of concurrent connections
- ๐ก๏ธ Rock-Solid Security: Advanced SSL/TLS, security headers, and access controls protect your sites
- ๐ Infinite Scalability: Load balancing and clustering support massive traffic growth
- ๐ฏ Perfect Reliability: High availability configurations ensure 99.99% uptime
- ๐ฐ Cost Efficiency: Optimized servers reduce hardware requirements and hosting costs
- ๐ Flexible Architecture: Support for multiple sites, applications, and technologies
- ๐ Global Reach: CDN integration and geographic load balancing
- ๐ Smart Analytics: Built-in logging and monitoring for data-driven optimization
๐ฏ What You Need
Before we dive into web server mastery, letโs make sure you have everything ready:
โ AlmaLinux server (your web hosting powerhouse!) โ Domain name(s) (for testing virtual hosts and SSL certificates) โ Root or sudo access (needed for web server installation and configuration) โ At least 2GB RAM (more traffic = more memory needed) โ Fast storage (SSDs dramatically improve web server performance) โ Network connectivity (obviously needed for web serving!) โ Text editor (nano, vim, or your favorite editor) โ Basic understanding of DNS (how domain names point to servers)
๐ Step 1: Nginx Installation and Basic Configuration
Letโs start with Nginx, the performance champion! ๐๏ธ Nginx excels at handling massive concurrent connections with minimal resource usage.
# Update system packages
sudo dnf update -y
# Ensures you have the latest security patches
# Install Nginx
sudo dnf install -y nginx
# Installs the latest stable Nginx version
# Start and enable Nginx service
sudo systemctl enable --now nginx
# Starts Nginx and configures it to start automatically
# Check Nginx status
sudo systemctl status nginx
# Verifies Nginx is running properly
# Test Nginx is serving pages
curl -I http://localhost
# Should return HTTP/1.1 200 OK
Configure firewall for web traffic:
# Allow HTTP and HTTPS traffic through firewall
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# Verify firewall rules
sudo firewall-cmd --list-services
# Should show http and https in the list
Create optimized Nginx configuration:
# Backup original configuration
sudo cp /etc/nginx/nginx.conf /etc/nginx/nginx.conf.backup
# Create optimized main configuration
sudo nano /etc/nginx/nginx.conf
# Replace with this optimized configuration:
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log;
pid /run/nginx.pid;
# Load dynamic modules
include /usr/share/nginx/modules/*.conf;
events {
worker_connections 4096;
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;
# 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" '
'rt=$request_time uct="$upstream_connect_time" '
'uht="$upstream_header_time" urt="$upstream_response_time"';
access_log /var/log/nginx/access.log main;
# Gzip compression
gzip on;
gzip_vary on;
gzip_min_length 1024;
gzip_proxied expired no-cache no-store private auth;
gzip_types text/plain text/css text/xml text/javascript
application/x-javascript application/xml+rss
application/javascript application/json
application/xml application/rss+xml
application/atom+xml image/svg+xml;
# Security headers
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
# Rate limiting
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=login:10m rate=1r/s;
# Include virtual host configurations
include /etc/nginx/conf.d/*.conf;
include /etc/nginx/sites-enabled/*;
}
Create sites directory structure:
# Create sites directories (similar to Debian/Ubuntu structure)
sudo mkdir -p /etc/nginx/sites-available
sudo mkdir -p /etc/nginx/sites-enabled
# Create document root directories
sudo mkdir -p /var/www/html
sudo mkdir -p /var/www/example.com
sudo mkdir -p /var/www/api.example.com
# Set proper ownership and permissions
sudo chown -R nginx:nginx /var/www
sudo chmod -R 755 /var/www
Create Nginx management script:
# Create Nginx management helper
sudo nano /usr/local/bin/nginx-manager.sh
#!/bin/bash
echo "๐ NGINX MANAGEMENT TOOL"
echo "========================"
show_status() {
echo "๐ Nginx Status:"
sudo systemctl status nginx --no-pager -l
echo ""
echo "๐ Active Connections:"
ss -tuln | grep :80
ss -tuln | grep :443
echo ""
echo "๐ Current Connections:"
curl -s http://localhost/nginx_status 2>/dev/null || echo "Status page not configured"
}
test_config() {
echo "๐งช Testing Nginx Configuration:"
sudo nginx -t
if [ $? -eq 0 ]; then
echo "โ
Configuration is valid"
else
echo "โ Configuration has errors"
return 1
fi
}
reload_nginx() {
echo "๐ Reloading Nginx Configuration:"
test_config && sudo systemctl reload nginx
if [ $? -eq 0 ]; then
echo "โ
Nginx reloaded successfully"
else
echo "โ Nginx reload failed"
return 1
fi
}
show_sites() {
echo "๐ Available Sites:"
ls -la /etc/nginx/sites-available/ 2>/dev/null || echo "No sites found"
echo ""
echo "โ
Enabled Sites:"
ls -la /etc/nginx/sites-enabled/ 2>/dev/null || echo "No enabled sites found"
}
enable_site() {
local site="$1"
if [ -z "$site" ]; then
echo "Usage: $0 enable <site-name>"
return 1
fi
if [ ! -f "/etc/nginx/sites-available/$site" ]; then
echo "โ Site '$site' not found in sites-available"
return 1
fi
sudo ln -sf "/etc/nginx/sites-available/$site" "/etc/nginx/sites-enabled/$site"
echo "โ
Site '$site' enabled"
test_config && reload_nginx
}
disable_site() {
local site="$1"
if [ -z "$site" ]; then
echo "Usage: $0 disable <site-name>"
return 1
fi
sudo rm -f "/etc/nginx/sites-enabled/$site"
echo "โ
Site '$site' disabled"
reload_nginx
}
case "$1" in
status)
show_status
;;
test)
test_config
;;
reload)
reload_nginx
;;
sites)
show_sites
;;
enable)
enable_site "$2"
;;
disable)
disable_site "$2"
;;
*)
echo "Usage: $0 {status|test|reload|sites|enable|disable}"
echo " status - Show Nginx status and connections"
echo " test - Test configuration syntax"
echo " reload - Reload Nginx configuration"
echo " sites - List available and enabled sites"
echo " enable <site> - Enable a site"
echo " disable <site> - Disable a site"
;;
esac
# Make the script executable
sudo chmod +x /usr/local/bin/nginx-manager.sh
# Test Nginx configuration
sudo /usr/local/bin/nginx-manager.sh test
๐ง Step 2: Apache Installation and Configuration
Now letโs set up Apache, the versatile powerhouse! ๐ช Apache offers incredible flexibility and module support for complex configurations.
# Install Apache HTTP server
sudo dnf install -y httpd httpd-tools
# httpd is the Apache package name on RHEL/AlmaLinux
# httpd-tools provides useful utilities
# Start and enable Apache service
sudo systemctl enable --now httpd
# Check Apache status
sudo systemctl status httpd
# Test Apache is serving pages
curl -I http://localhost
# Should return HTTP/1.1 200 OK with Server: Apache header
Configure Apache with optimized settings:
# Backup original configuration
sudo cp /etc/httpd/conf/httpd.conf /etc/httpd/conf/httpd.conf.backup
# Create optimized Apache configuration
sudo nano /etc/httpd/conf.d/performance.conf
# Add these performance optimizations:
# Server Performance Settings
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# Prefork MPM settings (for PHP compatibility)
<IfModule mod_prefork.c>
StartServers 8
MinSpareServers 5
MaxSpareServers 20
ServerLimit 256
MaxRequestWorkers 256
MaxConnectionsPerChild 4000
</IfModule>
# Event MPM settings (better performance, no PHP)
<IfModule mod_event.c>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 400
MaxConnectionsPerChild 0
</IfModule>
# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
# Hide Apache version
ServerTokens Prod
ServerSignature Off
# Compression
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>
Create virtual hosts configuration:
# Create virtual hosts directory
sudo mkdir -p /etc/httpd/sites-available
sudo mkdir -p /etc/httpd/sites-enabled
# Add include directive to main configuration
echo "IncludeOptional sites-enabled/*.conf" | sudo tee -a /etc/httpd/conf/httpd.conf
# Create document roots
sudo mkdir -p /var/www/html
sudo mkdir -p /var/www/example.com
sudo mkdir -p /var/www/blog.example.com
# Set proper ownership
sudo chown -R apache:apache /var/www
sudo chmod -R 755 /var/www
Create Apache management script:
# Create Apache management helper
sudo nano /usr/local/bin/apache-manager.sh
#!/bin/bash
echo "๐๏ธ APACHE MANAGEMENT TOOL"
echo "=========================="
show_status() {
echo "๐ Apache Status:"
sudo systemctl status httpd --no-pager -l
echo ""
echo "๐ Active Connections:"
ss -tuln | grep :80
ss -tuln | grep :443
echo ""
echo "๐ Server Information:"
httpd -V | head -10
}
test_config() {
echo "๐งช Testing Apache Configuration:"
sudo httpd -t
if [ $? -eq 0 ]; then
echo "โ
Configuration is valid"
else
echo "โ Configuration has errors"
return 1
fi
}
reload_apache() {
echo "๐ Reloading Apache Configuration:"
test_config && sudo systemctl reload httpd
if [ $? -eq 0 ]; then
echo "โ
Apache reloaded successfully"
else
echo "โ Apache reload failed"
return 1
fi
}
show_modules() {
echo "๐งฉ Loaded Apache Modules:"
httpd -M | sort
}
show_sites() {
echo "๐ Available Sites:"
ls -la /etc/httpd/sites-available/ 2>/dev/null || echo "No sites found"
echo ""
echo "โ
Enabled Sites:"
ls -la /etc/httpd/sites-enabled/ 2>/dev/null || echo "No enabled sites found"
}
enable_site() {
local site="$1"
if [ -z "$site" ]; then
echo "Usage: $0 enable <site-name>"
return 1
fi
if [ ! -f "/etc/httpd/sites-available/$site" ]; then
echo "โ Site '$site' not found in sites-available"
return 1
fi
sudo ln -sf "/etc/httpd/sites-available/$site" "/etc/httpd/sites-enabled/$site"
echo "โ
Site '$site' enabled"
test_config && reload_apache
}
disable_site() {
local site="$1"
if [ -z "$site" ]; then
echo "Usage: $0 disable <site-name>"
return 1
fi
sudo rm -f "/etc/httpd/sites-enabled/$site"
echo "โ
Site '$site' disabled"
reload_apache
}
case "$1" in
status)
show_status
;;
test)
test_config
;;
reload)
reload_apache
;;
modules)
show_modules
;;
sites)
show_sites
;;
enable)
enable_site "$2"
;;
disable)
disable_site "$2"
;;
*)
echo "Usage: $0 {status|test|reload|modules|sites|enable|disable}"
echo " status - Show Apache status and connections"
echo " test - Test configuration syntax"
echo " reload - Reload Apache configuration"
echo " modules - List loaded modules"
echo " sites - List available and enabled sites"
echo " enable <site> - Enable a site"
echo " disable <site> - Disable a site"
;;
esac
# Make the script executable
sudo chmod +x /usr/local/bin/apache-manager.sh
# Test Apache configuration
sudo /usr/local/bin/apache-manager.sh test
๐ Step 3: SSL/TLS Configuration with Letโs Encrypt
Letโs secure your websites with free SSL certificates! ๐ HTTPS is essential for security, SEO, and user trust.
Install Certbot for automatic SSL certificates:
# Install EPEL repository (if not already installed)
sudo dnf install -y epel-release
# Install Certbot and web server plugins
sudo dnf install -y certbot python3-certbot-nginx python3-certbot-apache
# Verify Certbot installation
certbot --version
Configure SSL for Nginx:
# Create SSL-ready Nginx virtual host
sudo nano /etc/nginx/sites-available/example.com
server {
listen 80;
server_name example.com www.example.com;
# Redirect all HTTP traffic to HTTPS
return 301 https://$server_name$request_uri;
}
server {
listen 443 ssl http2;
server_name example.com www.example.com;
root /var/www/example.com;
index index.html index.php;
# SSL configuration (certificates will be added by Certbot)
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-SHA256:ECDHE-RSA-AES256-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=31536000; includeSubDomains" always;
# Security headers
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
add_header X-XSS-Protection "1; mode=block" always;
# Gzip compression
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
location / {
try_files $uri $uri/ =404;
}
# PHP-FPM configuration (if needed)
location ~ \.php$ {
fastcgi_pass unix:/run/php-fpm/www.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
# Deny access to hidden files
location ~ /\. {
deny all;
access_log off;
log_not_found off;
}
# Browser caching for static assets
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
}
# Enable the site
sudo /usr/local/bin/nginx-manager.sh enable example.com
Configure SSL for Apache:
# Create SSL-ready Apache virtual host
sudo nano /etc/httpd/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# Redirect all HTTP to HTTPS
RewriteEngine On
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
</VirtualHost>
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com
# SSL Engine
SSLEngine on
# SSL Configuration (certificates will be added by Certbot)
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384
SSLHonorCipherOrder off
SSLSessionTickets off
# Security headers
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"
Header always set X-Frame-Options DENY
Header always set X-Content-Type-Options nosniff
Header always set X-XSS-Protection "1; mode=block"
# Logging
ErrorLog /var/log/httpd/example.com_error.log
CustomLog /var/log/httpd/example.com_access.log combined
# Document root settings
<Directory "/var/www/example.com">
AllowOverride All
Require all granted
</Directory>
# Deny access to hidden files
<FilesMatch "^\.">
Require all denied
</FilesMatch>
# Browser caching
<FilesMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$">
ExpiresActive On
ExpiresDefault "access plus 1 year"
Header append Cache-Control "public"
</FilesMatch>
</VirtualHost>
# Enable the site
sudo /usr/local/bin/apache-manager.sh enable example.com.conf
Obtain SSL certificates:
# Create sample website content
sudo mkdir -p /var/www/example.com
echo "<h1>Welcome to Example.com</h1><p>Secured with Let's Encrypt SSL!</p>" | sudo tee /var/www/example.com/index.html
# For Nginx - obtain SSL certificate
sudo certbot --nginx -d example.com -d www.example.com
# For Apache - obtain SSL certificate
# sudo certbot --apache -d example.com -d www.example.com
# Test automatic renewal
sudo certbot renew --dry-run
Create SSL management script:
# Create SSL certificate management script
sudo nano /usr/local/bin/ssl-manager.sh
#!/bin/bash
echo "๐ SSL CERTIFICATE MANAGER"
echo "=========================="
list_certificates() {
echo "๐ Installed Certificates:"
sudo certbot certificates
}
renew_certificates() {
echo "๐ Renewing SSL Certificates:"
sudo certbot renew
# Reload web servers if certificates were renewed
if sudo certbot renew --dry-run 2>&1 | grep -q "renew"; then
echo "๐ Reloading web servers..."
sudo systemctl reload nginx 2>/dev/null
sudo systemctl reload httpd 2>/dev/null
fi
}
check_expiry() {
echo "โฐ Certificate Expiry Information:"
# Check all certificates
sudo certbot certificates | grep -E "(Certificate Name|Expiry Date)" | while read line; do
echo " $line"
done
}
setup_auto_renewal() {
echo "๐ค Setting up automatic renewal..."
# Create cron job for automatic renewal
(crontab -l 2>/dev/null; echo "0 12 * * * /usr/bin/certbot renew --quiet") | crontab -
# Create systemd timer (alternative method)
sudo systemctl enable --now certbot-renew.timer
echo "โ
Automatic renewal configured"
echo "๐
Certificates will be checked daily at 12:00"
}
test_config() {
echo "๐งช Testing SSL Configuration:"
# Test certificate installation
openssl s_client -connect localhost:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -text | grep -E "(Subject|Issuer|Not After)"
}
case "$1" in
list)
list_certificates
;;
renew)
renew_certificates
;;
expiry)
check_expiry
;;
auto)
setup_auto_renewal
;;
test)
test_config
;;
*)
echo "Usage: $0 {list|renew|expiry|auto|test}"
echo " list - List all installed certificates"
echo " renew - Renew certificates manually"
echo " expiry - Check certificate expiry dates"
echo " auto - Set up automatic renewal"
echo " test - Test SSL configuration"
;;
esac
# Make the script executable
sudo chmod +x /usr/local/bin/ssl-manager.sh
# Set up automatic renewal
sudo /usr/local/bin/ssl-manager.sh auto
โ Step 4: Load Balancing and High Availability
Letโs create a bulletproof web infrastructure! ๐๏ธ Weโll set up load balancing to distribute traffic across multiple servers.
Configure Nginx as a load balancer:
# Create load balancer configuration
sudo nano /etc/nginx/conf.d/load-balancer.conf
# Define upstream servers
upstream web_backend {
# Load balancing methods: round-robin (default), least_conn, ip_hash
least_conn;
# Backend servers
server 192.168.1.101:80 weight=3 max_fails=3 fail_timeout=30s;
server 192.168.1.102:80 weight=2 max_fails=3 fail_timeout=30s;
server 192.168.1.103:80 weight=1 max_fails=3 fail_timeout=30s backup;
# Health check (Nginx Plus feature, using max_fails for open source)
keepalive 32;
}
upstream api_backend {
ip_hash; # Session persistence based on client IP
server 192.168.1.201:8080 max_fails=2 fail_timeout=10s;
server 192.168.1.202:8080 max_fails=2 fail_timeout=10s;
keepalive 16;
}
# Load balancer virtual host
server {
listen 80;
listen 443 ssl http2;
server_name loadbalancer.example.com;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/loadbalancer.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/loadbalancer.example.com/privkey.pem;
# Security headers
add_header X-Load-Balancer "nginx" always;
add_header X-Backend-Server $upstream_addr always;
# Main website load balancing
location / {
proxy_pass http://web_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;
# Proxy timeouts
proxy_connect_timeout 5s;
proxy_send_timeout 10s;
proxy_read_timeout 10s;
# Enable proxy buffering
proxy_buffering on;
proxy_buffer_size 4k;
proxy_buffers 8 4k;
# Health check
proxy_next_upstream error timeout invalid_header http_500 http_502 http_503 http_504;
}
# API load balancing with session persistence
location /api/ {
proxy_pass http://api_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;
# API-specific settings
proxy_connect_timeout 3s;
proxy_send_timeout 5s;
proxy_read_timeout 5s;
}
# Health check endpoint
location /health {
access_log off;
return 200 "OK\n";
add_header Content-Type text/plain;
}
# Load balancer status (restrict access)
location /lb-status {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
access_log off;
return 200 "Load Balancer Status: Active\nBackend Servers: $upstream_addr\n";
add_header Content-Type text/plain;
}
}
Configure Apache with mod_proxy for load balancing:
# Enable required modules
sudo dnf install -y httpd-devel
sudo systemctl restart httpd
# Create Apache load balancer configuration
sudo nano /etc/httpd/conf.d/load-balancer.conf
# Load 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
LoadModule lbmethod_bytraffic_module modules/mod_lbmethod_bytraffic.so
# Define proxy balancer clusters
ProxyPreserveHost On
ProxyRequests Off
<Proxy "balancer://web-cluster">
BalancerMember http://192.168.1.101:80 route=1
BalancerMember http://192.168.1.102:80 route=2
BalancerMember http://192.168.1.103:80 route=3 status=+H
ProxySet lbmethod=byrequests
</Proxy>
<Proxy "balancer://api-cluster">
BalancerMember http://192.168.1.201:8080 route=api1
BalancerMember http://192.168.1.202:8080 route=api2
ProxySet lbmethod=bytraffic
Header add Set-Cookie "ROUTEID=.%{BALANCER_WORKER_ROUTE}e; path=/"
</Proxy>
<VirtualHost *:80>
ServerName loadbalancer.example.com
# Main website load balancing
ProxyPass / balancer://web-cluster/
ProxyPassReverse / balancer://web-cluster/
# API load balancing
ProxyPass /api/ balancer://api-cluster/
ProxyPassReverse /api/ balancer://api-cluster/
# Balancer manager (restrict access)
<Location "/balancer-manager">
SetHandler balancer-manager
Require ip 127.0.0.1
Require ip 192.168.1.0/24
</Location>
# Health check
<Location "/health">
SetHandler server-status
Require all granted
</Location>
# Logging
ErrorLog /var/log/httpd/loadbalancer_error.log
CustomLog /var/log/httpd/loadbalancer_access.log combined
</VirtualHost>
Create load balancer monitoring script:
# Create load balancer monitoring script
sudo nano /usr/local/bin/lb-monitor.sh
#!/bin/bash
echo "โ๏ธ LOAD BALANCER MONITOR"
echo "========================"
check_backend_health() {
echo "๐ฅ Backend Server Health Check:"
echo "================================"
# List of backend servers
BACKENDS=(
"192.168.1.101:80"
"192.168.1.102:80"
"192.168.1.103:80"
"192.168.1.201:8080"
"192.168.1.202:8080"
)
for backend in "${BACKENDS[@]}"; do
echo -n "Testing $backend: "
if curl -s --connect-timeout 5 "http://$backend/health" >/dev/null 2>&1; then
echo "โ
Healthy"
else
echo "โ Unhealthy"
fi
done
}
show_nginx_upstream() {
echo "๐ Nginx Upstream Status:"
echo "========================="
# Check Nginx upstream status (requires nginx-plus or custom module)
if command -v nginx-debug >/dev/null 2>&1; then
nginx-debug -T | grep -A 20 "upstream"
else
echo "๐ก Install nginx-plus or nginx-module-upstream for detailed upstream stats"
echo "๐ Current configuration:"
grep -A 10 "upstream" /etc/nginx/conf.d/load-balancer.conf
fi
}
show_apache_balancer() {
echo "โ๏ธ Apache Balancer Status:"
echo "=========================="
# Query Apache balancer manager
if curl -s "http://localhost/balancer-manager" >/dev/null 2>&1; then
echo "๐ Balancer manager available at: http://localhost/balancer-manager"
curl -s "http://localhost/balancer-manager" | grep -E "(balancer|Member|Status)" | head -20
else
echo "โ Balancer manager not accessible"
fi
}
test_load_distribution() {
echo "๐งช Load Distribution Test:"
echo "=========================="
echo "Making 10 requests to test load balancing..."
for i in {1..10}; do
RESPONSE=$(curl -s -H "X-Test-Request: $i" http://localhost/health 2>/dev/null)
BACKEND=$(curl -s -I http://localhost/ 2>/dev/null | grep -i "x-backend-server" | cut -d: -f2 | tr -d ' \r')
echo "Request $i: Backend $BACKEND"
sleep 1
done
}
monitor_connections() {
echo "๐ Active Connections Monitor:"
echo "=============================="
echo "Load balancer connections:"
ss -tuln | grep -E ":(80|443|8080)" | while read line; do
echo " $line"
done
echo ""
echo "Connection summary:"
ss -s
}
case "$1" in
health)
check_backend_health
;;
nginx)
show_nginx_upstream
;;
apache)
show_apache_balancer
;;
test)
test_load_distribution
;;
connections)
monitor_connections
;;
all)
check_backend_health
echo ""
show_nginx_upstream
echo ""
test_load_distribution
;;
*)
echo "Usage: $0 {health|nginx|apache|test|connections|all}"
echo " health - Check backend server health"
echo " nginx - Show Nginx upstream status"
echo " apache - Show Apache balancer status"
echo " test - Test load distribution"
echo " connections - Monitor active connections"
echo " all - Run all checks"
;;
esac
# Make the script executable
sudo chmod +x /usr/local/bin/lb-monitor.sh
# Test load balancer health
sudo /usr/local/bin/lb-monitor.sh health
๐ Step 5: Performance Optimization and Monitoring
Letโs supercharge your web servers for maximum performance! ๐ Weโll implement caching, compression, and monitoring.
Configure advanced caching for Nginx:
# Create Nginx caching configuration
sudo nano /etc/nginx/conf.d/caching.conf
# Proxy cache configuration
proxy_cache_path /var/cache/nginx/proxy levels=1:2 keys_zone=proxy_cache:10m max_size=1g inactive=60m use_temp_path=off;
proxy_cache_path /var/cache/nginx/static levels=1:2 keys_zone=static_cache:10m max_size=2g inactive=7d use_temp_path=off;
# Create cache directories
mkdir -p /var/cache/nginx/proxy
mkdir -p /var/cache/nginx/static
chown -R nginx:nginx /var/cache/nginx
chmod -R 755 /var/cache/nginx
# FastCGI cache (for PHP)
fastcgi_cache_path /var/cache/nginx/fastcgi levels=1:2 keys_zone=fastcgi_cache:100m max_size=1g inactive=60m use_temp_path=off;
map $request_method $purge_method {
PURGE 1;
default 0;
}
# Cache configuration for different content types
map $uri $cache_control {
~*\.(css|js)$ "public, max-age=31536000, immutable";
~*\.(jpg|jpeg|png|gif|ico|svg|webp)$ "public, max-age=31536000, immutable";
~*\.(woff|woff2|ttf|eot)$ "public, max-age=31536000, immutable";
~*\.(pdf|doc|docx)$ "public, max-age=86400";
default "public, max-age=0, must-revalidate";
}
Add caching to Nginx virtual host:
# Update Nginx virtual host with caching
sudo nano /etc/nginx/sites-available/example.com
# Add these location blocks to your server block:
# Static file caching
location ~* \.(css|js|jpg|jpeg|png|gif|ico|svg|webp|woff|woff2|ttf|eot|pdf|doc|docx)$ {
root /var/www/example.com;
expires 1y;
add_header Cache-Control $cache_control;
add_header X-Cache-Status "STATIC";
# Enable gzip for text-based static files
gzip_static on;
# Optional: serve compressed versions if available
try_files $uri $uri.gz $uri =404;
}
# API response caching
location /api/ {
proxy_pass http://api_backend;
# Proxy cache settings
proxy_cache proxy_cache;
proxy_cache_valid 200 302 10m;
proxy_cache_valid 404 1m;
proxy_cache_key $scheme$proxy_host$request_uri$is_args$args;
proxy_cache_bypass $arg_nocache $cookie_nocache $http_pragma $http_authorization;
# Cache headers
add_header X-Cache-Status $upstream_cache_status;
add_header X-Cache-Key $scheme$proxy_host$request_uri$is_args$args;
# Standard proxy headers
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;
}
# Cache purge endpoint (restrict access)
location ~ /purge(/.*) {
allow 127.0.0.1;
allow 192.168.1.0/24;
deny all;
proxy_cache_purge proxy_cache $scheme$proxy_host$1$is_args$args;
}
Configure Apache caching modules:
# Enable Apache caching modules
sudo nano /etc/httpd/conf.d/caching.conf
# Load caching modules
LoadModule cache_module modules/mod_cache.so
LoadModule cache_disk_module modules/mod_cache_disk.so
LoadModule expires_module modules/mod_expires.so
LoadModule headers_module modules/mod_headers.so
# Disk cache configuration
CacheRoot /var/cache/httpd/
CacheEnable disk /
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 1000000
CacheMinFileSize 1
CacheDefaultExpire 3600
# Create cache directory
mkdir -p /var/cache/httpd
chown apache:apache /var/cache/httpd
chmod 755 /var/cache/httpd
# Expires configuration
ExpiresActive On
ExpiresByType text/css "access plus 1 year"
ExpiresByType application/javascript "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
# Cache control headers
<FilesMatch "\.(css|js|png|jpg|jpeg|gif|ico|svg|woff|woff2)$">
Header set Cache-Control "public, max-age=31536000, immutable"
Header set X-Cache-Status "STATIC"
</FilesMatch>
<FilesMatch "\.(html|htm)$">
Header set Cache-Control "public, max-age=3600, must-revalidate"
</FilesMatch>
Create performance monitoring script:
# Create web server performance monitor
sudo nano /usr/local/bin/web-performance.sh
#!/bin/bash
echo "๐ WEB SERVER PERFORMANCE MONITOR"
echo "=================================="
monitor_nginx() {
echo "๐ Nginx Performance Metrics:"
echo "============================="
# Nginx status (requires stub_status module)
if curl -s http://localhost/nginx_status >/dev/null 2>&1; then
echo "๐ Nginx Status:"
curl -s http://localhost/nginx_status
else
echo "๐ก Configure stub_status module for detailed metrics"
fi
echo ""
echo "๐ Active Connections:"
ss -tuln | grep :80 | wc -l
echo ""
echo "๐พ Cache Statistics:"
if [ -d /var/cache/nginx ]; then
echo "Cache size: $(du -sh /var/cache/nginx 2>/dev/null | cut -f1)"
echo "Cache files: $(find /var/cache/nginx -type f 2>/dev/null | wc -l)"
fi
}
monitor_apache() {
echo "๐๏ธ Apache Performance Metrics:"
echo "=============================="
# Apache status (requires mod_status)
if curl -s http://localhost/server-status >/dev/null 2>&1; then
echo "๐ Apache Status:"
curl -s "http://localhost/server-status?auto"
else
echo "๐ก Configure mod_status for detailed metrics"
fi
echo ""
echo "๐ Active Connections:"
ss -tuln | grep :80 | wc -l
echo ""
echo "๐พ Cache Statistics:"
if [ -d /var/cache/httpd ]; then
echo "Cache size: $(du -sh /var/cache/httpd 2>/dev/null | cut -f1)"
echo "Cache files: $(find /var/cache/httpd -type f 2>/dev/null | wc -l)"
fi
}
test_response_times() {
echo "โฑ๏ธ Response Time Testing:"
echo "========================"
URLS=(
"http://localhost/"
"http://localhost/static/test.css"
"http://localhost/api/health"
)
for url in "${URLS[@]}"; do
echo -n "Testing $url: "
TIME=$(curl -o /dev/null -s -w "%{time_total}" "$url" 2>/dev/null)
echo "${TIME}s"
done
}
check_ssl_performance() {
echo "๐ SSL Performance Check:"
echo "========================"
# Test SSL handshake time
echo -n "SSL handshake time: "
TIME=$(curl -o /dev/null -s -w "%{time_connect}" "https://localhost/" 2>/dev/null)
echo "${TIME}s"
# Check SSL configuration
echo "SSL configuration score:"
if command -v sslscan >/dev/null 2>&1; then
sslscan localhost:443 | grep -E "(Certificate|Cipher|Protocol)" | head -5
else
echo "Install sslscan for detailed SSL analysis"
fi
}
generate_performance_report() {
echo "๐ Generating Performance Report..."
REPORT_FILE="/tmp/web-performance-$(date +%Y%m%d_%H%M%S).txt"
{
echo "Web Server Performance Report"
echo "Generated: $(date)"
echo "=============================="
echo ""
# System resources
echo "System Resources:"
echo "CPU Usage: $(top -bn1 | grep "Cpu(s)" | awk '{print $2}' | cut -d'%' -f1)%"
echo "Memory Usage: $(free | grep Mem | awk '{printf("%.1f", $3/$2 * 100.0)}')%"
echo "Disk Usage: $(df / | awk 'NR==2{print $5}')"
echo ""
# Network connections
echo "Network Connections:"
echo "HTTP (port 80): $(ss -tuln | grep :80 | wc -l) listeners"
echo "HTTPS (port 443): $(ss -tuln | grep :443 | wc -l) listeners"
echo ""
# Response times
echo "Response Times:"
test_response_times 2>&1
} > "$REPORT_FILE"
echo "โ
Report saved to: $REPORT_FILE"
echo "๐ Summary:"
tail -10 "$REPORT_FILE"
}
case "$1" in
nginx)
monitor_nginx
;;
apache)
monitor_apache
;;
response)
test_response_times
;;
ssl)
check_ssl_performance
;;
report)
generate_performance_report
;;
all)
monitor_nginx
echo ""
monitor_apache
echo ""
test_response_times
echo ""
check_ssl_performance
;;
*)
echo "Usage: $0 {nginx|apache|response|ssl|report|all}"
echo " nginx - Monitor Nginx performance"
echo " apache - Monitor Apache performance"
echo " response - Test response times"
echo " ssl - Check SSL performance"
echo " report - Generate performance report"
echo " all - Run all performance checks"
;;
esac
# Make the script executable
sudo chmod +x /usr/local/bin/web-performance.sh
# Test performance monitoring
sudo /usr/local/bin/web-performance.sh all
๐ฎ Quick Examples
Letโs see your web servers in action with real-world scenarios! ๐ฏ
Example 1: High-Traffic Website Setup
# Create high-performance website configuration
sudo nano /etc/nginx/sites-available/high-traffic.com
server {
listen 443 ssl http2;
server_name high-traffic.com www.high-traffic.com;
root /var/www/high-traffic.com;
index index.html index.php;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/high-traffic.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/high-traffic.com/privkey.pem;
# Performance optimizations
sendfile on;
tcp_nopush on;
tcp_nodelay on;
# Rate limiting
limit_req zone=api burst=20 nodelay;
# Static content with aggressive caching
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
add_header X-Content-Type-Options nosniff;
gzip_static on;
}
# API with moderate caching
location /api/ {
proxy_pass http://api_backend;
proxy_cache proxy_cache;
proxy_cache_valid 200 5m;
add_header X-Cache-Status $upstream_cache_status;
}
# Security headers
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
add_header X-Frame-Options DENY always;
add_header X-Content-Type-Options nosniff always;
}
# Enable the site
sudo /usr/local/bin/nginx-manager.sh enable high-traffic.com
Example 2: WordPress with Apache
# Install PHP and MySQL for WordPress
sudo dnf install -y php php-mysqlnd php-fpm php-opcache php-gd php-xml php-mbstring
# Create WordPress Apache virtual host
sudo nano /etc/httpd/sites-available/wordpress.conf
<VirtualHost *:443>
ServerName blog.example.com
DocumentRoot /var/www/blog.example.com
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/blog.example.com/cert.pem
SSLCertificateKeyFile /etc/letsencrypt/live/blog.example.com/privkey.pem
SSLCertificateChainFile /etc/letsencrypt/live/blog.example.com/chain.pem
# PHP configuration
<FilesMatch \.php$>
SetHandler "proxy:unix:/run/php-fpm/www.sock|fcgi://localhost"
</FilesMatch>
# WordPress optimizations
<Directory "/var/www/blog.example.com">
AllowOverride All
Require all granted
# Security
<Files wp-config.php>
Require all denied
</Files>
# Performance
ExpiresActive On
ExpiresByType image/jpg "access plus 1 month"
ExpiresByType image/jpeg "access plus 1 month"
ExpiresByType image/gif "access plus 1 month"
ExpiresByType image/png "access plus 1 month"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/pdf "access plus 1 month"
ExpiresByType text/javascript "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</Directory>
# Logging
ErrorLog /var/log/httpd/blog.example.com_error.log
CustomLog /var/log/httpd/blog.example.com_access.log combined
</VirtualHost>
# Enable the site
sudo /usr/local/bin/apache-manager.sh enable wordpress.conf
Example 3: API Gateway Configuration
# Create API gateway with rate limiting and authentication
sudo nano /etc/nginx/sites-available/api-gateway.com
upstream auth_service {
server 127.0.0.1:3001;
}
upstream user_service {
server 127.0.0.1:3002;
}
upstream payment_service {
server 127.0.0.1:3003;
}
server {
listen 443 ssl http2;
server_name api.example.com;
# SSL configuration
ssl_certificate /etc/letsencrypt/live/api.example.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/api.example.com/privkey.pem;
# Rate limiting zones
limit_req_zone $binary_remote_addr zone=auth:10m rate=5r/s;
limit_req_zone $binary_remote_addr zone=api:10m rate=10r/s;
limit_req_zone $binary_remote_addr zone=payment:10m rate=2r/s;
# Authentication service
location /auth/ {
limit_req zone=auth burst=10 nodelay;
proxy_pass http://auth_service/;
include proxy_params;
}
# User service (requires authentication)
location /users/ {
limit_req zone=api burst=20 nodelay;
# Authentication check
auth_request /auth/verify;
auth_request_set $user_id $upstream_http_x_user_id;
proxy_pass http://user_service/;
proxy_set_header X-User-ID $user_id;
include proxy_params;
}
# Payment service (strict rate limiting)
location /payments/ {
limit_req zone=payment burst=5 nodelay;
# Authentication check
auth_request /auth/verify;
auth_request_set $user_id $upstream_http_x_user_id;
proxy_pass http://payment_service/;
proxy_set_header X-User-ID $user_id;
include proxy_params;
}
# Health check
location /health {
access_log off;
return 200 "API Gateway OK\n";
add_header Content-Type text/plain;
}
}
# Enable the API gateway
sudo /usr/local/bin/nginx-manager.sh enable api-gateway.com
๐จ Fix Common Problems
Donโt worry when web server issues arise โ here are solutions to common problems! ๐ ๏ธ
Problem 1: 502 Bad Gateway Errors
Symptoms: Nginx returns 502 errors, upstream connection failures
# Check upstream server status
curl -I http://backend-server:8080
# Check Nginx error logs
sudo tail -f /var/log/nginx/error.log
# Common fixes:
# 1. Increase proxy timeouts
proxy_connect_timeout 60s;
proxy_send_timeout 60s;
proxy_read_timeout 60s;
# 2. Check upstream server health
sudo /usr/local/bin/lb-monitor.sh health
# 3. Restart backend services
sudo systemctl restart php-fpm
sudo systemctl restart nodejs-app
Problem 2: SSL Certificate Issues
Symptoms: SSL errors, certificate warnings, HTTPS not working
# Check certificate status
sudo /usr/local/bin/ssl-manager.sh list
# Test SSL configuration
openssl s_client -connect example.com:443 -servername example.com
# Common fixes:
# 1. Renew expired certificates
sudo certbot renew
# 2. Fix certificate permissions
sudo chmod 644 /etc/letsencrypt/live/*/fullchain.pem
sudo chmod 600 /etc/letsencrypt/live/*/privkey.pem
# 3. Reload web server after certificate renewal
sudo systemctl reload nginx
sudo systemctl reload httpd
Problem 3: High Memory Usage
Symptoms: Web server consuming too much memory, slow responses
# Check memory usage
ps aux --sort=-%mem | head -10
# For Apache - tune MPM settings
sudo nano /etc/httpd/conf.d/performance.conf
# Reduce MaxRequestWorkers, StartServers
# For Nginx - check worker processes
sudo nano /etc/nginx/nginx.conf
# Adjust worker_processes and worker_connections
# Monitor memory usage
sudo /usr/local/bin/web-performance.sh all
Problem 4: Slow Page Load Times
Symptoms: Website loading slowly, poor performance metrics
# Test response times
sudo /usr/local/bin/web-performance.sh response
# Enable compression
# For Nginx: gzip on;
# For Apache: LoadModule deflate_module
# Optimize caching
# Check cache hit rates
curl -I http://localhost/test.css | grep X-Cache-Status
# Enable static file caching
expires 1y;
add_header Cache-Control "public, immutable";
# Optimize images and static assets
# Use WebP format, minify CSS/JS
๐ Simple Commands Summary
Hereโs your web server management quick reference guide! ๐
Task | Command | Purpose |
---|---|---|
Nginx Status | sudo systemctl status nginx | Check Nginx service status |
Apache Status | sudo systemctl status httpd | Check Apache service status |
Test Config | sudo nginx -t or sudo httpd -t | Test configuration syntax |
Reload Config | sudo systemctl reload nginx/httpd | Reload configuration |
View Logs | sudo tail -f /var/log/nginx/error.log | Monitor error logs |
SSL Certificate | sudo certbot certificates | List SSL certificates |
Renew SSL | sudo certbot renew | Renew SSL certificates |
Enable Site | sudo /usr/local/bin/nginx-manager.sh enable site | Enable virtual host |
Check Performance | sudo /usr/local/bin/web-performance.sh all | Monitor performance |
Load Balancer | sudo /usr/local/bin/lb-monitor.sh health | Check load balancer |
SSL Manager | sudo /usr/local/bin/ssl-manager.sh list | Manage SSL certificates |
Firewall | sudo firewall-cmd --list-services | Check firewall rules |
๐ก Tips for Success
Follow these expert strategies to master web server administration! ๐
๐ฏ Performance Optimization
- Enable compression โ Gzip/Brotli compression reduces bandwidth usage by 70%+
- Implement caching โ Static file caching and proxy caching dramatically improve speed
- Optimize SSL โ Use HTTP/2, OCSP stapling, and session resumption
- Monitor continuously โ Set up automated performance monitoring and alerting
๐ง Security Best Practices
- Always use HTTPS โ SSL/TLS encryption is mandatory for modern websites
- Implement security headers โ HSTS, CSP, X-Frame-Options protect against attacks
- Regular updates โ Keep web servers and modules updated for security patches
- Access control โ Use proper authentication and authorization mechanisms
๐ก๏ธ High Availability Strategies
- Load balancing โ Distribute traffic across multiple servers for redundancy
- Health monitoring โ Implement automated health checks and failover
- Backup procedures โ Regular backups of configurations and content
- Disaster recovery โ Plan and test recovery procedures regularly
๐ Advanced Techniques
- CDN integration โ Use content delivery networks for global performance
- Database optimization โ Optimize backend databases for web workloads
- Containerization โ Consider Docker/Kubernetes for scalable deployments
- Monitoring and analytics โ Implement comprehensive logging and metrics
๐ What You Learned
Congratulations! Youโve mastered web server configuration on AlmaLinux! ๐ Hereโs your incredible achievement:
โ Configured both Nginx and Apache with production-ready optimizations โ Implemented SSL/TLS encryption with Letโs Encrypt automation โ Set up virtual hosts for multiple websites and applications โ Built load balancing solutions for high availability and scalability โ Optimized performance with caching, compression, and tuning โ Created management scripts for efficient server administration โ Configured security measures with headers, rate limiting, and access controls โ Implemented monitoring systems for proactive server management โ Mastered troubleshooting techniques for common web server issues โ Built enterprise-grade infrastructure capable of handling massive traffic
๐ฏ Why This Matters
Web server expertise is the foundation of the modern internet! ๐
Every website, API, and web application depends on properly configured web servers. From small business websites to global platforms serving millions of users, the principles youโve learned here scale to any size deployment.
These skills open doors to high-paying roles like DevOps Engineer, Site Reliability Engineer, Cloud Architect, and Full-Stack Developer. Companies desperately need web server experts who can build fast, secure, and scalable web infrastructure.
Remember, you havenโt just learned to configure web servers โ youโve mastered the art of creating digital experiences that users love. Your ability to build lightning-fast, secure web infrastructure puts you at the heart of the digital economy.
Keep optimizing, keep securing, and keep pushing the boundaries of web performance! Your expertise powers the websites and applications that millions of people use every day! ๐โก๐