diff --git a/apps/base/arrstack/arrproxy/migrate-job.yaml b/apps/base/arrstack/arrproxy/migrate-job.yaml index 7f908f6..6cc9fe5 100644 --- a/apps/base/arrstack/arrproxy/migrate-job.yaml +++ b/apps/base/arrstack/arrproxy/migrate-job.yaml @@ -35,7 +35,7 @@ spec: type: RuntimeDefault containers: - name: migrate - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/postgres:18-alpine + image: docker.io/library/postgres:18-alpine imagePullPolicy: IfNotPresent env: - name: HOME diff --git a/apps/base/arrstack/arrproxy/oauth2-proxy-deployment.yaml b/apps/base/arrstack/arrproxy/oauth2-proxy-deployment.yaml index 4b5faa4..70fb45e 100644 --- a/apps/base/arrstack/arrproxy/oauth2-proxy-deployment.yaml +++ b/apps/base/arrstack/arrproxy/oauth2-proxy-deployment.yaml @@ -35,7 +35,7 @@ spec: # identity.unkin.net serves a Vault-PKI cert; combine the system roots # with the internal CA so oauth2-proxy's OIDC HTTP client trusts it. - name: combine-certs - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/alpine:3 + image: docker.io/library/alpine:3 imagePullPolicy: IfNotPresent command: - sh diff --git a/apps/base/arrstack/kustomization.yaml b/apps/base/arrstack/kustomization.yaml index f975b7d..1ddf27f 100644 --- a/apps/base/arrstack/kustomization.yaml +++ b/apps/base/arrstack/kustomization.yaml @@ -8,9 +8,12 @@ resources: - pv-media-tv.yaml - pv-media-movies.yaml - pv-mediafs.yaml + - pv-mediastore.yaml - pvc-media-tv.yaml - pvc-media-movies.yaml - pvc-mediafs.yaml + - pvc-mediastore.yaml + - mediastore-bootstrap-job.yaml - media-bucket.yaml - backups-bucket.yaml - postgres diff --git a/apps/base/arrstack/mediastore-bootstrap-job.yaml b/apps/base/arrstack/mediastore-bootstrap-job.yaml new file mode 100644 index 0000000..846b070 --- /dev/null +++ b/apps/base/arrstack/mediastore-bootstrap-job.yaml @@ -0,0 +1,74 @@ +--- +# Seeds the directory skeleton on the freshly created mediastore subvolume so +# the arrs, nzbget and both jellyfins mount subPaths that already exist and are +# owned by uid/gid 1000 (the uid every arrstack media pod runs as). mkdir -p is +# idempotent, so re-running it on every sync is harmless and self-heals a tree +# someone deleted by hand. +# +# Sync hook with BeforeHookCreation delete: ArgoCD replaces the completed Job +# each sync instead of failing on the immutable pod template. No sync-wave is +# needed -- the PVC applies in the same wave and the pod simply stays Pending +# until it binds. +apiVersion: batch/v1 +kind: Job +metadata: + name: mediastore-bootstrap + namespace: arrstack + annotations: + argocd.argoproj.io/hook: Sync + argocd.argoproj.io/hook-delete-policy: BeforeHookCreation +spec: + backoffLimit: 6 + ttlSecondsAfterFinished: 600 + template: + metadata: + labels: + app: mediastore-bootstrap + spec: + serviceAccountName: default + automountServiceAccountToken: false + restartPolicy: Never + securityContext: + runAsNonRoot: true + runAsUser: 1000 + runAsGroup: 1000 + fsGroup: 1000 + fsGroupChangePolicy: OnRootMismatch + seccompProfile: + type: RuntimeDefault + containers: + - name: mkdir + image: docker.io/library/alpine:3 + imagePullPolicy: IfNotPresent + command: + - sh + - -c + - | + set -eu + mkdir -p \ + /media/fafflix/tvseries \ + /media/fafflix/movies \ + /media/cheeztv/tvseries \ + /media/cheeztv/movies \ + /media/nzbget/downloads/complete + ls -la /media + volumeMounts: + - name: mediastore + mountPath: /media + securityContext: + allowPrivilegeEscalation: false + readOnlyRootFilesystem: true + capabilities: + drop: + - ALL + resources: + requests: + cpu: 10m + memory: 32Mi + limits: + cpu: 200m + memory: 128Mi + volumes: + - name: mediastore + persistentVolumeClaim: + claimName: mediastore diff --git a/apps/base/arrstack/pv-mediastore.yaml b/apps/base/arrstack/pv-mediastore.yaml new file mode 100644 index 0000000..cad3614 --- /dev/null +++ b/apps/base/arrstack/pv-mediastore.yaml @@ -0,0 +1,32 @@ +--- +# Static PV for the shared MEDIASTORE CephFS subvolume: one 10Ti filesystem +# holding every library plus the nzbget download tree, so arr imports are +# same-filesystem hardlink moves across tv AND movies. Same rootPath as the +# fafflix/cheeztv mediastore PVs; each namespace gets its own PV (unique name + +# volumeHandle) pinned by claimRef. +apiVersion: v1 +kind: PersistentVolume +metadata: + name: arrstack-mediastore +spec: + capacity: + storage: 10Ti + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: "" + volumeMode: Filesystem + claimRef: + namespace: arrstack + name: mediastore + csi: + driver: cephfs.csi.ceph.com + volumeHandle: arrstack-mediastore-static + nodeStageSecretRef: + name: csi-cephfs-secret + namespace: csi-cephfs + volumeAttributes: + staticVolume: "true" + clusterID: cephfs_csi_ssd_ec_4_1 + fsName: cephfs + rootPath: /volumes/csi_ssd_ec_4_1/mediastore/a0152dac-a51b-4b95-ac5e-ecdd99bfe3f1 diff --git a/apps/base/arrstack/pvc-mediastore.yaml b/apps/base/arrstack/pvc-mediastore.yaml new file mode 100644 index 0000000..b6a4ebd --- /dev/null +++ b/apps/base/arrstack/pvc-mediastore.yaml @@ -0,0 +1,22 @@ +--- +# Whole media tree (/fafflix, /cheeztv, /nzbget) on one RWX filesystem, shared +# across the sonarr/radarr/nzbget pods. Statically bound to the +# arrstack-mediastore PV (the same CephFS subvolume fafflix and cheeztv mount). +# storageClassName "" + volumeName disables dynamic provisioning and binds the +# pre-created static PV. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: mediastore + namespace: arrstack + annotations: + k8up.io/backup: "false" +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Ti + storageClassName: "" + volumeName: arrstack-mediastore + volumeMode: Filesystem diff --git a/apps/base/arrstack/valkey/valkeycluster.yaml b/apps/base/arrstack/valkey/valkeycluster.yaml index 2c107df..87d207f 100644 --- a/apps/base/arrstack/valkey/valkeycluster.yaml +++ b/apps/base/arrstack/valkey/valkeycluster.yaml @@ -28,7 +28,7 @@ metadata: spec: shards: 1 replicas: 2 - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/valkey/valkey:9.0.0 + image: docker.io/valkey/valkey:9.0.0 exporter: enabled: false scheduling: diff --git a/apps/base/artifactapi/redis-deployment.yaml b/apps/base/artifactapi/redis-deployment.yaml index 4298e18..19f6e44 100644 --- a/apps/base/artifactapi/redis-deployment.yaml +++ b/apps/base/artifactapi/redis-deployment.yaml @@ -54,7 +54,7 @@ spec: successThreshold: 1 timeoutSeconds: 5 - name: metrics-exporter - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/oliver006/redis_exporter:v1.89.0 + image: docker.io/oliver006/redis_exporter:v1.89.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9121 diff --git a/apps/base/authentik/redis-deployment.yaml b/apps/base/authentik/redis-deployment.yaml index 5cc8552..c14838f 100644 --- a/apps/base/authentik/redis-deployment.yaml +++ b/apps/base/authentik/redis-deployment.yaml @@ -53,7 +53,7 @@ spec: - mountPath: /data name: redis-data - name: metrics-exporter - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/oliver006/redis_exporter:v1.89.0 + image: docker.io/oliver006/redis_exporter:v1.89.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9121 diff --git a/apps/base/cheeztv/kustomization.yaml b/apps/base/cheeztv/kustomization.yaml index d2454f3..3c953ff 100644 --- a/apps/base/cheeztv/kustomization.yaml +++ b/apps/base/cheeztv/kustomization.yaml @@ -15,8 +15,10 @@ resources: - pvc-transcode.yaml - pv-media-tv.yaml - pv-media-movies.yaml + - pv-mediastore.yaml - pvc-media-tv.yaml - pvc-media-movies.yaml + - pvc-mediastore.yaml - statefulset.yaml - plugin-configmap.yaml - pdb.yaml diff --git a/apps/base/cheeztv/pv-mediastore.yaml b/apps/base/cheeztv/pv-mediastore.yaml new file mode 100644 index 0000000..91ae2a5 --- /dev/null +++ b/apps/base/cheeztv/pv-mediastore.yaml @@ -0,0 +1,31 @@ +--- +# Static PV for the shared MEDIASTORE CephFS subvolume. Same rootPath as +# arrstack's mediastore PV so the arrs write and cheeztv reads the identical +# library tree (cheeztv scans /cheeztv/{tvseries,movies}); each namespace gets +# its own PV (unique name + volumeHandle) pinned by claimRef. +apiVersion: v1 +kind: PersistentVolume +metadata: + name: cheeztv-mediastore +spec: + capacity: + storage: 10Ti + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: "" + volumeMode: Filesystem + claimRef: + namespace: cheeztv + name: cheeztv-mediastore + csi: + driver: cephfs.csi.ceph.com + volumeHandle: cheeztv-mediastore-static + nodeStageSecretRef: + name: csi-cephfs-secret + namespace: csi-cephfs + volumeAttributes: + staticVolume: "true" + clusterID: cephfs_csi_ssd_ec_4_1 + fsName: cephfs + rootPath: /volumes/csi_ssd_ec_4_1/mediastore/a0152dac-a51b-4b95-ac5e-ecdd99bfe3f1 diff --git a/apps/base/cheeztv/pvc-mediastore.yaml b/apps/base/cheeztv/pvc-mediastore.yaml new file mode 100644 index 0000000..95e6fe2 --- /dev/null +++ b/apps/base/cheeztv/pvc-mediastore.yaml @@ -0,0 +1,24 @@ +--- +# Shared media tree, read-many across replicas. Statically bound to the +# cheeztv-mediastore PV (the CephFS subvolume also used by arrstack and +# fafflix). storageClassName "" + volumeName disables dynamic provisioning and +# binds the pre-created static PV. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: cheeztv-mediastore + namespace: cheeztv + annotations: + # Exclude from the cheeztv-config k8up Schedule (skipWithoutAnnotation is + # false cluster-wide, so unannotated PVCs are swept in). Only cheeztv-config + # is backed up; the media library is not restic-backup material. + k8up.io/backup: "false" +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Ti + storageClassName: "" + volumeName: cheeztv-mediastore + volumeMode: Filesystem diff --git a/apps/base/fafflix/kustomization.yaml b/apps/base/fafflix/kustomization.yaml index d2454f3..3c953ff 100644 --- a/apps/base/fafflix/kustomization.yaml +++ b/apps/base/fafflix/kustomization.yaml @@ -15,8 +15,10 @@ resources: - pvc-transcode.yaml - pv-media-tv.yaml - pv-media-movies.yaml + - pv-mediastore.yaml - pvc-media-tv.yaml - pvc-media-movies.yaml + - pvc-mediastore.yaml - statefulset.yaml - plugin-configmap.yaml - pdb.yaml diff --git a/apps/base/fafflix/pv-mediastore.yaml b/apps/base/fafflix/pv-mediastore.yaml new file mode 100644 index 0000000..717c2ca --- /dev/null +++ b/apps/base/fafflix/pv-mediastore.yaml @@ -0,0 +1,31 @@ +--- +# Static PV for the shared MEDIASTORE CephFS subvolume. Same rootPath as +# arrstack's mediastore PV so the arrs write and fafflix reads the identical +# library tree (fafflix scans /fafflix/{tvseries,movies}); each namespace gets +# its own PV (unique name + volumeHandle) pinned by claimRef. +apiVersion: v1 +kind: PersistentVolume +metadata: + name: fafflix-mediastore +spec: + capacity: + storage: 10Ti + accessModes: + - ReadWriteMany + persistentVolumeReclaimPolicy: Retain + storageClassName: "" + volumeMode: Filesystem + claimRef: + namespace: fafflix + name: fafflix-mediastore + csi: + driver: cephfs.csi.ceph.com + volumeHandle: fafflix-mediastore-static + nodeStageSecretRef: + name: csi-cephfs-secret + namespace: csi-cephfs + volumeAttributes: + staticVolume: "true" + clusterID: cephfs_csi_ssd_ec_4_1 + fsName: cephfs + rootPath: /volumes/csi_ssd_ec_4_1/mediastore/a0152dac-a51b-4b95-ac5e-ecdd99bfe3f1 diff --git a/apps/base/fafflix/pvc-mediastore.yaml b/apps/base/fafflix/pvc-mediastore.yaml new file mode 100644 index 0000000..ceb0011 --- /dev/null +++ b/apps/base/fafflix/pvc-mediastore.yaml @@ -0,0 +1,24 @@ +--- +# Shared media tree, read-many across replicas. Statically bound to the +# fafflix-mediastore PV (the CephFS subvolume also used by arrstack and +# cheeztv). storageClassName "" + volumeName disables dynamic provisioning and +# binds the pre-created static PV. +apiVersion: v1 +kind: PersistentVolumeClaim +metadata: + name: fafflix-mediastore + namespace: fafflix + annotations: + # Exclude from the fafflix-config k8up Schedule (skipWithoutAnnotation is + # false cluster-wide, so unannotated PVCs are swept in). Only fafflix-config + # is backed up; the media library is not restic-backup material. + k8up.io/backup: "false" +spec: + accessModes: + - ReadWriteMany + resources: + requests: + storage: 10Ti + storageClassName: "" + volumeName: fafflix-mediastore + volumeMode: Filesystem diff --git a/apps/base/gitea/valkey-deployment.yaml b/apps/base/gitea/valkey-deployment.yaml index 3015036..00163f7 100644 --- a/apps/base/gitea/valkey-deployment.yaml +++ b/apps/base/gitea/valkey-deployment.yaml @@ -83,7 +83,7 @@ spec: - mountPath: /data name: data - name: metrics-exporter - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/oliver006/redis_exporter:v1.89.0 + image: docker.io/oliver006/redis_exporter:v1.89.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9121 diff --git a/apps/base/litellm/redis-deployment.yaml b/apps/base/litellm/redis-deployment.yaml index d47597f..a5101c5 100644 --- a/apps/base/litellm/redis-deployment.yaml +++ b/apps/base/litellm/redis-deployment.yaml @@ -61,7 +61,7 @@ spec: mountPropagation: None name: data - name: metrics-exporter - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/oliver006/redis_exporter:v1.89.0 + image: docker.io/oliver006/redis_exporter:v1.89.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9121 diff --git a/apps/base/netbox/valkey-deployment.yaml b/apps/base/netbox/valkey-deployment.yaml index 9070964..a122b13 100644 --- a/apps/base/netbox/valkey-deployment.yaml +++ b/apps/base/netbox/valkey-deployment.yaml @@ -83,7 +83,7 @@ spec: - mountPath: /data name: data - name: metrics-exporter - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/oliver006/redis_exporter:v1.89.0 + image: docker.io/oliver006/redis_exporter:v1.89.0 imagePullPolicy: IfNotPresent ports: - containerPort: 9121 diff --git a/apps/base/watchstate/oauth2-proxy-deployment.yaml b/apps/base/watchstate/oauth2-proxy-deployment.yaml index 6c1d3ea..a4cca26 100644 --- a/apps/base/watchstate/oauth2-proxy-deployment.yaml +++ b/apps/base/watchstate/oauth2-proxy-deployment.yaml @@ -35,7 +35,7 @@ spec: # system roots with the internal CA so oauth2-proxy's OIDC HTTP client # trusts it. - name: combine-certs - image: artifactapi.k8s.syd1.au.unkin.net/dockerhub/library/alpine:3 + image: docker.io/library/alpine:3 imagePullPolicy: IfNotPresent command: - sh diff --git a/apps/base/woodpecker/kustomization.yaml b/apps/base/woodpecker/kustomization.yaml index d3c9360..6e0df22 100644 --- a/apps/base/woodpecker/kustomization.yaml +++ b/apps/base/woodpecker/kustomization.yaml @@ -11,6 +11,7 @@ resources: - serviceaccount_autobackup_operator_ci.yaml - serviceaccount_ghp.yaml - serviceaccount_kea_operator_ci.yaml + - serviceaccount_mediamark_ci.yaml - serviceaccount_plugin_docker_buildx.yaml - serviceaccount_jellyfin_ha_src.yaml - serviceaccount_terraform_artifactapi.yaml diff --git a/apps/base/woodpecker/serviceaccount_mediamark_ci.yaml b/apps/base/woodpecker/serviceaccount_mediamark_ci.yaml new file mode 100644 index 0000000..920b535 --- /dev/null +++ b/apps/base/woodpecker/serviceaccount_mediamark_ci.yaml @@ -0,0 +1,6 @@ +--- +apiVersion: v1 +kind: ServiceAccount +metadata: + name: mediamark-ci + namespace: woodpecker diff --git a/apps/overlays/au-syd1/clickhouse-system/values.yaml b/apps/overlays/au-syd1/clickhouse-system/values.yaml index 52b09b9..74b21a9 100644 --- a/apps/overlays/au-syd1/clickhouse-system/values.yaml +++ b/apps/overlays/au-syd1/clickhouse-system/values.yaml @@ -2,10 +2,9 @@ # resources in all namespaces (the logs cluster lives in the `logging` namespace). # CRDs are installed at runtime by the chart's crdHook Job. # -# All images are pulled through the artifactapi dockerhub remote (no direct -# upstream). Upstream official images are used; no Docker Hardened Image variant -# is adopted (DHI is subscription-gated and served from a private org namespace -# not reachable via the anonymous artifactapi dockerhub proxy). +# Upstream official images; no Docker Hardened Image variant is adopted (DHI is +# subscription-gated and served from a private org namespace not reachable via +# the anonymous artifactapi dockerhub proxy). # # Watch the logging namespace where the ClickHouseInstallation lives. The chart # default (watchNamespaces: []) makes the operator watch ONLY its own namespace @@ -14,7 +13,7 @@ watchNamespaces: - logging crdHook: image: - repository: artifactapi.k8s.syd1.au.unkin.net/dockerhub/bitnami/kubectl + repository: docker.io/bitnami/kubectl resources: requests: cpu: 50m @@ -25,7 +24,7 @@ crdHook: operator: image: - repository: artifactapi.k8s.syd1.au.unkin.net/dockerhub/altinity/clickhouse-operator + repository: docker.io/altinity/clickhouse-operator resources: requests: cpu: 100m @@ -36,7 +35,7 @@ operator: metrics: image: - repository: artifactapi.k8s.syd1.au.unkin.net/dockerhub/altinity/metrics-exporter + repository: docker.io/altinity/metrics-exporter resources: requests: cpu: 50m