
Sovereign Signing: A Self-Hosted Supply Chain with OpenBao, Cosign, and Flux CD

The Ground Is Moving Under Secrets Management
If you run a regulated platform, the last three years have shifted the assumptions under your secrets management strategy. In August 2023, HashiCorp relicensed Vault from the open source MPL 2.0 to the Business Source License (BSL 1.1). The source is still readable, but it now carries commercial-use restrictions that make it source-available, not open source. In February 2025, IBM completed its acquisition of HashiCorp. And on 1 July 2026, HCP Vault Secrets reached end of life, prompting its remaining users to move to higher, pricier tiers.
None of these changes is a red line on its own. Combined, however, they create a natural inflexion point for infrastructure teams. For the highly regulated organisations we work with, such as the public sector or enterprises with genuine data-sovereignty obligations, the resulting conversations rarely stop at picking a new secrets manager. They force us to address the fundamental question: how much of my trust chain am I willing to rent from infrastructure I don't control?
This post answers a specific slice of that question. We'll build a software supply chain signing pipeline for GitOps delivery where every link in the chain is self-hosted and vendor-neutral: OpenBao (opens in a new tab) holds the signing key, Cosign (opens in a new tab) signs the OCI artifacts, and Flux CD (opens in a new tab) verifies them before anything lands in the cluster. No public cloud KMS. No public Sigstore transparency log.
The full, reproducible reference lives at github.com/controlplaneio-openbao/openbao-flux-demo (opens in a new tab).
Defining "Sovereign"
The term “sovereign” is often used loosely, so we need to define it clearly for our context. The standard approach to signing (container) artifacts today relies heavily on two components outside of your control:
- A public cloud KMS (AWS KMS, GCP KMS, Azure Key Vault) to hold the signing key is convenient. It also means that the key's custody and jurisdiction are outside of your control.
- The public Sigstore stack (Fulcio for short-lived certificates, Rekor for the transparency log), when you sign keylessly. This removes the burden of managing the lifecycle of the signing key, but it makes your signing flow depend on public, shared infrastructure that must be reachable and trustworthy. In addition, leaking information about private signing events to a public ledger does not necessarily align with security requirements.
In most industries, these trade-offs are reasonable and make-or-buy decisions are primarily driven by market pressure. However, in heavily regulated environments, relying on public infrastructure introduces third-party dependencies that auditors will flag. To meet sovereignty requirements, we define a hard boundary: the signing key remains strictly within self-hosted infrastructure, and neither signing nor verification relies on external services.
The Chain

OpenBao is the Linux Foundation's open source fork of HashiCorp's Vault, created in direct response to the BSL relicensing. Its transit secrets engine is a "cryptography as a service" backend: it holds key material and performs cryptographic operations on request, so the private key is generated inside OpenBao and never leaves.
Cosign orchestrates signing the OCI artifact and storing the signature. Crucially, it has first-class, native support for OpenBao through the openbao:// KMS URI scheme. Cosign asks OpenBao to sign the artifact's digest, OpenBao does the cryptography, and the signature is stored in the registry right next to the artifact.
Flux CD verifies the signature during reconciliation before applying anything. Flux's verification is signing-backend-agnostic. It uses a configured public key to check the artifact's signature. It has no awareness of OpenBao, Vault, or any KMS, and when you use a static key, it never reaches out to Fulcio or Rekor.
The Deliberate Trade-off: Static Keys, Not Keyless
Regular readers will notice this diverges from our own Flux D2 Reference Architecture (opens in a new tab), which defaults to keyless signing via GitHub Actions OIDC. That is not an inconsistency, but the whole point on which the sovereignty claim rests!
Keyless signing is excellent. It removes the operational burden of key custody entirely: identities are short-lived, and the transparency log gives you a tamper-evident, auditable record for free. When operational convenience is the priority and reliance on the public Sigstore instance is acceptable, keyless is the right default, and it is ours.
But keyless depends on public Sigstore infrastructure. For a pipeline whose entire reason for existence is to avoid dependence on external infrastructure, that dependency disqualifies it. Therefore, we make the opposite call on purpose: a static key, held in OpenBao, with full self-custody. Still, this comes at a cost: you are now responsible for key custody and rotation. On the other hand, the benefit is a materially stronger sovereignty claim, and the trust chain is yours end-to-end.
The lesson here should not be that "static keys are good, keyless is bad." It's that the two approaches encode different threat models, and you should choose the one that best fits your organisation's requirements.
Building It (the Short Version)
The repository (opens in a new tab) automates the whole demo using make targets. Once you've cloned the repository and run make prereqs, you can step through each step of the demo using the sequence laid out in the project's README (opens in a new tab). In the following, we will step through the key insights and point out any sharp edges.
The key is generated inside OpenBao. With the transit engine enabled, Cosign creates the key in the vault and only ever writes out the public half:
cosign generate-key-pair --kms openbao://control-plane-demoThe signing occurs via digest, with the transparency log disabled. Here, we sign the immutable digest rather than a mutable tag, and pass --tlog-upload=false so nothing is written to the public Rekor log:
cosign sign --key openbao://control-plane-demo --tlog-upload=false \
ghcr.io/controlplaneio-openbao/openbao-flux-demo-workload@sha256:a8c47e...Next, Flux verifies the artifact with the public key. The OCIRepository references a secret that contains the cosign.pub; that's the entire verification configuration:
apiVersion: source.toolkit.fluxcd.io/v1
kind: OCIRepository
metadata:
name: demo-workload
namespace: flux-system
spec:
interval: 5m
url: oci://ghcr.io/controlplaneio-openbao/openbao-flux-demo-workload
ref:
tag: latest
verify:
provider: cosign
secretRef:
name: cosign-public-keyOn successful verification, Flux records the event and refuses to apply anything until it has:
SourceVerified=True (Succeeded): verified signature of revision latest@sha256:…We install Flux with the Flux Operator (opens in a new tab) via a declarative FluxInstance, rather than the classic flux bootstrap CLI, just as we do in our D2 Reference Architecture (opens in a new tab).
Mind the (demo environment) gap
Note that this is a demo environment and some trade-offs have been made for educational purposes:
- OpenBao dev mode is not production. The demo runs bao server -dev with a well-known root token and an in-memory store. This configuration is intended for a throwaway playground, and nothing else. The repo includes a worked example of a least-privilege policy scoped to a single transit key (read the public key and sign) because in production, you never sign with a root token.
- GHCR packages default to private and unlinked, even when the repository is public. Until you set the package to public in the GitHub UI, Flux cannot pull it anonymously, and verification never starts. When you have to change the configuration, the demo will call this out.
- GitHub Packages still requires a classic PAT. Fine-grained tokens currently have no Packages permission at all, so a classic token with write:packages is unavoidable today. Use a short-lived token and revoke it afterwards.
- flux push artifact --creds and Cosign's registry auth are separate credential paths. Cosign needs its own cosign login.
It is worth noting that we chose GitHub and GHCR to make it easier to share code with our readers. In a regulated enterprise environment, you may find different tools for SCM and OCI registry, but the approach will work the same.
A Word on Licensing
The licenses used by these projects match what enterprises expect today. In addition, most projects are governed by the Linux Foundation:
- OpenBao: MPL 2.0, Linux Foundation-governed.
- Flux CD: Apache 2.0, Linux Foundation-governed.
- Flux Operator: AGPL 3.0
- Cosign: Apache 2.0, Linux Foundation-governed.
Prove That It Blocks
A control you never watch fail is a control you don't trust. The repository includes a tamper test that pushes an unsigned artifact to a separate tag, points a throwaway OCIRepository at it, and confirms that Flux refuses to deploy it: SourceVerified=False. The manifests never reach the cluster. Watching the pipeline correctly reject an unsigned artifact closes the loop and builds trust in the system.
The Path to Production
Note that the code is just a demo, and not a complete production blueprint. To focus on the trust chain as the primary educational piece, we deliberately scoped out several enterprise requirements. To make this production-ready, several factors need to be considered: HA/DR for OpenBao, proper seal management, and configured audit devices. Key rotation must be automated, and the public key must be delivered declaratively (e.g., via SOPS (opens in a new tab) or Sealed Secrets (opens in a new tab)) rather than applied imperatively.
And there's one more step toward full sovereignty we didn't take here: a self-hosted Rekor transparency log. Static-key signing gives you self-custody of the key; a self-hosted transparency log would provide a tamper-evident, auditable signing history without relying on the public Sigstore instance.
Talk to the People Who Maintain These Projects
If you're navigating the secrets-management decision the Vault relicensing has forced, or hardening a GitOps delivery pipeline against supply chain attacks, that's exactly the work we do. Explore Enterprise for Flux CD and Enterprise for OpenBao, or get in touch to talk through what a sovereign, self-hosted supply chain looks like for your environment.
Get in touch
- [email protected]
- London, NYC, Melbourne, Auckland
Related blogs
View allFluxCon Atlanta Was Just the Start
Reflecting on eight years of Flux deployment, two years of Enterprise and a watershed moment.

Hardening Git for GitOps
ControlPlane whitepaper on securing GitOps workflows at source \u270D

Speak to an expert
Engage with world-leading AI and cloud security specialists
