Skip to content
Infrastructure

Migrating my SMTP relay from Postfix to Mailrise

By Victor Da Luz
mailrise apprise smtp qnap homelab docker

Consolidating homelab alerting with Apprise covers how the whole notification stack fits together. This post zooms in on one narrow piece: swapping Postfix for Mailrise on the QNAP relay.

My QNAP sends alerts over SMTP. I had a small relay on the LAN that accepted mail and forwarded it into Apprise, which fans out to Discord and everything else. The original stack was Postfix in Docker plus a custom Python script that read the message and hit Apprise’s HTTP API.

It worked until it didn’t, repeatedly. The boky/postfix image ships virtual_transport = virtual by default, which meant Postfix ignored my transport_maps and shoved virtual-alias mail down the wrong transport. I tried unsetting it with postconf, but the base image’s config won on reload, so the fix never stuck. Map databases (.lmdb) had to be rebuilt on every container restart, which meant a brittle entrypoint and more moving parts. Every image update was a lottery.

I was spending time fighting Postfix instead of running the lab.

Investigation

I did not need a general-purpose MTA for “receive SMTP, turn it into a webhook-shaped notification.” I needed something that spoke SMTP on one side and Apprise on the other without a pile of maps and transports.

Mailrise is built exactly for that: SMTP in, Apprise out, YAML config, no Postfix archaeology. Self-hosted, no third-party SaaS in the middle.

Solution

I reused the same LXC instead of carving a new VM: stop the Postfix container, remove the old role and scripts, rename the host from smtp-relay.lan to mailrise.lan, update internal DNS, point QNAP at mailrise.lan:25.

Mailrise config stayed boring on purpose: one address mapped to the existing Apprise QNAP endpoint:

configs:
  qnap-alerts@homelab.local:
    apprise_url: 'http://apprise.lan:8080/notify/qnap'

Compose (shape only; pin versions in your own repo): jcberthon/mailrise, config file mounted read-only, network_mode: host or an explicit publish on 25/8025 depending on how you run it, healthcheck against Mailrise’s HTTP health endpoint.

Ansible owns deploy: compose file, templated mailrise.yml, service lifecycle, health check. The old smtp-relay role and iac/services/smtp-relay/ tree went away with the Postfix stack.

Verification

After cutover: Mailrise healthy, QNAP delivers to the new hostname on port 25, Apprise receives the notify URL, Discord shows the alert, restarts do not require manual map rebuilds. That was the bar: reliability over cleverness.

What I tried and rolled back (whitespace)

QNAP’s emails arrive with extra headers, footers, and spacing. I tried a custom Mailrise router (subclass of SimpleRouter, strip everything after Message:, etc.) loaded via import_code. I hit integration friction: typing and imports against Mailrise internals, and apprise:// URLs throwing “Bad Request - Unsupported Parameters” until I started patching Apprise inside the container, which did not survive rebuilds.

After enough iterations, I restored the simple YAML-only config and accepted the noisy formatting. Reliability beats pretty Discord messages for this path.

Lessons learned

  • Pick the tool that matches the job. Postfix is powerful; for SMTP-to-Apprise it was the wrong hammer.
  • When the base image keeps undoing your config, question the approach, not just the next postconf flag.
  • Not every annoyance deserves a fork. I knew when to stop on the custom router.

Related reading

Infrastructure

Self-hosting Backlogia, and fixing it before running it

Backlogia is a self-hosted app that pulls your game libraries from Steam, GOG, Epic and more into one place. Before I would run it I read the code, found four security gaps, and forked it. Then Starlette and a CORS bug had opinions too.

Read
Infrastructure

Researching update automation for the homelab

Twenty-three self-hosted services and no update process beyond "when I remember". I compared Watchtower, Diun, Renovate, and WUD, looked at unattended-upgrades for system packages, and landed on a hybrid plan.

Read

Ready to Transform Your Career?

Let's work together to unlock your potential and achieve your professional goals.