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/AGENTS.md
CHANGED
|
@@ -3,13 +3,14 @@
|
|
|
3
3
|
`home-hosted` is a Node 24 / TypeScript harness for self-hosted servers: `up` starts a Hono/srvx
|
|
4
4
|
panel (default `127.0.0.1:3999`) that supervises the entries in `$HHOSTED_HOME/servers.config.json`
|
|
5
5
|
and serves a UI. User docs: `README.md`, `docs/SERVERS.md` (entries and port conflicts),
|
|
6
|
-
`docs/NOTIFICATIONS.md`; UI authors: `docs/UI_CREATION.md`.
|
|
6
|
+
`docs/NOTIFICATIONS.md`, `docs/DDNS.md`; UI authors: `docs/UI_CREATION.md`.
|
|
7
7
|
|
|
8
8
|
State lives only in `$HHOSTED_HOME` (default `~/.home-hosted`): `servers.config.json`,
|
|
9
|
-
`.control-secrets.json` (0600: password hash, API token hash, Telegram bot token
|
|
10
|
-
`.backups/`, `.ui/`, `.state/` (a persistent entry's nanny state, plus its 0600
|
|
11
|
-
nanny reads it
|
|
12
|
-
|
|
9
|
+
`.control-secrets.json` (0600: password hash, API token hash, Telegram bot token, DDNS credentials),
|
|
10
|
+
`.logs/`, `.tls/`, `.backups/`, `.ui/`, `.state/` (a persistent entry's nanny state, plus its 0600
|
|
11
|
+
spawn spec until the nanny reads it, plus `ddns.json` — the last address each target confirmed), and
|
|
12
|
+
`run.json` — the live daemon's pid/url/token, 0600. The package ships **no servers**: never commit a
|
|
13
|
+
config, a seed entry, or a path that names one.
|
|
13
14
|
|
|
14
15
|
## Commands
|
|
15
16
|
|
|
@@ -91,14 +92,15 @@ a minor without one.
|
|
|
91
92
|
`processCarriesServerId` for the environment marker and `processTreePids` for tree ownership),
|
|
92
93
|
`identity` (which port holder is this entry's own successor: marker first, then resolved image +
|
|
93
94
|
argv), `nanny` (a persistent entry's spec/state files and the liveness rules for one),
|
|
94
|
-
`log-tail` (an offset reader that survives rotation and truncation),
|
|
95
|
+
`log-tail` (an offset reader that survives rotation and truncation), `ddns/` (one `DdnsProvider` per
|
|
96
|
+
registrar over one HTTP call each, plus `ip` and `zone` helpers), health-check, host, telegram,
|
|
95
97
|
archive.
|
|
96
98
|
- `src/services/` — stateful orchestration: supervisor, control-server, config-watch, state,
|
|
97
|
-
auth + exposure, dependencies, history, log-buffer/log-files, notifications, host-monitor,
|
|
98
|
-
tls, ui, plus `init` (the scaffold behind `home-hosted init`: a manifest, a `.gitignore`,
|
|
99
|
-
prompts stay in the CLI), `nanny` (the process a persistent entry runs under) and
|
|
100
|
-
tailer that feeds its lines to the supervisor). It names no server — the scaffold
|
|
101
|
-
neutral as the supervisor.
|
|
99
|
+
auth + exposure, dependencies, history, log-buffer/log-files, notifications, host-monitor, ddns,
|
|
100
|
+
backups, tls, ui, plus `init` (the scaffold behind `home-hosted init`: a manifest, a `.gitignore`,
|
|
101
|
+
and the prompts stay in the CLI), `nanny` (the process a persistent entry runs under) and
|
|
102
|
+
`log-relay` (the tailer that feeds its lines to the supervisor). It names no server — the scaffold
|
|
103
|
+
must stay as neutral as the supervisor.
|
|
102
104
|
- `src/middleware/auth.ts` — the `/api/*` guard, and `requestIdentity()`, the one place a request's
|
|
103
105
|
credentials are read: the `hh_session` cookie or `Authorization: Bearer <api token>`. A token is
|
|
104
106
|
a first-class credential (same authority as a signed-in browser) and is verified from the secrets
|
|
@@ -127,10 +129,10 @@ a minor without one.
|
|
|
127
129
|
- `scripts/` — `build-uis.mjs` (build one UI, optionally zip it), `typecheck-uis.mjs`,
|
|
128
130
|
`capture-media.mjs` (the README's media), `check-release-version.mjs` and `release-notes.mjs`
|
|
129
131
|
(used by the release workflow), `dev.mjs` (`pnpm dev`).
|
|
130
|
-
- `docs/` — the topic docs (`SERVERS.md`, `NOTIFICATIONS.md`, `UI_CREATION.md`),
|
|
131
|
-
(hand-written UI examples in four directions) and `media/*`: their screenshots plus
|
|
132
|
-
`tour.gif`, all regenerated by `pnpm run media`. Only the
|
|
133
|
-
media is a build artifact.
|
|
132
|
+
- `docs/` — the topic docs (`SERVERS.md`, `NOTIFICATIONS.md`, `DDNS.md`, `UI_CREATION.md`),
|
|
133
|
+
`mockups/*.html` (hand-written UI examples in four directions) and `media/*`: their screenshots plus
|
|
134
|
+
the README's `tour.gif`, all regenerated by `pnpm run media`. Only the four `.md` files are
|
|
135
|
+
published; the media is a build artifact.
|
|
134
136
|
|
|
135
137
|
## Conventions
|
|
136
138
|
|
|
@@ -247,6 +249,9 @@ either is a last resort, and never an accidental one.
|
|
|
247
249
|
every entry's child) instead of killing it — a port held by a sibling is a config mistake.
|
|
248
250
|
- **Never expose beyond loopback without auth and a non-default password.** `checkExposure()` is the
|
|
249
251
|
single rule, enforced at startup, on every settings write, and in the UI.
|
|
252
|
+
- **The CLI drives a running panel through `/_hh`, never `/api`.** `down` and `start`/`stop` read
|
|
253
|
+
run.json's token and speak over loopback through one guard (`assertLocalCall`), so they need no
|
|
254
|
+
session, password or API token — and a new local command must not open an unauthenticated `/api` route.
|
|
250
255
|
- **UIs are external clients.** Nothing in `src/**` may know a UI's markup or files;
|
|
251
256
|
`$HHOSTED_HOME/.ui` overrides the packaged UI at runtime.
|
|
252
257
|
- **A restore writes only where a config says** — archive allowlist, `origin` matching first,
|
|
@@ -344,10 +349,12 @@ either is a last resort, and never an accidental one.
|
|
|
344
349
|
nested, the form in `uis/stock/src/components/settings/`, and the contract tests.
|
|
345
350
|
- **UI**: a new `uis/<name>/` with a `vite.config.ts` from the shared factory;
|
|
346
351
|
`node scripts/build-uis.mjs <name> --zip`. The contract is `docs/UI_CREATION.md`.
|
|
347
|
-
- **Capability**: a stateless `src/providers/*` returning plain data
|
|
352
|
+
- **Capability**: a stateless `src/providers/*` returning plain data; a DDNS provider is one file plus
|
|
353
|
+
a registry line (`src/providers/ddns/index.ts`), and the settings form, credentials and validation
|
|
354
|
+
follow from its metadata — see `docs/DDNS.md`.
|
|
348
355
|
|
|
349
356
|
## Publishing
|
|
350
357
|
|
|
351
|
-
`pnpm pack` runs `prepack` (a full build) and ships `bin/`, `dist/`, `uis/stock/dist`, `README.md`, `docs/
|
|
352
|
-
`docs/NOTIFICATIONS.md`, `docs/UI_CREATION.md`, `AGENTS.md` and `LICENSE`. The bin falls back to tsx so `pnpm link` works before a
|
|
358
|
+
`pnpm pack` runs `prepack` (a full build) and ships `bin/`, `dist/`, `uis/stock/dist`, `README.md`, `docs/DDNS.md`,
|
|
359
|
+
`docs/SERVERS.md`, `docs/NOTIFICATIONS.md`, `docs/UI_CREATION.md`, `AGENTS.md` and `LICENSE`. The bin falls back to tsx so `pnpm link` works before a
|
|
353
360
|
build; `vue`/`vue-router` are devDependencies because the UIs are prebuilt.
|
package/README.md
CHANGED
|
@@ -79,8 +79,8 @@ some arguments, and the environment you give it:
|
|
|
79
79
|
{ "id": "gateway", "command": "node", "args": ["server.js"], "port": 4000, "autostart": true }
|
|
80
80
|
```
|
|
81
81
|
|
|
82
|
-
<sub>Manage them from the panel, `home-hosted
|
|
83
|
-
the same status line for your own monitor, no session needed.</sub>
|
|
82
|
+
<sub>Manage them from the panel, `home-hosted start|stop <id>` from a shell, `home-hosted status --json`,
|
|
83
|
+
or `GET /api/state`; `GET /healthz` is the same status line for your own monitor, no session needed.</sub>
|
|
84
84
|
|
|
85
85
|
---
|
|
86
86
|
|
|
@@ -255,7 +255,8 @@ can be told what to be: *"Help me build a UI for home-hosted: nostalgic game the
|
|
|
255
255
|
| 📈 **Resources** | CPU and RSS of the whole process tree, with an optional memory ceiling that triggers a restart. |
|
|
256
256
|
| 🌡️ **Host vitals** | Load, memory, swap, disk and CPU temperature, with thresholds that notify once and again on recovery. |
|
|
257
257
|
| 🤖 **Token API** | Scripts and agents drive it with `Authorization: Bearer` — no browser, no session. [↑](#-agents-scripts-and-tools) |
|
|
258
|
-
| 🔔 **Notifications** | Telegram on crash, unhealthy, forced restart, recovery
|
|
258
|
+
| 🔔 **Notifications** | Telegram on crash, unhealthy, forced restart, recovery, host thresholds and DNS changes — [setup here](./docs/NOTIFICATIONS.md). |
|
|
259
|
+
| 🌐 **Dynamic DNS** | Keep hostnames pointed at your public IP — Cloudflare, Namecheap, Spaceship, Porkbun, GoDaddy, Gandi and more. [DDNS.md](./docs/DDNS.md) |
|
|
259
260
|
| 💾 **Backups** | One click for config, secrets, TLS and your declared data directories — plain `.zip`, or AES-256 with a password, restored per path. |
|
|
260
261
|
| 🎨 **BYOU — Bring Your Own UI** | Upload a static build, `ui-update` to follow its releases, `ui-revert` to go back. [UI_CREATION.md](./docs/UI_CREATION.md) |
|
|
261
262
|
| 🔐 **Security** | Cookie sessions, API tokens, scrypt hashes, per-IP lockout, optional TLS, and a refusal to expose itself without a password. |
|
|
@@ -293,6 +294,8 @@ restarts itself), and how hand-edits are validated: [SERVERS.md](./docs/SERVERS.
|
|
|
293
294
|
| `home-hosted down` | stop it cleanly — supervised processes included, persistent entries left running |
|
|
294
295
|
| `home-hosted restart` | `down`, then `up` |
|
|
295
296
|
| `home-hosted status` | pid, URL, health, uptime, state and log paths (`--json` for scripts) |
|
|
297
|
+
| `home-hosted start <id>` | start one server — and anything it `dependsOn` |
|
|
298
|
+
| `home-hosted stop <id>` | stop one server, nothing else |
|
|
296
299
|
| `home-hosted set-password` | set the panel password without opening a browser |
|
|
297
300
|
| `home-hosted set-token` | set the API token scripts and agents use (`--generate`, `--clear`) |
|
|
298
301
|
| `home-hosted migrate` | bring `servers.config.json` up to this release's schema (`--dry-run`, `--yes`) |
|
|
@@ -311,6 +314,7 @@ up, restart -c/--config -p/--port --host --open --no-autostart --foregroun
|
|
|
311
314
|
|
|
312
315
|
down (no flags)
|
|
313
316
|
status --json
|
|
317
|
+
start, stop <id> (the server's id in servers.config.json; both need the panel up)
|
|
314
318
|
init --dir --name --pm --no-install -y/--yes
|
|
315
319
|
set-password --clear
|
|
316
320
|
set-token --generate --clear
|
|
@@ -381,9 +385,18 @@ Everything binds `127.0.0.1` until you say otherwise.
|
|
|
381
385
|
## 🔔 Notifications
|
|
382
386
|
|
|
383
387
|
Telegram, when something happens while you are not looking: a server that gave up restarting, a
|
|
384
|
-
failing health check, a forced restart, a recovery,
|
|
385
|
-
temperature). Opt-in, rate-limited per server *and* reason, and the bot token
|
|
386
|
-
file. **Two minutes of setup: [NOTIFICATIONS.md](./docs/NOTIFICATIONS.md).**
|
|
388
|
+
failing health check, a forced restart, a recovery, a host threshold (disk, memory, swap, load,
|
|
389
|
+
temperature), or a dynamic DNS change. Opt-in, rate-limited per server *and* reason, and the bot token
|
|
390
|
+
stays in the secrets file. **Two minutes of setup: [NOTIFICATIONS.md](./docs/NOTIFICATIONS.md).**
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## 🌐 Dynamic DNS
|
|
395
|
+
|
|
396
|
+
**Settings → Dynamic DNS** keeps a list of hostnames pointed at this machine's public IP — add an
|
|
397
|
+
account, paste its credentials, add hostnames. The panel checks the address on an interval and calls a
|
|
398
|
+
provider only when it actually changed, and the last confirmed address survives a restart. Provider
|
|
399
|
+
tokens stay in the secrets file. **Providers and the config shape: [DDNS.md](./docs/DDNS.md).**
|
|
387
400
|
|
|
388
401
|
---
|
|
389
402
|
|