Files
FTStore/web/Dockerfile
T
Felitendo d749462782 fix(web): get the signing binary to compile in the app image
Two things stopped it. minizip's headers open with an include of zlib.h and
libminizip-dev does not bring the zlib headers with it, so the archive code
would not compile — zlib1g-dev now covers that.

The second is upstream drift. Zsign is maintained as a Swift package, and its
command line entry point was left behind when the signing call grew another
parameter, so the linux target does not build at the commit the submodule is
pinned to. The build supplies the argument instead of moving the pin: the app
and the manager share that pin, and moving it would change what they sign with
on a device in order to fix a server build. The value matches what the apps
send by default, which keeps the provisioning profile sealed into the
signature — an over-the-air install is refused without it.
2026-08-05 09:16:57 +02:00

107 lines
4.0 KiB
Docker

# NOTE: this image builds from the **repository root**, not from `web/`.
# The landing page's install endpoint signs with zsign, and zsign is built here
# from the monorepo's own `manager/Zsign` sources, so the server signs with
# exactly the code the Manager signs with on-device. `Dockerfile.worker` still
# builds from `web/` — the worker never signs anything.
#
# Stage 0: zsign
#
# bookworm-slim on purpose: node:20-slim is bookworm too, so the binary links
# against the same libssl3/libminizip1 the runner installs.
FROM debian:bookworm-slim AS zsign
# zlib1g-dev is not redundant: minizip's own headers open with `#include
# "zlib.h"` and libminizip-dev does not pull the zlib headers in behind it.
RUN apt-get update && apt-get install -y --no-install-recommends \
g++ make pkg-config libssl-dev libminizip-dev zlib1g-dev \
&& rm -rf /var/lib/apt/lists/*
WORKDIR /src
COPY manager/Zsign ./Zsign
# Upstream maintains the Swift package, not this CLI. `ZBundle::SignFolder`
# grew a tenth parameter, `src/zsign.mm` was updated for it and `src/zsign.cpp`
# was not, so `build/linux` does not compile at the commit the submodule is
# pinned to. The argument is supplied here rather than by moving the pin:
# ios/Zsign and manager/Zsign sit at the same commit, and moving it would change
# what both apps sign with on-device to fix a server build.
#
# The parameter reads backwards — `true` is what *writes* embedded.mobileprovision
# and seals it into the signature, `false` strips it. `true` is therefore the
# value to pass: it is what the apps send by default (ZsignHandler passes
# `removeProvision: !options.removeProvisioning`), and an over-the-air install
# is refused without the profile.
#
# The grep is a tripwire, not decoration. If a later submodule bump fixes the
# call site, this stops the build instead of letting a stale edit through.
RUN grep -q 'bWeakInject, bEnableCache);' Zsign/src/zsign.cpp && \
sed -i 's/bWeakInject, bEnableCache);/bWeakInject, bEnableCache, true);/' \
Zsign/src/zsign.cpp
# The Makefile writes to ../../bin/zsign, relative to build/linux.
RUN make -C Zsign/build/linux -j"$(nproc)"
# Stage 1: Dependencies
FROM node:20-slim AS deps
WORKDIR /app
COPY web/package.json web/package-lock.json ./
RUN npm ci --ignore-scripts
COPY web/prisma ./prisma/
RUN npx prisma generate
# Stage 2: Build
FROM node:20-slim AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY web/ .
ENV NEXT_TELEMETRY_DISABLED=1
ENV NODE_ENV=production
RUN npm run build
# Stage 3: Runner
FROM node:20-slim AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
ENV PORT=3000
ENV ZSIGN_PATH=/usr/local/bin/zsign
# libminizip1 is zsign's only runtime dependency beyond libssl3, which the
# openssl package already pulls in.
RUN apt-get update && apt-get install -y --no-install-recommends \
openssl \
libminizip1 \
&& rm -rf /var/lib/apt/lists/* && \
addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=zsign /src/Zsign/bin/zsign /usr/local/bin/zsign
COPY --from=builder /app/public ./public
COPY --from=builder /app/.next/standalone ./
COPY --from=builder /app/.next/static ./.next/static
COPY --from=builder /app/prisma ./prisma
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/scripts ./scripts
# /app/storage holds the IPA files and tweak icons and is shared with the
# worker. NOTE: a bind mount there shadows this directory, so the host path must
# already be owned by uid/gid 1001 — the build-time chown does not reach it.
#
# storage/install is the landing page's signing scratch: signed builds waiting
# for an `itms-services://` prompt to collect them, swept on a short expiry.
RUN mkdir -p /app/tdlib-data/db /app/tdlib-data/files \
/app/storage/ipa /app/storage/icons /app/storage/tmp \
/app/storage/install \
/tmp/ftstore && \
chown -R nextjs:nodejs /app /tmp/ftstore
USER nextjs
EXPOSE 3000
CMD ["sh", "-c", "node node_modules/prisma/build/index.js db push --skip-generate && node server.js"]