Apache2 – Website Configuration
I use different configurations for each site I host on my server, but most of them are nearly identical. Here I want to share the basic version I use.
For this, you must enable 2 mods in Apache2:
MOD | Command |
mod_rewrite | sudo a2enmod rewrite |
mod_ssl | sudo a2enmod ssl |
mod_headers | sudo a2enmode headers |
Do not forget to reload/restart Apache2. Your terminal should let you know anyways if this is necessary.
Non-SSL Configuration
This configuration is only there to redirect clients from http
to https
.
The example you see below is used for my (currently discontinued) project on https://auth.calucon.de:
<VirtualHost *:80> ServerAdmin simon@calucon.de ServerName auth.calucon.de DocumentRoot /var/www/auth/html ErrorLog ${APACHE_LOG_DIR}/auth_error.log CustomLog ${APACHE_LOG_DIR}/auth_access.log combined # Here we send the redirect header to https RewriteEngine on RewriteCond %{SERVER_NAME} =auth.calucon.de [NC] RewriteRule ^ https://%{SERVER_NAME}%{REQUEST_URI} [NC,END,QSA,R=permanent] # Security Related Headers Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "strict-origin-when-cross-origin" # Cache Control Header # only 1d for testing purposes Header always set Cache-Control "max-age=86400" </VirtualHost> # vim: syntax=apache ts=4 sw=4 sts=4 sr noet
SSL Configuration
Now we get to the interesting part, the actual configuration. This configuration file will be applied to basically all visitors on your site. (An exception might be clients that do not follow the redirect to the https
site and that case is mere non-existent)
So let’s have a look at the configuration file:
<IfModule mod_ssl.c> <VirtualHost *:443> ServerAdmin simon@calucon.de ServerName auth.calucon.de DocumentRoot /var/www/auth/html <Directory "/var/www/auth/html"> # General rules to e.g. disallow clients to view the folder structure Options -Indexes +FollowSymLinks +MultiViews AllowOverride None # Showing an Error-Page if any of these errors occur ErrorDocument 401 /error ErrorDocument 402 /error ErrorDocument 403 /error ErrorDocument 404 /error ErrorDocument 500 /error # Collection of Rewrite Rules to make the URL pretty # Put them in the config, it's more efficent than using a .htaccess file RewriteEngine on RewriteRule ^index(\/*)(.*)$ index.php [NC,QSA] RewriteRule ^error(?:\/*)$ index.php?s=error [NC,QSA] RewriteRule ^about(?:\/*)$ index.php?s=about [NC,QSA] RewriteRule ^docs(?:\/*)$ index.php?s=documentation [NC,QSA] RewriteRule ^login(?:\/*)$ index.php?s=account/login [NC,QSA] RewriteRule ^logout(?:\/*)$ index.php?s=account/logout [NC,QSA] RewriteRule ^register(?:\/*)$ index.php?s=account/register [NC,QSA] RewriteRule ^verify\/([a-zA-Z0-9\-]*)$ index.php?s=account/verify&token=$1 [NC,QSA] RewriteRule ^reset\/password(?:\/*)$ index.php?s=account/reset/password_reset [NC,QSA] RewriteRule ^reset\/password\/([a-zA-Z0-9\-]*)(?:\/*)$ index.php?s=account/reset/password_reset_token&resetToken=$1 [NC,QSA] RewriteRule ^change\/(mail|username|password)(?:\/*)$ index.php?s=account/change/$1 [NC,QSA] RewriteRule ^validate\/mail(?:\/*)$ index.php?s=account/validate/mail [NC,QSA] RewriteRule ^profile(?:\/*)$ index.php?s=account/profile [NC,QSA] RewriteRule ^app\/(view|used|create)(?:\/*)$ index.php?s=app/$1 [NC,QSA] RewriteRule ^app\/(edit|login|revoke)\/(.{32})(?:\/*)$ index.php?s=app/$1&token=$2 [NC,QSA] RewriteRule ^api\/(.+)(?:\/*)$ apix.php?s=$1 [NC,QSA] #RewriteRule ^profile\/((?:(?!\/).)*?(?:\s|%2520)*?)$ index.php?s=account/profile&u=$1 [NC,QSA] </Directory> ErrorLog ${APACHE_LOG_DIR}/auth_error.log CustomLog ${APACHE_LOG_DIR}/auth_access.log combined # Add Let'sEncrypt Certificate and apply ssl seciruty rules provied by Let'sEncrypt SSLCertificateFile /etc/letsencrypt/live/auth.calucon.de/fullchain.pem SSLCertificateKeyFile /etc/letsencrypt/live/auth.calucon.de/privkey.pem Include /etc/letsencrypt/options-ssl-apache.conf # CSP not enforced here as this header gets set by my PHP application! #Header always set Content-Security-Policy "default-src 'none'; script-src 'self'; connect-src 'self'; img-src 'self'; style-src 'self'; font-src 'self' data:; frame-ancestors 'self'; base-uri 'self'; form-action 'self'" # Security Related Headers Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains; preload" Header always set X-Frame-Options "SAMEORIGIN" Header always set X-Content-Type-Options "nosniff" Header always set X-XSS-Protection "1; mode=block" Header always set Referrer-Policy "strict-origin-when-cross-origin" #Cache Control Header # only 1d for testing purposes Header always set Cache-Control "max-age=86400" </VirtualHost> # vim: syntax=apache ts=4 sw </IfModule>
You may have noticed, that I disabled the CSP
header which should always be set, especially for security reasons!
This is because some parts of the website require a variable form-action
to be set for specific pages.
Basically, there is a form that will redirect the client to a remote site and this form includes a login-token
. To transfer this token securely, we can not add it the URL (GET
request) as this is unsafe, so we must make a POST
request which is best achieved using a Form
. The form data is sent to the external URL upon submit and if the external URL is not part of the CSP
, we are not allowed to submit the form.