eletrotupi / tcc/ ansible/scripts/import-vault.shc901c35af9c84b6a29e5185545ced1129f33b8f4
2.9 KB | 85 lines Raw
1
#!/usr/bin/env bash
2
#
3
# Build the encrypted Ansible vault from the values that are live on the VPS
4
#
5
# Pulls /srv/app/production/.env and .env.production, extracts the secrets,
6
# generates a logs UI credential, and writes the encrypted group_vars vault.
7
# Read-only on the server
8
#
9
#   ansible/scripts/import-vault.sh
10
#
11
# The vault password lives in ansible/.vault_pass (git-ignored); this script
12
# creates it on first run and prints it, so store it somewhere safe. Connection
13
# details come from ansible/inventory/hosts.yml, or the VPS_HOST / VPS_USER /
14
# VPS_KEY environment variables
15

16
set -euo pipefail
17

18
repo_root="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
19
ansible_dir="$repo_root/ansible"
20
inventory="$ansible_dir/inventory/hosts.yml"
21
vault_file="$ansible_dir/inventory/group_vars/all/vault.yml"
22
vault_pass_file="$ansible_dir/.vault_pass"
23

24
field() { awk -F': *' -v k="^[[:space:]]*$1" '$0 ~ k {print $2; exit}' "$inventory"; }
25

26
HOST="${VPS_HOST:-}"
27
USER="${VPS_USER:-}"
28
KEY="${VPS_KEY:-}"
29

30
if [ -f "$inventory" ]; then
31
  [ -n "$HOST" ] || HOST="$(field 'ansible_host:')"
32
  [ -n "$USER" ] || USER="$(field 'ansible_user:')"
33
  [ -n "$KEY" ]  || KEY="$(field 'ansible_ssh_private_key_file:')"
34
fi
35

36
KEY="${KEY/#\~/$HOME}"
37
KEY="${KEY:-$HOME/.ssh/id_ed25519}"
38
[ -n "$HOST" ] || { echo "no host: set VPS_HOST or provide inventory/hosts.yml" >&2; exit 2; }
39
[ -n "$USER" ] || { echo "no user: set VPS_USER or provide inventory/hosts.yml" >&2; exit 2; }
40

41
tmp="$(mktemp -d)"
42
trap 'rm -rf "$tmp"' EXIT
43
ssh_opts=(-i "$KEY" -o StrictHostKeyChecking=accept-new)
44

45
echo "Pulling live env from ${USER}@${HOST} ..."
46
scp "${ssh_opts[@]}" "${USER}@${HOST}:/srv/app/production/.env"             "$tmp/env"           >/dev/null
47
scp "${ssh_opts[@]}" "${USER}@${HOST}:/srv/app/production/.env.production" "$tmp/env.production" >/dev/null
48

49
# The env files are plain KEY=value; sourcing them is the least fussy parse
50
set -a
51
# shellcheck disable=SC1091
52
. "$tmp/env"
53
# shellcheck disable=SC1091
54
. "$tmp/env.production"
55
set +a
56

57
if [ ! -f "$vault_pass_file" ]; then
58
  umask 077
59
  openssl rand -base64 32 >"$vault_pass_file"
60
  echo "==> generated $vault_pass_file"
61
  echo "    vault password: $(cat "$vault_pass_file")"
62
fi
63

64
logs_pass="$(openssl rand -base64 18)"
65
logs_hash="$(openssl passwd -apr1 "$logs_pass")"
66

67
cat >"$vault_file.plain" <<EOF
68
vault_postgres_password: "${POSTGRES_PASSWORD:?missing POSTGRES_PASSWORD}"
69
vault_jwt_secret: "${JWT_SECRET:?missing JWT_SECRET}"
70
vault_resend_api_key: "${RESEND_API_KEY:?missing RESEND_API_KEY}"
71
vault_s3_access_key: "${S3_ACCESS_KEY:?missing S3_ACCESS_KEY}"
72
vault_s3_access_secret: "${S3_ACCESS_SECRET:?missing S3_ACCESS_SECRET}"
73
vault_nginx_logs_htpasswd: "logs:${logs_hash}"
74
EOF
75

76
ansible-vault encrypt \
77
  --vault-password-file "$vault_pass_file" \
78
  --output "$vault_file" \
79
  "$vault_file.plain"
80
rm -f "$vault_file.plain"
81

82
echo
83
echo "Wrote $vault_file (encrypted)."
84
echo "Logs UI credential: user 'logs', password '${logs_pass}'"
85
echo "Back up both the vault password and this credential."