Why Server Optimization Matters More Than Hardware Upgrades
Before spending money on additional CPU cores or RAM, there is almost always significant performance headroom achievable through software tuning. A misconfigured Linux server running on $20/month hardware often underperforms a properly tuned server running on $5/month hardware. This guide covers the systematic performance and security hardening of a Linux web hosting server — from kernel parameters to application-level caching, combined with the security layers necessary to defend production infrastructure.
OS-Level Tuning: sysctl and ulimits
Kernel parameters control how the OS handles network connections, memory, and file descriptors. Add these to /etc/sysctl.d/99-performance.conf:
# Network optimization
net.core.somaxconn = 65535
net.ipv4.tcp_max_syn_backlog = 65535
net.ipv4.tcp_fin_timeout = 15
net.ipv4.tcp_keepalive_time = 300
net.ipv4.tcp_keepalive_probes = 5
net.ipv4.tcp_keepalive_intvl = 15
net.core.netdev_max_backlog = 65535
# Memory management
vm.swappiness = 10
vm.dirty_ratio = 15
vm.dirty_background_ratio = 5
# File descriptors
fs.file-max = 2097152Apply with sysctl -p /etc/sysctl.d/99-performance.conf. For process-level file descriptor limits, add to /etc/security/limits.conf:
* soft nofile 65535
* hard nofile 65535
nginx soft nofile 65535
nginx hard nofile 65535
mysql soft nofile 65535Nginx Optimization
Nginx performs well with defaults but several tweaks significantly improve throughput under load:
worker_processes auto;
worker_rlimit_nofile 65535;
events {
worker_connections 4096;
use epoll;
multi_accept on;
}
http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 1000;
# Gzip compression
gzip on;
gzip_comp_level 5;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml image/svg+xml;
# Open file cache
open_file_cache max=10000 inactive=30s;
open_file_cache_valid 60s;
open_file_cache_min_uses 2;
# Client body and buffer sizes
client_body_buffer_size 16k;
client_max_body_size 50m;
client_header_buffer_size 1k;
}MySQL/MariaDB Query Optimization
Database performance is typically the primary bottleneck on web hosting servers. Key configuration changes in /etc/mysql/conf.d/performance.cnf:
[mysqld]
innodb_buffer_pool_size = 1G # 50-70% of available RAM
innodb_buffer_pool_instances = 4
innodb_log_file_size = 256M
innodb_flush_log_at_trx_commit = 2 # Trade durability for speed (acceptable for hosting)
innodb_flush_method = O_DIRECT
query_cache_type = 0 # Disable query cache — it causes contention
query_cache_size = 0
max_connections = 300
thread_cache_size = 50
table_open_cache = 4096Enable the slow query log to identify problematic queries: slow_query_log = 1, long_query_time = 1. Review weekly with pt-query-digest from Percona Toolkit.
Redis Caching Layer
Redis dramatically reduces database load for WordPress sites and custom applications. Install Redis and configure PHP sessions to use it, reducing file I/O for session storage. For WordPress, install the Redis Object Cache plugin and configure wp-config.php:
define('WP_REDIS_HOST', '127.0.0.1');
define('WP_REDIS_PORT', 6379);
define('WP_REDIS_DATABASE', 0);
define('WP_CACHE', true);Redis object caching can reduce WordPress database queries by 60–80%, transforming response times on content-heavy sites. Configure Redis memory limits appropriately — 256MB is sufficient for most shared hosting servers.
Fail2ban Configuration
Fail2ban monitors log files and blocks IP addresses that show malicious patterns. Install and configure jails for SSH, nginx authentication failures, WordPress login attempts, and cPanel brute force:
[sshd]
enabled = true
port = ssh
logpath = /var/log/auth.log
maxretry = 3
bantime = 3600
findtime = 600
[nginx-http-auth]
enabled = true
logpath = /var/log/nginx/error.log
maxretry = 5
[wordpress]
enabled = true
logpath = /var/log/nginx/access.log
filter = wordpress
maxretry = 5
bantime = 86400ModSecurity Web Application Firewall
ModSecurity with the OWASP Core Rule Set provides application-layer protection against SQL injection, XSS, and common web exploits. Install via EasyApache 4 on cPanel servers or manually on standalone nginx/Apache setups. Start in Detection Only mode to review false positives before switching to blocking mode. Add exceptions for legitimate applications that trigger rules (WooCommerce checkout, WordPress REST API) in a custom rules file rather than disabling rules globally.
Automated Backups with rsync
#!/bin/bash
# Daily backup script
BACKUP_DIR=/backup/$(date +%Y-%m-%d)
mkdir -p $BACKUP_DIR
rsync -az --delete /var/www/ $BACKUP_DIR/www/
mysqldump --all-databases | gzip > $BACKUP_DIR/databases.sql.gz
# Upload to S3
aws s3 sync $BACKUP_DIR s3://my-backup-bucket/$(date +%Y-%m-%d)/
# Remove backups older than 30 days
find /backup -type d -mtime +30 -exec rm -rf {} +Monitoring with Netdata and Prometheus
Install Netdata for real-time monitoring with zero configuration: bash <(curl -Ss https://my-netdata.io/kickstart.sh). Netdata auto-discovers nginx, MySQL, Redis, and system metrics immediately. For long-term metrics retention and alerting, pair with Prometheus and Grafana. Set up alert rules for disk usage above 80%, memory above 90%, and average response time above 500ms.
SSL/TLS Hardening
Disable outdated protocol versions and weak cipher suites in nginx:
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 1d;
ssl_session_tickets off;
ssl_stapling on;
ssl_stapling_verify on;
add_header Strict-Transport-Security "max-age=63072000" always;Verify your configuration with SSL Labs — aim for an A+ rating. This combination of kernel tuning, application optimization, security hardening, and monitoring creates a server that performs well and resists attack without requiring expensive hardware upgrades.