mirror of
https://gitlab.kube.huskypup.net/Scooby/Homelabv4.git
synced 2026-08-21 05:26:49 +00:00
- ZONE_NAME was "kube.huskypup.net" in both the home-ip-ddns CronJob and the VPS failover watcher - that's a record, not a Cloudflare zone (the actual zone is the parent "huskypup.net"). Caused home-ip-ddns to fail every run (zone lookup returned zero results, curl -f exit 22) - confirmed live and fixed. - Added seccompProfile/non-root/dropped-capabilities securityContext to the three CronJobs added this session that were missing it (flagged by the cluster's "restricted" PodSecurity admission). Repointed the raft snapshot job's mc binary install from /usr/local/bin to /tmp so it still works running as non-root.
105 lines
3.8 KiB
YAML
105 lines
3.8 KiB
YAML
---
|
|
# Keeps home.kube.huskypup.net pointed at this cluster's current public IP in
|
|
# Cloudflare. This is the health-check target the VPS's DNS failover watcher
|
|
# (scripts/vps-dns-failover.sh) uses to decide whether home is reachable -
|
|
# it only needs to run while home is up, which is exactly when it can run.
|
|
#
|
|
# Reuses the cloudflare-token-secret already wired via ExternalSecret for
|
|
# cert-manager's DNS-01 solver (see secret-cf-token.yaml) - same zone, same
|
|
# token, no new secret plumbing.
|
|
apiVersion: v1
|
|
kind: ConfigMap
|
|
metadata:
|
|
name: home-ip-ddns-script
|
|
namespace: cert-manager
|
|
data:
|
|
update.sh: |
|
|
#!/bin/sh
|
|
set -eu
|
|
|
|
ZONE_NAME="huskypup.net" # Cloudflare zone is the parent domain - kube.huskypup.net is just a record within it, not its own zone
|
|
RECORD_NAME="home.kube.huskypup.net"
|
|
TOKEN="$(cat /etc/cf/cloudflare-token)"
|
|
|
|
CURRENT_IP="$(curl -sf https://cloudflare.com/cdn-cgi/trace | grep -o '^ip=.*' | cut -d= -f2)"
|
|
if [ -z "$CURRENT_IP" ]; then
|
|
echo "ERROR: could not determine public IP"
|
|
exit 1
|
|
fi
|
|
|
|
ZONE_ID="$(curl -sf -H "Authorization: Bearer ${TOKEN}" \
|
|
"https://api.cloudflare.com/client/v4/zones?name=${ZONE_NAME}" \
|
|
| jq -r '.result[0].id')"
|
|
|
|
RECORD_JSON="$(curl -sf -H "Authorization: Bearer ${TOKEN}" \
|
|
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${RECORD_NAME}&type=A")"
|
|
RECORD_ID="$(echo "$RECORD_JSON" | jq -r '.result[0].id // empty')"
|
|
EXISTING_IP="$(echo "$RECORD_JSON" | jq -r '.result[0].content // empty')"
|
|
|
|
if [ "$EXISTING_IP" = "$CURRENT_IP" ]; then
|
|
echo "home.kube.huskypup.net already up to date (${CURRENT_IP})"
|
|
exit 0
|
|
fi
|
|
|
|
BODY="{\"type\":\"A\",\"name\":\"${RECORD_NAME}\",\"content\":\"${CURRENT_IP}\",\"ttl\":120,\"proxied\":false}"
|
|
|
|
if [ -n "$RECORD_ID" ]; then
|
|
echo "Updating ${RECORD_NAME}: ${EXISTING_IP} -> ${CURRENT_IP}"
|
|
curl -sf -X PATCH -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
|
|
-d "$BODY" \
|
|
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" >/dev/null
|
|
else
|
|
echo "Creating ${RECORD_NAME} -> ${CURRENT_IP}"
|
|
curl -sf -X POST -H "Authorization: Bearer ${TOKEN}" -H "Content-Type: application/json" \
|
|
-d "$BODY" \
|
|
"https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" >/dev/null
|
|
fi
|
|
echo "done"
|
|
---
|
|
apiVersion: batch/v1
|
|
kind: CronJob
|
|
metadata:
|
|
name: home-ip-ddns
|
|
namespace: cert-manager
|
|
spec:
|
|
schedule: "*/10 * * * *" # every 10 minutes; cheap, and only matters while home is up
|
|
concurrencyPolicy: Forbid
|
|
successfulJobsHistoryLimit: 3
|
|
failedJobsHistoryLimit: 3
|
|
jobTemplate:
|
|
spec:
|
|
backoffLimit: 2
|
|
template:
|
|
spec:
|
|
restartPolicy: Never
|
|
securityContext:
|
|
runAsNonRoot: true
|
|
runAsUser: 65534
|
|
seccompProfile:
|
|
type: RuntimeDefault
|
|
containers:
|
|
- name: ddns-update
|
|
image: alpine/k8s:1.32.13 # already has curl + jq (see MEMORY.md kubectl image note)
|
|
command: ["/bin/sh", "/scripts/update.sh"]
|
|
securityContext:
|
|
allowPrivilegeEscalation: false
|
|
capabilities:
|
|
drop: ["ALL"]
|
|
volumeMounts:
|
|
- name: script
|
|
mountPath: /scripts
|
|
- name: cf-token
|
|
mountPath: /etc/cf
|
|
readOnly: true
|
|
volumes:
|
|
- name: script
|
|
configMap:
|
|
name: home-ip-ddns-script
|
|
defaultMode: 0755
|
|
- name: cf-token
|
|
secret:
|
|
secretName: cloudflare-token-secret
|
|
items:
|
|
- key: cloudflare-token
|
|
path: cloudflare-token
|