Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
39 changes: 33 additions & 6 deletions apps/admin/Dockerfile.admin
Original file line number Diff line number Diff line change
Expand Up @@ -77,15 +77,42 @@ RUN pnpm turbo run build --filter=admin
# STAGE 3: Serve with Caddy
# *****************************************************************************

FROM caddy:2.11-builder-alpine AS caddy-builder
FROM caddy:2.11.4-builder-alpine AS caddy-builder

RUN xcaddy build \
RUN XCADDY_SKIP_CLEANUP=1 xcaddy build \
--with github.com/mholt/caddy-ratelimit

FROM caddy:2.11-alpine AS production

# curl is required by the HEALTHCHECK below and is not present in the base image
RUN apk update && apk upgrade --no-cache && apk add --no-cache curl && rm -rf /var/cache/apk/*
# Caddy's own go.mod pins x/crypto, x/net and x/text at versions with open CVEs
# (CVE-2026-56854 CRITICAL in x/crypto, CVE-2026-46600 in x/net,
# CVE-2026-56852 in x/text), so every xcaddy build re-ships them. xcaddy
# preserved its build dir above, so upgrade them there and rebuild.
# x/crypto v0.55.0 requires x/net v0.57.0 and x/text v0.41.0, hence those floors.
# grpc and otel move together: grpc >= v1.83.0 requires otel v1.44.0, so bump
# the otel pair in lockstep or go walks grpc backwards to satisfy the older one.
RUN cd "$(find /tmp -maxdepth 1 -name 'buildenv_*' -type d | head -1)" && \
go get golang.org/x/crypto@v0.55.0 && \
go get golang.org/x/net@v0.57.0 && \
go get golang.org/x/text@v0.41.0 && \
go get google.golang.org/grpc@v1.83.1 && \
go get go.opentelemetry.io/otel@v1.44.0 && \
go get go.opentelemetry.io/otel/sdk@v1.44.0 && \
go mod tidy && \
go build -o /usr/bin/caddy -ldflags "-w -s" -trimpath .

# `go get` resolves a module backwards rather than failing when pins conflict,
# so assert the binary really carries the pinned grpc: a silent downgrade must
# fail the build instead of shipping a caddy that only looks patched.
RUN go version -m /usr/bin/caddy | grep -qE 'google\.golang\.org/grpc[[:space:]]v1\.83\.1[[:space:]]' \
|| { echo "caddy was not built against the pinned grpc -- check the go get floors" >&2; exit 1; }

FROM caddy:2.11.4-alpine AS production

# curl is required by the HEALTHCHECK below and is not present in the base image.
# OS security updates too: --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available && apk add --no-cache curl && rm -rf /var/cache/apk/*

COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy

Expand Down
13 changes: 8 additions & 5 deletions apps/api/Dockerfile.api
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
FROM python:3.12.10-alpine
FROM python:3.12.12-alpine

# set environment variables
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
ENV PIP_DISABLE_PIP_VERSION_CHECK=1
ENV INSTANCE_CHANGELOG_URL=https://sites.plane.so/pages/691ef037bcfe416a902e48cb55f59891/

# Update system packages for security
RUN apk update && apk upgrade
# OS security updates. --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --available

WORKDIR /code

Expand All @@ -22,7 +25,7 @@ COPY requirements.txt ./
COPY requirements ./requirements
RUN apk add --no-cache libffi-dev
RUN apk add --no-cache --virtual .build-deps \
"bash~=5.2" \
"bash~=5.3" \
"g++" \
"gcc" \
"cargo" \
Expand All @@ -45,7 +48,7 @@ COPY plane plane/
COPY templates templates/
COPY package.json package.json

RUN apk --no-cache add "bash~=5.2"
RUN apk --no-cache add "bash~=5.3"
COPY ./bin ./bin/

RUN mkdir -p /code/plane/logs
Expand Down
13 changes: 11 additions & 2 deletions apps/live/Dockerfile.live
Original file line number Diff line number Diff line change
Expand Up @@ -54,11 +54,20 @@ RUN pnpm turbo run build --filter=live
FROM base AS runner
WORKDIR /app

# OS security updates. --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available

# Remove go from Alpine APK database; not needed at runtime and carries stdlib CVEs
RUN apk del go 2>/dev/null || true

# Remove vulnerable picomatch bundled inside npm (CVE-2026-33671); npm is not used at runtime
RUN rm -rf /usr/local/lib/node_modules/npm/node_modules/picomatch
# npm is not used at runtime (CMD is plain node); its bundled dependencies carry
# known vulnerabilities (tar, brace-expansion, pacote, sigstore, ip-address,
# fast-uri, browserslist), so remove the whole CLI rather than picking off one
# package at a time.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx

COPY --from=installer /app/packages ./packages
COPY --from=installer /app/apps/live/dist ./apps/live/dist
Expand Down
40 changes: 33 additions & 7 deletions apps/proxy/Dockerfile.ce
Original file line number Diff line number Diff line change
@@ -1,18 +1,44 @@
FROM caddy:2.11.3-builder-alpine AS caddy-builder
FROM caddy:2.11.4-builder-alpine AS caddy-builder

RUN xcaddy build \
# grpc and otel move together: grpc >= v1.83.0 requires otel v1.44.0, and xcaddy
# resolves these --with pins in one `go get`, so a stale otel pin makes go walk
# grpc backwards until it finds one that fits (silently, with a zero exit) --
# it lands on the v1.83.0-dev pre-release and the build still succeeds. Bump the
# otel pair in lockstep with grpc, and confirm with `go version -m` afterwards.
RUN XCADDY_SKIP_CLEANUP=1 xcaddy build \
--with github.com/caddy-dns/cloudflare@v0.2.1 \
--with github.com/caddy-dns/digitalocean@04bde2867106aa1b44c2f9da41a285fa02e629c5 \
--with github.com/mholt/caddy-l4@6faae83b167fda94e62b686be5cbeb9b3f8fe002 \
--with github.com/go-jose/go-jose/v3@v3.0.5 \
--with github.com/go-jose/go-jose/v4@v4.1.4 \
--with google.golang.org/grpc@v1.80.0 \
--with go.opentelemetry.io/otel@v1.43.0 \
--with go.opentelemetry.io/otel/sdk@v1.43.0
--with google.golang.org/grpc@v1.83.1 \
--with go.opentelemetry.io/otel@v1.44.0 \
--with go.opentelemetry.io/otel/sdk@v1.44.0

FROM caddy:2.11.3-alpine
# Caddy's own go.mod pins x/crypto, x/net and x/text at versions with open CVEs;
# xcaddy preserved its build dir above, so upgrade them there and rebuild.
# x/crypto v0.55.0 requires x/net v0.57.0 and x/text v0.41.0, hence those floors.
RUN cd "$(find /tmp -maxdepth 1 -name 'buildenv_*' -type d | head -1)" && \
go get golang.org/x/crypto@v0.55.0 && \
go get golang.org/x/net@v0.57.0 && \
go get golang.org/x/text@v0.41.0 && \
go mod tidy && \
go build -o /usr/bin/caddy -ldflags "-w -s" -trimpath -tags nobadger,nomysql,nopgx .

RUN apk update && apk upgrade --no-cache && apk add --no-cache nss-tools bash curl
# xcaddy resolves every --with pin in a single `go get`, which walks a module
# backwards to an older release rather than failing when the pins conflict.
# Assert the binary really carries the pinned grpc, so a silent downgrade fails
# the build instead of shipping a proxy that only looks patched.
RUN go version -m /usr/bin/caddy | grep -qE 'google\.golang\.org/grpc[[:space:]]v1\.83\.1[[:space:]]' \
|| { echo "caddy was not built against the pinned grpc -- check the --with pins" >&2; exit 1; }

FROM caddy:2.11.4-alpine

# OS security updates. --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available && apk add --no-cache nss-tools bash curl

COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy

Expand Down
17 changes: 13 additions & 4 deletions apps/space/Dockerfile.space
Original file line number Diff line number Diff line change
Expand Up @@ -80,12 +80,21 @@ FROM base AS runner

ENV NODE_ENV=production

# OS security updates. --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available

# Remove go from Alpine APK database; not needed at runtime and carries stdlib CVEs
RUN apk del go 2>/dev/null || true

# Remove vulnerable picomatch bundled inside npm (CVE-2026-33671)
# npx only needs picomatch when installing packages, not when running a locally-installed binary
RUN rm -rf /usr/local/lib/node_modules/npm/node_modules/picomatch
# npm is not used at runtime (the CMD execs the react-router-serve bin shim
# directly rather than going through npx); its bundled dependencies carry known
# vulnerabilities (tar, brace-expansion, pacote, sigstore, ip-address, fast-uri,
# browserslist), so remove the whole CLI rather than picking off one package at
# a time.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx

COPY --from=installer /app/apps/space/build ./apps/space/build
COPY --from=installer /app/apps/space/node_modules ./apps/space/node_modules
Expand All @@ -102,4 +111,4 @@ RUN apk add --no-cache curl
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -fsS http://127.0.0.1:3000/spaces/ >/dev/null || exit 1

CMD ["npx", "react-router-serve", "./build/server/index.js"]
CMD ["./node_modules/.bin/react-router-serve", "./build/server/index.js"]
39 changes: 33 additions & 6 deletions apps/web/Dockerfile.web
Original file line number Diff line number Diff line change
Expand Up @@ -75,15 +75,42 @@ RUN pnpm turbo run build --filter=web
# *****************************************************************************
# STAGE 3: Serve with Caddy
# *****************************************************************************
FROM caddy:2.11-builder-alpine AS caddy-builder
FROM caddy:2.11.4-builder-alpine AS caddy-builder

RUN xcaddy build \
RUN XCADDY_SKIP_CLEANUP=1 xcaddy build \
--with github.com/mholt/caddy-ratelimit

FROM caddy:2.11-alpine AS production

# curl is required by the HEALTHCHECK below and is not present in the base image
RUN apk update && apk upgrade --no-cache && apk add --no-cache curl && rm -rf /var/cache/apk/*
# Caddy's own go.mod pins x/crypto, x/net and x/text at versions with open CVEs
# (CVE-2026-56854 CRITICAL in x/crypto, CVE-2026-46600 in x/net,
# CVE-2026-56852 in x/text), so every xcaddy build re-ships them. xcaddy
# preserved its build dir above, so upgrade them there and rebuild.
# x/crypto v0.55.0 requires x/net v0.57.0 and x/text v0.41.0, hence those floors.
# grpc and otel move together: grpc >= v1.83.0 requires otel v1.44.0, so bump
# the otel pair in lockstep or go walks grpc backwards to satisfy the older one.
RUN cd "$(find /tmp -maxdepth 1 -name 'buildenv_*' -type d | head -1)" && \
go get golang.org/x/crypto@v0.55.0 && \
go get golang.org/x/net@v0.57.0 && \
go get golang.org/x/text@v0.41.0 && \
go get google.golang.org/grpc@v1.83.1 && \
go get go.opentelemetry.io/otel@v1.44.0 && \
go get go.opentelemetry.io/otel/sdk@v1.44.0 && \
go mod tidy && \
go build -o /usr/bin/caddy -ldflags "-w -s" -trimpath .

# `go get` resolves a module backwards rather than failing when pins conflict,
# so assert the binary really carries the pinned grpc: a silent downgrade must
# fail the build instead of shipping a caddy that only looks patched.
RUN go version -m /usr/bin/caddy | grep -qE 'google\.golang\.org/grpc[[:space:]]v1\.83\.1[[:space:]]' \
|| { echo "caddy was not built against the pinned grpc -- check the go get floors" >&2; exit 1; }

FROM caddy:2.11.4-alpine AS production

# curl is required by the HEALTHCHECK below and is not present in the base image.
# OS security updates too: --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available && apk add --no-cache curl && rm -rf /var/cache/apk/*

COPY --from=caddy-builder /usr/bin/caddy /usr/bin/caddy

Expand Down
33 changes: 29 additions & 4 deletions deployments/aio/community/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -16,21 +16,48 @@ FROM makeplane/plane-proxy:${PLANE_VERSION} AS proxy-img
# **************************************************
# STAGE 1: Runner
# **************************************************
FROM python:3.12.10-alpine AS runner
FROM python:3.12.12-alpine AS runner

WORKDIR /app

# OS security updates. --available forces reinstall from the current repos;
# bump APK_SECURITY_PATCH to bust buildx's cached layer (keyed on this command
# string), otherwise a rebuild silently re-ships the old packages.
ARG APK_SECURITY_PATCH=2026-09-07
RUN echo "apk-security-patch ${APK_SECURITY_PATCH}" && apk update && apk upgrade --no-cache --available

# All apk work must happen BEFORE the `COPY --from=node /usr/lib` below: that
# copy overwrites /usr/lib/libapk.so.* with node:22-alpine's copy, which is a
# different Alpine release, leaving /sbin/apk linked against a libapk that no
# longer exports the symbols it needs. Every later apk call then dies with
# "Error relocating /sbin/apk: ... symbol not found" (exit 127), and apk cannot
# repair itself because apk is the broken binary. So the runtime tools that used
# to be installed further down are folded in here.
RUN apk add --no-cache \
"libpq" \
"libxslt" \
"xmlsec"
"xmlsec" \
"nss-tools" \
"bash" \
"curl" \
"uuidgen" \
"ncdu" \
"vim"


COPY --from=node /usr/lib /usr/lib
COPY --from=node /usr/local/lib /usr/local/lib
COPY --from=node /usr/local/include /usr/local/include
COPY --from=node /usr/local/bin /usr/local/bin

# The copy above re-introduces node:22-alpine's npm, whose bundled dependencies
# carry known vulnerabilities (pacote, ip-address, brace-expansion, tar,
# sigstore) -- the per-service images strip npm, so without this the AIO is the
# only place they come back. npm is not needed at runtime: the space program in
# supervisor.conf execs its react-router-serve bin shim directly rather than
# going through npx.
RUN rm -rf /usr/local/lib/node_modules/npm /usr/local/bin/npm /usr/local/bin/npx

COPY --from=web-img /usr/share/caddy/html /app/web
COPY --from=space-img /app /app/space
COPY --from=admin-img /usr/share/caddy/html/god-mode /app/admin
Expand All @@ -45,8 +72,6 @@ COPY --from=backend-img /code /app/backend
COPY --from=backend-img /usr/local/lib/python3.12/site-packages/ /usr/local/lib/python3.12/site-packages/
COPY --from=backend-img /usr/local/bin/ /usr/local/bin/

RUN apk add --no-cache nss-tools bash curl uuidgen ncdu vim

RUN pip install supervisor
RUN mkdir -p /etc/supervisor/conf.d

Expand Down
2 changes: 1 addition & 1 deletion deployments/aio/community/supervisor.conf
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ priority=10

[program:space]
directory=/app/space/apps/space
command=sh -c "npx react-router-serve ./build/server/index.js"
command=sh -c "./node_modules/.bin/react-router-serve ./build/server/index.js"
autostart=true
autorestart=true
stdout_logfile=/app/logs/access/space.log
Expand Down
Loading
Loading