changemaker.lite/bunker-ops/scripts/bootstrap-vault.sh
2026-02-18 17:15:31 -07:00

154 lines
4.3 KiB
Bash
Executable File

#!/usr/bin/env bash
# =============================================================================
# Bunker Ops — Bootstrap Vault for a New Instance
# Generates all 19+ secrets and creates an encrypted vault.yml
#
# Usage: ./scripts/bootstrap-vault.sh <hostname> [--domain example.org]
# =============================================================================
set -euo pipefail
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
PROJECT_DIR="$(dirname "$SCRIPT_DIR")"
INVENTORY_DIR="${PROJECT_DIR}/inventory/host_vars"
# --- Parse args ---
HOSTNAME="${1:-}"
DOMAIN=""
shift || true
while [[ $# -gt 0 ]]; do
case "$1" in
--domain) DOMAIN="$2"; shift 2 ;;
*) echo "Unknown option: $1"; exit 1 ;;
esac
done
if [[ -z "$HOSTNAME" ]]; then
echo "Usage: $0 <hostname> [--domain example.org]"
echo ""
echo "Generates a vault.yml with random secrets for the given host."
echo "The file will be encrypted with ansible-vault."
exit 1
fi
HOST_DIR="${INVENTORY_DIR}/${HOSTNAME}"
VAULT_FILE="${HOST_DIR}/vault.yml"
# --- Helpers ---
generate_secret() { openssl rand -hex 32; }
generate_password() { openssl rand -base64 48 | tr -dc 'a-zA-Z0-9' | head -c "${1:-24}"; }
generate_token() { openssl rand -hex 16; }
# --- Create host_vars directory ---
mkdir -p "$HOST_DIR"
# --- Generate secrets ---
echo "Generating secrets for: ${HOSTNAME}"
echo ""
V2_PG_PASS=$(generate_password 24)
REDIS_PASS=$(generate_password 24)
JWT_ACCESS=$(generate_secret)
JWT_REFRESH=$(generate_secret)
ENC_KEY=$(generate_secret)
ADMIN_PASS=$(generate_password 20)
LM_DB_PASS=$(generate_password 24)
LM_WEB_PASS=$(generate_password 20)
LM_API_TOKEN=$(generate_token)
NC_PASS=$(generate_password 20)
GITEA_DB=$(generate_password 20)
GITEA_ROOT=$(generate_password 20)
N8N_ENC=$(generate_password 32)
N8N_PASS=$(generate_password 20)
GRAFANA_PASS=$(generate_password 20)
GOTIFY_PASS=$(generate_password 20)
VW_TOKEN=$(generate_secret)
RC_PASS=$(generate_password 20)
GANCIO_PASS=$(generate_password 20)
ADMIN_EMAIL="admin@${DOMAIN:-cmlite.org}"
# --- Write vault file ---
cat > "$VAULT_FILE" << EOF
---
# Bunker Ops — Secrets for ${HOSTNAME}
# Generated: $(date -Iseconds)
# Encrypt with: ansible-vault encrypt ${VAULT_FILE}
# --- Database ---
vault_cml_v2_postgres_password: "${V2_PG_PASS}"
# --- Redis ---
vault_cml_redis_password: "${REDIS_PASS}"
# --- JWT & Encryption ---
vault_cml_jwt_access_secret: "${JWT_ACCESS}"
vault_cml_jwt_refresh_secret: "${JWT_REFRESH}"
vault_cml_encryption_key: "${ENC_KEY}"
# --- Admin ---
vault_cml_initial_admin_email: "${ADMIN_EMAIL}"
vault_cml_initial_admin_password: "${ADMIN_PASS}"
# --- Listmonk ---
vault_cml_listmonk_db_password: "${LM_DB_PASS}"
vault_cml_listmonk_web_admin_password: "${LM_WEB_PASS}"
vault_cml_listmonk_api_token: "${LM_API_TOKEN}"
# --- NocoDB ---
vault_cml_nocodb_admin_password: "${NC_PASS}"
# --- Gitea ---
vault_cml_gitea_db_passwd: "${GITEA_DB}"
vault_cml_gitea_db_root_password: "${GITEA_ROOT}"
# --- n8n ---
vault_cml_n8n_encryption_key: "${N8N_ENC}"
vault_cml_n8n_user_password: "${N8N_PASS}"
# --- Monitoring ---
vault_cml_grafana_admin_password: "${GRAFANA_PASS}"
vault_cml_gotify_admin_password: "${GOTIFY_PASS}"
# --- Vaultwarden ---
vault_cml_vaultwarden_admin_token: "${VW_TOKEN}"
# --- Rocket.Chat ---
vault_cml_rocketchat_admin_password: "${RC_PASS}"
# --- Gancio ---
vault_cml_gancio_admin_password: "${GANCIO_PASS}"
# --- SMTP (set manually) ---
vault_cml_smtp_pass: ""
# --- Pangolin (set after tunnel setup) ---
vault_cml_pangolin_api_key: ""
vault_cml_pangolin_newt_id: ""
vault_cml_pangolin_newt_secret: ""
vault_cml_pangolin_site_id: ""
vault_cml_pangolin_endpoint: ""
# --- Bunker Ops (set if Tier 2) ---
vault_bunker_ops_remote_write_token: ""
EOF
echo "Created: ${VAULT_FILE}"
echo ""
# --- Encrypt if vault password file exists ---
VAULT_PASS_FILE="${PROJECT_DIR}/.vault_pass"
if [[ -f "$VAULT_PASS_FILE" ]]; then
ansible-vault encrypt "$VAULT_FILE" --vault-password-file "$VAULT_PASS_FILE"
echo "Encrypted with ansible-vault."
else
echo "WARNING: No .vault_pass file found at ${VAULT_PASS_FILE}"
echo "Encrypt manually with: ansible-vault encrypt ${VAULT_FILE}"
fi
echo ""
echo "Next steps:"
echo " 1. Create ${HOST_DIR}/main.yml with instance config (cml_domain, features, etc.)"
echo " 2. Add ${HOSTNAME} to inventory/hosts.yml"
echo " 3. Deploy: ansible-playbook playbooks/deploy.yml --limit ${HOSTNAME}"