# kubeseal --fetch-cert: Seal Offline in CI

> kubeseal --fetch-cert exports the controller public certificate so you can seal secrets without cluster access. Reference for --cert and offline CI sealing.

Source: https://latchkey.dev/learn/command-reference/kubeseal-fetch-cert  
Updated: 2026-06-30

kubeseal --fetch-cert downloads the sealed-secrets controller public certificate so you can seal secrets offline with --cert.

CI runners often cannot reach the cluster API. Fetch the public cert once, store it, and seal with --cert so no live connection is needed.

## What it does

kubeseal --fetch-cert connects to the sealed-secrets controller and prints its public certificate to stdout. That certificate is all kubeseal needs to encrypt, so saving it lets later kubeseal --cert calls run without any cluster access.

## Common usage

```Terminal
# export the public cert once (it is not secret)
kubeseal --fetch-cert \
  --controller-name sealed-secrets \
  --controller-namespace sealed-secrets > pub-cert.pem
# seal offline in CI using the saved cert
kubeseal --cert pub-cert.pem --format yaml < secret.yaml > sealed.yaml
```

## Options

| Flag | What it does |
| --- | --- |
| --fetch-cert | Print the controller public certificate |
| --cert <file|url> | Seal using a local or remote public cert (offline) |
| --controller-name <name> | Controller deployment name |
| --controller-namespace <ns> | Controller namespace |

## In CI

The public certificate is not sensitive, so commit it or store it as a build artifact and seal with --cert in pipelines that have no kube access. Refresh the cert when the controller rotates its key (by default every 30 days, though existing keys are retained for decryption).

## Common errors in CI

"error: cannot fetch certificate: Get ... connection refused" means no route to the controller; fetch the cert from a machine that can reach the cluster. "error: cannot get sealed secret service" means the --controller-name or namespace is wrong. Sealing with an outdated --cert still works as long as the controller kept the matching key.

## Using this in CI

A runner has no kubeconfig, no cached context, and no interactive auth. Every kubectl invocation in CI needs the context supplied explicitly, and most confusing CI failures here are the command running against the wrong cluster or no cluster at all.

```Terminal
# never rely on the ambient context on a runner
kubectl --context "$KUBE_CONTEXT" -n "$NAMESPACE" get pods

# confirm what you are actually connected to before mutating anything
kubectl config current-context
kubectl cluster-info

# fail fast instead of hanging on an unreachable API server
kubectl --request-timeout=30s get nodes
```

> Always set `--request-timeout` in CI. Without it an unreachable API server hangs until the job times out, which turns a thirty-second failure into a twenty-minute one.

## FAQ

### kubeseal --fetch-cert: Seal Offline in CI?

CI runners often cannot reach the cluster API. Fetch the public cert once, store it, and seal with --cert so no live connection is needed.

### What it does?

kubeseal --fetch-cert connects to the sealed-secrets controller and prints its public certificate to stdout. That certificate is all kubeseal needs to encrypt, so saving it lets later kubeseal --cert calls run without any cluster access.

### In CI?

The public certificate is not sensitive, so commit it or store it as a build artifact and seal with --cert in pipelines that have no kube access. Refresh the cert when the controller rotates its key (by default every 30 days, though existing keys are retained for decryption).

### Common errors in CI?

"error: cannot fetch certificate: Get ... connection refused" means no route to the controller; fetch the cert from a machine that can reach the cluster. "error: cannot get sealed secret service" means the --controller-name or namespace is wrong. Sealing with an outdated --cert still works as long as the controller kept the matching key.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
