Oops, I did it again ! I should have said “httpd” of course, the famous Apache web server.
I was so bored of starting from scratch for each new VHOST created, so the idea of writing an article keeping a template with the best security measures (taken from many places, see Sources below) has come up.
And here we are, a brand new Markdown post about it !
Let’s start with the first part !
Part 1 - Securing Apache
If you have never secured Apache globally, you should start with this part (although, if you do, skip it and go to the second part) !
In a few words, the configuration below will… :
Block all requests (your VHOSTs will have to allow them explicitly on their side)
Turn off Apache verbosity
Block all requests to a hidden resource (handful for
.git/folder for instance)
Enforce OWASP headers recommendations
Authorize Cookies only on secured connections
Reduce the default timeout for sessions and limit requests size to 1 MB (you can increase it if you need to)
Force clients to negotiate only with secure ciphers, on TLS v1.2 (see Sources)
Just create this file :
# nano /etc/apache2/conf.d/security.local.conf
… and paste the following :
You’ll need some new modules to enforce these measures (and those during the second part) :
# a2enmod headers rewrite ssl
I’d advise you to catch a glimpse of the modules already loaded with :
# apachectl -M
You can easily remove some of them you won’t use, as below :
# a2dismod cgi autoindex <...>
If you need any protection from DDoS or BruteForce attacks, I advise you to follow this tutorial.
Reload Apache to parse and apply the new configuration :
# systemctl reload apache2.service
Now, you’re all set for the second part
Part 2 - VHOST specific configuration
Below, you’ll find two configurations :
The first one is supposed to be named 000-default.conf : It will listen to the port 80, and redirect to each HTTPS VHOST in function of the domain name requested (just complete it with as many
RewriteCondas you need)
The second one is the content you’ll have to duplicate for each of your VHOST. They will listen to the port 443 (let’s say with Let’s Encrypt support).
This VHOST needs some explanations :
Set the webroot and harden the website authorization
Set HSTS header (see Sources)
Disable (only) HTTP 1.0 requests
Loads Let’s Encrypt SSL certificate
We should say “TLS”, shouldn’t we ? (Coucou Nico’ )
Set dedicated logs (useful to debug and monitor which website is under attack)
Don’t forget to enable each one of your websites with :
# a2ensite <website>
You may encounter a side effect of your VHOST naming.
Try to access your web server directly with its IP, instead of one of the VHOST’s domain names) : http://your.server.address.ip/.
It’s very likely that you don’t want this website to answer when crawlers will start dealing with your server.
To recover from this behavior, just rename the VHOST you want to answer by default to something like
When your IP will be accessed on the port 443, Apache will just redirect the query to the first VHOST name in a “top-down” way.
If you want to use a development Framework, it will surely shipped with a
.htaccess file. Don’t forget to pass the
All to authorize your default settings to be overridden for a specific VHOST.
On the same idea, some of them (hello CakePHP ) use symbolic link to enable their plugins. So, you may need to activate
It’s good to secure your web server, but if you are hosting a PHP application for instance, it won’t block any attack occurring at the “application level”…
So this is the end, I hope it helped you
Please do propose some changes if you think there is something bad (or something missing) ; I’ll try to keep this article up-to-date in the future !
HSTS Preloading (by the Chromium project)
History of revisions
2022-09-04 - Drop support for Apache < 2.4 and replace
2022-01-27 - Disable legacy XSS filtering through
2020-03-16 - Due to this notice,
cipherli.st has been replaced by
always set/edit security headers
2018-11-24 - Grants access to special (not-hidden)
2018-11-11 - Gets rid of CBC encryption mode in ciphers list
2018-10-12 - Adds a default
Referrer-Policy header to the local security configuration
2018-08-01 - Replaces
Deny options by
Require for Apache >= 2.4, in a BC way for previous versions
2018-01-14 - Fixes wrong HSTS header setting
2018-01-09 - Adds Content Security Policy header to
2017-11-21 - Adds SSLStapling and Internet Explorer specific directives