You are here

VPS Websites using free Webmin-Virtualmin

Webmin logo

This howto is a pretty version of my crib-sheet reminding me how I setup my VPS (Virtual Private Server) with webmin and virtualmin (gpl) in case I need to rebuild it or move it. It's in part my personal preferences so it's not gospel, but hopefully it will be helpful.

The specs of my setup are modest. A total of 3 websites running Drupal i.e. apache, mysql, php, plus email for all 3 with spamassassin and filters. Before I set up this VPS up I was on shared hosting and using the free version of CloudFlare CDN (Content Delivery Network). CloudFlare was more important when I was on shared hosting which was located in the USA than for this VPS where I can choose the server to be located in London, near to the majority of my users. However, CloudFlare takes some of the load off the VPS so it makes sense to keep it. This means that the DNS nameservers are on Cloudflare and need to be set up by hand which is not a big issue for just a few sites. It also means I don't need to worry about running a nameserver on the VPS so I don't need BIND, which takes more load off the VPS.

The VPS company I use is Digital Ocean which although not the cheapest I reckon is very good value for what you get. They also have the advantage of charging by the hour (capped to a fixed monthly fee). This means you can spin up a second VPS just for testing, rather than messing with your live site. This can be an image of the live site, if you take one which means a few minutes offline, or an older saved image. Currently Digital Ocean don't charge for image storage, and although that might change it would still be cheaper than running a second VPS just for the occasional testing. The cost of a VPS is cheaper than the full price of shared hosting. You also get far more performance and far more control, but at the cost of doing it all yourself.

On top of a VPS with a Digital Ocean's standard Ubuntu image is installed webmin and virtualmin (gpl). This supplies pretty much everything you need to get any website up and running, apache, php, perl, ssl, mysql, etc.. The pair of webmin/virtualmin are installed by a single script which can be found on this page.

0. Prerequisites

  1. Domain name for VPS (e.g.
  2. Domain name for each web site (e.g.,
  3. Putty or another SSH terminal program
  4. WinSCP or another SFTP program

It makes life simpler to have a separate domain name (or FQDN, FullY Qualified Domain Name) as well as domain names for all the websites. It is supposedly possible to use a subdomain of a site domain, but as £4 pa gets you a domain it wasn't worth the extra complication.

1. Create Droplet

  1. Sign up with Digital Ocean (or your vps company of choice).
  2. Create droplet (VPS) with name = VPS FQDN (i.e. and Ubuntu LTS 32Bit (LTS 14.04 is current latest).
  3. Add DNS records, A = VPS-FQDN, IP-NUMBER, A = mail.VPS-FQDN, IP-NUMBER, MX = 0, mail.VPS-FQDN

The reason for calling the droplet by the full domain name, e.g. and not just sites-hub is that for email spf is be valid reverse dns (PTR record) must point to FQDN. Digital Ocean control the PTR record and that uses the droplet name. Hence if you call the droplet sites-hub then PTR and email spf doesn't work (and guess how I know that). However, if this is a duplicate of an existing site then don't give a FQDN and come back to change it later when the duplicate is up and running. The reason for using a 32bit OS is more RAM efficient given that we are unlikely to need over 4GB (I run with the minimum size which is 512MB). And Ubuntu is just a personal choice, although it is also a popular choice.

2. Set-up Swap File

  1. Login to the droplet using putty and change password (which you'll be forced to do).
  2. Enter the following commands to make a 1GB swap file. Note {....} is a comment, don't enter that.
    fallocate -l 1G /swapfile
    ls -lh /swapfile {check size is correct}
    chmod 600 /swapfile {lock down permissions}
    ls -lh /swapfile {check permissions}
    mkswap /swapfile
    swapon /swapfile
    swapon -s {check swapfile}
    free -m {check memory includes swap}
  3. Now make swap file permanent, in WinSCP open /etc/fstab and add this line at the end, using tabs between fields.
    /swapfile none swap sw 0 0
  4. Configure Swapping, in WinSCP open /etc/sysctl.conf and add these lines at the end.
    # Custom swap settings for performance:
    vm.vfs_cache_pressure = 50
  5. Reboot. In putty type:
    reboot {and then log back in}
    free -m {check swap is permanent}

See this page for more details.

3. Fix Host name and Domain name

There is a catch22 in VPS naming. If, for example, your domain name is then the VPS name will be so that the reverse DNS, PTR, is However, Linux expects the VPS name to be something like from which it derives the domain name by taking off the text before the first dot. So if the VPS is named then sites-hub is the machine name and the domain name which is incorrect of course. You can see this using putty with the hostname command thus:

hostname -f {VPS FQDN}
hostname -d {VPS domain name}

The fix is to change the name assigned during the VPS creation by adding either server, primary, host, hub, etc., whatever takes your fancy to this. In WinSCP open /etc/hostname and then add a server name and save the file, i.e. becomes

And again in WinSCP open /etc/hosts and do the same i.e. sites-hub

becomes sites-hub

Note site-hub is an alias of, or you can change that. And finally in putty:

reboot {and then log back in}

When you log back in with putty you'll notice that if you added the name primary the command line is now root@primary rather than root@sites-hub.

4. Update System and Install Webmin/Virtualmin

  1. In putty enter the following commands to update everything. As before {....} is a comment.
    apt-get update {get new list of packages}
    apt-get dist-upgrade {upgrade distribution}
    apt-get upgrade {upgrade packages}
    apt-get autoremove {remove old replaced packages}
    apt-get autoclean {remove old cached packages}
    apt-get clean {remove cached packages}
    apt-get check {check no errors}
  2. Install fail2ban intrusion prevention.
    apt-get install fail2ban
  3. Install webm/virtualmin.
    chmod +x

    Answer any questions. If you did not give the droplet a name which is a FQDN, as you might not when creating a duplicate of an existing web site hub, then you'll be asked for a FQDN. Enter the existing hub FQDN in this case. Note that you when you did the hostname fix up then you could have corrected the hostname and domain name then too. The whole install takes a while so now is a good time to get a coffee. And finally when the install script has finished:


5. Initial Set-up of Webmin/Virtualmin

In a browser go to https://new-ip-number:10000 where new-ip-number is the IP number of your VPS. The browser will likely complain of a security issue because the ssl certificates are self-signed. Accept this and you should then have a login box. Enter user = root, password = VPS password. This will log you in and then ask more setup questions. My answers below:

  • Preload Virtualmin libraries? = N
  • Run email domain lookup server? = Y
  • Run ClamAV server scanner? = N
  • Run SpamAssassin server filter? = N
  • Run MySQL database server? = Y
  • Run PostgreSQL database server? = N
  • Set MSQL password {not system root since it saves this in /etc/webmin/mysql/config}
  • MySQL configuration size = 512M
  • Primary name server =
  • Password storage mode = Only store hashed passwords

The above answers assume your site runs mysql and you want good security. The other answers are to give minimal RAM usage with good performance. ClamAV uses a lot of resources and duplicates the AV on the email recipient's PC so that is disabled later. Emails are not so often so spamassassin is loaded each time rather than kept in memory. The nameserver doesn't matter since we are going to disable bind but we may as well give it something that is a nameserver.

On the screen now, which is System Information the side menu, it should say that all the virtualmin modules are up to date. If not click the Virtualmin Packages link and update them. This might require a refresh and second update. In any case click the Virtualmin Packages link and set up the checking schedule to your preference, say every day, email notification (see also unattended-upgrades end of 7 below).

Note the virtualmin install script sets up the system to check and upgrade virtualmin, webmin and usermin automatically so there is no need to manually upgrade. However, there is often a lag between upgrades available on the webmin site and those in the virtualmin repository. If you have a bug that a recent release fixes then you can, when logged in via a browser, go to System->Software Packages and install the new package direct with its URL. Typically you'll need to reboot either using putty to give the command reboot or go System->Bootup and Shutdown and hit the reboot button at the bottom of the page. Wait for it to reboot then refresh the page.

Set local timezone by going to Hardware->System Time and click the change timezone tab. Select the correct time zone and save.

Enable the firewall by going to Networking->Linux Firewall, set Activate at boot to Yes and click the button.

6. Removed unused Webmin/Virtualmin Features

Remove unused features by clicking virtualmin on the menu, System Settings->Features and Plugins. Untick in the first column and disable:

  • BIND DNS domain {not needed if VPS is not a nameserver}
  • PostgreSQL database {should be unticked already}
  • ProFTPd virtual FTP {only needed for ftp, not needed for sftp}
  • Virus filtering {= ClamAV which uses a lot of resources}
  • Mailman {unless you need a mailman mailing list}

And also remove these services in Webmin. In System->Bootup and Shutdown tick:

  • bind9 {not needed if VPS is not a nameserver}
  • clamav-daemon {should be No, No already}
  • clamav-freshclam {not running ClamAV so don't need it}
  • Mailman {unless you need a mailman mailing list}
  • proftpd {not needed by sftp}

Then click Disable On Boot button, and then click the reboot button.

Note that if you use sftp then you don't need proftpd, but, if you do want to use ftp or allow users to use ftp then you will need this. Uploading and downloading from websites does not need ftp either.

Turning of bind removes the local nameserver so we also need to remove from the nameserver list. To do this, in WinSCP open /etc/network/interfaces and remove from the dns-nameservers line. The default for this line is:

So this would just leave the 2 google nameservers. You can change these to other nameservers or add more. After changing this file reboot.

7. Install Extras, Pear, PECL

  1. As in section 4, in a browser go to https://new-ip-number:10000 and login. Go to Webmin Configuration->Webmin Modules and install the pear webmin module from . You should now have a new menu item Others->PHP Pear Modules.

  2. Login using putty. Upgrade pear to latest (using uncompressed since earlier version had a gzopen bug).
    pear upgrade -Z
  3. Again with putty. Install pecl uploadprogress (required by Drupal and maybe others). Installing uploadprogress requires other libraries which are easiest to install as php5-dev.
    apt-get install php5-dev
    pecl install uploadprogress
  4. Again with putty, install unattended-upgrades. This should be installed already but this command will either say it is installed or install it.
    apt-get install unattended-upgrades

Note that Digital Ocean images come with unattended-upgrades installed so this just makes sure of that. The default is for unattended-upgrades just to automatically install security upgrades. Webmin/Virtualmin has its own checking which can be found in Virtualmin Package Updates. This is separate from unattended-upgrades and duplicates its function. Hence it is best to set Virtualmin Package Updates to just check and report upgrades needed rather than actioned them when unattended-upgrades is installed.

To config unattended-upgrades the best method is to create a new file, 60unattended-upgrades, in /etc/apt/apt.conf.d which will override the defaults in 50unattended-upgrades and not get reset to the defaults if upgraded. It this file put:

// This overrides 50unattended-upgrades.
// See 50unattended-upgrades for descriptions.

Unattended-Upgrade::Allowed-Origins {
// "${distro_id}:${distro_codename}-updates";
// "${distro_id}:${distro_codename}-proposed";
// "${distro_id}:${distro_codename}-backports";

Unattended-Upgrade::Mail "";

Replacing with your email of course. This sticks to the default of just doing security upgrades but if you want to include normal updates as well as security updates then just take the // from the front of the -updates line. You will get emailed by unattended-upgrades when it does and upgrade and when it does an upgrade and reboot is required. If you set Virtualmin to email upgrade reports then that will tell you when any other upgrades are needed.

8. Create Websites

This is all pretty much self explanatory. In a browser go to https://new-ip-number:10000 and login. Click virtualmin and then create new virtual server. Fill in the fields as required, expanding the sections as needed, then click the create server button. Assuming you don't change the default settings this will create the website, e.g. with a master user of site1 with all permissions, email, ssh, ftp and database.

The default options will also create a database site1 too. The password for user site1 on database site1 can be changed by selecting virtual server, then clicking Edit Databases and selecting Passwords tab. At the same place clicking show will pop up a window with the current password in plain text. There is one password for all databases on a virtual server which virtualmin saves as plain text so don't use root password. Websites using Drupal etc. store the password in plain text too. Virtualmin uses this password when you use its restore function to restore or move a website so always change it here and not in webmin, Servers->MySQL Database Server. Similarly always use one of the site users as the database user and not a user created under webmin otherwise virtualmin restore won't work correctly.

Once the virtual server is created you can add additional user emails (and optionally give them database access too), email aliases (i.e. different email names for the same mailbox) and more databases. You don't have to use the default database and can delete that in favour of one with a different name. But, any database name should avoid using _ (underscore) as this does restore correctly. Letters, numbers and - (dash) do restore ok.

By default mail filtering is only done in webmin, Servers->Procmail Mail Filter. If you want to have email filtering at user level then you need to click virtualmin, then Email Messages->Spam and Virus Scanning and then select yes for Allow mailbox users to create mail filters. Mail filters are created in usermin which can be found by Edit Users, click user and then click the Login to Usermin button or via a direct login to https://new-ip-number:20000.

Webmin-Virtualmin How-To Blog Posts



multiple sites

Hi, I'm trying to host 2 sites on the same droplet, each with own email. I started with a droplet named but I noticed that you do it differently. Do I need to start over and name the droplet and later fix the host name as you do? Does it matter?

I can't get the email working and don't know if it is my mx records or the thing I mentioned above. Lets say my primary site is and second site is What mx records should I enter for each of them to get email working on both?

Thanks in advance for your help! I've been googling for the last day and you seem to have the best info on the subject.

The reason for having "hub"

The reason for having "hub" domain is that all email will be routed from that domain if you look at the headers.  So if have 3 different sites that are separate then to my mind it is neater to have a holding site, rather than the headers showing site2 email is routed from site1.  It can also useful if you want to move the sites as you can take out another domain name and work with that leaving current setup untouched.

Receiving email is handled by virtualmin so if you go to virtualmin for your domains  does it say under features that mail is enabled for domain?

The dns should be something like this

A <ip_number>
A mail <ip_number>
MX 0


Got it now. My problem was

Got it now. My problem was the missing a record for the mail. So we need an A record for, another A record for the, and an MX record for the

I also added A and MX records for the smtp, don't know whether it was required. Everything's working fine now.

Many thanks!

GCE tip

Instructions are efficiently simple and here is a side note for fellas doing the job on Google Compute Engine.

If you are getting "error connection timeout" on browser while connecting to "", you need create a firewall rule to allow incoming connection to the instance "VPS" on port "10000"

Also you need to create another rule for "usermin" which runs on port "20000"

Thank you Malc for the helpful post, It made things a lot easier.

About the mail setup and dns records

Hello. First of all great article and so easy to follow. I am coming through the same thing as you - trying to get rid of the shared hosting and go the VPS route. What I struggle is the mail setup. Now I have similar configuration to yours - 1 "hub" domain as you call it and 3 separate websites. I don't want to setup DNS, but I am not sure what to write as a DNS entries for the mail to work. Basically will you be able to share the steps for the mail setup and how to route it for the 3 different domains? Or at least some guidance will be great and much appreciated. Thank you in advance.

You can't avoid DNS setup. 

You can't avoid DNS setup.  You have to do DNS setup for your website to work.  For that you have an A record that says, for example is 123.456.789.012.  For mail all you have to do is add an MX record saying is your mail server.  Usually the website where you set up your dns will walk you through it.  Once that is setup so that mail goes to your IP address (same for hub and all your domains) then webmin/virtualmin handles it ending up in the right mailbox.


Hi Malc, and thank you for your answer. From what I understand I have to set A and MX records for all the domains with my registrar and point them all to the same IP which will be the IP of my VPS.
That sounds to easy. Do I have to do any other specific changes in Virtualmin for all the domains?
Also you say you use Cloudflare for DNS - do I set this through Virtualmin or again with the domains registrar?
Thank you for taking the time to answer!