Lumbox Docs

Deployment

Deploy to Hetzner and Vercel.

Deployment

Architecture Overview

ComponentPlatformCost
API + Mail Server + MCPHetzner CX22 (Docker)~$5/mo
DashboardVercelFree
DatabaseNeon PostgreSQLFree tier
Outbound EmailAWS SES$0.10/1k emails

Hetzner (API + Mail Server + MCP)

All backend services run via Docker Compose on a single Hetzner VPS.

1. Provision Server

  • Hetzner CX22 (2 vCPU, 4 GB RAM) or larger
  • Ubuntu 22.04
  • Ensure port 25 is unblocked (submit Hetzner support ticket — they block SMTP by default)

2. Install Dependencies

# Docker
curl -fsSL https://get.docker.com | sh

# Clone repo
git clone https://github.com/Lumbox/Lumbox.git
cd Lumbox

3. Configure Environment

cp .env.example .env

Edit .env:

DATABASE_URL="postgresql://user:pass@ep-xxx.us-east-2.aws.neon.tech/lumbox?sslmode=require"
DEFAULT_DOMAIN="lumbox.co"
INBOUND_SECRET="generate-a-random-secret"
ENCRYPTION_KEY="generate-32-byte-hex"
DEFAULT_EMAIL_PROVIDER="SES"
AWS_ACCESS_KEY_ID="AKIA..."
AWS_SECRET_ACCESS_KEY="..."
AWS_REGION="us-east-1"
MCP_PORT=3002

4. Build and Deploy

cd apps/mail-server
docker compose up -d --build

This starts:

  • API on port 3000
  • Haraka mail server on port 25
  • MCP HTTP server on port 3002

5. Reverse Proxy (nginx)

# /etc/nginx/sites-available/lumbox
server {
    listen 443 ssl;
    server_name api.lumbox.co;

    ssl_certificate /etc/letsencrypt/live/api.lumbox.co/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.lumbox.co/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}

server {
    listen 443 ssl;
    server_name mcp.lumbox.co;

    ssl_certificate /etc/letsencrypt/live/mcp.lumbox.co/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/mcp.lumbox.co/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:3002;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header Connection '';
        proxy_http_version 1.1;
        chunked_transfer_encoding off;
        proxy_buffering off;
        proxy_cache off;
    }
}
sudo certbot --nginx -d api.lumbox.co -d mcp.lumbox.co
sudo systemctl reload nginx

Vercel (Dashboard)

Deploy

cd apps/web-new
vercel

Or connect the GitHub repo to Vercel and set:

  • Root Directory: apps/web-new
  • Framework: Next.js
  • Build Command: bun run build

Environment Variables

Set in Vercel dashboard:

VariableValue
DATABASE_URLNeon connection string
BETTER_AUTH_SECRETRandom secret for auth
NEXT_PUBLIC_API_URLhttps://api.lumbox.co

Neon (Database)

  1. Create a free project at neon.tech
  2. Copy the connection string
  3. Set DATABASE_URL in all environments
  4. Push schema: cd apps/api && DATABASE_URL="..." bun run db:push

AWS SES (Outbound Email)

  1. Create an IAM user with AmazonSESFullAccess
  2. Verify your sending domain in SES console
  3. Request production access (to send to unverified addresses)
  4. Set AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION in .env

DNS Records

For lumbox.co (or your domain):

TypeNameValuePurpose
Aapi<hetzner-ip>API server
Amcp<hetzner-ip>MCP HTTP server
CNAMEappcname.vercel-dns.comDashboard
MX@mail.lumbox.co (priority 10)Inbound email
Amail<hetzner-ip>Mail server
TXT@v=spf1 include:amazonses.com ~allSPF for outbound

Port 25

Hetzner blocks port 25 by default. Submit a support ticket requesting SMTP unblock for legitimate transactional email. Include:

  • Your use case (email-as-a-service for AI agents)
  • That you'll comply with anti-spam policies
  • Your domain and expected volume

Turnaround is usually 1-2 business days.

Environment Variables Reference

VariableRequiredDefaultDescription
DATABASE_URLYesPostgreSQL connection string
DEFAULT_DOMAINNolumbox.coDefault domain for new inboxes
INBOUND_SECRETYesAuthenticates mail server → API
ENCRYPTION_KEYYes32-byte hex for SMTP credential encryption
PORTNo3000API server port
MCP_PORTNo3002MCP HTTP server port
DEFAULT_EMAIL_PROVIDERNoRESENDFallback outbound provider
RESEND_API_KEYNoResend API key
AWS_ACCESS_KEY_IDNoAWS SES access key
AWS_SECRET_ACCESS_KEYNoAWS SES secret key
AWS_REGIONNous-east-1AWS region
CORS_ORIGINSNo*Allowed CORS origins
RATE_LIMIT_RPMNo120Requests per minute per API key