Skip to content

Self-hosted Authentik via Posthorn

You’re running Authentik as your identity provider. Authentik sends email for account verification, password recovery, and MFA enrollment. On a cloud VPS that blocks outbound SMTP, or when you simply don’t want to hand Authentik your provider credentials, Posthorn’s SMTP listener accepts Authentik’s connection on a private Docker network and forwards over HTTPS to whichever transactional provider you’ve chosen.

At the end: Authentik points its email settings at posthorn:2525 over a private Docker network — no TLS, no AUTH — and Posthorn forwards via the configured HTTP transport to Postmark, Resend, Mailgun, or SES.

Docker hostPostmark · ResendMailgun · SESAuthentik(server + worker)PosthornSMTP listener (auth=none) SMTP on posthorn:2525(internal network)HTTPS

Only the Authentik worker sends mail, but pointing both server and worker at Posthorn is simplest and harmless.

  1. Put Posthorn and Authentik on the same private Docker network (no ports: exposure for Posthorn):

    # docker-compose.yml (excerpt)
    networks:
    internal:
    internal: true
    services:
    posthorn:
    image: ghcr.io/craigmccaskill/posthorn:latest
    restart: unless-stopped
    volumes:
    - ./posthorn.toml:/etc/posthorn/config.toml:ro # Podman/SELinux: append ,Z
    env_file: .env
    networks: [internal]
    # no ports: — reachable only from inside the network
  2. Write posthorn.toml.

    [smtp_listener]
    listen = ":2525"
    auth_required = "none"
    require_tls = false
    trusted_network = true # asserts the Docker network is the trust boundary (#41)
    allowed_senders = ["*@yourdomain.com"]
    [smtp_listener.transport]
    type = "postmark"
    [smtp_listener.transport.settings]
    api_key = "${env.POSTMARK_API_KEY}"
  3. Point Authentik at Posthorn via environment (applies to both server and worker):

    environment:
    AUTHENTIK_EMAIL__HOST: posthorn
    AUTHENTIK_EMAIL__PORT: "2525"
    AUTHENTIK_EMAIL__USE_TLS: "false"
    AUTHENTIK_EMAIL__USE_SSL: "false"
    AUTHENTIK_EMAIL__FROM: "authentik@yourdomain.com"
    # AUTHENTIK_EMAIL__USERNAME / __PASSWORD intentionally unset
  4. Start the stack and test. In the Authentik admin interface, use System → Settings → Test email (or trigger a password recovery). Posthorn logs the session:

    {"msg":"smtp_session_open","ingress":"smtp"}
    {"msg":"smtp_submission_sent","transport_message_id":"..."}
SymptomCauseFix
Authentik logs a TLS handshake errorAUTHENTIK_EMAIL__USE_TLS / USE_SSL still trueSet both to false; the listener runs plaintext on the internal network
550 5.7.1 Sender not authorizedAUTHENTIK_EMAIL__FROM isn’t on allowed_sendersAdd the address (or a *@domain wildcard)
Posthorn won’t start: auth_required = "none" refusedMissing the trust ackAdd trusted_network = true, and keep the listener off any host port

See Internal SMTP relay for the full reasoning on the auth-none + private-network model.