From 56a7734e8e11f7965a9c40aea1aa9223ec8eb267 Mon Sep 17 00:00:00 2001 From: Ruslan Bakiev Date: Mon, 9 Mar 2026 11:20:34 +0700 Subject: [PATCH] Switch from Infisical to Vault for secret loading --- Dockerfile | 8 +++--- scripts/load-vault-env.sh | 60 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 64 insertions(+), 4 deletions(-) create mode 100755 scripts/load-vault-env.sh diff --git a/Dockerfile b/Dockerfile index 81f159c..2be353d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -11,16 +11,16 @@ RUN npm run build FROM node:22-alpine +RUN apk add --no-cache curl jq + WORKDIR /app COPY package.json ./ -RUN npm install --omit=dev && npm install @infisical/sdk +RUN npm install --omit=dev COPY --from=builder /app/dist ./dist COPY scripts ./scripts -ENV INFISICAL_SECRET_PATHS="/geo,/shared" - EXPOSE 8000 -CMD ["sh", "-c", "node scripts/load-secrets.mjs && . ./.env.infisical && node dist/index.js"] +CMD ["sh", "-c", ". /app/scripts/load-vault-env.sh && node dist/index.js"] diff --git a/scripts/load-vault-env.sh b/scripts/load-vault-env.sh new file mode 100755 index 0000000..086c1e8 --- /dev/null +++ b/scripts/load-vault-env.sh @@ -0,0 +1,60 @@ +#!/bin/sh +set -eu + +log() { + printf '%s\n' "$*" >&2 +} + +VAULT_ENABLED="${VAULT_ENABLED:-auto}" +if [ "$VAULT_ENABLED" = "false" ] || [ "$VAULT_ENABLED" = "0" ]; then + exit 0 +fi + +if [ -z "${VAULT_ADDR:-}" ] || [ -z "${VAULT_TOKEN:-}" ]; then + if [ "$VAULT_ENABLED" = "true" ] || [ "$VAULT_ENABLED" = "1" ]; then + log "Vault bootstrap is required but VAULT_ADDR or VAULT_TOKEN is missing." + exit 1 + fi + exit 0 +fi + +if ! command -v curl >/dev/null 2>&1 || ! command -v jq >/dev/null 2>&1; then + log "Vault bootstrap requires curl and jq." + exit 1 +fi + +VAULT_KV_MOUNT="${VAULT_KV_MOUNT:-secret}" + +load_secret_path() { + path="$1" + source_name="$2" + if [ -z "$path" ]; then + return 0 + fi + + url="${VAULT_ADDR%/}/v1/${VAULT_KV_MOUNT}/data/${path}" + response="$(curl -fsS -H "X-Vault-Token: $VAULT_TOKEN" "$url")" || { + log "Failed to load Vault path ${VAULT_KV_MOUNT}/${path}." + return 1 + } + + encoded_items="$(printf '%s' "$response" | jq -r '.data.data // {} | to_entries[]? | @base64')" + if [ -z "$encoded_items" ]; then + return 0 + fi + + old_ifs="${IFS}" + IFS=' +' + for encoded_item in $encoded_items; do + key="$(printf '%s' "$encoded_item" | base64 -d | jq -r '.key')" + value="$(printf '%s' "$encoded_item" | base64 -d | jq -r '.value | tostring')" + export "$key=$value" + done + IFS="${old_ifs}" + + log "Loaded Vault ${source_name} secrets from ${VAULT_KV_MOUNT}/${path}." +} + +load_secret_path "${VAULT_SHARED_PATH:-}" "shared" +load_secret_path "${VAULT_PROJECT_PATH:-}" "project"