Apache Web Server on Ubuntu
Trademark Notice
Apache® and the Apache HTTP Server are trademarks of The Apache Software Foundation. All trademarks are used for representation purposes only. This content is for educational purposes only.
Complete guide to installing and configuring Apache HTTP Server on Ubuntu.
Installation
# Update package list
sudo apt update
# Install Apache
sudo apt install -y apache2
# Start and enable Apache
sudo systemctl start apache2
sudo systemctl enable apache2
# Check status
sudo systemctl status apache2
# Verify installation
apache2 -v
Firewall Configuration
# Allow Apache through firewall
sudo ufw allow 'Apache Full'
# Or allow specific ports
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
# Check firewall status
sudo ufw status
Basic Configuration
Main Configuration File
# Edit main config
sudo nano /etc/apache2/apache2.conf
Key configurations:
# Server root
ServerRoot "/etc/apache2"
# Timeout
Timeout 60
# KeepAlive
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5
# Security
ServerTokens Prod
ServerSignature Off
# Directory permissions
<Directory />
Options FollowSymLinks
AllowOverride None
Require all denied
</Directory>
<Directory /var/www/>
Options Indexes FollowSymLinks
AllowOverride All
Require all granted
</Directory>
Default Ports
# Edit ports configuration
sudo nano /etc/apache2/ports.conf
Listen 80
<IfModule ssl_module>
Listen 443
</IfModule>
<IfModule mod_gnutls.c>
Listen 443
</IfModule>
Virtual Hosts
Create Virtual Host
# Create document root
sudo mkdir -p /var/www/example.com/public_html
# Set permissions
sudo chown -R $USER:$USER /var/www/example.com/public_html
sudo chmod -R 755 /var/www
# Create sample page
echo "<h1>Welcome to example.com</h1>" | sudo tee /var/www/example.com/public_html/index.html
Virtual Host Configuration
# Create virtual host file
sudo nano /etc/apache2/sites-available/example.com.conf
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
ServerAdmin admin@example.com
DocumentRoot /var/www/example.com/public_html
<Directory /var/www/example.com/public_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 virtual host
sudo a2ensite example.com.conf
# Disable default site
sudo a2dissite 000-default.conf
# Test configuration
sudo apache2ctl configtest
# Reload Apache
sudo systemctl reload apache2
SSL/TLS Configuration
Install Certbot (Let's Encrypt)
# Install Certbot
sudo apt install -y certbot python3-certbot-apache
# Obtain certificate
sudo certbot --apache -d example.com -d www.example.com
# Certificate auto-renewal
sudo systemctl status certbot.timer
# Test renewal
sudo certbot renew --dry-run
Manual SSL Configuration
# /etc/apache2/sites-available/example.com-ssl.conf
<VirtualHost *:443>
ServerName example.com
ServerAlias www.example.com
ServerAdmin admin@example.com
DocumentRoot /var/www/example.com/public_html
SSLEngine on
SSLCertificateFile /etc/ssl/certs/example.com.crt
SSLCertificateKeyFile /etc/ssl/private/example.com.key
SSLCertificateChainFile /etc/ssl/certs/ca-bundle.crt
# Modern SSL configuration
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
<Directory /var/www/example.com/public_html>
Options -Indexes +FollowSymLinks
AllowOverride All
Require all granted
</Directory>
ErrorLog ${APACHE_LOG_DIR}/example.com-ssl-error.log
CustomLog ${APACHE_LOG_DIR}/example.com-ssl-access.log combined
</VirtualHost>
Force HTTPS Redirect
# Add to port 80 VirtualHost
<VirtualHost *:80>
ServerName example.com
ServerAlias www.example.com
Redirect permanent / https://example.com/
</VirtualHost>
Enable/Disable Modules
# List available modules
apache2ctl -M
# Enable modules
sudo a2enmod rewrite
sudo a2enmod ssl
sudo a2enmod headers
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod expires
sudo a2enmod deflate
# Disable modules
sudo a2dismod autoindex
sudo a2dismod status
# Reload Apache
sudo systemctl reload apache2
.htaccess Configuration
# Enable .htaccess
sudo nano /etc/apache2/sites-available/example.com.conf
<Directory /var/www/example.com/public_html>
AllowOverride All
</Directory>
Common .htaccess Rules
# /var/www/example.com/public_html/.htaccess
# URL Rewriting
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
# Redirect www to non-www
RewriteCond %{HTTP_HOST} ^www\.example\.com [NC]
RewriteRule ^(.*)$ https://example.com/$1 [L,R=301]
# Force HTTPS
RewriteCond %{HTTPS} off
RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
# Remove .php extension
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME}\.php -f
RewriteRule ^(.*)$ $1.php [L]
</IfModule>
# Security Headers
<IfModule mod_headers.c>
Header set X-XSS-Protection "1; mode=block"
Header set X-Content-Type-Options "nosniff"
Header set X-Frame-Options "SAMEORIGIN"
Header set Referrer-Policy "strict-origin-when-cross-origin"
</IfModule>
# Gzip Compression
<IfModule mod_deflate.c>
AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
</IfModule>
# Browser Caching
<IfModule mod_expires.c>
ExpiresActive On
ExpiresByType image/jpg "access plus 1 year"
ExpiresByType image/jpeg "access plus 1 year"
ExpiresByType image/gif "access plus 1 year"
ExpiresByType image/png "access plus 1 year"
ExpiresByType text/css "access plus 1 month"
ExpiresByType application/javascript "access plus 1 month"
</IfModule>
# Directory Protection
<Files .htaccess>
Require all denied
</Files>
# Disable directory browsing
Options -Indexes
Reverse Proxy Configuration
# Enable proxy modules
sudo a2enmod proxy
sudo a2enmod proxy_http
sudo a2enmod proxy_balancer
sudo a2enmod lbmethod_byrequests
# /etc/apache2/sites-available/proxy.conf
<VirtualHost *:80>
ServerName api.example.com
ProxyPreserveHost On
ProxyPass / http://localhost:3000/
ProxyPassReverse / http://localhost:3000/
ErrorLog ${APACHE_LOG_DIR}/proxy-error.log
CustomLog ${APACHE_LOG_DIR}/proxy-access.log combined
</VirtualHost>
Load Balancing
<VirtualHost *:80>
ServerName lb.example.com
<Proxy balancer://mycluster>
BalancerMember http://192.168.1.101:8080
BalancerMember http://192.168.1.102:8080
BalancerMember http://192.168.1.103:8080
ProxySet lbmethod=byrequests
</Proxy>
ProxyPreserveHost On
ProxyPass / balancer://mycluster/
ProxyPassReverse / balancer://mycluster/
</VirtualHost>
Performance Tuning
MPM Configuration
# Check current MPM
apache2ctl -V | grep MPM
# Disable current MPM
sudo a2dismod mpm_prefork
# Enable Event MPM (best performance)
sudo a2enmod mpm_event
# Configure MPM
sudo nano /etc/apache2/mods-available/mpm_event.conf
<IfModule mpm_event_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 25
MaxRequestWorkers 150
MaxConnectionsPerChild 0
</IfModule>
Enable Caching
# Enable cache modules
sudo a2enmod cache
sudo a2enmod cache_disk
sudo a2enmod expires
sudo a2enmod headers
# /etc/apache2/mods-available/cache_disk.conf
<IfModule mod_cache_disk.c>
CacheRoot /var/cache/apache2/mod_cache_disk
CacheEnable disk /
CacheDirLevels 2
CacheDirLength 1
CacheMaxFileSize 1000000
</IfModule>
Security Hardening
Security Modules
# Install ModSecurity
sudo apt install -y libapache2-mod-security2
# Enable module
sudo a2enmod security2
# Configure
sudo cp /etc/modsecurity/modsecurity.conf-recommended /etc/modsecurity/modsecurity.conf
sudo nano /etc/modsecurity/modsecurity.conf
# Enable ModSecurity
SecRuleEngine On
Hide Apache Version
# Edit security config
sudo nano /etc/apache2/conf-available/security.conf
ServerTokens Prod
ServerSignature Off
TraceEnable Off
Limit Request Size
# Limit upload size
LimitRequestBody 10485760 # 10MB
IP Access Control
<Directory /var/www/example.com/admin>
Require ip 192.168.1.0/24
Require ip 10.0.0.0/8
</Directory>
Logging
Custom Log Format
# Edit Apache config
sudo nano /etc/apache2/apache2.conf
LogFormat "%h %l %u %t \"%r\" %>s %O \"%{Referer}i\" \"%{User-Agent}i\" %D" custom
CustomLog ${APACHE_LOG_DIR}/access.log custom
Log Rotation
# View log rotation config
cat /etc/logrotate.d/apache2
/var/log/apache2/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 640 root adm
sharedscripts
postrotate
if /etc/init.d/apache2 status > /dev/null ; then \
/etc/init.d/apache2 reload > /dev/null; \
fi;
endscript
}
Monitoring & Troubleshooting
# Check Apache status
sudo systemctl status apache2
# Test configuration
sudo apache2ctl configtest
# View error logs
sudo tail -f /var/log/apache2/error.log
# View access logs
sudo tail -f /var/log/apache2/access.log
# Check active connections
sudo apache2ctl status
# Check loaded modules
apache2ctl -M
# Check virtual hosts
apache2ctl -S
# Monitor in real-time
sudo tail -f /var/log/apache2/access.log | grep "200"
PHP Integration
# Install PHP
sudo apt install -y php libapache2-mod-php php-mysql php-curl php-gd php-mbstring php-xml php-xmlrpc
# Configure PHP
sudo nano /etc/php/8.1/apache2/php.ini
upload_max_filesize = 64M
post_max_size = 64M
memory_limit = 256M
max_execution_time = 300
date.timezone = America/New_York
# Restart Apache
sudo systemctl restart apache2
# Test PHP
echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php
Backup Configuration
# Backup Apache configuration
sudo tar -czf apache-backup-$(date +%Y%m%d).tar.gz \
/etc/apache2/ \
/var/www/
# Backup to remote server
sudo rsync -avz /etc/apache2/ user@backup-server:/backup/apache2/
Best Practices
- Use Virtual Hosts: Separate configuration per site
- Enable SSL/TLS: Use Let's Encrypt for free certificates
- Security Headers: Implement security headers via .htaccess
- Log Monitoring: Regularly review access and error logs
- Performance: Enable caching and compression
- Updates: Keep Apache and modules updated
- Firewall: Restrict access to necessary ports only
- Backup: Regular backups of configuration and content
- Testing: Always test configuration before reloading
- Documentation: Document custom configurations
Resources
- Official Documentation: https://httpd.apache.org/docs/
- Ubuntu Apache Guide: https://ubuntu.com/server/docs/web-servers-apache
- Security: https://httpd.apache.org/docs/2.4/misc/security_tips.html
- ModSecurity: https://github.com/SpiderLabs/ModSecurity