The wrapper's config writing is gone: --env-file FILE selects the target instance (default .env; named like docker's flag — --env means a single variable there), the init fragment named by WERKATOR_INIT_CONFIG is uploaded and installed remotely via 'werkator init --apply', and instance-start places the .htaccess that init now generates. The heredoc/sed machine-config writing is deleted; control-token delegates to the werkator CLI; check-prerequisites uploads werkdock and runs its doctor — tools/werkator-build-prerequisites.sh retires. The idle-check and port-forward port lookups read the effective config via config:print, so a port living in the applied fragment is found too. Verified live against mih34 with the .env.mih34 + .env.mih34.yml pair (gitignored via the new /.env.* rule): update, doctor PASS 6/6, repo-init applying the fragment as the new layer, instance-start placing the generated proxy and restarting the unit, control-token. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
59 lines
6.4 KiB
Markdown
59 lines
6.4 KiB
Markdown
# Step 23: Init Owns the Files, `tools/remote` Wraps
|
|
|
|
Prerequisites: step 21 session D (the role-named `tools/remote`).
|
|
Read `README.md` first.
|
|
|
|
## The Problem
|
|
|
|
`werkator init` and `tools/remote` overlap: both write the machine config — init as a commented template, the script by appending heredoc blocks (`bwrap`, `server`) and patching values with `sed`.
|
|
The script re-implements configuration knowledge Werkator owns (YAML shape, indentation, key names), outside the three-places sync invariant — the indentation-mismatch of one append guard produced nine duplicate `bwrap` blocks on mih34 before it was found.
|
|
Smaller duplications of the same kind: the script re-implements control-token generation in bash (`ControlTokenService` owns it), and `check-prerequisites` still pipes the bash script whose generic half exists as `werkdock doctor`.
|
|
|
|
## The Decision (2026-09-01)
|
|
|
|
Werkator becomes the executing app wherever possible; `tools/remote` shrinks to a wrapper: build artifacts locally, transport them, execute Werkator/werkdock remotely, switch services.
|
|
|
|
Parameters travel as **files**, not as many CLI options — and each side gets the format that is native to it (refined 2026-09-01):
|
|
|
|
- The **wrapper** keeps a small, bash-sourceable env file with the transport values only: `tools/remote --env-file .env.mih34 werkator repo-init` selects the target (default: `.env`; named `--env-file` like docker's flag for the same thing, since `--env` means a single variable there), so several instances (`.env.mih34`, `.env.vm4006`, later a Werkbaum instance) are files, not edits.
|
|
- **Werkator** takes a **YAML fragment in its own config schema**: `werkator init --apply mih34.yml` deep-merges the fragment into the machine config, idempotently — creating sections that are missing, updating the given values, never duplicating.
|
|
No mapping table exists: the fragment says `server: {port: …}` and `builds: {default: {bwrap: …}}` directly, is validated by the existing schema binding, and is documented by the existing `docs/configuration.md`.
|
|
- The wrapper uploads the fragment alongside the artifacts and calls `werkator init --apply …` remotely — the heredocs and `sed` calls in `tools/remote` disappear.
|
|
- The env file names the fragment (`WERKATOR_INIT_CONFIG=mih34.yml`), keeping one entry point per instance.
|
|
|
|
The removed legacy env-to-YAML conversion stays removed — there is no conversion at all anymore: the fragment already *is* configuration in the one schema, applied once at setup time; the server reads nothing but its YAML at runtime.
|
|
|
|
## The Files per Instance
|
|
|
|
- `.env.mih34` (wrapper): `WERKATOR_REMOTE`, `WERKATOR_PATH`, `WERKATOR_LOCAL_PORT`, `WERKATOR_REPO_URL`, `WERKATOR_ROOTFS` (the *local* archive to upload), `WERKATOR_INIT_CONFIG`.
|
|
- `mih34.yml` (init fragment): `server.*` (port, publicBaseUrl, systemd limits) and `builds.default.bwrap.*` (enabled, the *remote* rootfs path, werkdock path) — exactly the blocks the script used to append.
|
|
- Secrets (`git.token`, `gitea` keys) stay out of both files on purpose — they are entered in the machine config on the host, as today.
|
|
|
|
## The Sessions
|
|
|
|
### A — Werkator side (implemented 2026-09-01 on branch `init-apply-config`)
|
|
|
|
- `init --apply FILE`: deep-merge the YAML fragment into the machine config — reusing the loader's merge, creating missing sections, updating given values, never duplicating (the duplication class dies here); a fragment that fails the schema binding or carries unknown keys is refused loudly.
|
|
- `init --systemd` keeps generating the units; decide in the session whether the Apache `.htaccess` becomes part of the host-integration output when the applied config carries `server.port` and a public domain (proposal: yes, under `init --systemd`, since it is generated host integration exactly like the units).
|
|
- New subcommand `werkator control-token`: print the token, creating it exactly like `ControlTokenService` does — the bash duplication in the wrapper dies.
|
|
- Tests per the writing-tests conventions; `docs/bootstrapping.md` documents `--apply` (the fragment keys need no new reference — they are ordinary `docs/configuration.md` keys).
|
|
|
|
### B — Wrapper side (implemented 2026-09-01 on branch `init-apply-config`)
|
|
|
|
- `tools/remote --env-file FILE` (default `.env`); the init fragment named by `WERKATOR_INIT_CONFIG` is uploaded, and the remote init runs with `--apply`.
|
|
- `repo-init` and `instance-start` lose their heredoc/`sed` config writing; `control-token` delegates to the new subcommand.
|
|
- `check-prerequisites` uploads the werkdock binary first and runs `werkdock doctor`; `tools/werkator-build-prerequisites.sh` retires (its werkdock port is the survivor).
|
|
|
|
### C — Live verification and docs (done 2026-09-01)
|
|
|
|
- Run the full wrapper flow against mih34 (`instance-update`, `repo-init`, `instance-start` as no-op re-runs); `docs/deployment.md`'s webspace section switches to the `--env` invocations.
|
|
|
|
## Acceptance Criteria
|
|
|
|
- Session A: done 2026-09-01 — `werkator init --apply …` installs and replaces a fragment idempotently; `werkator control-token` exists; full suite green.
|
|
Deviation from the sketch above: the fragment is NOT merged into the machine config — it is installed verbatim as its own layer (`.git/werkator/.werkator.applied.yml`, above project, below machine config), because an in-place merge would re-serialize the machine config, destroying its comments and rewriting the file that holds the secrets; a verbatim copy also makes re-apply a plain file replacement.
|
|
The `.htaccess` decision fell as proposed: generated beside the units by `init --systemd` whenever a `publicBaseUrl` is configured; the wrapper copies it into the domain docroot.
|
|
- Session B: done 2026-09-01 — `tools/remote` contains no YAML heredocs and no `sed` into the machine config (the port lookups for idle check and port-forward read the *effective* config via `config:print`, so a port living in the applied fragment is found too); the prerequisites bash script is gone.
|
|
- Session C: done 2026-09-01 — verified live on mih34 with the `.env.mih34` + `.env.mih34.yml` pair: instance-update, doctor-based check-prerequisites (PASS 6/6), repo-init applying the fragment, instance-start placing the generated `.htaccess` and restarting the unit, control-token via the CLI; `docs/deployment.md` shows only `--env-file`-style calls.
|
|
Known niggle: validating a fragment that carries a `builds.default` without triggers logs the loader's "no build defines onPush" warning, although a fragment is judged out of context — cosmetic, fix when it annoys.
|