homelab/manifests/network/ddns-cronjob.yaml
Nik Afiq 83f46c9748 feat(gitea): add backup CronJob with RBAC and NFS support
feat(gitea): create PersistentVolume and PersistentVolumeClaim for Gitea

feat(gitea): add script to create Gitea runner registration token secret

feat(gitea): deploy Gitea Actions runner with Docker socket access

feat(media): deploy JDownloader with Ingress configuration

feat(media): set up Jellyfin media server with NFS and Ingress

feat(media): configure qBittorrent deployment with Ingress

feat(monitoring): add Grafana Loki datasource ConfigMap

feat(monitoring): create Grafana admin credentials secret

feat(monitoring): define PersistentVolumes for monitoring stack

feat(network): implement DDNS CronJob for Porkbun DNS updates

feat(network): create secret for Porkbun DDNS API credentials

feat(network): set up Glances service and Ingress for Debian node

fix(network): patch Pi-hole DNS services with external IPs

feat(network): configure Traefik dashboard Ingress with Authentik auth

feat(network): set up Watch Party service and Ingress for Mac Mini

refactor(values): update Helm values files for various services
2026-03-12 21:56:32 +09:00

124 lines
5.3 KiB
YAML

# Apply: kubectl apply -f manifests/network/ddns-cronjob.yaml
# Delete: kubectl delete -f manifests/network/ddns-cronjob.yaml
# Description: CronJob that updates home.nik4nao.com DNS on Porkbun every 5 minutes.
apiVersion: v1
kind: Namespace
metadata:
name: ddns
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: porkbun-ddns
namespace: ddns
spec:
schedule: "*/5 * * * *"
successfulJobsHistoryLimit: 3
failedJobsHistoryLimit: 1
jobTemplate:
spec:
template:
spec:
restartPolicy: OnFailure
containers:
- name: ddns
image: alpine:latest
env:
- name: PORKBUN_API_KEY
valueFrom:
secretKeyRef:
name: porkbun-ddns
key: api-key
- name: PORKBUN_SECRET_KEY
valueFrom:
secretKeyRef:
name: porkbun-ddns
key: secret-api-key
command:
- /bin/sh
- -c
- |
set -euo pipefail
apk add --no-cache curl jq -q
DOMAIN="nik4nao.com"
RECORD_NAME="home"
RECORD_FQDN="${RECORD_NAME}.${DOMAIN}"
TTL=300
timestamp() { date +"%Y-%m-%d %H:%M:%S%z"; }
# Get current WAN IP
WAN_IP="$(curl -sf https://api.ipify.org)"
if [ -z "$WAN_IP" ]; then
echo "[$(timestamp)] ERROR: Could not detect WAN IP"
exit 1
fi
echo "[$(timestamp)] WAN IP: $WAN_IP"
# Get current DNS records from Porkbun API
RECORDS="$(curl -sf -X POST \
"https://api.porkbun.com/api/json/v3/dns/retrieve/${DOMAIN}" \
-H 'Content-Type: application/json' \
-d "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_KEY\"}")"
# Get all A record IDs for this subdomain
RECORD_IDS="$(echo "$RECORDS" | jq -r \
--arg fqdn "$RECORD_FQDN" \
'.records[] | select(.type=="A" and .name==$fqdn) | .id')"
# Get the current DNS IP from the first record
DNS_IP="$(echo "$RECORDS" | jq -r \
--arg fqdn "$RECORD_FQDN" \
'.records[] | select(.type=="A" and .name==$fqdn) | .content' | head -1)"
echo "[$(timestamp)] DNS IP: ${DNS_IP:-none}"
# Delete all stale duplicate records (keep none — we'll create/update cleanly)
RECORD_COUNT="$(echo "$RECORD_IDS" | grep -c . || true)"
if [ "$RECORD_COUNT" -gt 1 ]; then
echo "[$(timestamp)] Found $RECORD_COUNT duplicate records, deleting all..."
for ID in $RECORD_IDS; do
curl -sf -X POST \
"https://api.porkbun.com/api/json/v3/dns/delete/${DOMAIN}/${ID}" \
-H 'Content-Type: application/json' \
-d "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_KEY\"}" > /dev/null
echo "[$(timestamp)] Deleted record ID $ID"
done
DNS_IP=""
fi
# Get the single remaining record ID (if any)
RECORD_ID="$(echo "$RECORDS" | jq -r \
--arg fqdn "$RECORD_FQDN" \
'.records[] | select(.type=="A" and .name==$fqdn) | .id' | head -1)"
# Skip if already correct (single record, correct IP)
if [ "$RECORD_COUNT" -le 1 ] && [ "$WAN_IP" = "$DNS_IP" ]; then
echo "[$(timestamp)] No change, skipping."
exit 0
fi
echo "[$(timestamp)] IP changed ${DNS_IP:-none} -> $WAN_IP, updating..."
if [ -z "$RECORD_ID" ] || [ "$RECORD_COUNT" -gt 1 ]; then
# Create fresh record
echo "[$(timestamp)] Creating new record..."
RESP="$(curl -sf -X POST \
"https://api.porkbun.com/api/json/v3/dns/create/${DOMAIN}" \
-H 'Content-Type: application/json' \
-d "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_KEY\",\"type\":\"A\",\"name\":\"$RECORD_NAME\",\"content\":\"$WAN_IP\",\"ttl\":$TTL}")"
else
# Update existing single record
echo "[$(timestamp)] Updating record ID $RECORD_ID..."
RESP="$(curl -sf -X POST \
"https://api.porkbun.com/api/json/v3/dns/edit/${DOMAIN}/${RECORD_ID}" \
-H 'Content-Type: application/json' \
-d "{\"apikey\":\"$PORKBUN_API_KEY\",\"secretapikey\":\"$PORKBUN_SECRET_KEY\",\"type\":\"A\",\"name\":\"$RECORD_NAME\",\"content\":\"$WAN_IP\",\"ttl\":$TTL}")"
fi
echo "[$(timestamp)] Response: $(echo "$RESP" | jq -c .)"
echo "$RESP" | grep -q '"status":"SUCCESS"' && \
echo "[$(timestamp)] Update successful" || \
echo "[$(timestamp)] Update failed"