docs(deploy): push-button autumn deploy walkthrough (AC-8 of #1607)#1950
Conversation
…deployment path — Part of #1607 Adds the AC-8 push-button deployment journey to docs/guide/deployment.md — a verbatim `autumn new` → `[deploy] host` → secrets in `.env` → `autumn deploy check` → `autumn build --embed` → `autumn deploy up` → live walkthrough, plus zero-downtime redeploy, `autumn deploy rollback`, `autumn deploy plan`, where secrets live (0600 env file), preconditions (key-based SSH to stock Ubuntu; kamal-proxy binary present), troubleshooting via `autumn deploy check`/`autumn doctor`, and honest limitations (kamal-proxy binary is host-bootstrapped, migrations run on redeploy, single-host, remote-state atomicity #1938). The container and fly.io paths remain as documented alternatives. Completes #1607 AC-8.
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
|
Warning You have reached your daily quota limit. Please wait up to 24 hours and I will start processing your requests again! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: acfa19957a
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Put your secrets in a project `.env` (git-ignored — never committed). They are | ||
| read by the deploy and written to a `0600` env file **on the server only**: |
There was a problem hiding this comment.
Clarify that only two env vars are deployed
For apps with any runtime secret besides the signing secret and database URL (for example OAuth, SMTP, Redis, or storage credentials), this tells users to put “your secrets” in .env and expect the deploy to write them on the server. However autumn-cli/src/deploy.rs::build_env_file only serializes AUTUMN_SECURITY__SIGNING_SECRET and AUTUMN_DATABASE__URL, so the deployed systemd service will not receive other .env values and those features will fail in production unless the user provisions them separately.
Useful? React with 👍 / 👎.
…ployed to the host — Part of #1607 The push-button guide implied any `.env` secret is transferred to the server, but `autumn deploy` writes only AUTUMN_SECURITY__SIGNING_SECRET and (for DB-backed apps) AUTUMN_DATABASE__URL to the host's 0600 env file. Clarifies the secrets section and adds a Limitations bullet so operators provision other runtime secrets (OAuth/SMTP/Redis/storage/etc.) on the target separately. Addresses Codex P2 on #1950.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 29c89ace7c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| ```bash | ||
| autumn deploy check # same graders also run inside `autumn doctor` |
There was a problem hiding this comment.
Point the walkthrough at a CLI release with deploy
When a new user follows the Prerequisites exactly they install autumn-cli --version 0.5.0, but this newly added walkthrough immediately asks them to run autumn deploy check; the deploy subcommand is part of the checked-in 0.6.0 CLI (Cargo.toml is 0.6.0 and DeployCommands is in the current autumn-cli/src/main.rs). With the pinned 0.5.0 install, the primary path can fail before the first deploy command runs, so the install version needs to be updated or the deploy section needs to be marked as requiring the newer CLI.
Useful? React with 👍 / 👎.
| - **Key-based SSH access to a stock Ubuntu LTS (or other systemd) host.** The | ||
| deploy runs non-interactively (`BatchMode=yes`) as the configured user | ||
| (`[deploy] user`, default `root`) — no password prompts, so your SSH key must | ||
| already be authorized on the target. |
There was a problem hiding this comment.
Require a privileged SSH user for systemd writes
If the operator sets [deploy] user to a normal non-root SSH account, this precondition implies that key-based access as that user is enough, but the deploy executor writes /etc/systemd/system/*.service and runs systemctl ... directly over SSH without sudo. On a stock Ubuntu host that user cannot create units or manage services, so deploy up fails after preflight; document that the SSH user must be root or otherwise already have direct permission for systemd and the app directory.
Useful? React with 👍 / 👎.
| `plan` is a pure dry-run: it prints the exact systemd unit and the ordered | ||
| zero-downtime rollout steps without connecting to the host. |
There was a problem hiding this comment.
Don’t advertise the deploy plan’s unit as exact
The unit printed by autumn deploy plan is not the one written by a real deploy: print_plan renders render_systemd_unit, while deploy up renders slot-specific app units via render_app_unit with {service}-{blue,green}.service, AUTUMN_SERVER__HOST=127.0.0.1, and the private slot port. Users auditing the plan for unit names or port binding will see the wrong unit, so this should not be documented as the exact systemd unit unless the plan output is changed.
Useful? React with 👍 / 👎.
…nd deploy-plan-unit accuracy — Part of #1607 Addresses Codex review on #1950 — the push-button guide now (1) notes `autumn deploy` requires autumn-cli 0.6.0+ (the Prerequisites 0.5.0 install lacks the subcommand), (2) states the [deploy] user must be root or already have direct no-sudo permission for systemd + the app dir (the deploy writes /etc/systemd/system and runs systemctl without sudo), and (3) describes `autumn deploy plan`'s unit as representative rather than exact (real deploys write slot-specific {service}-{blue,green} units on a private loopback port).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 189ef92c87
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| server until it is green: | ||
|
|
||
| ```bash | ||
| autumn deploy check # same graders also run inside `autumn doctor` |
There was a problem hiding this comment.
Point SSH checks at doctor --online
When the only deploy problem is SSH reachability, this makes autumn doctor sound equivalent to autumn deploy check, but doctor gates deploy_ssh_reachability behind --online (doctor.rs only adds that task when opts.online is true). A user can therefore get a passing default autumn doctor while autumn deploy check still fails on an unreachable SSH port; the walkthrough should say autumn doctor --online for the same network grader or avoid claiming the graders are identical.
Useful? React with 👍 / 👎.
| ``` | ||
|
|
||
| `plan` is a pure dry-run: it prints a **representative** systemd unit and the | ||
| ordered zero-downtime rollout steps for review, without connecting to the host. |
There was a problem hiding this comment.
Mark plan steps as representative too
The remaining mismatch is in the step order, not the unit caveat: build_deploy_plan prints [migrate] before [start-candidate], while the real deploy up path in cutover_ops starts the candidate first and then runs the migration one-shot. For users using deploy plan to review rollout ordering, this paragraph still presents the step list as the ordered deploy sequence, so either the plan output should be aligned or the docs should state that the steps are illustrative as well.
Useful? React with 👍 / 👎.
…loy plan` step order is representative — Part of #1607 Addresses Codex review on #1950 — plain `autumn doctor` skips network probes, so the SSH-reachability grader needs `autumn doctor --online` (or `autumn deploy check`); and `autumn deploy plan`'s step order is illustrative (it lists migrate before start-candidate, whereas a live redeploy starts the candidate first, then runs the pre-cutover migration).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ad235e8460
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Put these two values in a project `.env` (git-ignored — never committed). The | ||
| deploy reads them and writes **only** them to a `0600` env file | ||
| (`app_dir/shared/autumn.env`) **on the server**: |
There was a problem hiding this comment.
Document that runtime config is not deployed
For apps that depend on any runtime autumn.toml settings beyond the defaults, this walkthrough leaves those settings behind: deploy up uploads only the release binary and writes the env file containing the signing secret/database URL, while the generated systemd unit runs from the release dir without copying autumn.toml. That means non-secret config such as auth, jobs/scheduler, health paths, telemetry, CORS, or signing-secret rotation entries resolve to defaults on the server unless users provision them separately, so the primary path can silently run a different configuration than the one tested locally.
Useful? React with 👍 / 👎.
| ```bash | ||
| autumn deploy rollback |
There was a problem hiding this comment.
Document rollback's local preflight requirement
In an emergency rollback run from CI or another checkout that no longer has the same local .env/config, this command will not reach the server as implied here: run_rollback first runs the full deploy preflight and can fail on the local signing secret, database URL, or migration-safety check before resolving the previous release on the host. The rollback section should say it still requires the same local preflight inputs, otherwise operators may discover during an outage that the documented one-command rollback is blocked locally.
Useful? React with 👍 / 👎.
…s the local preflight — Part of #1607 Addresses Codex review on #1950 — clarifies that `autumn deploy up` uploads only the release binary and the env file (signing secret + database URL), so non-secret `autumn.toml` settings resolve to defaults on the host unless provisioned separately; and that `autumn deploy rollback` runs the same local preflight first, so it needs the same local secrets/config inputs where it's invoked (an emergency rollback from a bare checkout fails preflight before reaching the host).
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 9ead84fc92
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| Put these two values in a project `.env` (git-ignored — never committed). The | ||
| deploy reads them and writes **only** them to a `0600` env file | ||
| (`app_dir/shared/autumn.env`) **on the server**: |
There was a problem hiding this comment.
Set the production profile on deployed units
When this walkthrough is followed exactly, the host env file contains only these two values and render_app_unit only adds the slot host/port, so no AUTUMN_ENV reaches systemd. AutumnConfig::resolve_profile then falls back to dev, enabling dev smart defaults such as permissive CORS, detailed actuator output, and CSRF/session settings that differ from production on the VPS. Please set AUTUMN_ENV=prod in the generated unit/env file or document a deploy-safe way to provide it before presenting this as the primary production deploy path.
Useful? React with 👍 / 👎.
| > configuration you actually tested, provision it on the host yourself: place | ||
| > your `autumn.toml` in the release/app dir on the server, or set the matching | ||
| > `AUTUMN_*` environment overrides in `app_dir/shared/autumn.env` (the env-file | ||
| > route persists across releases; a file dropped into a timestamped release dir |
There was a problem hiding this comment.
Avoid recommending edits to overwritten deploy files
The suggested app_dir/shared/autumn.env path is rewritten on every first deploy and redeploy: both deploy paths call WriteFile for that same env path using build_env_file(), which emits only the signing secret and database URL. Any OAuth/SMTP/Redis overrides an operator adds there will be removed by the next autumn deploy up even though this text says the env-file route persists across releases, so redeploys can silently boot without required runtime config; document a provisioning mechanism deploy does not overwrite or change deploy to merge/preserve extra entries.
Useful? React with 👍 / 👎.
… env file is regenerated each deploy — Part of #1607 Reflects the companion fix (#1956) that writes AUTUMN_ENV=prod by default (overridable via [deploy] profile / AUTUMN_DEPLOY__PROFILE), and corrects the earlier guidance that implied hand-added values in shared/autumn.env persist — the env file is rebuilt on every deploy (signing secret + database URL + AUTUMN_ENV), so it's not a durable override store; non-secret config still isn't deployed (tracked in #1952). Addresses remaining Codex review on #1950.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ef3c4428d9
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| > signing-secret enforcement. To deploy a non-production target, set `[deploy] | ||
| > profile = "staging"` in `autumn.toml` (or `AUTUMN_DEPLOY__PROFILE=staging`); | ||
| > the deploy writes that value as `AUTUMN_ENV` instead. |
There was a problem hiding this comment.
Remove the unsupported deploy profile knob
For non-production deploys, this documented setting is a no-op: DeployConfig has no profile field and apply_deploy_env_overrides does not recognize AUTUMN_DEPLOY__PROFILE; build_env_file also never writes AUTUMN_ENV. With strict config enabled the TOML key hard-fails as unknown, and otherwise both TOML/env forms are ignored, so users following this escape hatch still get the default runtime profile instead of staging.
Useful? React with 👍 / 👎.
| Run the preflight — it checks SSH reachability, the signing secret, the database | ||
| URL (when the app is DB-backed), and that pending migrations are safe for a | ||
| rolling deploy. It exits non-zero if anything fails, so nothing touches the |
There was a problem hiding this comment.
Don't call the migrate check pending-only
For repos that keep an old destructive migration file after it has already been applied, this preflight can still fail: grade_migrate_check is an offline scan of migrations/, and check_migrations_in_dir reads every migration directory without consulting DB state to know what is pending. The guide's "pending migrations" wording sends users down the wrong path when an already-applied migration blocks deploy check; either filter by pending in code or document that all local migrations must be rolling-safe.
Useful? React with 👍 / 👎.
…s offline, not just pending ones — Part of #1607 The deploy migrate check (grade_migrate_check) is an offline static scan of the local migrations/ directory and does not consult the database, so it requires ALL local migration files to be rolling-safe — an already-applied destructive migration still on disk will fail `deploy check`. Corrects the "pending migrations" wording. Addresses Codex review on #1950.
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 0bf6ac70ae
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| > ships them, install the CLI from the latest source (`cargo install autumn-cli | ||
| > --git https://github.com/madmax983/autumn`) and confirm the subcommand is |
There was a problem hiding this comment.
Specify the CLI package in the git install command
For users following this Version note before a release contains deploy, this cargo install --git command is still not reliably runnable for this workspace: Cargo's install --help says the [CRATE] argument selects the package from the --git source, and cargo metadata for this repo shows multiple binary packages (autumn-cli plus several examples/benchmarks). Omitting autumn-cli leaves Cargo unable to choose the package to install, so the primary deploy path can still stop before autumn deploy --help; use cargo install --git https://github.com/madmax983/autumn autumn-cli (with --force if replacing the pinned 0.5.0 install).
Useful? React with 👍 / 👎.
…m-source install command — Part of #1607 The workspace has multiple binary packages, so `cargo install --git <url>` without a crate name fails to pick one; the from-source install for the unreleased `autumn deploy` CLI now specifies `autumn-cli` and uses `--force` to replace a pinned prior install. Addresses Codex P1 on #1950.
…y — follow-up incoming Add a short known-gap callout in the deploy config section clarifying that values set only under [profile.prod] or .env.prod aren't yet read by autumn deploy, which resolves config under the ambient profile while running the service as prod. Part of #1607 Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ee9hUf7PA7p4SYdWNk8AU
… (#1956) * fix(cli): autumn deploy runs the app under the production profile by default — Part of #1607 The deployed systemd service never received a profile selector, so `AutumnConfig::resolve_profile` fell back to `dev` — a production deploy silently ran dev smart-defaults (permissive CORS, detailed actuators, dev CSRF/session). `build_env_file` now writes `AUTUMN_ENV=<profile>` into the 0600 host env file, defaulting to `prod` via a new `[deploy] profile` config key (overridable with `AUTUMN_DEPLOY__PROFILE`, e.g. "staging" for non-prod targets). Tests cover the prod default and the override. Addresses the Codex P1 on #1950. * test(config): register the new deploy.profile key in the schema-keys snapshot — Part of #1607 The `[deploy] profile` config field added in this PR emits a new `deploy.profile` schema key; regenerate the schema-keys snapshot so schema_keys_snapshot_guard passes. Fixes the CI Test failure on #1956. * fix(cli): grade deploy preflight signing secret against the resolved deploy profile — Part of #1607 The deploy preflight and the remote env-file generation used different profile sources. `collect_preflight` graded the signing-secret strength with `is_production_profile(config.profile)` — the LOCAL CLI runtime profile (dev/None on a dev box) — while `build_env_file` writes `AUTUMN_ENV=<resolved.profile>` (the `[deploy] profile`, default `prod`). Before: running `deploy check`/`deploy up` from a dev box with a weak/demo signing secret PASSED preflight (non-production grading), but the uploaded unit booted with `AUTUMN_ENV=prod` and exited in `fail_fast_on_invalid_signing_secret` — failing the deploy AFTER touching the host. After: preflight grades the signing secret against the SAME profile the env file will pin (`is_production_profile(Some(&resolved.profile))`), so a weak secret targeting a prod deploy is caught locally, before any remote call, while a non-production deploy profile still accepts a weak secret. All three preflight call sites (check/up/rollback) already pass `resolved`, so they stay coherent with `build_env_file`. Adds a regression test proving the default (prod) deploy profile fails a weak secret and a non-prod profile passes it. * fix(cli): canonicalize the deploy profile before grading and writing AUTUMN_ENV — Part of #1607 Before: `ResolvedDeployConfig::resolve` stored `[deploy] profile` verbatim, but the preflight grader `is_production_profile` matches only the exact lowercase `prod`/`production`. The app's runtime resolver `normalize_profile_name` instead trims and case-folds aliases, so `PROD`, `Production`, and ` production ` all boot under the canonical `prod`. A non-canonical production spelling was graded NON-production locally (a weak/demo signing secret passed preflight), yet `build_env_file` wrote that same raw string to `AUTUMN_ENV`; the host normalized it to `prod` and `fail_fast_on_invalid_signing_secret` rejected the weak secret at boot — failing the deploy only after touching the host. After: a CLI-local `canonicalize_deploy_profile` helper mirrors the runtime `normalize_profile_name` rules (trim; fold `production`/`prod` → `prod`, `development`/`dev` → `dev`; preserve other non-empty values; blank → `prod`) and is applied at resolve time, so both the preflight grade and the AUTUMN_ENV value use one canonical spelling. Weak secrets under `PROD`/`Production`/ ` production ` are now caught locally; custom profiles like `staging` are preserved verbatim and still grade non-production. Kept the helper private and did not touch autumn-web's public API. * fix(cli): preserve raw deploy profile in AUTUMN_ENV and grade doctor against deploy profile — Part of #1607 Two related deploy-profile grading fixes: 1. deploy: `ResolvedDeployConfig::resolve` now stores the operator's TRIMMED RAW `[deploy] profile` spelling (via new `trimmed_deploy_profile`) instead of the alias-folded canonical form. `build_env_file` writes that raw spelling to `AUTUMN_ENV`, so the host's runtime override-file lookup (`profile_override_file_lookup_names`) keeps its precedence — e.g. `autumn-production.toml` over `autumn-prod.toml` when the operator wrote `production`. Before: canonicalizing at resolve time flipped override-file precedence on hosts with both files. Grading is normalized separately by applying `canonicalize_deploy_profile` only at the grade site, so `PROD`/`Production`/` production ` are still held to production strength rules. 2. autumn doctor: the deploy branch now grades the deploy signing secret against the resolved `[deploy] profile` (default `prod`) via a new `deploy_is_production` flag, instead of the ambient `AUTUMN_ENV`/`AUTUMN_PROFILE` flag. Before: on a dev box `doctor --strict` PASSED a weak deploy signing secret that `deploy check`/`deploy up` FAIL; now doctor and `deploy check` agree. `is_production_profile`/`canonicalize_deploy_profile` are made `pub(crate)` for reuse; ambient (non-deploy) doctor checks are unchanged. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_014ee9hUf7PA7p4SYdWNk8AU --------- Co-authored-by: Claude <noreply@anthropic.com>
…e (Part of #1607) (#1966) * fix(cli): resolve autumn deploy config under the target deploy profile (Part of #1607) Before: `autumn deploy` did one `AutumnConfig::load()` under the operator's ambient profile (dev by default) and fed that single config to both preflight grading and the host env file. It graded and uploaded the DB URL (`resolve_writable_db_url`) and signing secret from config resolved under the ambient profile while running the service as the deploy profile (`prod`), so a strong prod secret / prod DB URL living only under `[profile.prod]` / `autumn-prod.toml` / `.env.prod` was never loaded, graded, or uploaded — a prod deploy could ship dev secrets/DB, and #1956 (which fixed the profile the secret is graded/written against) did not fix the profile the VALUES were loaded under. After: `deploy check`/`rollback`/`up` reload the config under the TARGET deploy profile via the existing autumn-web seams — a small `ForcedProfileEnv` wrapper (reports `AUTUMN_ENV=<resolved.profile>`, delegates every other read) over `os_env_with_dotenv_for_profile(&resolved.profile)`, fed to `AutumnConfig::load_with_env`. The reloaded `runtime_config` (not the ambient config) now drives preflight grading and the host env file, so `[profile.prod]` / `.env.prod` values are loaded, graded, and uploaded. The ambient load is kept only to read `[deploy]` and compute `resolved.profile`; `plan` stays a pure dry-run. #1956's behavior is preserved: grading still normalizes via `is_production_profile(canonicalize_deploy_profile(...))` and `AUTUMN_ENV` still carries the trimmed raw `resolved.profile`. Also removes the interim "Known gap" callout from docs/guide/deployment.md (added via #1950) now that this closes the gap. Part of #1607. * fix(cli): load .env.<profile> during deploy config reload Before: deploy's profile reload skipped `.env.prod` because dotenv auto-load is gated off for non-dev profiles (`should_load` needs `AUTUMN_DOTENV=1`), so prod-only values in `.env.<profile>` were never seen during the deploy config reload. After: `ForcedProfileEnv` reports `AUTUMN_DOTENV=1` through a new `autumn_web::dotenv::os_env_with_dotenv_for_profile_using(base, profile)` seam so `.env.<profile>` loads during the deploy reload without mutating the global process env. The profile-selector-key exclusion (the real safety boundary) is preserved. Adds a `.env.prod` regression test. Addresses the gemini review on #1966. * fix(cli): canonicalize deploy profile for dotenv overlay and honor explicit AUTUMN_DOTENV Two deploy-time config-reload fixes in autumn-cli/src/deploy.rs. AUTUMN_DOTENV (deploy.rs:834): Before: ForcedProfileEnv::var returned Ok("1") unconditionally for AUTUMN_DOTENV, so `AUTUMN_DOTENV=0 autumn deploy ...` was overridden and .env.<profile> loaded anyway. After: synthesize "1" only when the inner env has no explicit value; delegate to the inner env when it provides AUTUMN_DOTENV, preserving an explicit 0/false/1/true (should_load honors 0/false as the off switch). dotenv overlay selection (deploy.rs:864): Before: load_runtime_config passed the RAW resolved.profile to the dotenv overlay, so a `[deploy] profile` alias like `production`/`PROD` made the loader look for .env.production/.env.PROD instead of the canonical .env.prod used by AutumnConfig::load() after normalization. After: select the overlay by canonicalize_deploy_profile(&resolved.profile); AUTUMN_ENV and the TOML override-file precedence still carry the RAW spelling (only the dotenv-overlay selection is canonicalized). Adds a ForcedProfileEnv unit test (explicit 0 preserved, unset -> 1, true delegated) and two deploy integration tests (production alias loads .env.prod; AUTUMN_DOTENV=0 skips .env.prod). --------- Co-authored-by: Claude <noreply@anthropic.com>
AC-8 of #1607 — the deployment guide
Adds the push-button
autumn deployjourney todocs/guide/deployment.mdas the primary deployment path, with the container/OCI and fly.io paths kept as documented alternatives.What's added
A new
## Push-button deploy to your own server (autumn deploy)section (inserted between## Prerequisitesand the existing container## Step 1), covering:autumn new→ live walkthrough: scaffold → set[deploy] host→ put secrets in.env→autumn deploy check→autumn build --embed→autumn deploy up→curl /health;autumn deploy up— blue/green cutover, migrate-before-flip, health-gated atomic proxy flip, 0 dropped requests);autumn deploy rollbackandautumn deploy plan;kamal-proxybinary present at/usr/local/bin/kamal-proxy) and troubleshooting viaautumn deploy check/autumn doctor;Every command/flag/config key was verified against the shipped CLI.
Notes for reviewers / docs
> HTTPS/TLSnote links to issue Docs: self-hosting TLS + ACME deployment guide (direct TLS, certbot, mkcert, ACME happy path) #1860 rather than a dangling in-doc anchor. When Docs: self-hosting TLS + ACME deployment guide (direct TLS, certbot, mkcert, ACME happy path) #1860's TLS/ACME sections land, that cross-reference can be re-pointed at the real heading; the push-button section contains no TLS prose to conflict.docs/guide/deployment.md(+212 lines). No code, CHANGELOG, or version changes.Completes #1607 AC-8.