Add External Secrets Operator with 1Password Connect (#66) (#66)

## Summary
- Add 1Password Connect server for secrets automation API
- Add External Secrets Operator (ESO) to sync secrets from 1Password to K8s
- Add ClusterSecretStore connecting ESO to 1Password Connect
- Convert devpi secret to ExternalSecret as proof of concept

## Architecture
```
1Password Cloud → 1Password Connect (k8s) → ESO → Native K8s Secrets
```

## Deployment and Testing
- [ ] Mirror Helm charts to forge (connect-helm-charts, external-secrets) - DONE
- [ ] Create 1Password Connect credentials (`op connect server create`)
- [ ] Store credentials in 1Password item "1Password Connect"
- [ ] Bootstrap secret: `op inject -i argocd/manifests/1password-connect/secret-credentials.yaml.tpl | kubectl apply -f -`
- [ ] Deploy 1password-connect: `argocd app sync 1password-connect`
- [ ] Deploy external-secrets: `argocd app sync external-secrets`
- [ ] Deploy external-secrets-config: `argocd app sync external-secrets-config`
- [ ] Test devpi ExternalSecret: `argocd app sync devpi`
- [ ] Verify secret synced: `kubectl get externalsecret -n devpi`

## Future Work
After PoC validated, migrate remaining 12 secret templates to ExternalSecrets:
- databases (3), tailscale-operator (1), grafana-config (2), teslamate (2)
- forgejo-runner (1), argocd (1), immich (1), 1password-connect (1 - self-bootstrap)

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Reviewed-on: https://forge.ops.eblu.me/eblume/blumeops/pulls/66
This commit is contained in:
Erich Blume 2026-01-28 19:30:10 -08:00
commit 482414346e
13 changed files with 456 additions and 0 deletions

View file

@ -0,0 +1,38 @@
# 1Password Connect - Secrets Automation Server
# Provides REST API access to 1Password vault items for External Secrets Operator
#
# Chart mirrored from https://github.com/1Password/connect-helm-charts
#
# Prerequisites (one-time setup):
# 1. Create Connect server: op connect server create blumeops --vaults blumeops
# 2. Create token: op connect token create blumeops --server <server-id> --vault blumeops
# 3. Store credentials in 1Password item "1Password Connect" in blumeops vault
# 4. Bootstrap secret:
# kubectl --context=minikube-indri create namespace 1password
# op inject -i argocd/manifests/1password-connect/secret-credentials.yaml.tpl | \
# kubectl --context=minikube-indri apply -f -
#
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: 1password-connect
namespace: argocd
spec:
project: default
sources:
- repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/connect-helm-charts.git
targetRevision: connect-2.2.1
path: charts/connect
helm:
releaseName: onepassword-connect
valueFiles:
- $values/argocd/manifests/1password-connect/values.yaml
- repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: 1password
syncPolicy:
syncOptions:
- CreateNamespace=true

View file

@ -0,0 +1,26 @@
# External Secrets Configuration - ClusterSecretStore for 1Password
#
# Deploys the ClusterSecretStore that connects ESO to 1Password Connect.
# Must be synced AFTER external-secrets operator is running.
#
# Prerequisites:
# - 1password-connect is deployed and healthy
# - external-secrets operator is deployed and CRDs are installed
#
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-secrets-config
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
path: argocd/manifests/external-secrets
destination:
server: https://kubernetes.default.svc
namespace: external-secrets
syncPolicy:
syncOptions:
- CreateNamespace=true

View file

@ -0,0 +1,28 @@
# External Secrets Operator CRDs
#
# CRDs are installed separately because:
# 1. They need ServerSideApply due to large annotation sizes
# 2. The Helm chart's CRDs are auto-generated during packaging (not in raw git)
# 3. CRDs should exist before the operator starts
#
# Must be synced BEFORE external-secrets operator app.
#
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-secrets-crds
namespace: argocd
spec:
project: default
source:
repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/external-secrets.git
targetRevision: helm-chart-1.3.1
path: config/crds/bases
directory:
exclude: 'kustomization.yaml'
destination:
server: https://kubernetes.default.svc
syncPolicy:
syncOptions:
- ServerSideApply=true
- CreateNamespace=false

View file

@ -0,0 +1,33 @@
# External Secrets Operator - Kubernetes secret sync from external providers
# Syncs secrets from 1Password Connect to native Kubernetes Secrets
#
# Chart mirrored from https://github.com/external-secrets/external-secrets
#
# Prerequisites:
# - 1password-connect must be deployed and healthy
#
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: external-secrets
namespace: argocd
spec:
project: default
sources:
- repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/external-secrets.git
targetRevision: helm-chart-1.3.1
path: deploy/charts/external-secrets
helm:
releaseName: external-secrets
valueFiles:
- $values/argocd/manifests/external-secrets/values.yaml
- repoURL: ssh://forgejo@forge.ops.eblu.me:2222/eblume/blumeops.git
targetRevision: main
ref: values
destination:
server: https://kubernetes.default.svc
namespace: external-secrets
syncPolicy:
syncOptions:
- CreateNamespace=true
- ServerSideApply=true