512 lines
18 KiB
Bash
Executable File
512 lines
18 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
set -euo pipefail
|
|
|
|
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
BUILDX_CONFIG="/tmp/buildx-config.toml"
|
|
HOMELAB_STATE_DIR="${HOMELAB_STATE_DIR:-${XDG_DATA_HOME:-${HOME}/.local/share}/homelab}"
|
|
COSIGN_KEY_PREFIX="${COSIGN_KEY_PREFIX:-${HOMELAB_STATE_DIR}/cosign/cosign}"
|
|
COSIGN_KEY_PATH="${COSIGN_KEY_PATH:-${COSIGN_KEY_PREFIX}.key}"
|
|
COSIGN_PUBLIC_KEY_PATH="${COSIGN_PUBLIC_KEY_PATH:-${COSIGN_KEY_PREFIX}.pub}"
|
|
COSIGN_PASSWORD_FILE="${COSIGN_PASSWORD_FILE:-${HOMELAB_STATE_DIR}/cosign/cosign.password}"
|
|
COSIGN_VERSION="${COSIGN_VERSION:-2.6.3}"
|
|
COSIGN_BIN="${COSIGN_BIN:-}"
|
|
HOMELAB_COSIGN_PUBLIC_KEY_CONFIGMAP="${HOMELAB_COSIGN_PUBLIC_KEY_CONFIGMAP:-homelab-cosign-public-key}"
|
|
HOMELAB_SBOM_PREDICATE_TYPE="${HOMELAB_SBOM_PREDICATE_TYPE:-https://spdx.dev/Document}"
|
|
JEANNIE_LOG_DIR="${JEANNIE_LOG_DIR:-${HOMELAB_STATE_DIR}/logs}"
|
|
JEANNIE_LOG_FILE="${JEANNIE_LOG_FILE:-}"
|
|
JEANNIE_ERROR_LOG_FILE="${JEANNIE_ERROR_LOG_FILE:-}"
|
|
JEANNIE_STEP_INDEX=0
|
|
JEANNIE_STEP_TOTAL=0
|
|
|
|
# shellcheck disable=SC1091
|
|
source "${REPO_ROOT}/scripts/report-ui"
|
|
source "${REPO_ROOT}/lib/jeannie/core.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/env.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/toolchain.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/pimox.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/preflight.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/pipeline.sh"
|
|
source "${REPO_ROOT}/lib/jeannie/security.sh"
|
|
# shellcheck disable=SC1091
|
|
source "${REPO_ROOT}/lib/jeannie/commands.sh"
|
|
|
|
trap 'rm -f "${BUILDX_CONFIG}"' EXIT
|
|
|
|
load_homelab_inventory_defaults
|
|
export_homelab_inventory_tf_vars
|
|
KUBECONFIG_PATH="${KUBECONFIG_PATH:-${TF_VAR_kubeconfig_path:-${LAB_KUBECONFIG_PATH:-/home/jv/.kube/config}}}"
|
|
|
|
print_usage() {
|
|
cat <<'EOF'
|
|
Usage: ./jeannie <command> [args]
|
|
|
|
Base, Inventory, And Planning
|
|
help | -h | --help Show this grouped help.
|
|
validate Run repo validation checks.
|
|
inventory-check Validate the canonical homelab inventory.
|
|
preflight Run non-mutating infrastructure preflight checks.
|
|
doctor-preapply Run deeper pre-apply safety checks.
|
|
plan [all|provisioning|cluster|platform|apps|edge]
|
|
Run OpenTofu plans without applying changes.
|
|
|
|
Build And Bootstrap
|
|
up Deploy the full homelab pipeline.
|
|
deploy-gitea Deploy the Debian-hosted Gitea container.
|
|
deploy-heimdall Deploy the Debian-hosted Heimdall dashboard.
|
|
deploy-matrix Deploy the Matrix homeserver (Synapse + Element + Postgres).
|
|
deploy-omniroute Deploy the OmniRoute LLM routing gateway.
|
|
deploy-hermes Deploy the Hermes agent (git-install + venv + gateway service).
|
|
bootstrap-gitea-repo Ensure the Gitea repo and SSH key wiring exist.
|
|
rpi-services Deploy Pi-hole, Unbound, and Uptime Kuma on RPi4.
|
|
ollama-setup Install/configure Ollama on the Debian host.
|
|
artifact-cache {status|up|down|instructions}
|
|
Manage optional Debian artifact caches.
|
|
blockchain-devnet {status|up|down|logs|rpc}
|
|
Manage the local Ethereum Anvil devnet.
|
|
blockchain-test [forge args...] Run Foundry tests for labs/blockchain.
|
|
blockchain-wallet {instructions|new|address|sign-message}
|
|
Practice dev wallet and signing workflows.
|
|
golden-ledger {show|check} Show or validate Pimox golden image versions.
|
|
|
|
Cluster Lifecycle
|
|
rebuild-cluster Recreate the cluster through the guarded path.
|
|
stop-cluster Stop Kubernetes and worker VMs without destroy.
|
|
start-cluster Start Kubernetes and desired worker VMs.
|
|
workers <list|tailnet|start|stop|restart|drain|uncordon|recreate-plan|rebalance>
|
|
Manage Pimox/Kubernetes workers.
|
|
move-prometheus-stack-workers Move monitoring workloads to worker nodes.
|
|
doctor-versions [--all|--details|--verbose|--json]
|
|
Check Kubernetes/container tooling versions.
|
|
|
|
Operator View And Reports
|
|
status [--all|--details|--verbose|--json] Problems-first cascade from host to public URLs.
|
|
status --heal-plan Build a guarded self-heal plan from status.
|
|
status --heal Dry-run auto-eligible self-heal actions.
|
|
scorecard Compact pass/warn/fail operator scorecard.
|
|
capacity Compact capacity and placement report.
|
|
capacity-advisor Decide whether to add VMs or fix placement/resources.
|
|
capacity-limits [namespace] Recommend requests/limits YAML snippets.
|
|
recover-plan Print disaster recovery order and prerequisites.
|
|
recover-power [--dry-run] Run or preview post-outage recovery.
|
|
heal {plan|apply} Plan/apply guarded self-healing actions.
|
|
incident {list|replay|triage} Classify incident text and suggest read-only next steps.
|
|
safety-case [--since REF] [PATH...] Generate risk, blast-radius, test, and rollback case.
|
|
agent-sandbox {check|policy} Classify proposed commands against agent policy.
|
|
impact [--since REF] [PATH...] Explain affected lab areas before changes.
|
|
review-last-change [REF] Summarize changed files, impact, validation.
|
|
map [--dot] Print the homelab dependency map.
|
|
change-journal {list|path} Show risky-command journal entries.
|
|
release-snapshot Write a pre-change release snapshot.
|
|
|
|
Observability And GitOps
|
|
grafana-dashboards {list|apply} List or apply repo-managed Grafana dashboards.
|
|
gitops-status Print focused Argo CD health and sync status.
|
|
platform Deploy platform stack only.
|
|
edge Deploy/check the OCI edge stack only.
|
|
promote {plan|validate|rollback APP} Run canary promotion gates and rollback plan.
|
|
cert-check Check public DNS, TLS, and edge URL health.
|
|
backup-status Check backup and restore-drill freshness.
|
|
synthetic-checks Run end-to-end service probes.
|
|
resource-budget Report Kubernetes resource request/limit gaps.
|
|
route-inventory Report routes and Uptime Kuma coverage.
|
|
control-plane {status|taint|untaint|pods}
|
|
Keep normal pods off the Debian control plane.
|
|
explain <command>|output Explain warnings/errors and fix commands.
|
|
|
|
Recovery And State
|
|
backup-gitea Back up the Debian-hosted Gitea data.
|
|
drill-restore Run all restore drills.
|
|
drill-gitea-restore Run the Gitea restore drill.
|
|
drill-pihole-restore Run the Pi-hole restore drill.
|
|
state-backup Back up local OpenTofu state files.
|
|
|
|
Focused Doctors
|
|
doctor-edge [--all|--details|--verbose|--json]
|
|
Diagnose edge routing and public exposure.
|
|
doctor-gitea [--all|--details|--verbose|--json]
|
|
Diagnose Gitea local/public access.
|
|
doctor-rpi [--all|--details|--verbose|--json]
|
|
Diagnose RPi services and DNS.
|
|
doctor-cluster [--all|--details|--verbose|--json]
|
|
Diagnose Kubernetes cluster health.
|
|
|
|
Access, Secrets, And Policy
|
|
access-audit Audit SSH, Gitea, Kubernetes, and Tailscale access.
|
|
kubeconfig-readonly Create/check read-only kubeconfig material.
|
|
secrets-init Initialize SOPS/age secret tooling.
|
|
secrets-check Validate repo-managed secret prerequisites.
|
|
tailnet-policy-check Validate Tailscale ACL policy as code.
|
|
fix-debian-docker-root Repair Debian Docker root placement.
|
|
|
|
Apps And Services
|
|
apps Deploy application stack only.
|
|
website-translation-model Prepare website translation model support.
|
|
website-ollama-listen Configure website Ollama access.
|
|
install-gitea-runner [TOKEN] Install the Gitea Actions runner.
|
|
openwrt Deploy/check OpenWrt lab config.
|
|
|
|
Security Learning
|
|
security-scan Run the security scan bundle.
|
|
security-prepare Prepare defensive security tools.
|
|
security-zap Run OWASP ZAP checks.
|
|
security-k8s Run Kubernetes security checks.
|
|
security-host Run host security checks.
|
|
security-trivy Run Trivy scans.
|
|
security-secrets Run secret leak checks.
|
|
security-nuclei Run Nuclei web checks.
|
|
security-web Run web security checks.
|
|
security-logs Review security-relevant logs.
|
|
security-runtime Check runtime security sensors.
|
|
security-attack-path Print prioritized attack-path findings.
|
|
prompt-injection-lab {list|run|show} Run local prompt-injection defense drills.
|
|
red-blue {plan|run|ledger} Run or plan safe red-team/blue-team loop.
|
|
|
|
AI And Indexing
|
|
ai-index Build the local homelab RAG index.
|
|
ai-check Query/check the local AI index.
|
|
ask [--citations] QUESTION... Find relevant docs/runbooks/commands.
|
|
ai-evals {list|run|show} Run deterministic Jeannie/RAG eval cases.
|
|
ai-scheduler {simulate|recommend NAME} Simulate AI workload placement policy.
|
|
ai-memory {check} Check local RAG index provenance freshness.
|
|
model-observe {prompts|run|report} Track model behavior over stable prompts.
|
|
|
|
Destructive
|
|
nuke Guarded cluster state destruction path.
|
|
EOF
|
|
}
|
|
|
|
if [[ "${JEANNIE_LIBRARY_MODE:-false}" == "true" ]]; then
|
|
# shellcheck disable=SC2317
|
|
return 0 2>/dev/null || exit 0
|
|
fi
|
|
|
|
case "${1:-}" in
|
|
__up-task)
|
|
up_task "${2:-}"
|
|
;;
|
|
"" | help | -h | --help)
|
|
print_usage
|
|
;;
|
|
up)
|
|
record_change_journal "up" "$@"
|
|
up
|
|
;;
|
|
plan)
|
|
plan_homelab "${2:-all}"
|
|
;;
|
|
rebuild-cluster)
|
|
record_change_journal "rebuild-cluster" "$@"
|
|
rebuild_cluster
|
|
;;
|
|
stop-cluster)
|
|
record_change_journal "stop-cluster" "$@"
|
|
stop_cluster
|
|
;;
|
|
start-cluster)
|
|
record_change_journal "start-cluster" "$@"
|
|
start_cluster
|
|
;;
|
|
status)
|
|
status_report "${@:2}"
|
|
;;
|
|
capacity)
|
|
capacity_report "$@"
|
|
;;
|
|
capacity-advisor)
|
|
capacity_advisor "$@"
|
|
;;
|
|
capacity-limits)
|
|
capacity_limits "$@"
|
|
;;
|
|
recover-plan)
|
|
recover_plan
|
|
;;
|
|
gitops-status)
|
|
gitops_status
|
|
;;
|
|
platform)
|
|
record_change_journal "platform" "$@"
|
|
require_debian_server "platform"
|
|
jeannie_log_start "platform"
|
|
jeannie_step_plan 1
|
|
run_step "Platform OpenTofu apply" platform_apply
|
|
echo "Log: ${JEANNIE_LOG_FILE}"
|
|
;;
|
|
edge)
|
|
record_change_journal "edge" "$@"
|
|
require_debian_server "edge"
|
|
jeannie_log_start "edge"
|
|
jeannie_step_plan 1
|
|
run_step "Edge OpenTofu apply" edge_apply
|
|
echo "Log: ${JEANNIE_LOG_FILE}"
|
|
;;
|
|
promote)
|
|
promote "$@"
|
|
;;
|
|
cert-check)
|
|
cert_check
|
|
;;
|
|
release-snapshot)
|
|
record_change_journal "release-snapshot" "$@"
|
|
release_snapshot
|
|
;;
|
|
backup-status)
|
|
backup_status
|
|
;;
|
|
synthetic-checks)
|
|
synthetic_checks
|
|
;;
|
|
resource-budget)
|
|
resource_budget "$@"
|
|
;;
|
|
control-plane)
|
|
control_plane "$@"
|
|
;;
|
|
artifact-cache)
|
|
artifact_cache "$@"
|
|
;;
|
|
blockchain-devnet)
|
|
blockchain_devnet "$@"
|
|
;;
|
|
blockchain-test)
|
|
blockchain_test "$@"
|
|
;;
|
|
blockchain-wallet)
|
|
blockchain_wallet "$@"
|
|
;;
|
|
golden-ledger)
|
|
golden_ledger "$@"
|
|
;;
|
|
route-inventory)
|
|
route_inventory
|
|
;;
|
|
explain)
|
|
explain "$@"
|
|
;;
|
|
recover-power)
|
|
recover_power "$@"
|
|
;;
|
|
heal)
|
|
heal "$@"
|
|
;;
|
|
incident)
|
|
incident_commander "$@"
|
|
;;
|
|
safety-case)
|
|
safety_case "$@"
|
|
;;
|
|
agent-sandbox)
|
|
agent_sandbox "$@"
|
|
;;
|
|
scorecard)
|
|
scorecard
|
|
;;
|
|
grafana-dashboards)
|
|
grafana_dashboards "$@"
|
|
;;
|
|
workers)
|
|
workers_manage "$@"
|
|
;;
|
|
change-journal)
|
|
change_journal "$@"
|
|
;;
|
|
map)
|
|
homelab_map "$@"
|
|
;;
|
|
validate)
|
|
validate_homelab
|
|
;;
|
|
access-audit)
|
|
access_audit
|
|
;;
|
|
kubeconfig-readonly)
|
|
kubeconfig_readonly
|
|
;;
|
|
apps)
|
|
record_change_journal "apps" "$@"
|
|
require_debian_server "apps"
|
|
jeannie_log_start "apps"
|
|
jeannie_step_plan 1
|
|
run_step "Applications" apps
|
|
echo "Log: ${JEANNIE_LOG_FILE}"
|
|
;;
|
|
website-translation-model)
|
|
website_translation_model
|
|
;;
|
|
website-ollama-listen)
|
|
website_ollama_listen
|
|
;;
|
|
ollama-setup)
|
|
ollama_setup
|
|
;;
|
|
deploy-gitea)
|
|
record_change_journal "deploy-gitea" "$@"
|
|
deploy_gitea
|
|
;;
|
|
deploy-heimdall)
|
|
record_change_journal "deploy-heimdall" "$@"
|
|
deploy_heimdall
|
|
;;
|
|
deploy-matrix)
|
|
record_change_journal "deploy-matrix" "$@"
|
|
deploy_matrix
|
|
;;
|
|
deploy-omniroute)
|
|
record_change_journal "deploy-omniroute" "$@"
|
|
deploy_omniroute
|
|
;;
|
|
deploy-hermes)
|
|
record_change_journal "deploy-hermes" "$@"
|
|
deploy_hermes
|
|
;;
|
|
rpi-services)
|
|
record_change_journal "rpi-services" "$@"
|
|
deploy_rpi_services
|
|
;;
|
|
bootstrap-gitea-repo)
|
|
bootstrap_gitea_repo
|
|
;;
|
|
backup-gitea)
|
|
backup_gitea
|
|
;;
|
|
drill-restore)
|
|
drill_restore
|
|
;;
|
|
drill-gitea-restore)
|
|
drill_gitea_restore
|
|
;;
|
|
drill-pihole-restore)
|
|
drill_pihole_restore
|
|
;;
|
|
install-gitea-runner)
|
|
install_gitea_runner "${2:-}"
|
|
;;
|
|
move-prometheus-stack-workers)
|
|
move_prometheus_stack_workers
|
|
;;
|
|
doctor-versions)
|
|
doctor_versions "${@:2}"
|
|
;;
|
|
doctor-edge)
|
|
doctor_edge "${@:2}"
|
|
;;
|
|
doctor-gitea)
|
|
doctor_gitea "${@:2}"
|
|
;;
|
|
doctor-rpi)
|
|
doctor_rpi "${@:2}"
|
|
;;
|
|
doctor-cluster)
|
|
doctor_cluster "${@:2}"
|
|
;;
|
|
preflight)
|
|
homelab_preflight "full"
|
|
;;
|
|
doctor-preapply)
|
|
doctor_preapply
|
|
;;
|
|
inventory-check)
|
|
inventory_check
|
|
;;
|
|
state-backup)
|
|
backup_tofu_state
|
|
;;
|
|
fix-debian-docker-root)
|
|
fix_debian_docker_root
|
|
;;
|
|
secrets-init)
|
|
secrets_init
|
|
;;
|
|
secrets-check)
|
|
secrets_check
|
|
;;
|
|
tailnet-policy-check)
|
|
tailnet_policy_check
|
|
;;
|
|
ai-index)
|
|
ai_index
|
|
;;
|
|
ai-check)
|
|
ai_check
|
|
;;
|
|
ask)
|
|
ask_homelab "$@"
|
|
;;
|
|
ai-evals)
|
|
ai_evals "$@"
|
|
;;
|
|
ai-scheduler)
|
|
ai_scheduler "$@"
|
|
;;
|
|
ai-memory)
|
|
ai_memory "$@"
|
|
;;
|
|
model-observe)
|
|
model_observe "$@"
|
|
;;
|
|
impact)
|
|
impact "$@"
|
|
;;
|
|
review-last-change)
|
|
review_last_change "$@"
|
|
;;
|
|
security-scan)
|
|
security_scan
|
|
;;
|
|
security-prepare)
|
|
security_prepare
|
|
;;
|
|
security-zap)
|
|
security_zap
|
|
;;
|
|
security-k8s)
|
|
security_k8s
|
|
;;
|
|
security-host)
|
|
security_host
|
|
;;
|
|
security-trivy)
|
|
security_trivy
|
|
;;
|
|
security-secrets)
|
|
security_secrets
|
|
;;
|
|
security-nuclei)
|
|
security_nuclei
|
|
;;
|
|
security-web)
|
|
security_web
|
|
;;
|
|
security-logs)
|
|
security_logs
|
|
;;
|
|
security-runtime)
|
|
security_runtime
|
|
;;
|
|
security-attack-path)
|
|
security_attack_path "$@"
|
|
;;
|
|
prompt-injection-lab)
|
|
prompt_injection_lab "$@"
|
|
;;
|
|
red-blue)
|
|
red_blue_loop "$@"
|
|
;;
|
|
openwrt)
|
|
openwrt
|
|
;;
|
|
nuke)
|
|
record_change_journal "nuke" "$@"
|
|
require_debian_server "nuke"
|
|
jeannie_log_start "nuke"
|
|
jeannie_step_plan 1
|
|
run_step "Nuke homelab cluster state" nuke
|
|
echo "Log: ${JEANNIE_LOG_FILE}"
|
|
;;
|
|
*)
|
|
printf 'Unknown command: %s\n\n' "$1" >&2
|
|
print_usage >&2
|
|
exit 1
|
|
;;
|
|
esac
|