> ## Documentation Index
> Fetch the complete documentation index at: https://mintlify.com/TecharoHq/Anubis/llms.txt
> Use this file to discover all available pages before exploring further.

# Caddy Deployment

> Deploy Anubis behind Caddy reverse proxy

Caddy is a modern HTTP server with automatic HTTPS. This guide shows how to deploy Anubis behind Caddy.

## Basic Configuration

Caddy makes it simple to set up a reverse proxy with automatic TLS. Here's a minimal Caddyfile:

```caddy theme={null}
example.com {
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
  }
}
```

Caddy automatically:

* Obtains and renews TLS certificates via Let's Encrypt
* Redirects HTTP to HTTPS
* Sets HTTP/2 and HTTP/3

## Complete Example

Here's a production-ready setup with all recommended headers:

**Caddyfile:**

```caddy theme={null}
:80 {
  reverse_proxy http://anubis:3000 {
    header_up X-Real-IP {remote_host}
    header_up X-Http-Version {http.request.proto}
  }
}

:443 {
  tls /etc/certs/cert.pem /etc/certs/key.pem
  
  reverse_proxy http://anubis:3000 {
    header_up X-Real-IP {remote_host}
    header_up X-Http-Version {http.request.proto}
    header_up X-Tls-Version {http.request.tls.version}
  }
}
```

**docker-compose.yml:**

```yaml theme={null}
services:
  caddy:
    image: caddy:latest
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./certs:/etc/certs:ro
      - caddy_data:/data
      - caddy_config:/config
    depends_on:
      - anubis

  anubis:
    image: ghcr.io/techarohq/anubis:main
    environment:
      BIND: ":3000"
      TARGET: "http://backend:8080"
      POLICY_FNAME: "/etc/techaro/anubis/policy.yaml"
    volumes:
      - ./anubis-config:/etc/techaro/anubis

  backend:
    image: your-app:latest
    expose:
      - "8080"

volumes:
  caddy_data:
  caddy_config:
```

## Automatic HTTPS

For automatic HTTPS with Let's Encrypt:

```caddy theme={null}
example.com {
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
    header_up X-Forwarded-For {remote_host}
  }
}
```

Caddy automatically:

1. Obtains a TLS certificate from Let's Encrypt
2. Renews certificates before expiration
3. Redirects HTTP to HTTPS

No additional configuration needed!

## Custom TLS Certificates

To use your own certificates:

```caddy theme={null}
example.com {
  tls /path/to/cert.pem /path/to/key.pem
  
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
  }
}
```

## Multiple Backends

Protect multiple applications with one Anubis instance:

```caddy theme={null}
# Protected site 1
site1.example.com {
  reverse_proxy anubis:3000
}

# Protected site 2
site2.example.com {
  reverse_proxy anubis:3000
}

# Unprotected site
unprotected.example.com {
  reverse_proxy backend:8080
}
```

Configure Anubis to accept multiple domains:

```bash theme={null}
anubis --cookie-domain example.com \
       --redirect-domains site1.example.com,site2.example.com \
       --bind :3000
```

## Path-Based Routing

Protect only specific paths:

```caddy theme={null}
example.com {
  # Protected admin area
  reverse_proxy /admin/* anubis:3000
  
  # Public content goes directly to backend
  reverse_proxy backend:8080
}
```

Note: This requires configuring Anubis with `--base-prefix /admin`.

## Header Configuration

Caddy automatically sets several headers, but you can customize them:

```caddy theme={null}
example.com {
  reverse_proxy anubis:3000 {
    # Client IP
    header_up X-Real-IP {remote_host}
    header_up X-Forwarded-For {remote_host}
    
    # Protocol information
    header_up X-Forwarded-Proto {scheme}
    header_up X-Forwarded-Host {host}
    
    # TLS information
    header_up X-Tls-Version {http.request.tls.version}
    header_up X-Tls-Cipher {http.request.tls.cipher_suite}
  }
}
```

## Placeholders

Caddy provides many useful placeholders:

* `{remote_host}` - Client IP address
* `{scheme}` - http or https
* `{host}` - Host header value
* `{method}` - HTTP method
* `{uri}` - Request URI
* `{http.request.proto}` - HTTP version
* `{http.request.tls.version}` - TLS version
* `{http.request.tls.cipher_suite}` - TLS cipher suite

See [Caddy placeholders](https://caddyserver.com/docs/caddyfile/concepts#placeholders) for the complete list.

## Health Checks

Caddy can perform active health checks on Anubis:

```caddy theme={null}
example.com {
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
    
    health_uri /healthz
    health_port 9090
    health_interval 10s
    health_timeout 5s
  }
}
```

This checks Anubis metrics endpoint every 10 seconds.

## Load Balancing

Run multiple Anubis instances behind Caddy:

```caddy theme={null}
example.com {
  reverse_proxy anubis1:3000 anubis2:3000 anubis3:3000 {
    header_up X-Real-IP {remote_host}
    
    lb_policy round_robin
    lb_try_duration 5s
    
    health_uri /healthz
    health_port 9090
  }
}
```

Important: All Anubis instances must share the same signing key:

```bash theme={null}
# Generate key once
openssl rand -hex 32 > anubis-key.txt

# Use on all instances
anubis --ed25519-private-key-hex-file /secrets/anubis-key.txt
```

## Logging

Customize access logs:

```caddy theme={null}
example.com {
  log {
    output file /var/log/caddy/access.log {
      roll_size 100mb
      roll_keep 10
    }
    format json
  }
  
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
  }
}
```

## Advanced Configuration

### Custom Error Pages

```caddy theme={null}
example.com {
  handle_errors {
    @502 `{http.error.status_code} == 502`
    handle @502 {
      respond "Service temporarily unavailable" 502
    }
  }
  
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
  }
}
```

### Rate Limiting

Caddy can rate limit before reaching Anubis:

```caddy theme={null}
example.com {
  rate_limit {
    zone example_zone 1m 100r/s
  }
  
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
  }
}
```

Note: This requires the [caddy-ratelimit](https://github.com/mholt/caddy-ratelimit) plugin.

### Request Buffering

```caddy theme={null}
example.com {
  reverse_proxy anubis:3000 {
    header_up X-Real-IP {remote_host}
    
    # Buffer requests up to 10MB
    flush_interval -1
    request_buffers 10MB
  }
}
```

## Testing

Test your Caddy configuration:

```bash theme={null}
# Validate Caddyfile syntax
caddy validate --config Caddyfile

# Test with curl
curl -v https://example.com

# Check headers received by Anubis
curl -H "X-Forwarded-For: 1.2.3.4" http://localhost:3000/
```

## Troubleshooting

### Certificate Issues

If Let's Encrypt certificates fail:

```bash theme={null}
# Check Caddy logs
docker logs caddy

# Ensure port 80 is accessible for ACME challenge
curl http://example.com/.well-known/acme-challenge/test
```

### IP Address Not Detected

Verify Anubis receives the correct IP:

1. Don't use `--use-remote-address` when behind Caddy
2. Ensure `header_up X-Real-IP {remote_host}` is set
3. Check Anubis logs for received IP

### Connection Refused

Check that:

1. Anubis is running: `docker ps`
2. Anubis is listening on correct port
3. Network connectivity: `docker exec caddy wget -O- http://anubis:3000/`

## Resources

* [Caddy Documentation](https://caddyserver.com/docs/)
* [Reverse Proxy Directive](https://caddyserver.com/docs/caddyfile/directives/reverse_proxy)
* [Automatic HTTPS](https://caddyserver.com/docs/automatic-https)
