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

100
gitea-bootstrap/SKILL.md Normal file
View File

@@ -0,0 +1,100 @@
---
name: gitea-bootstrap
description: >
Bootstrap a sovereign Git service on Node B using Gitea (Docker or native),
with two-phase plan/apply, backups, verification, and rollback. Creates an
admin user, configures SSH/HTTP, and outputs an audit report.
Triggers: 'install gitea', 'bootstrap gitea', 'self-host git', 'node b git',
'gitea plan', 'gitea rollback'.
version: 1.0.0
---
# Gitea Bootstrap
Tier 2 (Infrastructure Sovereignty): build **Node B** as your self-hosted Git authority.
This skill supports two deployment modes:
- **Docker** (recommended for fastest repeatability)
- **Native** (system package + systemd)
It is **plan/apply** gated with DRY_RUN and a confirmation phrase.
## Quick Start
```bash
cd ~/.claude/skills/gitea-bootstrap
# Choose mode
export MODE="docker" # docker | native
export NODE_NAME="node-b"
# Network
export HTTP_PORT=3000
export SSH_PORT=2222 # external SSH for git (docker mode)
export DOMAIN="git.example.com" # optional; for reverse proxy
# Storage
export DATA_DIR="$HOME/gitea"
export BACKUP_DIR="outputs/backups"
# Admin bootstrap (you'll be prompted to set password securely)
export ADMIN_USER="sovereign"
export ADMIN_EMAIL="sovereign@vaultmesh.org"
# Safety
export DRY_RUN=1
export REQUIRE_CONFIRM=1
export CONFIRM_PHRASE="I UNDERSTAND THIS WILL INSTALL AND CONFIGURE GITEA"
./scripts/00_preflight.sh
./scripts/10_plan.sh
export DRY_RUN=0
./scripts/11_apply.sh
./scripts/90_verify.sh
./scripts/99_report.sh
```
## Inputs
| Parameter | Required | Default | Description |
|---|---:|---|---|
| MODE | Yes | docker | docker or native |
| NODE_NAME | No | node-b | Identifier for reporting |
| HTTP_PORT | No | 3000 | Gitea web port |
| SSH_PORT | No | 2222 | SSH port for git (docker mode) |
| DOMAIN | No | (empty) | Hostname if using reverse proxy |
| DATA_DIR | No | ~/gitea | Data directory (repos, config, db) |
| ADMIN_USER | Yes | (none) | Initial admin username |
| ADMIN_EMAIL | Yes | (none) | Initial admin email |
| DRY_RUN | No | 1 | Apply refuses unless DRY_RUN=0 |
| REQUIRE_CONFIRM | No | 1 | Require confirmation phrase |
| CONFIRM_PHRASE | No | I UNDERSTAND THIS WILL INSTALL AND CONFIGURE GITEA | Safety phrase |
## Outputs
- `outputs/compose.yml` (docker mode)
- `outputs/gitea_app.ini` (rendered config template)
- `outputs/status_matrix.json`
- `outputs/audit_report.md`
- Backups under `outputs/backups/`
## Safety Guarantees
1. Default **DRY_RUN=1**
2. Confirmation phrase required
3. Backups of generated configs + service definitions
4. Rollback scripts for docker and native modes
## EU Compliance
| Aspect | Value |
|---|---|
| Data Residency | EU (Ireland - Dublin) |
| Jurisdiction | Irish Law |
| Git Data | Stored on Node B only |
| Backups | Local outputs + optional offsite via backup-sovereign |
## References
- [Gitea Hardening Notes](references/gitea_hardening_notes.md)

View File

@@ -0,0 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SKILL_ROOT/scripts/_common.sh"
: "${HTTP_PORT:=3000}"
: "${SSH_PORT:=2222}"
main() {
if command -v ss >/dev/null 2>&1; then
ss -ltn | awk '{print $4}' | grep -q ":$HTTP_PORT$" && die "HTTP_PORT $HTTP_PORT already in use"
ss -ltn | awk '{print $4}' | grep -q ":$SSH_PORT$" && die "SSH_PORT $SSH_PORT already in use"
else
log_warn "ss not available; skipping port checks."
fi
log_info "Ports appear free."
}
main "$@"

View File

@@ -0,0 +1,42 @@
{
"name": "gitea-bootstrap",
"version": "1.0.0",
"description": "Bootstrap Gitea on Node B with plan/apply gates, verify, rollback.",
"defaults": {
"MODE": "docker",
"NODE_NAME": "node-b",
"HTTP_PORT": "3000",
"SSH_PORT": "2222",
"DATA_DIR": "~/gitea",
"DRY_RUN": "1",
"REQUIRE_CONFIRM": "1",
"CONFIRM_PHRASE": "I UNDERSTAND THIS WILL INSTALL AND CONFIGURE GITEA"
},
"phases": {
"preflight": [
"00_preflight.sh"
],
"gitea": {
"plan": [
"10_plan.sh"
],
"apply": [
"11_apply.sh"
],
"rollback": [
"rollback/undo.sh"
]
},
"verify": [
"90_verify.sh"
],
"report": [
"99_report.sh"
]
},
"eu_compliance": {
"data_residency": "EU",
"jurisdiction": "Ireland",
"gdpr_applicable": true
}
}

View File

@@ -0,0 +1,16 @@
# Gitea Hardening Notes
## Minimum Hardening
- Put Gitea behind reverse proxy (nginx/Traefik) with TLS
- Disable public registration if not needed
- Enforce 2FA for admin/org owners
- Restrict SSH to known networks or require VPN/tunnel
- Back up the data dir regularly (repos + config + sqlite/db)
## Backups
If using sqlite, backing up `/data/gitea/gitea.db` plus repos is enough.
For Postgres/MySQL, dump database + repos.
## Next Skills
- container-registry (self-hosted with signatures)
- dns-sovereign (PowerDNS + Cloudflare hybrid)

View File

@@ -0,0 +1,49 @@
#!/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}"
: "${ADMIN_USER:=}"
: "${ADMIN_EMAIL:=}"
: "${DATA_DIR:=$HOME/gitea}"
: "${HTTP_PORT:=3000}"
: "${SSH_PORT:=2222}"
main() {
log_info "Starting 00_preflight.sh"
[[ -n "$ADMIN_USER" ]] || die "ADMIN_USER is required."
[[ -n "$ADMIN_EMAIL" ]] || die "ADMIN_EMAIL is required."
need curl
need jq
if [[ "$MODE" == "docker" ]]; then
need docker
need docker-compose || log_warn "docker-compose not found; will use 'docker compose' if available."
docker version >/dev/null 2>&1 || die "Docker not working."
elif [[ "$MODE" == "native" ]]; then
need sudo
need systemctl
else
die "MODE must be 'docker' or 'native' (got: $MODE)"
fi
mkdir -p "$SKILL_ROOT/outputs"
mkdir -p "$SKILL_ROOT/outputs/backups"
mkdir -p "$DATA_DIR"
# lightweight port sanity
if command -v ss >/dev/null 2>&1; then
if ss -ltn | awk '{print $4}' | grep -q ":$HTTP_PORT$"; then
log_warn "HTTP_PORT $HTTP_PORT already in use."
fi
if ss -ltn | awk '{print $4}' | grep -q ":$SSH_PORT$"; then
log_warn "SSH_PORT $SSH_PORT already in use."
fi
fi
log_info "Preflight OK."
}
main "$@"

View File

@@ -0,0 +1,36 @@
#!/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}"
: "${NODE_NAME:=node-b}"
: "${HTTP_PORT:=3000}"
: "${SSH_PORT:=2222}"
: "${DOMAIN:=}"
: "${DATA_DIR:=$HOME/gitea}"
: "${ADMIN_USER:=}"
: "${ADMIN_EMAIL:=}"
main() {
[[ -n "$ADMIN_USER" ]] || die "ADMIN_USER is required."
[[ -n "$ADMIN_EMAIL" ]] || die "ADMIN_EMAIL is required."
echo "[PLAN] $(date -Iseconds) Gitea Bootstrap ($MODE)"
echo "[PLAN] Node: $NODE_NAME"
echo "[PLAN] Data dir: $DATA_DIR"
echo "[PLAN] Web: http://<host>:$HTTP_PORT (or https://$DOMAIN via reverse proxy)"
if [[ "$MODE" == "docker" ]]; then
echo "[PLAN] SSH (git): <host>:$SSH_PORT (container maps to 22)"
echo "[PLAN] Will generate: outputs/compose.yml and outputs/gitea_app.ini"
echo "[PLAN] Will run: docker compose up -d"
else
echo "[PLAN] Native install: package + systemd"
echo "[PLAN] Will write: /etc/gitea/app.ini (backup first)"
fi
echo "[PLAN] Admin bootstrap:"
echo " username=$ADMIN_USER email=$ADMIN_EMAIL"
echo "[PLAN] Next: export DRY_RUN=0 && ./scripts/11_apply.sh"
}
main "$@"

View File

@@ -0,0 +1,112 @@
#!/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}"
: "${NODE_NAME:=node-b}"
: "${HTTP_PORT:=3000}"
: "${SSH_PORT:=2222}"
: "${DOMAIN:=}"
: "${DATA_DIR:=$HOME/gitea}"
: "${ADMIN_USER:=}"
: "${ADMIN_EMAIL:=}"
compose_cmd() {
if command -v docker-compose >/dev/null 2>&1; then
echo "docker-compose"
else
echo "docker compose"
fi
}
main() {
confirm_gate
[[ -n "$ADMIN_USER" ]] || die "ADMIN_USER is required."
[[ -n "$ADMIN_EMAIL" ]] || die "ADMIN_EMAIL is required."
local ts; ts="$(date -Iseconds | tr ':' '-')"
local backup_dir="$SKILL_ROOT/outputs/backups/$ts"
mkdir -p "$backup_dir"
if [[ "$MODE" == "docker" ]]; then
need docker
mkdir -p "$SKILL_ROOT/outputs"
# Render minimal app.ini (Gitea will expand defaults)
cat > "$SKILL_ROOT/outputs/gitea_app.ini" <<EOF
APP_NAME = VaultMesh Gitea
RUN_MODE = prod
[server]
DOMAIN = ${DOMAIN}
HTTP_PORT = ${HTTP_PORT}
ROOT_URL = ${DOMAIN:+https://${DOMAIN}/}${DOMAIN:+" "}${DOMAIN:-http://localhost:${HTTP_PORT}/}
SSH_DOMAIN = ${DOMAIN:-localhost}
SSH_PORT = ${SSH_PORT}
DISABLE_SSH = false
START_SSH_SERVER = true
[database]
DB_TYPE = sqlite3
PATH = /data/gitea/gitea.db
[security]
INSTALL_LOCK = true
EOF
# Render compose.yml
cat > "$SKILL_ROOT/outputs/compose.yml" <<EOF
version: "3"
services:
gitea:
image: gitea/gitea:latest
container_name: gitea
restart: unless-stopped
environment:
- USER_UID=1000
- USER_GID=1000
- GITEA__server__HTTP_PORT=${HTTP_PORT}
- GITEA__server__SSH_PORT=${SSH_PORT}
volumes:
- ${DATA_DIR}:/data
- ${SKILL_ROOT}/outputs/gitea_app.ini:/data/gitea/conf/app.ini
ports:
- "${HTTP_PORT}:${HTTP_PORT}"
- "${SSH_PORT}:22"
EOF
cp -a "$SKILL_ROOT/outputs/compose.yml" "$backup_dir/compose.yml"
cp -a "$SKILL_ROOT/outputs/gitea_app.ini" "$backup_dir/gitea_app.ini"
log_info "Starting Gitea via compose..."
cd "$SKILL_ROOT/outputs"
$(compose_cmd) -f compose.yml up -d
log_info "Waiting for HTTP..."
for i in $(seq 1 30); do
if curl -fsS "http://127.0.0.1:${HTTP_PORT}/" >/dev/null 2>&1; then
break
fi
sleep 1
done
log_warn "Admin creation is interactive via web UI on first run (recommended)."
log_warn "Open: http://<host>:${HTTP_PORT}/ and create admin user: $ADMIN_USER"
log_warn "Then lock install is already set in app.ini (INSTALL_LOCK=true)."
elif [[ "$MODE" == "native" ]]; then
need sudo
need systemctl
log_warn "Native mode is a scaffold in v1.0.0."
log_warn "It intentionally does not auto-install packages to avoid distro variance."
log_warn "Next action: follow references/gitea_hardening_notes.md and extend apply script for your distro."
else
die "MODE must be docker|native"
fi
log_info "Apply complete."
}
main "$@"

View File

@@ -0,0 +1,59 @@
#!/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}"
: "${HTTP_PORT:=3000}"
: "${DATA_DIR:=$HOME/gitea}"
main() {
local status="$SKILL_ROOT/outputs/status_matrix.json"
local ok_http=false ok_data=false ok_compose=false ok_container=false
[[ -d "$DATA_DIR" ]] && ok_data=true
[[ -f "$SKILL_ROOT/outputs/compose.yml" ]] && ok_compose=true
if curl -fsS "http://127.0.0.1:${HTTP_PORT}/" >/dev/null 2>&1; then
ok_http=true
fi
if [[ "$MODE" == "docker" ]]; then
if docker ps --format '{{.Names}}' | grep -q '^gitea$'; then
ok_container=true
fi
fi
blockers="[]"
if [[ "$ok_data" != "true" ]]; then blockers='["data_dir_missing"]'
elif [[ "$ok_compose" != "true" && "$MODE" == "docker" ]]; then blockers='["compose_missing"]'
elif [[ "$ok_http" != "true" ]]; then blockers='["http_unreachable"]'
fi
cat > "$status" <<EOF
{
"skill": "gitea-bootstrap",
"timestamp": "$(date -Iseconds)",
"checks": [
{"name":"data_dir_present", "ok": $ok_data},
{"name":"compose_present", "ok": $ok_compose},
{"name":"container_running", "ok": $ok_container},
{"name":"http_reachable", "ok": $ok_http}
],
"blockers": $blockers,
"warnings": [
"Admin user creation is recommended via first-run web UI in v1"
],
"next_steps": [
"Create admin via web UI and record admin creation in your ops log",
"Put Gitea behind reverse proxy + TLS (optional)",
"Proceed to container-registry or dns-sovereign"
]
}
EOF
log_info "Wrote $status"
cat "$status"
}
main "$@"

View File

@@ -0,0 +1,79 @@
#!/usr/bin/env bash
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "$0")" && pwd)"
SKILL_ROOT="$(dirname "$SCRIPT_DIR")"
source "$SCRIPT_DIR/_common.sh"
: "${NODE_NAME:=node-b}"
: "${MODE:=docker}"
: "${HTTP_PORT:=3000}"
: "${SSH_PORT:=2222}"
: "${DOMAIN:=}"
: "${DATA_DIR:=$HOME/gitea}"
: "${ADMIN_USER:=}"
: "${ADMIN_EMAIL:=}"
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
# Gitea Bootstrap Audit Report
**Generated:** $(date -Iseconds)
**Node:** $(json_escape "$NODE_NAME")
**Mode:** $(json_escape "$MODE")
**Web Port:** $HTTP_PORT
**SSH Port:** $SSH_PORT
**Domain:** $(json_escape "$DOMAIN")
**Data Dir:** $(json_escape "$DATA_DIR")
**Admin (planned):** $(json_escape "${ADMIN_USER:-}") / $(json_escape "${ADMIN_EMAIL:-}")
**Skill Version:** 1.0.0
---
## Artifacts
| Item | Path |
|---|---|
| Compose | \`$SKILL_ROOT/outputs/compose.yml\` |
| app.ini | \`$SKILL_ROOT/outputs/gitea_app.ini\` |
| 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 |
| Git Authority | Self-hosted on Node B |
| Backups | Local outputs; optional offsite via backup-sovereign |
---
## Rollback
- Docker/native undo: \`./scripts/rollback/undo.sh\`
EOF
log_info "Wrote $report"
cat "$report"
}
main "$@"

View File

@@ -0,0 +1,32 @@
#!/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 WILL INSTALL AND CONFIGURE GITEA}"
[[ "$DRY_RUN" == "0" ]] || die "DRY_RUN=$DRY_RUN (set DRY_RUN=0 to apply)."
if [[ "$REQUIRE_CONFIRM" == "1" ]]; then
echo "Type to confirm:"
echo " $CONFIRM_PHRASE"
read -r input
[[ "$input" == "$CONFIRM_PHRASE" ]] || die "Confirmation phrase mismatch."
fi
}

View File

@@ -0,0 +1,34 @@
#!/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"
: "${MODE:=docker}"
: "${DATA_DIR:=$HOME/gitea}"
compose_cmd() {
if command -v docker-compose >/dev/null 2>&1; then
echo "docker-compose"
else
echo "docker compose"
fi
}
main() {
confirm_gate
if [[ "$MODE" == "docker" ]]; then
if [[ -f "$SKILL_ROOT/outputs/compose.yml" ]]; then
log_warn "Stopping compose stack..."
cd "$SKILL_ROOT/outputs"
$(compose_cmd) -f compose.yml down || true
else
log_warn "No compose.yml found; attempting to stop container 'gitea'..."
docker rm -f gitea 2>/dev/null || true
fi
else
log_warn "Native mode rollback scaffold (stop gitea service manually if configured)."
fi
log_info "Rollback complete. Data dir preserved at: $DATA_DIR"
}
main "$@"