Introduce a Woodpecker CI/CD pipeline in `.woodpecker.yml` for automated deployment on pushes to the main branch. Add new components for visualizing campaign performance, including `DailyPerformanceChart`, `InboxPlacementChart`, and `InboxVsSpamChart`, to enhance the Campaign Detail page. Update `WarmupPlanChart` to include additional metrics and improve tooltip information. Enhance utility functions for chart data formatting and daily statistics mapping.
5.5 KiB
Deploy Warmbox with Nginx Proxy Manager (Docker)
Warmbox runs as one container on your existing npm_network. Nginx Proxy Manager (NPM) terminates HTTPS and forwards to http://warmbox:3000.
Internet → warmbox.jonnyn.com (DNS) → NPM :443 → warmbox:3000 (Docker network)
No host port is published. Warmbox can run alongside homepage on host port 3000 — they do not conflict.
Prerequisites
- Ubuntu server with Docker + Compose v2
- Nginx Proxy Manager already running on Docker network
npm_network - DNS A record:
warmbox.jonnyn.com→ your home public IP - Router forwards 80 and 443 to NPM (if not already)
Confirm NPM’s network name:
docker network ls | grep npm
docker inspect <npm-container-name> --format '{{json .NetworkSettings.Networks}}' | jq
If your network is not npm_network, edit networks.default.name in docker-compose.yml.
1. Clone and configure
cd /srv/docker-configs/warmbox # or your path
git pull # get latest docker-compose.yml
cp .env.example .env
nano .env
Required variables:
ENCRYPTION_KEY=<openssl rand -hex 32> # never change after first deploy
API_KEY=<openssl rand -hex 24> # dashboard login
PUBLIC_BASE_URL=https://warmbox.jonnyn.com
AI_API_KEY=sk-or-v1-...
Migrating from your Mac: use the same ENCRYPTION_KEY and copy prisma/dev.db (see §6).
2. Start Warmbox
cd /srv/docker-configs/warmbox
# Stop any old stack (including previous compose overrides)
docker compose down
# Build and start — joins npm_network automatically
docker compose up -d --build
Verify:
docker compose ps
docker compose logs -f warmbox
Warmbox should be healthy. Check it is on npm_network:
docker inspect warmbox --format '{{range $k,$v := .NetworkSettings.Networks}}{{$k}} {{end}}'
# should include: npm_network
Test from another container on the same network (e.g. NPM):
docker exec -it <npm-app-container> wget -qO- http://warmbox:3000/health
# expect: {"status":"ok"}
3. Nginx Proxy Manager — proxy host
Open NPM UI (usually http://<server-ip>:81).
Hosts → Proxy Hosts → Add Proxy Host
| Tab / field | Value |
|---|---|
| Domain names | warmbox.jonnyn.com |
| Scheme | http |
| Forward hostname / IP | warmbox |
| Forward port | 3000 |
| Cache assets | off |
| Block common exploits | on |
| Websockets support | on |
SSL tab:
- SSL Certificate: Request a new Let's Encrypt certificate
- Force SSL: on
- HTTP/2: on
If Cloudflare proxies your A record (orange cloud), set Cloudflare SSL mode to Full or Full (strict).
Save, then test:
curl -s https://warmbox.jonnyn.com/health
4. Dashboard login
- Open
https://warmbox.jonnyn.com - Enter
API_KEYfrom.env - Leave Base URL empty (same origin in production)
5. OAuth redirect URIs
Update in Google Cloud / Azure if you use these integrations:
| Integration | Redirect URI |
|---|---|
| Google Postmaster | https://warmbox.jonnyn.com/api/integrations/google/callback |
| Microsoft Outlook | https://warmbox.jonnyn.com/api/integrations/microsoft/callback |
6. Migrate local database (optional)
# On your Mac
scp prisma/dev.db jonnyn@burke:/tmp/warmbox.db
# On server
cd /srv/docker-configs/warmbox
docker compose down
docker run --rm -v warmbox_warmbox-data:/data -v /tmp:/backup alpine \
cp /backup/warmbox.db /data/warmbox.db
docker compose up -d
Use the same ENCRYPTION_KEY as on your Mac.
7. Day-to-day commands
cd /srv/docker-configs/warmbox
docker compose logs -f warmbox # live logs
docker compose up -d --build # rebuild after git pull
docker compose down # stop
docker compose restart warmbox # restart app only
# Backup SQLite
docker compose exec warmbox sh -c 'cp /data/warmbox.db /data/warmbox-$(date +%F).db'
Troubleshooting
port 3000 already allocated
Your docker-compose.yml must not have a ports: section under warmbox:
grep ports docker-compose.yml
# should return nothing (or only comments)
Warmbox uses port 3000 inside the container only. homepage on host 0.0.0.0:3000 is unrelated.
NPM 502 Bad Gateway
- Warmbox running and healthy:
docker compose ps - On
npm_network:docker inspect warmbox --format '{{json .NetworkSettings.Networks}}' - NPM forward host is
warmbox(notlocalhost, not127.0.0.1) - NPM forward port is
3000 - Logs:
docker compose logs warmbox
network npm_network not found
Create it or fix the name to match NPM:
docker network ls
# edit docker-compose.yml → networks.default.name
Login fails
API_KEYin.envmust match what you type- Restart after
.envchange:docker compose up -d --force-recreate
Container unhealthy
docker compose logs warmbox
Common causes: missing ENCRYPTION_KEY, bad DATABASE_URL, migration error.
Why only npm_network?
NPM and Warmbox must share a Docker network so NPM can resolve the hostname warmbox. A separate warmbox_internal network is unnecessary for this setup — one external network is enough.
See also self-host-hardening.md.
CI/CD (Woodpecker)
Push to main on Forgejo → automatic deploy. See deploy-ci-cd.md.