feat(velero): schedules + PVC exclude annotations (DEV-573)

- velero/schedules/: cluster-all @ 03:00 (30d TTL, manifests only),
  per-namespace <ns>-manifests @ 03:15+n min (30 in-scope namespaces,
  30d TTL, no fs backup), and per-namespace <ns>-data @ 03:45+n min
  for the whitelist (pocket-id, vaultwarden, vikunja, passbolt;
  14d TTL, defaultVolumesToFsBackup=true).
- All schedules exclude velero, kube-system, kube-node-lease,
  kube-public so the Kopia password Secret never lands in S3.
- apps/app-velero-schedules.yaml: sibling Argo app syncing that
  directory into namespace velero with prune+selfHeal.
- opencloud, harbor(registry+trivy): pod-template annotation
  backup.velero.io/backup-volumes-excludes as a safety net so blob-
  heavy PVCs are never fs-backed-up even under a manual defaultVolumes
  run. nextcloud/monitoring workloads are not Argo-tracked yet — they
  were patched live in the same commit but need a follow-up to source-
  control them.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
This commit is contained in:
CTO (Paperclip Agent) 2026-09-12 17:35:49 +00:00
parent 9b8cfebbd5
commit ec3e9624b3
6 changed files with 943 additions and 0 deletions

View file

@ -0,0 +1,23 @@
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: velero-schedules
namespace: argocd
spec:
project: default
source:
repoURL: git@forgejo.forgejo.svc.cluster.local:basicstack/stack.basicstack.de.git
targetRevision: main
path: velero/schedules
directory:
recurse: false
include: '*.yaml'
destination:
server: https://kubernetes.default.svc
namespace: velero
syncPolicy:
automated:
prune: true
selfHeal: true
syncOptions:
- ServerSideApply=true

View file

@ -95,6 +95,9 @@ harbor:
cpu: 500m
registry:
# Skip Kopia fs-backup of the registry blob PVC (DEV-573 safety net).
podAnnotations:
backup.velero.io/backup-volumes-excludes: registry-data
registry:
resources:
requests:
@ -106,6 +109,9 @@ harbor:
trivy:
enabled: true
# Skip Kopia fs-backup of the trivy scan cache PVC (DEV-573 safety net).
podAnnotations:
backup.velero.io/backup-volumes-excludes: data
resources:
requests:
memory: 512Mi

View file

@ -51,6 +51,12 @@ spec:
metadata:
labels:
app: opencloud
annotations:
# Skip Kopia fs-backup of the 100 GiB opencloud object-store PVC — this
# blob store is out of scope for the DEV-573 data schedules; the
# exclusion is a safety net so an accidental defaultVolumesToFsBackup
# run never streams it into the Kopia repo.
backup.velero.io/backup-volumes-excludes: opencloud-data
spec:
securityContext:
fsGroup: 1000

View file

@ -0,0 +1,24 @@
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: cluster-all
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: cluster
spec:
schedule: "0 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- '*'
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: true
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default

View file

@ -0,0 +1,780 @@
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: argocd-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: argocd
spec:
schedule: "15 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- argocd
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: basicstack-web-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: basicstack-web
spec:
schedule: "16 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- basicstack-web
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: bookstack-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: bookstack
spec:
schedule: "17 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- bookstack
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: cert-manager-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: cert-manager
spec:
schedule: "18 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- cert-manager
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: container-registry-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: container-registry
spec:
schedule: "19 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- container-registry
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: directus-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: directus
spec:
schedule: "20 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- directus
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: dozzle-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: dozzle
spec:
schedule: "21 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- dozzle
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: forgejo-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: forgejo
spec:
schedule: "22 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- forgejo
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: grist-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: grist
spec:
schedule: "23 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- grist
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: harbor-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: harbor
spec:
schedule: "24 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- harbor
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: headlamp-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: headlamp
spec:
schedule: "25 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- headlamp
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: kaneo-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: kaneo
spec:
schedule: "26 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- kaneo
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: keycloak-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: keycloak
spec:
schedule: "27 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- keycloak
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: monitoring-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: monitoring
spec:
schedule: "28 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- monitoring
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: nextcloud-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: nextcloud
spec:
schedule: "29 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- nextcloud
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: observability-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: observability
spec:
schedule: "30 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- observability
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: opencloud-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: opencloud
spec:
schedule: "31 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- opencloud
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: openwebui-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: openwebui
spec:
schedule: "32 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- openwebui
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: outline-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: outline
spec:
schedule: "33 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- outline
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: pangolin-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: pangolin
spec:
schedule: "34 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- pangolin
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: paperclip-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: paperclip
spec:
schedule: "35 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- paperclip
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: paperclip-system-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: paperclip-system
spec:
schedule: "36 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- paperclip-system
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: passbolt-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: passbolt
spec:
schedule: "37 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- passbolt
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: planka-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: planka
spec:
schedule: "38 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- planka
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: platform-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: platform
spec:
schedule: "39 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- platform
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: pocket-id-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: pocket-id
spec:
schedule: "40 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- pocket-id
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: reloader-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: reloader
spec:
schedule: "41 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- reloader
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: stalwart-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: stalwart
spec:
schedule: "42 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- stalwart
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: vaultwarden-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: vaultwarden
spec:
schedule: "43 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- vaultwarden
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: vikunja-manifests
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-manifests
velero.basicstack.de/namespace: vikunja
spec:
schedule: "44 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 720h0m0s
includedNamespaces:
- vikunja
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: false
storageLocation: default

View file

@ -0,0 +1,104 @@
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: pocket-id-data
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-data
velero.basicstack.de/namespace: pocket-id
spec:
schedule: "45 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 336h0m0s
includedNamespaces:
- pocket-id
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: true
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: vaultwarden-data
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-data
velero.basicstack.de/namespace: vaultwarden
spec:
schedule: "47 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 336h0m0s
includedNamespaces:
- vaultwarden
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: true
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: vikunja-data
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-data
velero.basicstack.de/namespace: vikunja
spec:
schedule: "49 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 336h0m0s
includedNamespaces:
- vikunja
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: true
storageLocation: default
---
apiVersion: velero.io/v1
kind: Schedule
metadata:
name: passbolt-data
namespace: velero
labels:
app.kubernetes.io/part-of: velero-schedules
tier: namespace-data
velero.basicstack.de/namespace: passbolt
spec:
schedule: "51 3 * * *"
useOwnerReferencesInBackup: false
template:
ttl: 336h0m0s
includedNamespaces:
- passbolt
excludedNamespaces:
- velero
- kube-system
- kube-node-lease
- kube-public
includeClusterResources: false
snapshotVolumes: false
defaultVolumesToFsBackup: true
storageLocation: default