# Sealed Secrets

> Create sealed secrets for Kubernetes using kubeseal

- Skill: `majiayu000/sealed-secrets` (Agent Skill, multi-file: 2 files)
- Install (CLI): `npx skillmds add majiayu000/sealed-secrets`
- Raw SKILL.md: https://api.skillmd.com/api/skills/majiayu000/sealed-secrets/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: DevOps & Infra
- Author: majiayu000 (https://skillmd.com/u/majiayu000)
- Updated: 2026-09-09
- Page: https://skillmd.com/skills/majiayu000/sealed-secrets

---

# Sealed Secrets

Create encrypted sealed secrets for storing sensitive data in Git repositories.

## Prerequisites

- `kubeseal` CLI installed
- Access to Kubernetes cluster with sealed-secrets-controller
- kubectl configured with cluster access

## Workaround for Network Issues

The sealed-secrets-controller may not be directly reachable due to network policies. Use port-forwarding as a workaround:

```bash
# Start port-forward in background
kubectl port-forward -n flux-system svc/sealed-secrets-controller 8080:8080 &
PF_PID=$!
sleep 3

# Fetch the certificate
CERT=$(curl -s http://localhost:8080/v1/cert.pem)

# Create and seal the secret using the certificate
cat <<EOF | kubeseal --cert <(echo "$CERT") --format yaml > sealed-secret.yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
  namespace: my-namespace
type: Opaque
stringData:
  key1: "value1"
  key2: "value2"
EOF

# Clean up port-forward
kill $PF_PID 2>/dev/null || true
```

## Process

### 1. Prepare the secret manifest

Create a standard Kubernetes Secret manifest with your sensitive data:

```yaml
apiVersion: v1
kind: Secret
metadata:
  name: my-secret
  namespace: target-namespace
type: Opaque
stringData:
  api-key: "your-api-key"
  password: "your-password"
```

For docker registry secrets:
```yaml
apiVersion: v1
kind: Secret
metadata:
  name: registry-secret
  namespace: target-namespace
type: kubernetes.io/dockerconfigjson
data:
  .dockerconfigjson: <base64-encoded-docker-config>
```

### 2. Seal the secret

Using port-forward (recommended for our environment):

```bash
kubectl port-forward -n flux-system svc/sealed-secrets-controller 8080:8080 &
PF_PID=$!
sleep 3
CERT=$(curl -s http://localhost:8080/v1/cert.pem)

cat secret.yaml | kubeseal --cert <(echo "$CERT") --format yaml > sealed-secret.yaml

kill $PF_PID 2>/dev/null || true
```

### 3. Apply or commit the sealed secret

The sealed secret can be safely committed to Git:

```yaml
apiVersion: bitnami.com/v1alpha1
kind: SealedSecret
metadata:
  name: my-secret
  namespace: target-namespace
spec:
  encryptedData:
    api-key: AgB...encrypted...
    password: AgC...encrypted...
  template:
    metadata:
      name: my-secret
      namespace: target-namespace
    type: Opaque
```

## Common Secret Types

### API Credentials
```yaml
stringData:
  api-key: "${API_KEY}"
  private-key: |
    ${PRIVATE_KEY_CONTENT}
```

### Docker Registry (GHCR)
```bash
# Get existing secret from another namespace
kubectl get secret ghcr-secret -n source-namespace -o jsonpath='{.data.\.dockerconfigjson}'
```

### TLS Certificates
```yaml
type: kubernetes.io/tls
data:
  tls.crt: <base64-cert>
  tls.key: <base64-key>
```

## Troubleshooting

### "Resource already exists and is not managed by SealedSecret"
Delete the existing secret first:
```bash
kubectl delete secret my-secret -n target-namespace
```

### "illegal base64 data"
Ensure the encrypted data has no line breaks or extra whitespace. The sealed secret YAML should have the encrypted values on single lines.

### Controller not reachable (502 Bad Gateway)
Use the port-forward workaround described above.

## Notes

- Sealed secrets are namespace-scoped by default
- The encryption key is stored in the sealed-secrets-controller
- If the controller key rotates, old sealed secrets still work but you should re-seal with new key
- Always verify the sealed secret syncs correctly: `kubectl get sealedsecrets -n namespace`

