A modern DNS aggregation management platform built with React + TailwindCSS (frontend) and Node.js + TypeScript (backend).
对于中国用户请看: 简体中文文档
Multi-provider Support: Manage DNS records across 18 providers:
Multi-user & Team Management: Role-based access (admin/member), team-based domain sharing
Full DNS Record Management: CRUD for all record types (A, AAAA, CNAME, MX, TXT, SRV, CAA, etc.)
Modern UI: React 18 + TailwindCSS with responsive design
API Documentation: Swagger UI at /api/docs
Extensible Architecture: Abstract DNS interface makes adding new providers easy
When creating/updating DNS accounts, the API normalizes lego-style provider names to internal provider types.
| Internal Type | Supported Aliases |
|---|---|
aliyun | aliyun, alidns |
aliyunesa | aliesa |
baidu | baiducloud |
huawei | huaweicloud |
huoshan | huoshan, volcengine |
west | westcn |
cloudflare | cloudflare |
jdcloud | jdcloud |
namesilo | namesilo |
rainyun | rainyun |
powerdns | powerdns, pdns |
dnspod | dnspod, tencentcloud |
tencenteo | tencenteo, edgeone |
DNSMgr/ ├── server/ # Node.js + TypeScript backend │ └── src/ │ ├── lib/dns/ # DNS provider adapters (abstract interface) │ ├── routes/ # REST API routes │ ├── middleware/ # Auth (JWT), validation │ ├── service/ # Business logic services │ └── db/ # Three-layer database architecture │ ├── business-adapter.ts # Business adapter layer (functional API) │ ├── core/ # Database abstraction layer │ ├── drivers/ # Database drivers (MySQL/PostgreSQL/SQLite) │ └── schemas/ # Database schemas └── client/ # React + Vite + TailwindCSS frontend └── src/ ├── pages/ # All UI pages ├── components/ # Reusable components └── api/ # API client
DNSMgr implements a strict three-layer database architecture:
Routes/Service Layer → Business Adapter Layer → Core Layer → Driver Layer → Database
Layer 1: Business Adapter Layer (db/business-adapter.ts)
query(), get(), execute(), insert(), run()UserOperations, DnsAccountOperations, etc.Layer 2: Database Abstraction Layer (db/core/)
Layer 3: Driver Layer (db/drivers/)
// ✅ Correct - Use business adapter functions
import { query, get, execute, insert, UserOperations } from '../db';
const user = await get<User>('SELECT * FROM users WHERE id = ?', [userId]);
const users = await query<User>('SELECT * FROM users WHERE status = ?', ['active']);
const id = await insert('INSERT INTO users (name, email) VALUES (?, ?)', [name, email]);
// Use business operation modules
const user = await UserOperations.getById(1);
See ARCHITECTURE.md for detailed architecture documentation.
pnpm install
Start both frontend and backend with a single command (runs on separate ports):
# Start both server (port 3001) and client (port 5173) in parallel
pnpm dev
Access: http://localhost:5173
First startup note: if the system is not initialized yet, open the setup wizard at
http://localhost:5173/setup(orhttp://localhost:3001/setupin unified mode) to configure DB and create the first admin.
Start frontend and backend independently in separate terminals:
# Terminal 1 - Backend only (port 3001)
cd server && pnpm dev
# Terminal 2 - Frontend only (port 5173)
cd client && pnpm dev
pnpm build
Run both frontend and backend on the same port (3001) - backend serves static files:
# Step 1: Build frontend first
pnpm --filter client build
# Step 2: Start backend only (serves both API and frontend on port 3001)
cd server && pnpm dev
Access: http://localhost:3001
This mode is useful when you want:
Docker deployment uses all-in-one mode (frontend + backend in single container).
# Run with pre-built image from GitHub Container Registry
docker run -d \
-p 3001:3001 \
-v $(pwd)/data:/app/data \
--name dnsmgr \
ghcr.io/hipm-tech/dnsmgr:latest
Or use Docker Compose:
# Download compose file
curl -O https://raw.githubusercontent.com/HiPM-Tech/DNSMgr/main/docker-compose.yml
# Start service
docker-compose up -d
# Build and run
docker build -t dnsmgr .
docker run -d \
-p 3001:3001 \
-v $(pwd)/data:/app/data \
--name dnsmgr \
dnsmgr
Access: http://localhost:3001
Copy .env.example to .env in the server/ directory:
cp server/.env.example server/.env
| Variable | Default | Description |
|---|---|---|
PORT | 3001 | Server port |
NODE_ENV | development | Runtime environment |
JWT_SECRET | unset | Base JWT secret; if unset, server falls back to an insecure default (set this in production) |
DB_PATH | ./dnsmgr.db | SQLite database path |
DB_TYPE | sqlite | Database type: sqlite, mysql, or postgresql |
DB_HOST | - | Database host (for MySQL/PostgreSQL) |
DB_PORT | - | Database port (for MySQL/PostgreSQL) |
DB_NAME | - | Database name (for MySQL/PostgreSQL) |
DB_USER | - | Database user (for MySQL/PostgreSQL) |
DB_PASSWORD | - | Database password (for MySQL/PostgreSQL) |
DB_SSL | false | Enable SSL for MySQL/PostgreSQL |
JWT_SECRET + runtime_secret (from DB table runtime_secrets)./api/init/* endpoints are intended for pre-setup initialization./api/init/database rejects re-initialization with 403./api/init/admin), not by a fixed default account.After starting the server, visit: http://localhost:3001/api/docs
line field for backward compatibility.cloudflare.proxied: proxy switch (true = proxied, false = DNS only)cloudflare.proxiable: whether the current record type can be proxiedcloudflare.proxied is provided, it is used.line ('1' = proxied, '0' = DNS only).server/src/lib/dns/providers/myprovider.ts implementing DnsAdapterserver/src/lib/dns/DnsHelper.ts (add to DNS_PROVIDERS map)server/src/lib/dns/providers/index.tsThe adapter must implement the DnsAdapter interface:
interface DnsAdapter {
check(): Promise<boolean>;
getDomainList(...): Promise<PageResult<DomainInfo>>;
getDomainRecords(...): Promise<PageResult<DnsRecord>>;
addDomainRecord(...): Promise<string | null>;
updateDomainRecord(...): Promise<boolean>;
deleteDomainRecord(...): Promise<boolean>;
setDomainRecordStatus(...): Promise<boolean>;
// ...
}
Backend:
Frontend:
MIT
DNSMgr uses react-i18next for internationalization. The current supported languages are English, Simplified Chinese, Spanish, and Japanese.
We welcome community contributions for new languages! Here's how to add one:
client/src/i18n/locales/en.ts) to a new file like fr.ts (for French).resources object in client/src/i18n/index.ts.client/src/pages/Settings.tsx to include your new language option.Tip: We recommend using the i18n-ally VS Code extension. The project already includes the .vscode/settings.json configuration for it, which helps you easily find missing translations and manage keys.
We support multiple DNS providers out of the box (Cloudflare, AliYun, TencentCloud, HuaweiCloud, DNSPod, GoDaddy). If your provider is not supported, you can easily add it:
server/src/lib/dns/providers/ implementing the DnsAdapter interface.server/src/lib/dns/DnsHelper.ts.PROVIDERS list in client/src/pages/Accounts.tsx with its required configuration fields.