Virtualmin is some handy software if you want to self-host your domain, (web, email, etc).
After installation there are some steps to follow to make your virtualmin install a bit better. I haven’t found one single piece of documentation that combines this post install best practices together. “So why not create one yourself”.
A small note. I blanked out domain names and IP addresses as the value of the two is for everybody different and mine doesn’t matter for the example.
Post install procedure within webmin
If you install virtualmin by using the installation script on the virtualmin website (using curl and sudo) and you log in for the first time you are immediately greated with a post install procedure.








If the primary nameserver doesn’t resolve yet, tick the box “Skip check for resolvability”.






Create a new server

Once the server is reachable you can also request a Let’s Encrypt certificate under “Manage Virtual Server” -> “Setup SSL Certificate”.
Make sure that you also use that certificate for the services (Dovecot etc).
Hardening
In order to check if the server is setup as good as possible, I personally use Internet.nl (dutch), but there are similar english sites to check. Each section refers to a section of Internet.nl. In each section, I will show the initial value and if there is something to improve, I will describe the improvement and subsequently the result.
Overall Initial score

Let’s handle each item at a time
IPv6

This is currently not possible yet, as long as IPv6 is not available, it will not possible to reach 100%, but only 55%. Once IPv6 is available I will create a follow-up post.
DNSSEC

DNSSEC by default is disabled. You need to enable it under “DNS Settings” -> “DNS Options”.

Once enabled (DNSSEC signature enabled), it will create the signature and you will get an extra section, that you can click open to show you your DNSSEC keys.

In that “DNSSEC zone keys” section, at the bottom, there is a line: “DS records for domain registrar”. I’ve put that in the zonefile of the parent domain.


HTTPS



HTTPS compression
In order to disable https compression, you have to disable the deflated module in apache2. You can find it under Webmin -> Servers -> Apache Webserver -> “Global configuration” tab -> “Configure Apache Modules”

I was not able to disable it there so I used the following command on the command prompt:
sudo a2dismod deflate
WARNING: The following essential module will be disabled.
This might result in unexpected behavior and should NOT be done
unless you know exactly what you are doing!
deflate
To continue type in the phrase 'Yes, do as I say!' or retry by passing '-f': Yes, do as I say!
Module deflate disabled.
To activate the new configuration, you need to run:
systemctl restart apache2


HSTS
First and foremost, make sure that https is the default protocol to use and that http traffic is forwarded to https.
In virtualmin under your domain go to Web Configuration -> Website Options and select Yes on “Redirect all requests to SSL site”

At the end of your apache config of all websites add:
Header always set Strict-Transport-Security "max-age=31536000; includeSubDomains"

I’ve added this also to /etc/apache2/sites-available/default-ssl.conf. After I wanted to reload apache2 I got an error, that it didn’t recognize the Header line. Turns out I need to enable headers as a apache2 module.
a2enmod headers
Enabling module headers.
To activate the new configuration, you need to run:
systemctl restart apache2

Cipher order
There is no cipher list and preferred order supplied in /etc/apache2/apache2.conf. This can be fixed by adding the following lines at the end of the apache2.conf
SSLCipherSuite EECDH+AESGCM:AES256+EECDH:DES-CBC3-SHA
SSLHonorCipherOrder on

OCSP stapling
I’ve added the following to apache2.conf.
SSLUseStapling on
SSLStaplingCache shmcb:/var/run/ocsp(128000)
SSLStaplingResponderTimeout 5
SSLStaplingReturnResponderErrors off

DANE presence


I double checked but the entries were present in the DNS server. So I rebooted the server in order to make sure that all process were restarted and are looking at the latest config. And that gave the required result.

Security options

X-Frame-Options
To fix this add the following to your apache2.conf
Header always set X-Frame-Options SAMEORIGIN

X-Content-Type-Options
Just add the following line to your apache2.conf
Header always set X-Content-Type-Options nosniff

Content-Security-Policy
Add the following to your apache2.conf
Header always set Content-Security-Policy "default-src 'self'; script-src 'self'; style-src 'self'; img-src 'self' data:; font-src 'self'; object-src 'none'; frame-ancestors 'none'; base-uri 'self'; form-action 'self';"

Referrer-Policy
Add the following line in the same place as the previous ones.
Header always set Referrer-Policy "no-referrer"

security.txt
I am ignoring this one for now. As it doesn’t increase the score and you need to resign and review it regurlaly. I will have a look at a later date to see if this can be automated.
Route authorization (RPKI)

Result
After doing all the configuration the score increased and except for IPv6 and security.txt everything is green on the board.
