Goal: a single, sane vhost. TLS 1.2/1.3, basic security headers, OCSP stapling, HSTS (opt-in), tight logs, and no server leaks.
1) Modules & hardening
sudo a2enmod ssl headers rewrite socache_shmcb
# Hide version
echo "ServerTokens Prod\nServerSignature Off" | sudo tee /etc/apache2/conf-available/hideversion.conf
sudo a2enconf hideversion
2) Vhost
<VirtualHost *:443>
ServerName example.com
DocumentRoot /var/www/html
SSLEngine on
SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1
SSLCipherSuite HIGH:!aNULL:!MD5
SSLHonorCipherOrder on
# If using Let's Encrypt:
SSLCertificateFile /etc/letsencrypt/live/example.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/example.com/privkey.pem
SSLUseStapling on
SSLStaplingCache "shmcb:/var/run/ocsp(128000)"
# Security headers
Header always set X-Content-Type-Options "nosniff"
Header always set X-Frame-Options "SAMEORIGIN"
Header always set Referrer-Policy "strict-origin-when-cross-origin"
Header always set Permissions-Policy "geolocation=(), microphone=(), camera=()"
# CSP is site-specific: add after testing.
# HSTS (enable only after confirming HTTPS works everywhere)
# Header always set Strict-Transport-Security "max-age=15552000; includeSubDomains; preload"
# Logs
LogFormat "%h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" vhost_combined
CustomLog ${APACHE_LOG_DIR}/example_access.log vhost_combined
ErrorLog ${APACHE_LOG_DIR}/example_error.log
</VirtualHost>
3) Reload
sudo apache2ctl -t && sudo systemctl reload apache2