Deployment
Deploy to Hetzner and Vercel.
Deployment
Architecture Overview
| Component | Platform | Cost |
|---|---|---|
| API + Mail Server + MCP | Hetzner CX22 (Docker) | ~$5/mo |
| Dashboard | Vercel | Free |
| Database | Neon PostgreSQL | Free tier |
| Outbound Email | AWS 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 Lumbox3. Configure Environment
cp .env.example .envEdit .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=30024. Build and Deploy
cd apps/mail-server
docker compose up -d --buildThis 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 nginxVercel (Dashboard)
Deploy
cd apps/web-new
vercelOr 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:
| Variable | Value |
|---|---|
DATABASE_URL | Neon connection string |
BETTER_AUTH_SECRET | Random secret for auth |
NEXT_PUBLIC_API_URL | https://api.lumbox.co |
Neon (Database)
- Create a free project at neon.tech
- Copy the connection string
- Set
DATABASE_URLin all environments - Push schema:
cd apps/api && DATABASE_URL="..." bun run db:push
AWS SES (Outbound Email)
- Create an IAM user with
AmazonSESFullAccess - Verify your sending domain in SES console
- Request production access (to send to unverified addresses)
- Set
AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_REGIONin.env
DNS Records
For lumbox.co (or your domain):
| Type | Name | Value | Purpose |
|---|---|---|---|
| A | api | <hetzner-ip> | API server |
| A | mcp | <hetzner-ip> | MCP HTTP server |
| CNAME | app | cname.vercel-dns.com | Dashboard |
| MX | @ | mail.lumbox.co (priority 10) | Inbound email |
| A | mail | <hetzner-ip> | Mail server |
| TXT | @ | v=spf1 include:amazonses.com ~all | SPF 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
| Variable | Required | Default | Description |
|---|---|---|---|
DATABASE_URL | Yes | — | PostgreSQL connection string |
DEFAULT_DOMAIN | No | lumbox.co | Default domain for new inboxes |
INBOUND_SECRET | Yes | — | Authenticates mail server → API |
ENCRYPTION_KEY | Yes | — | 32-byte hex for SMTP credential encryption |
PORT | No | 3000 | API server port |
MCP_PORT | No | 3002 | MCP HTTP server port |
DEFAULT_EMAIL_PROVIDER | No | RESEND | Fallback outbound provider |
RESEND_API_KEY | No | — | Resend API key |
AWS_ACCESS_KEY_ID | No | — | AWS SES access key |
AWS_SECRET_ACCESS_KEY | No | — | AWS SES secret key |
AWS_REGION | No | us-east-1 | AWS region |
CORS_ORIGINS | No | * | Allowed CORS origins |
RATE_LIMIT_RPM | No | 120 | Requests per minute per API key |