xcaddy is the official build tool for Caddy that simplifies building custom binaries with plugins and proper version information.
What is xcaddy?
From README.md:145, xcaddy is our builder tool that automates the build process.
It handles:
Creating proper project structure
Managing Go modules
Injecting version information
Adding custom plugins
Cross-compilation
Installation
Install xcaddy using Go:
go install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
Verify installation:
Ensure $GOPATH/bin is in your PATH to run xcaddy from anywhere.
Basic Usage
Build Standard Caddy
From README.md:148:
This creates a caddy binary in the current directory with:
Proper version information
All standard modules
Platform-specific optimizations
Build Specific Version
Or use a commit hash:
xcaddy build abc123def456
Or a branch:
Building with Plugins
Add a Plugin from GitHub
xcaddy build \
--with github.com/caddyserver/nginx-adapter
Add Multiple Plugins
xcaddy build \
--with github.com/caddyserver/nginx-adapter \
--with github.com/greenpau/caddy-security
Specify Plugin Version
Local Plugin Development
For local plugin development, use a local path:
xcaddy build \
--with github.com/example/caddy-plugin=../caddy-plugin
The local path is relative to where you run xcaddy. Use absolute paths to avoid confusion.
Output Control
Specify Output Path
xcaddy build --output /usr/local/bin/caddy
# Linux AMD64
GOOS = linux GOARCH = amd64 xcaddy build
# Windows AMD64
GOOS = windows GOARCH = amd64 xcaddy build --output caddy.exe
# macOS ARM64 (Apple Silicon)
GOOS = darwin GOARCH = arm64 xcaddy build
# Linux ARM (Raspberry Pi)
GOOS = linux GOARCH = arm GOARM = 7 xcaddy build
What xcaddy Automates
From README.md:151, xcaddy performs these steps automatically:
Copy main.go
Copies Caddy’s main.go and adds plugin imports: import (
_ " time/tzdata "
caddycmd " github.com/caddyserver/caddy/v2/cmd "
_ " github.com/caddyserver/caddy/v2/modules/standard "
// Plugins added by xcaddy
_ " github.com/example/plugin "
)
Pin Caddy version
go get github.com/caddyserver/caddy/v2@version
Add plugin dependencies
go get github.com/example/plugin@version
Build with proper flags
go build -tags=nobadger,nomysql,nopgx
Advanced Options
Replace Modules
Replace a dependency with a fork:
xcaddy build \
--with github.com/caddyserver/caddy/v2=github.com/myuser/caddy/v2@mybranch
Build with Specific Go Version
go1.25.0 install github.com/caddyserver/xcaddy/cmd/xcaddy@latest
go1.25.0 run github.com/caddyserver/xcaddy/cmd/xcaddy build
Disable Module Optimization
By default, xcaddy trims unused dependencies:
xcaddy build --with-trimpath=false
Development Workflow
Quick Iteration
For rapid plugin development:
# Build with local plugin
xcaddy build \
--with github.com/myuser/caddy-plugin=./caddy-plugin
# Test
./caddy run --config test.Caddyfile
# Make changes to plugin...
# Rebuild
xcaddy build \
--with github.com/myuser/caddy-plugin=./caddy-plugin
Using xcaddy run
Test without building:
xcaddy run \
--with github.com/myuser/caddy-plugin=./caddy-plugin \
--config Caddyfile
This builds a temporary binary and runs it immediately.
Build Caching
xcaddy leverages Go’s build cache. Subsequent builds are faster:
# First build (slow)
xcaddy build --with github.com/example/plugin
# Subsequent builds (fast, if plugin unchanged)
xcaddy build --with github.com/example/plugin
Clear the cache if needed:
Environment Variables
Proxy Configuration
export GOPROXY = https :// proxy . golang . org , direct
xcaddy build
Private Repositories
export GOPRIVATE = github . com / myorg / *
xcaddy build --with github.com/myorg/private-plugin
Custom Build Flags
export XCADDY_GO_BUILD_FLAGS = "-ldflags='-s -w' -trimpath"
xcaddy build
Common Plugin Examples
Nginx Config Adapter
Convert Nginx configs to Caddy:
xcaddy build \
--with github.com/caddyserver/nginx-adapter
./caddy adapt --config nginx.conf --adapter nginx
CloudFlare DNS Provider
For DNS-01 ACME challenges:
xcaddy build \
--with github.com/caddy-dns/cloudflare
Rate Limiting
xcaddy build \
--with github.com/mholt/caddy-ratelimit
Multiple Plugins Together
xcaddy build \
--with github.com/caddyserver/nginx-adapter \
--with github.com/caddy-dns/cloudflare \
--with github.com/greenpau/caddy-security \
--with github.com/mholt/caddy-ratelimit
Verification
After building, verify your binary includes plugins:
# List all modules
./caddy list-modules
# Check for specific module
./caddy list-modules | grep plugin_name
# Verify version
./caddy version
Troubleshooting
Module Not Found
Ensure the plugin path is correct and accessible:
# Check if module exists
go get -d github.com/example/plugin
# Then build
xcaddy build --with github.com/example/plugin
Version Conflicts
Specify exact versions:
Permission Denied
On Linux, set capabilities:
sudo setcap cap_net_bind_service=+ep ./caddy
Build Fails with Local Plugin
Ensure your plugin has a go.mod file:
cd caddy-plugin
go mod init github.com/myuser/caddy-plugin
go mod tidy
GOPROXY Timeout
Use direct mode:
GOPROXY = direct xcaddy build \
--with github.com/example/plugin
Comparison with Manual Build
xcaddy (recommended)
Manual Process
xcaddy build \
--with github.com/example/plugin
xcaddy is:
✅ Faster and less error-prone
✅ Handles version information correctly
✅ Manages all dependencies automatically
✅ Supports quick iteration with local plugins
Next Steps
Custom Builds Create production-ready custom builds
Plugin Tutorial Develop your own plugin
Building from Source Manual build process details
Module Development Deep dive into module creation