Skip to content

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"}