stack.basicstack.de/velero/restore-drill/20-restore-drill-cronjob.yaml
CTO 765962c936 fix(velero-drill): hostAliases to reach paperclip.home webhook from cluster (DEV-579)
Public DNS for paperclip.home.imicros.de returns the LAN IP 10.0.0.2, so the
drill's webhook POST was landing with HTTP 000 from Hetzner. The home reverse
proxy at 46.225.155.185 already serves that vhost publicly, so pinning the
hostname to the home public IP in the CronJob's hostAliases lets the webhook
fire the Paperclip routine without any home-network or SealedSecret changes.

Verified end-to-end: bearer POST via --resolve returns HTTP 202 with
status=issue_created (run issue b07fc035 created under DEV-578).

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-09-12 18:15:51 +00:00

108 lines
3.8 KiB
YAML

apiVersion: batch/v1
kind: CronJob
metadata:
name: velero-restore-drill
namespace: velero
labels:
app.kubernetes.io/part-of: velero-restore-drill
spec:
# Monthly at 04:00 UTC on the 1st (per DEV-575 acceptance).
schedule: "0 4 1 * *"
timeZone: "UTC"
concurrencyPolicy: Forbid
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 3
startingDeadlineSeconds: 3600
jobTemplate:
metadata:
labels:
app.kubernetes.io/part-of: velero-restore-drill
spec:
backoffLimit: 0
activeDeadlineSeconds: 3600
ttlSecondsAfterFinished: 604800 # keep completed jobs for 7d for debug
template:
metadata:
labels:
app.kubernetes.io/part-of: velero-restore-drill
spec:
restartPolicy: Never
serviceAccountName: restore-drill
# DEV-579: public DNS for paperclip.home.imicros.de returns the LAN IP
# 10.0.0.2 (split-brain), which is unroutable from the cluster. The
# home reverse proxy at home.imicros.de (46.225.155.185) already
# serves the paperclip.home.imicros.de vhost publicly, so overriding
# the hostname to that public IP lets the webhook reach the routine.
# If the home ISP rotates the public IP, refresh this entry from
# `dig +short home.imicros.de` (DDNS record).
hostAliases:
- ip: "46.225.155.185"
hostnames:
- "paperclip.home.imicros.de"
securityContext:
runAsNonRoot: true
runAsUser: 65532
runAsGroup: 65532
fsGroup: 65532
seccompProfile:
type: RuntimeDefault
containers:
- name: drill
image: alpine/k8s:1.30.5
imagePullPolicy: IfNotPresent
command: ["/bin/bash", "/scripts/drill.sh"]
env:
- name: DRILL_SOURCE_NS
value: "openwebui"
- name: DRILL_SCHEDULE_NAME
value: "openwebui-manifests"
- name: DRILL_RESULT_NS
value: "velero"
- name: DRILL_RESULT_CM
value: "velero-restore-drill-last-result"
- name: DRILL_RESTORE_TIMEOUT
value: "1800"
- name: DRILL_NS_DELETE_TIMEOUT
value: "600"
# Optional Paperclip webhook (mounted from SealedSecret if wired).
- name: PAPERCLIP_WEBHOOK_URL
valueFrom:
secretKeyRef:
name: velero-restore-drill-webhook
key: webhookUrl
optional: true
- name: PAPERCLIP_WEBHOOK_SECRET
valueFrom:
secretKeyRef:
name: velero-restore-drill-webhook
key: webhookSecret
optional: true
resources:
requests:
cpu: 50m
memory: 128Mi
limits:
cpu: 500m
memory: 512Mi
securityContext:
allowPrivilegeEscalation: false
readOnlyRootFilesystem: true
capabilities:
drop: ["ALL"]
volumeMounts:
- name: script
mountPath: /scripts
readOnly: true
- name: tmp
mountPath: /tmp
- name: kube
mountPath: /.kube
volumes:
- name: script
configMap:
name: restore-drill-script
defaultMode: 0555
- name: tmp
emptyDir: {}
- name: kube
emptyDir: {}