Skip to main content
The easiest way to deploy Caddy Defender is using the pre-built Docker image. This guide walks you through pulling the image, configuring volumes, and running your container.

Quick Start

1

Pull the Docker Image

Pull the latest pre-built Caddy Defender image from GitHub Container Registry:
docker pull ghcr.io/jasonlovesdoggo/caddy-defender:latest
This image includes Caddy with the Defender plugin pre-installed and all standard IP ranges embedded.
2

Prepare Your Caddyfile

Create a Caddyfile with your Defender configuration. For example:
example.com {
    defender block {
        ranges openai aws deepseek
    }
    respond "Hello from Caddy Defender!"
}
Save this file to a known location on your host system, such as /path/to/Caddyfile.
3

Run the Container

Start the container with proper volume mounts and port mappings:
docker run -d \
  --name caddy \
  -v /path/to/Caddyfile:/etc/caddy/Caddyfile \
  -p 80:80 -p 443:443 \
  ghcr.io/jasonlovesdoggo/caddy-defender:latest
Key parameters:
  • -d: Run in detached mode
  • --name caddy: Container name for easy reference
  • -v /path/to/Caddyfile:/etc/caddy/Caddyfile: Mount your Caddyfile
  • -p 80:80 -p 443:443: Expose HTTP and HTTPS ports
4

Verify the Container

Check that the container is running:
docker ps
View the logs to confirm Caddy started successfully:
docker logs caddy

Volume Mounts

Caddyfile Configuration

The Caddyfile must be mounted at /etc/caddy/Caddyfile:
-v /path/to/Caddyfile:/etc/caddy/Caddyfile

Data Directory (Optional)

For persistent TLS certificates and other Caddy data:
-v caddy_data:/data

Config Directory (Optional)

For additional configuration files:
-v caddy_config:/config

Port Mappings

By default, Caddy uses port 80 for HTTP and port 443 for HTTPS. Both should be mapped to your host.
Standard mapping:
-p 80:80 -p 443:443
Custom ports: If you need to use different host ports:
-p 8080:80 -p 8443:443

Docker Compose

For easier management, use Docker Compose:
version: '3.8'

services:
  caddy:
    image: ghcr.io/jasonlovesdoggo/caddy-defender:latest
    container_name: caddy
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddy_data:/data
      - caddy_config:/config

volumes:
  caddy_data:
  caddy_config:
Start with Docker Compose:
docker compose up -d
View logs:
docker compose logs -f caddy
Stop the service:
docker compose down

Advanced Configuration

Running with Custom Network

docker network create caddy-network

docker run -d \
  --name caddy \
  --network caddy-network \
  -v /path/to/Caddyfile:/etc/caddy/Caddyfile \
  -p 80:80 -p 443:443 \
  ghcr.io/jasonlovesdoggo/caddy-defender:latest

Updating the Container

1

Pull the Latest Image

docker pull ghcr.io/jasonlovesdoggo/caddy-defender:latest
2

Stop and Remove Old Container

docker stop caddy
docker rm caddy
3

Start New Container

docker run -d \
  --name caddy \
  -v /path/to/Caddyfile:/etc/caddy/Caddyfile \
  -p 80:80 -p 443:443 \
  ghcr.io/jasonlovesdoggo/caddy-defender:latest
With Docker Compose, updating is simpler:
docker compose pull
docker compose up -d

Troubleshooting

Port Already in Use

If you see an error about ports being in use:
# Check what's using port 80
sudo lsof -i :80

# Or use different host ports
docker run -d --name caddy -p 8080:80 -p 8443:443 ...

Permission Denied on Volume Mount

Ensure your Caddyfile has proper permissions:
chmod 644 /path/to/Caddyfile

Configuration Errors

Test your Caddyfile before running:
docker run --rm \
  -v /path/to/Caddyfile:/etc/caddy/Caddyfile \
  ghcr.io/jasonlovesdoggo/caddy-defender:latest \
  caddy validate --config /etc/caddy/Caddyfile

Next Steps

Configuration

Learn how to configure the Defender plugin

Examples

See real-world configuration examples

Build docs developers (and LLMs) love