docs: Ledger Live integration, contract deploy learnings, NEXT_STEPS updates
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
Some checks failed
Deploy to Phoenix / deploy (push) Has been cancelled
- ADD_CHAIN138_TO_LEDGER_LIVE: Ledger form done; public code review repo bis-innovations/LedgerLive; init/push commands - CONTRACT_DEPLOYMENT_RUNBOOK: Chain 138 gas price 1 gwei, 36-addr check, TransactionMirror workaround - CONTRACT_*: AddressMapper, MirrorManager deployed 2026-02-12; 36-address on-chain check - NEXT_STEPS_FOR_YOU: Ledger done; steps completable now (no LAN); run-completable-tasks-from-anywhere - MASTER_INDEX, OPERATOR_OPTIONAL, SMART_CONTRACTS_INVENTORY_SIMPLE: updates - LEDGER_BLOCKCHAIN_INTEGRATION_COMPLETE: bis-innovations/LedgerLive reference Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
70
scripts/cloudflare/add-explorer-csp-transform-rule.sh
Normal file
70
scripts/cloudflare/add-explorer-csp-transform-rule.sh
Normal file
@@ -0,0 +1,70 @@
|
||||
#!/usr/bin/env bash
|
||||
# Add Cloudflare Transform Rule to set Content-Security-Policy with unsafe-eval for explorer.d-bis.org
|
||||
# Requires: CLOUDFLARE_API_TOKEN or (CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY)
|
||||
# Zone: d-bis.org (CLOUDFLARE_ZONE_ID_D_BIS_ORG)
|
||||
set -euo pipefail
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
[ -f "$PROJECT_ROOT/.env" ] && source "$PROJECT_ROOT/.env" 2>/dev/null || true
|
||||
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID_D_BIS_ORG:-${CLOUDFLARE_ZONE_ID:-}}"
|
||||
if [ -z "$ZONE_ID" ]; then echo "CLOUDFLARE_ZONE_ID required"; exit 1; fi
|
||||
|
||||
# Auth - use token if available, else email+key
|
||||
if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
||||
CURL_AUTH=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
|
||||
elif [ -n "${CLOUDFLARE_EMAIL:-}" ] && [ -n "${CLOUDFLARE_API_KEY:-}" ]; then
|
||||
CURL_AUTH=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
|
||||
else
|
||||
echo "Need CLOUDFLARE_API_TOKEN or CLOUDFLARE_EMAIL+CLOUDFLARE_API_KEY"; exit 1
|
||||
fi
|
||||
|
||||
CSP="default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https: data:; style-src 'self' 'unsafe-inline' https: data:; font-src 'self' https: data:; img-src 'self' data: https: blob:; connect-src 'self' https: wss: ws:; media-src 'self' https: data:; object-src 'none'; base-uri 'self'; form-action 'self' https:; frame-ancestors 'none'; upgrade-insecure-requests"
|
||||
|
||||
# 1. List zone rulesets to find http_response_headers_transform
|
||||
RULESETS=$(curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
|
||||
"${CURL_AUTH[@]}" -H "Content-Type: application/json")
|
||||
RULESET_ID=$(echo "$RULESETS" | jq -r '.result[] | select(.phase == "http_response_headers_transform") | .id' | head -1)
|
||||
|
||||
# 2. If no ruleset exists, create one
|
||||
if [ -z "$RULESET_ID" ] || [ "$RULESET_ID" = "null" ]; then
|
||||
CREATE=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets" \
|
||||
"${CURL_AUTH[@]}" -H "Content-Type: application/json" \
|
||||
-d "{\"name\":\"Zone Response Headers Transform\",\"kind\":\"zone\",\"phase\":\"http_response_headers_transform\",\"rules\":[]}")
|
||||
RULESET_ID=$(echo "$CREATE" | jq -r '.result.id')
|
||||
if [ -z "$RULESET_ID" ] || [ "$RULESET_ID" = "null" ]; then
|
||||
echo "Failed to create ruleset: $(echo "$CREATE" | jq -r '.errors')"; exit 1
|
||||
fi
|
||||
echo "Created ruleset $RULESET_ID"
|
||||
fi
|
||||
|
||||
# 3. Get current rules (if any) and add our rule
|
||||
CURRENT=$(curl -s "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" "${CURL_AUTH[@]}")
|
||||
EXISTING_RULES=$(echo "$CURRENT" | jq -r '.result.rules // []')
|
||||
|
||||
# Remove any existing explorer CSP rule
|
||||
NEW_RULES=$(echo "$EXISTING_RULES" | jq '[.[] | select(.ref != "explorer_csp_unsafe_eval")]')
|
||||
# Add our rule (use jq for safe JSON)
|
||||
RULE=$(jq -n --arg csp "$CSP" '{
|
||||
ref: "explorer_csp_unsafe_eval",
|
||||
expression: "(http.host eq \"explorer.d-bis.org\")",
|
||||
description: "Explorer CSP with unsafe-eval for ethers.js v5",
|
||||
action: "rewrite",
|
||||
action_parameters: {
|
||||
headers: {
|
||||
"Content-Security-Policy": { operation: "set", value: $csp }
|
||||
}
|
||||
}
|
||||
}')
|
||||
NEW_RULES=$(echo "$NEW_RULES" | jq --argjson rule "$RULE" '. + [$rule]')
|
||||
|
||||
# 4. Update ruleset
|
||||
RES=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/$ZONE_ID/rulesets/$RULESET_ID" \
|
||||
"${CURL_AUTH[@]}" -H "Content-Type: application/json" \
|
||||
-d "{\"rules\":$NEW_RULES}")
|
||||
|
||||
if echo "$RES" | jq -e '.success' >/dev/null 2>&1; then
|
||||
echo "Cloudflare Transform Rule added for explorer.d-bis.org"
|
||||
else
|
||||
echo "Failed: $(echo "$RES" | jq -r '.errors')"; exit 1
|
||||
fi
|
||||
117
scripts/cloudflare/configure-alltra-hybx-tunnel-and-dns.sh
Normal file
117
scripts/cloudflare/configure-alltra-hybx-tunnel-and-dns.sh
Normal file
@@ -0,0 +1,117 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure Cloudflare Tunnel ingress and DNS for Alltra/HYBX hostnames
|
||||
# Tunnel: Alltra/HYBX → NPMplus at 192.168.11.169:443
|
||||
# Usage: bash scripts/cloudflare/configure-alltra-hybx-tunnel-and-dns.sh
|
||||
# Requires: CLOUDFLARE_API_KEY + CLOUDFLARE_EMAIL or CLOUDFLARE_API_TOKEN in .env
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
source config/ip-addresses.conf 2>/dev/null || true
|
||||
[ -f .env ] && set +u && source .env 2>/dev/null || true && set -u
|
||||
|
||||
# Tunnel ID for sfvalley02 (Alltra/HYBX + Nathan rpc-core-2) — Zero Trust → Networks → Tunnels
|
||||
TUNNEL_ID="${CLOUDFLARE_TUNNEL_ID_SFVALLEY02:-${CLOUDFLARE_TUNNEL_ID_ALLTRA_HYBX:-892bd3fe-c6fa-4ddf-8b60-a8ed2b849c3d}}"
|
||||
ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID}"
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID:-${CLOUDFLARE_ZONE_ID_D_BIS_ORG}}"
|
||||
# Third NPMplus (192.168.11.169) — Alltra, HYBX, rpc-core-2
|
||||
ORIGIN="https://192.168.11.169:443"
|
||||
CNAME_TARGET="${TUNNEL_ID}.cfargotunnel.com"
|
||||
|
||||
# All hostnames on this tunnel (must match NPMplus proxy hosts on 192.168.11.169)
|
||||
HOSTNAMES=(
|
||||
rpc-core-2.d-bis.org
|
||||
rpc-alltra.d-bis.org
|
||||
rpc-alltra-2.d-bis.org
|
||||
rpc-alltra-3.d-bis.org
|
||||
rpc-hybx.d-bis.org
|
||||
rpc-hybx-2.d-bis.org
|
||||
rpc-hybx-3.d-bis.org
|
||||
cacti-alltra.d-bis.org
|
||||
cacti-hybx.d-bis.org
|
||||
firefly-alltra-1.d-bis.org
|
||||
firefly-alltra-2.d-bis.org
|
||||
firefly-hybx-1.d-bis.org
|
||||
firefly-hybx-2.d-bis.org
|
||||
fabric-alltra.d-bis.org
|
||||
indy-alltra.d-bis.org
|
||||
fabric-hybx.d-bis.org
|
||||
indy-hybx.d-bis.org
|
||||
)
|
||||
|
||||
# Auth
|
||||
if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
||||
AUTH_H=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
|
||||
elif [ -n "${CLOUDFLARE_API_KEY:-}" ] && [ -n "${CLOUDFLARE_EMAIL:-}" ]; then
|
||||
AUTH_H=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
|
||||
else
|
||||
echo "Set CLOUDFLARE_API_TOKEN or (CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY) in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z "${ACCOUNT_ID:-}" ] && { echo "Set CLOUDFLARE_ACCOUNT_ID in .env"; exit 1; }
|
||||
[ -z "${ZONE_ID:-}" ] && { echo "Set CLOUDFLARE_ZONE_ID in .env"; exit 1; }
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Cloudflare Tunnel + DNS: sfvalley02 (Alltra/HYBX + rpc-core-2)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Tunnel ID: $TUNNEL_ID"
|
||||
echo "Origin: $ORIGIN"
|
||||
echo "CNAME target: $CNAME_TARGET"
|
||||
echo ""
|
||||
|
||||
# Build ingress config from HOSTNAMES + catch-all
|
||||
CONFIG=$(printf '%s\n' "${HOSTNAMES[@]}" | jq -R -s -c --arg origin "$ORIGIN" '
|
||||
split("\n") | map(select(length > 0)) | map({ hostname: ., service: $origin, originRequest: { noTLSVerify: true } }) + [{ service: "http_status:404" }] | { config: { ingress: ., "warp-routing": { enabled: false } } }
|
||||
')
|
||||
|
||||
echo "Updating tunnel ingress..."
|
||||
RESP=$(curl -s -X PUT \
|
||||
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/configurations" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$CONFIG")
|
||||
|
||||
if echo "$RESP" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " Tunnel ingress updated."
|
||||
else
|
||||
echo " Tunnel update response: $(echo "$RESP" | jq -c '.' 2>/dev/null || echo "$RESP")"
|
||||
echo " (Tunnel may not exist yet; create in Zero Trust → Networks → Tunnels)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Adding/updating DNS CNAME records..."
|
||||
for h in "${HOSTNAMES[@]}"; do
|
||||
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${h}&type=CNAME" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json")
|
||||
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id // empty')
|
||||
CONTENT=$(echo "$EXISTING" | jq -r '.result[0].content // empty')
|
||||
|
||||
DATA=$(jq -n --arg name "$h" --arg target "$CNAME_TARGET" \
|
||||
'{type:"CNAME",name:$name,content:$target,ttl:1,proxied:true}')
|
||||
|
||||
if [ -n "$RECORD_ID" ] && [ "$RECORD_ID" != "null" ]; then
|
||||
if [ "$CONTENT" = "$CNAME_TARGET" ]; then
|
||||
echo " $h: OK (CNAME → $CNAME_TARGET)"
|
||||
else
|
||||
UPD=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$UPD" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $h: Updated CNAME → $CNAME_TARGET"
|
||||
else
|
||||
echo " $h: Update failed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
CR=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$CR" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $h: Created CNAME → $CNAME_TARGET"
|
||||
else
|
||||
echo " $h: Create failed ($(echo "$CR" | jq -r '.errors[0].message // "unknown"' 2>/dev/null))"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done. Next: Request Let's Encrypt certs in NPMplus UI for each domain."
|
||||
echo "See: docs/04-configuration/UDM_PRO_NPMPLUS_ALLTRA_HYBX_PORT_FORWARD.md for UDM Pro port forward (manual)."
|
||||
107
scripts/cloudflare/configure-dev-codespaces-tunnel-and-dns.sh
Normal file
107
scripts/cloudflare/configure-dev-codespaces-tunnel-and-dns.sh
Normal file
@@ -0,0 +1,107 @@
|
||||
#!/usr/bin/env bash
|
||||
# Configure Cloudflare Tunnel ingress and DNS for dev/Codespaces (fourth NPMplus)
|
||||
# Tunnel: dev, Gitea, Proxmox admin → NPMplus at 192.168.11.170:443
|
||||
# Usage: bash scripts/cloudflare/configure-dev-codespaces-tunnel-and-dns.sh
|
||||
# Requires: CLOUDFLARE_TUNNEL_ID_DEV_CODESPACES (or CLOUDFLARE_API_TOKEN / CLOUDFLARE_EMAIL+KEY) in .env
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
source config/ip-addresses.conf 2>/dev/null || true
|
||||
[ -f .env ] && set +u && source .env 2>/dev/null || true && set -u
|
||||
|
||||
# Tunnel ID for dev/Codespaces — create in Zero Trust → Networks → Tunnels, then set in .env
|
||||
TUNNEL_ID="${CLOUDFLARE_TUNNEL_ID_DEV_CODESPACES:-}"
|
||||
ACCOUNT_ID="${CLOUDFLARE_ACCOUNT_ID}"
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID:-${CLOUDFLARE_ZONE_ID_D_BIS_ORG}}"
|
||||
# Fourth NPMplus (192.168.11.170)
|
||||
ORIGIN="https://${IP_NPMPLUS_FOURTH:-192.168.11.170}:443"
|
||||
CNAME_TARGET="${TUNNEL_ID}.cfargotunnel.com"
|
||||
|
||||
# Hostnames on this tunnel (must match NPMplus fourth proxy hosts)
|
||||
HOSTNAMES=(
|
||||
dev.d-bis.org
|
||||
gitea.d-bis.org
|
||||
codespaces.d-bis.org
|
||||
pve.ml110.d-bis.org
|
||||
pve.r630-01.d-bis.org
|
||||
pve.r630-02.d-bis.org
|
||||
)
|
||||
|
||||
# Auth
|
||||
if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
||||
AUTH_H=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
|
||||
elif [ -n "${CLOUDFLARE_API_KEY:-}" ] && [ -n "${CLOUDFLARE_EMAIL:-}" ]; then
|
||||
AUTH_H=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
|
||||
else
|
||||
echo "Set CLOUDFLARE_API_TOKEN or (CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY) in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z "${TUNNEL_ID:-}" ] && { echo "Set CLOUDFLARE_TUNNEL_ID_DEV_CODESPACES in .env (create tunnel in Zero Trust → Networks → Tunnels first)"; exit 1; }
|
||||
[ -z "${ACCOUNT_ID:-}" ] && { echo "Set CLOUDFLARE_ACCOUNT_ID in .env"; exit 1; }
|
||||
[ -z "${ZONE_ID:-}" ] && { echo "Set CLOUDFLARE_ZONE_ID in .env"; exit 1; }
|
||||
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Cloudflare Tunnel + DNS: dev/Codespaces (fourth NPMplus)"
|
||||
echo "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━"
|
||||
echo "Tunnel ID: $TUNNEL_ID"
|
||||
echo "Origin: $ORIGIN"
|
||||
echo "CNAME target: $CNAME_TARGET"
|
||||
echo ""
|
||||
|
||||
# Build ingress config from HOSTNAMES + catch-all
|
||||
CONFIG=$(printf '%s\n' "${HOSTNAMES[@]}" | jq -R -s -c --arg origin "$ORIGIN" '
|
||||
split("\n") | map(select(length > 0)) | map({ hostname: ., service: $origin, originRequest: { noTLSVerify: true } }) + [{ service: "http_status:404" }] | { config: { ingress: ., "warp-routing": { enabled: false } } }
|
||||
')
|
||||
|
||||
echo "Updating tunnel ingress..."
|
||||
RESP=$(curl -s -X PUT \
|
||||
"https://api.cloudflare.com/client/v4/accounts/${ACCOUNT_ID}/cfd_tunnel/${TUNNEL_ID}/configurations" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$CONFIG")
|
||||
|
||||
if echo "$RESP" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " Tunnel ingress updated."
|
||||
else
|
||||
echo " Tunnel update response: $(echo "$RESP" | jq -c '.' 2>/dev/null || echo "$RESP")"
|
||||
echo " (Tunnel may not exist yet; create in Zero Trust → Networks → Tunnels)"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "Adding/updating DNS CNAME records..."
|
||||
for h in "${HOSTNAMES[@]}"; do
|
||||
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${h}&type=CNAME" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json")
|
||||
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id // empty')
|
||||
CONTENT=$(echo "$EXISTING" | jq -r '.result[0].content // empty')
|
||||
|
||||
DATA=$(jq -n --arg name "$h" --arg target "$CNAME_TARGET" \
|
||||
'{type:"CNAME",name:$name,content:$target,ttl:1,proxied:true}')
|
||||
|
||||
if [ -n "$RECORD_ID" ] && [ "$RECORD_ID" != "null" ]; then
|
||||
if [ "$CONTENT" = "$CNAME_TARGET" ]; then
|
||||
echo " $h: OK (CNAME → $CNAME_TARGET)"
|
||||
else
|
||||
UPD=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$UPD" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $h: Updated CNAME → $CNAME_TARGET"
|
||||
else
|
||||
echo " $h: Update failed"
|
||||
fi
|
||||
fi
|
||||
else
|
||||
CR=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$CR" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $h: Created CNAME → $CNAME_TARGET"
|
||||
else
|
||||
echo " $h: Create failed ($(echo "$CR" | jq -r '.errors[0].message // "unknown"' 2>/dev/null))"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "Done. Next: Add proxy hosts on fourth NPMplus (192.168.11.170), then request Let's Encrypt in NPMplus UI."
|
||||
echo "See: docs/04-configuration/DEV_CODESPACES_76_53_10_40.md"
|
||||
76
scripts/cloudflare/configure-mifos-dns.sh
Executable file
76
scripts/cloudflare/configure-mifos-dns.sh
Executable file
@@ -0,0 +1,76 @@
|
||||
#!/usr/bin/env bash
|
||||
# Create or update Cloudflare DNS for mifos.d-bis.org.
|
||||
# Mode: "direct" = A record to PUBLIC_IP_MIFOS (76.53.10.41); "tunnel" = CNAME to tunnel (set CLOUDFLARE_TUNNEL_ID_MIFOS_R630_02).
|
||||
# Usage: MIFOS_DNS_MODE=direct bash scripts/cloudflare/configure-mifos-dns.sh
|
||||
# MIFOS_DNS_MODE=tunnel bash scripts/cloudflare/configure-mifos-dns.sh
|
||||
# Requires: .env with CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY (or CLOUDFLARE_API_TOKEN), and config/ip-addresses.conf
|
||||
set -euo pipefail
|
||||
|
||||
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
||||
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../.." && pwd)"
|
||||
cd "$PROJECT_ROOT"
|
||||
source config/ip-addresses.conf 2>/dev/null || true
|
||||
[ -f .env ] && set +u && source .env 2>/dev/null || true && set -u
|
||||
|
||||
ZONE_ID="${CLOUDFLARE_ZONE_ID:-${CLOUDFLARE_ZONE_ID_D_BIS_ORG}}"
|
||||
HOSTNAME="mifos.d-bis.org"
|
||||
MODE="${MIFOS_DNS_MODE:-tunnel}"
|
||||
|
||||
if [ -n "${CLOUDFLARE_API_TOKEN:-}" ]; then
|
||||
AUTH_H=(-H "Authorization: Bearer $CLOUDFLARE_API_TOKEN")
|
||||
elif [ -n "${CLOUDFLARE_API_KEY:-}" ] && [ -n "${CLOUDFLARE_EMAIL:-}" ]; then
|
||||
AUTH_H=(-H "X-Auth-Email: $CLOUDFLARE_EMAIL" -H "X-Auth-Key: $CLOUDFLARE_API_KEY")
|
||||
else
|
||||
echo "Set CLOUDFLARE_API_TOKEN or (CLOUDFLARE_EMAIL + CLOUDFLARE_API_KEY) in .env"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
[ -z "${ZONE_ID:-}" ] && { echo "Set CLOUDFLARE_ZONE_ID or CLOUDFLARE_ZONE_ID_D_BIS_ORG in .env"; exit 1; }
|
||||
|
||||
echo "Mifos DNS: $HOSTNAME (mode=$MODE)"
|
||||
|
||||
if [ "$MODE" = "direct" ]; then
|
||||
TARGET="${PUBLIC_IP_MIFOS:-76.53.10.41}"
|
||||
TYPE="A"
|
||||
CONTENT="$TARGET"
|
||||
DATA=$(jq -n --arg name "mifos" --arg content "$CONTENT" \
|
||||
'{type:"A",name:$name,content:$content,ttl:1,proxied:true}')
|
||||
else
|
||||
TUNNEL_ID="${CLOUDFLARE_TUNNEL_ID_MIFOS_R630_02:-}"
|
||||
[ -z "$TUNNEL_ID" ] && { echo "Set CLOUDFLARE_TUNNEL_ID_MIFOS_R630_02 in .env for tunnel mode"; exit 1; }
|
||||
TARGET="${TUNNEL_ID}.cfargotunnel.com"
|
||||
TYPE="CNAME"
|
||||
CONTENT="$TARGET"
|
||||
DATA=$(jq -n --arg name "mifos" --arg content "$CONTENT" \
|
||||
'{type:"CNAME",name:$name,content:$content,ttl:1,proxied:true}')
|
||||
fi
|
||||
|
||||
EXISTING=$(curl -s -X GET "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records?name=${HOSTNAME}" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json")
|
||||
RECORD_ID=$(echo "$EXISTING" | jq -r '.result[0].id // empty')
|
||||
CURRENT_TYPE=$(echo "$EXISTING" | jq -r '.result[0].type // empty')
|
||||
CURRENT_CONTENT=$(echo "$EXISTING" | jq -r '.result[0].content // empty')
|
||||
|
||||
if [ -n "$RECORD_ID" ] && [ "$RECORD_ID" != "null" ]; then
|
||||
if [ "$CURRENT_TYPE" = "$TYPE" ] && [ "$CURRENT_CONTENT" = "$CONTENT" ]; then
|
||||
echo " $HOSTNAME: OK ($TYPE → $CONTENT)"
|
||||
exit 0
|
||||
fi
|
||||
UPD=$(curl -s -X PUT "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records/${RECORD_ID}" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$UPD" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $HOSTNAME: Updated $TYPE → $CONTENT"
|
||||
else
|
||||
echo " $HOSTNAME: Update failed ($(echo "$UPD" | jq -r '.errors[0].message // "unknown"' 2>/dev/null))"
|
||||
exit 1
|
||||
fi
|
||||
else
|
||||
CR=$(curl -s -X POST "https://api.cloudflare.com/client/v4/zones/${ZONE_ID}/dns_records" \
|
||||
"${AUTH_H[@]}" -H "Content-Type: application/json" -d "$DATA")
|
||||
if echo "$CR" | jq -e '.success == true' >/dev/null 2>&1; then
|
||||
echo " $HOSTNAME: Created $TYPE → $CONTENT"
|
||||
else
|
||||
echo " $HOSTNAME: Create failed ($(echo "$CR" | jq -r '.errors[0].message // "unknown"' 2>/dev/null))"
|
||||
exit 1
|
||||
fi
|
||||
fi
|
||||
Reference in New Issue
Block a user