Deployment guide

Virtualmin

Overview

Virtualmin GPL is an open-source web hosting control panel built on Webmin. It turns a single Linux server into a multi-tenant hosting platform. Each website you add becomes a virtual server, and Virtualmin provisions everything that site needs in one step: an Apache virtual host, a dedicated Unix user and home directory, a DNS zone, mailboxes, a database and FTP access.

This SecureAnyCloud image installs Virtualmin GPL through the official upstream installer, pinned to the GPL edition, together with the hosting stack it manages. You can run dozens of domains without hand-editing Apache, BIND, Postfix and MariaDB configuration separately.

Virtualmin has full administrative control of the operating system it runs on. It can create and delete system users, edit DNS zones, install packages, change the firewall, and read and write almost any file on the server. Treat the panel credentials as root-equivalent, and read the security notes in Maintenance before you expose this VM beyond your own management network.

What you get:

  • Virtualmin GPL installed through the official upstream installer, explicitly pinned to the GPL edition
  • Webmin's own web server (miniserv) serving the Virtualmin console over HTTPS directly on port 10000, with Webmin's session login as the only gate in front of it
  • The full hosting stack the panel manages: Apache, MariaDB, PHP, Postfix, Dovecot and BIND
  • Ports 80 and 443 reserved for Apache to serve your hosted websites
  • A unique administrator password and a unique self-signed TLS certificate, generated on the first boot of every VM
  • The panel password recorded in a root-only file (username root)
  • webmin.service plus the Apache, MariaDB, Postfix, Dovecot and BIND units, enabled and active
  • 24/7 SecureAnyCloud support

Prerequisites

You need an active Azure subscription, an SSH key pair, and a VNet with a subnet in the target region.

Standard_B4ms (4 vCPU / 16 GiB RAM) is the recommended starting size. Virtualmin runs a web server, a database, a mail stack and a DNS server together, so it needs more memory than a single-service appliance.

Configure the network security group (NSG) for inbound traffic as follows:

  • Allow 22/tcp from your management network only.
  • Allow 80/tcp and 443/tcp if you intend to serve websites from this server.
  • Restrict 10000/tcp (the Virtualmin panel) to trusted source IP ranges. Do not leave it open to the whole internet, because the panel has full control of the server.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Virtualmin by SecureAnyCloud, and select Create.

On the Basics tab, pick your subscription, resource group, region and size. Under Administrator account, choose SSH public key and paste your key.

Under Inbound port rules, allow SSH (22), HTTP (80) and HTTPS (443). Then add a custom rule for TCP 10000 restricted to your own IP range. Select Review + create, then Create.

Step 2 - Deploy from the Azure CLI

az vm create \
  --resource-group <your-rg> \
  --name virtualmin \
  --image <marketplace-image-urn> \
  --size Standard_B4ms \
  --admin-username azureuser \
  --ssh-key-values ~/.ssh/id_ed25519.pub \
  --vnet-name <your-vnet> --subnet <your-subnet> \
  --public-ip-sku Standard
az vm open-port --resource-group <your-rg> --name virtualmin --port 80 --priority 1010
az vm open-port --resource-group <your-rg> --name virtualmin --port 443 --priority 1015
az vm open-port --resource-group <your-rg> --name virtualmin --port 10000 --priority 1020

Restrict the port 10000 NSG rule to your own management IP range. Do not leave it open to *.

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the hosting stack is running

Virtualmin is several services working together. Confirm that they are all active:

systemctl is-active webmin.service apache2.service mariadb.service postfix.service dovecot.service named.service

Every line should read active. Then confirm that the panel listens on port 10000:

sudo ss -tln | grep ':10000'

Step 5 - Retrieve your panel password

Each VM generates a unique panel password on first boot and writes it to a root-only file. No password is baked into the image. Read the file with sudo:

sudo cat /root/virtualmin-credentials.txt

To confirm that the installed edition is GPL, with no server limit, run:

sudo virtualmin license-info

Step 6 - Confirm the panel is serving over TLS

curl -sk -o /dev/null -w 'HTTP %{http_code}\n' https://127.0.0.1:10000/session_login.cgi

HTTP 200 confirms that the panel is serving its login page. A freshly deployed image hosts no websites until you create one:

sudo virtualmin list-domains --name-only

Step 7 - Verify authentication from the command line

Before you open the panel in a browser, confirm that the generated password authenticates and that a wrong password does not. Virtualmin's login is a form POST to session_login.cgi. It requires a cookie from an initial unauthenticated request, so the check first primes a cookie jar:

login(){ jar=$(mktemp); curl -sk -o /dev/null -c "$jar" https://127.0.0.1:10000/session_login.cgi; s=$(curl -sk -o /dev/null -b "$jar" -c "$jar" -w '%{http_code}' --data-urlencode action=login --data-urlencode user=root --data-urlencode "pass=$1" --data-urlencode page=/ https://127.0.0.1:10000/session_login.cgi); rm -f "$jar"; echo "$s"; }
PW=$(sudo grep '^VIRTUALMIN_PASSWORD=' /root/virtualmin-credentials.txt | cut -d= -f2-) login "$PW" login "wrong-pw-xyz"

The correct password returns 302, which means you are authenticated and have a fresh session cookie. The wrong password returns 200: the login form is redisplayed and no session is issued.

Step 8 - Sign in to the panel

Browse to https://<vm-public-ip>:10000/ and sign in with username root and the password from Step 5.

The appliance ships a self-signed certificate generated for this VM, so your browser shows a warning the first time. Accept it, or install a trusted certificate as described in Maintenance.

Step 9 - The Virtualmin dashboard

After you sign in, you land on the Virtualmin dashboard. It lists your virtual servers and summarizes the health of the server behind them.

Step 10 - Create your first virtual server

Choose Create Virtual Server, enter the domain name you want to host, and set an administration password. Then choose the features it should have: website, DNS zone, mailboxes, database and so on. Virtualmin provisions all of them together.

The same operation is available from the command line, which suits scripted bulk provisioning:

sudo virtualmin create-domain \
  --domain example.com \
  --pass <a-strong-password> \
  --unix --dir --web --dns --mail --logrotate

Step 11 - Verify a virtual server from the command line

Once a virtual server exists, list it and show what Virtualmin provisioned for it:

sudo virtualmin list-domains --name-only sudo virtualmin list-domains --domain example.com --multiline

Each virtual server gets its own Unix user and home directory (with a public_html web root) and its own Apache virtual host. If you enabled them, it also gets its own DNS zone and mailboxes. To remove a virtual server and everything it owns, run:

sudo virtualmin delete-domain --domain example.com

Step 12 - System information

Open Webmin's System Information page to see the server's load, memory, disk and package status beneath the panel.

Maintenance

Restrict access to the panel. Port 10000 gives complete control of this server. Scope its NSG rule to trusted management IP ranges, and never expose it to 0.0.0.0/0.

Replace the self-signed certificate. The appliance generates a self-signed certificate for this VM on first boot. For production, install a trusted certificate from within the panel at Webmin -> Webmin Configuration -> SSL Encryption. You can also use Virtualmin's built-in Let's Encrypt support, which is fully available in the GPL edition.

The server hostname is fixed by design. Virtualmin writes the appliance hostname into Apache, Postfix and BIND configuration at install time, so the image keeps its hostname rather than adopting the Azure VM name. To rename the server, go to Webmin -> Networking -> Network Configuration -> Hostname and DNS Client. Then run Virtualmin -> System Settings -> Re-Check Configuration.

The post-installation wizard. Virtualmin normally intercepts the first administrator login with a multi-step post-installation wizard, and the panel is not usable until the wizard is completed. This image ships with the wizard already completed using Virtualmin's own default settings, so you land straight on the dashboard. To revisit those choices, run the wizard at any time from Virtualmin -> System Settings -> Re-run post-installation wizard. The choices cover preloading libraries for lower memory use, spam and virus scanning, database passwords, and DNS behavior.

DNS. Virtualmin can create BIND zones for the domains you host. For those zones to be authoritative on the public internet, point the domain's nameservers at this server and open port 53. If you use an external DNS provider instead, create virtual servers without the DNS feature.

GPL edition and source code. This image ships Virtualmin GPL, which is licensed under the GNU General Public License v3, and Webmin, which is licensed under the BSD 3-Clause License. Their license texts ship on the image under /usr/share/doc. Corresponding source is available from the upstream projects at github.com/virtualmin/virtualmin-gpl and github.com/webmin/webmin. Virtualmin Professional is a separate commercial product and is not included.

Updates. The image is patched at build time and keeps Ubuntu's unattended security updates enabled. Virtualmin and Webmin update through the Virtualmin package repositories. Use the panel's System Information -> Package Updates page or apt.

Support

SecureAnyCloud images are backed by 24/7 support. Contact sales@secureanycloud.com and include your Azure subscription ID and the VM name.

Deploy on Azure

Launch Virtualmin GPL on Ubuntu 24.04 LTS on Azure with 24/7 support from SecureAnyCloud.

View on Marketplace

Need Help?

Our support team is available 24/7.

sales@secureanycloud.com

Deploy on Azure