Control panels

Virtualmin: manage email, DNS and SSL for virtual servers

Day-to-day Virtualmin work on a Linux VPS: create mail users, edit DNS records in the zone, and request a Let's Encrypt certificate for each virtual server.

IntermediateLinux server6 min read

Virtualmin puts mail users, DNS zones and SSL certificates for every virtual server behind one login, so most daily work happens in the browser instead of the shell. This guide covers the three tasks you will repeat most: adding a mailbox, editing a DNS record in the server's zone, and requesting a Let's Encrypt certificate.

Before you start

  • A Linux VPS running Virtualmin, installed from the vendor's install script on Ubuntu 22.04/24.04, Debian 12, or AlmaLinux/Rocky 8–9. Follow the Virtualmin documentation for the install itself.
  • Root SSH access to the server, plus the panel login at https://203.0.113.10:10000.
  • At least one virtual server, for example example.com, already created in Virtualmin.
  • A decision about DNS: either Virtualmin's BIND runs the zone and your registrar points nameservers at this server, or the zone lives at your registrar and you only mirror records in Virtualmin.

Warning: Every DNS change takes time to propagate and can interrupt mail or website access. Lower the record's TTL a day before a planned change, and never edit MX or NS records without a reason.

Virtualmin email, DNS and SSL: what lives where

Inside a virtual server, the left menu holds everything this guide uses:

  • Edit Users — mailboxes and mailbox quotas for the domain.
  • DNS Settings → DNS Records — the zone for that domain, if BIND is enabled.
  • Server Configuration → SSL Certificate → Let's Encrypt — certificate requests and renewal status.
  • Logs and Reports — mail log, Apache/nginx log and BIND status when something fails.

Pick the domain from the dropdown at the top left before you start. Every action below applies only to the currently selected virtual server.

Add email users to a Virtualmin server

  1. Log in at https://203.0.113.10:10000 as root.
  2. Select example.com in the domain dropdown.
  3. Open Edit Users, then click Add a user to this server.
  4. Fill in the username (for example deploy), a strong password, the real name and a mailbox quota. Leave the mailbox option enabled, otherwise the account is a login-only user with no inbox.
  5. Click Create. Virtualmin creates the Unix user, the home directory and the Dovecot mailbox in one step.

The same task from the shell, useful when you provision many mailboxes at once:

Bash
sudo virtualmin create-user --domain example.com --user deploy --pass 'ChangeMe-Str0ng' --email deploy@example.com

Run virtualmin help create-user on your server to confirm the flags your version accepts before scripting it.

Confirm the mailbox exists:

Bash
sudo doveadm user deploy@example.com
sudo systemctl status postfix dovecot --no-pager

doveadm user should print the account details. If it prints nothing, the account exists as a Unix user but has no mailbox — check the Mailbox settings under Edit Users → deploy.

Edit DNS records in the zone

  1. Select example.com, then open DNS Settings → DNS Records.
  2. The list shows the records Virtualmin created: an A record for the domain, an A record for www, an MX pointing at mail.example.com, and TXT records for SPF and DKIM when mail is enabled.
  3. Click Add Record to create a new entry, or the edit icon next to an existing one. Set the name (shop for shop.example.com, or @ for the root), the type, the value and a TTL.
  4. Save the page. Virtualmin bumps the zone serial and reloads BIND, so the change is live on this server immediately — propagation to resolvers still depends on the old TTL.

Common entries you will add by hand:

shop.example.com.    A     203.0.113.10
example.com.         TXT   "v=spf1 a mx ip4:203.0.113.10 ~all"
_dmarc.example.com.  TXT   "v=DMARC1; p=quarantine; rua=mailto:postmaster@example.com"

Check what your server actually serves before you blame the registrar:

Bash
dig @203.0.113.10 example.com MX +short
dig @203.0.113.10 shop.example.com A +short
sudo systemctl status named --no-pager

On Debian and Ubuntu the service may be called bind9 instead of named. If the local answer is wrong, the problem is in Virtualmin or BIND, not in propagation.

Tip: If your registrar hosts the zone, keep the Virtualmin records as documentation and copy changes to the registrar's panel. Mixing the two — one zone authoritative, the other stale — is the most common cause of "mail works for me but not for my client".

Request a Let's Encrypt certificate

The certificate request needs the domain to resolve to this server and port 80 to be reachable from the internet, because Let's Encrypt validates over HTTP.

  1. Confirm DNS first: dig +short example.com must return 203.0.113.10.
  2. Select the domain, open Server Configuration → SSL Certificate, then the Let's Encrypt tab.
  3. Choose the names to include — normally example.com and www.example.com. Enable the option that copies the certificate to mail and other services if your Virtualmin version offers it, so Dovecot and Postfix present the same certificate.
  4. Accept the terms and click Request Certificate. The request usually finishes in under a minute.

Renewal is scheduled by Virtualmin and runs automatically before expiry; the tab shows the expiry date and the last renewal result. Check the certificate the world sees:

Bash
curl -sI https://example.com | head -n 1
openssl s_client -connect example.com:443 -servername example.com </dev/null 2>/dev/null | openssl x509 -noout -subject -dates

If you changed the certificate for mail as well, tell users to restart their mail client so it picks up the new certificate chain.

Check it works

Run these checks after all three tasks:

  • Mailbox: sudo swaks --to deploy@example.com --server 127.0.0.1 (install swaks if missing), then read /var/log/mail.log (/var/log/maillog on AlmaLinux/Rocky) for a status=sent line.
  • DNS: dig +short MX example.com and dig +short TXT example.com against both 203.0.113.10 and 1.1.1.1 — the answers should match.
  • SSL: the openssl s_client output above should show the correct subject and a notAfter date in the future.
  • Services: sudo ss -tlnp | grep -E ':(25|80|443|993)' should list Postfix, the web server and Dovecot.

Troubleshooting

  • Let's Encrypt fails with "challenge did not succeed" — the domain does not resolve to this server, or port 80 is blocked. Check dig +short example.com, then test from outside with curl -I http://example.com.
  • Mail user cannot log in — Dovecot is stopped, or the login format is wrong. Try the full address deploy@example.com; check systemctl status dovecot and /var/log/mail.log (/var/log/maillog on AlmaLinux/Rocky).
  • DNS change shows locally but nowhere else — the old record is cached for the old TTL. Confirm with dig @1.1.1.1, and wait rather than editing the zone repeatedly.
  • Browser shows the wrong certificate after adding an alias — the alias was added after the certificate was issued. Re-request the certificate with all names selected.
  • Mail lands in spam — SPF or DKIM is missing. Add the DKIM record under Email Settings → DomainKeys Identified Mail, then re-check the TXT records with dig.

Next steps

Was this guide helpful?

Still stuck?

Ask MdmHost AI for a quick answer, or open a ticket and our team will take a look. We are here 24/7.