feat(worker): adopt canonical public URL
Все проверки выполнены успешно
CI / test (push) Successful in 10m15s
Docker / Build and publish worker image (push) Successful in 34m59s
Все проверки выполнены успешно
CI / test (push) Successful in 10m15s
Docker / Build and publish worker image (push) Successful in 34m59s
Этот коммит содержится в:
@@ -78,10 +78,14 @@ provided by a validated control-plane task.
|
||||
Raft, and closes SQLite without exceeding the service stop timeout.
|
||||
- A web-console failure is reported and causes an intentional process policy;
|
||||
it must not silently leave a partially healthy process.
|
||||
- Startup currently rejects malformed `WORKER_URL`; the accepted target is
|
||||
`PUBLIC_URL` with bounded compatibility migration. Startup also rejects
|
||||
incomplete auth credentials, invalid cluster settings, and unwritable data
|
||||
directories before accepting work.
|
||||
- Startup validates the advertised origin: canonical `PUBLIC_URL` is held to
|
||||
the strict scheme-and-authority shape (no userinfo, query, fragment, or
|
||||
ambiguous path) and plain HTTP on a non-loopback host is rejected in an
|
||||
explicitly production environment; the legacy `WORKER_URL` is read as a
|
||||
bounded-migration fallback, held only to the tolerant absolute-URL check,
|
||||
and logged with a deprecation warning. Both reject a missing hostname, e.g.
|
||||
`https://:27401`. Startup also rejects incomplete auth credentials, invalid
|
||||
cluster settings, and unwritable data directories before accepting work.
|
||||
- `GET /healthz` reports process-local liveness. Control-plane reachability is
|
||||
a separate readiness/selfcheck signal and must not make a healthy container
|
||||
fail its local liveness probe.
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
# Changelog
|
||||
|
||||
## 2026-08-12
|
||||
|
||||
### Public endpoint configuration (milestone 1 of public-endpoint-and-identity)
|
||||
|
||||
- `PUBLIC_URL` is now the canonical advertised public origin; the legacy
|
||||
`WORKER_URL` is accepted only for the bounded migration and logs a startup
|
||||
deprecation warning. `PUBLIC_URL` wins whenever both are set, and the
|
||||
installer drops `WORKER_URL` from freshly written env files when
|
||||
`PUBLIC_URL` is present.
|
||||
- Startup and install validate the origin shape: absolute `http`/`https` URL
|
||||
with scheme and authority only; userinfo, query, fragment, and any path
|
||||
other than `/` are rejected.
|
||||
- Plain-HTTP `PUBLIC_URL` on a non-loopback host is rejected in an explicitly
|
||||
production environment (`DEPLOY_ENV`, `RSMON_ENV`, or `GO_ENV` =
|
||||
`production`); other environments keep the historical warning.
|
||||
- `internal/wire` adds `public_url` to `WorkerInit` (control plane to worker),
|
||||
keeping the legacy `url` field for old control planes; the worker prefers
|
||||
`public_url` and rejects unusable values, keeping the previous accepted
|
||||
URL. `RegisterRequest.public_url` is the registration contract for the
|
||||
pending RSMon counterpart (the worker does not currently transmit the URL
|
||||
during registration; it consumes the accepted endpoint from `WorkerInit`).
|
||||
- The legacy `WORKER_URL` is held only to the tolerant absolute-URL check
|
||||
(no newly rejected legacy shapes); `PUBLIC_URL` is held to the strict
|
||||
scheme-and-authority origin shape. Both reject a missing hostname, e.g.
|
||||
`https://:27401`.
|
||||
|
||||
## 2026-07-19
|
||||
|
||||
### Standalone installation and deployment
|
||||
|
||||
@@ -46,9 +46,9 @@ without execution or reporting.
|
||||
|
||||
## Initialization And Refresh
|
||||
|
||||
The worker proposes `PUBLIC_URL` during registration. The control plane
|
||||
validates and canonicalizes it; `wire.WorkerInit` returns the accepted endpoint
|
||||
and supplies runtime values owned by the control plane:
|
||||
The worker is expected to propose `PUBLIC_URL` during registration and the
|
||||
control plane to validate and canonicalize it; `wire.WorkerInit` returns the
|
||||
accepted endpoint and supplies runtime values owned by the control plane:
|
||||
|
||||
- worker ID, region, advertised URL, capabilities, and concurrency;
|
||||
- allowed notification methods and account IDs;
|
||||
@@ -57,6 +57,12 @@ and supplies runtime values owned by the control plane:
|
||||
- scoped notification credentials and system contacts;
|
||||
- signed, cluster-scoped peer topology for selfcheck and Raft behavior.
|
||||
|
||||
Current worker behavior: the worker validates its local `PUBLIC_URL`
|
||||
configuration at startup and *consumes* the accepted endpoint from
|
||||
`wire.WorkerInit` (preferring `public_url`, falling back to the legacy `url`
|
||||
field). Transmitting the proposed URL during registration is the pending RSMon
|
||||
control-plane counterpart; the worker does not currently send it.
|
||||
|
||||
Worker ID, account, region, cluster, membership, role, topology generation, and
|
||||
certificate identity are control-plane authority. Local environment or a peer
|
||||
response cannot override them. Static peer environment remains lab-only.
|
||||
@@ -65,6 +71,14 @@ The worker clamps supplied concurrency to its local maximum. Credentials are
|
||||
replaced atomically in memory on refresh. Removed credentials must become
|
||||
unavailable immediately after the refresh is applied.
|
||||
|
||||
`wire.WorkerInit` returns the accepted endpoint as `public_url`, with the
|
||||
legacy `url` field still populated during the bounded migration; the worker
|
||||
prefers `public_url` and ignores an unusable value (keeping the previous
|
||||
accepted URL). `RegisterRequest.public_url` is the registration contract the
|
||||
RSMon control-plane counterpart must populate when it wires worker-initiated
|
||||
registration; the worker does not transmit it today. See
|
||||
[public-endpoint-and-identity.md](public-endpoint-and-identity.md).
|
||||
|
||||
Private-worker hardening will add an immutable worker account ID, config
|
||||
version, expiry, and signature. Until then the executable trusts the
|
||||
authenticated control plane to send a correctly scoped config; server-side
|
||||
|
||||
@@ -30,8 +30,10 @@ Worker repository:
|
||||
|
||||
- wire local inventory and metrics collector lifecycle into web server start
|
||||
and shutdown;
|
||||
- validate full HTTP config, including the accepted `PUBLIC_URL`, in main
|
||||
startup;
|
||||
- [x] validate full HTTP config, including the accepted `PUBLIC_URL`, in main
|
||||
startup (milestone 1 of
|
||||
[public-endpoint-and-identity.md](public-endpoint-and-identity.md): origin
|
||||
shape, production HTTPS, legacy `WORKER_URL` fallback);
|
||||
- [x] reconnect in memory on token rotation without stopping the runner;
|
||||
- [x] resend bounded check/notification results after websocket reconnect;
|
||||
- define process policy when the web listener exits unexpectedly;
|
||||
|
||||
@@ -33,8 +33,8 @@ sudo apt-get install -y ca-certificates chromium libcap2-bin tzdata
|
||||
The installer reads the same environment variables the worker runtime reads.
|
||||
Each variable is resolved with this precedence (highest first):
|
||||
|
||||
1. **Explicit flags** (`--url`, `--token`, `--host`, `--port`, `--login`,
|
||||
`--password`, `--name`).
|
||||
1. **Explicit flags** (`--url`, `--public-url`, `--token`, `--host`, `--port`,
|
||||
`--login`, `--password`, `--name`).
|
||||
2. **`--env-file`** — a strict, systemd-safe `KEY=VALUE` file (validated before
|
||||
anything is written to disk).
|
||||
3. **Process environment**, including a `.env` file in the working directory
|
||||
@@ -54,7 +54,7 @@ values automatically. To override a value, pass the matching flag.
|
||||
| `RSMON_TOKEN` | yes | none | Worker bearer token. |
|
||||
| `WORKER_HOST` | no | `127.0.0.1` | Operator-console bind address. |
|
||||
| `WORKER_PORT` | no | `27401` (primary) | Operator-console port. **Required** for named instances. |
|
||||
| `PUBLIC_URL` | no | none | Proposed public HTTPS origin; accepted by the control plane. |
|
||||
| `PUBLIC_URL` | no | none | Advertised public origin: absolute http(s) URL with scheme and authority only (no userinfo, query, fragment, or path). Canonical name; `WORKER_URL` is a deprecated legacy alias read only during the bounded migration. |
|
||||
| `WORKER_LOGIN` | no | `admin` (generated) | Operator-console basic-auth login. |
|
||||
| `WORKER_PASSWORD` | no | generated | Operator-console basic-auth password. |
|
||||
| `WORKER_COMPOSE_ENABLED` | no | feature default (on) | Enable Docker Compose discovery/management. |
|
||||
@@ -69,8 +69,19 @@ endpoints.
|
||||
|
||||
`PUBLIC_URL` does not bind a listener or terminate TLS. It advertises the one
|
||||
external origin used for the console, authenticated peer status, and planned
|
||||
Raft `/raft` transport. See
|
||||
[public-endpoint-and-identity.md](public-endpoint-and-identity.md).
|
||||
Raft `/raft` transport. It must be an absolute `http`/`https` URL with a scheme
|
||||
and authority and nothing else; a path (other than `/`), userinfo, query, or
|
||||
fragment is rejected at install time and at worker startup. `PUBLIC_URL` is the
|
||||
canonical variable; the legacy `WORKER_URL` is still accepted for the bounded
|
||||
migration defined in
|
||||
[public-endpoint-and-identity.md](public-endpoint-and-identity.md), and is
|
||||
dropped from a freshly written env file whenever `PUBLIC_URL` is also set.
|
||||
The legacy `WORKER_URL` is held only to the tolerant absolute-URL check, so
|
||||
shapes that previously installed keep working. In an explicitly production
|
||||
environment (`DEPLOY_ENV=production`, or `RSMON_ENV`/`GO_ENV=production`) a
|
||||
plain-HTTP `PUBLIC_URL` on a non-loopback host is rejected at startup; a legacy
|
||||
`WORKER_URL` keeps the historical warn-only behavior. Both variables reject a
|
||||
missing hostname, e.g. `https://:27401`.
|
||||
|
||||
Values must be systemd-safe: no whitespace, quotes, backslashes, or `$`
|
||||
interpolation inside a value. This keeps the file unambiguous across systemd
|
||||
@@ -208,6 +219,7 @@ rsmon-worker install [--token TOKEN|--token-file FILE|--env-file FILE]
|
||||
| `--token-file` | File containing the worker token (avoids shell history). |
|
||||
| `--env-file` | Strict worker env file; validated then used as the config source. |
|
||||
| `--url` | Control-plane URL (`RSMON_URL`). |
|
||||
| `--public-url` | Advertised public origin (`PUBLIC_URL`; scheme + host, no path). |
|
||||
| `--host` | Console bind address (`WORKER_HOST`). |
|
||||
| `--port` | Console port (`WORKER_PORT`; required with `--name`). |
|
||||
| `--login` | Console login (`WORKER_LOGIN`). |
|
||||
|
||||
@@ -6,6 +6,16 @@ Accepted target architecture. Ordinary peer status checks already support an
|
||||
external HTTPS worker URL. Raft currently uses a separate plaintext listener,
|
||||
static peers, and shared Basic authentication; it does not yet meet this plan.
|
||||
|
||||
Milestone 1 (worker side) is implemented: the worker configures `PUBLIC_URL`
|
||||
as the canonical advertised origin with the legacy `WORKER_URL` accepted only
|
||||
for a bounded migration, and validates the origin shape at startup and install
|
||||
time. On the wire the worker consumes the accepted endpoint from
|
||||
`wire.WorkerInit` (`public_url`, falling back to the legacy `url` field) and
|
||||
rejects unusable values. Transmitting the proposed URL during registration is
|
||||
the pending RSMon control-plane counterpart: it must populate `public_url` in
|
||||
`WorkerInit` and accept `RegisterRequest.public_url`; until then the worker
|
||||
reads whichever field the control plane sends.
|
||||
|
||||
## One Worker, One Public URL
|
||||
|
||||
Every worker configures one absolute `PUBLIC_URL`, for example:
|
||||
@@ -103,6 +113,16 @@ voter.
|
||||
|
||||
1. Add `PUBLIC_URL` wire/config fields while accepting legacy `WORKER_URL` only
|
||||
for a bounded migration.
|
||||
|
||||
Worker side implemented: `PUBLIC_URL` is canonical, `WORKER_URL` is a
|
||||
deprecated fallback with a startup warning, `internal/wire` carries
|
||||
`public_url` on `WorkerInit` (keeping `url` for compatibility), and
|
||||
startup/install enforce the strict origin shape for `PUBLIC_URL` while
|
||||
tolerating legacy `WORKER_URL` shapes. Control-plane counterpart: read
|
||||
`RegisterRequest.public_url` when worker-initiated registration is wired,
|
||||
populate `public_url` (not `url`) in `WorkerInit`, and persist the accepted
|
||||
origin. Until then the worker consumes whichever of `public_url`/`url` the
|
||||
control plane sends.
|
||||
2. Validate ownership/reachability and return accepted signed configuration.
|
||||
3. Add scoped, versioned in-memory peer topology and concurrent health probes.
|
||||
4. Extend status APIs/UI with networking, control-plane RTT, and Raft state.
|
||||
|
||||
Ссылка в новой задаче
Block a user