summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Buetow <paul@buetow.org>2026-01-03 20:32:15 +0200
committerPaul Buetow <paul@buetow.org>2026-01-03 20:32:15 +0200
commit9c29ad4ceed23bff8453dd699dd70f08bea1b55e (patch)
treeedf0444ec7dca3decf6d23b9f7edcc3cbc358319
parent5fdeef735666c1012b208cb588a469f985b84748 (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/Justfile31
-rw-r--r--f3s/immich/README.md179
-rw-r--r--f3s/immich/helm-chart/Chart.yaml5
-rw-r--r--f3s/immich/helm-chart/templates/.gitignore4
-rw-r--r--f3s/immich/helm-chart/templates/middleware.yaml9
-rw-r--r--f3s/immich/helm-chart/templates/persistent-volume.yaml115
-rw-r--r--f3s/immich/helm-chart/templates/postgres.yaml52
-rw-r--r--f3s/immich/values.yaml66
-rw-r--r--frontends/etc/relayd.conf.tpl7
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"