5.4 KiB
Sloth Manager
A self-hosted web app to manage DNS records across Cloudflare, Loopia, Pi-hole, Azure DNS, and cPanel from a single interface.
Requirements
- Node.js 18+
- npm
Setup
1. Backend
cd backend
npm install
cp .env.example .env
Edit .env with your credentials and settings. See ENVIRONMENT.md for a full reference of every variable.
Start the backend:
npm run dev # development (auto-restarts on saved file changes)
npm start # production
Note:
npm run devuses nodemon and will automatically restart when you edit existing files. However, if you add a new file to the project while nodemon is running, you need to stop (Ctrl+C) and restart manually — nodemon does not detect brand new files being required for the first time.
2. Frontend
cd frontend
npm install
npm start # dev server on http://localhost:3000
For production, build the static files and serve them via nginx or similar:
npm run build # outputs to frontend/build/
First run
On first start the backend automatically creates a default admin account and prints a warning in the terminal:
⚠ No users found — created default admin account.
⚠ Username: admin Password: admin
⚠ Change this password immediately in Settings → Users.
Log in with admin / admin, then go to 👤 My Profile to change the password.
Usage
- Open
http://localhost:3000and sign in - The 🏠 Overview page shows statistics based on your locally cached records
- The 🌍 All Domains page shows every zone across all providers in one table — duplicate domains across providers are highlighted
- Select a provider from the sidebar, then select a zone to see its domains
- Press ⟳ Sync to fetch the latest records from the provider — this is the only action that calls the provider API for reads
- Add, edit, or delete records directly from the table — changes apply to the provider immediately and update the local cache
- All record changes are logged in 📋 Audit Log
- Configure notifications, users, provider tag colours, and cache under ⚙️ Settings
Data files
The backend stores these files at runtime:
| File | Purpose |
|---|---|
backend/dns-cache.json |
Local cache of synced DNS records |
backend/settings.json |
App settings (Gotify, provider colours) |
backend/users.json |
User accounts (hashed passwords) |
backend/audit-log.json |
Record change history (last 500 entries) |
All files are created automatically on first use.
Documentation
| File | Contents |
|---|---|
ENVIRONMENT.md |
Every .env variable explained |
API-ACCESS.md |
API credentials and permissions for each provider |
NOTIFICATIONS.md |
Gotify notification setup and troubleshooting |
Adding more providers
-
Create
backend/src/adapters/yourprovider.jsexporting:listZones()→[{ id, name }]listRecords(zoneId)→[{ id, type, name, content, ttl, priority }]addRecord(zoneId, record)→{ id, ... }updateRecord(zoneId, recordId, record)→{ id, ... }deleteRecord(zoneId, recordId)
-
Register it in
backend/src/routes/zones.jsandrecords.js -
Add its env vars to
.env -
Restart the backend after making these changes
Project structure
dns-manager/
├── backend/
│ ├── src/
│ │ ├── index.js # Express server entry point
│ │ ├── db.js # JSON file cache
│ │ ├── settings.js # Settings persistence
│ │ ├── notify.js # Gotify notification helper
│ │ ├── audit.js # Audit log
│ │ ├── auth.js # JWT helpers & middleware
│ │ ├── users.js # User management
│ │ ├── routes/
│ │ │ ├── zones.js
│ │ │ ├── records.js
│ │ │ ├── settings.js
│ │ │ ├── auth.js
│ │ │ └── users.js
│ │ └── adapters/
│ │ ├── cloudflare.js
│ │ ├── loopia.js
│ │ ├── pihole.js
│ │ ├── azure.js
│ │ └── cpanel.js
│ ├── dns-cache.json # created on first sync
│ ├── settings.json # created on first save
│ ├── users.json # created on first start
│ ├── audit-log.json # created on first change
│ ├── .env.example
│ └── package.json
└── frontend/
├── src/
│ ├── App.js
│ ├── App.css
│ ├── index.js
│ ├── api/dns.js
│ ├── context/
│ │ ├── ProviderColors.js
│ │ └── Theme.js
│ ├── utils/
│ │ └── exportCsv.js
│ └── components/
│ ├── LoginPage.js
│ ├── Dashboard.js
│ ├── DomainsPage.js
│ ├── ProviderOverview.js
│ ├── RecordsTable.js
│ ├── AddRecordForm.js
│ ├── AuditPage.js
│ ├── ProfilePage.js
│ ├── SettingsPage.js
│ └── ConfirmDialog.js
└── package.json