154 lines
4.3 KiB
Bash
Executable File
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}"
|