From 351528474c36eb7b594164ffd0a5c09c8617503f Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Wed, 28 Jan 2026 19:50:38 -0800 Subject: [PATCH 1/4] 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 --- .../argocd/external-secret-repo-forge.yaml | 36 +++++++++++++++++++ argocd/manifests/argocd/kustomization.yaml | 1 + .../databases/external-secret-borgmatic.yaml | 30 ++++++++++++++++ .../databases/external-secret-eblume.yaml | 30 ++++++++++++++++ .../databases/external-secret-teslamate.yaml | 30 ++++++++++++++++ argocd/manifests/databases/kustomization.yaml | 3 ++ .../forgejo-runner/external-secret.yaml | 34 ++++++++++++++++++ .../grafana-config/external-secret-admin.yaml | 29 +++++++++++++++ .../external-secret-teslamate-datasource.yaml | 31 ++++++++++++++++ .../grafana-config/kustomization.yaml | 2 ++ .../tailscale-operator/external-secret.yaml | 29 +++++++++++++++ .../tailscale-operator/kustomization.yaml | 4 +-- .../teslamate/external-secret-db.yaml | 25 +++++++++++++ .../external-secret-encryption-key.yaml | 27 ++++++++++++++ argocd/manifests/teslamate/kustomization.yaml | 2 ++ 15 files changed, 310 insertions(+), 3 deletions(-) create mode 100644 argocd/manifests/argocd/external-secret-repo-forge.yaml create mode 100644 argocd/manifests/databases/external-secret-borgmatic.yaml create mode 100644 argocd/manifests/databases/external-secret-eblume.yaml create mode 100644 argocd/manifests/databases/external-secret-teslamate.yaml create mode 100644 argocd/manifests/forgejo-runner/external-secret.yaml create mode 100644 argocd/manifests/grafana-config/external-secret-admin.yaml create mode 100644 argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml create mode 100644 argocd/manifests/tailscale-operator/external-secret.yaml create mode 100644 argocd/manifests/teslamate/external-secret-db.yaml create mode 100644 argocd/manifests/teslamate/external-secret-encryption-key.yaml diff --git a/argocd/manifests/argocd/external-secret-repo-forge.yaml b/argocd/manifests/argocd/external-secret-repo-forge.yaml new file mode 100644 index 0000000..61fe3d6 --- /dev/null +++ b/argocd/manifests/argocd/external-secret-repo-forge.yaml @@ -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 diff --git a/argocd/manifests/argocd/kustomization.yaml b/argocd/manifests/argocd/kustomization.yaml index 6662c4b..31b9cd6 100644 --- a/argocd/manifests/argocd/kustomization.yaml +++ b/argocd/manifests/argocd/kustomization.yaml @@ -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 diff --git a/argocd/manifests/databases/external-secret-borgmatic.yaml b/argocd/manifests/databases/external-secret-borgmatic.yaml new file mode 100644 index 0000000..0af8cf6 --- /dev/null +++ b/argocd/manifests/databases/external-secret-borgmatic.yaml @@ -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 diff --git a/argocd/manifests/databases/external-secret-eblume.yaml b/argocd/manifests/databases/external-secret-eblume.yaml new file mode 100644 index 0000000..532a1ed --- /dev/null +++ b/argocd/manifests/databases/external-secret-eblume.yaml @@ -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 diff --git a/argocd/manifests/databases/external-secret-teslamate.yaml b/argocd/manifests/databases/external-secret-teslamate.yaml new file mode 100644 index 0000000..346a4bb --- /dev/null +++ b/argocd/manifests/databases/external-secret-teslamate.yaml @@ -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 diff --git a/argocd/manifests/databases/kustomization.yaml b/argocd/manifests/databases/kustomization.yaml index e2eaa0c..4e33a7c 100644 --- a/argocd/manifests/databases/kustomization.yaml +++ b/argocd/manifests/databases/kustomization.yaml @@ -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 diff --git a/argocd/manifests/forgejo-runner/external-secret.yaml b/argocd/manifests/forgejo-runner/external-secret.yaml new file mode 100644 index 0000000..ec1f5c6 --- /dev/null +++ b/argocd/manifests/forgejo-runner/external-secret.yaml @@ -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 diff --git a/argocd/manifests/grafana-config/external-secret-admin.yaml b/argocd/manifests/grafana-config/external-secret-admin.yaml new file mode 100644 index 0000000..547676b --- /dev/null +++ b/argocd/manifests/grafana-config/external-secret-admin.yaml @@ -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 diff --git a/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml b/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml new file mode 100644 index 0000000..4533c2f --- /dev/null +++ b/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml @@ -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 diff --git a/argocd/manifests/grafana-config/kustomization.yaml b/argocd/manifests/grafana-config/kustomization.yaml index 2611b0a..6a14e45 100644 --- a/argocd/manifests/grafana-config/kustomization.yaml +++ b/argocd/manifests/grafana-config/kustomization.yaml @@ -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 diff --git a/argocd/manifests/tailscale-operator/external-secret.yaml b/argocd/manifests/tailscale-operator/external-secret.yaml new file mode 100644 index 0000000..b8658cc --- /dev/null +++ b/argocd/manifests/tailscale-operator/external-secret.yaml @@ -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 diff --git a/argocd/manifests/tailscale-operator/kustomization.yaml b/argocd/manifests/tailscale-operator/kustomization.yaml index f0517ad..65f3786 100644 --- a/argocd/manifests/tailscale-operator/kustomization.yaml +++ b/argocd/manifests/tailscale-operator/kustomization.yaml @@ -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 diff --git a/argocd/manifests/teslamate/external-secret-db.yaml b/argocd/manifests/teslamate/external-secret-db.yaml new file mode 100644 index 0000000..38d1925 --- /dev/null +++ b/argocd/manifests/teslamate/external-secret-db.yaml @@ -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 diff --git a/argocd/manifests/teslamate/external-secret-encryption-key.yaml b/argocd/manifests/teslamate/external-secret-encryption-key.yaml new file mode 100644 index 0000000..92e1f50 --- /dev/null +++ b/argocd/manifests/teslamate/external-secret-encryption-key.yaml @@ -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 diff --git a/argocd/manifests/teslamate/kustomization.yaml b/argocd/manifests/teslamate/kustomization.yaml index 5ae053f..3be2de4 100644 --- a/argocd/manifests/teslamate/kustomization.yaml +++ b/argocd/manifests/teslamate/kustomization.yaml @@ -7,3 +7,5 @@ resources: - deployment.yaml - service.yaml - ingress-tailscale.yaml + - external-secret-db.yaml + - external-secret-encryption-key.yaml -- 2.50.1 (Apple Git-155) From dd6cf20d51e622f7315bb42c70d159e1dbf21011 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Wed, 28 Jan 2026 20:26:37 -0800 Subject: [PATCH 2/4] Remove obsolete secret templates - Delete 13 .yaml.tpl files replaced by ExternalSecrets - Update immich/README.md with direct CNPG secret copy instructions - Update miniflux/README.md with context flag and ESO note Only 1password-connect/secret-credentials.yaml.tpl remains (bootstrap). Co-Authored-By: Claude Opus 4.5 --- .../argocd/repo-forge-secret.yaml.tpl | 31 ------------------- .../databases/secret-borgmatic.yaml.tpl | 13 -------- .../databases/secret-eblume.yaml.tpl | 13 -------- .../databases/secret-teslamate.yaml.tpl | 11 ------- argocd/manifests/devpi/secret-root.yaml.tpl | 12 ------- .../manifests/forgejo-runner/secret.yaml.tpl | 17 ---------- .../grafana-config/secret-admin.yaml.tpl | 16 ---------- .../secret-teslamate-datasource.yaml.tpl | 13 -------- argocd/manifests/immich/README.md | 17 +++++----- argocd/manifests/immich/secret-db.yaml.tpl | 12 ------- argocd/manifests/miniflux/README.md | 7 +++-- argocd/manifests/miniflux/secret-db.yaml.tpl | 13 -------- .../tailscale-operator/secret.yaml.tpl | 14 --------- argocd/manifests/teslamate/secret-db.yaml.tpl | 11 ------- .../teslamate/secret-encryption-key.yaml.tpl | 12 ------- 15 files changed, 15 insertions(+), 197 deletions(-) delete mode 100644 argocd/manifests/argocd/repo-forge-secret.yaml.tpl delete mode 100644 argocd/manifests/databases/secret-borgmatic.yaml.tpl delete mode 100644 argocd/manifests/databases/secret-eblume.yaml.tpl delete mode 100644 argocd/manifests/databases/secret-teslamate.yaml.tpl delete mode 100644 argocd/manifests/devpi/secret-root.yaml.tpl delete mode 100644 argocd/manifests/forgejo-runner/secret.yaml.tpl delete mode 100644 argocd/manifests/grafana-config/secret-admin.yaml.tpl delete mode 100644 argocd/manifests/grafana-config/secret-teslamate-datasource.yaml.tpl delete mode 100644 argocd/manifests/immich/secret-db.yaml.tpl delete mode 100644 argocd/manifests/miniflux/secret-db.yaml.tpl delete mode 100644 argocd/manifests/tailscale-operator/secret.yaml.tpl delete mode 100644 argocd/manifests/teslamate/secret-db.yaml.tpl delete mode 100644 argocd/manifests/teslamate/secret-encryption-key.yaml.tpl diff --git a/argocd/manifests/argocd/repo-forge-secret.yaml.tpl b/argocd/manifests/argocd/repo-forge-secret.yaml.tpl deleted file mode 100644 index 9d6187e..0000000 --- a/argocd/manifests/argocd/repo-forge-secret.yaml.tpl +++ /dev/null @@ -1,31 +0,0 @@ -# ArgoCD credential template for forge SSH access -# This is a repo-creds (credential template) that matches ALL repos under eblume/ -# -# IMPORTANT: Use ?ssh-format=openssh to get OpenSSH format (required by ArgoCD) -# -# The SSH key must be added to the Forgejo user's SSH keys (not as a deploy key) -# so it has access to all repos owned by that user. -# -# Create the secret with: -# -# PRIV_KEY=$(op read "op://vg6xf6vvfmoh5hqjjhlhbeoaie/csjncynh6htjvnh2l2da65y32q/private key?ssh-format=openssh")$'\n' && \ -# kubectl create secret generic repo-creds-forge -n argocd \ -# --from-literal=type=git \ -# --from-literal=url='ssh://forgejo@forge.ops.eblu.me:2222/eblume/' \ -# --from-literal=insecure=true \ -# --from-literal=sshPrivateKey="$PRIV_KEY" && \ -# kubectl label secret repo-creds-forge -n argocd argocd.argoproj.io/secret-type=repo-creds -# -apiVersion: v1 -kind: Secret -metadata: - name: repo-creds-forge - namespace: argocd - labels: - argocd.argoproj.io/secret-type: repo-creds -stringData: - type: git - url: ssh://forgejo@forge.ops.eblu.me:2222/eblume/ - insecure: "true" - sshPrivateKey: | - # Key from 1Password: op://vg6xf6vvfmoh5hqjjhlhbeoaie/csjncynh6htjvnh2l2da65y32q/private key diff --git a/argocd/manifests/databases/secret-borgmatic.yaml.tpl b/argocd/manifests/databases/secret-borgmatic.yaml.tpl deleted file mode 100644 index 6a1c52a..0000000 --- a/argocd/manifests/databases/secret-borgmatic.yaml.tpl +++ /dev/null @@ -1,13 +0,0 @@ -# Template for borgmatic backup user password -# Apply with: op inject -i secret-borgmatic.yaml.tpl | kubectl apply -f - -# -# Uses the same borgmatic password from 1Password as the brew PostgreSQL setup -apiVersion: v1 -kind: Secret -metadata: - name: blumeops-pg-borgmatic - namespace: databases -type: kubernetes.io/basic-auth -stringData: - username: borgmatic - password: {{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/mw2bv5we7woicjza7hc6s44yvy/db-password }} diff --git a/argocd/manifests/databases/secret-eblume.yaml.tpl b/argocd/manifests/databases/secret-eblume.yaml.tpl deleted file mode 100644 index 481bd96..0000000 --- a/argocd/manifests/databases/secret-eblume.yaml.tpl +++ /dev/null @@ -1,13 +0,0 @@ -# Template for eblume superuser password -# Apply with: op inject -i secret-eblume.yaml.tpl | kubectl apply -f - -# -# Uses the same 1Password item as the brew PostgreSQL setup on indri -apiVersion: v1 -kind: Secret -metadata: - name: blumeops-pg-eblume - namespace: databases -type: kubernetes.io/basic-auth -stringData: - username: eblume - password: {{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/guxu3j7ajhjyey6xxl2ovsl2ui/password }} diff --git a/argocd/manifests/databases/secret-teslamate.yaml.tpl b/argocd/manifests/databases/secret-teslamate.yaml.tpl deleted file mode 100644 index 355e2be..0000000 --- a/argocd/manifests/databases/secret-teslamate.yaml.tpl +++ /dev/null @@ -1,11 +0,0 @@ -# Template for TeslaMate database user password -# Apply with: op inject -i argocd/manifests/databases/secret-teslamate.yaml.tpl | kubectl apply -f - -apiVersion: v1 -kind: Secret -metadata: - name: blumeops-pg-teslamate - namespace: databases -type: kubernetes.io/basic-auth -stringData: - username: teslamate - password: {{ op://blumeops/TeslaMate/db_password }} diff --git a/argocd/manifests/devpi/secret-root.yaml.tpl b/argocd/manifests/devpi/secret-root.yaml.tpl deleted file mode 100644 index d69f9a8..0000000 --- a/argocd/manifests/devpi/secret-root.yaml.tpl +++ /dev/null @@ -1,12 +0,0 @@ -# Template for devpi root password secret -# Create the secret before deploying: -# kubectl create namespace devpi -# op inject -i argocd/manifests/devpi/secret-root.yaml.tpl | kubectl apply -f - -apiVersion: v1 -kind: Secret -metadata: - name: devpi-root - namespace: devpi -type: Opaque -stringData: - password: "{{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/kyhzfifryqnuk7jeyibmmjvxxm/root password }}" diff --git a/argocd/manifests/forgejo-runner/secret.yaml.tpl b/argocd/manifests/forgejo-runner/secret.yaml.tpl deleted file mode 100644 index b24029a..0000000 --- a/argocd/manifests/forgejo-runner/secret.yaml.tpl +++ /dev/null @@ -1,17 +0,0 @@ -# Forgejo Runner Environment Secret -# This template is processed by `op inject` to resolve 1Password references. -# -# Usage: -# op inject -i secret.yaml.tpl | kubectl --context=minikube-indri apply -f - -# -apiVersion: v1 -kind: Secret -metadata: - name: forgejo-runner-env - namespace: forgejo-runner -type: Opaque -stringData: - 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: "{{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/w3663ffnvkewbftncqxtcpeavy/runner_reg }}" diff --git a/argocd/manifests/grafana-config/secret-admin.yaml.tpl b/argocd/manifests/grafana-config/secret-admin.yaml.tpl deleted file mode 100644 index bdd2c7b..0000000 --- a/argocd/manifests/grafana-config/secret-admin.yaml.tpl +++ /dev/null @@ -1,16 +0,0 @@ -# Grafana admin password secret -# -# Apply with: op inject -i secret-admin.yaml.tpl | kubectl apply -f - -# -# 1Password item: blumeops vault (vg6xf6vvfmoh5hqjjhlhbeoaie) -# Item ID: oxkcr3xtxnewy7noep2izvyr6y -# Field: password -apiVersion: v1 -kind: Secret -metadata: - name: grafana-admin - namespace: monitoring -type: Opaque -stringData: - admin-user: admin - admin-password: {{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/oxkcr3xtxnewy7noep2izvyr6y/password }} diff --git a/argocd/manifests/grafana-config/secret-teslamate-datasource.yaml.tpl b/argocd/manifests/grafana-config/secret-teslamate-datasource.yaml.tpl deleted file mode 100644 index fc2ef62..0000000 --- a/argocd/manifests/grafana-config/secret-teslamate-datasource.yaml.tpl +++ /dev/null @@ -1,13 +0,0 @@ -# TeslaMate PostgreSQL datasource password for Grafana -# Apply with: op inject -i argocd/manifests/grafana-config/secret-teslamate-datasource.yaml.tpl | kubectl apply -f - -# -# This secret is mounted as environment variables in Grafana -# The password is referenced in values.yaml datasource config as $TESLAMATE_DB_PASSWORD -apiVersion: v1 -kind: Secret -metadata: - name: grafana-teslamate-datasource - namespace: monitoring -type: Opaque -stringData: - TESLAMATE_DB_PASSWORD: {{ op://blumeops/TeslaMate/db_password }} diff --git a/argocd/manifests/immich/README.md b/argocd/manifests/immich/README.md index 0c1bfef..76e8ac9 100644 --- a/argocd/manifests/immich/README.md +++ b/argocd/manifests/immich/README.md @@ -19,17 +19,20 @@ Self-hosted photo and video management solution with AI-powered search and face ## Secret Setup +The `immich-db` secret contains the database password, which is auto-generated by CloudNativePG +in the `immich-pg-app` secret. To create or regenerate the secret: + ```bash -# Create namespace -kubectl create namespace immich +# Create namespace if needed +kubectl --context=minikube-indri create namespace immich -# Get the auto-generated immich password from CloudNativePG -kubectl -n databases get secret immich-pg-app -o jsonpath='{.data.password}' | base64 -d - -# Store that password in 1Password under blumeops/immich-pg, then: -op inject -i argocd/manifests/immich/secret-db.yaml.tpl | kubectl apply -f - +# Copy password from CNPG secret to immich namespace +kubectl --context=minikube-indri create secret generic immich-db -n immich \ + --from-literal=password="$(kubectl --context=minikube-indri -n databases get secret immich-pg-app -o jsonpath='{.data.password}' | base64 -d)" ``` +Note: This secret is not managed by ExternalSecrets since the source of truth is the CNPG-generated secret. + ## Access - **URL**: https://photos.ops.eblu.me (after Caddy is updated) diff --git a/argocd/manifests/immich/secret-db.yaml.tpl b/argocd/manifests/immich/secret-db.yaml.tpl deleted file mode 100644 index cec6328..0000000 --- a/argocd/manifests/immich/secret-db.yaml.tpl +++ /dev/null @@ -1,12 +0,0 @@ -# Immich database password secret -# Apply with: op inject -i argocd/manifests/immich/secret-db.yaml.tpl | kubectl apply -f - -apiVersion: v1 -kind: Secret -metadata: - name: immich-db - namespace: immich -type: Opaque -stringData: - # Password is auto-generated by CloudNativePG and stored in immich-pg-app secret - # Retrieve with: kubectl -n databases get secret immich-pg-app -o jsonpath='{.data.password}' | base64 -d - password: "{{ op://blumeops/immich-pg/password }}" diff --git a/argocd/manifests/miniflux/README.md b/argocd/manifests/miniflux/README.md index 4d093dd..b66d41b 100644 --- a/argocd/manifests/miniflux/README.md +++ b/argocd/manifests/miniflux/README.md @@ -16,8 +16,11 @@ RSS/Atom feed reader deployed via ArgoCD. kubectl create namespace miniflux # The miniflux user password is auto-generated by CNPG in blumeops-pg-app secret -kubectl create secret generic miniflux-db -n miniflux \ - --from-literal=url="$(kubectl -n databases get secret blumeops-pg-app -o jsonpath='{.data.uri}' | base64 -d)" +kubectl --context=minikube-indri create secret generic miniflux-db -n miniflux \ + --from-literal=url="$(kubectl --context=minikube-indri -n databases get secret blumeops-pg-app -o jsonpath='{.data.uri}' | base64 -d)" + +# Note: This secret is not managed by ExternalSecrets since the source of truth +# is the CNPG-generated secret. ``` 2. Apply the ArgoCD application: diff --git a/argocd/manifests/miniflux/secret-db.yaml.tpl b/argocd/manifests/miniflux/secret-db.yaml.tpl deleted file mode 100644 index 462e407..0000000 --- a/argocd/manifests/miniflux/secret-db.yaml.tpl +++ /dev/null @@ -1,13 +0,0 @@ -# Miniflux database connection secret -# -# The miniflux user password is auto-generated by CloudNativePG and stored in -# blumeops-pg-app secret in the databases namespace. To create this secret: -# -# 1. Get the URI from CNPG secret: -# kubectl -n databases get secret blumeops-pg-app -o jsonpath='{.data.uri}' | base64 -d -# -# 2. Create the secret (one-liner): -# kubectl create secret generic miniflux-db -n miniflux \ -# --from-literal=url="$(kubectl -n databases get secret blumeops-pg-app -o jsonpath='{.data.uri}' | base64 -d)" -# -# Note: Uses internal k8s DNS hostname (blumeops-pg-rw.databases) not Tailscale diff --git a/argocd/manifests/tailscale-operator/secret.yaml.tpl b/argocd/manifests/tailscale-operator/secret.yaml.tpl deleted file mode 100644 index 700bfc0..0000000 --- a/argocd/manifests/tailscale-operator/secret.yaml.tpl +++ /dev/null @@ -1,14 +0,0 @@ -# Tailscale Operator OAuth Secret -# This template is processed by `op inject` to resolve 1Password references. -# -# Usage: -# op inject -i secret.yaml.tpl | kubectl apply -f - -# -apiVersion: v1 -kind: Secret -metadata: - name: operator-oauth - namespace: tailscale -stringData: - client_id: "{{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/2it22lavwgbxdskoaxanej354q/client-id }}" - client_secret: "{{ op://vg6xf6vvfmoh5hqjjhlhbeoaie/2it22lavwgbxdskoaxanej354q/client-secret }}" diff --git a/argocd/manifests/teslamate/secret-db.yaml.tpl b/argocd/manifests/teslamate/secret-db.yaml.tpl deleted file mode 100644 index 82aa731..0000000 --- a/argocd/manifests/teslamate/secret-db.yaml.tpl +++ /dev/null @@ -1,11 +0,0 @@ -# TeslaMate database password secret -# -# Apply with: op inject -i argocd/manifests/teslamate/secret-db.yaml.tpl | kubectl apply -f - -apiVersion: v1 -kind: Secret -metadata: - name: teslamate-db - namespace: teslamate -type: Opaque -stringData: - password: {{ op://blumeops/TeslaMate/db_password }} diff --git a/argocd/manifests/teslamate/secret-encryption-key.yaml.tpl b/argocd/manifests/teslamate/secret-encryption-key.yaml.tpl deleted file mode 100644 index a0e57a4..0000000 --- a/argocd/manifests/teslamate/secret-encryption-key.yaml.tpl +++ /dev/null @@ -1,12 +0,0 @@ -# TeslaMate encryption key secret -# This key encrypts Tesla API tokens at rest in the database -# -# Apply with: op inject -i argocd/manifests/teslamate/secret-encryption-key.yaml.tpl | kubectl apply -f - -apiVersion: v1 -kind: Secret -metadata: - name: teslamate-encryption - namespace: teslamate -type: Opaque -stringData: - key: {{ op://blumeops/TeslaMate/api_enc_key }} -- 2.50.1 (Apple Git-155) From 9114aac8f66246a698f4a7bb3fe0708430f0df11 Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Wed, 28 Jan 2026 20:27:16 -0800 Subject: [PATCH 3/4] Switch all ExternalSecrets to creationPolicy: Owner ESO now has full ownership of these secrets. Co-Authored-By: Claude Opus 4.5 --- argocd/manifests/argocd/external-secret-repo-forge.yaml | 2 +- argocd/manifests/databases/external-secret-borgmatic.yaml | 2 +- argocd/manifests/databases/external-secret-eblume.yaml | 2 +- argocd/manifests/databases/external-secret-teslamate.yaml | 2 +- argocd/manifests/forgejo-runner/external-secret.yaml | 2 +- argocd/manifests/grafana-config/external-secret-admin.yaml | 2 +- .../grafana-config/external-secret-teslamate-datasource.yaml | 2 +- argocd/manifests/tailscale-operator/external-secret.yaml | 2 +- argocd/manifests/teslamate/external-secret-db.yaml | 2 +- argocd/manifests/teslamate/external-secret-encryption-key.yaml | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/argocd/manifests/argocd/external-secret-repo-forge.yaml b/argocd/manifests/argocd/external-secret-repo-forge.yaml index 61fe3d6..1f96a43 100644 --- a/argocd/manifests/argocd/external-secret-repo-forge.yaml +++ b/argocd/manifests/argocd/external-secret-repo-forge.yaml @@ -19,7 +19,7 @@ spec: name: onepassword-blumeops target: name: repo-creds-forge - creationPolicy: Merge + creationPolicy: Owner template: metadata: labels: diff --git a/argocd/manifests/databases/external-secret-borgmatic.yaml b/argocd/manifests/databases/external-secret-borgmatic.yaml index 0af8cf6..ee600e3 100644 --- a/argocd/manifests/databases/external-secret-borgmatic.yaml +++ b/argocd/manifests/databases/external-secret-borgmatic.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: blumeops-pg-borgmatic - creationPolicy: Merge + creationPolicy: Owner template: type: kubernetes.io/basic-auth data: diff --git a/argocd/manifests/databases/external-secret-eblume.yaml b/argocd/manifests/databases/external-secret-eblume.yaml index 532a1ed..a324c7d 100644 --- a/argocd/manifests/databases/external-secret-eblume.yaml +++ b/argocd/manifests/databases/external-secret-eblume.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: blumeops-pg-eblume - creationPolicy: Merge + creationPolicy: Owner template: type: kubernetes.io/basic-auth data: diff --git a/argocd/manifests/databases/external-secret-teslamate.yaml b/argocd/manifests/databases/external-secret-teslamate.yaml index 346a4bb..0c52e0b 100644 --- a/argocd/manifests/databases/external-secret-teslamate.yaml +++ b/argocd/manifests/databases/external-secret-teslamate.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: blumeops-pg-teslamate - creationPolicy: Merge + creationPolicy: Owner template: type: kubernetes.io/basic-auth data: diff --git a/argocd/manifests/forgejo-runner/external-secret.yaml b/argocd/manifests/forgejo-runner/external-secret.yaml index ec1f5c6..21139b7 100644 --- a/argocd/manifests/forgejo-runner/external-secret.yaml +++ b/argocd/manifests/forgejo-runner/external-secret.yaml @@ -20,7 +20,7 @@ spec: name: onepassword-blumeops target: name: forgejo-runner-env - creationPolicy: Merge + creationPolicy: Owner template: data: FORGEJO_URL: "https://forge.ops.eblu.me" diff --git a/argocd/manifests/grafana-config/external-secret-admin.yaml b/argocd/manifests/grafana-config/external-secret-admin.yaml index 547676b..6876d97 100644 --- a/argocd/manifests/grafana-config/external-secret-admin.yaml +++ b/argocd/manifests/grafana-config/external-secret-admin.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: grafana-admin - creationPolicy: Merge + creationPolicy: Owner template: data: admin-user: admin diff --git a/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml b/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml index 4533c2f..3f8af1a 100644 --- a/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml +++ b/argocd/manifests/grafana-config/external-secret-teslamate-datasource.yaml @@ -20,7 +20,7 @@ spec: name: onepassword-blumeops target: name: grafana-teslamate-datasource - creationPolicy: Merge + creationPolicy: Owner template: data: TESLAMATE_DB_PASSWORD: "{{ .password }}" diff --git a/argocd/manifests/tailscale-operator/external-secret.yaml b/argocd/manifests/tailscale-operator/external-secret.yaml index b8658cc..45aae71 100644 --- a/argocd/manifests/tailscale-operator/external-secret.yaml +++ b/argocd/manifests/tailscale-operator/external-secret.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: operator-oauth - creationPolicy: Merge + creationPolicy: Owner data: - secretKey: client_id remoteRef: diff --git a/argocd/manifests/teslamate/external-secret-db.yaml b/argocd/manifests/teslamate/external-secret-db.yaml index 38d1925..11eeec6 100644 --- a/argocd/manifests/teslamate/external-secret-db.yaml +++ b/argocd/manifests/teslamate/external-secret-db.yaml @@ -17,7 +17,7 @@ spec: name: onepassword-blumeops target: name: teslamate-db - creationPolicy: Merge + creationPolicy: Owner data: - secretKey: password remoteRef: diff --git a/argocd/manifests/teslamate/external-secret-encryption-key.yaml b/argocd/manifests/teslamate/external-secret-encryption-key.yaml index 92e1f50..96938bf 100644 --- a/argocd/manifests/teslamate/external-secret-encryption-key.yaml +++ b/argocd/manifests/teslamate/external-secret-encryption-key.yaml @@ -19,7 +19,7 @@ spec: name: onepassword-blumeops target: name: teslamate-encryption - creationPolicy: Merge + creationPolicy: Owner data: - secretKey: key remoteRef: -- 2.50.1 (Apple Git-155) From 8f4660915d4dbee51fbaf8bc3a34df1146dfb2bb Mon Sep 17 00:00:00 2001 From: Erich Blume Date: Wed, 28 Jan 2026 20:31:16 -0800 Subject: [PATCH 4/4] Fix argocd SSH key format for 1Password Connect 1Password Connect doesn't support ?ssh-format=openssh, so we need a separate Secure Note item with the OpenSSH-formatted key. Created new 1Password item: argocd-forge-ssh-key Co-Authored-By: Claude Opus 4.5 --- .../manifests/argocd/external-secret-repo-forge.yaml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/argocd/manifests/argocd/external-secret-repo-forge.yaml b/argocd/manifests/argocd/external-secret-repo-forge.yaml index 1f96a43..dbb6724 100644 --- a/argocd/manifests/argocd/external-secret-repo-forge.yaml +++ b/argocd/manifests/argocd/external-secret-repo-forge.yaml @@ -2,8 +2,11 @@ # # Replaces the manual op inject workflow from repo-forge-secret.yaml.tpl # -# 1Password item: "argocd forge key" in blumeops vault -# Field: "private key" +# 1Password item: "argocd-forge-ssh-key" in blumeops vault (Secure Note) +# Field: "private-key-openssh" +# +# Note: Uses a separate Secure Note item because 1Password Connect doesn't +# support the ?ssh-format=openssh query parameter that the CLI uses. # # This is a repo-creds (credential template) that matches ALL repos under eblume/ # @@ -32,5 +35,5 @@ spec: data: - secretKey: privateKey remoteRef: - key: argocd forge key - property: private key + key: argocd-forge-ssh-key + property: private-key-openssh -- 2.50.1 (Apple Git-155)