From f006090fea106bc4a42d02c6745c6cb000ed3c52 Mon Sep 17 00:00:00 2001 From: Nik Afiq Date: Thu, 23 Jul 2026 20:21:05 +0900 Subject: [PATCH] fix: remove Immich entirely Not used enough to justify chasing the stale-NFS-handle issue on its photos-art mount. Removes manifests/media/immich.yaml (Namespace, PVCs, Deployments, Service, Certificate, IngressRoute), its secret script and sealed secret, immich.home.arpa from both Pi-hole values files, its Dashy dashboard tile, and all other repo references (READMEs, secrets-leak-scanner scope, regen-sealed-secret example, .env.example). Per explicit confirmation: this also means the live namespace's PVCs (immich-library 50Gi, immich-postgres-data 20Gi, immich-ml-cache 10Gi, all local-path with Delete reclaim policy) are intended to be deleted along with it -- any photos actually uploaded to Immich's own library are gone once the namespace is deleted, separately from the read-only NFS folders it browsed (untouched either way, those live independently on nik-debian). Git removal alone does not delete the live cluster resources -- the media Application has prune: false. Manual `kubectl delete namespace immich` still needed to actually free the namespace/PVCs/data. Co-Authored-By: Claude Sonnet 5 --- .claude/agents/secrets-leak-scanner.md | 2 +- .claude/skills/regen-sealed-secret/SKILL.md | 4 +- .env.example | 3 - README.md | 4 +- REFACTOR_PLAN.md | 9 + config/dashy/conf.yaml | 5 - manifests/README.md | 2 +- manifests/media/immich-postgres-sealed.yaml | 13 - manifests/media/immich-postgres-secret.sh | 16 - manifests/media/immich.yaml | 365 -------------------- values/pihole-debian.yaml | 1 - values/pihole.yaml | 1 - 12 files changed, 14 insertions(+), 411 deletions(-) delete mode 100644 manifests/media/immich-postgres-sealed.yaml delete mode 100755 manifests/media/immich-postgres-secret.sh delete mode 100644 manifests/media/immich.yaml diff --git a/.claude/agents/secrets-leak-scanner.md b/.claude/agents/secrets-leak-scanner.md index e9f1b8b..933ef16 100644 --- a/.claude/agents/secrets-leak-scanner.md +++ b/.claude/agents/secrets-leak-scanner.md @@ -22,7 +22,7 @@ names this repo uses: `PORKBUN_API_KEY`, `PORKBUN_SECRET_KEY`, `K3S_NODE_TOKEN`, `GITEA_RUNNER_TOKEN`, `GRAFANA_ADMIN_PASSWORD`, `AUTHENTIK_PROXY_TOKEN`, `AUTHENTIK_*_CLIENT_ID`/`_CLIENT_SECRET`, `REGISTRY_PASSWORD`, `HA_TOKEN`, `DISCORD_TOKEN`, `GUILD_ID`, -`IMMICH_POSTGRES_PASSWORD`, `PIA_USER`, `PIA_PASSWORD`, and Ansible's +`PIA_USER`, `PIA_PASSWORD`, and Ansible's `vault_k3s_node_token` (`ansible/group_vars/all/vault.yaml`). A finding is real if a tracked (non-`.env`) file contains what looks like an diff --git a/.claude/skills/regen-sealed-secret/SKILL.md b/.claude/skills/regen-sealed-secret/SKILL.md index 25d3cba..75961a9 100644 --- a/.claude/skills/regen-sealed-secret/SKILL.md +++ b/.claude/skills/regen-sealed-secret/SKILL.md @@ -9,8 +9,8 @@ Regenerate the sealed secret for: $ARGUMENTS This repo keeps sealed secrets and their source script side by side (e.g. `manifests/home-services/discord-bot-secret.sh` → `manifests/home-services/discord-bot-sealed.yaml`, -`manifests/media/immich-postgres-secret.sh` → -`manifests/media/immich-postgres-sealed.yaml`). The script is the source of +`manifests/home-services/ha-gateway-secret.sh` → +`manifests/home-services/ha-gateway-sealed.yaml`). The script is the source of truth; the `*-sealed.yaml` file is generated output. ## Steps diff --git a/.env.example b/.env.example index 7f06310..d33351b 100644 --- a/.env.example +++ b/.env.example @@ -35,9 +35,6 @@ GUILD_ID=your_discord_guild_id_here SWITCHBOT_TOKEN=your_switchbot_token_here SWITCHBOT_SECRET=your_switchbot_secret_here -# Immich database credentials -IMMICH_POSTGRES_PASSWORD=your_password_here - # Dashy weather widget API key (rotated off the plaintext value formerly in config/dashy/conf.yaml) DASHY_WEATHER_API_KEY=your_api_key_here diff --git a/README.md b/README.md index 6642fd0..2fa900b 100644 --- a/README.md +++ b/README.md @@ -38,7 +38,7 @@ Public services under `nik4nao.com` use Let's Encrypt. | Identity | Authentik, Traefik forward-auth middleware, OIDC integrations | | Observability | kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector, Glances | | Git and CI | Gitea, Gitea Actions runner, registry pull secrets, Gitea backup CronJob | -| Media | Jellyfin, qBittorrent, JDownloader, Immich | +| Media | Jellyfin, qBittorrent, JDownloader | | Home services | Home Assistant ingress, HA gateway, AI gateway, Discord bot | | Public apps | Portfolio, Watch Party ingress to the Mac Mini | | Dashboard | Dashy | @@ -58,7 +58,6 @@ Public services under `nik4nao.com` use Let's Encrypt. | `https://jellyfin.home.arpa` | Jellyfin | Internal CA | | `https://qbittorrent.home.arpa` | qBittorrent | Internal CA | | `https://jdownloader.home.arpa` | JDownloader | Internal CA | -| `https://immich.home.arpa` | Immich | Internal CA | | `https://ha.home.arpa` | Home Assistant | Internal CA | | `https://glances.home.arpa` | Glances on K3s | Internal CA | | `https://glances-debian.home.arpa` | Glances on Debian | Internal CA | @@ -197,7 +196,6 @@ Sealed Secret regeneration: ```bash bash manifests/home-services/discord-bot-secret.sh bash manifests/home-services/ha-gateway-secret.sh -bash manifests/media/immich-postgres-secret.sh ``` Some sealed secrets are maintained directly in the repo, including Argo CD OIDC, diff --git a/REFACTOR_PLAN.md b/REFACTOR_PLAN.md index 1a11e81..9d3044c 100644 --- a/REFACTOR_PLAN.md +++ b/REFACTOR_PLAN.md @@ -12,6 +12,15 @@ Ansible-against-real-hosts was run. All findings are grounded in file citations, and the highest-severity ones were independently re-verified (not just taken from sub-agent research output) before being recorded here. +**Immich removed entirely, 2026-07-23**: not used enough to justify chasing +its stale-NFS-handle issue. `manifests/media/immich.yaml` (+ its secret +script/sealed secret), `immich.home.arpa` DNS entries, its Dashy tile, and all +other repo references are gone. Findings #16 and #20 that mentioned Immich +are now moot for it specifically (kept as historical record, not rewritten). +Live namespace/PVCs need a manual `kubectl delete namespace immich` to +actually free the data -- Argo CD's `media` Application won't do this itself +(`prune: false`). + ## Stage Tracker | Stage | Scope | Status | diff --git a/config/dashy/conf.yaml b/config/dashy/conf.yaml index c33d01c..9d5d094 100644 --- a/config/dashy/conf.yaml +++ b/config/dashy/conf.yaml @@ -129,11 +129,6 @@ sections: url: https://jdownloader.home.arpa target: newtab id: 8_services_jdownloader - - title: Immich - icon: si-immich - url: https://immich.home.arpa - target: newtab - id: 9_services_immich - title: Home Assistant icon: si-homeassistant url: https://ha.home.arpa diff --git a/manifests/README.md b/manifests/README.md index 3621de6..893198f 100644 --- a/manifests/README.md +++ b/manifests/README.md @@ -14,7 +14,7 @@ subdirectories are consumed by Argo CD Applications in `argocd/apps`. | `gitea/` | Gitea storage, backup, public ingress, runner and OIDC/admin secrets | | `home-services/` | HA gateway, AI gateway, Discord bot, service TLS, registry secret | | `homeassistant/` | Home Assistant external service and ingress | -| `media/` | Jellyfin, qBittorrent, JDownloader, Immich | +| `media/` | Jellyfin, qBittorrent, JDownloader | | `monitoring/` | Monitoring PVs, Grafana datasource, Grafana/Auth OIDC secrets | | `network/` | Pi-hole secrets, DDNS, Traefik dashboard, external host ingresses | | `portfolio/` | Portfolio deployment, ingress, registry pull secret | diff --git a/manifests/media/immich-postgres-sealed.yaml b/manifests/media/immich-postgres-sealed.yaml deleted file mode 100644 index 790f82c..0000000 --- a/manifests/media/immich-postgres-sealed.yaml +++ /dev/null @@ -1,13 +0,0 @@ ---- -apiVersion: bitnami.com/v1alpha1 -kind: SealedSecret -metadata: - name: immich-postgres - namespace: immich -spec: - encryptedData: - password: AgAHwzFI/21GYnhIc08Q4E0fshe9AHn77D0u28+f4jxPRSWPvKf7OaKOAoQUfZhFWsfaayphASg7NMpuhgvFl8oC1MZ1oXX48p3M3wOQmV3yhaWFjXtQuDIyhwsRY7IYTED4sPNaEpVM/NGQS8XQyKaFaQ1aAqPwVZwLAVEj5SeJcCnG9lfANB+x8Hua1DZezrYelQQ8kT3xURfOkvZ57e/2kCdvHYs/SXJZCj6iyuXzefjH25ZNqNVGdaa36cT5Mo7V3eNrT014qed+4Uf7uv+aPcrKJYkSRkaPEJdp0THCofiI/QrgKknQTWRrQLxnOFMnTTckrkI89JTo9wCzfXOFF8KcDMAur7E4QfYbgFqLMlCShsY9bcb5mGD5xa2RKoBnQyQslNMYeNWgVmt7sn1F56v5Gh3e2tg++ydCIlQwvUywPFyt/lL9+Eojdn8LknykpmH34z0cd+KVDcsl+9dHRx3jAgefpIwJc+MihGB8H+Sm6dP8PW3r7o29/KgpBPjpebbq4G31QLDyeAjVavk2CxTdnHsJWmWl2mwB5GlrEB1cRqSOctzvDkwx+TdwyRM2Ggl5J2azt+QZaCYES6sTdxPQOUuDJ7SeY3qy9C0v+0OBpu9q1WPUP6E14LUZzdOp4+S8mC6Llwxcypro7oWOS3GrK4z6eSrpj6bg5FlqkEjQjc0EJ4C6kPevLp2JaCdFXt9FXkDTKv97A8sT1ruG9M86FqHf1d6aTWw2UC9i7w== - template: - metadata: - name: immich-postgres - namespace: immich diff --git a/manifests/media/immich-postgres-secret.sh b/manifests/media/immich-postgres-secret.sh deleted file mode 100755 index a4dfdf3..0000000 --- a/manifests/media/immich-postgres-secret.sh +++ /dev/null @@ -1,16 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail -SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" -source "$SCRIPT_DIR/../../.env" - -kubectl create secret generic immich-postgres \ - --namespace=immich \ - --from-literal=password="${IMMICH_POSTGRES_PASSWORD}" \ - --dry-run=client -o yaml \ - | kubeseal \ - --controller-namespace=kube-system \ - --controller-name=sealed-secrets-controller \ - --format yaml \ - > "$SCRIPT_DIR/immich-postgres-sealed.yaml" - -echo "Wrote $SCRIPT_DIR/immich-postgres-sealed.yaml" \ No newline at end of file diff --git a/manifests/media/immich.yaml b/manifests/media/immich.yaml deleted file mode 100644 index 3243394..0000000 --- a/manifests/media/immich.yaml +++ /dev/null @@ -1,365 +0,0 @@ -# Apply: kubectl apply -f manifests/media/immich.yaml -# Delete: kubectl delete -f manifests/media/immich.yaml -# Description: Immich photo management deployment at immich.home.arpa. -# External libraries mounted read-only from NFS. -# NOTE: Set the postgres password before first apply (see Secret below). -apiVersion: v1 -kind: Namespace -metadata: - name: immich ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: immich-postgres-data - namespace: immich - annotations: - helm.sh/resource-policy: keep -spec: - accessModes: - - ReadWriteOnce - storageClassName: local-path - resources: - requests: - storage: 20Gi ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: immich-library - namespace: immich - annotations: - helm.sh/resource-policy: keep -spec: - accessModes: - - ReadWriteOnce - storageClassName: local-path - resources: - requests: - storage: 50Gi ---- -apiVersion: v1 -kind: PersistentVolumeClaim -metadata: - name: immich-ml-cache - namespace: immich -spec: - accessModes: - - ReadWriteOnce - storageClassName: local-path - resources: - requests: - storage: 10Gi ---- -# ─── Postgres ───────────────────────────────────────────────────────────────── -apiVersion: apps/v1 -kind: Deployment -metadata: - name: immich-postgres - namespace: immich -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: immich-postgres - template: - metadata: - labels: - app: immich-postgres - spec: - containers: - - name: postgres - image: ghcr.io/immich-app/postgres:14-vectorchord0.4.3-pgvectors0.2.0 - ports: - - containerPort: 5432 - env: - - name: POSTGRES_DB - value: immich - - name: POSTGRES_USER - value: immich - - name: POSTGRES_PASSWORD - valueFrom: - secretKeyRef: - name: immich-postgres - key: password - - name: POSTGRES_INITDB_ARGS - value: "--data-checksums" - - name: PGDATA - value: /var/lib/postgresql/data/pgdata - readinessProbe: - tcpSocket: - port: 5432 - initialDelaySeconds: 10 - periodSeconds: 15 - livenessProbe: - tcpSocket: - port: 5432 - initialDelaySeconds: 20 - periodSeconds: 30 - resources: - requests: - cpu: 100m - memory: 512Mi - limits: - cpu: 1000m - memory: 1Gi - volumeMounts: - - name: data - mountPath: /var/lib/postgresql/data - volumes: - - name: data - persistentVolumeClaim: - claimName: immich-postgres-data ---- -apiVersion: v1 -kind: Service -metadata: - name: immich-postgres - namespace: immich -spec: - selector: - app: immich-postgres - ports: - - port: 5432 - targetPort: 5432 ---- -# ─── Redis ──────────────────────────────────────────────────────────────────── -apiVersion: apps/v1 -kind: Deployment -metadata: - name: immich-redis - namespace: immich -spec: - replicas: 1 - selector: - matchLabels: - app: immich-redis - template: - metadata: - labels: - app: immich-redis - spec: - containers: - - name: redis - image: docker.io/redis:6.2-alpine - ports: - - containerPort: 6379 - readinessProbe: - tcpSocket: - port: 6379 - initialDelaySeconds: 5 - periodSeconds: 10 - livenessProbe: - tcpSocket: - port: 6379 - initialDelaySeconds: 10 - periodSeconds: 30 - resources: - requests: - cpu: 10m - memory: 32Mi - limits: - cpu: 200m - memory: 128Mi - volumeMounts: - - name: data - mountPath: /data - volumes: - - name: data - emptyDir: {} ---- -apiVersion: v1 -kind: Service -metadata: - name: immich-redis - namespace: immich -spec: - selector: - app: immich-redis - ports: - - port: 6379 - targetPort: 6379 ---- -# ─── Immich Server ──────────────────────────────────────────────────────────── -apiVersion: apps/v1 -kind: Deployment -metadata: - name: immich-server - namespace: immich -spec: - replicas: 1 - strategy: - type: Recreate - selector: - matchLabels: - app: immich-server - template: - metadata: - labels: - app: immich-server - spec: - containers: - - name: immich-server - image: ghcr.io/immich-app/immich-server:v2.7.5 - ports: - - containerPort: 2283 - env: - - name: DB_HOSTNAME - value: immich-postgres - - name: DB_DATABASE_NAME - value: immich - - name: DB_USERNAME - value: immich - - name: DB_PASSWORD - valueFrom: - secretKeyRef: - name: immich-postgres - key: password - - name: REDIS_HOSTNAME - value: immich-redis - - name: IMMICH_MACHINE_LEARNING_URL - value: http://immich-machine-learning:3003 - - name: TZ - value: Asia/Tokyo - readinessProbe: - tcpSocket: - port: 2283 - initialDelaySeconds: 15 - periodSeconds: 15 - livenessProbe: - tcpSocket: - port: 2283 - initialDelaySeconds: 30 - periodSeconds: 30 - resources: - requests: - cpu: 200m - memory: 2Gi - limits: - cpu: 2000m - memory: 4Gi - volumeMounts: - - name: library - mountPath: /usr/src/app/upload - - name: photos-other - mountPath: /mnt/external/other - readOnly: true - - name: photos-art - mountPath: /mnt/external/art - readOnly: true - volumes: - - name: library - persistentVolumeClaim: - claimName: immich-library - - name: photos-other - nfs: - server: 192.168.7.183 - path: /mnt/storage/jellyfin/other - - name: photos-art - nfs: - server: 192.168.7.183 - path: /mnt/storage/jellyfin/art ---- -apiVersion: v1 -kind: Service -metadata: - name: immich-server - namespace: immich -spec: - selector: - app: immich-server - ports: - - port: 2283 - targetPort: 2283 ---- -# ─── Immich Machine Learning ────────────────────────────────────────────────── -apiVersion: apps/v1 -kind: Deployment -metadata: - name: immich-machine-learning - namespace: immich -spec: - replicas: 1 - selector: - matchLabels: - app: immich-machine-learning - template: - metadata: - labels: - app: immich-machine-learning - spec: - containers: - - name: immich-machine-learning - image: ghcr.io/immich-app/immich-machine-learning:v2.7.5 - ports: - - containerPort: 3003 - readinessProbe: - tcpSocket: - port: 3003 - initialDelaySeconds: 15 - periodSeconds: 15 - livenessProbe: - tcpSocket: - port: 3003 - initialDelaySeconds: 30 - periodSeconds: 30 - resources: - requests: - cpu: 200m - memory: 512Mi - limits: - cpu: 2000m - memory: 2Gi - volumeMounts: - - name: cache - mountPath: /cache - volumes: - - name: cache - persistentVolumeClaim: - claimName: immich-ml-cache ---- -apiVersion: v1 -kind: Service -metadata: - name: immich-machine-learning - namespace: immich -spec: - selector: - app: immich-machine-learning - ports: - - port: 3003 - targetPort: 3003 ---- -# ─── Ingress / TLS ──────────────────────────────────────────────────────────── -apiVersion: cert-manager.io/v1 -kind: Certificate -metadata: - name: immich-tls - namespace: immich -spec: - secretName: immich-tls - issuerRef: - name: internal-ca-issuer - kind: ClusterIssuer - dnsNames: - - immich.home.arpa ---- -apiVersion: traefik.io/v1alpha1 -kind: IngressRoute -metadata: - name: immich - namespace: immich -spec: - entryPoints: - - websecure - routes: - - kind: Rule - match: Host(`immich.home.arpa`) - services: - - name: immich-server - namespace: immich - port: 2283 - tls: - secretName: immich-tls diff --git a/values/pihole-debian.yaml b/values/pihole-debian.yaml index 9374a7f..630904f 100644 --- a/values/pihole-debian.yaml +++ b/values/pihole-debian.yaml @@ -46,7 +46,6 @@ dnsmasq: - address=/ca.home.arpa/192.168.7.77 - address=/auth.home.arpa/192.168.7.77 - address=/traefik.home.arpa/192.168.7.77 - - address=/immich.home.arpa/192.168.7.77 - address=/gitea.nik4nao.com/192.168.7.77 - address=/ha.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77 diff --git a/values/pihole.yaml b/values/pihole.yaml index 55baab7..d900011 100644 --- a/values/pihole.yaml +++ b/values/pihole.yaml @@ -77,7 +77,6 @@ dnsmasq: - address=/ca.home.arpa/192.168.7.77 - address=/auth.home.arpa/192.168.7.77 - address=/traefik.home.arpa/192.168.7.77 - - address=/immich.home.arpa/192.168.7.77 - address=/gitea.nik4nao.com/192.168.7.77 - address=/ha.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77