Prerequisites & VPS Selection
💡 Tip: Apache uses ~50-100MB per idle process. For WordPress or PHP apps, consider at least 2GB RAM for comfortable operation.
Install Apache
Update your system and install Apache:
# Update system packages
sudo apt update && sudo apt upgrade -y
# Install Apache
sudo apt install apache2 -y
# Start and enable Apache
sudo systemctl start apache2
sudo systemctl enable apache2
# Verify installation
sudo systemctl status apache2
# Check Apache version
apache2 -vFor RHEL/AlmaLinux/Rocky Linux:
# Install Apache (httpd)
sudo dnf install httpd -y
# Start and enable
sudo systemctl start httpd
sudo systemctl enable httpd
# Check status
sudo systemctl status httpd✅ Success! Apache is now running. Visit http://YOUR_SERVER_IP to see the default page.
Configure Firewall
# Check available Apache profiles
sudo ufw app list
# Allow Apache through firewall (HTTP only)
sudo ufw allow 'Apache'
# Or allow both HTTP and HTTPS
sudo ufw allow 'Apache Full'
# Enable firewall if not already enabled
sudo ufw enable
# Check status
sudo ufw statusFor firewalld (RHEL-based):
# Allow HTTP and HTTPS
sudo firewall-cmd --permanent --add-service=http
sudo firewall-cmd --permanent --add-service=https
sudo firewall-cmd --reload
# Verify
sudo firewall-cmd --list-allConfigure Virtual Hosts
Virtual hosts allow you to host multiple websites on a single server:
# Create directory for your site
sudo mkdir -p /var/www/example.com/html
# Set ownership
sudo chown -R $USER:$USER /var/www/example.com/html
# Set permissions
sudo chmod -R 755 /var/www/example.com
# Create a sample index page
nano /var/www/example.com/html/index.html<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Welcome to example.com</title>
</head>
<body>
<h1>Success! example.com is working!</h1>
</body>
</html>sudo nano /etc/apache2/sites-available/example.com.conf<VirtualHost *:80>
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
<Directory /var/www/example.com/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
</VirtualHost># Enable the virtual host
sudo a2ensite example.com.conf
# Disable default site (optional)
sudo a2dissite 000-default.conf
# Test configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2SSL Certificates with Let's Encrypt
# Install Certbot
sudo apt install certbot python3-certbot-apache -y
# Obtain SSL certificate (auto-configures Apache)
sudo certbot --apache -d example.com -d www.example.com
# Verify auto-renewal
sudo certbot renew --dry-runCertbot will automatically create an SSL virtual host. Here's what it generates:
<VirtualHost *:443>
ServerAdmin webmaster@example.com
ServerName example.com
ServerAlias www.example.com
DocumentRoot /var/www/example.com/html
<Directory /var/www/example.com/html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-access.log combined
SSLEngine on
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
Include /etc/letsencrypt/options-ssl-apache.conf
</VirtualHost>PHP Integration
# Install PHP and common extensions
sudo apt install php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-zip php-intl php-bcmath -y
# Verify PHP installation
php -v
# Check loaded modules
php -m
# Restart Apache
sudo systemctl restart apache2Create a PHP info page to verify:
echo "<?php phpinfo(); ?>" | sudo tee /var/www/example.com/html/info.php⚠️ Security: Delete info.php after testing: sudo rm /var/www/example.com/html/info.php
Configure PHP Settings
sudo nano /etc/php/8.1/apache2/php.ini; Increase upload limits
upload_max_filesize = 64M
post_max_size = 64M
; Increase memory limit
memory_limit = 256M
; Increase execution time
max_execution_time = 300
; Set timezone
date.timezone = UTC
; Disable expose_php for security
expose_php = Offsudo systemctl restart apache2Enable Apache Modules
Apache's functionality can be extended with modules:
# Enable URL rewriting (required for WordPress, Laravel, etc.)
sudo a2enmod rewrite
# Enable SSL module
sudo a2enmod ssl
# Enable headers module (for security headers)
sudo a2enmod headers
# Enable deflate for compression
sudo a2enmod deflate
# Enable expires for caching
sudo a2enmod expires
# Enable proxy modules (for reverse proxy)
sudo a2enmod proxy proxy_http proxy_balancer lbmethod_byrequests
# Restart Apache to apply
sudo systemctl restart apache2
# List all enabled modules
apache2ctl -MSecurity Hardening
sudo nano /etc/apache2/conf-available/security-hardening.conf# Hide Apache version and OS
ServerTokens Prod
ServerSignature Off
# Disable directory listing
<Directory /var/www/>
Options -Indexes
</Directory>
# Security headers
<IfModule mod_headers.c>
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"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
</IfModule>
# Disable TRACE method
TraceEnable Off
# Prevent clickjacking
Header set Content-Security-Policy "frame-ancestors 'self'"
# Disable ETag (fingerprinting)
FileETag None# Enable the security config
sudo a2enconf security-hardening
# Test and reload
sudo apache2ctl configtest
sudo systemctl reload apache2Secure the Default Apache Config
sudo nano /etc/apache2/apache2.conf# Timeout for slow connections
Timeout 60
# Limit request size (10MB)
LimitRequestBody 10485760
# Disable access to .htaccess and .git directories
<FilesMatch "^.ht">
Require all denied
</FilesMatch>
<DirectoryMatch "/.git">
Require all denied
</DirectoryMatch>Performance Tuning
MPM Configuration
Configure the Multi-Processing Module for your server's resources:
sudo nano /etc/apache2/mods-available/mpm_prefork.conf<IfModule mpm_prefork_module>
StartServers 5
MinSpareServers 5
MaxSpareServers 10
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>Enable Compression
sudo nano /etc/apache2/conf-available/compression.conf<IfModule mod_deflate.c>
# Compress HTML, CSS, JavaScript, Text, XML and fonts
AddOutputFilterByType DEFLATE application/javascript
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/vnd.ms-fontobject
AddOutputFilterByType DEFLATE application/x-font
AddOutputFilterByType DEFLATE application/x-font-opentype
AddOutputFilterByType DEFLATE application/x-font-otf
AddOutputFilterByType DEFLATE application/x-font-truetype
AddOutputFilterByType DEFLATE application/x-font-ttf
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE font/opentype
AddOutputFilterByType DEFLATE font/otf
AddOutputFilterByType DEFLATE font/ttf
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE image/x-icon
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/javascript
AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
</IfModule>Browser Caching
sudo nano /etc/apache2/conf-available/caching.conf<IfModule mod_expires.c>
ExpiresActive On
# Images
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType image/webp "access plus 1 year"
ExpiresByType image/svg+xml "access plus 1 year"
ExpiresByType image/x-icon "access plus 1 year"
# CSS/JS
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
# Fonts
ExpiresByType font/ttf "access plus 1 year"
ExpiresByType font/otf "access plus 1 year"
ExpiresByType font/woff "access plus 1 year"
ExpiresByType font/woff2 "access plus 1 year"
# HTML
ExpiresByType text/html "access plus 0 seconds"
</IfModule>sudo a2enconf compression caching
sudo systemctl reload apache2Logging Configuration
# View error log
sudo tail -f /var/log/apache2/error.log
# View access log
sudo tail -f /var/log/apache2/access.log
# View specific site logs
sudo tail -f /var/log/apache2/example.com-error.logLog Rotation
cat /etc/logrotate.d/apache2/var/log/apache2/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
if invoke-rc.d apache2 status > /dev/null 2>&1; then
invoke-rc.d apache2 reload > /dev/null 2>&1
fi
endscript
}Reverse Proxy Configuration
Use Apache as a reverse proxy for Node.js, Python, or other backend apps:
sudo a2enmod proxy proxy_http proxy_wstunnel<VirtualHost *:80>
ServerName app.example.com
ProxyPreserveHost On
ProxyRequests Off
# Proxy to Node.js app running on port 3000
ProxyPass / http://127.0.0.1:3000/
ProxyPassReverse / http://127.0.0.1:3000/
# WebSocket support
RewriteEngine On
RewriteCond %{HTTP:Upgrade} websocket [NC]
RewriteCond %{HTTP:Connection} upgrade [NC]
RewriteRule ^/?(.*) ws://127.0.0.1:3000/$1 [P,L]
ErrorLog ${APACHE_LOG_DIR}/app-error.log
CustomLog ${APACHE_LOG_DIR}/app-access.log combined
</VirtualHost>sudo a2enmod rewrite
sudo a2ensite app.example.com.conf
sudo apache2ctl configtest
sudo systemctl reload apache2Troubleshooting
Apache won't start
# Check syntax errors
sudo apache2ctl configtest
# Check detailed status
sudo systemctl status apache2 -l
# View full error log
sudo journalctl -u apache2 --no-pager
# Check for port conflicts
sudo netstat -tlnp | grep :80
sudo lsof -i :80Permission Denied Errors
# Fix ownership
sudo chown -R www-data:www-data /var/www/example.com
# Fix directory permissions
sudo find /var/www/example.com -type d -exec chmod 755 {} \;
# Fix file permissions
sudo find /var/www/example.com -type f -exec chmod 644 {} \;.htaccess Not Working
# Ensure AllowOverride is set to All in your virtual host
# Check your site config:
sudo nano /etc/apache2/sites-available/example.com.conf
# Make sure this is set:
# <Directory /var/www/example.com/html>
# AllowOverride All
# </Directory>
# Enable mod_rewrite
sudo a2enmod rewrite
sudo systemctl restart apache2Useful Commands
# Test configuration
sudo apache2ctl configtest
# Graceful restart (no downtime)
sudo apache2ctl graceful
# Full restart
sudo systemctl restart apache2
# List enabled sites
ls -la /etc/apache2/sites-enabled/
# List enabled modules
apache2ctl -M
# Check Apache status
sudo apache2ctl statusCongratulations!
You've successfully deployed Apache web server on your RamNode VPS. Your sites are now ready to serve traffic.
Security Checklist
- ✅ Hide server version - Set ServerTokens Prod and ServerSignature Off
- ✅ Enable HTTPS - Use Let's Encrypt for free SSL certificates
- ✅ Disable directory listing - Options -Indexes in all directories
- ✅ Keep Apache updated - Regular
apt update && apt upgrade - ✅ Configure firewall - Only allow necessary ports (80, 443)
- ✅ Secure .htaccess - Deny access to sensitive files
