diff --git a/.env.example b/.env.example index 0910189..257d157 100644 --- a/.env.example +++ b/.env.example @@ -14,4 +14,14 @@ GITEA_RUNNER_TOKEN=your_token_here # Grafana admin password GRAFANA_ADMIN_PASSWORD=your_password_here +# Authentik secrets AUTHENTIK_PROXY_TOKEN=your_token_here +AUTHENTIK_GITEA_CLIENT_ID=your_client_id_here +AUTHENTIK_GITEA_CLIENT_SECRET=your_client_secret_here +AUTHENTIK_GRAFANA_CLIENT_ID=your_client_id_here +AUTHENTIK_GRAFANA_CLIENT_SECRET=your_client_secret_here + +# Gitea container registry credentials +REGISTRY_SERVER=your_registry_server_here +REGISTRY_USER=your_username_here +REGISTRY_PASSWORD=your_token_here \ No newline at end of file diff --git a/manifests/network/ddns-cronjob.yaml b/manifests/network/ddns-cronjob.yaml index 7cff9c9..c4b4a87 100644 --- a/manifests/network/ddns-cronjob.yaml +++ b/manifests/network/ddns-cronjob.yaml @@ -1,6 +1,6 @@ # 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. +# Description: CronJob that updates nik4nao.com and home.nik4nao.com DNS on Porkbun every 5 minutes. apiVersion: v1 kind: Namespace metadata: @@ -42,8 +42,6 @@ spec: 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"; } @@ -56,68 +54,74 @@ spec: fi echo "[$(timestamp)] WAN IP: $WAN_IP" - # Get current DNS records from Porkbun API + # Get all DNS records once (reused for all iterations) 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')" + for RECORD_NAME in "" "home"; do + RECORD_FQDN="${DOMAIN}" + [ -n "$RECORD_NAME" ] && RECORD_FQDN="${RECORD_NAME}.${DOMAIN}" + echo "[$(timestamp)] Processing: ${RECORD_FQDN}" - # 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)" + # Get all A record IDs for this record + RECORD_IDS="$(echo "$RECORDS" | jq -r \ + --arg fqdn "$RECORD_FQDN" \ + '.records[] | select(.type=="A" and .name==$fqdn) | .id')" - echo "[$(timestamp)] DNS IP: ${DNS_IP:-none}" + # 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)" - # 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}" \ + echo "[$(timestamp)] DNS IP: ${DNS_IP:-none}" + + # Delete all stale duplicate records + 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 + if [ "$RECORD_COUNT" -le 1 ] && [ "$WAN_IP" = "$DNS_IP" ]; then + echo "[$(timestamp)] No change, skipping." + continue + 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\"}" > /dev/null - echo "[$(timestamp)] Deleted record ID $ID" - done - DNS_IP="" - fi + -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 - # 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" + echo "[$(timestamp)] Response: $(echo "$RESP" | jq -c .)" + echo "$RESP" | grep -q '"status":"SUCCESS"' && \ + echo "[$(timestamp)] Update successful" || \ + echo "[$(timestamp)] Update failed" + done \ No newline at end of file diff --git a/manifests/portfolio/portfolio.yaml b/manifests/portfolio/portfolio.yaml new file mode 100644 index 0000000..5e4a6ee --- /dev/null +++ b/manifests/portfolio/portfolio.yaml @@ -0,0 +1,77 @@ +--- +apiVersion: v1 +kind: Namespace +metadata: + name: portfolio +--- +apiVersion: apps/v1 +kind: Deployment +metadata: + name: portfolio + namespace: portfolio +spec: + replicas: 1 + selector: + matchLabels: + app: portfolio + template: + metadata: + labels: + app: portfolio + spec: + imagePullSecrets: + - name: gitea-registry + containers: + - name: portfolio + image: gitea.nik4nao.com/nik/portfolio:latest + ports: + - containerPort: 80 + resources: + requests: + cpu: 50m + memory: 64Mi + limits: + cpu: 200m + memory: 128Mi +--- +apiVersion: v1 +kind: Service +metadata: + name: portfolio + namespace: portfolio +spec: + selector: + app: portfolio + ports: + - port: 80 + targetPort: 80 +--- +apiVersion: cert-manager.io/v1 +kind: Certificate +metadata: + name: portfolio-tls + namespace: portfolio +spec: + secretName: portfolio-tls + issuerRef: + name: letsencrypt-prod + kind: ClusterIssuer + dnsNames: + - nik4nao.com +--- +apiVersion: traefik.io/v1alpha1 +kind: IngressRoute +metadata: + name: portfolio + namespace: portfolio +spec: + entryPoints: + - websecure + routes: + - match: Host(`nik4nao.com`) + kind: Rule + services: + - name: portfolio + port: 80 + tls: + secretName: portfolio-tls \ No newline at end of file diff --git a/manifests/portfolio/registry-secret.sh b/manifests/portfolio/registry-secret.sh new file mode 100644 index 0000000..f8f9ba6 --- /dev/null +++ b/manifests/portfolio/registry-secret.sh @@ -0,0 +1,12 @@ +#!/bin/bash +set -euo pipefail + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +source "$SCRIPT_DIR/../../.env" + +kubectl create secret docker-registry gitea-registry \ + --namespace portfolio \ + --docker-server="$REGISTRY_SERVER" \ + --docker-username="$REGISTRY_USER" \ + --docker-password="$REGISTRY_PASSWORD" \ + --dry-run=client -o yaml | kubectl apply -f - \ No newline at end of file