Zones, Cache, Blocking, DNS Client, Settings, DHCP and Logs can now be
changed on one chosen server through the hub, with that server's admin
token. Operators manage cache and blocking; admins also zones, settings
and DHCP. Under "All servers", or on a server without an admin token,
the controls are disabled with a hint.
The hub refuses settings/set changes to a server's web service fields
and anything about users, SSO or LDAP; backup, restore, log and stats
deletion and admin/* stay refused. Non-admins get settings with secrets
blanked. Write params travel in the POST body, downloads pass through
with a single-use token, and the audit log names no values.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Every saved config, and every earlier baseline, is listed per app. You
can view it, diff it against a server's current config, and roll it back
through preview and apply. Earlier baselines can be restored.
A drift check (HUB_DRIFT_MINUTES, default 15) compares each server with
its effective config. Drift shows in the header and the matrix, with
Accept as baseline and Revert to baseline. All baselines export to one
file. Importing that file shows a dry run before it writes.
Rolling back preselects, and diffs against, the server the version came
from. The line-diff op "del" is renamed to "remove" for the language lint.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Writes use only <ID>_ADMIN_TOKEN and need the apps.write capability.
Store URLs are resolved from each server's own listing. The config is saved
to history before an uninstall. Zip uploads are fanned out to the servers.
Every target's result is audited. The console gets a row menu on the
matrix, a target picker, a results dialog with Retry failed, the store and
install from file in All servers mode, and single-server actions for writers.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Users in HUB_DATA/users.json with scrypt hashes and roles (viewer, operator,
apps-admin, admin), managed by hub/users-cli.ts; HUB_USER/HUB_PASSWORD remain a
bootstrap admin while the file does not exist. Five failed logins in 15 minutes lock
the address or the name for 15 minutes. Logins, logouts and every refused request go
to a JSON Lines audit log that admins read through hub/audit/list. Endpoints are
listed in routes.ts with their kind and capability; writes stay refused for now.
Optional <ID>_ADMIN_TOKEN is read for the coming write stages. The management plan
is in docs/hub-management-plan.md.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
docker/Dockerfile.hub builds the console and ships it with the hub sources on
node:22-alpine, without node_modules, as a non-root user with a healthcheck.
.gitea/workflows/hub.yaml checks and pushes git.shx.one/denozord/technitium-hub
(latest from main, sha-*, X.Y.Z and X.Y from hub-v tags), independent of the console
pipeline, which now ignores hub-only changes. Compose example for hub.shnt.top and
hub/README.md, with the read-only permissions each server's token needs.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>