Extending Caddy Functionality by Installing Modules

Sep 24, 2025 · 2 min read · 282 Words · -Views -Comments

I recently had a requirement where I needed Caddy to inject a custom JavaScript snippet into the HTML responses of a proxied web service. After some research, I found that this can be achieved by installing a specific Caddy module. Since I hadn’t worked with Caddy modules before, I spent some time learning how to install and configure them.

Caddy’s Modular Architecture

Caddy is built as a collection of modules. While the default distribution includes the most common features, it doesn’t include everything—even official modules. To add a specific module, you must recompile Caddy with that module included.

Checking Installed Modules

You can verify which modules are currently active in your Caddy binary using the following commands:


# List all installed modules
caddy list-modules

# Search for a specific module (e.g., 'replace')
caddy list-modules | grep replace

Customizing Caddy via Docker

I needed the replace-response module. Since I run Caddy via Docker, the best approach was to create a custom Docker image using a multi-stage build. Here is the Dockerfile:

# Use the official Caddy builder image
FROM caddy:2-builder AS builder

# Build Caddy with the desired external module
RUN xcaddy build \
    --with github.com/caddyserver/replace-response

# Switch to the standard Caddy runtime image
FROM caddy:2

# Replace the default binary with the custom-built one
COPY --from=builder /usr/bin/caddy /usr/bin/caddy

Run docker build -t my-caddy . to build the image. You will then have a my-caddy image that includes the replace-response functionality.

Final Thoughts

By following these steps, we successfully added a custom module to Caddy. Using a Docker multi-stage build is an efficient way to manage dependencies and ensures that your custom Caddy environment remains consistent across different deployments.

Resources

Authors
Developer, digital product enthusiast, tinkerer, sharer, open source lover