Initial commit: VaultMesh Skills collection

Collection of operational skills for VaultMesh infrastructure including:
- backup-sovereign: Backup and recovery operations
- btc-anchor: Bitcoin anchoring
- cloudflare-tunnel-manager: Cloudflare tunnel management
- container-registry: Container registry operations
- disaster-recovery: Disaster recovery procedures
- dns-sovereign: DNS management
- eth-anchor: Ethereum anchoring
- gitea-bootstrap: Gitea setup and configuration
- hetzner-bootstrap: Hetzner server provisioning
- merkle-forest: Merkle tree operations
- node-hardening: Node security hardening
- operator-bootstrap: Operator initialization
- proof-verifier: Cryptographic proof verification
- rfc3161-anchor: RFC3161 timestamping
- secrets-vault: Secrets management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
Vault Sovereign
2025-12-27 00:25:00 +00:00
commit eac77ef7b4
213 changed files with 11724 additions and 0 deletions

View File

@@ -0,0 +1,29 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${MODE:=docker}"
: "${PDNS_API_KEY:=}"
: "${PDNS_DATA_DIR:=$HOME/pdns}"
: "${PDNS_PORT:=53}"
: "${PDNS_WEB_PORT:=8081}"
main() {
[[ -n "$PDNS_API_KEY" ]] || die "PDNS_API_KEY is required."
need curl
need jq
if [[ "$MODE" == "docker" ]]; then
need docker
else
die "MODE must be docker in v1.0.0"
fi
mkdir -p "$SKILL_ROOT/outputs" "$SKILL_ROOT/outputs/backups"
mkdir -p "$PDNS_DATA_DIR"
log_info "Preflight OK."
}
main "$@"

View File

@@ -0,0 +1,21 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${PDNS_DATA_DIR:=$HOME/pdns}"
: "${PDNS_PORT:=53}"
: "${PDNS_WEB_PORT:=8081}"
main() {
echo "[PLAN] $(date -Iseconds) PowerDNS Authoritative (Docker)"
echo "[PLAN] Data dir: $PDNS_DATA_DIR"
echo "[PLAN] DNS port: $PDNS_PORT/udp + $PDNS_PORT/tcp"
echo "[PLAN] API/Web: 127.0.0.1:$PDNS_WEB_PORT (recommended to keep private)"
echo "[PLAN] Outputs:"
echo " outputs/compose.yml"
echo " outputs/pdns.conf"
echo "[PLAN] Next: export DRY_RUN=0 && ./scripts/11_pdns_apply.sh"
}
main "$@"

View File

@@ -0,0 +1,71 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${PDNS_API_KEY:=}"
: "${PDNS_DATA_DIR:=$HOME/pdns}"
: "${PDNS_PORT:=53}"
: "${PDNS_WEB_PORT:=8081}"
main() {
confirm_gate
need docker
[[ -n "$PDNS_API_KEY" ]] || die "PDNS_API_KEY is required."
local ts; ts="$(date -Iseconds | tr ':' '-')"
local backup_dir="$SKILL_ROOT/outputs/backups/$ts"
mkdir -p "$backup_dir"
# pdns.conf (mounted into container)
cat > "$SKILL_ROOT/outputs/pdns.conf" <<EOF
launch=gsqlite3
gsqlite3-database=/var/lib/powerdns/pdns.sqlite3
api=yes
api-key=$PDNS_API_KEY
webserver=yes
webserver-address=0.0.0.0
webserver-port=8081
# security posture
disable-syslog=yes
loglevel=4
# allow API only from container network; bind published port to localhost in compose
webserver-allow-from=127.0.0.1,10.0.0.0/8,172.16.0.0/12,192.168.0.0/16
EOF
# compose
cat > "$SKILL_ROOT/outputs/compose.yml" <<EOF
version: "3.8"
services:
pdns:
image: powerdns/pdns-auth-49:latest
container_name: pdns-auth
restart: unless-stopped
ports:
- "${PDNS_PORT}:53/udp"
- "${PDNS_PORT}:53/tcp"
- "127.0.0.1:${PDNS_WEB_PORT}:8081/tcp"
volumes:
- ${PDNS_DATA_DIR}:/var/lib/powerdns
- ${SKILL_ROOT}/outputs/pdns.conf:/etc/powerdns/pdns.conf:ro
EOF
cp -a "$SKILL_ROOT/outputs/pdns.conf" "$backup_dir/pdns.conf"
cp -a "$SKILL_ROOT/outputs/compose.yml" "$backup_dir/compose.yml"
log_info "Starting PowerDNS..."
cd "$SKILL_ROOT/outputs"
$(compose_cmd) -f compose.yml up -d
# Probe API
log_info "Probing PDNS API..."
local api="http://127.0.0.1:${PDNS_WEB_PORT}/api/v1/servers/localhost"
curl -fsS -H "X-API-Key: $PDNS_API_KEY" "$api" | jq '.' > "$SKILL_ROOT/outputs/pdns_api_probe.json"
log_info "PDNS API probe saved: outputs/pdns_api_probe.json"
log_info "PDNS apply complete."
}
main "$@"

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${ZONE_NAME:=}"
: "${NS1_NAME:=}"
: "${NS2_NAME:=}"
main() {
if [[ -z "$ZONE_NAME" ]]; then
log_warn "ZONE_NAME not set; zone creation will be skipped."
exit 0
fi
echo "[PLAN] $(date -Iseconds) Create zone in PowerDNS"
echo "[PLAN] Zone: $ZONE_NAME"
echo "[PLAN] NS1: ${NS1_NAME:-ns1.$ZONE_NAME}"
echo "[PLAN] NS2: ${NS2_NAME:-ns2.$ZONE_NAME}"
echo "[PLAN] Note: PowerDNS API expects trailing dot for zone operations."
echo "[PLAN] Next: export DRY_RUN=0 && ./scripts/21_zone_apply.sh"
}
main "$@"

View File

@@ -0,0 +1,45 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${PDNS_API_KEY:=}"
: "${PDNS_WEB_PORT:=8081}"
: "${ZONE_NAME:=}"
: "${NS1_NAME:=}"
: "${NS2_NAME:=}"
api() {
local method="$1"; shift
local url="$1"; shift
curl -sS -X "$method" "$url" -H "X-API-Key: $PDNS_API_KEY" -H "Content-Type: application/json" "$@"
}
main() {
confirm_gate
[[ -n "$PDNS_API_KEY" ]] || die "PDNS_API_KEY is required."
[[ -n "$ZONE_NAME" ]] || die "ZONE_NAME is required."
local zone="${ZONE_NAME%\.}."
local ns1="${NS1_NAME:-ns1.${ZONE_NAME}}"
local ns2="${NS2_NAME:-ns2.${ZONE_NAME}}"
local base="http://127.0.0.1:${PDNS_WEB_PORT}/api/v1/servers/localhost"
# Check if zone exists
if api GET "$base/zones/$zone" | jq -e '.name' >/dev/null 2>&1; then
log_warn "Zone already exists: $zone"
exit 0
fi
log_info "Creating zone: $zone"
api POST "$base/zones" --data "{
\"name\": \"$zone\",
\"kind\": \"Native\",
\"masters\": [],
\"nameservers\": [\"$ns1.\", \"$ns2.\"]
}" | jq '.' > "$SKILL_ROOT/outputs/zone_create_result.json"
log_info "Zone created; output saved: outputs/zone_create_result.json"
}
main "$@"

View File

@@ -0,0 +1,23 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${CF_API_TOKEN:=}"
: "${CF_ZONE_NAME:=}"
: "${ZONE_NAME:=}"
main() {
if [[ -z "$CF_API_TOKEN" || -z "$CF_ZONE_NAME" ]]; then
log_warn "Cloudflare mirror not configured (CF_API_TOKEN/CF_ZONE_NAME). Skipping CF plan."
exit 0
fi
echo "[PLAN] $(date -Iseconds) Cloudflare DNS mirror"
echo "[PLAN] Mirror target zone in Cloudflare: $CF_ZONE_NAME"
echo "[PLAN] Source zone (PowerDNS): ${ZONE_NAME:-<unset>}"
echo "[PLAN] v1 mirrors only records listed in outputs/mirror_records.json if present."
echo "[PLAN] Create that file to define records (A/AAAA/CNAME/TXT)."
echo "[PLAN] Next: export DRY_RUN=0 && ./scripts/31_cf_apply.sh"
}
main "$@"

View File

@@ -0,0 +1,73 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${CF_API_TOKEN:=}"
: "${CF_ZONE_NAME:=}"
api() {
local method="$1"; shift
local url="$1"; shift
curl -sS -X "$method" "$url" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
"$@"
}
main() {
confirm_gate
[[ -n "$CF_API_TOKEN" ]] || die "CF_API_TOKEN is required."
[[ -n "$CF_ZONE_NAME" ]] || die "CF_ZONE_NAME is required."
need jq
need curl
local mirror_file="$SKILL_ROOT/outputs/mirror_records.json"
if [[ ! -f "$mirror_file" ]]; then
die "Missing $mirror_file. Create it like: [{\"type\":\"A\",\"name\":\"app\",\"content\":\"1.2.3.4\",\"ttl\":120}]"
fi
log_info "Resolving Cloudflare zone id for: $CF_ZONE_NAME"
local zid; zid="$(api GET "https://api.cloudflare.com/client/v4/zones?name=$CF_ZONE_NAME" | jq -r '.result[0].id')"
[[ -n "$zid" && "$zid" != "null" ]] || die "Unable to resolve zone id."
# For each record, create/update in CF
created_ids=[]
results=[]
while IFS= read -r rec; do
rtype="$(echo "$rec" | jq -r '.type')"
rname="$(echo "$rec" | jq -r '.name')"
rcontent="$(echo "$rec" | jq -r '.content')"
rttl="$(echo "$rec" | jq -r '.ttl // 120')"
# Convert short name to FQDN if needed
if [[ "$rname" != *"."* ]]; then
fqdn="${rname}.${CF_ZONE_NAME}"
else
fqdn="$rname"
fi
# check existing
existing="$(api GET "https://api.cloudflare.com/client/v4/zones/$zid/dns_records?type=$rtype&name=$fqdn")"
rid="$(echo "$existing" | jq -r '.result[0].id')"
if [[ -n "$rid" && "$rid" != "null" ]]; then
log_info "Updating $rtype $fqdn"
api PUT "https://api.cloudflare.com/client/v4/zones/$zid/dns_records/$rid" \
--data "{\"type\":\"$rtype\",\"name\":\"$fqdn\",\"content\":\"$rcontent\",\"ttl\":$rttl,\"proxied\":true}" \
| jq -e '.success==true' >/dev/null || die "Failed update for $fqdn"
echo "$rid" >> "$SKILL_ROOT/outputs/cloudflare_record_ids.txt"
else
log_info "Creating $rtype $fqdn"
resp="$(api POST "https://api.cloudflare.com/client/v4/zones/$zid/dns_records" \
--data "{\"type\":\"$rtype\",\"name\":\"$fqdn\",\"content\":\"$rcontent\",\"ttl\":$rttl,\"proxied\":true}")"
echo "$resp" | jq -e '.success==true' >/dev/null || die "Failed create for $fqdn"
new_id="$(echo "$resp" | jq -r '.result.id')"
echo "$new_id" >> "$SKILL_ROOT/outputs/cloudflare_record_ids.txt"
fi
done < <(jq -c '.[]' "$mirror_file")
log_info "Cloudflare mirror applied. IDs saved to outputs/cloudflare_record_ids.txt"
}
main "$@"

View File

@@ -0,0 +1,52 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${PDNS_WEB_PORT:=8081}"
: "${PDNS_API_KEY:=}"
: "${PDNS_PORT:=53}"
main() {
local status="$SKILL_ROOT/outputs/status_matrix.json"
local ok_container=false ok_api=false ok_probe=false
if docker ps --format '{{.Names}}' | grep -q '^pdns-auth$'; then ok_container=true; fi
if [[ -n "${PDNS_API_KEY:-}" ]]; then
if curl -fsS -H "X-API-Key: $PDNS_API_KEY" "http://127.0.0.1:${PDNS_WEB_PORT}/api/v1/servers/localhost" >/dev/null 2>&1; then
ok_api=true
fi
fi
[[ -f "$SKILL_ROOT/outputs/pdns_api_probe.json" ]] && ok_probe=true
blockers="[]"
if [[ "$ok_container" != "true" ]]; then blockers='["pdns_container_not_running"]'
elif [[ "$ok_api" != "true" ]]; then blockers='["pdns_api_unreachable_or_key_missing"]'
fi
cat > "$status" <<EOF
{
"skill": "dns-sovereign",
"timestamp": "$(date -Iseconds)",
"checks": [
{"name":"pdns_container_running", "ok": $ok_container},
{"name":"pdns_api_reachable", "ok": $ok_api},
{"name":"api_probe_saved", "ok": $ok_probe}
],
"blockers": $blockers,
"warnings": [
"PowerDNS API is bound to localhost only in compose; keep it private"
],
"next_steps": [
"Create/verify zones and NS records",
"Point domain registrar to your NS hosts when ready",
"Optionally mirror select records to Cloudflare"
]
}
EOF
log_info "Wrote $status"
cat "$status"
}
main "$@"

View File

@@ -0,0 +1,77 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${PDNS_PORT:=53}"
: "${PDNS_WEB_PORT:=8081}"
: "${PDNS_DATA_DIR:=$HOME/pdns}"
: "${ZONE_NAME:=}"
: "${CF_ZONE_NAME:=}"
main() {
mkdir -p "$SKILL_ROOT/outputs"
local report="$SKILL_ROOT/outputs/audit_report.md"
local status="$SKILL_ROOT/outputs/status_matrix.json"
cat > "$report" <<EOF
# DNS Sovereign Audit Report
**Generated:** $(date -Iseconds)
**PDNS DNS Port:** $PDNS_PORT
**PDNS API Port (localhost):** $PDNS_WEB_PORT
**PDNS Data Dir:** $(json_escape "$PDNS_DATA_DIR")
**Zone (PDNS):** $(json_escape "${ZONE_NAME:-}")
**Cloudflare Mirror Zone:** $(json_escape "${CF_ZONE_NAME:-}")
**Skill Version:** 1.0.0
---
## Artifacts
| Item | Path |
|---|---|
| Compose | \`$SKILL_ROOT/outputs/compose.yml\` |
| pdns.conf | \`$SKILL_ROOT/outputs/pdns.conf\` |
| API Probe | \`$SKILL_ROOT/outputs/pdns_api_probe.json\` |
| Status Matrix | \`$SKILL_ROOT/outputs/status_matrix.json\` |
| Backups | \`$SKILL_ROOT/outputs/backups/\` |
---
## Status Matrix
$(if [[ -f "$status" ]]; then
echo '```json'
cat "$status"
echo '```'
else
echo "_Missing status_matrix.json — run 90_verify.sh first._"
fi)
---
## EU Compliance Declaration
| Aspect | Value |
|---|---|
| Data Residency | EU (Ireland - Dublin) |
| Jurisdiction | Irish Law |
| Authoritative DNS | PowerDNS on your node |
| Mirror | Optional Cloudflare mirror |
---
## Rollback
- PDNS stop/remove: \`./scripts/rollback/undo_pdns.sh\`
- Delete zone (optional): \`./scripts/rollback/undo_zone.sh\`
- Remove CF records created by this skill: \`./scripts/rollback/undo_cloudflare.sh\`
EOF
log_info "Wrote $report"
cat "$report"
}
main "$@"

View File

@@ -0,0 +1,38 @@
#!/usr/bin/env bash
set -euo pipefail
log_info(){ echo "[INFO] $(date -Iseconds) $*"; }
log_warn(){ echo "[WARN] $(date -Iseconds) $*" >&2; }
log_error(){ echo "[ERROR] $(date -Iseconds) $*" >&2; }
die(){ log_error "$*"; exit 1; }
need(){ command -v "$1" >/dev/null 2>&1 || die "Missing required tool: $1"; }
json_escape() {
local s="$1"
s="${s//\\/\\\\}"
s="${s//\"/\\\"}"
s="${s//$'\n'/\\n}"
s="${s//$'\r'/\\r}"
s="${s//$'\t'/\\t}"
printf "%s" "$s"
}
confirm_gate() {
: "${DRY_RUN:=1}"
: "${REQUIRE_CONFIRM:=1}"
: "${CONFIRM_PHRASE:=I UNDERSTAND THIS CAN CHANGE DNS}"
[[ "$DRY_RUN" == "0" ]] || die "DRY_RUN=$DRY_RUN (set DRY_RUN=0)."
if [[ "$REQUIRE_CONFIRM" == "1" ]]; then
echo "Type to confirm:"
echo " $CONFIRM_PHRASE"
read -r input
[[ "$input" == "$CONFIRM_PHRASE" ]] || die "Confirmation phrase mismatch."
fi
}
compose_cmd() {
if command -v docker-compose >/dev/null 2>&1; then
echo "docker-compose"
else
echo "docker compose"
fi
}

View File

@@ -0,0 +1,44 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
source "$SKILL_ROOT/scripts/_common.sh"
: "${CF_API_TOKEN:=}"
: "${CF_ZONE_NAME:=}"
api() {
local method="$1"; shift
local url="$1"; shift
curl -sS -X "$method" "$url" \
-H "Authorization: Bearer $CF_API_TOKEN" \
-H "Content-Type: application/json" \
"$@"
}
main() {
confirm_gate
[[ -n "$CF_API_TOKEN" ]] || die "CF_API_TOKEN required."
[[ -n "$CF_ZONE_NAME" ]] || die "CF_ZONE_NAME required."
need jq
need curl
local ids_file="$SKILL_ROOT/outputs/cloudflare_record_ids.txt"
if [[ ! -f "$ids_file" ]]; then
log_warn "No cloudflare_record_ids.txt found; nothing to undo."
exit 0
fi
local zid; zid="$(api GET "https://api.cloudflare.com/client/v4/zones?name=$CF_ZONE_NAME" | jq -r '.result[0].id')"
[[ -n "$zid" && "$zid" != "null" ]] || die "Unable to resolve zone id."
while IFS= read -r rid; do
[[ -n "$rid" ]] || continue
log_warn "Deleting Cloudflare DNS record id: $rid"
api DELETE "https://api.cloudflare.com/client/v4/zones/$zid/dns_records/$rid" | jq -e '.success==true' >/dev/null || log_warn "Failed delete for $rid"
done < "$ids_file"
rm -f "$ids_file" || true
log_info "Cloudflare rollback complete."
}
main "$@"

View File

@@ -0,0 +1,17 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
source "$SKILL_ROOT/scripts/_common.sh"
main() {
confirm_gate
if docker ps -a --format '{{.Names}}' | grep -q '^pdns-auth$'; then
log_warn "Stopping/removing pdns-auth container..."
docker rm -f pdns-auth || true
else
log_warn "pdns-auth container not found."
fi
log_info "PDNS rollback complete. Data preserved in PDNS_DATA_DIR."
}
main "$@"

View File

@@ -0,0 +1,28 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$(dirname "$SCRIPT_DIR")")"
source "$SKILL_ROOT/scripts/_common.sh"
: "${PDNS_API_KEY:=}"
: "${PDNS_WEB_PORT:=8081}"
: "${ZONE_NAME:=}"
api() {
local method="$1"; shift
local url="$1"; shift
curl -sS -X "$method" "$url" -H "X-API-Key: $PDNS_API_KEY" -H "Content-Type: application/json" "$@"
}
main() {
confirm_gate
[[ -n "$PDNS_API_KEY" ]] || die "PDNS_API_KEY required."
[[ -n "$ZONE_NAME" ]] || die "ZONE_NAME required."
local zone="${ZONE_NAME%\.}."
local base="http://127.0.0.1:${PDNS_WEB_PORT}/api/v1/servers/localhost"
log_warn "Deleting zone: $zone"
api DELETE "$base/zones/$zone" | jq '.' || die "Failed to delete zone."
log_info "Zone rollback complete."
}
main "$@"