- Created comprehensive QA checklist covering edge cases (missing EXIF, timezones, codecs, corrupt files) - Added ErrorBoundary component wrapped around TimelineTree and MediaPanel - Created global error.tsx page for unhandled errors - Improved failed asset UX with red borders, warning icons, and inline error display - Added loading skeletons to TimelineTree and MediaPanel - Added retry button for failed media loads - Created DEPLOYMENT_VALIDATION.md with validation commands and checklist - Applied k8s recommendations: - Changed node affinity to required for compute nodes (Pi 5) - Enabled Tailscale LoadBalancer service for MinIO S3 (reliable Range requests) - Enabled cleanup CronJob for staging files
664 lines
17 KiB
YAML
664 lines
17 KiB
YAML
---
|
|
# Source: tline/templates/secret.yaml.tpl
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: tline-tline-secrets
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
type: Opaque
|
|
data:
|
|
POSTGRES_PASSWORD: Y2hhbmdlLW1l
|
|
MINIO_ACCESS_KEY_ID: bWluaW9hZG1pbg==
|
|
MINIO_SECRET_ACCESS_KEY: bWluaW9hZG1pbg==---
|
|
apiVersion: v1
|
|
kind: Secret
|
|
metadata:
|
|
name: tline-tline-registry
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
type: kubernetes.io/dockerconfigjson
|
|
data:
|
|
.dockerconfigjson: eyJhdXRocyI6eyJyZWdpc3RyeS5sYW46NTAwMCI6eyJhdXRoIjoiZFRwdyIsImVtYWlsIjoiZUBleGFtcGxlLmNvbSIsInBhc3N3b3JkIjoicCIsInVzZXJuYW1lIjoidSJ9fX0=
|
|
---
|
|
# Source: tline/templates/configmap.yaml.tpl
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: tline-tline-config
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
data:
|
|
APP_NAME: "flux"
|
|
NEXT_PUBLIC_APP_NAME: "flux"
|
|
QUEUE_NAME: "tline"
|
|
DATABASE_URL: "postgres://tline:change-me@tline-tline-postgres:5432/tline"
|
|
REDIS_URL: "redis://tline-tline-redis:6379"
|
|
MINIO_INTERNAL_ENDPOINT: "http://tline-tline-minio:9000"
|
|
MINIO_PUBLIC_ENDPOINT_TS: "https://minio.tailxyz.ts.net"
|
|
MINIO_REGION: "us-east-1"
|
|
MINIO_BUCKET: "media"
|
|
MINIO_PRESIGN_EXPIRES_SECONDS: "900"
|
|
---
|
|
# Source: tline/templates/minio.yaml.tpl
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: tline-tline-minio
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: minio
|
|
spec:
|
|
type: ClusterIP
|
|
ports:
|
|
- name: s3
|
|
port: 9000
|
|
targetPort: s3
|
|
- name: console
|
|
port: 9001
|
|
targetPort: console
|
|
selector:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: minio
|
|
---
|
|
# Source: tline/templates/postgres.yaml.tpl
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: tline-tline-postgres
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
spec:
|
|
type: ClusterIP
|
|
ports:
|
|
- name: postgres
|
|
port: 5432
|
|
targetPort: postgres
|
|
selector:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: postgres
|
|
---
|
|
# Source: tline/templates/redis.yaml.tpl
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: tline-tline-redis
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
spec:
|
|
type: ClusterIP
|
|
ports:
|
|
- name: redis
|
|
port: 6379
|
|
targetPort: redis
|
|
selector:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: redis
|
|
---
|
|
# Source: tline/templates/web.yaml.tpl
|
|
apiVersion: v1
|
|
kind: Service
|
|
metadata:
|
|
name: tline-tline-web
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: web
|
|
spec:
|
|
type: ClusterIP
|
|
ports:
|
|
- name: http
|
|
port: 3000
|
|
targetPort: http
|
|
selector:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: web
|
|
---
|
|
# Source: tline/templates/redis.yaml.tpl
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: tline-tline-redis
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: redis
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: redis
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: redis
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: redis
|
|
image: "redis:7"
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: redis
|
|
containerPort: 6379
|
|
resources:
|
|
limits:
|
|
cpu: 300m
|
|
memory: 512Mi
|
|
requests:
|
|
cpu: 50m
|
|
memory: 128Mi
|
|
---
|
|
# Source: tline/templates/web.yaml.tpl
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: tline-tline-web
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: web
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: web
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: web
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: web
|
|
image: "registry.lan:5000/tline-web:dev"
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: http
|
|
containerPort: 3000
|
|
envFrom:
|
|
- configMapRef:
|
|
name: tline-tline-config
|
|
env:
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: POSTGRES_PASSWORD
|
|
- name: MINIO_ACCESS_KEY_ID
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_ACCESS_KEY_ID
|
|
- name: MINIO_SECRET_ACCESS_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_SECRET_ACCESS_KEY
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /api/healthz
|
|
port: http
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 5
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /api/healthz
|
|
port: http
|
|
initialDelaySeconds: 20
|
|
periodSeconds: 10
|
|
resources:
|
|
limits:
|
|
cpu: 1000m
|
|
memory: 1Gi
|
|
requests:
|
|
cpu: 200m
|
|
memory: 256Mi
|
|
---
|
|
# Source: tline/templates/worker.yaml.tpl
|
|
apiVersion: apps/v1
|
|
kind: Deployment
|
|
metadata:
|
|
name: tline-tline-worker
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: worker
|
|
spec:
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: worker
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: worker
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: worker
|
|
image: "registry.lan:5000/tline-worker:dev"
|
|
imagePullPolicy: IfNotPresent
|
|
envFrom:
|
|
- configMapRef:
|
|
name: tline-tline-config
|
|
env:
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: POSTGRES_PASSWORD
|
|
- name: MINIO_ACCESS_KEY_ID
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_ACCESS_KEY_ID
|
|
- name: MINIO_SECRET_ACCESS_KEY
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_SECRET_ACCESS_KEY
|
|
resources:
|
|
limits:
|
|
cpu: 2000m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
---
|
|
# Source: tline/templates/minio.yaml.tpl
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: tline-tline-minio
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: minio
|
|
spec:
|
|
serviceName: tline-tline-minio
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: minio
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: minio
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: minio
|
|
image: "minio/minio:RELEASE.2024-01-16T16-07-38Z"
|
|
imagePullPolicy: IfNotPresent
|
|
args:
|
|
- server
|
|
- /data
|
|
- "--console-address=:9001"
|
|
ports:
|
|
- name: s3
|
|
containerPort: 9000
|
|
- name: console
|
|
containerPort: 9001
|
|
env:
|
|
- name: MINIO_ROOT_USER
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_ACCESS_KEY_ID
|
|
- name: MINIO_ROOT_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: MINIO_SECRET_ACCESS_KEY
|
|
readinessProbe:
|
|
httpGet:
|
|
path: /minio/health/ready
|
|
port: s3
|
|
initialDelaySeconds: 10
|
|
periodSeconds: 5
|
|
livenessProbe:
|
|
httpGet:
|
|
path: /minio/health/live
|
|
port: s3
|
|
initialDelaySeconds: 20
|
|
periodSeconds: 10
|
|
resources:
|
|
limits:
|
|
cpu: 1500m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 250m
|
|
memory: 512Mi
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /data
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: data
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: "200Gi"
|
|
---
|
|
# Source: tline/templates/postgres.yaml.tpl
|
|
apiVersion: apps/v1
|
|
kind: StatefulSet
|
|
metadata:
|
|
name: tline-tline-postgres
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: postgres
|
|
spec:
|
|
serviceName: tline-tline-postgres
|
|
replicas: 1
|
|
selector:
|
|
matchLabels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: postgres
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: postgres
|
|
spec:
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: postgres
|
|
image: "postgres:16"
|
|
imagePullPolicy: IfNotPresent
|
|
ports:
|
|
- name: postgres
|
|
containerPort: 5432
|
|
env:
|
|
- name: POSTGRES_USER
|
|
value: "tline"
|
|
- name: POSTGRES_DB
|
|
value: "tline"
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: POSTGRES_PASSWORD
|
|
readinessProbe:
|
|
exec:
|
|
command:
|
|
- sh
|
|
- -c
|
|
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
|
initialDelaySeconds: 5
|
|
periodSeconds: 5
|
|
livenessProbe:
|
|
exec:
|
|
command:
|
|
- sh
|
|
- -c
|
|
- pg_isready -U "$POSTGRES_USER" -d "$POSTGRES_DB"
|
|
initialDelaySeconds: 20
|
|
periodSeconds: 10
|
|
resources:
|
|
limits:
|
|
cpu: 1500m
|
|
memory: 2Gi
|
|
requests:
|
|
cpu: 500m
|
|
memory: 1Gi
|
|
volumeMounts:
|
|
- name: data
|
|
mountPath: /var/lib/postgresql/data
|
|
volumeClaimTemplates:
|
|
- metadata:
|
|
name: data
|
|
spec:
|
|
accessModes:
|
|
- ReadWriteOnce
|
|
resources:
|
|
requests:
|
|
storage: "20Gi"
|
|
---
|
|
# Source: tline/templates/ingress-tailscale.yaml.tpl
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: tline-tline-web
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: web
|
|
annotations:
|
|
spec:
|
|
ingressClassName: tailscale
|
|
tls:
|
|
- hosts:
|
|
- "app"
|
|
rules:
|
|
- host: "app"
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: tline-tline-web
|
|
port:
|
|
number: 3000
|
|
---
|
|
# Source: tline/templates/ingress-tailscale.yaml.tpl
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: tline-tline-minio
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: minio
|
|
annotations:
|
|
spec:
|
|
ingressClassName: tailscale
|
|
tls:
|
|
- hosts:
|
|
- "minio"
|
|
rules:
|
|
- host: "minio"
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: tline-tline-minio
|
|
port:
|
|
number: 9000
|
|
---
|
|
# Source: tline/templates/ingress-tailscale.yaml.tpl
|
|
apiVersion: networking.k8s.io/v1
|
|
kind: Ingress
|
|
metadata:
|
|
name: tline-tline-minio-console
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: minio
|
|
annotations:
|
|
spec:
|
|
ingressClassName: tailscale
|
|
tls:
|
|
- hosts:
|
|
- "minio-console"
|
|
rules:
|
|
- host: "minio-console"
|
|
http:
|
|
paths:
|
|
- path: /
|
|
pathType: Prefix
|
|
backend:
|
|
service:
|
|
name: tline-tline-minio
|
|
port:
|
|
number: 9001
|
|
---
|
|
# Source: tline/templates/job-migrate.yaml.tpl
|
|
apiVersion: batch/v1
|
|
kind: Job
|
|
metadata:
|
|
name: tline-tline-migrate
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/managed-by: Helm
|
|
helm.sh/chart: "tline-0.1.0"
|
|
app.kubernetes.io/component: migrate
|
|
annotations:
|
|
"helm.sh/hook": pre-install,pre-upgrade
|
|
"helm.sh/hook-weight": "-10"
|
|
"helm.sh/hook-delete-policy": before-hook-creation,hook-succeeded
|
|
spec:
|
|
backoffLimit: 3
|
|
template:
|
|
metadata:
|
|
labels:
|
|
app.kubernetes.io/name: tline
|
|
app.kubernetes.io/instance: tline
|
|
app.kubernetes.io/component: migrate
|
|
spec:
|
|
restartPolicy: Never
|
|
imagePullSecrets:
|
|
- name: "tline-tline-registry"
|
|
affinity:
|
|
nodeAffinity:
|
|
requiredDuringSchedulingIgnoredDuringExecution:
|
|
nodeSelectorTerms:
|
|
- matchExpressions:
|
|
- key: node-class
|
|
operator: In
|
|
values:
|
|
- compute
|
|
containers:
|
|
- name: migrate
|
|
image: "registry.lan:5000/tline-worker:dev"
|
|
imagePullPolicy: IfNotPresent
|
|
command:
|
|
- bun
|
|
- run
|
|
- packages/db/src/migrate.ts
|
|
envFrom:
|
|
- configMapRef:
|
|
name: tline-tline-config
|
|
env:
|
|
- name: POSTGRES_PASSWORD
|
|
valueFrom:
|
|
secretKeyRef:
|
|
name: tline-tline-secrets
|
|
key: POSTGRES_PASSWORD
|