974486bc53
Remove the Clay role (Claude Code web UI) and its Anthropic API key. New roles: - ollama: local CPU LLM (qwen3:4b-instruct), internal network only - browserless: headless Chromium for JavaScript-heavy pages - searxng: metasearch backend for the chat web_search tool - n8n at agent.ladkau.de: web chat (/chat), scheduled workflows, Telegram bot; workflows and credentials are imported from the repo Telegram bot: Gemini 3.8 -> Gemini 3.5 -> local Qwen fallback chain, /qwen to force the local model, /stocks and a weekday schedule (07:30, 13:00, 17:40) for the MTE.DE / PTX.F stock report. Also: dashboard and check-services entries for the chat, vault checks for the new secrets (n8n, SearXNG, Gemini, Telegram, SMTP), updated CLAUDE.md, runbooks and README.
107 lines
3.3 KiB
Bash
Executable File
107 lines
3.3 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# Decrypts ansible/group_vars/vault.yml and checks all required secrets are present
|
|
# and non-empty, and validates optional secrets when they are present.
|
|
# Exits non-zero if any check fails.
|
|
# Usage: bash scripts/check-vault.sh
|
|
|
|
set -euo pipefail
|
|
|
|
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
|
|
REPO_ROOT="$(cd "${SCRIPT_DIR}/.." && pwd)"
|
|
VAULT_FILE="${REPO_ROOT}/ansible/group_vars/all/vault.yml"
|
|
|
|
if [ ! -f "${VAULT_FILE}" ]; then
|
|
echo "ERROR: vault file not found at ${VAULT_FILE}" >&2
|
|
echo " Create it with: ansible-vault create ansible/group_vars/all/vault.yml" >&2
|
|
exit 1
|
|
fi
|
|
|
|
if ! command -v ansible-vault &>/dev/null; then
|
|
echo "ERROR: ansible-vault not found — install with: pip install ansible" >&2
|
|
exit 1
|
|
fi
|
|
|
|
echo "==> Decrypting vault (you will be prompted for the vault password)"
|
|
VAULT_CONTENT=$(ansible-vault view "${VAULT_FILE}")
|
|
|
|
# Pass vault content via environment variable — avoids a pipe+heredoc stdin conflict
|
|
# where python3 - consumes stdin for the script, leaving sys.stdin.read() empty.
|
|
export VAULT_CONTENT
|
|
python3 - <<'PYEOF'
|
|
import os, sys, yaml
|
|
|
|
data = yaml.safe_load(os.environ['VAULT_CONTENT'])
|
|
|
|
# Required non-empty scalar strings
|
|
required_scalars = [
|
|
"gitea_db_password",
|
|
"gitea_secret_key",
|
|
"gitea_internal_token",
|
|
"keycloak_db_password",
|
|
"keycloak_admin_password",
|
|
"nextcloud_db_password",
|
|
"nextcloud_admin_password",
|
|
"roundcube_db_password",
|
|
"roundcube_des_key",
|
|
"vaultwarden_admin_token",
|
|
"n8n_encryption_key",
|
|
"searxng_secret_key",
|
|
"smtp_user",
|
|
"smtp_password",
|
|
"gemini_api_key",
|
|
"telegram_bot_token",
|
|
"telegram_user_id",
|
|
]
|
|
|
|
# Required non-empty lists (must contain at least one entry)
|
|
required_lists = [
|
|
"traefik_dashboard_users",
|
|
"registry_users",
|
|
"dovecot_users",
|
|
"n8n_users",
|
|
]
|
|
|
|
# Optional scalars: validated only when present — (key, validator_fn, hint)
|
|
SSH_KEY_PREFIXES = ("ssh-rsa", "ssh-ed25519", "ssh-ecdsa", "ecdsa-sha2-", "sk-ssh-")
|
|
|
|
def is_nonempty(val):
|
|
return bool(str(val).strip())
|
|
|
|
def is_ssh_pubkey(val):
|
|
return any(str(val).strip().startswith(p) for p in SSH_KEY_PREFIXES)
|
|
|
|
optional_scalars = [
|
|
("vaultwarden_sso_client_secret", is_nonempty, "must be a non-empty string"),
|
|
("dl_sftp_authorized_keys", is_ssh_pubkey, "must be a valid SSH public key (ssh-ed25519 / ssh-rsa / ecdsa-sha2-*)"),
|
|
]
|
|
|
|
errors = []
|
|
|
|
for key in required_scalars:
|
|
val = data.get(key, "")
|
|
if not val or str(val).strip() in ("", '""', "''"):
|
|
errors.append(f"{key}: missing or empty (required)")
|
|
|
|
for key in required_lists:
|
|
val = data.get(key)
|
|
if not isinstance(val, list) or len(val) == 0:
|
|
errors.append(f"{key}: missing or empty list (required)")
|
|
|
|
for key, validator, hint in optional_scalars:
|
|
if key in data:
|
|
val = data[key]
|
|
if not val or not validator(str(val).strip()):
|
|
errors.append(f"{key}: present but invalid — {hint}")
|
|
|
|
if errors:
|
|
print("", file=sys.stderr)
|
|
print("ERROR: vault.yml has the following issues:", file=sys.stderr)
|
|
for msg in errors:
|
|
print(f" - {msg}", file=sys.stderr)
|
|
print("", file=sys.stderr)
|
|
print("Edit the vault with: ansible-vault edit ansible/group_vars/all/vault.yml", file=sys.stderr)
|
|
sys.exit(1)
|
|
|
|
print(" OK — all secrets are present and valid")
|
|
PYEOF
|