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/grafana/grafana.yaml b/apps/base/grafana/grafana.yaml index 82b6a1f..1665d71 100644 --- a/apps/base/grafana/grafana.yaml +++ b/apps/base/grafana/grafana.yaml @@ -26,13 +26,6 @@ spec: secretKeyRef: name: oauth-credentials key: client_secret - # identity.unkin.net is served by the internal unkin.net CA, which - # the stock Grafana image doesn't trust. Mount the reflected - # vault-ca-cert and point generic_oauth's tls_client_ca at it. - volumeMounts: - - name: vault-ca-cert - mountPath: /etc/grafana/vault-ca - readOnly: true resources: requests: cpu: 100m @@ -40,13 +33,6 @@ spec: limits: cpu: "1" memory: 1Gi - volumes: - - name: vault-ca-cert - secret: - secretName: vault-ca-cert - items: - - key: ca.crt - path: ca.crt config: server: root_url: "https://grafana.k8s.syd1.au.unkin.net" @@ -71,9 +57,6 @@ spec: auth_url: "https://identity.unkin.net/application/o/authorize/" token_url: "https://identity.unkin.net/application/o/token/" api_url: "https://identity.unkin.net/application/o/userinfo/" - # Trust the internal unkin.net CA that signs identity.unkin.net's cert - # (mounted from the reflected vault-ca-cert Secret). - tls_client_ca: "/etc/grafana/vault-ca/ca.crt" # Authentik permission groups -> Grafana roles. akP-grafana-admin is granted # to akR-global-admin members (and direct members) via terraform-authentik. role_attribute_path: "contains(ak_groups[*], 'akP-grafana-admin') && 'Admin' || 'Viewer'" 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 diff --git a/apps/overlays/au-syd1/valkey-operator-system/values.yaml b/apps/overlays/au-syd1/valkey-operator-system/values.yaml index e1afdf9..cbbd383 100644 --- a/apps/overlays/au-syd1/valkey-operator-system/values.yaml +++ b/apps/overlays/au-syd1/valkey-operator-system/values.yaml @@ -1,5 +1,7 @@ +# rke2's `registries.yaml` rewrites upstream image names to the artifactapi +# mirror, so this manifest carries the canonical upstream registry. image: - registry: artifactapi.k8s.syd1.au.unkin.net/ghcr + registry: ghcr.io repository: valkey-io/valkey-operator tag: v0.5.0 diff --git a/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml b/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml index 8701640..fe2f258 100644 --- a/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml +++ b/clusters/au-syd1/bootstrap/argocd-cm-patch.yaml @@ -26,33 +26,8 @@ data: issuer: https://identity.unkin.net/application/o/argocd/ clientID: argocd clientSecret: $argocd-oidc:client_secret - # argocd-server does OIDC discovery/egress to identity.unkin.net over TLS, - # which is served by the internal `unkin.net` CA (not a public root), so the - # stock image trust store rejects it (x509: certificate signed by unknown - # authority). Anchor on the stable `unkin.net` root; identity presents its - # intermediate in the handshake, and the intermediate is periodically - # re-keyed, so pinning the root (not the intermediate) is rotation-proof. - rootCA: | - -----BEGIN CERTIFICATE----- - MIIDLzCCAhegAwIBAgIUIDADwsHIrQ8dfncpechBdIUCQdIwDQYJKoZIhvcNAQEL - BQAwFDESMBAGA1UEAxMJdW5raW4ubmV0MB4XDTI0MDQyNzExMjcwMloXDTM0MDQy - NTExMjczMlowFDESMBAGA1UEAxMJdW5raW4ubmV0MIIBIjANBgkqhkiG9w0BAQEF - AAOCAQ8AMIIBCgKCAQEA3ENPv7R7gCUJAg8Q4hB2LEZSdvbK155YbcrguLDDnu6m - 2fkJn8jYMMW3Z6/+Y04ouGwi6sKup8ggTb217sY+dC4IUZjotDPAhruxfXVQAh0v - Yr3RYoxVDrm4nRSFLo1RA4Qt+1KK299mHGQf9iAiwbsFp5mDrJT9uz15FE2uWmbK - 8/onMyJC4fnkMihVN6NIgTtjpHYNm5aAJwxoWldTopgF0ucb7X3XVPNbKAmd3Avd - lsOo6m751zSZ0HvJOxgRSy7lvPzMuUfCQsOcmI4O4+Z2FL4Y7p+T9DvWkciC7L3i - tBiK30fPfGKNpWaof1ONCcPQNjMwWcEFXqSiWUOXkwIDAQABo3kwdzAOBgNVHQ8B - Af8EBAMCAQYwDwYDVR0TAQH/BAUwAwEB/zAdBgNVHQ4EFgQUGpy/pj6F8e3gSOAp - r+6hAYQdOScwHwYDVR0jBBgwFoAUGpy/pj6F8e3gSOApr+6hAYQdOScwFAYDVR0R - BA0wC4IJdW5raW4ubmV0MA0GCSqGSIb3DQEBCwUAA4IBAQA5xocILzuvD+R2Iub1 - UnTdcVpgNcxJmESz0eX4UrkcBmddtuFINXvDTv5//XTFs78LsVVSf00xZ+2C62Xe - xRdCdluHN8VDCAKulP4XJY1BiZ7im0v+iMgPDKhq4OXb86WFYI/8J6uRm7oIAwj1 - zhhKxMimkzli+yHB8ipL15W7l68CMUgmOjFA+EG6sbfadFpQTX/h6TVj3FQPkU/p - UJEm2XjlGNAKGJrNRU47PM4vRDv5Joyowp9zv/pHFXvUJladaJupMKRJQVWQz1US - EXE67rawG79s3vm8dDolnbli/IhPHtjDRIprxAwrMs5tt9cY0xsRkFBZVcAOjrpb - 4gqd - -----END CERTIFICATE----- + # identity.unkin.net now serves the LetsEncrypt *.unkin.net wildcard, so the + # stock image trust store validates it; no rootCA pin. requestedScopes: - openid - profile