Proxmox SMTP Relay: Alert Email from PVE and Backup Server
Proxmox ships Postfix preconfigured to send alerts from root@pve — an address no receiver will accept. Here's the SMTP relay setup for PVE and PBS, end to end.
Proxmox ships Postfix preconfigured to send alerts from root@pve — an address no receiver will accept. Here's the SMTP relay setup for PVE and PBS, end to end.
A nightly backup job can fail for months without anyone noticing, because every alert it sends dies in transit when there's no Proxmox SMTP relay behind it.
Proxmox does try to tell you. Every notification gets handed to the local Postfix instance, which dutifully tries to deliver a message from root@pve to your Gmail, and Gmail does the only sensible thing with mail from a domain that doesn't exist: drops it on the floor. No bounce you'll ever see. No banner in the web UI. Just a task log with a red X on a page you don't open unless something's already wrong.
Here's what makes Proxmox different from a NAS. It does ship a working mail stack — Postfix installed, running, relaying locally from the moment the installer finishes. Which is worse than shipping nothing, because a missing feature makes you go configure it and a half-working one makes you assume it's fine.
So. Both boxes, PVE and PBS, wired to a relay that delivers.
Backup-job results, ZFS scrub reports, SMART warnings, and replication failures from a Proxmox VE node and a Proxmox Backup Server that:
root@pveThis guide relays through JustEmails — the $49/year plan covers unlimited mailboxes, so a dedicated pve@ address adds nothing. Any authenticated SMTP host works the same way.
Sending has a daily ceiling per account, and it ramps from the day your domain is verified: no more than 50 a day in the first week, 200 in the second, and up to 500 from day 15, with mailbox sends and API sends counted against the same number. Worth knowing before the first retry storm: a replication job that fails on a short interval can push a surprising number of notifications at that ceiling.
One pre-flight check from the node itself, not your laptop:
nc -zv mail.justemails.app 587
If that hangs, egress is blocked and nothing in the UI will save you. Proxmox nodes often sit on a management VLAN with tighter outbound rules than you'd expect.
Create one in the JustEmails dashboard. pve@yourdomain.com, homelab@yourdomain.com, whatever you'll recognize in a filter rule six months from now.
Don't reuse a mailbox you care about. This credential ends up in a world-readable-until-you-chmod-it file on a hypervisor, and the smaller the blast radius the better. Mailboxes are unlimited on the plan, so there's no reason to be frugal.
Note four things:
mail.justemails.app587pve@yourdomain.com, not pveThen check your domain's DNS status in the dashboard and confirm SPF, DKIM, and DMARC all pass. JustEmails generates the records including MTA-STS; your registrar still has to serve them. If you're not at enforcement yet, the DMARC rollout guide covers p=none to p=reject without blackholing your own mail.
This is the step people skip, and it's the one that decides whether any of the rest matters.
Proxmox sets the system mail name to the node's hostname. Not an FQDN you own — the short hostname from the installer. So mail leaves as root@pve, root@pve01, root@hv-basement, take your pick. Look at what a receiver has to work with: a domain with no MX, no SPF record, no DKIM selector, frequently not even a valid public TLD. DMARC checks alignment between the visible From domain and an authenticated identifier, and when that domain is pve there's nothing on either side to align. The message isn't just unsigned. It's structurally unverifiable.
Gmail and Outlook both drop it silently — correct behavior, and the same failure mode that catches cron jobs relaying through the local MTA on any Debian box.
Two places to fix it, and do both:
smtp_generic_maps in Postfix (Step 5) — rewrites senders at the MTA level, catching everything else on the box. ZED, smartd, cron, apt-listchanges, the lot.The notification system doesn't own every process on that machine, and the ones it doesn't own are exactly the ones that mail you about dying disks.
Datacenter → Notifications. You'll see one existing target named mail-to-root and one matcher called default-matcher.
Click Add → SMTP:
| Field | Value |
|---|---|
| Endpoint Name | justemails |
| Server | mail.justemails.app |
| Port | 587 |
| Encryption | STARTTLS |
| Authenticate | checked |
| Username | pve@yourdomain.com |
| Password | your mailbox password |
| From Address | pve@yourdomain.com |
| Recipient(s) | root@pam (sends to that user's Email field) |
| Additional Recipients | any extra inboxes |
Two traps. Username must be the full address — PVE accepts pve without complaint, then fails auth with a message that tells you approximately nothing. And From Address must be on your verified domain: a From address on Gmail, or any domain you don't control, has nothing to align against, which is the root@pve problem all over again.
While you're here: Datacenter → Permissions → Users → root@pam, and put a real inbox in the Email field. The Recipient(s) field resolves through that user, so an empty field means a perfectly configured target that mails nobody.
Hit Test. Should land in a few seconds.
A target is a place to send mail. A matcher decides which events go there. Configure the first without the second and your test email sails through while every real notification keeps going to mail-to-root.
Which is a bad default, and I'll say it plainly: that Test button hands you a green tick for a pipeline that is still broken end to end.
Open default-matcher, repoint it at justemails or add one of your own. The rules are worth ten minutes:
info catches everything including successful backups. warning and above is what I'd normally recommend, with one exception below.type (vzdump, replication, fencing, system-mail) or on specific job IDs.My contrarian take, and plenty of homelab people will disagree: keep successful backup notifications on for the first month. Conventional wisdom says only alert on failure. But a job that stops running — disabled by a UI misclick, orphaned when you renamed a storage — produces no failure notification, because it produces nothing at all. A nightly success email you glance at weekly is the cheapest check on that.
Then kill the noise that trains you to ignore the folder. Package updates, certificate renewals, every info from a healthy replication job.
PBS moves on its own release cadence, and the notification system landed there later than on PVE. Check Configuration → Notifications — if an SMTP target type is offered, the fields match Step 3 and you can skip ahead.
If it isn't, you're configuring Postfix directly. Which is also what you want on a PVE node for the senders the notification system doesn't own.
Open /etc/postfix/main.cf. There's already an empty relayhost = line — edit that one rather than appending a second:
relayhost = [mail.justemails.app]:587
smtp_sasl_auth_enable = yes
smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
smtp_sasl_security_options = noanonymous
smtp_tls_security_level = encrypt
smtp_generic_maps = hash:/etc/postfix/generic
The square brackets matter — they tell Postfix to skip the MX lookup and connect to that host directly.
Create /etc/postfix/sasl_passwd:
[mail.justemails.app]:587 pbs@yourdomain.com:your-mailbox-password
And /etc/postfix/generic, which is the sender rewrite:
root@pbs pbs@yourdomain.com
root@localhost pbs@yourdomain.com
@pbs pbs@yourdomain.com
Swap pbs for your actual hostname — hostname -f if you're unsure. The third line catches anything on the box generating a local sender you didn't anticipate.
Then:
chmod 600 /etc/postfix/sasl_passwd
postmap /etc/postfix/sasl_passwd
postmap /etc/postfix/generic
apt install -y libsasl2-modules bsd-mailx
systemctl reload postfix
chmod first, postmap second — that ordering isn't decoration. The file holds a plaintext mailbox password, and it shouldn't be world-readable even briefly.
libsasl2-modules is the one that bites people. Proxmox's Debian base ships Postfix without the SASL auth plugins, so Postfix opens the connection, finds no mechanism it can offer, and logs SASL authentication failed: no worthy mechs found. Reads like a credential error. Isn't one.
If postmap errors on an unsupported map type — more likely on a Debian 13-based build, where Berkeley DB has been deprecated a while — swap hash: for lmdb: in both main.cf lines and re-run.
Last piece: /etc/aliases. Add root: you@example.com, run newaliases. Without it, mail to local root sits in /var/mail/root until the heat death of the universe.
Test it:
echo "relay test" | mail -s "PBS relay test" you@example.com
tail -f /var/log/mail.log
You want status=sent. Anything else, the log line says why — genuinely specific, a rare pleasure in this line of work.
Two senders that matter don't route through the PVE notification system at all.
ZFS Event Daemon. Scrub results and pool degradation come from ZED, in /etc/zfs/zed.d/zed.rc. Uncomment and set:
ZED_EMAIL_ADDR="root"
ZED_NOTIFY_VERBOSE=1
Then systemctl restart zfs-zed. ZED hands mail to local sendmail, which is why Step 5's Postfix config matters even on a node with a working notification target. Leave ZED_NOTIFY_VERBOSE at 0 and you only hear about scrubs that found errors — except then a scrub that never ran looks exactly like a clean one.
Set it to 1 and leave it there. Strong opinion, and I'll defend it: silence from a storage daemon is not information. A monthly all-clear you barely skim beats an alert channel you've never once seen fire.
smartd. Disk health lives in /etc/smartd.conf. Make sure its DEVICESCAN line carries a mail directive:
DEVICESCAN -a -o on -S on -n standby,q -m root -M exec /usr/share/smartmontools/smartd-runner
-m root is the part that matters. Same Postfix path.
A test email proves the relay works. It doesn't prove the alert pipeline works — different code path, different recipient resolution, and on PBS a different mail system entirely.
Cheapest real test: point a backup job at a storage target you've deliberately unmounted. Job fails, real notification fires down the real path. On ZFS, zpool scrub rpool with verbose ZED notifications on does the same once the scrub finishes.
SASL authentication failed: no worthy mechs found — libsasl2-modules isn't installed. See Step 5. Not a password problem.
535 5.7.8 Authentication credentials invalid — now it's a password problem. Almost always the username missing its domain part, occasionally a trailing space from a paste.
Connection times out on 587 — blocked egress. Test with nc from the node itself. Unsure which port you want, the breakdown of 25, 465, 587, and 993 covers it.
Relay access denied or a rejected sender — your From address isn't on a verified domain, or smtp_generic_maps isn't rewriting. Run postmap -q root@pbs hash:/etc/postfix/generic; it should print your real address.
TLS handshake failures — usually a stale CA bundle. apt install --reinstall ca-certificates fixes most of them.
Mail sends, lands in spam — DNS. Send one to mail-tester.com. Under 7/10 is almost always a DKIM typo or a missing DMARC record.
Test target works, real notifications don't — matcher, not target. Step 4.
pve-01@, pve-02@, pbs@. Costs nothing, makes filtering trivial, lets you revoke one credential without touching the cluster.One gap remains. Neither PVE nor PBS tells you that a notification failed to send anywhere you'd naturally look — you'd have to be tailing /var/log/mail.log, and nobody does that unprompted. A quarterly test email is the closest thing to a safety net, and the missing warning is how a backup job goes months unnoticed.
Because the default sender is root@pve (or root@ whatever your hostname is), and that domain doesn't exist in public DNS. No SPF record to check, no DKIM key to verify, so DMARC has nothing to align against and receivers treat the message as forged. The fix is rewriting the sender to an address on a domain you own — smtp_generic_maps in Postfix, or the From Address field on the SMTP notification target in PVE.
Go to Datacenter → Notifications, add a target of type SMTP, and fill in mail.justemails.app, port 587, STARTTLS, your full mailbox address as the username, and a From Address on your verified domain. Then repoint the existing default matcher at the new target, or add your own. Setting the target without wiring a matcher to it is the most common reason nothing sends.
PBS is a separate product on its own release cadence, and the notification system landed there later than in PVE. On older PBS builds there's no SMTP target in the UI at all — mail goes out through local Postfix, so you configure the relay in /etc/postfix/main.cf with a hash or lmdb sasl_passwd map. Check Configuration → Notifications first; if the SMTP option is there, use it.
The libsasl2-modules package isn't installed. Proxmox's minimal Debian base ships Postfix without the SASL auth plugins, so Postfix advertises no mechanism it can use and the login never happens. Run apt install libsasl2-modules, then systemctl reload postfix. It's not a password problem — retyping the credential won't fix it.
Unlimited custom domain email hosting for $49/year flat — unlimited domains, unlimited mailboxes, 10 GB storage, full IMAP/SMTP. Built for agencies, freelancers, and anyone managing email across more than one domain.