deploy: collapse to single .env, make updater token optional for main app#134
Conversation
… main app
UX cleanup based on operator feedback that the deployment looks more
complicated than it has to be. Two surgical changes; architecture
(separate updater sidecar) is preserved exactly.
Change 1 — Collapse to a single .env file.
Before:
- ../.env (project root) — operator app config; mounted via env_file
- deploy/.env — interpolation source for token + version
This was a split I introduced when first writing the compose
integration. It bought nothing useful and forced operators to copy a
template AND remember a second hidden file at the project root.
After:
- deploy/.env — single source of truth. Compose reads it
automatically for variable substitution (because it lives next to
the compose file), and the app + bootstrap services receive it
via env_file. The processgit-updater service's RW bind mount of
deploy/ already exposes this file at /deploy/.env, so the
in-place rewrite on update commit works unchanged.
This also lets us drop the `..:/host-root:ro` bind mount on the
updater container, which was only there to reach ../.env from inside.
One fewer bind mount, narrower attack surface.
Change 2 — Make PROCESSGIT_UPDATER_TOKEN optional for the main app.
Before, every operator had to set the token even if they didn't want
the self-update sidecar — compose refused to start with a hard
"required" check on both services.
After:
- processgit service: PROCESSGIT_UPDATER_TOKEN: ${...:-} (optional)
- processgit-updater service: PROCESSGIT_UPDATER_TOKEN: ${...:?...} (required)
Effect:
- Operators who want the full deployment: set the token once in
deploy/.env, run `docker compose up -d`. Identical to before.
- Operators who don't want self-updates: leave the token blank,
run `docker compose up -d processgit-init-perms processgit
processgit-bootstrap` (just list the services they want). Main
app starts identically; no friction.
The error message on the updater service is now actionable:
"... requires PROCESSGIT_UPDATER_TOKEN in deploy/.env. Generate one
with `openssl rand -hex 32` and add it. Or omit this service from
`docker compose up` if you don't want self-updates."
Updates to deploy/.env.example:
- Reformatted as a clean single-source-of-truth template
- Documents both the with-updater and without-updater paths
- Includes example Gitea app-config keys (DOMAIN, ROOT_URL, etc.)
operators commonly need but were previously buried in ../.env
Top-of-file comment in docker-compose.yml rewritten to lead with the
3-line quick start and explicitly call out the opt-out path.
Validation:
- YAML syntax valid
- python3 yaml.safe_load assertions confirm env_file paths,
token-required asymmetry between services, removed host-root mount
- No structural changes to services, volumes, networks, or ports
Co-authored-by: Claude <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3ed9fa4097
ℹ️ 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".
| image: ghcr.io/algomation-ai/processgit-updater:${PROCESSGIT_VERSION:-latest} | ||
| environment: | ||
| PROCESSGIT_UPDATER_TOKEN: ${PROCESSGIT_UPDATER_TOKEN:?PROCESSGIT_UPDATER_TOKEN is required - see deploy/.env.example} | ||
| PROCESSGIT_UPDATER_TOKEN: ${PROCESSGIT_UPDATER_TOKEN:?The processgit-updater service requires PROCESSGIT_UPDATER_TOKEN in deploy/.env. Generate one with `openssl rand -hex 32` and add it. Or omit this service from `docker compose up` if you don't want self-updates.} |
There was a problem hiding this comment.
Remove required token interpolation from optional service
Using ${PROCESSGIT_UPDATER_TOKEN:?...} here breaks the advertised “run without updater” flow, because Compose resolves variable interpolation across the Compose model before service selection; a missing required variable aborts parsing even when up targets only processgit-init-perms processgit processgit-bootstrap. In practice, docker compose -f deploy/docker-compose.yml up -d processgit-init-perms processgit processgit-bootstrap will still fail unless a token is set, so the new optional-token behavior for the main app is not actually reachable.
Useful? React with 👍 / 👎.
deploy: collapse to single
.envfile, make updater token optional for main appUX cleanup. Same architecture (separate updater sidecar) but installs as cleanly as a single-binary product.
Two surgical changes, both addressing the friction noted in #130 (comment)... — sorry, addressing operator feedback: "two .env files is confusing" and "I shouldn't have to generate a 64-char hex string just to start the app."
Change 1 — Single
.envfileBefore
../.env(project root)env_file:deploy/.envAfter
deploy/.envCompose automatically reads
deploy/.envfor variable substitution because it lives next to the compose file. The same file is now also theenv_file:source for the main app and bootstrap services. The updater's RW bind mount ofdeploy/already exposes it at/deploy/.env, so the in-place rewrite on commit works unchanged.Side benefit: the
..:/host-root:robind mount on the updater container is gone — it only existed to reach../.env. One fewer bind mount, narrower attack surface.Change 2 — Token is optional for the main app
Before —
compose upfails immediately ifPROCESSGIT_UPDATER_TOKENis unset, even on operators who don't want self-updates.After
processgit(main app)${PROCESSGIT_UPDATER_TOKEN:-}— optionalprocessgit-updater${PROCESSGIT_UPDATER_TOKEN:?…}— required (with actionable error)Effect
deploy/.env, rundocker compose up -d. Identical to before.docker compose up -d processgit-init-perms processgit processgit-bootstrap. The main app starts identically; no friction.The updater service's required-token error now spells out both paths:
Resulting install UX
Three to four commands, one .env file. Updater on by default; opt-out is a flag on
up..env.examplerewriteReformatted as a clean single-source-of-truth template:
../.envwhich we no longer usecompose upcommandValidation
python3 yaml.safe_load)env_file: ['.env']on processgit + bootstrap (not../.env)${...:-}on processgit's TOKEN${...:?...}on processgit-updater's TOKENhost-rootmount remaining on the updaterDiff stat
Sequencing
The README rewrite (PR-2 in this cleanup pass) is its own follow-up because the install instructions there reference the new flow. Best merged before or with this one.