diff --git a/Dockerfile b/Dockerfile index 509f07b..37ea406 100644 --- a/Dockerfile +++ b/Dockerfile @@ -23,6 +23,17 @@ ENV NEXT_TELEMETRY_DISABLED 1 RUN npm run build +# Download Bitwarden Secrets Manager CLI +FROM base AS bws +ARG BWS_VERSION=2.1.0 +ARG BWS_ARCH=x86_64-unknown-linux-musl +RUN apk add --no-cache curl unzip +RUN curl -fsSL "https://github.com/bitwarden/sdk-sm/releases/download/bws-v${BWS_VERSION}/bws-${BWS_ARCH}-${BWS_VERSION}.zip" -o /tmp/bws.zip && \ + mkdir -p /tmp/bws-extract && \ + unzip -q /tmp/bws.zip -d /tmp/bws-extract && \ + find /tmp/bws-extract -type f -name bws -exec chmod +x {} \; -exec cp {} /usr/local/bin/bws \; && \ + /usr/local/bin/bws --version + # Production image, copy all the files and run next FROM base AS runner WORKDIR /app @@ -44,6 +55,20 @@ RUN chown nextjs:nodejs .next COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./ COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static +# Copy Bitwarden Secrets Manager CLI and entrypoint +COPY --from=bws /usr/local/bin/bws /usr/local/bin/bws +COPY docker-entrypoint.sh /app/docker-entrypoint.sh +RUN chmod +x /app/docker-entrypoint.sh + +# bws config/state directory (writable by nextjs) +# server_base is required as of bws 2.x — the profile errors with +# "Profile has no `server_base` or `server_identity`" without it, even +# for the default Bitwarden cloud instance. +RUN mkdir -p /app/.config/bws && chown -R nextjs:nodejs /app/.config/bws && \ + printf '[profiles.default]\nserver_base = "https://vault.bitwarden.com"\nstate_dir = "/app/.config/bws/state"\n' > /app/.config/bws/config && \ + chown nextjs:nodejs /app/.config/bws/config +ENV BWS_CONFIG_FILE=/app/.config/bws/config + USER nextjs # Use custom port 3100 instead of 3000 @@ -52,4 +77,4 @@ EXPOSE 3100 ENV PORT 3100 ENV HOSTNAME "0.0.0.0" -CMD ["node", "server.js"] +CMD ["/app/docker-entrypoint.sh"] diff --git a/docker-compose.yml b/docker-compose.yml index 6ab9d2b..dd07d0c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -142,6 +142,13 @@ services: POSTGRES_USER: ${POSTGRES_USER:-pulse_user} POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-your_secure_password_here_change_in_production} DATABASE_URL: postgresql://${POSTGRES_USER:-pulse_user}:${POSTGRES_PASSWORD:-your_secure_password_here_change_in_production}@postgres:5432/${POSTGRES_DB:-pulse_autotask} + + # Bitwarden Secrets Manager (optional) — deliberately NOT re-declared here. + # env_file: .env.local already injects BWS_ACCESS_TOKEN/BWS_PROJECT_ID directly. + # Re-declaring them as ${VAR:-} substitutions resolves against the root .env / + # shell env (not .env.local), which clobbers the real value with an empty string + # when the var isn't also present in root .env — as it correctly isn't here, + # since BWS_ACCESS_TOKEN is a live secret that must never land in the committed .env. depends_on: redis: condition: service_healthy diff --git a/docker-entrypoint.sh b/docker-entrypoint.sh new file mode 100644 index 0000000..619444e --- /dev/null +++ b/docker-entrypoint.sh @@ -0,0 +1,10 @@ +#!/bin/sh +set -e + +if [ -n "${BWS_ACCESS_TOKEN:-}" ]; then + echo "Loading secrets from Bitwarden Secrets Manager..." + exec bws run ${BWS_PROJECT_ID:+--project-id "${BWS_PROJECT_ID}"} -- node server.js +fi + +echo "BWS_ACCESS_TOKEN not set; starting without Bitwarden secrets." +exec node server.js