home-hosted 0.7.3 → 0.7.5
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 +12 -8
- package/README.md +26 -36
- package/dist/cli.js +179 -60
- package/dist/cli.js.map +1 -1
- package/docs/NOTIFICATIONS.md +1 -1
- package/docs/REVERSE_PROXY.md +5 -5
- package/docs/SERVERS.md +3 -2
- package/docs/UI_CREATION.md +5 -4
- package/package.json +1 -1
- package/uis/stock/dist/assets/{index-DoDrajgK.js → index-5B9zsc8b.js} +3 -3
- package/uis/stock/dist/assets/{index-JGpABIqV.css → index-D8S55m4E.css} +1 -1
- package/uis/stock/dist/index.html +2 -2
- package/uis/stock/dist/ui.json +3 -3
package/AGENTS.md
CHANGED
|
@@ -12,8 +12,9 @@ level: `settings.json` (listener, auth, TLS policy, host vitals, backups, revers
|
|
|
12
12
|
`.backups/`, `.ui/`, `.logs/` (the panel console), `.proxy/` (the reverse-proxy engine, its generated
|
|
13
13
|
configuration and its nanny state), and `run.json` — the live daemon's pid/url/token, 0600. Every workspace owns
|
|
14
14
|
`.hh/<id>/`: `settings.json` (server defaults, log retention, notifications, DDNS), `servers.config.json`,
|
|
15
|
-
`.secrets.json` (0600: Telegram bot token
|
|
16
|
-
`HHOSTED_DDNS_SECRET`
|
|
15
|
+
`.secrets.json` (0600: Telegram bot token, plus DDNS credentials sealed with AES-256-GCM under
|
|
16
|
+
`HHOSTED_DDNS_SECRET` — only DDNS is sealed, because it is the one thing replayed to a third party),
|
|
17
|
+
`.logs/`, and `.state/` (a persistent entry's nanny state plus its 0600 spawn
|
|
17
18
|
spec until the nanny reads it, plus `ddns.json`). A pre-`.hh` instance is relocated automatically by
|
|
18
19
|
`ensureLayout()` (`src/config/layout.ts`). The package ships **no servers**: never commit a config, a
|
|
19
20
|
seed entry, or a path that names one.
|
|
@@ -165,9 +166,10 @@ a minor without one.
|
|
|
165
166
|
- A single on/off setting is a `ToggleSwitch`; `CheckField` is only for picking items out of a set
|
|
166
167
|
(the restore plan). A checkbox in a `FieldGroup` grid reads as misaligned next to the inputs.
|
|
167
168
|
- A create body carries only what differs from what the entry would inherit — the schema's defaults
|
|
168
|
-
with `Workspace Settings → Server defaults` on top (`inheritBaseline`
|
|
169
|
-
|
|
170
|
-
person did not decide stays out; the editor applies the
|
|
169
|
+
with `Workspace Settings → Server defaults` on top (each UI's own `inheritBaseline` plus the shared
|
|
170
|
+
`diffFields` in `src/shared/patch-diff.ts`). A value written into `servers.config.json` stops
|
|
171
|
+
following those defaults, so anything the person did not decide stays out; the editor applies the
|
|
172
|
+
same rule to an edit.
|
|
171
173
|
- ArkType at every runtime boundary: routes use `validate('json'|'query'|'param', schema)` then
|
|
172
174
|
`c.req.valid(...)`; ad-hoc payloads use `parseOrThrow`. Schemas reject undeclared keys.
|
|
173
175
|
- Every failure is a `DetailedError` (`@namesmt/utils`), mapped by `src/helpers/error.ts` into one
|
|
@@ -277,10 +279,12 @@ either is a last resort, and never an accidental one.
|
|
|
277
279
|
boot through `.state/<id>.json` before any port preflight (`nannyIsAlive` = live pid **and** a fresh
|
|
278
280
|
heartbeat, the `HHOSTED_SERVER_ID` marker or the argv), tails that file for live logs, and reads
|
|
279
281
|
`lastExit` once so a crash nobody watched is reported. The spawn spec is consumed by the read and
|
|
280
|
-
swept at boot — it carries expanded env.
|
|
282
|
+
swept at boot — it carries expanded env. Three lifetimes are pinned: the nanny **exits with its child**
|
|
281
283
|
(an inherited pipe would keep it alive, and the panel would report a healthy entry whose server is a
|
|
282
|
-
detached stranger),
|
|
283
|
-
`killGroup: false` cannot be forwarded — which is why a self-restarting program belongs on `reclaim
|
|
284
|
+
detached stranger), a stop reaches the child by pid from the state file, because `SIGKILL` and
|
|
285
|
+
`killGroup: false` cannot be forwarded — which is why a self-restarting program belongs on `reclaim` —
|
|
286
|
+
and its `SIGTERM`/`SIGINT` traps are armed *before* the child exists and before that state file
|
|
287
|
+
appears, so a stop that beats the spawn can never orphan a child nobody has a record of.
|
|
284
288
|
The nanny never restarts anything: retries and health stay the supervisor's. `logs.persist: false`
|
|
285
289
|
keeps that file out of the Logs page but never stops it being written — it is the transport.
|
|
286
290
|
- **A port is only ever freed by re-listing its listeners.** `POST /api/servers/:id/free-port` never
|
package/README.md
CHANGED
|
@@ -25,7 +25,7 @@ them, watches them, restarts what dies, and shows you one page of what is going
|
|
|
25
25
|
|
|
26
26
|
<div align="center">
|
|
27
27
|
|
|
28
|
-

|
|
29
29
|
|
|
30
30
|
<sub>The stock panel, the [NOC-console](./uis/noc-console) that ships alongside it (for TUI and
|
|
31
31
|
shortcuts wizards), and UI directions you could build yourself —
|
|
@@ -163,13 +163,13 @@ Worked example, with per-server data inside the project:
|
|
|
163
163
|
<sub>Call them as `pnpm run up` — `pnpm up` is pnpm's own update, not your script.</sub>
|
|
164
164
|
|
|
165
165
|
> [!TIP]
|
|
166
|
-
>
|
|
167
|
-
>
|
|
166
|
+
> Recommended to give a project its own panel port (`control.port`, e.g. `4399`), to avoid port conflict
|
|
167
|
+
> with other projects.
|
|
168
168
|
|
|
169
169
|
</details>
|
|
170
170
|
|
|
171
171
|
<details>
|
|
172
|
-
<summary><b>🧰 Run it under systemd or Docker
|
|
172
|
+
<summary><b>🧰 Run it under systemd or Docker</b></summary>
|
|
173
173
|
|
|
174
174
|
```bash
|
|
175
175
|
home-hosted up --foreground # stays in the foreground, logs to stderr
|
|
@@ -179,12 +179,16 @@ home-hosted up --foreground # stays in the foreground, logs to stderr
|
|
|
179
179
|
[Unit]
|
|
180
180
|
Description=home-hosted
|
|
181
181
|
[Service]
|
|
182
|
+
User=$YOUR_USER
|
|
182
183
|
ExecStart=/usr/local/bin/home-hosted up --foreground
|
|
183
184
|
Environment=HHOSTED_HOME=/srv/home-hosted
|
|
184
185
|
Restart=always
|
|
185
186
|
[Install]
|
|
186
187
|
WantedBy=multi-user.target
|
|
187
188
|
```
|
|
189
|
+
> [!CAUTION]
|
|
190
|
+
> Note: change `$YOUR_USER` to your actual user account, or remove for `root`.
|
|
191
|
+
> You could also change `/srv/home-hosted` to change where the data stores.
|
|
188
192
|
|
|
189
193
|
</details>
|
|
190
194
|
|
|
@@ -228,11 +232,11 @@ default workspace.
|
|
|
228
232
|
| `GET`/`PATCH /api/settings/workspace` | server defaults, logs, notifications | ✅ |
|
|
229
233
|
| `GET`/`PATCH /api/settings` | panel-wide: listener, authentication, TLS, host vitals, backups | ❌ |
|
|
230
234
|
| `GET`/`POST /api/backups`, restore | archives | ❌ |
|
|
235
|
+
| `GET`/`PATCH /api/proxy`, `POST /api/proxy/{engine,start,stop,apply,revert}`, `PUT`/`DELETE /api/proxy/certificates/:id` | the reverse proxy: its engine, its route table, and its uploaded certificates | ❌ |
|
|
231
236
|
| `GET /healthz` | no session needed — the one an external monitor wants (its per-server detail needs a credential) | ❌ |
|
|
232
237
|
| `GET /api/metrics` | Prometheus text (needs a token or session, like every `/api` route) | ❌ |
|
|
233
238
|
|
|
234
|
-
✅ takes `?workspace=<id>`; ❌ is panel-wide. Omitting
|
|
235
|
-
another one.
|
|
239
|
+
✅ takes `?workspace=<id>`; ❌ is panel-wide. Omitting `?workspace` means `default` workspace is used.
|
|
236
240
|
|
|
237
241
|
`GET /openapi/spec.json` describes all of it, `/openapi/ui` is the browsable version, and every error
|
|
238
242
|
comes back as one envelope (`{ message, code, detail }`) with a stable `code` a tool can branch on.
|
|
@@ -273,7 +277,7 @@ can be told what to be: *"Help me build a UI for home-hosted: nostalgic game the
|
|
|
273
277
|
| 🔔 **Notifications** | Telegram on crash, unhealthy, forced restart, recovery, host thresholds and DNS changes — [setup here](./docs/NOTIFICATIONS.md). |
|
|
274
278
|
| 🌐 **Dynamic DNS** | Keep hostnames pointed at your public IP — Cloudflare, Namecheap, Spaceship, Porkbun, GoDaddy, Gandi and more. [DDNS.md](./docs/DDNS.md) |
|
|
275
279
|
| 🔀 **Reverse proxy** | One engine in front of everything, with automatic HTTPS: `git.example.com` → a Gitea entry, `media.example.com` → a service on another box, `panel.example.com` → the panel. Caddy, installed and supervised by the panel. [REVERSE_PROXY.md](./docs/REVERSE_PROXY.md) |
|
|
276
|
-
| 💾 **Backups** |
|
|
280
|
+
| 💾 **Backups** | Deep and customizable: pick global settings, global secrets, TLS, Workspaces, then the pieces inside it (workspace settings, servers, secrets, data directories) — plain `.zip`, or AES-256 with a password, customized restore is supported too! |
|
|
277
281
|
| 🎨 **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) |
|
|
278
282
|
| 🔐 **Security** | Cookie sessions, API tokens, scrypt hashes, per-IP lockout, optional TLS, and a refusal to expose itself without a password. |
|
|
279
283
|
| 🧩 **No special treatment** | A server is `command` + `args` + `env` + `cwd`; nothing is built in for any particular app. |
|
|
@@ -283,27 +287,17 @@ can be told what to be: *"Help me build a UI for home-hosted: nostalgic game the
|
|
|
283
287
|
|
|
284
288
|
## 🗂 Workspaces
|
|
285
289
|
|
|
286
|
-
A workspace is the ownership boundary: its own servers, secrets, logs,
|
|
287
|
-
|
|
288
|
-
what it supervises first). The first boot creates a `default` workspace; a pre-workspaces instance is
|
|
289
|
-
relocated into one automatically.
|
|
290
|
-
|
|
291
|
-
> [!IMPORTANT]
|
|
292
|
-
> **Upgrading from before workspaces (0.6 → 0.7)?** That release is breaking: state moves under
|
|
293
|
-
> `$HHOSTED_HOME/.hh`, settings split global vs. per-workspace, and backups become two-level. The
|
|
294
|
-
> relocation runs on the next command — `home-hosted migrate` reports it and stamps every file. See
|
|
295
|
-
> [Upgrading](#-cli).
|
|
290
|
+
A workspace is the ownership boundary: its own servers, secrets, logs, states and settings.
|
|
291
|
+
The first boot creates a `default` workspace.
|
|
296
292
|
|
|
297
293
|
| page | url | scope |
|
|
298
294
|
| --- | --- | --- |
|
|
299
295
|
| **Overview** | `/w/<workspace>` | the selected workspace: its servers, counts and live status |
|
|
300
296
|
| **Servers** · **Logs** · **Workspace settings** | `/w/<workspace>/servers` · `/w/<workspace>/logs` · `/w/<workspace>/settings` | the selected workspace |
|
|
297
|
+
| **One server** | `/w/<workspace>/servers/<id>` | that entry: config, live logs, resources |
|
|
301
298
|
| **Global Overview** | `/global/overview` | host vitals plus every server from every workspace |
|
|
302
299
|
| **Global settings** | `/global/settings` | Listener, Authentication, Host vitals, Backups, TLS, Interface, Paths |
|
|
303
|
-
|
|
304
|
-
Every page is bookmarked by its own URL: the workspace id is part of it, so a link opens the same
|
|
305
|
-
workspace even in a browser that never selected it. `/` opens **Global Overview**. The sidebar lists
|
|
306
|
-
the panel-wide pages first, then the selected workspace's.
|
|
300
|
+
| **Reverse Proxy** | `/proxy` | panel-wide: one engine, every workspace's servers ([REVERSE_PROXY.md](./docs/REVERSE_PROXY.md)) |
|
|
307
301
|
|
|
308
302
|
<details>
|
|
309
303
|
<summary><b>🗂 What lives where</b></summary>
|
|
@@ -334,6 +328,7 @@ An entry is a few lines. Add one with **➕ Add server**, or write it into the s
|
|
|
334
328
|
```
|
|
335
329
|
|
|
336
330
|
`dataEnvs` declares a data directory once: it is exported to the process *and* picked up by Backups.
|
|
331
|
+
|
|
337
332
|
**Every field, every placeholder, the port-conflict policies (including adopting a server that
|
|
338
333
|
restarts itself), and how hand-edits are validated: [SERVERS.md](./docs/SERVERS.md).**
|
|
339
334
|
|
|
@@ -352,9 +347,9 @@ restarts itself), and how hand-edits are validated: [SERVERS.md](./docs/SERVERS.
|
|
|
352
347
|
| `home-hosted set-password` | set the panel password without opening a browser |
|
|
353
348
|
| `home-hosted set-token` | set the API token scripts and agents use (`--generate`, `--clear`) |
|
|
354
349
|
| `home-hosted migrate` | relocate a pre-workspaces state directory and stamp every config for this release (`--dry-run`, `--yes`) |
|
|
355
|
-
| `home-hosted init` | scaffold a project
|
|
350
|
+
| `home-hosted init` | scaffold a self-contained project, whose scripts keep state in the repo (`--home ./state`) |
|
|
356
351
|
| `home-hosted ui-switch` | install a UI from a release asset, a zip file or a URL (interactive) |
|
|
357
|
-
| `home-hosted ui-update` | bring an installed UI up to date
|
|
352
|
+
| `home-hosted ui-update` | bring an installed UI up to date automatically (official UI) or pick a release (`--old`, `--check`) |
|
|
358
353
|
| `home-hosted ui-revert` | go back to the stock panel UI after uploading your own |
|
|
359
354
|
|
|
360
355
|
<details>
|
|
@@ -390,16 +385,6 @@ for a launcher that pins one; a workspace picked in the UI keeps its own. `start
|
|
|
390
385
|
<details>
|
|
391
386
|
<summary><b>🧭 Upgrading, and why the panel sometimes refuses to start</b></summary>
|
|
392
387
|
|
|
393
|
-
> **Breaking in 0.7 — workspaces.** State moved under `$HHOSTED_HOME/.hh`: global files at its top
|
|
394
|
-
> level, one directory per workspace. Settings split into panel-wide **Global settings** and
|
|
395
|
-
> per-workspace **Workspace settings**, backups became two-level, and `--config` now points at the
|
|
396
|
-
> default workspace's servers file. The old `servers.config.json` becomes
|
|
397
|
-
> `.hh/default/servers.config.json`.
|
|
398
|
-
|
|
399
|
-
Relocation is automatic: the CLI relocates a pre-`.hh` `$HHOSTED_HOME` before any command runs, so an
|
|
400
|
-
existing instance keeps working after the upgrade. `home-hosted migrate` reports what it moved and
|
|
401
|
-
stamps every file for this release:
|
|
402
|
-
|
|
403
388
|
```bash
|
|
404
389
|
home-hosted migrate --dry-run # print the steps, write nothing
|
|
405
390
|
home-hosted migrate # ask, then write — keeps a .bak beside each rewritten file
|
|
@@ -582,7 +567,10 @@ run.json the running panel (pid, url, token, mode 0600)
|
|
|
582
567
|
<details>
|
|
583
568
|
<summary><b>Which ports does it use?</b></summary>
|
|
584
569
|
|
|
585
|
-
|
|
570
|
+
The control panel, `3999` by default. Supervised servers use the ports you give them. The reverse
|
|
571
|
+
proxy is the one panel-wide listener, and only when you switch it on: `80`/`443` for automatic HTTPS,
|
|
572
|
+
or `4480`/`4443` unprivileged with your router forwarding to them
|
|
573
|
+
([REVERSE_PROXY.md](./docs/REVERSE_PROXY.md#ports)).
|
|
586
574
|
|
|
587
575
|
</details>
|
|
588
576
|
|
|
@@ -591,7 +579,9 @@ Just the control panel, `3999` by default. Supervised servers use the ports you
|
|
|
591
579
|
|
|
592
580
|
Yes. Process trees are sampled from Win32_Process, termination uses `taskkill /T`, and the shipped
|
|
593
581
|
examples avoid POSIX-only commands. CPU temperature and swap are best-effort where the OS does not
|
|
594
|
-
expose them to an unprivileged process
|
|
582
|
+
expose them to an unprivileged process. Adopting a self-restarted process works on Windows too, off
|
|
583
|
+
its argv instead of the environment marker; a launcher whose real process is a `.cmd` shim is the one
|
|
584
|
+
case it cannot see through, and `kill` is the answer there.
|
|
595
585
|
|
|
596
586
|
</details>
|
|
597
587
|
|
|
@@ -634,7 +624,7 @@ plus types; `pnpm test` is vitest; `pnpm run media` regenerates the GIF above.
|
|
|
634
624
|
<details>
|
|
635
625
|
<summary><b>🔗 Interesting resources</b></summary>
|
|
636
626
|
|
|
637
|
-
- [dsh-home-hosted](https://github.com/NamesMT/dsh-home-hosted) — home-hosted servers management with boot autostart from inside [DeepSeek Harness](https://github.com/deepseek-ai/
|
|
627
|
+
- [dsh-home-hosted](https://github.com/NamesMT/dsh-home-hosted) — home-hosted servers management with boot autostart from inside [DeepSeek Harness](https://github.com/deepseek-ai/deepseek-harness)
|
|
638
628
|
|
|
639
629
|
<sub><i>+ PR to add yours</i></sub>
|
|
640
630
|
|