Apache virtual hosts
Fri, Aug 26, 2016 · 5 minute readwebhow to
Didn’t exactly pick this all up today, rather this is my refined experience from setting up numerous virtual hosts (vhost) on numerous servers.
What follows requires at least Apache 2.4.
Useful Apache documentation:
Documentation index for current Apache version
Environment variables
Define variable in configuration file
VirtualHost directive \
A few words on what the configuration below is trying to achieve.
A vhost configuration that can becopied from one serrver (e.g. dev) to another (e.g. production) without changes.
Essentially this means avoiding hard coding names and paths in vhost configuration as much as possible.All sites are redirected to use SSL.
For production sites we use LetsEncrypt for SSL Certificates.
We currently assume other environments are hosted on personal servers of some sort so we use the default snakeoil certificates.
Per (1) above we avoid hard-coding paths to these certificates.A consistent vhost configuration across all servers and all sites.
For example, we want to make sure that all the sites use the same SSL configuration without having to change that configuration for each vhost (see (1)).
To achieve these aims we use a combination of environment and configuration file variables.
Our approach was developed on Debian, if you are using a distribution that is not based on Ubuntu your files may be in different places - but the approach will be the same.
Environment variables
Add environment variables to the Apache envvars file which can be found in /etc/apache2/envvars
.
# add the following to the bottom of /etc/apache2/envvars
## Bespoke IT Solutions variables (prefix BITS)
## NB: Apache must be stopped and started (not restart) for changes here to take effect.
##
## Prefix applied to virtual host domain configuration
## local A local, presumably dev, environment running on local server. Handled in vhost conf
## XX Some other environment, change XX as necessary. Would need to be handled in vhost conf file.
## prod Production
export BITS_SERVERNAME_PREFIX=local
[ "$BITS_SERVERNAME_PREFIX" = "prod" ] && {
## For production sites, define a prefix for the SSL path
export BITS_SSL_PATH=/etc/letsencrypt/live
} || {
## Do not define SSL path prefix for non-prod path
##
## Append period to prefix for non-prod environments for correct names in vhost conf
export BITS_SERVERNAME_PREFIX="${BITS_SERVERNAME_PREFIX}."
}
Note the comment in that code - Apache must be stopped and started for changeshere to take effect, a restart will not do it.
Virtual host configuration
What follows requires the Apache ssl and headers modules be enabled.
Create a virtual host configuration file in /etc/apache2/sites-available
with contents similar to:
#
# Virtual Host Configuration
#
# VHost ID used for ordering the configuration files (order can be important)
Define VHostId 010
# The FQDN
Define VDomain bespoke-it.solutions
# Apache server name. Prefix defined in /etc/apache2/envvars
Define VServerName ${BITS_SERVERNAME_PREFIX}${VDomain}
# Document root
Define VHostDir /var/www/vhosts/${VServerName}
Define VHostLogDir ${APACHE_LOG_DIR}/vhosts/${VDomain}
# SSL
<IfDefine BITS_SSL_PATH>
Define VSSLCertFile ${BITS_SSL_PATH}/${VDomain}/fullchain.pem
Define VSSLCertKey ${BITS_SSL_PATH}/${VDomain}/privkey.pem
</IfDefine>
<IfDefine !BITS_SSL_PATH>
Define VSSLCertFile /etc/ssl/certs/ssl-cert-snakeoil.pem
Define VSSLCertKey /etc/ssl/private/ssl-cert-snakeoil.key
</IfDefine>
Include bits-vhost.conf
A few words about this configuration:
Define VHostDir /var/www/vhosts/${VServerName}
The document root is always under/var/www/vhosts
and always includes the FQDN.
Where we are on a non-production environment there will be a symobolic link from the local name to the FQDN, e.g.# Non-production # 'local' in the link name should match the value used for BITS_SERVERNAME_PREFIX in Apache envvars $ sudo ln -s /var/www/vhosts/bespoke-it.solutions /var/www/vhosts/local.bespoke-it.solutions
Define VHostLogDir ${APACHE_LOG_DIR}/vhosts/${VDomain}
Our vhosts logs are in a FQDN named directory under the standard Apache log directory.
We create separate logs for access, error and PHP in this directory.Paths to the SSL certificates are defined based on wether or not the BITS_SSL_PATH was defined in envvars.
Include bits-vhost.conf
All the other configuration directives required for our vhosts are defined in a single file which gets included in every vhost.
That file looks like this:# # Virtual Host Configuration # # Included in every vhost configuration file <VirtualHost *:80> DocumentRoot ${VHostDir} ServerName ${VServerName} ServerAlias www.${VServerName} # Redirect everything to https RewriteEngine On RewriteRule ^(.*)$ https://%{HTTP_HOST}$1 [R=301,L] </VirtualHost> <VirtualHost *:443> ServerAdmin info@${VDomain} DocumentRoot ${VHostDir} ServerName ${VServerName} ServerAlias www.${VServerName} <Directory ${VHostDir}> Options Indexes FollowSymLinks MultiViews AllowOverride All Order allow,deny allow from all </Directory> # Logging # Possible values: debug, info, notice, warn, error, crit, alert, emerg LogLevel info ErrorLog ${VHostLogDir}/error.log CustomLog ${VHostLogDir}/access.log combined # PHP php_flag log_errors on # php_flag display_errors on php_value error_reporting 2147483647 php_value error_log ${VHostLogDir}/php.log # SSL SSLEngine on SSLCertificateFile ${VSSLCertFile} SSLCertificateKeyFile ${VSSLCertKey} SSLProtocol All -SSLv2 -SSLv3 SSLHonorCipherOrder on # Prefer PFS, allow TLS, avoid SSL, for IE8 on XP still allow 3DES SSLCipherSuite "EECDH+ECDSA+AESGCM EECDH+aRSA+AESGCM EECDH+ECDSA+SHA384 EECDH+ECDSA+SHA256 EECDH+aRSA+SHA384 EECDH+aRSA+SHA256 EECDH+AESGCM EECDH EDH+AESGCM EDH+aRSA HIGH !MEDIUM !LOW !aNULL !eNULL !LOW !RC4 !MD5 !EXP !PSK !SRP !DSS" # Prevent CRIME/BREACH compression attacks SSLCompression Off # Headers # Commit to HTTPS only traffic for at least 180 days # # Note: this will cause errors if an invalid SSL certificate is detected which will cause css, jss, etc. to not be loaded if they are on https URL's Header add Strict-Transport-Security "max-age=15552000" # Content Security Policy # Be very careful changing this!! Refer to https://report-uri.io/ # Feb2016, AJP, removed, prevents Stripe payment processor js from loading!! # Header add Content-Security-Policy: "default-src 'self' ; script-src 'self' 'unsafe-inline' 'unsafe-eval'; style-src 'self' 'unsafe-inline' ; img-src 'self' ; font-src 'self' ;" # Prevent clickjacking Header always set X-Frame-Options "SAMEORIGIN" # X-Xss-Protection for reflective XSS Header always set X-Xss-Protection "1; mode=block" </VirtualHost>
Some notes about this configuration:
We always define a www server alias
The SSL directives are comprehensive and (in our tests) result in an A+ result from Qualys SSL labs
Note: It can be easy to break your site by enabling Content Security Policy (as the note above indicates).