Automatic DNS failover driven by health checks. When the primary IP becomes unreachable, the DNS record is swapped to a backup IP — and swapped back automatically when the primary recovers.
- Multiple DNS providers: Cloudflare, Huawei Cloud DNS (extensible)
- Multiple check methods: ICMP ping, TCP ping, HTTP(S)
- Failure / recovery thresholds: only flip after N consecutive failures and recover after M consecutive successes
- Primary / backup failover: each record carries a primary and an optional backup IP; a state machine drives the switch
- DNS change audit: every
add/switch/removeis persisted and viewable in the UI - Realtime updates: SSE pushes status changes to the browser, plus optional Telegram notifications
- Full management UI: Vite + React + shadcn/ui, embedded into a single binary
- Auth: JWT in an httpOnly cookie; the first visit prompts you to create the admin account
- Backend: Go + Gin + ent ORM + PostgreSQL
- Frontend: Vite + React + TypeScript + Tailwind + shadcn/ui
- Realtime: Server-Sent Events
- Deployment: single binary (frontend embedded via
go:embed)
Requires Go 1.22+, Node 18+, PostgreSQL.
# 1. Create the database
createdb dns_failover
# 2. Configure
cp .env.example .env
# Edit .env: DATABASE_URL, and (optionally) TELEGRAM_BOT_TOKEN / TELEGRAM_CHAT_ID
# 3. Build the frontend
cd web && npm install && npm run build && cd ..
# 4. Run
go run ./cmd/server
# Open http://localhost:8080 — the first visit walks you through admin setup.Production build:
make build # Produces a single ./dns-failover binary with the frontend embedded
./dns-failoverAn image tagged latest is published to Docker Hub on every push to main: long2ice/dns-failover.
# Easiest: docker compose brings up the app and a PostgreSQL service together
cp .env.example .env
docker compose up -d
# Open http://localhost:8080
# Or run the app container alone, pointing at your own Postgres:
docker run -d \
--name dns-failover \
-p 8080:8080 \
--sysctl net.ipv4.ping_group_range="0 2147483647" \
-e DATABASE_URL="postgres://user:pass@host:5432/dns_failover?sslmode=disable" \
long2ice/dns-failover:latestThe
ping_group_rangesysctl lets the container open unprivileged ICMP sockets — required for thepingchecker. Drop it if you only usetcping/http.
Configure via a .env file or real environment variables (real env vars take precedence):
| Variable | Default | Description |
|---|---|---|
DATABASE_URL |
postgres://postgres:postgres@localhost:5432/dns_failover?sslmode=disable |
PostgreSQL connection string |
ADDR |
:8080 |
HTTP listen address |
GIN_MODE |
release |
Gin mode (debug / release / test) |
TELEGRAM_BOT_TOKEN |
— | Telegram bot token (optional) |
TELEGRAM_CHAT_ID |
— | Telegram target chat ID (optional) |
┌─────────────────┐
│ React (Vite) │ ← SSE / REST
└────────┬────────┘
│
┌────────▼────────────────────────────────────┐
│ Gin HTTP server │
│ ├── /api/* REST handlers │
│ └── /api/events SSE │
└────────┬───────────────┬────────────────────┘
│ │
┌─────▼──────┐ ┌─────▼────────┐
│ Monitor │ │ Notifier │
│ Manager │ │ (Telegram) │
│ (workers) │ │ │
└─────┬──────┘ └─────▲────────┘
│ │
│ ┌───────────┴─────────┐
│ │ Event Hub (in-mem) │ ← pub/sub
│ └─────────────────────┘
│
┌─────▼──────────────┐ ┌──────────────┐
│ Checkers │ │ DNS Provider │
│ ping/tcping/http │ │ Cloudflare │
│ │ │ Huawei │
└────────────────────┘ └──────────────┘
↕ ↕
┌──────▼────────────────────▼──────┐
│ PostgreSQL (via ent) │
└──────────────────────────────────┘
Every enabled monitor runs in its own goroutine with its own ticker. On a status change the worker calls applyRecordState, which diff-syncs each bound DNS record against the target provider.
- Multi-vantage checks: a single check point produces false positives when its own network blips. Add lightweight agent nodes that report check results, and only flip when M of N agents agree
- Encrypted credentials at rest:
providers.credentialsis currently plaintext JSON in Postgres; encrypt it with AES using anENCRYPTION_KEYenv var - Generic webhook notifications: ship a webhook channel alongside Telegram so users can wire Slack, WeCom, Feishu, DingTalk, Bark, etc.
- More DNS providers: Aliyun, Route53, DNSPod, Google Cloud DNS
- More check types: DNS resolution check, TLS certificate expiry, custom shell scripts
- Tags / grouping and search filters on monitors and records
- API tokens (for CI/CD and scripts)
- Audit log: who changed what and when
- Role-based access (read-only / operator / admin)
.
├── cmd/server/ # entry point
├── internal/
│ ├── api/ # HTTP handlers (Gin)
│ ├── checker/ # ping / tcping / http
│ ├── config/ # .env / env vars
│ ├── dns/ # provider adapters (Cloudflare, Huawei)
│ ├── model/ # API/store shared model
│ ├── monitor/ # background worker + event hub
│ ├── notifier/ # Telegram push
│ └── store/ # ent wrapper + converters
├── ent/
│ └── schema/ # ent schemas (run `go generate ./ent` to regenerate)
└── web/ # Vite + React frontend
├── src/ # source
└── dist/ # build output (go:embed)
MIT