Add ExternalSecrets for remaining k8s secrets

Migrate 10 secret templates to ESO ExternalSecrets with 1Password Connect:
- databases: eblume, borgmatic, teslamate passwords
- tailscale-operator: OAuth client credentials
- grafana-config: admin password, teslamate datasource
- teslamate: db password, encryption key
- forgejo-runner: runner registration token
- argocd: forge SSH credentials

All use creationPolicy: Merge for safe migration from existing secrets.

Skipped:
- miniflux/secret-db: Uses CNPG secret, not 1Password directly
- immich/secret-db: Requires 1Password item creation first
- 1password-connect: Bootstrap secret, must stay as template

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
Erich Blume 2026-01-28 19:50:38 -08:00
commit 351528474c
15 changed files with 310 additions and 3 deletions

View file

@ -0,0 +1,36 @@
# ExternalSecret for ArgoCD Forge SSH credentials
#
# Replaces the manual op inject workflow from repo-forge-secret.yaml.tpl
#
# 1Password item: "argocd forge key" in blumeops vault
# Field: "private key"
#
# This is a repo-creds (credential template) that matches ALL repos under eblume/
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: repo-creds-forge
namespace: argocd
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: repo-creds-forge
creationPolicy: Merge
template:
metadata:
labels:
argocd.argoproj.io/secret-type: repo-creds
data:
type: git
url: "ssh://forgejo@forge.ops.eblu.me:2222/eblume/"
insecure: "true"
sshPrivateKey: "{{ .privateKey }}"
data:
- secretKey: privateKey
remoteRef:
key: argocd forge key
property: private key

View file

@ -7,6 +7,7 @@ resources:
# Pin to specific version for intentional upgrades
- https://raw.githubusercontent.com/argoproj/argo-cd/v3.2.6/manifests/install.yaml
- service-tailscale.yaml
- external-secret-repo-forge.yaml
patches:
- path: argocd-cmd-params-cm.yaml

View file

@ -0,0 +1,30 @@
# ExternalSecret for borgmatic backup user password
#
# Replaces the manual op inject workflow from secret-borgmatic.yaml.tpl
#
# 1Password item: "borgmatic" in blumeops vault
# Field: "db-password"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: blumeops-pg-borgmatic
namespace: databases
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: blumeops-pg-borgmatic
creationPolicy: Merge
template:
type: kubernetes.io/basic-auth
data:
username: borgmatic
password: "{{ .password }}"
data:
- secretKey: password
remoteRef:
key: borgmatic
property: db-password

View file

@ -0,0 +1,30 @@
# ExternalSecret for eblume superuser password
#
# Replaces the manual op inject workflow from secret-eblume.yaml.tpl
#
# 1Password item: "postgres" in blumeops vault
# Field: "password"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: blumeops-pg-eblume
namespace: databases
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: blumeops-pg-eblume
creationPolicy: Merge
template:
type: kubernetes.io/basic-auth
data:
username: eblume
password: "{{ .password }}"
data:
- secretKey: password
remoteRef:
key: postgres
property: password

View file

@ -0,0 +1,30 @@
# ExternalSecret for TeslaMate database user password
#
# Replaces the manual op inject workflow from secret-teslamate.yaml.tpl
#
# 1Password item: "TeslaMate" in blumeops vault
# Field: "db_password"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: blumeops-pg-teslamate
namespace: databases
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: blumeops-pg-teslamate
creationPolicy: Merge
template:
type: kubernetes.io/basic-auth
data:
username: teslamate
password: "{{ .password }}"
data:
- secretKey: password
remoteRef:
key: TeslaMate
property: db_password

View file

@ -8,3 +8,6 @@ resources:
- immich-pg.yaml
- service-tailscale.yaml
- service-metrics-tailscale.yaml
- external-secret-eblume.yaml
- external-secret-borgmatic.yaml
- external-secret-teslamate.yaml

View file

@ -0,0 +1,34 @@
# ExternalSecret for Forgejo Runner environment
#
# Replaces the manual op inject workflow from secret.yaml.tpl
#
# 1Password item: "Forgejo Secrets" in blumeops vault
# Field: "runner_reg"
#
# Note: Static values (FORGEJO_URL, RUNNER_NAME, RUNNER_LABELS) are included
# via template since they don't need to be in 1Password.
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: forgejo-runner-env
namespace: forgejo-runner
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: forgejo-runner-env
creationPolicy: Merge
template:
data:
FORGEJO_URL: "https://forge.ops.eblu.me"
RUNNER_NAME: "k8s-runner"
RUNNER_LABELS: "k8s:docker://registry.ops.eblu.me/blumeops/forgejo-runner:v2.1.7"
RUNNER_TOKEN: "{{ .runner_token }}"
data:
- secretKey: runner_token
remoteRef:
key: Forgejo Secrets
property: runner_reg

View file

@ -0,0 +1,29 @@
# ExternalSecret for Grafana admin password
#
# Replaces the manual op inject workflow from secret-admin.yaml.tpl
#
# 1Password item: "Grafana (blumeops)" in blumeops vault
# Field: "password"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: grafana-admin
namespace: monitoring
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: grafana-admin
creationPolicy: Merge
template:
data:
admin-user: admin
admin-password: "{{ .password }}"
data:
- secretKey: password
remoteRef:
key: Grafana (blumeops)
property: password

View file

@ -0,0 +1,31 @@
# ExternalSecret for TeslaMate PostgreSQL datasource password
#
# Replaces the manual op inject workflow from secret-teslamate-datasource.yaml.tpl
#
# 1Password item: "TeslaMate" in blumeops vault
# Field: "db_password"
#
# This secret is mounted as environment variables in Grafana.
# The password is referenced in values.yaml datasource config as $TESLAMATE_DB_PASSWORD
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: grafana-teslamate-datasource
namespace: monitoring
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: grafana-teslamate-datasource
creationPolicy: Merge
template:
data:
TESLAMATE_DB_PASSWORD: "{{ .password }}"
data:
- secretKey: password
remoteRef:
key: TeslaMate
property: db_password

View file

@ -5,6 +5,8 @@ namespace: monitoring
resources:
- ingress-tailscale.yaml
- external-secret-admin.yaml
- external-secret-teslamate-datasource.yaml
# Dashboard ConfigMaps - discovered by Grafana sidecar via label grafana_dashboard=1
- dashboards/configmap-borgmatic.yaml
- dashboards/configmap-devpi.yaml

View file

@ -0,0 +1,29 @@
# ExternalSecret for Tailscale Operator OAuth credentials
#
# Replaces the manual op inject workflow from secret.yaml.tpl
#
# 1Password item: "Tailscale K8s Operator OAuth" in blumeops vault
# Fields: "client-id", "client-secret"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: operator-oauth
namespace: tailscale
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: operator-oauth
creationPolicy: Merge
data:
- secretKey: client_id
remoteRef:
key: Tailscale K8s Operator OAuth
property: client-id
- secretKey: client_secret
remoteRef:
key: Tailscale K8s Operator OAuth
property: client-secret

View file

@ -8,6 +8,4 @@ resources:
- proxyclass.yaml
- dnsconfig.yaml
- egress-forge.yaml
# Note: OAuth secret (operator-oauth) is NOT included here.
# It must be manually applied before deploying - see README.md
- external-secret.yaml

View file

@ -0,0 +1,25 @@
# ExternalSecret for TeslaMate database password
#
# Replaces the manual op inject workflow from secret-db.yaml.tpl
#
# 1Password item: "TeslaMate" in blumeops vault
# Field: "db_password"
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: teslamate-db
namespace: teslamate
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: teslamate-db
creationPolicy: Merge
data:
- secretKey: password
remoteRef:
key: TeslaMate
property: db_password

View file

@ -0,0 +1,27 @@
# ExternalSecret for TeslaMate encryption key
#
# Replaces the manual op inject workflow from secret-encryption-key.yaml.tpl
#
# 1Password item: "TeslaMate" in blumeops vault
# Field: "api_enc_key"
#
# This key encrypts Tesla API tokens at rest in the database.
#
apiVersion: external-secrets.io/v1
kind: ExternalSecret
metadata:
name: teslamate-encryption
namespace: teslamate
spec:
refreshInterval: 1h
secretStoreRef:
kind: ClusterSecretStore
name: onepassword-blumeops
target:
name: teslamate-encryption
creationPolicy: Merge
data:
- secretKey: key
remoteRef:
key: TeslaMate
property: api_enc_key

View file

@ -7,3 +7,5 @@ resources:
- deployment.yaml
- service.yaml
- ingress-tailscale.yaml
- external-secret-db.yaml
- external-secret-encryption-key.yaml