#!/usr/bin/env bash # Merge .env into inventories/production/group_vars/all/vault.yml # Usage: make vault-import-env [ENV_FILE=.env] set -euo pipefail REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)" ENV_FILE="${1:-${ENV_FILE:-${REPO_ROOT}/.env}}" VAULT_FILE="${REPO_ROOT}/inventories/production/group_vars/all/vault.yml" VAULT_PASS="${HOME}/.ansible-vault-pass" ANSIBLE_VAULT="${REPO_ROOT}/.venv/bin/ansible-vault" [[ -f "${ENV_FILE}" ]] || { echo "No env file: ${ENV_FILE}" >&2; exit 1; } [[ -f "${VAULT_PASS}" ]] || { echo "Missing ${VAULT_PASS}" >&2; exit 1; } "${REPO_ROOT}/.venv/bin/python3" - "${ENV_FILE}" "${VAULT_FILE}" "${VAULT_PASS}" "${ANSIBLE_VAULT}" <<'PY' import os, re, subprocess, sys, tempfile, yaml env_file, vault_file, vault_pass, ansible_vault = sys.argv[1:5] def load_env(path): out = {} with open(path) as f: for line in f: line = line.strip() if not line or line.startswith("#"): continue if line.startswith("export "): line = line[7:].strip() if "=" not in line: continue k, _, v = line.partition("=") v = v.strip().strip("'").strip('"') if v: out[k.strip()] = v return out # .env key -> vault key (or vault_mailcow_mailbox_passwords.) MAP = { "MAILCOW_API_KEY": "vault_mailcow_api_key", "ALERTS_PASSWORD": ("vault_alerts_mailbox_password", "alerts"), "KUMA_PASSWORD": "vault_uptime_kuma_password", "KUMA_USER": "vault_uptime_kuma_user", "KUMA_URL": "vault_uptime_kuma_url", "UMAMI_ADMIN_PASSWORD": "vault_umami_admin_password", "UMAMI_DB_PASS": "vault_umami_db_password", "UMAMI_APP_SECRET": "vault_umami_app_secret", "SMTP_HOST": "vault_kuma_smtp_host", "SMTP_PORT": "vault_kuma_smtp_port", "SMTP_USER": "vault_kuma_smtp_user", "SMTP_PASS": "vault_kuma_smtp_password", "SMTP_TO": "vault_kuma_smtp_to", "MATTERMOST_URL": "vault_mattermost_url", "MATTERMOST_TOKEN": "vault_mattermost_token", "MATTERMOST_ALLOWED_USERS": "vault_mattermost_allowed_users", "PROXMOX_PASSWORD": "vault_proxmox_password", "LXC_ROOT_PASSWORD": "vault_lxc_root_password", } env = load_env(env_file) text = subprocess.check_output( [ansible_vault, "view", vault_file, "--vault-password-file", vault_pass], text=True, ) data = yaml.safe_load(text) or {} passwords = dict(data.get("vault_mailcow_mailbox_passwords") or {}) for k, v in env.items(): m = re.match(r"^MAILBOX_(.+)_PASSWORD$", k, re.I) if m: passwords[m.group(1).lower()] = v continue target = MAP.get(k) if not target: continue if isinstance(target, tuple): data[target[0]] = v passwords[target[1]] = v else: data[target] = v if passwords: data["vault_mailcow_mailbox_passwords"] = passwords fd, tmp = tempfile.mkstemp(suffix=".yml") os.close(fd) with open(tmp, "w") as f: yaml.dump(data, f, default_flow_style=False, sort_keys=False, allow_unicode=True) subprocess.run( [ansible_vault, "encrypt", tmp, "--output", vault_file, "--vault-password-file", vault_pass, "--encrypt-vault-id", "default"], check=True, ) os.remove(tmp) print(f"Updated {vault_file} from {env_file} ({len(env)} values)") PY