Archived
Update README production setup
This commit is contained in:
1 parent
30aef1fee8
commit
9f5cee8a0e
1 file changed
+53
-18
@@ -2,7 +2,7 @@
|
||||
|
||||
**Self-hosted Dynamic DNS (DynDNS / DDNS) for FRITZ!Box, OpenWrt, pfSense, OPNsense, UniFi, MikroTik, Linux cron jobs, and any router that can call a custom DDNS update URL.**
|
||||
|
||||
KarlDNS is the friendly name for `karldns`: a small FastAPI Dynamic DNS provider you can run on your own VPS. It gives users accountless private update URLs, FRITZ!Box-ready DynDNS fields, public A/AAAA records through Cloudflare or RFC 2136, and generated hostnames that also work as CNAME targets for user-owned domains.
|
||||
KarlDNS is the friendly name for `karldns`: a small FastAPI Dynamic DNS provider you can run on a VPS, VM, or LXC. It gives users private bearer update URLs, FRITZ!Box-ready DynDNS fields, public A/AAAA records through Cloudflare or RFC 2136, and generated hostnames that also work as CNAME targets for user-owned domains.
|
||||
|
||||
If you want a lightweight DuckDNS / Dynu / No-IP style service that you control yourself, KarlDNS is built for that use case.
|
||||
|
||||
@@ -13,7 +13,7 @@ If you want a lightweight DuckDNS / Dynu / No-IP style service that you control
|
||||
- **Self-hosted Dynamic DNS provider** for home labs, small ISPs, communities, and private infrastructure.
|
||||
- **FRITZ!Box compatible**: copy the generated `Update-URL` and `Domainnamen` straight into the German FRITZ!Box DynDNS form.
|
||||
- **CNAME-friendly hostnames**: users can use the generated hostname directly, or point `home.example.com` to it with a CNAME.
|
||||
- **No registration required**: generated hostnames use private bearer links, with no accounts or login flow.
|
||||
- **No user accounts required**: generated hostnames use private bearer links instead of a login flow.
|
||||
- **CNAME alias support**: users create one KarlDNS hostname, then point `home.example.com` to it at their own DNS provider.
|
||||
- **Real DNS publishing** through **Cloudflare** or **RFC 2136** with A and AAAA support.
|
||||
- **Small-server friendly**: FastAPI, SQLite WAL, simple Docker deployment, and no heavy background platform.
|
||||
@@ -73,7 +73,7 @@ That means users always have a current hostname for VPN, remote access, self-hos
|
||||
| Persistence | SQLite with WAL mode |
|
||||
| API | FastAPI, small API docs page, public OpenAPI JSON |
|
||||
| Auth model | No user accounts. Private bearer links for hostnames and dashboards |
|
||||
| Operations | Rate limiting, admin audit views, update logs, cleanup jobs, Docker, Caddy example |
|
||||
| Operations | Rate limiting, admin audit views, update logs, cleanup jobs, Docker, reverse-proxy friendly deployment |
|
||||
|
||||
## Quick Start
|
||||
|
||||
@@ -110,23 +110,58 @@ The API guide and OpenAPI JSON document the user and router endpoints only. Admi
|
||||
|
||||
## Production Setup
|
||||
|
||||
For an internet-facing DynDNS service, run behind HTTPS and require a real DNS backend:
|
||||
For an internet-facing DynDNS service, run behind HTTPS and require a real DNS backend. The normal production shape is:
|
||||
|
||||
```bash
|
||||
export DDNS_ADMIN_PASSWORD='replace-with-a-long-random-value'
|
||||
export DDNS_ADMIN_PATH='/admin'
|
||||
export DDNS_DASHBOARD_COOKIE_SECRET='replace-with-a-32-plus-character-random-value'
|
||||
export DDNS_PUBLIC_BASE_URL='https://karldns.de'
|
||||
export DDNS_HOSTNAME_SUFFIX='karldns.de'
|
||||
export DDNS_DATABASE='/data/ddns.sqlite3'
|
||||
export DDNS_REQUIRE_DNS_PROVIDER=1
|
||||
export DDNS_DNS_PROVIDER='cloudflare'
|
||||
export DDNS_CLOUDFLARE_API_TOKEN='replace-with-cloudflare-token'
|
||||
export DDNS_CLOUDFLARE_ZONE_ID='replace-with-cloudflare-zone-id'
|
||||
export DDNS_TTL=60
|
||||
```text
|
||||
Cloudflare DNS
|
||||
-> HTTPS reverse proxy
|
||||
-> KarlDNS on port 8080
|
||||
-> SQLite database at /data/ddns.sqlite3
|
||||
```
|
||||
|
||||
That is the normal Cloudflare setup. Use a least-privilege Cloudflare API token limited to the zone KarlDNS should update. `DDNS_TRUSTED_HOSTS` is optional because KarlDNS automatically trusts the host in `DDNS_PUBLIC_BASE_URL`; set it only when the same instance should answer for additional public hostnames.
|
||||
KarlDNS works well in a small VPS, VM, or Proxmox LXC. The current public `karldns.de` deployment runs in an Alpine LXC on Proxmox, with Docker Compose in `/opt/karldns` and Nginx Proxy Manager forwarding HTTPS traffic to the app.
|
||||
|
||||
Create `.env` from the example and replace every placeholder:
|
||||
|
||||
```bash
|
||||
cp .env.example .env
|
||||
docker compose up -d --build
|
||||
```
|
||||
|
||||
Minimum Cloudflare production settings:
|
||||
|
||||
```env
|
||||
DDNS_ADMIN_PASSWORD=replace-with-a-long-random-value
|
||||
DDNS_ADMIN_PATH=/admin
|
||||
DDNS_DASHBOARD_COOKIE_SECRET=replace-with-a-32-plus-character-random-value
|
||||
DDNS_PUBLIC_BASE_URL=https://karldns.de
|
||||
DDNS_HOSTNAME_SUFFIX=karldns.de
|
||||
DDNS_DATABASE=/data/ddns.sqlite3
|
||||
DDNS_REQUIRE_DNS_PROVIDER=1
|
||||
DDNS_DNS_PROVIDER=cloudflare
|
||||
DDNS_CLOUDFLARE_API_TOKEN=replace-with-cloudflare-token
|
||||
DDNS_CLOUDFLARE_ZONE_ID=replace-with-cloudflare-zone-id
|
||||
DDNS_TTL=60
|
||||
```
|
||||
|
||||
Use a least-privilege Cloudflare API token limited to the zone KarlDNS should update. `DDNS_TRUSTED_HOSTS` is optional because KarlDNS automatically trusts the host in `DDNS_PUBLIC_BASE_URL`; set it only when the same instance should answer for additional public hostnames.
|
||||
|
||||
On Alpine hosts, keep Docker enabled with OpenRC:
|
||||
|
||||
```bash
|
||||
rc-service docker status
|
||||
rc-service docker start
|
||||
rc-update add docker default
|
||||
```
|
||||
|
||||
Common production commands:
|
||||
|
||||
```bash
|
||||
cd /opt/karldns
|
||||
docker compose ps
|
||||
docker compose logs -f karldns
|
||||
docker compose restart karldns
|
||||
```
|
||||
|
||||
### RFC 2136 DNS Backend
|
||||
|
||||
@@ -325,7 +360,7 @@ The image uses the current Python 3.14 Alpine base image and installs production
|
||||
|
||||
The default container command runs one Uvicorn worker. Keep that deployment shape unless you have tested multi-worker update behavior for your traffic pattern; rate-limit counters and per-host update locks are process-local.
|
||||
|
||||
`Caddyfile.example` contains a minimal HTTPS reverse proxy example.
|
||||
`Caddyfile.example` contains a minimal HTTPS reverse proxy example. Production can use Caddy, Nginx, Nginx Proxy Manager, Traefik, or another reverse proxy as long as HTTPS, trusted hosts, forwarded headers, and access logs are configured carefully.
|
||||
|
||||
## Operations Checklist
|
||||
|
||||
|
||||
Reference in new issue
Block a user