Skip to content

Commit f864ee8

Browse files
bpamiriclaude
andauthored
docs(web/guides): align deploy config-reference + architecture with verified CLI behavior (#3097)
* docs(web/guides): align deploy config-reference + architecture with verified CLI behavior Guide-behavioral-audit batch 2 (p1-16-deploy, cfg-*/arch-* claims). Both pages now describe what the released/develop CLI actually does and link the tracking issues for everything broken-but-unfixed instead of documenting aspirational behavior. config-reference.mdx: - Flag every accepted-but-ignored key (boot, logging, retain_containers, minimum_version, asset_path, require_destination, allow_empty_roles, run_directory, readiness_delay, hooks.path, builder.arch/args/remote, ssh.proxy/keys_only, proxy.forward_headers/buffering, role env/options/ labels, accessory files) and link #3088. - env: remove the nonexistent per-role precedence table; env.secret callout (dropped on 4.0.3, EnvSecretUnsupported on develop) citing #2956. - proxy: app_port default is 80, init writes 8080, deploy/rollback hardcode the proxy target to :3000 (#3089). - ssh: user defaults to root; ~/.ssh/config is not read (known_hosts is). - servers: every role currently gets a kamal-proxy deploy call (#2957); host validator colon-count gap (#3086). - Interpolation: drop the nonexistent CLI --env step; secrets resolve from config/.kamal/secrets (#3084). Overlays: config verb ignores --destination (#3085). Validation errors: absolute-path prefix, never line-scoped, plus the fourth invalid-name class (#3008). architecture.mdx: - Annotate aspirational byte-compat rows (audit log never written, kamal network never created, /home/root proxy dir) pending #2957. - Same --env removal + config/.kamal/secrets note (#3084). - init scaffolding renders four templates, not two. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com> * docs(web/guides): fix unsupported Ruby Kamal proxy-config-dir claim in byte-compat aside Ruby Kamal v2.4.0 boots kamal-proxy with a named Docker volume (kamal-proxy-config), not a host home path under /root, so the prior clause was a factual error. State the named-volume behavior and note the bind mount diverges from Kamal either way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Signed-off-by: Peter Amiri <peter@alurium.com> --------- Signed-off-by: Peter Amiri <peter@alurium.com> Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
1 parent 79cd0d3 commit f864ee8

2 files changed

Lines changed: 73 additions & 83 deletions

File tree

web/sites/guides/src/content/docs/v4-0-0/deployment/architecture.mdx

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -43,6 +43,14 @@ The design bet: a server managed by Ruby Kamal can be taken over by `wheels depl
4343
| Hook env prefix | `KAMAL_*` |
4444
| Secret file | `.kamal/secrets`, `.kamal/secrets.<destination>` |
4545

46+
<Aside type="caution" title="Three rows are still aspirational">
47+
The values above are what the code is written against, but three rows don't hold on a live host yet ([#2957](https://github.com/wheels-dev/wheels/issues/2957)):
48+
49+
- **Audit log**`/tmp/kamal-audit.log` is never written; the audit `record()` command builder has no call sites.
50+
- **Docker network** — containers are run with `--network kamal`, but `docker network create kamal` is never issued, so on a host not previously managed by Ruby Kamal the network doesn't exist.
51+
- **Proxy config dir** — the path is built as `/home/<user>/.config/kamal-proxy/`, which resolves to `/home/root` for the default `root` SSH user; root's home is actually `/root` — and Ruby Kamal mounts a named Docker volume (`kamal-proxy-config`) rather than a host home path, so the bind mount diverges from Kamal either way.
52+
</Aside>
53+
4654
Two choices in that table warrant commentary.
4755

4856
**Why `KAMAL_*` and not `WHEELS_*`.** Every hook script ever written for Ruby Kamal reads environment variables named `KAMAL_SERVICE`, `KAMAL_VERSION`, and so on. Renaming to `WHEELS_*` would be slightly more consistent with the rest of the Wheels CLI — and it would break every user's existing hook scripts for zero benefit.
@@ -78,10 +86,9 @@ image: ${REGISTRY}/${APP_NAME}
7886

7987
The interpolator (`ConfigLoader.$interpolate`) walks the parsed YAML tree and resolves each `${VAR}` token through this lookup chain:
8088

81-
1. CLI `--env` overrides (test/CI shims).
82-
2. `.kamal/secrets`, then `.kamal/secrets.<destination>` overlay if `--destination` is set.
83-
3. `System.getenv(VAR)` on the machine running `wheels deploy`.
84-
4. Empty string for unset vars (matching Kamal's behavior).
89+
1. `.kamal/secrets`, then `.kamal/secrets.<destination>` overlay if `--destination` is set. Known defect: this leg resolves the secrets file relative to `deploy.yml`'s own directory — `config/.kamal/secrets` for the standard layout — so the project-root `.kamal/secrets` the rest of the CLI uses is never consulted ([#3084](https://github.com/wheels-dev/wheels/issues/3084)).
90+
2. `System.getenv(VAR)` on the machine running `wheels deploy`.
91+
3. Empty string for unset vars (matching Kamal's behavior).
8592

8693
Only uppercase-and-underscore tokens are expanded — the regex is `\$\{([A-Z_][A-Z0-9_]*)\}`. That keeps shell-style `${service}` placeholders elsewhere in the config from being captured by accident, the same rule Kamal applies.
8794

@@ -90,7 +97,7 @@ No conditionals, no method calls, no computed expressions. If your existing conf
9097
We considered preserving ERB by shelling out to a system Ruby. The problem is that it turns a single-binary install into a "works if you also have Ruby" story, and every user without Ruby installed gets a cryptic error on their first deploy. Naming the divergence up front — and keeping Kamal's `${VAR}` syntax untouched — is the honest trade-off.
9198

9299
<Aside type="note" title="Mustache is used elsewhere — not in deploy.yml at runtime">
93-
The `cli/lucli/services/deploy/lib/Mustache.cfc` wrapper is a thin facade over jmustache, but it is **not** applied to `deploy.yml` at runtime. It's used by `wheels deploy init` to render the initial scaffolding templates (`config/deploy.yml` and `.kamal/secrets`) when a project doesn't have one yet. Once those files exist, `${VAR}` is the only interpolation that runs.
100+
The `cli/lucli/services/deploy/lib/Mustache.cfc` wrapper is a thin facade over jmustache, but it is **not** applied to `deploy.yml` at runtime. It's used by `wheels deploy init` to render the initial scaffolding templates (`config/deploy.yml`, `.kamal/secrets`, `Dockerfile`, and `.dockerignore`) when a project doesn't have them yet. Once those files exist, `${VAR}` is the only interpolation that runs.
94101
</Aside>
95102

96103
## Commands-are-strings invariant
@@ -136,7 +143,7 @@ The separation of `cli/` (user-facing orchestration) from `commands/` (pure comm
136143

137144
- **snakeyaml** — YAML parsing for `config/deploy.yml`
138145
- **sshj** (with BouncyCastle transitives) — SSH transport
139-
- **jmustache** — template rendering for the `wheels deploy init` scaffolding (`deploy.yml.mustache`, `secrets.mustache`); not applied to `deploy.yml` at runtime
146+
- **jmustache** — template rendering for the `wheels deploy init` scaffolding (`deploy.yml.mustache`, `secrets.mustache`, `Dockerfile.mustache`, `dockerignore.mustache`); not applied to `deploy.yml` at runtime
140147

141148
These JARs load through a dedicated `URLClassLoader` isolated from the main JVM classpath. That isolation matters because CFML engines (Lucee, Adobe CF) ship their own copies of some transitive dependencies (older BouncyCastle versions, in particular). Without isolation, class-resolution order would be nondeterministic and you'd get obscure `NoSuchMethodError` failures depending on load order.
142149

0 commit comments

Comments
 (0)