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.
107 lines
4.0 KiB
Docker
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"]
|