#!/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 [--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 [--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}"