Skip to content

Document deploying from CI: GitHub Actions with an SSH key and the sops age key #89

Closed

Description

@shipmill-romamo

Problem

Found while setting up Abecra's staging on 2026-10-19. Every guide (docs/getting-started.md, docs/operator-guide.md, docs/secrets-guide.md) runs Cloudfall from an operator's machine: SOPS_AGE_KEY_FILE=~/.config/cloudfall/age.key, the operator's SSH agent, ansible-playbook on their PATH. Nothing says how to run artifact build and cloudfall deploy from a pipeline on merge to main, which is how most teams expect a staging environment to update.

The questions a team has to answer alone today:

  • which secrets the runner needs (an SSH private key for the declared ssh.user, the age key, known_hosts for the server) and how to scope them (a GitHub environment per Cloudfall environment)
  • the toolchain to install (uv, ansible-playbook >= 2.21.0, git >= 2.24.0, sops) and the versions required_tools will check
  • where artifacts and receipts go: tmp/artifacts, tmp/deployments are on the runner and disappear with it, so the receipts that make deploys auditable are lost unless they are uploaded or committed
  • how an approval (Application.spec.approval: manual) maps onto a CI job without an agent approving its own deploy
  • that cloudfall deploy needs a release id from artifact build, and that artifact build is cloudfall-engine, not cloudfall (or the build_artifact MCP tool)

Proposal

A docs/ci-deploy-guide.md with one worked GitHub Actions workflow, tested against a real project:

  • on: push to main in the fleet repository and workflow_dispatch with a ref input; app repositories trigger it with repository_dispatch
  • secrets: CLOUDFALL_SSH_KEY, CLOUDFALL_KNOWN_HOSTS, SOPS_AGE_KEY in a GitHub environment named after the Cloudfall environment, with required reviewers for production
  • steps: install the pinned toolchain, secrets render, artifact build --ref, deploy --release --yes, upload tmp/deployments as a workflow artifact (or commit receipts back, if the project wants them in git)
  • a note on the age key: one key per environment, so a staging runner cannot decrypt production secrets

If the guide shows that artifact build belongs in the cloudfall CLI (one tool for CI to install and pin), that is a follow-up issue.

Alternatives

  • A Cloudfall-published reusable action: less copy-paste, but one more artifact to version; the guide comes first either way

Acceptance

  • The guide's workflow, copied into a fresh project with the three secrets set, deploys a component on push and the run uploads its release and deployment receipts
  • The guide shows that a runner holding only the staging age key cannot render production secrets
  • getting-started.md links the guide

Activity

  1. shipmill-romamo commented on Oct 20, 2026

    @shipmill-romamo
    ContributorAuthor

    Triage: implement (documentation).

    Confirmed on main (348ed73): docs/getting-started.md, docs/operator-guide.md and docs/secrets-guide.md all run Cloudfall from an operator's machine, and nothing covers a pipeline. Every question in the issue is answerable from the code today, so this is a guide, not a feature.

    The plan:

    • docs/ci-deploy-guide.md with one GitHub Actions workflow: push to main and workflow_dispatch with a ref input, a GitHub environment per Cloudfall environment holding CLOUDFALL_SSH_KEY, CLOUDFALL_KNOWN_HOSTS and SOPS_AGE_KEY, required reviewers on production
    • Steps: install the toolchain at the versions required_tools checks, secrets render, cloudfall-engine artifact build --ref, cloudfall deploy --release --yes, upload tmp/artifacts and tmp/deployments as workflow artifacts so the receipts outlive the runner
    • One age key per environment, and why a staging runner then can't decrypt production secrets
    • How approval: manual maps onto an environment's required reviewers, so no job approves its own deploy
    • A link from getting-started.md

    The guide is written from the code and checked against the CLI's real flags. A live run on a fresh project, which the issue's first acceptance point asks for, needs real secrets and a server; the guide will say it hasn't had one yet until someone runs it. Whether artifact build should move into cloudfall stays a follow-up, as the issue says. I'll link the PR here.

  2. shipmill-romamo commented on Oct 20, 2026

    @shipmill-romamo
    ContributorAuthor

    The guide is in #104: docs/ci-deploy-guide.md, with one GitHub Actions workflow, a link from getting-started.md, and a row in the README's guide table. Every command and flag was checked against --help and the source, and the guide says at the top that the workflow hasn't had a live run yet.

    Things the code showed that differ from this issue:

    • cloudfall deploy writes its receipt to tmp/releases/<component>.json; tmp/deployments holds converge and domain receipts. The workflow uploads tmp/artifacts, tmp/releases and tmp/env-receipts, and never tmp/env, which holds decrypted values
    • approval: manual isn't enforced by deploy at all, so the guide makes the GitHub environment's required reviewers (with "prevent self-review") the gate. Filed separately
    • cloudfall init encrypts all of secrets/ to one age key; the guide shows splitting .sops.yaml by environment, after which a staging runner fails with secrets_decrypt_failed on a production file
    • --ref is a ref of the component's repository, so production rebuilds the same commit instead of reusing staging's archive

    This issue closes when #104 merges.

  3. shipmill-romamo commented on Oct 20, 2026

    @shipmill-romamo
    ContributorAuthor

    Released in v0.8.0rc1 (pre-release). uv tool install --prerelease allow cloudfall==0.8.0rc1
    A plain install gets it with the next stable release.
    If you filed this: react 👍 on this comment once it works for you, or reply if it doesn't.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    documentationImprovements or additions to documentationenhancementNew feature or request

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions