Guides15 min read

Self-hosting Programmable Inbox: a complete guide

Everything you need to deploy Programmable Inbox on your own server, from DNS setup to TLS termination and SMTP configuration.

AR

Alex Rivera

Co-founder · July 8, 2025

The self-hosted version of Programmable Inbox is a first-class product. This guide covers everything from DNS configuration to production hardening.

Prerequisites

  • A Linux server (Ubuntu 22.04 recommended) with at least 1 vCPU and 1 GB RAM
  • A domain you control (e.g. inbox.yourdomain.com)
  • Docker and Docker Compose installed

Step 1: DNS

You'll need two records:

TypeNameValue
MX`@` or subdomain`mail.inbox.yourdomain.com` (priority 10)
A`mail.inbox.yourdomain.com`Your server IP

Also add an SPF record to improve deliverability:

TXT @ "v=spf1 ip4:YOUR_SERVER_IP ~all"

Step 2: Clone and configure

bash
git clone https://github.com/programmable-inbox/inbox
cd inbox
cp .env.example .env

Edit .env:

bash
DOMAIN=inbox.yourdomain.com
SMTP_HOSTNAME=mail.inbox.yourdomain.com
API_SECRET=your-random-secret-here

Step 3: TLS

We use Caddy for automatic TLS via Let's Encrypt. Just make sure port 80 and 443 are open on your server — Caddy handles the rest.

Step 4: Start the stack

bash
docker compose -f docker-compose.prod.yml up -d

The stack includes:

  • smtp — Haraka-based SMTP server
  • api — REST API server
  • worker — Webhook delivery queue
  • caddy — Reverse proxy + TLS
  • postgres — Message store
  • redis — Queue backend

Step 5: Verify

Send a test email to [email protected] and check the API:

bash
curl https://inbox.yourdomain.com/api/health
# {"status":"ok","version":"0.3.1"}

Production hardening

A few things to do before handling real traffic:

  • Set SMTP_MAX_MESSAGE_SIZE (default 10 MB)
  • Configure fail2ban for SMTP brute-force protection
  • Enable Postgres daily backups
  • Set up Uptime monitoring on /api/health

The full configuration reference is in the repo's docs/ directory.