# Caddy Reverse Proxy on Chinese Servers

Caddy is a simpler alternative to Nginx for reverse proxy + auto-SSL on Chinese cloud servers. Less config, automatic Let's Encrypt, and no certbot cron jobs.

## Quick Setup (Ubuntu)

```bash
sudo apt-get install -y caddy
```

## Caddyfile Template

```caddyfile
# Global block: email + ACME CA
{
    email admin@yourdomain.com
    acme_ca https://acme-v02.api.letsencrypt.org/directory
}

# Simple reverse proxy — Caddy handles SSL automatically
sub.example.com {
    reverse_proxy localhost:8001
    encode gzip
}

# Multiple domains → same backend
callback.example.com, bot.example.com {
    reverse_proxy localhost:8645
}
```

## HTTP-Only Mode (During DNS Transition)

When DNS still points to Cloudflare proxy, Let's Encrypt HTTP-01 challenges can't reach Caddy. Use `http://` prefix to run without TLS during transition:

```caddyfile
# Phase 1: HTTP-only (DNS not yet pointing here)
http://sub.example.com {
    reverse_proxy localhost:8001
}
```

After DNS cutover → remove `http://` prefix → `sudo systemctl restart caddy` → auto-obtains certs.

## Pitfalls

### PITFALL: Caddy 2.6.x ZeroSSL EAB failure
Caddy 2.6.2 (Ubuntu 24.04 apt default) fails to get ZeroSSL EAB credentials (HTTP 422: `caddy_legacy_user_removed`). **Fix**: always set `acme_ca https://acme-v02.api.letsencrypt.org/directory` in the global block.

### PITFALL: Caddy won't bind ports without valid certificate
When TLS cert acquisition fails, Caddy does NOT listen on 80/443 at all. The process starts but `ss -tlnp | grep caddy` shows nothing. Use `http://` prefix mode as a workaround during DNS transition.

### PITFALL: Let's Encrypt HTTP-01 behind Cloudflare proxy
If DNS is proxied through Cloudflare (orange cloud), HTTP-01 challenges go to CF edge, not Caddy. Caddy sees `no solvers available for remaining challenges (remaining=[dns-01])`. Solution: switch DNS to gray cloud (DNS-only) first, then Caddy auto-obtains certs.

### Firewall: Lighthouse calls it "防火墙" not "安全组"
腾讯云 轻量应用服务器 → 实例详情 → 防火墙 → 添加规则 → TCP 80 + TCP 443 → 所有IP (0.0.0.0/0)

### Caddyfile validation
```bash
sudo caddy validate --config /etc/caddy/Caddyfile
sudo caddy fmt --overwrite /etc/caddy/Caddyfile  # auto-format
sudo systemctl restart caddy
```

## HTTPS Upgrade After DNS Cutover

```bash
# 1. Edit Caddyfile: remove http:// prefix from all site blocks
# 2. Reload
sudo systemctl restart caddy
# 3. Caddy auto-obtains Let's Encrypt certs (may take 1-2 min)
sudo journalctl -u caddy -f
```

## Cloudflare Latency Diagnosis

When a China-facing site is slow behind Cloudflare proxy:

```bash
# Breakdown where time is spent
curl -s -w "DNS: %{time_namelookup}s | TCP: %{time_connect}s | SSL: %{time_appconnect}s | TTFB: %{time_starttransfer}s | Total: %{time_total}s\n" -o /dev/null https://site

# Check CF data center location (critical)
curl -sI https://site | grep cf-ray
# cf-ray: a18c543d6f8f0bb4-AMS  ← AMS = Amsterdam → bad for China
```

**Interpretation**: TTFB > 1s + CF data center outside Asia = the CF proxy is adding 1-2s of latency. Cloudflare free tier has NO mainland China edge nodes. Domestic users get routed through AMS/SIN/NRT.

**Fix**: Switch to DNS-only mode (gray cloud) in Cloudflare DNS panel, point A record directly to origin server IP. TTFB drops from 1.5s to <0.1s.
