diff --git a/.cspell.json b/.cspell.json index 03d9921d5..0b309d6cb 100644 --- a/.cspell.json +++ b/.cspell.json @@ -10,6 +10,8 @@ ], "words": [ "abool", + "addgroup", + "adduser", "anbraten", "antfu", "apimachinery", diff --git a/.woodpecker/docker.yaml b/.woodpecker/docker.yaml index d5b164496..e49cc9d5e 100644 --- a/.woodpecker/docker.yaml +++ b/.woodpecker/docker.yaml @@ -125,7 +125,7 @@ steps: image: *buildx_plugin settings: repo: woodpeckerci/woodpecker-server - dockerfile: docker/Dockerfile.server.alpine.multiarch + dockerfile: docker/Dockerfile.server.alpine.multiarch.rootless platforms: *platforms_preview tag: pull_${CI_COMMIT_PULL_REQUEST}-alpine logins: *publish_logins @@ -142,7 +142,7 @@ steps: settings: dry_run: true repo: woodpeckerci/woodpecker-server - dockerfile: docker/Dockerfile.server.multiarch + dockerfile: docker/Dockerfile.server.multiarch.rootless platforms: *platforms_preview tag: pull_${CI_COMMIT_PULL_REQUEST} when: &when-dryrun @@ -156,7 +156,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_server - dockerfile: docker/Dockerfile.server.multiarch + dockerfile: docker/Dockerfile.server.multiarch.rootless platforms: *platforms_server tag: [next, 'next-${CI_COMMIT_SHA:0:10}'] logins: *publish_logins @@ -171,7 +171,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_server - dockerfile: docker/Dockerfile.server.alpine.multiarch + dockerfile: docker/Dockerfile.server.alpine.multiarch.rootless platforms: *platforms_alpine tag: [next-alpine, 'next-${CI_COMMIT_SHA:0:10}-alpine'] logins: *publish_logins @@ -183,7 +183,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_server - dockerfile: docker/Dockerfile.server.multiarch + dockerfile: docker/Dockerfile.server.multiarch.rootless platforms: *platforms_server tag: ['${CI_COMMIT_TAG%%.*}', '${CI_COMMIT_TAG%.*}-alpine', '${CI_COMMIT_TAG}'] logins: *publish_logins @@ -196,7 +196,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_server - dockerfile: docker/Dockerfile.server.alpine.multiarch + dockerfile: docker/Dockerfile.server.alpine.multiarch.rootless platforms: *platforms_alpine tag: ['${CI_COMMIT_TAG%%.*}-alpine', '${CI_COMMIT_TAG%.*}-alpine', '${CI_COMMIT_TAG}-alpine'] logins: *publish_logins @@ -212,7 +212,7 @@ steps: image: *buildx_plugin settings: repo: woodpeckerci/woodpecker-agent - dockerfile: docker/Dockerfile.agent.alpine.multiarch + dockerfile: docker/Dockerfile.agent.alpine.multiarch.rootless platforms: *platforms_preview tag: pull_${CI_COMMIT_PULL_REQUEST}-alpine build_args: *build_args @@ -226,7 +226,7 @@ steps: settings: dry_run: true repo: woodpeckerci/woodpecker-agent - dockerfile: docker/Dockerfile.agent.multiarch + dockerfile: docker/Dockerfile.agent.multiarch.rootless platforms: *platforms_preview tag: pull_${CI_COMMIT_PULL_REQUEST} build_args: *build_args @@ -241,7 +241,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_agent - dockerfile: docker/Dockerfile.agent.multiarch + dockerfile: docker/Dockerfile.agent.multiarch.rootless platforms: *platforms_release tag: [next, 'next-${CI_COMMIT_SHA:0:10}'] logins: *publish_logins @@ -260,7 +260,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_agent - dockerfile: docker/Dockerfile.agent.alpine.multiarch + dockerfile: docker/Dockerfile.agent.alpine.multiarch.rootless platforms: *platforms_alpine tag: [next-alpine, 'next-${CI_COMMIT_SHA:0:10}-alpine'] logins: *publish_logins @@ -276,7 +276,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_agent - dockerfile: docker/Dockerfile.agent.multiarch + dockerfile: docker/Dockerfile.agent.multiarch.rootless platforms: *platforms_release tag: ['${CI_COMMIT_TAG%%.*}', '${CI_COMMIT_TAG%.*}', '${CI_COMMIT_TAG}'] logins: *publish_logins @@ -292,7 +292,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_agent - dockerfile: docker/Dockerfile.agent.alpine.multiarch + dockerfile: docker/Dockerfile.agent.alpine.multiarch.rootless platforms: *platforms_alpine tag: ['${CI_COMMIT_TAG%%.*}-alpine', '${CI_COMMIT_TAG%.*}-alpine', '${CI_COMMIT_TAG}-alpine'] logins: *publish_logins @@ -310,7 +310,7 @@ steps: settings: dry_run: true repo: woodpeckerci/woodpecker-cli - dockerfile: docker/Dockerfile.cli.multiarch + dockerfile: docker/Dockerfile.cli.multiarch.rootless platforms: *platforms_preview tag: pull_${CI_COMMIT_PULL_REQUEST} build_args: *build_args @@ -325,7 +325,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_cli - dockerfile: docker/Dockerfile.cli.multiarch + dockerfile: docker/Dockerfile.cli.multiarch.rootless platforms: *platforms_release tag: [next, 'next-${CI_COMMIT_SHA:0:10}'] logins: *publish_logins @@ -341,7 +341,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_cli - dockerfile: docker/Dockerfile.cli.alpine.multiarch + dockerfile: docker/Dockerfile.cli.alpine.multiarch.rootless platforms: *platforms_alpine tag: [next-alpine, 'next-${CI_COMMIT_SHA:0:10}-alpine'] logins: *publish_logins @@ -357,7 +357,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_cli - dockerfile: docker/Dockerfile.cli.multiarch + dockerfile: docker/Dockerfile.cli.multiarch.rootless platforms: *platforms_release tag: ['${CI_COMMIT_TAG%%.*}', '${CI_COMMIT_TAG%.*}', '${CI_COMMIT_TAG}'] logins: *publish_logins @@ -373,7 +373,7 @@ steps: image: *buildx_plugin settings: repo: *publish_repos_cli - dockerfile: docker/Dockerfile.cli.alpine.multiarch + dockerfile: docker/Dockerfile.cli.alpine.multiarch.rootless platforms: *platforms_alpine tag: ['${CI_COMMIT_TAG%%.*}-alpine', '${CI_COMMIT_TAG%.*}-alpine', '${CI_COMMIT_TAG}-alpine'] logins: *publish_logins diff --git a/docker/Dockerfile.agent.alpine.multiarch b/docker/Dockerfile.agent.alpine.multiarch.rootless similarity index 75% rename from docker/Dockerfile.agent.alpine.multiarch rename to docker/Dockerfile.agent.alpine.multiarch.rootless index 3ce6b783f..b631f2d18 100644 --- a/docker/Dockerfile.agent.alpine.multiarch +++ b/docker/Dockerfile.agent.alpine.multiarch.rootless @@ -8,14 +8,20 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ make build-agent FROM docker.io/alpine:3.21 -RUN apk add -U --no-cache ca-certificates + +RUN apk add -U --no-cache ca-certificates && \ + adduser -u 1000 -g 1000 woodpecker && \ + mkdir -p /etc/woodpecker && \ + chown -R woodpecker:woodpecker /etc/woodpecker + ENV GODEBUG=netdns=go # Internal setting do NOT change! Signals that woodpecker is running inside a container ENV WOODPECKER_IN_CONTAINER=true EXPOSE 3000 COPY --from=build /src/dist/woodpecker-agent /bin/ -RUN mkdir -p /etc/woodpecker + +USER woodpecker HEALTHCHECK CMD ["/bin/woodpecker-agent", "ping"] ENTRYPOINT ["/bin/woodpecker-agent"] diff --git a/docker/Dockerfile.agent.multiarch b/docker/Dockerfile.agent.multiarch.rootless similarity index 74% rename from docker/Dockerfile.agent.multiarch rename to docker/Dockerfile.agent.multiarch.rootless index ccf5b3a23..e0cb739a1 100644 --- a/docker/Dockerfile.agent.multiarch +++ b/docker/Dockerfile.agent.multiarch.rootless @@ -1,12 +1,16 @@ FROM --platform=$BUILDPLATFORM docker.io/golang:1.23 AS build +RUN groupadd -g 1000 woodpecker && \ + useradd -u 1000 -g 1000 woodpecker && \ + mkdir -p /etc/woodpecker && \ + chown -R woodpecker:woodpecker /etc/woodpecker + WORKDIR /src COPY . . ARG TARGETOS TARGETARCH CI_COMMIT_SHA CI_COMMIT_TAG CI_COMMIT_BRANCH RUN --mount=type=cache,target=/root/.cache/go-build \ --mount=type=cache,target=/go/pkg \ make build-agent -RUN mkdir -p /etc/woodpecker FROM scratch ENV GODEBUG=netdns=go @@ -19,6 +23,10 @@ COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certifica # copy agent binary COPY --from=build /src/dist/woodpecker-agent /bin/ COPY --from=build /etc/woodpecker /etc +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group + +USER woodpecker HEALTHCHECK CMD ["/bin/woodpecker-agent", "ping"] ENTRYPOINT ["/bin/woodpecker-agent"] diff --git a/docker/Dockerfile.cli.alpine.multiarch b/docker/Dockerfile.cli.alpine.multiarch.rootless similarity index 83% rename from docker/Dockerfile.cli.alpine.multiarch rename to docker/Dockerfile.cli.alpine.multiarch.rootless index 3768c0373..471cbd00a 100644 --- a/docker/Dockerfile.cli.alpine.multiarch +++ b/docker/Dockerfile.cli.alpine.multiarch.rootless @@ -8,14 +8,18 @@ RUN --mount=type=cache,target=/root/.cache/go-build \ make build-cli FROM docker.io/alpine:3.21 + WORKDIR /woodpecker -RUN apk add -U --no-cache ca-certificates +RUN apk add -U --no-cache ca-certificates && \ + adduser -u 1000 -g 1000 woodpecker ENV GODEBUG=netdns=go ENV WOODPECKER_DISABLE_UPDATE_CHECK=true COPY --from=build /src/dist/woodpecker-cli /bin/ +USER woodpecker + HEALTHCHECK CMD ["/bin/woodpecker-cli", "ping"] ENTRYPOINT ["/bin/woodpecker-cli"] diff --git a/docker/Dockerfile.cli.multiarch b/docker/Dockerfile.cli.multiarch.rootless similarity index 78% rename from docker/Dockerfile.cli.multiarch rename to docker/Dockerfile.cli.multiarch.rootless index 2e1a7009f..0a57a315c 100644 --- a/docker/Dockerfile.cli.multiarch +++ b/docker/Dockerfile.cli.multiarch.rootless @@ -1,5 +1,8 @@ FROM --platform=$BUILDPLATFORM docker.io/golang:1.23 AS build +RUN groupadd -g 1000 woodpecker && \ + useradd -u 1000 -g 1000 woodpecker + WORKDIR /src COPY . . ARG TARGETOS TARGETARCH CI_COMMIT_SHA CI_COMMIT_TAG CI_COMMIT_BRANCH @@ -17,6 +20,10 @@ ENV WOODPECKER_DISABLE_UPDATE_CHECK=true COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt # copy cli binary COPY --from=build /src/dist/woodpecker-cli /bin/ +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group + +USER woodpecker HEALTHCHECK CMD ["/bin/woodpecker-cli", "ping"] ENTRYPOINT ["/bin/woodpecker-cli"] diff --git a/docker/Dockerfile.server.alpine.multiarch b/docker/Dockerfile.server.alpine.multiarch.rootless similarity index 69% rename from docker/Dockerfile.server.alpine.multiarch rename to docker/Dockerfile.server.alpine.multiarch.rootless index ae7d5fc38..b07179c9a 100644 --- a/docker/Dockerfile.server.alpine.multiarch +++ b/docker/Dockerfile.server.alpine.multiarch.rootless @@ -1,7 +1,11 @@ FROM docker.io/alpine:3.21 ARG TARGETOS TARGETARCH -RUN apk add -U --no-cache ca-certificates +RUN apk add -U --no-cache ca-certificates && \ + adduser -u 1000 -g 1000 woodpecker && \ + mkdir -p /var/lib/woodpecker && \ + chown -R woodpecker:woodpecker /var/lib/woodpecker + ENV GODEBUG=netdns=go # Internal setting do NOT change! Signals that woodpecker is running inside a container ENV WOODPECKER_IN_CONTAINER=true @@ -11,5 +15,7 @@ EXPOSE 8000 9000 80 443 COPY dist/server/${TARGETOS}_${TARGETARCH}/woodpecker-server /bin/ +USER woodpecker + HEALTHCHECK CMD ["/bin/woodpecker-server", "ping"] ENTRYPOINT ["/bin/woodpecker-server"] diff --git a/docker/Dockerfile.server.multiarch b/docker/Dockerfile.server.multiarch.rootless similarity index 53% rename from docker/Dockerfile.server.multiarch rename to docker/Dockerfile.server.multiarch.rootless index 56e02b462..7bf4b5cde 100644 --- a/docker/Dockerfile.server.multiarch +++ b/docker/Dockerfile.server.multiarch.rootless @@ -1,4 +1,9 @@ -FROM --platform=$BUILDPLATFORM docker.io/golang:1.23 AS certs +FROM --platform=$BUILDPLATFORM docker.io/golang:1.23 AS build + +RUN groupadd -g 1000 woodpecker && \ + useradd -u 1000 -g 1000 woodpecker && \ + mkdir -p /var/lib/woodpecker && \ + chown -R woodpecker:woodpecker /var/lib/woodpecker FROM scratch ARG TARGETOS TARGETARCH @@ -10,9 +15,14 @@ ENV XDG_DATA_HOME=/var/lib/woodpecker EXPOSE 8000 9000 80 443 # copy certs from certs image -COPY --from=certs /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt +COPY --from=build /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt # copy server binary COPY dist/server/${TARGETOS}_${TARGETARCH}/woodpecker-server /bin/ +COPY --from=build /etc/passwd /etc/passwd +COPY --from=build /etc/group /etc/group +COPY --from=build /var/lib/woodpecker /var/lib/woodpecker + +USER woodpecker HEALTHCHECK CMD ["/bin/woodpecker-server", "ping"] ENTRYPOINT ["/bin/woodpecker-server"] diff --git a/docs/docs/30-administration/04-image-variants.md b/docs/docs/30-administration/04-image-variants.md new file mode 100644 index 000000000..1885eb4d8 --- /dev/null +++ b/docs/docs/30-administration/04-image-variants.md @@ -0,0 +1,30 @@ +# Image variants + +:::info +The `latest` tag has been deprecated as of v3.0 and will be completely removed in the future. +This was done to prevent accidental major version upgrades. +::: + +- `vX.Y.Z`: SemVer tags for specific releases, no entrypoint shell (scratch image) + - `vX.Y` + - `vX` +- `vX.Y.Z-alpine`: SemVer tags for specific releases, based on Alpine, rootless (as of v3.0). + - `vX.Y-alpine` + - `vX-alpine` +- `next`: Built from the `main` branch +- `pull_`: Images built from Pull Request branches. + +## Image registries + +Images are pushed to DockerHub and Quay. + +[woodpecker-server (DockerHub)](https://hub.docker.com/repository/docker/woodpeckerci/woodpecker-server) +[woodpecker-server (Quay)](https://quay.io/repository/woodpeckerci/woodpecker-server) + +[woodpecker-agent (DockerHub)](https://hub.docker.com/repository/docker/woodpeckerci/woodpecker-agent) +[woodpecker-agent (Quay)](https://quay.io/repository/woodpeckerci/woodpecker-agent) + +[woodpecker-cli (DockerHub)](https://hub.docker.com/repository/docker/woodpeckerci/woodpecker-cli) +[woodpecker-cli (Quay)](https://quay.io/repository/woodpeckerci/woodpecker-cli) + +[woodpecker-autoscaler (DockerHub)](https://hub.docker.com/repository/docker/woodpeckerci/autoscaler) diff --git a/docs/docs/92-development/07-guides.md b/docs/docs/92-development/07-guides.md index 124cd4031..eaff951ee 100644 --- a/docs/docs/92-development/07-guides.md +++ b/docs/docs/92-development/07-guides.md @@ -40,7 +40,7 @@ export PLATFORMS='linux|amd64' make cross-compile-server ### build the image -docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.server.multiarch --push . +docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.server.multiarch.rootless --push . ``` :::info @@ -55,7 +55,7 @@ You can try to use the `build-server` rule instead, however this one fails for s make build-agent ### build the image -docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.agent.multiarch --push . +docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.agent.multiarch.rootless --push . ``` ### CLI @@ -65,5 +65,5 @@ docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Docker make build-cli ### build the image -docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.cli.multiarch --push . +docker buildx build --platform linux/amd64 -t username/repo:tag -f docker/Dockerfile.cli.multiarch.rootless --push . ``` diff --git a/docs/src/pages/migrations.md b/docs/src/pages/migrations.md index d90db416e..07ee320e3 100644 --- a/docs/src/pages/migrations.md +++ b/docs/src/pages/migrations.md @@ -174,6 +174,11 @@ The following restructuring was done to achieve a more consistent grouping: - Webhook signatures now use the `rfc9421` protocol +#### Rootless images + +All Woodpecker images now use a non-privileged user (`woodpecker`) by default. +If you have volume mounts attached to containers, you might need to update the ownership of these directories from `root` to `woodpecker`. + ## User migrations - `gated` has been replaced by `require-approval`