Skip to content

feat(compose): x-orcinus-env-from-secret — load an existing Secret as env vars - #10

Merged
anak10thn merged 1 commit into
mainfrom
feat/env-from-secret
Aug 3, 2026
Merged

feat(compose): x-orcinus-env-from-secret — load an existing Secret as env vars#10
anak10thn merged 1 commit into
mainfrom
feat/env-from-secret

Conversation

@anak10thn

Copy link
Copy Markdown
Member

Problem

There was no compose-native way to consume a Secret that already exists in the cluster.

x-orcinus-secret reads like it should do this, but it does the opposite — it creates a Secret from values written in the compose file. So referencing one made by orcinus secret create left two options, both bad:

  • compose secrets: + external: true — mounts it as a file, and only really fits a Secret holding a single value (details below)
  • drop the whole workload to a raw manifest for envFrom.secretRef — which passes through untouched and therefore gets no orcinus labels, so it disappears from orcinus ls and from --prune scope

Change

services:
  app:
    image: myapp:1.0
    x-orcinus-env-from-secret: app-secret      # or [app-secret, extra-secret]
#
containers:
- envFrom:
  - secretRef:
      name: app-secret

Every key in the Secret becomes an env var under its own name. Nothing is generated for the Secret — it must exist at deploy time.

Applied next to applyImagePullSecrets, before Rollout conversion, so StatefulSets and Argo Rollouts inherit it (covered by a test). The reference is appended after any env_file ConfigMap, so a key in both resolves to the Secret's value — which is the point of naming a Secret.

Docs

While answering "how do I attach app-secret?" it turned out the file-mount route works but was documented nowhere — COMPOSE.md only mentioned file:. Now written down, including two sharp edges found by testing:

  • the key in the secrets: map must equal the Secret's name in the cluster — a name: field is silently ignored
  • the Secret must contain a data key of that same name; target: renames the file, not the key. orcinus secret create app-secret --from-literal DB_PASS=x then mounting it leaves the pod stuck on the missing key

Also worth flagging for reviewers: the fork logs level=warning msg="External secrets app-secret is not currently supported - ignoring" while wiring it up correctly. The warning is wrong; it is not from this PR, and I left it alone.

Discoverability, since the original confusion was "I made the secret, now what":

  • orcinus secret create now ends with — load it into a service with \x-orcinus-env-from-secret: ``
  • the secrets skill card said how to make a secret but never how to consume one; it now covers both, and warns that x-orcinus-secret is not the way to reference an existing one

Tests

Four cases: scalar form, list form (order preserved), ordering after an env_file ConfigMap, and inheritance by StatefulSet + Rollout. Full suite 137 passing.

… env vars

There was no compose-native way to read a Secret that already exists in the
cluster. x-orcinus-secret sounds like it, but it does the opposite: it creates
a Secret from values written in the compose file. Referencing one made by
`orcinus secret create` meant either mounting it as a file through compose's
`external: true`, which only fits a single value, or dropping the whole
workload down to a raw manifest and losing the orcinus ownership labels with it.

    services:
      app:
        image: myapp:1.0
        x-orcinus-env-from-secret: app-secret     # or [app-secret, extra]

Every key in the Secret becomes an env var under its own name, via envFrom.
Nothing is generated for the Secret — it is expected to exist at deploy time.

Applied alongside imagePullSecrets, before Rollout conversion, so StatefulSets
and Argo Rollouts carry it too. The reference is appended after any env_file
ConfigMap, so a key present in both resolves to the Secret's value, which is
the reason to name a Secret in the first place.

Also documents the file-mount route, which turned out to work but was written
down nowhere: compose `secrets:` with `external: true` mounts an existing
Secret, with the sharp edges that the map key must equal the Secret's name (a
`name:` field is ignored) and the Secret needs a data key of that same name.
The fork warns "External secrets ... not currently supported - ignoring" while
doing it correctly; the warning is wrong.

`orcinus secret create` now ends by naming the key to reference it with, and
the secrets skill card says how to consume a secret rather than only how to
make one.
@anak10thn
anak10thn merged commit 6b3f12a into main Aug 3, 2026
2 checks passed
@anak10thn
anak10thn deleted the feat/env-from-secret branch August 3, 2026 08:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant