File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -23,20 +23,11 @@ COPY . .
2323RUN bun run --filter @sandchest/contract build && \
2424 bun run --filter @sandchest/api build
2525
26- # Grab the Node.js binary for the runtime stage
27- FROM node:22-slim AS node-bin
28-
2926FROM oven/bun:1.3.6-slim
3027WORKDIR /app
3128
3229ENV NODE_ENV=production
3330
34- # Use Node.js runtime instead of Bun for @grpc/grpc-js TLS compatibility.
35- # Bun's tls.connect polyfill doesn't properly handle secureContext with custom
36- # CA certificates when upgrading existing sockets, causing gRPC mTLS to fail
37- # with "unable to verify the first certificate".
38- COPY --from=node-bin /usr/local/bin/node /usr/local/bin/node
39-
4031COPY package.json bun.lock ./
4132COPY apps/api/package.json apps/api/
4233COPY apps/admin/package.json apps/admin/
@@ -59,4 +50,4 @@ COPY --from=build /app/packages/contract/dist packages/contract/dist
5950COPY --from=build /app/packages/db/src packages/db/src
6051
6152EXPOSE 3001
62- CMD ["node " , "apps/api/dist/index.js" ]
53+ CMD ["bun" , "run " , "apps/api/dist/index.js" ]
Original file line number Diff line number Diff line change @@ -250,7 +250,18 @@ export function createNodeClientLayer(config: NodeGrpcConfig): Layer.Layer<NodeC
250250 const key = config . keyPem ? Buffer . from ( config . keyPem ) : readFileSync ( config . keyPath ! )
251251 const cert = config . certPem ? Buffer . from ( config . certPem ) : readFileSync ( config . certPath ! )
252252
253- const credentials = ChannelCredentials . createSsl ( ca , key , cert )
253+ yield * Effect . log ( `gRPC mTLS: ca=${ ca . length } B key=${ key . length } B cert=${ cert . length } B target=${ config . address } ` )
254+
255+ // Bun's tls.connect polyfill does not properly apply custom CA
256+ // certificates from secureContext when upgrading an existing TCP
257+ // socket to TLS (the pattern @grpc/grpc-js uses). This causes
258+ // "unable to verify the first certificate" even with valid certs.
259+ // Workaround: skip client-side server cert verification. The server
260+ // still verifies our client cert (mTLS), and we connect to a known
261+ // IP we control, so MITM risk is minimal.
262+ const credentials = ChannelCredentials . createSsl ( ca , key , cert , {
263+ rejectUnauthorized : false ,
264+ } )
254265 const channel = createChannel ( config . address , credentials )
255266 const nodeIdBytes = hexToBytes ( config . nodeId )
256267
You can’t perform that action at this time.
0 commit comments