diff options
| author | Paul Buetow <paul@buetow.org> | 2026-01-03 20:32:15 +0200 |
|---|---|---|
| committer | Paul Buetow <paul@buetow.org> | 2026-01-03 20:32:15 +0200 |
| commit | 9c29ad4ceed23bff8453dd699dd70f08bea1b55e (patch) | |
| tree | edf0444ec7dca3decf6d23b9f7edcc3cbc358319 | |
| parent | 5fdeef735666c1012b208cb588a469f985b84748 (diff) | |
Enable WebSocket support in relayd for audiobookshelf
- Add http websockets directive to relayd.conf.tpl to allow WebSocket upgrade connections
- Fix "Socket failed to connect" error in audiobookshelf web interface
- Also add immich helm chart configuration
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
| -rw-r--r-- | f3s/immich/Justfile | 31 | ||||
| -rw-r--r-- | f3s/immich/README.md | 179 | ||||
| -rw-r--r-- | f3s/immich/helm-chart/Chart.yaml | 5 | ||||
| -rw-r--r-- | f3s/immich/helm-chart/templates/.gitignore | 4 | ||||
| -rw-r--r-- | f3s/immich/helm-chart/templates/middleware.yaml | 9 | ||||
| -rw-r--r-- | f3s/immich/helm-chart/templates/persistent-volume.yaml | 115 | ||||
| -rw-r--r-- | f3s/immich/helm-chart/templates/postgres.yaml | 52 | ||||
| -rw-r--r-- | f3s/immich/values.yaml | 66 | ||||
| -rw-r--r-- | frontends/etc/relayd.conf.tpl | 7 |
9 files changed, 466 insertions, 2 deletions
diff --git a/f3s/immich/Justfile b/f3s/immich/Justfile new file mode 100644 index 0000000..c351bc8 --- /dev/null +++ b/f3s/immich/Justfile @@ -0,0 +1,31 @@ +NAMESPACE := "services" +RELEASE_NAME := "immich" +CHART_NAME := "immich/immich" +VALUES_FILE := "./values.yaml" +CHART_PATH := "./helm-chart" + +# Install the custom resources (PVs, PVCs, PostgreSQL, etc.) +install-resources: + kubectl apply -f {{CHART_PATH}}/templates/ --namespace {{NAMESPACE}} + +# Install Immich using the official Helm chart with custom values +install: + helm install {{RELEASE_NAME}} {{CHART_NAME}} -f {{VALUES_FILE}} --namespace {{NAMESPACE}} --create-namespace + +# Upgrade Immich deployment +upgrade: + helm upgrade {{RELEASE_NAME}} {{CHART_NAME}} -f {{VALUES_FILE}} --namespace {{NAMESPACE}} + +# Delete Immich deployment (keeps PVs and data) +delete: + helm uninstall {{RELEASE_NAME}} --namespace {{NAMESPACE}} + +# Delete all resources including PVs (WARNING: This will delete all data!) +delete-all: + helm uninstall {{RELEASE_NAME}} --namespace {{NAMESPACE}} + kubectl delete -f {{CHART_PATH}}/templates/ --namespace {{NAMESPACE}} + +# Show current deployment status +status: + kubectl get all -n {{NAMESPACE}} -l app.kubernetes.io/instance={{RELEASE_NAME}} + kubectl get pvc -n {{NAMESPACE}} | grep immich diff --git a/f3s/immich/README.md b/f3s/immich/README.md new file mode 100644 index 0000000..d86ec0b --- /dev/null +++ b/f3s/immich/README.md @@ -0,0 +1,179 @@ +# Immich Kubernetes Deployment + +This directory contains the Kubernetes configuration for deploying [Immich](https://immich.app/) - a self-hosted photo and video backup solution. + +## Architecture + +Immich consists of several components: +- **Server**: Main API and web interface +- **Machine Learning**: AI-powered face recognition, object detection, and smart search +- **Valkey**: Redis-compatible cache for job queues +- **PostgreSQL**: Database with pgvector extension for AI features + +## Prerequisites + +1. **Create storage directories on the host**: + ```bash + for host in f0 f1 f2; do + ssh paul@$host "doas mkdir -p /data/nfs/k3svolumes/immich/{library,ml-cache,valkey,postgres}" + ssh paul@$host "doas chown -R 911:911 /data/nfs/k3svolumes/immich/" + done + ``` + +2. **Create a secure database password secret** (REQUIRED before deployment): + ```bash + kubectl create secret generic immich-db-secret \ + --from-literal=password='YOUR_SECURE_PASSWORD_HERE' \ + -n services + ``` + + **Important**: + - Use a strong, unique password + - This secret is NOT included in the repository for security reasons + - The secret must be created before deploying, as PostgreSQL will use it during database initialization + +## Deployment + +⚠️ **Important**: Complete all prerequisites above before deploying, especially creating the database secret! + +1. **Install the custom resources** (PVs, PVCs, PostgreSQL, middleware): + ```bash + just install-resources + ``` + +2. **Install Immich using Helm**: + ```bash + just install + ``` + +3. **Check deployment status**: + ```bash + just status + ``` + + Wait for all pods to be in `Running` state (may take a few minutes for image pulls). + +## Access + +Once deployed, Immich will be available at: **https://immich.f3s.buetow.org** + +Default setup instructions: +1. Navigate to the URL above +2. Create your admin account on first access +3. Follow the setup wizard to configure your preferences + +## Storage + +Persistent storage is configured with the following volumes: +- **Library**: 500GB - Main photo/video storage at `/data/nfs/k3svolumes/immich/library` +- **ML Cache**: 10GB - Machine learning models at `/data/nfs/k3svolumes/immich/ml-cache` +- **PostgreSQL**: 20GB - Database storage at `/data/nfs/k3svolumes/immich/postgres` +- **Valkey**: 1GB - Cache/queue data at `/data/nfs/k3svolumes/immich/valkey` + +## Maintenance + +### Upgrade Immich to latest version +```bash +just upgrade +``` + +### Redeploy after configuration changes + +If you modified any configuration files (values.yaml, templates, etc.): + +1. **Update custom resources** (PVs, PostgreSQL, middleware, etc.): + ```bash + kubectl apply -f helm-chart/templates/ --namespace services + ``` + +2. **Upgrade Immich with new values**: + ```bash + just upgrade + ``` + +3. **Restart specific components** (if needed): + ```bash + # Restart server + kubectl rollout restart deployment/immich-server -n services + + # Restart all Immich components + kubectl rollout restart deployment -l app.kubernetes.io/instance=immich -n services + ``` + +### Update database password secret + +To change the database password after deployment: + +1. **Delete existing secret**: + ```bash + kubectl delete secret immich-db-secret -n services + ``` + +2. **Create new secret with updated password**: + ```bash + kubectl create secret generic immich-db-secret \ + --from-literal=password='YOUR_NEW_PASSWORD' \ + -n services + ``` + +3. **Update PostgreSQL password and restart**: + ```bash + # Connect to PostgreSQL and change password + kubectl exec -n services -it deployment/immich-postgres -- \ + psql -U immich -d immich -c "ALTER USER immich WITH PASSWORD 'YOUR_NEW_PASSWORD';" + + # Restart Immich components to use new password + kubectl rollout restart deployment -l app.kubernetes.io/instance=immich -n services + kubectl rollout restart deployment/immich-postgres -n services + ``` + +### Uninstall (keeps data) +```bash +just delete +``` + +### Complete removal (deletes all data) +```bash +just delete-all +``` + +## Troubleshooting + +### Check pod logs +```bash +kubectl logs -n services -l app.kubernetes.io/instance=immich --tail=100 +``` + +### Check PostgreSQL connection +```bash +kubectl exec -n services -it deployment/immich-postgres -- psql -U immich -d immich -c '\l' +``` + +### Verify persistent volumes +```bash +kubectl get pv,pvc -n services | grep immich +``` + +## Quick Reference + +### Common redeployment workflow + +After making changes to configuration files: + +```bash +# 1. Apply template changes (if any) +kubectl apply -f helm-chart/templates/ --namespace services + +# 2. Upgrade Helm release +just upgrade + +# 3. Check status +just status +``` + +### Force restart all Immich components + +```bash +kubectl rollout restart deployment -l app.kubernetes.io/instance=immich -n services +kubectl rollout restart deployment/immich-postgres -n services +``` diff --git a/f3s/immich/helm-chart/Chart.yaml b/f3s/immich/helm-chart/Chart.yaml new file mode 100644 index 0000000..ff87d46 --- /dev/null +++ b/f3s/immich/helm-chart/Chart.yaml @@ -0,0 +1,5 @@ +apiVersion: v2 +name: immich-resources +description: Custom resources for Immich deployment (PVs, PVCs, PostgreSQL, Middleware) +version: 0.1.0 +appVersion: "2.0.0" diff --git a/f3s/immich/helm-chart/templates/.gitignore b/f3s/immich/helm-chart/templates/.gitignore new file mode 100644 index 0000000..e333298 --- /dev/null +++ b/f3s/immich/helm-chart/templates/.gitignore @@ -0,0 +1,4 @@ +# Do not commit secrets to the repository +# Create secrets manually using kubectl as documented in README.md +secret.yaml +*-secret.yaml diff --git a/f3s/immich/helm-chart/templates/middleware.yaml b/f3s/immich/helm-chart/templates/middleware.yaml new file mode 100644 index 0000000..a53eeaf --- /dev/null +++ b/f3s/immich/helm-chart/templates/middleware.yaml @@ -0,0 +1,9 @@ +# Traefik Middleware to remove body size limit for large photo/video uploads +apiVersion: traefik.io/v1alpha1 +kind: Middleware +metadata: + name: immich-body-size + namespace: services +spec: + buffering: + maxRequestBodyBytes: 0 diff --git a/f3s/immich/helm-chart/templates/persistent-volume.yaml b/f3s/immich/helm-chart/templates/persistent-volume.yaml new file mode 100644 index 0000000..0b3a49f --- /dev/null +++ b/f3s/immich/helm-chart/templates/persistent-volume.yaml @@ -0,0 +1,115 @@ +# Immich Library PersistentVolume - Main photo/video storage +apiVersion: v1 +kind: PersistentVolume +metadata: + name: immich-library-pv +spec: + capacity: + storage: 500Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/immich/library + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: immich-library-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 500Gi +--- +# Immich ML Cache PersistentVolume - Machine learning models cache +apiVersion: v1 +kind: PersistentVolume +metadata: + name: immich-ml-cache-pv +spec: + capacity: + storage: 10Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/immich/ml-cache + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: immich-ml-cache-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 10Gi +--- +# Immich Valkey PersistentVolume - Redis replacement for job queues +apiVersion: v1 +kind: PersistentVolume +metadata: + name: immich-valkey-pv +spec: + capacity: + storage: 1Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/immich/valkey + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: immich-valkey-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 1Gi +--- +# Immich PostgreSQL PersistentVolume - Database storage +apiVersion: v1 +kind: PersistentVolume +metadata: + name: immich-postgres-pv +spec: + capacity: + storage: 20Gi + volumeMode: Filesystem + accessModes: + - ReadWriteOnce + persistentVolumeReclaimPolicy: Retain + hostPath: + path: /data/nfs/k3svolumes/immich/postgres + type: Directory +--- +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: immich-postgres-pvc + namespace: services +spec: + storageClassName: "" + accessModes: + - ReadWriteOnce + resources: + requests: + storage: 20Gi diff --git a/f3s/immich/helm-chart/templates/postgres.yaml b/f3s/immich/helm-chart/templates/postgres.yaml new file mode 100644 index 0000000..0064dcd --- /dev/null +++ b/f3s/immich/helm-chart/templates/postgres.yaml @@ -0,0 +1,52 @@ +# PostgreSQL Deployment for Immich +# Requires PostgreSQL 16+ with pgvector extension +apiVersion: apps/v1 +kind: Deployment +metadata: + name: immich-postgres + namespace: services +spec: + replicas: 1 + selector: + matchLabels: + app: immich-postgres + template: + metadata: + labels: + app: immich-postgres + spec: + containers: + - name: postgres + image: tensorchord/pgvecto-rs:pg16-v0.3.0 + ports: + - containerPort: 5432 + env: + - name: POSTGRES_DB + value: immich + - name: POSTGRES_USER + value: immich + - name: POSTGRES_PASSWORD + valueFrom: + secretKeyRef: + name: immich-db-secret + key: password + volumeMounts: + - name: postgres-data + mountPath: /var/lib/postgresql/data + volumes: + - name: postgres-data + persistentVolumeClaim: + claimName: immich-postgres-pvc +--- +apiVersion: v1 +kind: Service +metadata: + name: immich-postgres + namespace: services +spec: + selector: + app: immich-postgres + ports: + - protocol: TCP + port: 5432 + targetPort: 5432 diff --git a/f3s/immich/values.yaml b/f3s/immich/values.yaml new file mode 100644 index 0000000..4063242 --- /dev/null +++ b/f3s/immich/values.yaml @@ -0,0 +1,66 @@ +# Immich Helm Chart Configuration +# Deploy to services namespace with persistent storage + +# Enable Valkey (Redis replacement) with persistent storage +valkey: + enabled: true + persistence: + data: + enabled: true + type: persistentVolumeClaim + size: 1Gi + storageClass: "" + existingClaim: "immich-valkey-pvc" + +# Immich-specific configuration +immich: + persistence: + # Main data store for all photos/videos shared between components + library: + existingClaim: "immich-library-pvc" + +# Server component with ingress +server: + enabled: true + ingress: + main: + enabled: true + annotations: + spec.ingressClassName: traefik + traefik.ingress.kubernetes.io/router.entrypoints: web + # Remove body size limit for file uploads + traefik.ingress.kubernetes.io/router.middlewares: services-immich-body-size@kubernetescrd + hosts: + - host: immich.f3s.buetow.org + paths: + - path: "/" + service: + identifier: main + port: 2283 + +# Machine Learning component with cache persistence +machine-learning: + enabled: true + persistence: + cache: + enabled: true + type: persistentVolumeClaim + size: 10Gi + storageClass: "" + existingClaim: "immich-ml-cache-pvc" + +# PostgreSQL database configuration +# Note: You'll need to configure database connection via environment variables +controllers: + main: + containers: + main: + env: + DB_HOSTNAME: immich-postgres + DB_DATABASE_NAME: immich + DB_USERNAME: immich + DB_PASSWORD: + valueFrom: + secretKeyRef: + name: immich-db-secret + key: password diff --git a/frontends/etc/relayd.conf.tpl b/frontends/etc/relayd.conf.tpl index 328ba8f..2a2901b 100644 --- a/frontends/etc/relayd.conf.tpl +++ b/frontends/etc/relayd.conf.tpl @@ -28,10 +28,13 @@ http protocol "https" { <% } -%> tls keypair <%= $hostname.'.'.$domain -%> + # Enable WebSocket support + http websockets + match request header set "X-Forwarded-For" value "$REMOTE_ADDR" match request header set "X-Forwarded-Proto" value "https" - - # WebSocket support for audiobookshelf + + # WebSocket headers - passed through for WebSocket connections pass header "Connection" pass header "Upgrade" pass header "Sec-WebSocket-Key" |
