Add DDNS CronJob and secret creation script for Porkbun integration

This commit is contained in:
Nik Afiq 2026-03-06 20:32:19 +09:00
parent 4129089d09
commit b2b5437fd2
3 changed files with 119 additions and 1 deletions

View File

@ -1,6 +1,6 @@
# Porkbun API credentials # Porkbun API credentials
PORKBUN_API_KEY=pk1_your_key_here PORKBUN_API_KEY=pk1_your_key_here
PORKBUN_SECRET_API_KEY=sk1_your_key_here PORKBUN_SECRET_KEY=sk1_your_key_here
# K3s node token for agent join # K3s node token for agent join
K3S_NODE_TOKEN=your_token_here K3S_NODE_TOKEN=your_token_here

View File

@ -0,0 +1,97 @@
# DDNS CronJob — updates home.nik4nao.com on Porkbun every 5 minutes
# Requires: porkbun-ddns secret in ddns namespace
# Apply: kubectl apply -f manifests/ddns-cronjob.yaml
apiVersion: v1
kind: Namespace
metadata:
name: ddns
---
apiVersion: batch/v1
kind: CronJob
metadata:
name: porkbun-ddns
namespace: ddns
spec:
schedule: "*/5 * * * *"
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 bind-tools -q
DOMAIN="nik4nao.com"
RECORD_NAME="home"
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 record via dig
DNS_IP="$(dig +short ${RECORD_NAME}.${DOMAIN} @1.1.1.1 | head -1)"
echo "[$(timestamp)] DNS IP: $DNS_IP"
# Skip if unchanged
if [ "$WAN_IP" = "$DNS_IP" ]; then
echo "[$(timestamp)] No change, skipping."
exit 0
fi
echo "[$(timestamp)] IP changed $DNS_IP -> $WAN_IP, updating..."
# Retrieve existing records to get record ID
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\"}")"
RECORD_ID="$(echo "$RECORDS" | jq -r \
--arg name "$RECORD_NAME" \
'.records[] | select(.type=="A" and .name==$name) | .id' | head -1)"
if [ -z "$RECORD_ID" ]; then
# Create new record
echo "[$(timestamp)] No existing record, creating..."
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 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"

21
manifests/ddns-secret.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/bash
# Usage: bash manifests/ddns-secret.sh
set -e
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ENV_FILE="$SCRIPT_DIR/../.env"
if [ ! -f "$ENV_FILE" ]; then
echo "Error: .env file not found"
exit 1
fi
source "$ENV_FILE"
kubectl create secret generic porkbun-ddns \
--namespace ddns \
--from-literal=api-key="$PORKBUN_API_KEY" \
--from-literal=secret-api-key="$PORKBUN_SECRET_KEY" \
--dry-run=client -o yaml | kubectl apply -f -
echo "Secret applied"