logo
0
0
WeChat Login
HINS<HINS@hinswu.top>
docs(readme): update README with new database architecture

DNSMgr - DNS Aggregation Management Platform

A modern DNS aggregation management platform built with React + TailwindCSS (frontend) and Node.js + TypeScript (backend).

对于中国用户请看: 简体中文文档

Features

  • Multi-provider Support: Manage DNS records across 18 providers:

    • Aliyun (阿里云), DNSPod (腾讯云), Huawei Cloud (华为云), Baidu Cloud (百度云)
    • Volcengine (火山引擎), JD Cloud (京东云), Cloudflare, DNS.LA
    • West Digital (西部数码), Qingcloud (青云), NameSilo, BT Panel (宝塔)
    • Spaceship, PowerDNS, Aliyun ESA (阿里云 ESA), Tencent EdgeOne (腾讯 EdgeOne)
    • DNSHE, Rainyun (雨云)
  • 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

Provider Type & Alias Mapping

When creating/updating DNS accounts, the API normalizes lego-style provider names to internal provider types.

Internal TypeSupported Aliases
aliyunaliyun, alidns
aliyunesaaliesa
baidubaiducloud
huaweihuaweicloud
huoshanhuoshan, volcengine
westwestcn
cloudflarecloudflare
jdcloudjdcloud
namesilonamesilo
rainyunrainyun
powerdnspowerdns, pdns
dnspoddnspod, tencentcloud
tencenteotencenteo, edgeone

Architecture

System Architecture

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

Database Architecture (Three-Layer Design)

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)

  • Functional API: query(), get(), execute(), insert(), run()
  • Business operation modules: UserOperations, DnsAccountOperations, etc.
  • All database operations MUST go through this layer
  • Automatic logging and performance monitoring

Layer 2: Database Abstraction Layer (db/core/)

  • Unified type definitions
  • Connection manager (singleton pattern)
  • Database configuration management

Layer 3: Driver Layer (db/drivers/)

  • MySQL driver (connection pool)
  • PostgreSQL driver (connection pool)
  • SQLite driver (better-sqlite3)

Database API Usage

// ✅ 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.

Quick Start

Prerequisites

  • Node.js >= 18
  • pnpm

Install Dependencies

pnpm install

Development

Mode 1: Concurrent Start (Recommended for most users)

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 (or http://localhost:3001/setup in unified mode) to configure DB and create the first admin.

Mode 2: Separate Start (For advanced users)

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

Production Build

pnpm build

Source Code - Unified Mode (Single Port)

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:

  • Only one port exposed
  • Same behavior as Docker deployment
  • Simpler reverse proxy configuration

Docker Deployment

Docker deployment uses all-in-one mode (frontend + backend in single container).

Option 1: Use Pre-built Image (Recommended)

# 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

Option 2: Build from Source

# 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

Environment Variables

Copy .env.example to .env in the server/ directory:

cp server/.env.example server/.env
VariableDefaultDescription
PORT3001Server port
NODE_ENVdevelopmentRuntime environment
JWT_SECRETunsetBase JWT secret; if unset, server falls back to an insecure default (set this in production)
DB_PATH./dnsmgr.dbSQLite database path
DB_TYPEsqliteDatabase 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_SSLfalseEnable SSL for MySQL/PostgreSQL

JWT runtime secret rotation (important)

  • JWT signing uses: JWT_SECRET + runtime_secret (from DB table runtime_secrets).
  • A per-runtime secret is generated/stored automatically if missing.
  • During setup, after creating the first admin, runtime secrets are rotated.
  • Existing JWT tokens become invalid when runtime secret changes.

Initialization & Security Notes

  • /api/init/* endpoints are intended for pre-setup initialization.
  • Once the system is initialized (DB ready + users exist), /api/init/database rejects re-initialization with 403.
  • Admin credentials are created by setup wizard/API (/api/init/admin), not by a fixed default account.

API Documentation

After starting the server, visit: http://localhost:3001/api/docs

Record Model Notes

  • DNS records still expose the generic line field for backward compatibility.
  • For Cloudflare, use provider-specific fields in request/response payloads:
    • cloudflare.proxied: proxy switch (true = proxied, false = DNS only)
    • cloudflare.proxiable: whether the current record type can be proxied
  • Write precedence for Cloudflare create/update:
    • If cloudflare.proxied is provided, it is used.
    • Otherwise, fallback to line ('1' = proxied, '0' = DNS only).

Adding a New DNS Provider

  1. Create a new adapter in server/src/lib/dns/providers/myprovider.ts implementing DnsAdapter
  2. Register it in server/src/lib/dns/DnsHelper.ts (add to DNS_PROVIDERS map)
  3. Export it in server/src/lib/dns/providers/index.ts

The 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>; // ... }

Tech Stack

Backend:

  • Node.js + TypeScript
  • Express.js
  • SQLite (better-sqlite3), MySQL (mysql2), PostgreSQL (pg)
  • JWT authentication
  • Swagger/OpenAPI documentation

Frontend:

  • React 18 + TypeScript
  • Vite
  • TailwindCSS v3
  • React Router v6
  • @tanstack/react-query
  • Axios
  • lucide-react

License

MIT

Internationalization (i18n) & Contribution

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:

  1. Copy an existing language file (e.g., client/src/i18n/locales/en.ts) to a new file like fr.ts (for French).
  2. Translate the string values in your new file.
  3. Import and add your new language to the resources object in client/src/i18n/index.ts.
  4. Update the language selector in 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.

Adding New DNS Providers

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:

  1. Implement the Adapter: Create a new file in server/src/lib/dns/providers/ implementing the DnsAdapter interface.
  2. Register the Adapter: Add your adapter to the switch case in server/src/lib/dns/DnsHelper.ts.
  3. Update Frontend: Add your provider to the PROVIDERS list in client/src/pages/Accounts.tsx with its required configuration fields.
  4. Submit a PR: We welcome pull requests! Ensure your code follows the existing style and passes the tests.