all repos — website @ hugo

My website

content/post/postfix-as-null-client-with-external-catchall.md (view raw)


title: ‘Postfix on a NixOS null client with external catch-all’ date: 2020-09-11T18:49:00+02:00

Tags: [“development”,“git”,“nixos”]

I wanted to set up a server so that any local email (e.g. generated by cron jobs/systemd timers) would be forwarded to an external address, regardless of the user. I also wanted the from address to keep the system hostname whilst not allowing any external use of the mailserver.

It took me a while to figure out how to this, so I thought I’d share my method.

Here’s the config that can be used to do this on any NixOS host, after redefining the first two variables.

services.postfix = let
  localUser = "example-user";
  forwardingAddress = "user@external.domain";
in
{
  enable = true;
  destination = [];
  domain = config.networking.domain;
  virtual = ''
    @${config.networking.hostName}.${config.networking.domain} ${localUser}
    ${localUser} ${forwardingAddress}
  '';
  config = {
    inet_interfaces = "loopback-only";
  };
};

Emails to any user without a domain part are all sent to the forwarding address with a clear from address (e.g. System administrator <root@host.example.com>).

Background

First, the basic setup for a null client can be found in the postfix documentation. The example config would be translated into NixOS like so:

services.postfix = {
  enable = true;
  destination = [];
  domain = config.networking.domain;
  origin = config.networking.domain;
  relayHost = config.networking.domain;
  lookupMX = true;
  config = {
    inet_interfaces = "loopback-only";
  };
};

However, this rewrites user\@hostname.example.com to user\@example.com (due to origin on line 5). I wanted to be able to see which host a mail concerns.