feat: cloudfare-ddns updater
This commit is contained in:
@@ -0,0 +1,16 @@
|
|||||||
|
apiVersion: argoproj.io/v1alpha1
|
||||||
|
kind: Application
|
||||||
|
metadata:
|
||||||
|
name: cloudfare-ddns
|
||||||
|
namespace: argocd
|
||||||
|
spec:
|
||||||
|
project: default
|
||||||
|
source:
|
||||||
|
repoURL: https://gitea.zb-kw.duckdns.org/willemjan/cluster.git
|
||||||
|
targetRevision: main
|
||||||
|
path: services/cloudfare-ddns
|
||||||
|
destination:
|
||||||
|
server: https://kubernetes.default.svc
|
||||||
|
namespace: cloudfare-ddns
|
||||||
|
syncPolicy:
|
||||||
|
automated: {prune: true, selfHeal: true}
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-ddns-config
|
||||||
|
namespace: cloudflare-ddns
|
||||||
|
data:
|
||||||
|
# Comma-separated list of domains to update
|
||||||
|
# Format: subdomain.domain.tld,subdomain2.domain.tld
|
||||||
|
DOMAINS: "*.labzand.com"
|
||||||
|
ZONE_ID: "6093605ad5a8db13e9c9d9faad240ca6"
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
piVersion: batch/v1
|
||||||
|
kind: CronJob
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-ddns
|
||||||
|
namespace: cloudflare-ddns
|
||||||
|
spec:
|
||||||
|
# Run every hour at the top of the hour
|
||||||
|
schedule: "0 * * * *"
|
||||||
|
successfulJobsHistoryLimit: 3
|
||||||
|
failedJobsHistoryLimit: 3
|
||||||
|
concurrencyPolicy: Forbid
|
||||||
|
jobTemplate:
|
||||||
|
spec:
|
||||||
|
template:
|
||||||
|
metadata:
|
||||||
|
labels:
|
||||||
|
app: cloudflare-ddns
|
||||||
|
spec:
|
||||||
|
restartPolicy: OnFailure
|
||||||
|
containers:
|
||||||
|
- name: cloudflare-ddns
|
||||||
|
image: curlimages/curl:latest
|
||||||
|
command:
|
||||||
|
- /bin/sh
|
||||||
|
- /scripts/update-dns.sh
|
||||||
|
env:
|
||||||
|
- name: DOMAINS
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: cloudflare-ddns-config
|
||||||
|
key: DOMAINS
|
||||||
|
- name: ZONE_ID
|
||||||
|
valueFrom:
|
||||||
|
configMapKeyRef:
|
||||||
|
name: cloudflare-ddns-config
|
||||||
|
key: ZONE_ID
|
||||||
|
- name: API_TOKEN
|
||||||
|
valueFrom:
|
||||||
|
secretKeyRef:
|
||||||
|
name: cloudflare-ddns-secret
|
||||||
|
key: API_TOKEN
|
||||||
|
volumeMounts:
|
||||||
|
- name: scripts
|
||||||
|
mountPath: /scripts
|
||||||
|
readOnly: true
|
||||||
|
volumes:
|
||||||
|
- name: scripts
|
||||||
|
configMap:
|
||||||
|
name: cloudflare-ddns-script
|
||||||
|
defaultMode: 0755
|
||||||
@@ -0,0 +1,11 @@
|
|||||||
|
apiVersion: kustomize.config.k8s.io/v1beta1
|
||||||
|
kind: Kustomization
|
||||||
|
|
||||||
|
namespace: cloudflare-ddns
|
||||||
|
|
||||||
|
resources:
|
||||||
|
- namespace.yaml
|
||||||
|
- configmap.yaml
|
||||||
|
- script-configmap.yaml
|
||||||
|
- secret.yaml
|
||||||
|
- cronjob.yaml
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: Namespace
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-ddns
|
||||||
|
labels:
|
||||||
|
name: cloudflare-ddns
|
||||||
@@ -0,0 +1,127 @@
|
|||||||
|
apiVersion: v1
|
||||||
|
kind: ConfigMap
|
||||||
|
metadata:
|
||||||
|
name: cloudflare-ddns-script
|
||||||
|
namespace: cloudflare-ddns
|
||||||
|
data:
|
||||||
|
update-dns.sh: |
|
||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# Colors for output
|
||||||
|
RED='\033[0;31m'
|
||||||
|
GREEN='\033[0;32m'
|
||||||
|
YELLOW='\033[1;33m'
|
||||||
|
NC='\033[0m' # No Color
|
||||||
|
|
||||||
|
echo "Starting Cloudflare DDNS update..."
|
||||||
|
echo "Timestamp: $(date)"
|
||||||
|
|
||||||
|
# Check required environment variables
|
||||||
|
if [ -z "$API_TOKEN" ]; then
|
||||||
|
echo "${RED}ERROR: API_TOKEN is not set${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$ZONE_ID" ]; then
|
||||||
|
echo "${RED}ERROR: ZONE_ID is not set${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$DOMAINS" ]; then
|
||||||
|
echo "${RED}ERROR: DOMAINS is not set${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Get current public IP address
|
||||||
|
echo "Fetching current public IP address..."
|
||||||
|
PUBLIC_IP=$(curl -s https://api.ipify.org)
|
||||||
|
|
||||||
|
if [ -z "$PUBLIC_IP" ]; then
|
||||||
|
echo "First attempt failed, trying alternative service..."
|
||||||
|
PUBLIC_IP=$(curl -s https://ifconfig.me)
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ -z "$PUBLIC_IP" ]; then
|
||||||
|
echo "${RED}ERROR: Could not determine public IP address${NC}"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${GREEN}Current public IP: $PUBLIC_IP${NC}"
|
||||||
|
|
||||||
|
# Process each domain
|
||||||
|
echo "$DOMAINS" | tr ',' '\n' | while IFS= read -r DOMAIN; do
|
||||||
|
# Trim whitespace
|
||||||
|
DOMAIN=$(echo "$DOMAIN" | xargs)
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Processing domain: $DOMAIN"
|
||||||
|
|
||||||
|
# Get DNS record ID for the domain
|
||||||
|
echo "Fetching DNS record for $DOMAIN..."
|
||||||
|
RECORD_RESPONSE=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records?name=$DOMAIN&type=A" \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json")
|
||||||
|
|
||||||
|
# Check if the request was successful
|
||||||
|
SUCCESS=$(echo "$RECORD_RESPONSE" | grep -o '"success":[^,]*' | cut -d':' -f2)
|
||||||
|
|
||||||
|
if [ "$SUCCESS" != "true" ]; then
|
||||||
|
echo "${RED}ERROR: Failed to fetch DNS record for $DOMAIN${NC}"
|
||||||
|
echo "$RECORD_RESPONSE"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Extract record ID and current IP
|
||||||
|
RECORD_ID=$(echo "$RECORD_RESPONSE" | grep -o '"id":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||||
|
CURRENT_IP=$(echo "$RECORD_RESPONSE" | grep -o '"content":"[^"]*"' | head -1 | cut -d'"' -f4)
|
||||||
|
|
||||||
|
if [ -z "$RECORD_ID" ]; then
|
||||||
|
echo "${YELLOW}WARNING: DNS record not found for $DOMAIN. Creating new record...${NC}"
|
||||||
|
|
||||||
|
# Create new DNS record
|
||||||
|
CREATE_RESPONSE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records" \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$PUBLIC_IP\",\"ttl\":120,\"proxied\":false}")
|
||||||
|
|
||||||
|
CREATE_SUCCESS=$(echo "$CREATE_RESPONSE" | grep -o '"success":[^,]*' | cut -d':' -f2)
|
||||||
|
|
||||||
|
if [ "$CREATE_SUCCESS" = "true" ]; then
|
||||||
|
echo "${GREEN}Successfully created DNS record for $DOMAIN with IP $PUBLIC_IP${NC}"
|
||||||
|
else
|
||||||
|
echo "${RED}ERROR: Failed to create DNS record for $DOMAIN${NC}"
|
||||||
|
echo "$CREATE_RESPONSE"
|
||||||
|
fi
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "Current DNS IP: $CURRENT_IP"
|
||||||
|
|
||||||
|
# Check if IP needs to be updated
|
||||||
|
if [ "$CURRENT_IP" = "$PUBLIC_IP" ]; then
|
||||||
|
echo "${GREEN}IP address is already up to date for $DOMAIN${NC}"
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "${YELLOW}Updating DNS record for $DOMAIN from $CURRENT_IP to $PUBLIC_IP${NC}"
|
||||||
|
|
||||||
|
# Update DNS record
|
||||||
|
UPDATE_RESPONSE=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/dns_records/$RECORD_ID" \
|
||||||
|
-H "Authorization: Bearer $API_TOKEN" \
|
||||||
|
-H "Content-Type: application/json" \
|
||||||
|
--data "{\"type\":\"A\",\"name\":\"$DOMAIN\",\"content\":\"$PUBLIC_IP\",\"ttl\":120,\"proxied\":false}")
|
||||||
|
|
||||||
|
UPDATE_SUCCESS=$(echo "$UPDATE_RESPONSE" | grep -o '"success":[^,]*' | cut -d':' -f2)
|
||||||
|
|
||||||
|
if [ "$UPDATE_SUCCESS" = "true" ]; then
|
||||||
|
echo "${GREEN}Successfully updated DNS record for $DOMAIN to $PUBLIC_IP${NC}"
|
||||||
|
else
|
||||||
|
echo "${RED}ERROR: Failed to update DNS record for $DOMAIN${NC}"
|
||||||
|
echo "$UPDATE_RESPONSE"
|
||||||
|
fi
|
||||||
|
done
|
||||||
|
|
||||||
|
echo ""
|
||||||
|
echo "Cloudflare DDNS update completed at $(date)"
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
"kind": "SealedSecret",
|
||||||
|
"apiVersion": "bitnami.com/v1alpha1",
|
||||||
|
"metadata": {
|
||||||
|
"name": "cloudfare-ddns-secret",
|
||||||
|
"namespace": "cloudfare-ddns"
|
||||||
|
},
|
||||||
|
"spec": {
|
||||||
|
"template": {
|
||||||
|
"metadata": {
|
||||||
|
"name": "cloudfare-ddns-secret",
|
||||||
|
"namespace": "cloudfare-ddns"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"encryptedData": {
|
||||||
|
"API_TOKEN": "AgAHCYYKi6dkQ5IltIQ0nCSyO5pbTKWNWhyqfNYEjSQYLKbCq2KZCqB3AbFgnwM6kIgtnJ7dYoqZtDFYp+WohTdxi6BnGVzMNbmWQ5luugJ88QxlmNMcoYv4ooHgCbD20riBFMXiDxALmLswJsNA3CuJBWpG8N3Ac51zyqccZAbyDzTq+0M5ltv5AL5sPVmKSClK96rt42p1KZVeprZlSoeJ9ZJnBgNMOTtEBF8xGYSLxxoaTOJZTCMtCzQp1975q93qUY/OLuPUKdgccYMEPESo9md+KpvkHQ87jtDC0sdcg7bYmHIoQgeNOzE5Y18wBQSSWkuARkKz1p6+uJo+3OvmcRCf+Gi5n8vmedrX3xGzKYXHZRFEPkbLFmkI/cT8hu914hctUd7YhS5UU5qqMOLSecKATLj1U4bxIvysw7aDLTB5F7G5q0um4TczaKx5XKHxw5xB5ldk7gOKrzztnKXNd3wK4SPYrCI0RKPSvESOZFBlU76hU8ZColkKE5H4dE9CtTxvKqwaje5qzoup2+SqtlQ4EytGZ0+ww1rKJCLR46vzgvSItB40q6pyDAUaLkLSw7iBLcma9QXelf1RX8Dynk76dajB+TXJjMWYDuLJMkHaB5GgQCH8R9Y4WtTA64WTlg8DPDhEOnFNwBsCdn3jsMjuguTo4SoCe9wK+eSETOrt/t8Aokj0hnvdHnHFBMlutvvA1c6Zy/PSpRhG6g325yEgMnMcyuy6pVKy3PqCe3But+yQ51Yh3wAdo6p+oAsKeFEBPA=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user