Files
porthole/.tmp-render.yaml
OpenCode Test 4e2ab7cdd8 task-11: complete QA + hardening with resilience fixes
- 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
2025-12-24 12:45:22 -08:00

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