Application Stacks Azure

Virtualmin GPL on Ubuntu 24.04 on Azure User Guide

| Product: Virtualmin GPL on Ubuntu 24.04 LTS on Azure

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 website needs in one step, including an Apache virtual host, a dedicated Unix user and home directory, a DNS zone, mailboxes, a database and FTP access. Managing dozens of domains no longer means hand editing Apache, BIND, Postfix and MariaDB configuration separately.

The cloudimg image installs Virtualmin GPL through the official upstream installer, pinned to the GPL edition, together with the complete hosting stack it manages: Apache, MariaDB, PHP, Postfix, Dovecot and BIND. The panel runs on Webmin's own web server (miniserv) and serves its console directly over HTTPS on port 10000, with Webmin's session login as the only gate in front of it. Ports 80 and 443 are left entirely to Apache so they can serve the websites you host. A unique administrator password and a unique self signed TLS certificate are generated on the first boot of every VM. Backed by 24/7 cloudimg support.

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 exposing this VM beyond your own management network.

What is included:

  • Virtualmin GPL installed via the official upstream installer, explicitly pinned to the GPL edition
  • Webmin serving the Virtualmin console over HTTPS directly on port 10000 (self signed certificate, regenerated per VM on first boot)
  • 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 panel password generated on first boot, recorded in a root only file (username root)
  • webmin.service plus the Apache, MariaDB, Postfix, Dovecot and BIND units, enabled and active
  • 24/7 cloudimg support

Prerequisites

An active Azure subscription, an SSH key pair, and a VNet + 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 meaningfully more memory than a single service appliance. NSG inbound: allow 22/tcp from your management network only, 80/tcp and 443/tcp if you intend to serve websites from this server, and restrict 10000/tcp (the Virtualmin panel) to trusted source IP ranges - do not leave it open to the whole internet, since the panel has full control of the box.

Step 1 - Deploy from the Azure Marketplace

Sign in to the Azure Portal, choose Create a resource, search the Marketplace for Virtualmin by cloudimg, and select Create. On Basics 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. Then Review + create -> 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 rather than leaving it open to *.

Step 3 - Connect to your VM

ssh azureuser@<vm-public-ip>

Step 4 - Confirm the hosting stack is running

Virtualmin is not one service but several working together. Confirm they are all active:

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

Every line should read active. The panel itself listens on port 10000:

sudo ss -tln | grep ':10000'

Virtualmin hosting stack service status

Step 5 - Retrieve your panel password

A unique panel password is generated on the first boot of every VM and written to a root only file. Nothing is baked into the image:

sudo cat /root/virtualmin-credentials.txt

You can also confirm the installed edition is GPL, with no server limit:

sudo virtualmin license-info

Virtualmin edition and per-VM credentials

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 the panel is serving its login page. A freshly deployed image hosts no websites until you create one:

sudo virtualmin list-domains --name-only

Virtualmin panel health check

Step 7 - Verify authentication from the command line

Before opening 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, and it requires a cookie from an initial unauthenticated request, so the check primes a cookie jar first:

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 (authenticated, with a fresh session cookie). The wrong password returns 200 - the login form is simply redisplayed and no session is issued.

Virtualmin authentication round trip

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 specific VM, so your browser will show a warning the first time - accept it, or install a trusted certificate as described in Maintenance.

Virtualmin login page

Step 9 - The Virtualmin dashboard

After signing in you land on the Virtualmin dashboard, which lists your virtual servers and summarises the health of the server behind them.

Virtualmin dashboard

Step 10 - Create your first virtual server

This is what the panel exists for. Choose Create Virtual Server, enter the domain name you want to host, set an administration password, and choose which features it should have - website, DNS zone, mailboxes, database and so on. Virtualmin then provisions all of them together.

Create Virtual Server form

The same operation is available from the command line, which is useful for scripting 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, Virtualmin can list it and show what it provisioned:

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), its own Apache virtual host, and, where you enabled them, its own DNS zone and mailboxes. To remove one and everything it owns:

sudo virtualmin delete-domain --domain example.com

Step 12 - System information

Webmin's System Information page reports the server's load, memory, disk and package status underneath the panel.

Virtualmin system information

Maintenance

Restrict access to the panel. Port 10000 gives complete control of this server. Keep the NSG rule for it scoped 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 specific VM on first boot. For production, install a trusted certificate from within the panel: Webmin -> Webmin Configuration -> SSL Encryption, or 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, use 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 it is completed. This image ships with that wizard already completed using Virtualmin's own default settings, so you land straight on the dashboard. If you want to revisit those choices - preloading libraries for lower memory use, spam and virus scanning, database passwords, and DNS behaviour - run it at any time from Virtualmin -> System Settings -> Re-run post-installation wizard.

DNS. Virtualmin can create BIND zones for the domains you host, but for those zones to be authoritative on the public internet you must 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 licence 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 ships fully patched and keeps Ubuntu's unattended security updates enabled. Virtualmin and Webmin themselves update through the Virtualmin package repositories using the panel's own System Information -> Package Updates page or apt.

Support

cloudimg images are backed by 24/7 support. Contact support@cloudimg.co.uk with your Azure subscription ID and the VM name.