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
- Log in at
https://203.0.113.10:10000asroot. - Select
example.comin the domain dropdown. - Open Edit Users, then click Add a user to this server.
- 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. - 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:
sudo virtualmin create-user --domain example.com --user deploy --pass 'ChangeMe-Str0ng' --email deploy@example.comRun virtualmin help create-user on your server to confirm the flags your version accepts before scripting it.
Confirm the mailbox exists:
sudo doveadm user deploy@example.com
sudo systemctl status postfix dovecot --no-pagerdoveadm 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
- Select
example.com, then open DNS Settings → DNS Records. - The list shows the records Virtualmin created: an A record for the domain, an A record for
www, an MX pointing atmail.example.com, and TXT records for SPF and DKIM when mail is enabled. - Click Add Record to create a new entry, or the edit icon next to an existing one. Set the name (
shopforshop.example.com, or@for the root), the type, the value and a TTL. - 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:
dig @203.0.113.10 example.com MX +short
dig @203.0.113.10 shop.example.com A +short
sudo systemctl status named --no-pagerOn 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.
- Confirm DNS first:
dig +short example.commust return203.0.113.10. - Select the domain, open Server Configuration → SSL Certificate, then the Let's Encrypt tab.
- Choose the names to include — normally
example.comandwww.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. - 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:
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 -datesIf 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(installswaksif missing), then read/var/log/mail.log(/var/log/maillogon AlmaLinux/Rocky) for astatus=sentline. - DNS:
dig +short MX example.comanddig +short TXT example.comagainst both203.0.113.10and1.1.1.1— the answers should match. - SSL: the
openssl s_clientoutput above should show the correct subject and anotAfterdate 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 withcurl -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; checksystemctl status dovecotand/var/log/mail.log(/var/log/maillogon 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
- HestiaCP: add a domain, DNS zone and mail domain if you compare panels.
- Secure Nginx with a free Let's Encrypt SSL certificate for the manual certificate workflow.
- Set your server hostname and reverse DNS so outgoing mail passes reputation checks.
- Get email or Telegram alerts when Fail2ban bans an IP to keep an eye on a mail-facing server.
