ci: deploy dev infra [rebuild]

This commit is contained in:
Stephan D
2026-03-17 01:21:29 +01:00
parent 85ae6254a0
commit 9e91a9f90c
43 changed files with 390 additions and 105 deletions

View File

@@ -9,9 +9,11 @@ trap 'echo "[deploy-db] error at line $LINENO" >&2' ERR
: "${DB_DIR:?missing DB_DIR}"
: "${SSH_USER:?missing SSH_USER}"
: "${SSH_HOST:?missing SSH_HOST}"
# Pass-through AppRole creds for Vault Agent (provided by Woodpecker secrets with existing names)
: "${VAULT_ROLE_ID:?missing VAULT_ROLE_ID}"
: "${VAULT_SECRET_ID:?missing VAULT_SECRET_ID}"
if [[ "${CI_RUNTIME_ENV_NAME:-prod}" != "devserver" ]]; then
# Pass-through AppRole creds for the prod Vault Agent.
: "${VAULT_ROLE_ID:?missing VAULT_ROLE_ID}"
: "${VAULT_SECRET_ID:?missing VAULT_SECRET_ID}"
fi
REMOTE_DIR="${REMOTE_BASE%/}/${DB_DIR}"
REMOTE_TARGET="${SSH_USER}@${SSH_HOST}"
@@ -49,19 +51,45 @@ rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" "${RUNTIME_ENV_FILE}" "$REMOTE
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" \
REMOTE_DIR="$REMOTE_DIR" \
COMPOSE_FILE="$COMPOSE_FILE" \
VAULT_ROLE_ID="$VAULT_ROLE_ID" \
VAULT_SECRET_ID="$VAULT_SECRET_ID" \
VAULT_ROLE_ID="${VAULT_ROLE_ID:-}" \
VAULT_SECRET_ID="${VAULT_SECRET_ID:-}" \
bash -s <<'EOSSH'
set -euo pipefail
cd "${REMOTE_DIR}/compose"
set -a; . ../env/.env.runtime; set +a
load_kv_file() {
local file="$1"
while IFS= read -r line || [ -n "$line" ]; do
case "$line" in
''|\#*) continue ;;
esac
if printf '%s' "$line" | grep -Eq '^[[:alpha:]_][[:alnum:]_]*='; then
local key="${line%%=*}"
local value="${line#*=}"
key="$(printf '%s' "$key" | tr -d '[:space:]')"
value="${value#"${value%%[![:space:]]*}"}"
value="${value%"${value##*[![:space:]]}"}"
if [[ -n "$key" ]]; then
export "$key=$value"
fi
fi
done <"$file"
}
set -a
. ../env/.env.runtime
if [[ -f ../env/vault.env ]]; then
load_kv_file ../env/vault.env
fi
set +a
COMPOSE_PROJECT_NAME="${DB_COMPOSE_PROJECT:-sendico-db}"
export COMPOSE_PROJECT_NAME
# Run with ephemeral AppRole env (scoped only to these commands)
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" docker compose -f "${COMPOSE_FILE}" pull --quiet 2>/dev/null || \
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" docker compose -f "${COMPOSE_FILE}" pull
: "${VAULT_ADDR:?missing VAULT_ADDR}"
: "${VAULT_ROLE_ID:?missing VAULT_ROLE_ID}"
: "${VAULT_SECRET_ID:?missing VAULT_SECRET_ID}"
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" VAULT_ADDR="${VAULT_ADDR}" docker compose -f "${COMPOSE_FILE}" pull --quiet 2>/dev/null || \
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" VAULT_ADDR="${VAULT_ADDR}" docker compose -f "${COMPOSE_FILE}" pull
VAULT_ROLE_ID="${VAULT_ROLE_ID}" VAULT_SECRET_ID="${VAULT_SECRET_ID}" VAULT_ADDR="${VAULT_ADDR}" docker compose -f "${COMPOSE_FILE}" up -d --remove-orphans
docker compose -f "${COMPOSE_FILE}" ps
date -Is > .last_deploy

View File

@@ -13,6 +13,7 @@ REMOTE_DIR="${REMOTE_BASE%/}/${VAULT_DIR}"
REMOTE_TARGET="${SSH_USER}@${SSH_HOST}"
RUNTIME_ENV_FILE="${RUNTIME_ENV_FILE:-ci/prod/.env.runtime}"
COMPOSE_FILE="vault.yml"
SEED_ENV_FILE="${DEV_VAULT_SEED_FILE:-}"
SSH_OPTS=(
-i /root/.ssh/id_rsa
@@ -35,6 +36,9 @@ ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" "mkdir -p ${REMOTE_DIR}/{compose,env}"
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" ci/prod/compose/ "$REMOTE_TARGET:${REMOTE_DIR}/compose/"
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" "${RUNTIME_ENV_FILE}" "$REMOTE_TARGET:${REMOTE_DIR}/env/.env.runtime"
if [[ -n "${SEED_ENV_FILE}" && -f "${SEED_ENV_FILE}" ]]; then
rsync "${RSYNC_FLAGS[@]}" -e "ssh ${SSH_OPTS[*]}" "${SEED_ENV_FILE}" "$REMOTE_TARGET:${REMOTE_DIR}/env/dev-vault-seed.env"
fi
ssh "${SSH_OPTS[@]}" "$REMOTE_TARGET" \
REMOTE_BASE="$REMOTE_BASE" \
@@ -52,6 +56,21 @@ set +a
COMPOSE_PROJECT_NAME="$COMPOSE_PROJECT"
export COMPOSE_PROJECT_NAME
if base64 -d >/dev/null 2>&1 <<<'AA=='; then
BASE64_DECODE_FLAG='-d'
else
BASE64_DECODE_FLAG='--decode'
fi
decode_b64() {
val="$1"
if [[ -z "$val" ]]; then
printf ''
return
fi
printf '%s' "$val" | base64 "${BASE64_DECODE_FLAG}"
}
docker compose -f "$COMPOSE_FILE" pull --quiet 2>/dev/null || docker compose -f "$COMPOSE_FILE" pull
docker compose -f "$COMPOSE_FILE" up -d --remove-orphans
@@ -97,6 +116,63 @@ fi
docker exec dev-vault sh -lc "export VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN='${ROOT_TOKEN}'; vault auth list -format=json | grep -q '\"approle/\"' || vault auth enable approle >/dev/null"
docker exec dev-vault sh -lc "export VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN='${ROOT_TOKEN}'; vault secrets list -format=json | grep -q '\"kv/\"' || vault secrets enable -path=kv kv-v2 >/dev/null"
if [[ -f ../env/dev-vault-seed.env ]]; then
set -a
. ../env/dev-vault-seed.env
set +a
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv registry \
user="$(decode_b64 "${REGISTRY_USER_B64:-}")" \
password="$(decode_b64 "${REGISTRY_PASSWORD_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/db \
user="$(decode_b64 "${SENDICO_DB_USER_B64:-}")" \
password="$(decode_b64 "${SENDICO_DB_PASSWORD_B64:-}")" \
key="$(decode_b64 "${SENDICO_DB_KEY_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/nats \
user="$(decode_b64 "${SENDICO_NATS_USER_B64:-}")" \
password="$(decode_b64 "${SENDICO_NATS_PASSWORD_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/api/endpoint \
secret="$(decode_b64 "${SENDICO_API_ENDPOINT_SECRET_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/notification/mail \
user="$(decode_b64 "${NOTIFICATION_MAIL_USER_B64:-}")" \
password="$(decode_b64 "${NOTIFICATION_MAIL_PASSWORD_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/notification/telegram \
bot_token="$(decode_b64 "${NOTIFICATION_TELEGRAM_BOT_TOKEN_B64:-}")" \
chat_id="$(decode_b64 "${NOTIFICATION_TELEGRAM_CHAT_ID_B64:-}")" \
thread_id="$(decode_b64 "${NOTIFICATION_TELEGRAM_THREAD_ID_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/gateway/chain \
arbitrum_rpc_url="$(decode_b64 "${CHAIN_GATEWAY_RPC_URL_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/gateway/chain/wallet \
private_key="$(decode_b64 "${CHAIN_GATEWAY_WALLET_PRIVATE_KEY_B64:-}")" \
address="$(decode_b64 "${CHAIN_GATEWAY_WALLET_ADDRESS_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/gateway/tron \
rpc_url="$(decode_b64 "${TRON_GATEWAY_RPC_URL_B64:-}")" \
grpc_url="$(decode_b64 "${TRON_GATEWAY_GRPC_URL_B64:-}")" \
grpc_token="$(decode_b64 "${TRON_GATEWAY_GRPC_TOKEN_B64:-}")" >/dev/null
docker exec -e VAULT_ADDR=http://127.0.0.1:8200 -e VAULT_TOKEN="${ROOT_TOKEN}" dev-vault \
vault kv put -mount=kv sendico/gateway/tron/wallet \
private_key="$(decode_b64 "${TRON_GATEWAY_WALLET_PRIVATE_KEY_B64:-}")" \
address="$(decode_b64 "${TRON_GATEWAY_WALLET_ADDRESS_B64:-}")" >/dev/null
fi
docker exec -i dev-vault sh -lc "export VAULT_ADDR=http://127.0.0.1:8200 VAULT_TOKEN='${ROOT_TOKEN}'; vault policy write sendico-dev-apps -" <<'EOF'
path "kv/data/*" {
capabilities = ["create", "read", "update", "delete", "list"]
@@ -124,12 +200,14 @@ write_vault_env() {
local env_dir="${REMOTE_BASE%/}/${service_dir}/env"
mkdir -p "$env_dir"
cat >"${env_dir}/vault.env" <<EOF
VAULT_ADDR=${APP_VAULT_ADDR:-http://dev-vault:8200}
${role_var}=${APPROLE_ROLE_ID}
${secret_var}=${APPROLE_SECRET_ID}
EOF
chmod 600 "${env_dir}/vault.env"
}
write_vault_env "${DB_DIR}" "VAULT_ROLE_ID" "VAULT_SECRET_ID"
write_vault_env "${BFF_DIR}" "BFF_VAULT_ROLE_ID" "BFF_VAULT_SECRET_ID"
write_vault_env "${CALLBACKS_DIR}" "CALLBACKS_VAULT_ROLE_ID" "CALLBACKS_VAULT_SECRET_ID"
write_vault_env "${CHAIN_GATEWAY_DIR}" "CHAIN_GATEWAY_VAULT_ROLE_ID" "CHAIN_GATEWAY_VAULT_SECRET_ID"