fix: remove Immich entirely
Some checks failed
validate / lint (push) Failing after 1s

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 <noreply@anthropic.com>
This commit is contained in:
Nik Afiq 2026-07-23 20:21:05 +09:00
parent 7fbab2561a
commit f006090fea
12 changed files with 14 additions and 411 deletions

View File

@ -22,7 +22,7 @@ names this repo uses: `PORKBUN_API_KEY`, `PORKBUN_SECRET_KEY`,
`K3S_NODE_TOKEN`, `GITEA_RUNNER_TOKEN`, `GRAFANA_ADMIN_PASSWORD`, `K3S_NODE_TOKEN`, `GITEA_RUNNER_TOKEN`, `GRAFANA_ADMIN_PASSWORD`,
`AUTHENTIK_PROXY_TOKEN`, `AUTHENTIK_*_CLIENT_ID`/`_CLIENT_SECRET`, `AUTHENTIK_PROXY_TOKEN`, `AUTHENTIK_*_CLIENT_ID`/`_CLIENT_SECRET`,
`REGISTRY_PASSWORD`, `HA_TOKEN`, `DISCORD_TOKEN`, `GUILD_ID`, `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`). `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 A finding is real if a tracked (non-`.env`) file contains what looks like an

View File

@ -9,8 +9,8 @@ Regenerate the sealed secret for: $ARGUMENTS
This repo keeps sealed secrets and their source script side by side (e.g. 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-secret.sh`
`manifests/home-services/discord-bot-sealed.yaml`, `manifests/home-services/discord-bot-sealed.yaml`,
`manifests/media/immich-postgres-secret.sh` → `manifests/home-services/ha-gateway-secret.sh` →
`manifests/media/immich-postgres-sealed.yaml`). The script is the source of `manifests/home-services/ha-gateway-sealed.yaml`). The script is the source of
truth; the `*-sealed.yaml` file is generated output. truth; the `*-sealed.yaml` file is generated output.
## Steps ## Steps

View File

@ -35,9 +35,6 @@ GUILD_ID=your_discord_guild_id_here
SWITCHBOT_TOKEN=your_switchbot_token_here SWITCHBOT_TOKEN=your_switchbot_token_here
SWITCHBOT_SECRET=your_switchbot_secret_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 widget API key (rotated off the plaintext value formerly in config/dashy/conf.yaml)
DASHY_WEATHER_API_KEY=your_api_key_here DASHY_WEATHER_API_KEY=your_api_key_here

View File

@ -38,7 +38,7 @@ Public services under `nik4nao.com` use Let's Encrypt.
| Identity | Authentik, Traefik forward-auth middleware, OIDC integrations | | Identity | Authentik, Traefik forward-auth middleware, OIDC integrations |
| Observability | kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector, Glances | | Observability | kube-prometheus-stack, Grafana, Loki, Tempo, OpenTelemetry Collector, Glances |
| Git and CI | Gitea, Gitea Actions runner, registry pull secrets, Gitea backup CronJob | | 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 | | Home services | Home Assistant ingress, HA gateway, AI gateway, Discord bot |
| Public apps | Portfolio, Watch Party ingress to the Mac Mini | | Public apps | Portfolio, Watch Party ingress to the Mac Mini |
| Dashboard | Dashy | | Dashboard | Dashy |
@ -58,7 +58,6 @@ Public services under `nik4nao.com` use Let's Encrypt.
| `https://jellyfin.home.arpa` | Jellyfin | Internal CA | | `https://jellyfin.home.arpa` | Jellyfin | Internal CA |
| `https://qbittorrent.home.arpa` | qBittorrent | Internal CA | | `https://qbittorrent.home.arpa` | qBittorrent | Internal CA |
| `https://jdownloader.home.arpa` | JDownloader | 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://ha.home.arpa` | Home Assistant | Internal CA |
| `https://glances.home.arpa` | Glances on K3s | Internal CA | | `https://glances.home.arpa` | Glances on K3s | Internal CA |
| `https://glances-debian.home.arpa` | Glances on Debian | Internal CA | | `https://glances-debian.home.arpa` | Glances on Debian | Internal CA |
@ -197,7 +196,6 @@ Sealed Secret regeneration:
```bash ```bash
bash manifests/home-services/discord-bot-secret.sh bash manifests/home-services/discord-bot-secret.sh
bash manifests/home-services/ha-gateway-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, Some sealed secrets are maintained directly in the repo, including Argo CD OIDC,

View File

@ -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 citations, and the highest-severity ones were independently re-verified
(not just taken from sub-agent research output) before being recorded here. (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 Tracker
| Stage | Scope | Status | | Stage | Scope | Status |

View File

@ -129,11 +129,6 @@ sections:
url: https://jdownloader.home.arpa url: https://jdownloader.home.arpa
target: newtab target: newtab
id: 8_services_jdownloader id: 8_services_jdownloader
- title: Immich
icon: si-immich
url: https://immich.home.arpa
target: newtab
id: 9_services_immich
- title: Home Assistant - title: Home Assistant
icon: si-homeassistant icon: si-homeassistant
url: https://ha.home.arpa url: https://ha.home.arpa

View File

@ -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 | | `gitea/` | Gitea storage, backup, public ingress, runner and OIDC/admin secrets |
| `home-services/` | HA gateway, AI gateway, Discord bot, service TLS, registry secret | | `home-services/` | HA gateway, AI gateway, Discord bot, service TLS, registry secret |
| `homeassistant/` | Home Assistant external service and ingress | | `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 | | `monitoring/` | Monitoring PVs, Grafana datasource, Grafana/Auth OIDC secrets |
| `network/` | Pi-hole secrets, DDNS, Traefik dashboard, external host ingresses | | `network/` | Pi-hole secrets, DDNS, Traefik dashboard, external host ingresses |
| `portfolio/` | Portfolio deployment, ingress, registry pull secret | | `portfolio/` | Portfolio deployment, ingress, registry pull secret |

View File

@ -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

View File

@ -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"

View File

@ -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

View File

@ -46,7 +46,6 @@ dnsmasq:
- address=/ca.home.arpa/192.168.7.77 - address=/ca.home.arpa/192.168.7.77
- address=/auth.home.arpa/192.168.7.77 - address=/auth.home.arpa/192.168.7.77
- address=/traefik.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=/gitea.nik4nao.com/192.168.7.77
- address=/ha.home.arpa/192.168.7.77 - address=/ha.home.arpa/192.168.7.77
- address=/argocd.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77

View File

@ -77,7 +77,6 @@ dnsmasq:
- address=/ca.home.arpa/192.168.7.77 - address=/ca.home.arpa/192.168.7.77
- address=/auth.home.arpa/192.168.7.77 - address=/auth.home.arpa/192.168.7.77
- address=/traefik.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=/gitea.nik4nao.com/192.168.7.77
- address=/ha.home.arpa/192.168.7.77 - address=/ha.home.arpa/192.168.7.77
- address=/argocd.home.arpa/192.168.7.77 - address=/argocd.home.arpa/192.168.7.77