ARG POSTHOG_HOST=https://app.posthog.com ARG POSTHOG_API_KEY=posthog-api-key ARG INTERCOM_ID=intercom-id ARG CAPTCHA_SITE_KEY=captcha-site-key FROM node:20.19.5-trixie-slim AS base # Fixes NPM vulnerability: https://security.snyk.io/vuln/SNYK-JS-CROSSSPAWN-8303230 RUN npm install -g npm@10.9.0 FROM base AS frontend-dependencies WORKDIR /app COPY frontend/package.json frontend/package-lock.json ./ # Install dependencies RUN npm ci --only-production --ignore-scripts # Rebuild the source code only when needed FROM base AS frontend-builder WORKDIR /app # Copy dependencies COPY --from=frontend-dependencies /app/node_modules ./node_modules # Copy all files COPY /frontend . ENV NODE_ENV production ARG POSTHOG_HOST ENV VITE_POSTHOG_HOST $POSTHOG_HOST ARG POSTHOG_API_KEY ENV VITE_POSTHOG_API_KEY $POSTHOG_API_KEY ARG INTERCOM_ID ENV VITE_INTERCOM_ID $INTERCOM_ID ARG INFISICAL_PLATFORM_VERSION ENV VITE_INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION ARG CAPTCHA_SITE_KEY ENV VITE_CAPTCHA_SITE_KEY $CAPTCHA_SITE_KEY ENV NODE_OPTIONS="--max-old-space-size=8192" # Build RUN npm run build # Production image FROM base AS frontend-runner WORKDIR /app RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user COPY --from=frontend-builder --chown=non-root-user:nodejs /app/dist ./ USER non-root-user ## ## BACKEND ## FROM base AS backend-build ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/ RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user WORKDIR /app # Required for pkcs11js and ODBC RUN apt-get update && apt-get install -y \ python3 \ make \ g++ \ unixodbc \ unixodbc-dev \ freetds-dev \ freetds-bin \ tdsodbc \ && rm -rf /var/lib/apt/lists/* # Configure ODBC RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini COPY backend/package*.json ./ RUN npm ci --only-production COPY /backend . COPY --chown=non-root-user:nodejs standalone-entrypoint.sh standalone-entrypoint.sh RUN npm i -D tsconfig-paths RUN npm run build # Production stage FROM base AS backend-runner ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/ WORKDIR /app # Required for pkcs11js and ODBC RUN apt-get update && apt-get install -y \ python3 \ make \ g++ \ unixodbc \ unixodbc-dev \ freetds-dev \ freetds-bin \ tdsodbc \ && rm -rf /var/lib/apt/lists/* # Configure ODBC RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini COPY backend/package*.json ./ RUN npm ci --only-production COPY --from=backend-build /app . RUN mkdir frontend-build # Production stage FROM base AS production # Install necessary packages including ODBC RUN apt-get update && apt-get install -y \ build-essential \ autoconf \ automake \ libtool \ wget \ libssl-dev \ ca-certificates \ curl \ git \ python3 \ make \ g++ \ unixodbc \ unixodbc-dev \ freetds-dev \ freetds-bin \ tdsodbc \ openssh-client \ && rm -rf /var/lib/apt/lists/* # Configure ODBC in production RUN printf "[FreeTDS]\nDescription = FreeTDS Driver\nDriver = /usr/lib/x86_64-linux-gnu/odbc/libtdsodbc.so\nSetup = /usr/lib/x86_64-linux-gnu/odbc/libtdsS.so\nFileUsage = 1\n" > /etc/odbcinst.ini WORKDIR /openssl-build RUN wget https://www.openssl.org/source/openssl-3.1.2.tar.gz \ && tar -xf openssl-3.1.2.tar.gz \ && cd openssl-3.1.2 \ && ./Configure enable-fips \ && make \ && make install_fips \ && cd / \ && rm -rf /openssl-build \ && apt-get clean \ && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # Install Infisical CLI RUN curl -1sLf 'https://artifacts-cli.infisical.com/setup.deb.sh' | bash \ && apt-get update && apt-get install -y infisical=0.43.14 \ && rm -rf /var/lib/apt/lists/* RUN groupadd -r -g 1001 nodejs && useradd -r -u 1001 -g nodejs non-root-user # Give non-root-user permission to update SSL certs RUN chown -R non-root-user /etc/ssl/certs RUN chown non-root-user /etc/ssl/certs/ca-certificates.crt RUN chmod -R u+rwx /etc/ssl/certs RUN chmod u+rw /etc/ssl/certs/ca-certificates.crt RUN chown non-root-user /usr/sbin/update-ca-certificates RUN chmod u+rx /usr/sbin/update-ca-certificates ## set pre baked keys ARG POSTHOG_API_KEY ENV POSTHOG_API_KEY=$POSTHOG_API_KEY ARG INTERCOM_ID=intercom-id ENV INTERCOM_ID=$INTERCOM_ID ARG CAPTCHA_SITE_KEY ENV CAPTCHA_SITE_KEY=$CAPTCHA_SITE_KEY WORKDIR / COPY --from=backend-runner /app /backend COPY --from=frontend-runner /app ./backend/frontend-build # Make export-assets script executable for CDN asset extraction RUN chmod +x /backend/scripts/export-assets.sh ARG INFISICAL_PLATFORM_VERSION ENV INFISICAL_PLATFORM_VERSION $INFISICAL_PLATFORM_VERSION ENV PORT 8080 ENV HOST=0.0.0.0 ENV HTTPS_ENABLED false ENV NODE_ENV production ENV STANDALONE_BUILD true ENV STANDALONE_MODE true ENV ChrystokiConfigurationPath=/usr/safenet/lunaclient/ ENV NODE_OPTIONS="--max-old-space-size=8192 --force-fips" # FIPS mode of operation: ENV OPENSSL_CONF=/backend/nodejs.fips.cnf ENV OPENSSL_MODULES=/usr/local/lib/ossl-modules ENV FIPS_ENABLED=true WORKDIR /backend ENV TELEMETRY_ENABLED true EXPOSE 8080 EXPOSE 443 # Remove telemetry. dd-trace uses BullMQ with MD5 hashing, which breaks when FIPS mode is enabled. RUN grep -v 'import "./lib/telemetry/instrumentation.mjs";' dist/main.mjs > dist/main.mjs.tmp && \ mv dist/main.mjs.tmp dist/main.mjs # The OpenSSL library is installed in different locations in different architectures (x86_64 and arm64). # This is a workaround to avoid errors when the library is not found. RUN ln -sf /usr/local/lib64/ossl-modules /usr/local/lib/ossl-modules || \ ln -sf /usr/local/lib/ossl-modules /usr/local/lib64/ossl-modules USER non-root-user CMD ["./standalone-entrypoint.sh"]