diff --git a/2.10/rootless/Caddyfile b/2.10/rootless/Caddyfile new file mode 100644 index 0000000..8a74d0d --- /dev/null +++ b/2.10/rootless/Caddyfile @@ -0,0 +1,11 @@ +# Global options: rootless image uses non-privileged ports +{ + http_port 8080 + https_port 8443 +} + +:8080 + +route { + teapot +} diff --git a/2.10/rootless/Dockerfile b/2.10/rootless/Dockerfile new file mode 100644 index 0000000..4af2f13 --- /dev/null +++ b/2.10/rootless/Dockerfile @@ -0,0 +1,88 @@ +FROM alpine:3.22 + +RUN apk add --no-cache \ + ca-certificates \ + curl \ + libcap \ + mailcap + +RUN set -eux; \ + mkdir -p \ + /config/caddy \ + /data/caddy \ + /etc/caddy \ + /usr/share/caddy \ + ; \ + wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/config/Caddyfile"; \ + wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/welcome/index.html"; \ + sed -i 's/:80/:{\$CADDY_HTTP_PORT:8080}/g' /etc/caddy/Caddyfile + +# https://github.com/caddyserver/caddy/releases +ENV CADDY_VERSION=v2.10.2 + +RUN set -eux; \ + apkArch="$(apk --print-arch)"; \ + case "$apkArch" in \ + x86_64) binArch='amd64'; checksum='747df7ee74de188485157a383633a1a963fd9233b71fbb4a69ddcbcc589ce4e2cc82dacf5dbbe136cb51d17e14c59daeb5d9bc92487610b0f3b93680b2646546' ;; \ + armhf) binArch='armv6'; checksum='95b71fd99595018eebf4890782de63018ee86455531380b2a83a1814bb09c2588c0a531c877a26ba8a16a5b78072a1c26f7548bdec0e18abcef423fcc31a2e0e' ;; \ + armv7) binArch='armv7'; checksum='215af42cf952726d962c9753a12c04248781221b66df8b7110726fa7905d7a5c2e50056e0b47ab3c709d3dcfb48fde0f11e184a6950de0a2ddf941d3e503d07b' ;; \ + aarch64) binArch='arm64'; checksum='6ce061a690312ab38367df3c5d5f89a2e4a263e7300d300d87356211bb81e79b15933e6d6203e03fbf26f15cc0311f264805f336147dbdd24938d84b57a4421c' ;; \ + ppc64el|ppc64le) binArch='ppc64le'; checksum='ab286a51e0e8ce79393519b0c7ebe99075f4539b57f6a34fe555ba8060f8fbaee36197a1e8e49d0050ab5d6a783253839bc2675137635f8d252aea27f2ca5a85' ;; \ + riscv64) binArch='riscv64'; checksum='e71c8ba2462990e0d8a67c544b694446ad36d045bf40ce641fae6774181677457f6ae8ed0b5c4c927ef8302d91c587074b6001318f377d7054113b5da6dee6df' ;; \ + s390x) binArch='s390x'; checksum='b8aaa737b63308fac14cf84d7a658d9a0d74d2fe5f6a2eb57ca3ce7c52a73bea702c95da73ebfd20b3206bfb7b71ac8613aef9797e0f7a2c2a04bf5083092c2b' ;; \ + *) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\ + esac; \ + wget -O /tmp/caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v2.10.2/caddy_2.10.2_linux_${binArch}.tar.gz"; \ + echo "$checksum /tmp/caddy.tar.gz" | sha512sum -c; \ + tar x -z -f /tmp/caddy.tar.gz -C /usr/bin caddy; \ + rm -f /tmp/caddy.tar.gz; \ + chmod +x /usr/bin/caddy; \ + caddy version + +# Create non-root user with UID 1001 and root group (GID 0) +# OpenShift will override the UID but keep GID=0 +# The -D flag creates a system user without password +# The -H flag prevents creating a home directory +RUN adduser -D -u 1001 -H -h /data caddy && \ + addgroup caddy root + +# Set ownership to 1001:0 (user:root-group) for OpenShift compatibility +# OpenShift assigns arbitrary UIDs but always uses GID=0 (root group) +# The root group has no special privileges despite the name +RUN chown -R 1001:0 /data /config /etc/caddy + +# Make directories writable by the root group for OpenShift compatibility +RUN chmod -R g+w /data /config /etc/caddy + +# See https://caddyserver.com/docs/conventions#file-locations for details +ENV XDG_CONFIG_HOME=/config +ENV XDG_DATA_HOME=/data + +# Set default HTTP and HTTPS ports to non-privileged ports for rootless operation +ENV CADDY_HTTP_PORT=8080 +ENV CADDY_HTTPS_PORT=8443 + +LABEL org.opencontainers.image.version=v2.10.2 +LABEL org.opencontainers.image.title=Caddy +LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go (rootless)" +LABEL org.opencontainers.image.url=https://caddyserver.com +LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs +LABEL org.opencontainers.image.vendor="Light Code Labs" +LABEL org.opencontainers.image.licenses=Apache-2.0 +LABEL org.opencontainers.image.source="https://github.com/caddyserver/caddy-docker" + +# Expose non-privileged ports (rootless containers cannot bind to ports < 1024) +# Configure these ports in your Caddyfile with http_port and https_port directives +# 8080: HTTP, 8443: HTTPS (TCP), 8443/udp: HTTP/3 (QUIC), 2019: Admin API +EXPOSE 8080 +EXPOSE 8443 +EXPOSE 8443/udp +EXPOSE 2019 + +WORKDIR /srv + +# Switch to non-root user +# OpenShift will override this UID with an arbitrary one, but keep GID=0 +USER 1001 + +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/2.10/rootless/Dockerfile.base b/2.10/rootless/Dockerfile.base new file mode 100644 index 0000000..7a4fc3c --- /dev/null +++ b/2.10/rootless/Dockerfile.base @@ -0,0 +1 @@ +FROM alpine:3.22 diff --git a/2.11/rootless/Caddyfile b/2.11/rootless/Caddyfile new file mode 100644 index 0000000..8a74d0d --- /dev/null +++ b/2.11/rootless/Caddyfile @@ -0,0 +1,11 @@ +# Global options: rootless image uses non-privileged ports +{ + http_port 8080 + https_port 8443 +} + +:8080 + +route { + teapot +} diff --git a/2.11/rootless/Dockerfile b/2.11/rootless/Dockerfile new file mode 100644 index 0000000..3d46151 --- /dev/null +++ b/2.11/rootless/Dockerfile @@ -0,0 +1,88 @@ +FROM alpine:3.22 + +RUN apk add --no-cache \ + ca-certificates \ + curl \ + libcap \ + mailcap + +RUN set -eux; \ + mkdir -p \ + /config/caddy \ + /data/caddy \ + /etc/caddy \ + /usr/share/caddy \ + ; \ + wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/config/Caddyfile"; \ + wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/33ae08ff08d168572df2956ed14fbc4949880d94/welcome/index.html"; \ + sed -i 's/:80/:{\$CADDY_HTTP_PORT:8080}/g' /etc/caddy/Caddyfile + +# https://github.com/caddyserver/caddy/releases +ENV CADDY_VERSION=v2.11.0-beta.2 + +RUN set -eux; \ + apkArch="$(apk --print-arch)"; \ + case "$apkArch" in \ + x86_64) binArch='amd64'; checksum='f9c72942891b3983d26cd96a2353f0985de3381f0996ae2fd37e9dc662c3b78a6cdad121d5ab225ffbe36d9425b46c5258c08dba707299a111d41ede7228171b' ;; \ + armhf) binArch='armv6'; checksum='ff625cf10b3af39aa55e9f912342fda2868b2de8df1a3da543ccbae998cbe5b7d12ebb707edc061ebdb6df3c656a8c3a67743f5212df2132c4ce6f26bc8bf057' ;; \ + armv7) binArch='armv7'; checksum='de69fc54499bcfecacd1f37533ebca116545bd46d27070d6858b042c61e11d673a13bf4f08db238ead6d54ed79a59c7ce2ce103ac94241715cfaba5034861541' ;; \ + aarch64) binArch='arm64'; checksum='e3caa4eed7104549029aa31074fc8f9e0399706c787a7ad22d23135d0c765ced8e9c2577fbb0b1e8a000042d86ad80cabb49e85eaf973e18b435926cc8b356fd' ;; \ + ppc64el|ppc64le) binArch='ppc64le'; checksum='ea4a8ef21630b5363e7c3f62ebb7926d152ac4fdc854fe374b08eb6c0edfd50dbb5c6f01b5c89aad1871b83690fcd4f9178ecd64db9544dab605161af0352644' ;; \ + riscv64) binArch='riscv64'; checksum='f68fd4802b8d77e8b7fcc4eb1d3576edceabe9494edfa07fee402b4643aa2cf3402f88f049bafa2995ddf4dfbdc2aa569abb7056e9696d94360725b25e5df91c' ;; \ + s390x) binArch='s390x'; checksum='e809207408cab3d9c96c7c70f832f244311c5e2b5546ad4e15179cae665c0cf3a759692ff0f8de0519c3b587309b2b892ca0559bf7ac9c3244f3ed851353cfa5' ;; \ + *) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\ + esac; \ + wget -O /tmp/caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v2.11.0-beta.2/caddy_2.11.0-beta.2_linux_${binArch}.tar.gz"; \ + echo "$checksum /tmp/caddy.tar.gz" | sha512sum -c; \ + tar x -z -f /tmp/caddy.tar.gz -C /usr/bin caddy; \ + rm -f /tmp/caddy.tar.gz; \ + chmod +x /usr/bin/caddy; \ + caddy version + +# Create non-root user with UID 1001 and root group (GID 0) +# OpenShift will override the UID but keep GID=0 +# The -D flag creates a system user without password +# The -H flag prevents creating a home directory +RUN adduser -D -u 1001 -H -h /data caddy && \ + addgroup caddy root + +# Set ownership to 1001:0 (user:root-group) for OpenShift compatibility +# OpenShift assigns arbitrary UIDs but always uses GID=0 (root group) +# The root group has no special privileges despite the name +RUN chown -R 1001:0 /data /config /etc/caddy + +# Make directories writable by the root group for OpenShift compatibility +RUN chmod -R g+w /data /config /etc/caddy + +# See https://caddyserver.com/docs/conventions#file-locations for details +ENV XDG_CONFIG_HOME=/config +ENV XDG_DATA_HOME=/data + +# Set default HTTP and HTTPS ports to non-privileged ports for rootless operation +ENV CADDY_HTTP_PORT=8080 +ENV CADDY_HTTPS_PORT=8443 + +LABEL org.opencontainers.image.version=v2.11.0-beta.2 +LABEL org.opencontainers.image.title=Caddy +LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go (rootless)" +LABEL org.opencontainers.image.url=https://caddyserver.com +LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs +LABEL org.opencontainers.image.vendor="Light Code Labs" +LABEL org.opencontainers.image.licenses=Apache-2.0 +LABEL org.opencontainers.image.source="https://github.com/caddyserver/caddy-docker" + +# Expose non-privileged ports (rootless containers cannot bind to ports < 1024) +# Configure these ports in your Caddyfile with http_port and https_port directives +# 8080: HTTP, 8443: HTTPS (TCP), 8443/udp: HTTP/3 (QUIC), 2019: Admin API +EXPOSE 8080 +EXPOSE 8443 +EXPOSE 8443/udp +EXPOSE 2019 + +WORKDIR /srv + +# Switch to non-root user +# OpenShift will override this UID with an arbitrary one, but keep GID=0 +USER 1001 + +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/2.11/rootless/Dockerfile.base b/2.11/rootless/Dockerfile.base new file mode 100644 index 0000000..7a4fc3c --- /dev/null +++ b/2.11/rootless/Dockerfile.base @@ -0,0 +1 @@ +FROM alpine:3.22 diff --git a/Dockerfile.rootless.tmpl b/Dockerfile.rootless.tmpl new file mode 100644 index 0000000..cfce003 --- /dev/null +++ b/Dockerfile.rootless.tmpl @@ -0,0 +1,88 @@ +{{ .base | strings.TrimSpace }} + +RUN apk add --no-cache \ + ca-certificates \ + curl \ + libcap \ + mailcap + +RUN set -eux; \ + mkdir -p \ + /config/caddy \ + /data/caddy \ + /etc/caddy \ + /usr/share/caddy \ + ; \ + wget -O /etc/caddy/Caddyfile "https://github.com/caddyserver/dist/raw/{{ .config.dist_commit }}/config/Caddyfile"; \ + wget -O /usr/share/caddy/index.html "https://github.com/caddyserver/dist/raw/{{ .config.dist_commit }}/welcome/index.html"; \ + sed -i 's/:80/:{\$CADDY_HTTP_PORT:8080}/g' /etc/caddy/Caddyfile + +# https://github.com/caddyserver/caddy/releases +ENV CADDY_VERSION=v{{ .config.caddy_version }} + +RUN set -eux; \ + apkArch="$(apk --print-arch)"; \ + case "$apkArch" in \ + x86_64) binArch='amd64'; checksum='{{ .checksums.amd64 }}' ;; \ + armhf) binArch='armv6'; checksum='{{ .checksums.arm32v6 }}' ;; \ + armv7) binArch='armv7'; checksum='{{ .checksums.arm32v7 }}' ;; \ + aarch64) binArch='arm64'; checksum='{{ .checksums.arm64v8 }}' ;; \ + ppc64el|ppc64le) binArch='ppc64le'; checksum='{{ .checksums.ppc64le }}' ;; \ + riscv64) binArch='riscv64'; checksum='{{ .checksums.riscv64 }}' ;; \ + s390x) binArch='s390x'; checksum='{{ .checksums.s390x }}' ;; \ + *) echo >&2 "error: unsupported architecture ($apkArch)"; exit 1 ;;\ + esac; \ + wget -O /tmp/caddy.tar.gz "https://github.com/caddyserver/caddy/releases/download/v{{ .config.caddy_version }}/caddy_{{ .config.caddy_version }}_linux_${binArch}.tar.gz"; \ + echo "$checksum /tmp/caddy.tar.gz" | sha512sum -c; \ + tar x -z -f /tmp/caddy.tar.gz -C /usr/bin caddy; \ + rm -f /tmp/caddy.tar.gz; \ + chmod +x /usr/bin/caddy; \ + caddy version + +# Create non-root user with UID 1001 and root group (GID 0) +# OpenShift will override the UID but keep GID=0 +# The -D flag creates a system user without password +# The -H flag prevents creating a home directory +RUN adduser -D -u 1001 -H -h /data caddy && \ + addgroup caddy root + +# Set ownership to 1001:0 (user:root-group) for OpenShift compatibility +# OpenShift assigns arbitrary UIDs but always uses GID=0 (root group) +# The root group has no special privileges despite the name +RUN chown -R 1001:0 /data /config /etc/caddy + +# Make directories writable by the root group for OpenShift compatibility +RUN chmod -R g+w /data /config /etc/caddy + +# See https://caddyserver.com/docs/conventions#file-locations for details +ENV XDG_CONFIG_HOME=/config +ENV XDG_DATA_HOME=/data + +# Set default HTTP and HTTPS ports to non-privileged ports for rootless operation +ENV CADDY_HTTP_PORT=8080 +ENV CADDY_HTTPS_PORT=8443 + +LABEL org.opencontainers.image.version=v{{ .config.caddy_version }} +LABEL org.opencontainers.image.title=Caddy +LABEL org.opencontainers.image.description="a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go (rootless)" +LABEL org.opencontainers.image.url=https://caddyserver.com +LABEL org.opencontainers.image.documentation=https://caddyserver.com/docs +LABEL org.opencontainers.image.vendor="Light Code Labs" +LABEL org.opencontainers.image.licenses=Apache-2.0 +LABEL org.opencontainers.image.source="https://github.com/caddyserver/caddy-docker" + +# Expose non-privileged ports (rootless containers cannot bind to ports < 1024) +# Configure these ports in your Caddyfile with http_port and https_port directives +# 8080: HTTP, 8443: HTTPS (TCP), 8443/udp: HTTP/3 (QUIC), 2019: Admin API +EXPOSE 8080 +EXPOSE 8443 +EXPOSE 8443/udp +EXPOSE 2019 + +WORKDIR /srv + +# Switch to non-root user +# OpenShift will override this UID with an arbitrary one, but keep GID=0 +USER 1001 + +CMD ["caddy", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"] diff --git a/Makefile b/Makefile index 5b5c19a..599f36a 100644 --- a/Makefile +++ b/Makefile @@ -3,11 +3,12 @@ all: gen-dockerfiles library/caddy .github/dependabot.yml -gen-dockerfiles: render-dockerfiles.tmpl Dockerfile.tmpl Dockerfile.builder.tmpl Dockerfile.windows.tmpl Dockerfile.windows-builder.tmpl Dockerfile.nanoserver.tmpl */*/Dockerfile.base +gen-dockerfiles: render-dockerfiles.tmpl Dockerfile.tmpl Dockerfile.builder.tmpl Dockerfile.rootless.tmpl Dockerfile.windows.tmpl Dockerfile.windows-builder.tmpl Dockerfile.nanoserver.tmpl */*/Dockerfile.base @gomplate \ --plugin getChecksums=./getChecksums.sh \ -t dockerfile=Dockerfile.tmpl \ -t builder-dockerfile=Dockerfile.builder.tmpl \ + -t rootless-dockerfile=Dockerfile.rootless.tmpl \ -t windows-dockerfile=Dockerfile.windows.tmpl \ -t windows-builder-dockerfile=Dockerfile.windows-builder.tmpl \ -t nanoserver-dockerfile=Dockerfile.nanoserver.tmpl \ diff --git a/render-dockerfiles.tmpl b/render-dockerfiles.tmpl index 451f8eb..970610c 100644 --- a/render-dockerfiles.tmpl +++ b/render-dockerfiles.tmpl @@ -10,6 +10,8 @@ {{- $template := "dockerfile" }} {{- if eq "builder" $variant.dir -}} {{ $template = "builder-dockerfile" -}} + {{- else if eq "rootless" $variant.dir -}} + {{ $template = "rootless-dockerfile" -}} {{ end -}} {{- if strings.HasPrefix "windows-builder" $variant.dir -}} {{ $template = "windows-builder-dockerfile" -}} diff --git a/stackbrew-config.yaml b/stackbrew-config.yaml index c5b2e5d..dbab1d1 100644 --- a/stackbrew-config.yaml +++ b/stackbrew-config.yaml @@ -19,6 +19,10 @@ variants: tags: [ "builder-alpine" ] shared_tags: [ "builder" ] architectures: [ amd64, arm64v8, arm32v6, arm32v7, ppc64le, riscv64, s390x ] + - dir: rootless + tags: [ "rootless-alpine" ] + shared_tags: [ "rootless" ] + architectures: [ amd64, arm64v8, arm32v6, arm32v7, ppc64le, riscv64, s390x ] - dir: windows/ltsc2022 tags: [ "windowsservercore-ltsc2022" ] shared_tags: [ "windowsservercore", "latest" ] @@ -48,4 +52,4 @@ variants: tags: [ "builder-windowsservercore-ltsc2025" ] shared_tags: [ "builder" ] architectures: [ windows-amd64 ] - constraints: [ windowsservercore-ltsc2025 ] \ No newline at end of file + constraints: [ windowsservercore-ltsc2025 ]