FROM node:22-alpine AS build WORKDIR /app # Native modules (better-sqlite3, ssh2, node-pty) need a toolchain to compile. RUN apk add --no-cache python3 make g++ COPY package.json package-lock.json* ./ RUN npm install --omit=dev=false COPY . . RUN npm run build FROM node:22-alpine WORKDIR /app ENV NODE_ENV=production # Toolchain is needed again here: production deps are reinstalled fresh, and the # native modules (better-sqlite3, ssh2, node-pty) compile from source on install. # openssh-client provides the `ssh` binary, which node-pty shells out to for # certificate-based auth (ssh2 has no OpenSSH certificate support). RUN apk add --no-cache python3 make g++ openssh-client COPY package.json package-lock.json* ./ RUN npm install --omit=dev COPY --from=build /app/dist ./dist # Old-format encrypted PEM keys (e.g. "BEGIN RSA PRIVATE KEY" + DEK-Info) rely on an # MD5-based KDF that OpenSSL 3's default provider disables. Enable the legacy provider # so `ssh` (used for certificate-based auth) can still decrypt these keys. RUN { \ echo 'openssl_conf = openssl_init'; \ echo ''; \ echo '[openssl_init]'; \ echo 'providers = provider_sect'; \ echo ''; \ echo '[provider_sect]'; \ echo 'default = default_sect'; \ echo 'legacy = legacy_sect'; \ echo ''; \ echo '[default_sect]'; \ echo 'activate = 1'; \ echo ''; \ echo '[legacy_sect]'; \ echo 'activate = 1'; \ } > /etc/ssl/openssl-legacy.cnf ENV OPENSSL_CONF=/etc/ssl/openssl-legacy.cnf EXPOSE 4000 CMD ["node", "dist/server.js"]