Skip to content

Conversation

@i5okie
Copy link

@i5okie i5okie commented Nov 19, 2025

Add rootless Docker images for enhanced security and Kubernetes/OpenShift compatibility

Purpose

This PR adds rootless variants of the Caddy Docker images that run as a non-root user (UID 1001), making them suitable for security-constrained environments like Kubernetes and OpenShift, while remaining a drop-in replacement for the alpine images.

Why rootless?

Security best practices: Running containers as root is discouraged in production environments. Non-root containers provide defense-in-depth by limiting the impact of potential container breakouts or exploits.

Kubernetes/OpenShift requirements: Many Kubernetes clusters enforce Pod Security Standards that prohibit root containers. OpenShift, in particular, assigns arbitrary UIDs to containers by default and requires images to support this pattern.

Port restrictions: Non-root users cannot bind to privileged ports (< 1024). Using ports 80 and 443 in Kubernetes is problematic anyway since:

  • Services and Ingress controllers handle external traffic routing
  • Internal container ports are mapped through service definitions
  • Non-privileged ports (8080, 8443) are the standard convention

What's included

New image variants:

  • caddy:rootless - Rootless runtime image (ports 8080, 8443, 2019)
  • caddy:rootless-builder - Rootless builder image for custom Caddy builds with xcaddy

Key features:

  • Runs as UID 1001 with GID 0 (root group) for OpenShift compatibility
  • Automatically uses ports 8080/8443 via environment variables
  • Drop-in replacement for standard images - just change the tag
  • All directories writable by group 0 for arbitrary UID support
  • Uses the standard Caddyfile with automatic port substitution

Implementation details:
The rootless templates are based on the standard alpine templates with these modifications:

  • Removed setcap capability (not needed for non-privileged ports)
  • Added non-root user creation with adduser -D -u 1001 -g 0
  • Set proper ownership (chown 1001:0) and group permissions (chmod g+w) on all Caddy directories
  • Downloads the standard Caddyfile and uses sed to replace :80 with :{$CADDY_HTTP_PORT:8080}
  • Sets CADDY_HTTP_PORT=8080 and CADDY_HTTPS_PORT=8443 environment variables
  • Changed exposed ports from 80/443 to 8080/8443
  • Added USER 1001 directive to run as non-root
  • Users can mount custom Caddyfiles that reference these env vars or hardcode ports

Testing

Built and tested locally - serves the welcome page on port 8080 as expected. The image runs without root privileges and properly serves static content.

@i5okie
Copy link
Author

i5okie commented Nov 24, 2025

Is anyone available to take a look at this and offer feedback? There are several issues discussing the need for a rootless image.

Our team is working on several Hyperledger and OpenWallet Foundation projects utilizing Caddy server as a reverse proxy.
I've discovered that most of our deployments use older Caddy images and are working properly in a government maintained OpenShift platform. I'm working on creating helm charts for some of these projects. When attempting to use the latest caddy docker images, the deployments fail due to strict SCC rules in OpenShift. When developing helm charts which are meant to be used by the wider community, and be compatible with the government platform, using an initContainer to copy the binary into an arbitrary directory to bypass the issues, is not ideal. It does not look like a professional and robust solution to the problem. This PR should solve this issue. Not just for our projects, but for the wider community overall. And hopefully boost Caddy Server's use across the community :).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant