Deployment Guide¶
Dreadnought runs anywhere Docker runs. Pick the deployment method that fits your environment.
Choosing a Method¶
| Method | Best for | Difficulty | Auto HTTPS? |
|---|---|---|---|
| Docker Desktop | Windows / macOS local development or home use | Beginner | No |
| Docker Compose — Linux/VPS | Linux server, cloud VPS, home server | Beginner | No (add reverse proxy) |
| Docker Compose — Raspberry Pi | Raspberry Pi at home | Beginner | No (add reverse proxy) |
| Manual Dockerfile Build | Custom pipelines, CI/CD, image registries | Intermediate | No |
| Coolify | Cloud VPS with easy management UI | Beginner | Yes |
| Portainer | Teams already using Portainer for Docker management | Beginner | No (depends on setup) |
| Bare Metal — Systemd | Environments where Docker isn't available | Advanced | No (add reverse proxy) |
Add a reverse proxy for HTTPS access: - Nginx — battle-tested, widely supported - Traefik — Docker-native, automatic TLS - Caddy — simplest automatic HTTPS
What Gets Deployed¶
Regardless of method, you'll always end up with these three components:
┌─────────────────────────────────────────────────────────┐
│ api FastAPI backend Port 8081 (host) │
│ worker APScheduler No exposed port │
│ web Next.js frontend Port 8082 (host) │
└─────────────────────────────────────────────────────────┘
And one persistent data directory:
./data/ddns.db ← SQLite database (all your data lives here)
The Key Variable: NEXT_PUBLIC_API_URL¶
Every deployment method has one potential gotcha: NEXT_PUBLIC_API_URL.
This variable tells the browser (not the server) where to find the API. The default is http://localhost:8081, which only works when your browser and the app are on the same machine.
| Scenario | What to set |
|---|---|
| Accessing from the same machine | http://localhost:8081 |
| Accessing from another device on your LAN | http://192.168.1.x:8081 (your server's LAN IP) |
| Behind a reverse proxy with a domain | https://ddns-api.yourdomain.com |
If you don't set this correctly, the UI will load but all API calls will fail.
Network Architecture¶
Internet
│
▼
Reverse Proxy (Nginx / Traefik / Caddy) ← Only needed for HTTPS/public access
│
├── ddns.yourdomain.com ──► port 8082 (web container, port 3000 internally)
│
└── ddns-api.yourdomain.com ──► port 8081 (api container, port 8000 internally)
worker container (no port, internal only)
├── Reads/writes SQLite at /data
└── Calls Cloudflare API + IP detection services outbound
For local / LAN use, you don't need a reverse proxy. Access the UI directly at http://server-ip:8082.
For public HTTPS access, put a reverse proxy in front and follow one of the reverse proxy guides.
Data Persistence¶
All application state lives in one SQLite file:
./data/ddns.db
This file is mounted into all three containers via Docker volume. As long as you don't delete ./data, your data survives:
- Container restarts
- Image rebuilds
- docker compose down and up cycles
- Application updates
Do not delete ./data unless you intend to start fresh.
Port Reference¶
| Service | Host Port | Container Port | Purpose |
|---|---|---|---|
api |
8081 |
8000 |
REST API, health check |
web |
8082 |
3000 |
Next.js frontend |
worker |
— | — | Background worker, no HTTP |
To change the host ports (if 8081/8082 conflict with something else), edit docker-compose.yml:
ports:
- "9001:8000" # Change 9001 to whatever you want
Health Checks¶
Both api and web have Docker health checks configured:
# Check all service statuses
docker compose ps
# Manually test the API health endpoint
curl http://localhost:8081/health
A healthy API response:
{"status": "ok"}