Skip to main content
Deploy or upgrade the Caddy reverse proxy across all machines in the cluster with zero-downtime rolling updates.

Usage

uc caddy deploy [OPTIONS]

Options

--caddyfile
string
Path to a custom global Caddy config (Caddyfile) that will be prepended to the auto-generated configuration
--image
string
Caddy Docker image to deploy (default: latest stable version from Docker Hub)
--machine, -m
string[]
Machine names or IDs to deploy to. Can be specified multiple times or as a comma-separated list. If not specified, deploys to all machines

Description

The caddy deploy command deploys or upgrades the Caddy reverse proxy service across your cluster. Caddy runs in global mode, meaning one container runs on each machine to handle incoming HTTP/HTTPS traffic.

What It Does

  1. Checks current state: Inspects any existing Caddy deployment
  2. Creates deployment plan: Shows what will change (new containers, updates, removals)
  3. Asks for confirmation: Prompts you to approve the plan
  4. Performs rolling update: Updates containers one at a time to avoid downtime
  5. Updates DNS records: Configures cluster domain to point to reachable machines

Rolling Updates

When upgrading an existing Caddy deployment, containers are updated one at a time:
  • New container starts on a machine
  • Health checks verify it’s working
  • Old container stops
  • Process repeats for the next machine
This ensures zero downtime for your services.

Examples

Initial Caddy deployment

Deploy Caddy for the first time:
uc caddy deploy
Output:
Service: caddy (not running)

Preparing a deployment plan...
Target image: caddy:2.8.4 (latest stable)

This will run a Caddy container on each machine.

Deployment plan:
  + Create container caddy-a1b2 on machine oracle-vm (10.210.0.2)
  + Create container caddy-c3d4 on machine hetzner-server (10.210.1.2)

Continue? [y/N]: y

[+] Deploying service caddy (global mode) 2/2
 ✔ Container caddy-a1b2 on oracle-vm        Started
 ✔ Container caddy-c3d4 on hetzner-server   Started

Updating cluster domain records...
DNS records updated:
  *.abc123.cluster.uncloud.run  A → 152.67.101.197, 5.223.45.199

Upgrade Caddy version

Upgrade to a specific Caddy version:
uc caddy deploy --image caddy:2.9.0
Output:
Service: caddy (global mode)
Current image: caddy:2.8.4
Target image: caddy:2.9.0

Preparing a deployment plan...

Deployment plan:
  ↻ Update container caddy-a1b2 on machine oracle-vm
  ↻ Update container caddy-c3d4 on machine hetzner-server

Continue? [y/N]: y

[+] Deploying service caddy (global mode) 2/2
 ✔ Container caddy-e5f6 on oracle-vm        Started
 ✔ Container caddy-a1b2 on oracle-vm        Removed
 ✔ Container caddy-g7h8 on hetzner-server   Started
 ✔ Container caddy-c3d4 on hetzner-server   Removed

Deploy with custom Caddyfile

Add custom global configuration (rate limiting, authentication, etc.):
uc caddy deploy --caddyfile ./custom-caddy.conf
Example custom-caddy.conf:
{
    # Global options
    email [email protected]
    
    # Rate limiting
    servers {
        protocols h1 h2 h3
    }
}

# Custom error pages
(error_pages) {
    handle_errors {
        respond "{err.status_code} {err.status_text}"
    }
}

Deploy to specific machines

Deploy Caddy only to edge machines:
uc caddy deploy -m edge-1,edge-2,edge-3
Or using multiple flags:
uc caddy deploy -m edge-1 -m edge-2 -m edge-3
Deploying to specific machines is useful for edge deployments or when you want to control which machines handle public traffic.

DNS Record Updates

After deployment, Caddy automatically updates your cluster domain DNS records to point to machines running Caddy containers. Only internet-reachable machines are included in the DNS records. If no machines are reachable from the internet:
DNS records for domain 'abc123.cluster.uncloud.run' could not be updated as there 
are no internet-reachable machines running caddy containers.

Possible solutions:
- Ensure your machines have public IP addresses
- Use --public-ip flag when adding machines to override detected IPs
- Check firewall settings on your machines
- Configure port forwarding if behind NAT

Configuration Priority

Caddy uses configuration from multiple sources in this order:
  1. Custom Caddyfile (via --caddyfile flag) - prepended first
  2. Auto-generated config - created from service port definitions
  3. Service-specific Caddy config - from x-caddy in compose files
Custom Caddyfile configuration is prepended to the auto-generated config. Make sure your custom directives don’t conflict with auto-generated ones.

When to Use

Run uc caddy deploy:
  • After initializing your first cluster
  • When upgrading to a new Caddy version
  • After adding new machines to the cluster
  • When modifying global Caddy configuration
  • To fix Caddy containers that stopped unexpectedly

Build docs developers (and LLMs) love