home-hosted 0.6.5 → 0.6.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +25 -18
- package/README.md +19 -6
- package/dist/cli.js +2829 -797
- package/dist/cli.js.map +1 -1
- package/docs/DDNS.md +80 -0
- package/docs/NOTIFICATIONS.md +3 -0
- package/package.json +2 -1
- package/uis/stock/dist/assets/{index-Dqs9Vd8M.js → index-C6tbSbCK.js} +7 -7
- package/uis/stock/dist/assets/index-Do5DvzS4.css +2 -0
- package/uis/stock/dist/index.html +2 -2
- package/uis/stock/dist/assets/index-DMo6krK0.css +0 -2
package/docs/DDNS.md
ADDED
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Dynamic DNS
|
|
2
|
+
|
|
3
|
+
Keep a list of hostnames pointed at this machine's public IP. The panel checks the address on an
|
|
4
|
+
interval and calls a provider only when it actually changed — restart-safe, because the last
|
|
5
|
+
confirmed address per hostname is kept in `$HHOSTED_HOME/.state/ddns.json`.
|
|
6
|
+
|
|
7
|
+
**Settings → Dynamic DNS** is the whole setup: add an account, paste its credentials, add hostnames.
|
|
8
|
+
Nothing else is required, and provider credentials never enter `servers.config.json`.
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"ddns": {
|
|
13
|
+
"enabled": true,
|
|
14
|
+
"intervalMs": 300000,
|
|
15
|
+
"ipv4": { "enabled": true, "url": "" },
|
|
16
|
+
"ipv6": { "enabled": false, "url": "" },
|
|
17
|
+
"ttl": 1,
|
|
18
|
+
"proxied": false,
|
|
19
|
+
"notify": true,
|
|
20
|
+
"accounts": [
|
|
21
|
+
{ "id": "cf", "provider": "cloudflare", "label": "Home zone" }
|
|
22
|
+
],
|
|
23
|
+
"domains": [
|
|
24
|
+
{ "host": "home.example.com", "account": "cf", "types": ["A"] },
|
|
25
|
+
{ "host": "vpn.example.com", "account": "cf", "types": ["A", "AAAA"], "proxied": true }
|
|
26
|
+
]
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
Credentials live in `.control-secrets.json` (0600), keyed by the account `id`. Header fields:
|
|
32
|
+
|
|
33
|
+
| Field | Default | Notes |
|
|
34
|
+
| --- | --- | --- |
|
|
35
|
+
| `enabled` | `false` | Nothing runs until this is on. |
|
|
36
|
+
| `intervalMs` | `300000` | How often the public address is re-checked. |
|
|
37
|
+
| `ipv4` / `ipv6` | on / off | Which families to detect. A family must be on for its record types. |
|
|
38
|
+
| `ipv4.url` / `ipv6.url` | `""` | Override the detector with one endpoint. |
|
|
39
|
+
| `ttl` | `1` | Default record TTL; `1` is automatic where supported. |
|
|
40
|
+
| `proxied` | `false` | Default for providers with a CDN flag (Cloudflare). |
|
|
41
|
+
| `notify` | `true` | Tell Telegram about a change, and about a failure. |
|
|
42
|
+
| `accounts[]` | — | `id` (keys the credentials), `provider`, optional `label`. |
|
|
43
|
+
| `domains[]` | — | `host`, `account`, `types` (`A`/`AAAA`, default `A`), optional `ttl`, `proxied`, `zone`, `enabled`. |
|
|
44
|
+
|
|
45
|
+
Per-hostname `zone` pins the registered domain — only needed where a provider has to be told the apex
|
|
46
|
+
and the guess is wrong (`home.example.co.uk` is handled; an unusual suffix may not be).
|
|
47
|
+
|
|
48
|
+
## Providers
|
|
49
|
+
|
|
50
|
+
| Provider | Record types | Credentials | Notes |
|
|
51
|
+
| --- | --- | --- | --- |
|
|
52
|
+
| **Cloudflare** | A, AAAA | API token (`Zone → DNS → Edit`); or legacy email + global key | Zones and record ids are discovered, then cached. Updates use `PATCH`, so comments survive. |
|
|
53
|
+
| **Namecheap** | A | Dynamic DNS password | Router-style Dynamic DNS, not the XML API. The password is under Advanced DNS → Dynamic DNS — not the account password. IPv4 only. |
|
|
54
|
+
| **Spaceship** | A, AAAA | API key + secret | No DDNS endpoint; uses the DNS API's whole-record-set upsert. |
|
|
55
|
+
| **Porkbun** | A, AAAA | API key + secret key | Read-then-upsert by name and type. |
|
|
56
|
+
| **GoDaddy** | A, AAAA | API key + secret | Optional `baseUrl` points at the OTE test environment. GoDaddy has gated this API by account before; a 403 means the account is not eligible. |
|
|
57
|
+
| **Gandi** | A, AAAA | Personal access token (`pat_…`) | LiveDNS RRset update. |
|
|
58
|
+
| **DigitalOcean** | A, AAAA | API token | No upsert-by-name; lists records, then updates the one it found. |
|
|
59
|
+
| **deSEC** | A, AAAA | API token | `update.dedyn.io`, HTTP Basic with the hostname. |
|
|
60
|
+
| **DuckDNS** | A, AAAA | Account token | One token covers every subdomain. |
|
|
61
|
+
| **No-IP** | A, AAAA | Email + password | Sends a recognised `User-Agent`; override it if yours is registered. |
|
|
62
|
+
| **Dynu** | A, AAAA | Username + password | `password` may be the SHA-256 hash. |
|
|
63
|
+
| **Hurricane Electric** | A, AAAA | Per-host DDNS key | `dyn.dns.he.net`. |
|
|
64
|
+
| **FreeDNS (afraid.org)** | A, AAAA | The per-record "Direct URL" | Paste the whole URL or just its hash. |
|
|
65
|
+
|
|
66
|
+
Not supported: **Route 53** (AWS SigV4 signing, a much larger dependency), **DreamHost** (no public
|
|
67
|
+
DNS API), and the Namecheap XML API (a full zone rewrite per update).
|
|
68
|
+
|
|
69
|
+
## Notifications
|
|
70
|
+
|
|
71
|
+
Telegram carries one message per pass that changed a record, and one for a pass that failed. Turn it
|
|
72
|
+
off under Settings → Notifications → *Dynamic DNS*, or with `ddns.notify: false`.
|
|
73
|
+
|
|
74
|
+
## Adding a provider
|
|
75
|
+
|
|
76
|
+
`src/providers/ddns/<name>.ts` exports one `DdnsProvider`: its credential fields, the families it can
|
|
77
|
+
manage, and an `update()` that makes one HTTP call and returns `{ ok, changed, message }`. Register it
|
|
78
|
+
in `src/providers/ddns/index.ts`; the settings page, the credentials form and validation follow from
|
|
79
|
+
that metadata. Put the reasoning for `changed: false` in the provider — it is what makes the panel
|
|
80
|
+
skip a write when a record is already current.
|
package/docs/NOTIFICATIONS.md
CHANGED
|
@@ -47,8 +47,11 @@ curl -X POST http://127.0.0.1:3999/api/notifications/test \
|
|
|
47
47
|
| a server was force-restarted (health timeout) | `onForcedRestart` | ✅ |
|
|
48
48
|
| a server recovered | `onRecovered` | ⬜ |
|
|
49
49
|
| host thresholds breached, and recovered | `onHost` | ✅ |
|
|
50
|
+
| a dynamic DNS record changed, or a pass failed | `onDdns` | ✅ |
|
|
50
51
|
|
|
51
52
|
Host thresholds themselves — disk, memory, swap, load, temperature — are **Settings → Host**.
|
|
53
|
+
Dynamic DNS carries one message per pass that changed a record, and one per failed pass — see
|
|
54
|
+
[DDNS.md](./DDNS.md).
|
|
52
55
|
|
|
53
56
|
## Quiet periods
|
|
54
57
|
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "home-hosted",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.6.
|
|
4
|
+
"version": "0.6.7",
|
|
5
5
|
"packageManager": "pnpm@12.5.1",
|
|
6
6
|
"description": "Self-hosted control panel that keeps your home-server processes alive: supervision, restarts, port conflicts, logs — and a UI you can replace.",
|
|
7
7
|
"author": "NamesMT <dangquoctrung123@gmail.com>",
|
|
@@ -55,6 +55,7 @@
|
|
|
55
55
|
"README.md",
|
|
56
56
|
"bin",
|
|
57
57
|
"dist",
|
|
58
|
+
"docs/DDNS.md",
|
|
58
59
|
"docs/NOTIFICATIONS.md",
|
|
59
60
|
"docs/SERVERS.md",
|
|
60
61
|
"docs/UI_CREATION.md",
|