apiVersion: apps/v1 kind: Deployment metadata: name: pegasus namespace: jellyfin spec: replicas: 1 revisionHistoryLimit: 3 strategy: type: RollingUpdate rollingUpdate: maxSurge: 0 maxUnavailable: 1 selector: { matchLabels: { app: pegasus } } template: metadata: { labels: { app: pegasus } } spec: nodeSelector: kubernetes.io/arch: amd64 imagePullSecrets: - name: zot-regcred securityContext: runAsNonRoot: true runAsUser: 65532 runAsGroup: 65532 fsGroup: 65532 fsGroupChangePolicy: "OnRootMismatch" initContainers: - name: fix-perms image: alpine:3.20 command: - sh - -lc - | set -eux # Scratch area for tus uploads (always writable) mkdir -p /media/.pegasus-tus chmod 0777 /media/.pegasus-tus # Make each top-level library dir group-writable and setgid, # and try to set its group to 65532 (so the app can write). for d in /media/*; do [ -d "$d" ] || continue base="$(basename "$d")" [ "$base" = ".pegasus-tus" ] && continue # chgrp can fail on some backends; don't block the pod if it does. chgrp 65532 "$d" || true chmod 2775 "$d" || true done securityContext: runAsUser: 0 runAsGroup: 0 runAsNonRoot: false allowPrivilegeEscalation: false volumeMounts: - { name: media, mountPath: /media } containers: - name: pegasus image: registry.bstein.dev/pegasus:1.2.30 # {"$imagepolicy": "jellyfin:pegasus"} imagePullPolicy: Always command: ["/pegasus"] env: - name: PEGASUS_MEDIA_ROOT valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_MEDIA_ROOT } } - name: PEGASUS_BIND valueFrom: { configMapKeyRef: { name: pegasus-config, key: PEGASUS_BIND } } - name: PEGASUS_USER_MAP_FILE value: "/config/user-map.yaml" - name: PEGASUS_SESSION_KEY valueFrom: { secretKeyRef: { name: pegasus-secrets, key: PEGASUS_SESSION_KEY } } - name: JELLYFIN_URL valueFrom: { secretKeyRef: { name: pegasus-secrets, key: JELLYFIN_URL } } - name: PEGASUS_DEBUG value: "1" - name: PEGASUS_DRY_RUN value: "0" ports: [{ name: http, containerPort: 8080 }] readinessProbe: httpGet: { path: /healthz, port: http } initialDelaySeconds: 2 periodSeconds: 5 timeoutSeconds: 1 livenessProbe: httpGet: { path: /healthz, port: http } initialDelaySeconds: 10 periodSeconds: 10 timeoutSeconds: 2 securityContext: allowPrivilegeEscalation: false readOnlyRootFilesystem: true capabilities: { drop: ["ALL"] } resources: requests: { cpu: 100m, memory: 256Mi } limits: { cpu: 1000m, memory: 1Gi } volumeMounts: - name: media mountPath: /media - name: config mountPath: /config readOnly: true - name: tmp mountPath: /tmp volumes: - name: media persistentVolumeClaim: claimName: jellyfin-media-asteria - name: config configMap: { name: pegasus-user-map } - name: tmp emptyDir: {}