Skip to content

Installation

Posthorn ships in three forms. Docker is the recommended path for most operators — it’s a single container running next to your apps, and it’s the deployment shape that’s exercised most heavily in tests and documentation.

Terminal window
docker pull ghcr.io/craigmccaskill/posthorn:latest

Multi-arch images are published for linux/amd64 and linux/arm64. The container expects a TOML config mounted at /etc/posthorn/config.toml and listens on 8080 by default.

A minimal docker-compose.yml:

services:
posthorn:
image: ghcr.io/craigmccaskill/posthorn:latest
restart: unless-stopped
volumes:
- ./posthorn.toml:/etc/posthorn/config.toml:ro
environment:
POSTMARK_API_KEY: ${POSTMARK_API_KEY}
ports:
- "8080:8080"

Continue to the Quick start for a working contact form.

Regardless of how you install Posthorn, you need:

PrerequisiteWhy
A Postmark account with a verified sender domainPosthorn relays through Postmark’s HTTP API
A Postmark server token (not the account token)Used as ${env.POSTMARK_API_KEY}
SPF, DKIM, and DMARC records on your sending domainRequired for deliverability — see DNS
A reverse proxy in front of Posthorn (Caddy, nginx, Traefik, Cloudflare)TLS termination, HTTP/2, request logging
Terminal window
docker run --rm ghcr.io/craigmccaskill/posthorn:latest --version
# posthorn v1.0.0

If you’re running the standalone binary:

Terminal window
posthorn --version

For a deeper sanity check, run posthorn validate --config <your-config> — it parses the TOML, resolves ${env.VAR} placeholders, and reports schema errors without starting the listener.