fix(helper): verify download checksums and update bundled tools

Pin every helper download by SHA256 and the base images by digest, drop
the curl | bash installers, and add scripts/helper-checksums to refresh
the checksums. Update Alpine to 3.24, Docker CLI 29.9.2, Compose 5.6.1,
Buildx 0.38.1, pack 0.40.10, Railpack 0.43.0, and mise 2026.10.14.
Bump the helper to 1.0.19.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras BacsaiandClaude Opus 5.5 committed 2026-10-24 23:19:08 +02:00
1 parent 547bdc3bf4
commit 1e4431f53d
5 files changed
+148 -43

No files matched your search

+2
View File
@@ -230,6 +230,8 @@ To build and run Coolify locally, see: [Development](./DEVELOPMENT.md)
### Testing the Coolify Helper Locally
When you change a tool version in `docker/coolify-helper/Dockerfile`, run `./scripts/helper-checksums` to update the SHA256 checksums of the downloads.
Use `scripts/dev-helper` to build a local helper image and test it with the running development instance. The script requires the standard local Coolify container and the seeded Dockerfile, Docker Compose, and Nixpacks applications.
Run the complete workflow:
+2 -2
View File
@@ -6,8 +6,8 @@ $sshCommandTimeout = (int) env('SSH_COMMAND_TIMEOUT', 3600);
return [
'coolify' => [
'version' => env('COOLIFY_VERSION') ?: '4.5.1',
'helper_version' => '1.0.18',
'railpack_version' => '0.40.1',
'helper_version' => '1.0.19',
'railpack_version' => '0.43.0',
'self_hosted' => env('SELF_HOSTED', true),
'autoupdate' => env('AUTOUPDATE'),
'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'),
+58 -40
View File
@@ -1,25 +1,28 @@
# Versions
# https://hub.docker.com/_/alpine
ARG BASE_IMAGE=alpine:3.21
ARG BASE_IMAGE=alpine:3.24@sha256:be2656061b536c1883c4034790e21d0a09c5aaaf51968b89368a3c0371ea2c9a
# https://quay.io/repository/minio/aistor/mc?tab=tags
ARG MINIO_CLIENT_IMAGE=quay.io/minio/aistor/mc:RELEASE.2026-09-19T15-24-59Z@sha256:23511e340cbabf07e6a8b53f9c434975708f22f3c047d6beeddc17bf1a5aed88
# https://download.docker.com/linux/static/stable/
ARG DOCKER_VERSION=29.7.2
ARG DOCKER_VERSION=29.9.2
# https://github.com/docker/compose/releases
ARG DOCKER_COMPOSE_VERSION=5.5.0
ARG DOCKER_COMPOSE_VERSION=5.6.1
# https://github.com/docker/buildx/releases
ARG DOCKER_BUILDX_VERSION=0.36.1
ARG DOCKER_BUILDX_VERSION=0.38.1
# https://github.com/buildpacks/pack/releases
ARG PACK_VERSION=0.38.2
ARG PACK_VERSION=0.40.10
# https://github.com/railwayapp/nixpacks/releases
ARG NIXPACKS_VERSION=1.41.0
# https://github.com/railwayapp/railpack/releases
ARG RAILPACK_VERSION=0.40.1
ARG RAILPACK_VERSION=0.43.0
# https://github.com/jdx/mise/releases — must match the version pinned at that railpack tag (https://raw.githubusercontent.com/railwayapp/railpack/v${RAILPACK_VERSION}/core/mise/version.txt)
ARG MISE_VERSION=2026.9.15
FROM quay.io/minio/aistor/mc:RELEASE.2026-09-06T02-44-40Z AS minio-client
ARG MISE_VERSION=2026.10.14
FROM ${MINIO_CLIENT_IMAGE} AS minio-client
FROM ${BASE_IMAGE} AS base
ARG TARGETPLATFORM
ARG TARGETARCH
ARG DOCKER_VERSION
ARG DOCKER_COMPOSE_VERSION
ARG DOCKER_BUILDX_VERSION
@@ -33,41 +36,56 @@ WORKDIR /artifacts
ENV RAILPACK_VERSION=${RAILPACK_VERSION}
RUN apk upgrade --no-cache && \
apk add --no-cache bash curl git git-lfs openssh-client pigz tar tini
RUN mkdir -p ~/.docker/cli-plugins
SHELL ["/bin/bash", "-euo", "pipefail", "-c"]
# Install mise (musl build) at the path railpack expects (/tmp/railpack/mise/mise-VERSION).
# Railpack skips its own mise download when this file exists.
RUN mkdir -p /tmp/railpack/mise && \
if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \
curl -sSL "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/mise-v${MISE_VERSION}-linux-x64-musl.tar.gz" | tar xz && \
mv mise/bin/mise "/tmp/railpack/mise/mise-${MISE_VERSION}" && rm -rf mise; \
elif [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \
curl -sSL "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/mise-v${MISE_VERSION}-linux-arm64-musl.tar.gz" | tar xz && \
mv mise/bin/mise "/tmp/railpack/mise/mise-${MISE_VERSION}" && rm -rf mise; \
fi
# SHA256 of every download, per architecture. After you change a version above, run scripts/helper-checksums to update them.
COPY <<'EOF' /tmp/SHA256SUMS
9ac225999fd5e863f7694c728ef23d480616b1e5639328fa309befd4243d69eb docker-amd64.tgz
873b3e0207857c3b2f28392fb922f3ea6efe37620c16d4d4aaf2fef409c90b73 docker-arm64.tgz
e25d5cd675092bb5d1d03632fdc46cdf3fede7b514dc5f023a105e00d3ce5ad4 docker-buildx-amd64
3b83b3731916ba433feccaaa689fe5bcdc81c641d92c8e6c2ea865dfa141c97a docker-buildx-arm64
47737f4236e6d3ccea7291995203f8f018058783b4c3a9469119811a0b5db8c0 docker-compose-amd64
42cfa75f51ad0ccf290bad37899e0038a8c10a0069e85233ecc1d53e3ff1347d docker-compose-arm64
b0e388c8014f9ac14a5ddf7a4042b0db28043f7f9ce485ffc2521bff02247f8e mise-amd64
c71eec4d0015f6ced74ac9d5cd755b56674df04e899d0d1566d533c95511ae6c mise-arm64
0f55de7874507b9cf7502113120bd96f2ab6979f78d10eaf2eb2ade9207b3af6 nixpacks-amd64.tgz
912bd02dd2bb6f9c3a9ed965fe8a68b4aa318dc7a2546e2eca6f2806a894ba39 nixpacks-arm64.tgz
687c3616e21824a449b56d4f989613ca68c921c6cce670b4de4459b025233806 pack-amd64.tgz
9a294abb0576fd95e19a009b3f9d5f5aa9fecdc2d7da7fa05e7e1e94f5085d77 pack-arm64.tgz
248a8f60f36854aabed6124113631078a802de3461660855fc4de9c26065c1fb railpack-amd64.tgz
732ece14eb4f4676a43ebba19431f954edf7b130acb76159ef0f2ff86ac42ac9 railpack-arm64.tgz
EOF
RUN if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \
curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-amd64 -o ~/.docker/cli-plugins/docker-buildx && \
curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-x86_64 -o ~/.docker/cli-plugins/docker-compose && \
(curl -sSL https://download.docker.com/linux/static/stable/x86_64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \
(curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \
curl -sSL https://nixpacks.com/install.sh | bash && \
curl -sSL https://railpack.com/install.sh | RAILPACK_VERSION=${RAILPACK_VERSION} sh && \
chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \
;fi
RUN if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \
curl -sSL https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-arm64 -o ~/.docker/cli-plugins/docker-buildx && \
curl -sSL https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-aarch64 -o ~/.docker/cli-plugins/docker-compose && \
(curl -sSL https://download.docker.com/linux/static/stable/aarch64/docker-${DOCKER_VERSION}.tgz | tar -C /usr/bin/ --no-same-owner -xzv --strip-components=1 docker/docker) && \
(curl -sSL https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux-arm64.tgz | tar -C /usr/local/bin/ --no-same-owner -xzv pack) && \
curl -sSL https://nixpacks.com/install.sh | bash && \
curl -sSL https://railpack.com/install.sh | RAILPACK_VERSION=${RAILPACK_VERSION} sh && \
chmod +x ~/.docker/cli-plugins/docker-compose /usr/bin/docker /usr/local/bin/pack /root/.docker/cli-plugins/docker-buildx \
;fi
RUN case "${TARGETARCH}" in \
amd64) DOCKER_ARCH=x86_64; PACK_SUFFIX=""; NIXPACKS_ARCH=x86_64; RAILPACK_ARCH=x86_64; MISE_ARCH=x64 ;; \
arm64) DOCKER_ARCH=aarch64; PACK_SUFFIX="-arm64"; NIXPACKS_ARCH=aarch64; RAILPACK_ARCH=arm64; MISE_ARCH=arm64 ;; \
*) echo "Unsupported architecture: ${TARGETARCH}" >&2; exit 1 ;; \
esac && \
mkdir -p /tmp/downloads && cd /tmp/downloads && \
download() { curl -fsSL --proto '=https' --tlsv1.2 --retry 3 -o "$1" "$2"; } && \
download "docker-${TARGETARCH}.tgz" "https://download.docker.com/linux/static/stable/${DOCKER_ARCH}/docker-${DOCKER_VERSION}.tgz" && \
download "docker-compose-${TARGETARCH}" "https://github.com/docker/compose/releases/download/v${DOCKER_COMPOSE_VERSION}/docker-compose-linux-${DOCKER_ARCH}" && \
download "docker-buildx-${TARGETARCH}" "https://github.com/docker/buildx/releases/download/v${DOCKER_BUILDX_VERSION}/buildx-v${DOCKER_BUILDX_VERSION}.linux-${TARGETARCH}" && \
download "pack-${TARGETARCH}.tgz" "https://github.com/buildpacks/pack/releases/download/v${PACK_VERSION}/pack-v${PACK_VERSION}-linux${PACK_SUFFIX}.tgz" && \
download "nixpacks-${TARGETARCH}.tgz" "https://github.com/railwayapp/nixpacks/releases/download/v${NIXPACKS_VERSION}/nixpacks-v${NIXPACKS_VERSION}-${NIXPACKS_ARCH}-unknown-linux-musl.tar.gz" && \
download "railpack-${TARGETARCH}.tgz" "https://github.com/railwayapp/railpack/releases/download/v${RAILPACK_VERSION}/railpack-v${RAILPACK_VERSION}-${RAILPACK_ARCH}-unknown-linux-musl.tar.gz" && \
download "mise-${TARGETARCH}" "https://github.com/jdx/mise/releases/download/v${MISE_VERSION}/mise-v${MISE_VERSION}-linux-${MISE_ARCH}-musl" && \
grep -- "-${TARGETARCH}" /tmp/SHA256SUMS | sha256sum -c - && \
mkdir -p /root/.docker/cli-plugins /tmp/railpack/mise && \
tar -xzf "docker-${TARGETARCH}.tgz" -C /usr/bin --no-same-owner --strip-components=1 docker/docker && \
install -m 0755 "docker-compose-${TARGETARCH}" /root/.docker/cli-plugins/docker-compose && \
install -m 0755 "docker-buildx-${TARGETARCH}" /root/.docker/cli-plugins/docker-buildx && \
tar -xzf "pack-${TARGETARCH}.tgz" -C /usr/local/bin --no-same-owner pack && \
tar -xzf "nixpacks-${TARGETARCH}.tgz" -C /usr/local/bin --no-same-owner nixpacks && \
tar -xzf "railpack-${TARGETARCH}.tgz" -C /usr/local/bin --no-same-owner railpack && \
# Railpack skips its own mise download when this file exists.
install -m 0755 "mise-${TARGETARCH}" "/tmp/railpack/mise/mise-${MISE_VERSION}" && \
cd / && rm -rf /tmp/downloads /tmp/SHA256SUMS && \
docker --version && docker compose version && docker buildx version && pack --version && \
nixpacks --version && railpack --version
COPY --from=minio-client /usr/bin/mc /usr/bin/mc
RUN chmod +x /usr/bin/mc
RUN chmod +x /usr/bin/mc && mc --version
ENTRYPOINT ["/sbin/tini", "--"]
CMD ["tail", "-f", "/dev/null"]
+1 -1
View File
@@ -7,7 +7,7 @@
"version": "4.6-rc.1"
},
"helper": {
"version": "1.0.18"
"version": "1.0.19"
},
"sentinel": {
"version": "1.1.2"
+85
View File
@@ -0,0 +1,85 @@
#!/usr/bin/env bash
# Update the SHA256SUMS block in docker/coolify-helper/Dockerfile.
# Change the ARG versions in the Dockerfile first, then run this script.
# It downloads every file, compares it with the upstream checksum file where one exists, and writes the new block.
set -euo pipefail
ROOT_DIR=$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)
DOCKERFILE="$ROOT_DIR/docker/coolify-helper/Dockerfile"
GH=https://github.com
arg() {
sed -n "s/^ARG $1=//p" "$DOCKERFILE"
}
DOCKER_VERSION=$(arg DOCKER_VERSION)
DOCKER_COMPOSE_VERSION=$(arg DOCKER_COMPOSE_VERSION)
DOCKER_BUILDX_VERSION=$(arg DOCKER_BUILDX_VERSION)
PACK_VERSION=$(arg PACK_VERSION)
NIXPACKS_VERSION=$(arg NIXPACKS_VERSION)
RAILPACK_VERSION=$(arg RAILPACK_VERSION)
MISE_VERSION=$(arg MISE_VERSION)
railpack_mise=$(curl -fsSL "https://raw.githubusercontent.com/railwayapp/railpack/v${RAILPACK_VERSION}/core/mise/version.txt")
if [[ $railpack_mise != "$MISE_VERSION" ]]; then
echo "MISE_VERSION is $MISE_VERSION, but Railpack $RAILPACK_VERSION pins mise $railpack_mise." >&2
exit 1
fi
WORK_DIR=$(mktemp -d)
trap 'rm -rf "$WORK_DIR"' EXIT
lines=()
# add <name> <url> [upstream checksum file URL]
add() {
local name=$1 url=$2 sums_url=${3:-} sum upstream
curl -fsSL --proto '=https' --tlsv1.2 --retry 3 -o "$WORK_DIR/$name" "$url"
sum=$(sha256sum "$WORK_DIR/$name" | cut -d' ' -f1)
if [[ -n $sums_url ]]; then
upstream=$(curl -fsSL "$sums_url" | grep -F "${url##*/}" | awk '{print $1}' | head -1)
if [[ $upstream != "$sum" ]]; then
echo "Checksum mismatch for $url (upstream: ${upstream:-not found}, downloaded: $sum)." >&2
exit 1
fi
echo "verified $name"
else
echo "no upstream checksum $name"
fi
lines+=("$sum $name")
}
for arch in amd64 arm64; do
case $arch in
amd64) DOCKER_ARCH=x86_64; PACK_SUFFIX=""; NIXPACKS_ARCH=x86_64; RAILPACK_ARCH=x86_64; MISE_ARCH=x64 ;;
arm64) DOCKER_ARCH=aarch64; PACK_SUFFIX="-arm64"; NIXPACKS_ARCH=aarch64; RAILPACK_ARCH=arm64; MISE_ARCH=arm64 ;;
esac
add "docker-$arch.tgz" \
"https://download.docker.com/linux/static/stable/$DOCKER_ARCH/docker-$DOCKER_VERSION.tgz"
add "docker-compose-$arch" \
"$GH/docker/compose/releases/download/v$DOCKER_COMPOSE_VERSION/docker-compose-linux-$DOCKER_ARCH" \
"$GH/docker/compose/releases/download/v$DOCKER_COMPOSE_VERSION/checksums.txt"
add "docker-buildx-$arch" \
"$GH/docker/buildx/releases/download/v$DOCKER_BUILDX_VERSION/buildx-v$DOCKER_BUILDX_VERSION.linux-$arch" \
"$GH/docker/buildx/releases/download/v$DOCKER_BUILDX_VERSION/checksums.txt"
add "pack-$arch.tgz" \
"$GH/buildpacks/pack/releases/download/v$PACK_VERSION/pack-v$PACK_VERSION-linux$PACK_SUFFIX.tgz" \
"$GH/buildpacks/pack/releases/download/v$PACK_VERSION/pack-v$PACK_VERSION-linux$PACK_SUFFIX.tgz.sha256"
add "nixpacks-$arch.tgz" \
"$GH/railwayapp/nixpacks/releases/download/v$NIXPACKS_VERSION/nixpacks-v$NIXPACKS_VERSION-$NIXPACKS_ARCH-unknown-linux-musl.tar.gz"
add "railpack-$arch.tgz" \
"$GH/railwayapp/railpack/releases/download/v$RAILPACK_VERSION/railpack-v$RAILPACK_VERSION-$RAILPACK_ARCH-unknown-linux-musl.tar.gz" \
"$GH/railwayapp/railpack/releases/download/v$RAILPACK_VERSION/checksums.txt"
add "mise-$arch" \
"$GH/jdx/mise/releases/download/v$MISE_VERSION/mise-v$MISE_VERSION-linux-$MISE_ARCH-musl" \
"$GH/jdx/mise/releases/download/v$MISE_VERSION/SHASUMS256.txt"
done
block=$(printf '%s\n' "${lines[@]}" | sort -k2)
BLOCK="$block" perl -0pi -e 's/(COPY <<.EOF. \/tmp\/SHA256SUMS\n).*?(\nEOF\n)/$1$ENV{BLOCK}$2/s' "$DOCKERFILE"
echo "Updated SHA256SUMS in $DOCKERFILE"