8.3 KiB
8.3 KiB
name, description
| name | description |
|---|---|
| caddy-ssl-termination | 专门用于 Traefik 前置 Caddy 进行 SSL 卸载的架构配置,适用于 K3s 环境。 |
Caddy SSL Termination Skill
Architecture Overview
Setup: Traefik (routing) → Caddy (HTTPS/SSL termination) → HTTP backend
- Caddy: Handles HTTPS (443) with automatic SSL certificates, forwards to Traefik on HTTP (80)
- Traefik: Routes HTTP traffic to appropriate backend services
- Flow: Internet → Caddy:443 (HTTPS) → Traefik:80 (HTTP) → Backend Pods
Quick Configuration Template
1. Basic Caddyfile Structure
# /etc/caddy/Caddyfile
# Domain configuration
example.com {
reverse_proxy traefik-service:80
}
# Multiple domains
app1.example.com {
reverse_proxy traefik-service:80
}
app2.example.com {
reverse_proxy traefik-service:80
}
# Wildcard subdomain (requires DNS wildcard)
*.example.com {
reverse_proxy traefik-service:80
}
2. ConfigMap for Caddyfile
apiVersion: v1
kind: ConfigMap
metadata:
name: caddy-config
namespace: default
data:
Caddyfile: |
# Global options
{
email your-email@example.com
# Use Let's Encrypt staging for testing
# acme_ca https://acme-staging-v02.api.letsencrypt.org/directory
}
# Your domains
example.com {
reverse_proxy traefik-service:80 {
header_up Host {host}
header_up X-Real-IP {remote}
header_up X-Forwarded-For {remote}
header_up X-Forwarded-Proto {scheme}
}
}
3. Caddy Deployment
apiVersion: apps/v1
kind: Deployment
metadata:
name: caddy
namespace: default
spec:
replicas: 1
selector:
matchLabels:
app: caddy
template:tadata:
labels:
app: caddy
spec:
containers:
- name: caddy
image: caddy:latest
ports:
- containerPort: 80
- containerPort: 443
- containerPort: 2019 # Admin API
volumeMounts:
- name: config
mountPath: /etc/caddy
- name: data
mountPath: /data
- name: config-cache
mountPath: /config
volumes:
- name: config
configMap:
name: caddy-config
- name: data
persistentVolumeClaim:
claimName: caddy-data
- name: config-cache
emptyDir: {}
---
apiVersion: v1
kind: Service
metadata:
name: caddy
namespace: default
spec:
type: LoadBalancer # or NodePort
ports:
- name: http
port: 80
targetPort: 80
- name: https
port: 443
targetPort: 443
selector:
app: caddy
---
apiVersion: v1
kind: PersistentVolumeClaim
metadata:
name: caddy-data
namespace: default
spec:
accessModes:
- ReadWriteOnce
resources:
requests:
storage: 1Gi
Common Operations
Reload Configuration
After updating the ConfigMap:
# Method 1: Reload via exec (preserves connections)
kubectl exec -n default deployment/caddy -- caddy reload --config /etc/caddy/Caddyfile
# Method 2: Restart pod (brief downtime)
kubectl rollout restart deployment/caddy -n default
# Method 3: Delete pod (auto-recreates)
kubectl delete pod -n default -l app=caddy
Update Caddyfile
# Edit ConfigMap
kubectl edit configmap caddy-config -n default
# Or apply updated file
kubectl apply -f caddy-configmap.yaml
# Then reload
kubectl exec -n default deployment/caddy -- caddy reload --config /etc/caddy/Caddyfile
View Logs
# Follow logs
kubectl logs -n default -f deployment/caddy
# Check SSL certificate issues
kubectl logs -n default deployment/caddy | grep -i "certificate\|acme\|tls"
Check Configuration
# Validate Caddyfile syntax
kubectl exec -n default deployment/caddy -- caddy validate --config /etc/caddy/Caddyfile
# View current config via API
kubectl exec -n default deployment/caddy -- curl localhost:2019/config/
Adding New Domain
Step-by-step Process
-
Update DNS: Point new domain to Caddy's LoadBalancer IP
kubectl get svc caddy -n default -o jsonpath='{.status.loadBalancer.ingress[0].ip}' -
Update ConfigMap: Add new domain block
kubectl edit configmap caddy-config -n defaultAdd:
newapp.example.com { reverse_proxy traefik-service:80 { header_up Host {host} header_up X-Real-IP {remote} header_up X-Forwarded-For {remote} header_up X-Forwarded-Proto {scheme} } } -
Reload Caddy:
kubectl exec -n default deployment/caddy -- caddy reload --config /etc/caddy/Caddyfile -
Verify: Check logs for certificate acquisition
kubectl logs -n default deployment/caddy | tail -20
Traefik Integration
Traefik IngressRoute Example
apiVersion: traefik.containo.us/v1alpha1
kind: IngressRoute
metadata:
name: myapp
namespace: default
spec:
entryPoints:
- web # HTTP only, Caddy handles HTTPS
routes:
- match: Host(`myapp.example.com`)
kind: Rule
services:
- name: myapp-service
port: 8080
Important Notes
- Traefik should listen on HTTP (80) only
- Caddy handles all HTTPS/SSL
- Use
Host()matcher in Traefik to route by domain - Caddy forwards the original
Hostheader to Traefik
Troubleshooting
SSL Certificate Issues
# Check certificate status
kubectl exec -n default deployment/caddy -- caddy list-certificates
# View ACME logs
kubectl logs -n default deployment/caddy | grep -i acme
# Common issues:
# - Port 80/443 not accessible from internet
# - DNS not pointing to correct IP
# - Rate limit hit (use staging CA for testing)
Configuration Errors
# Test config before reload
kubectl exec -n default deployment/caddy -- caddy validate --config /etc/caddy/Caddyfile
# Check for syntax errors
kubectl logs -n default deployment/caddy | grep -i error
Connection Issues
# Test from inside cluster
kubectl run -it --rm debug --image=curlimages/curl --restart=Never -- curl -v http://traefik-service:80
# Check if Caddy can reach Traefik
kubectl exec -n default deployment/caddy -- curl -v http://traefik-service:80
Advanced Configurations
Custom TLS Settings
example.com {
tls {
protocols tls1.2 tls1.3
ciphers TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384
}
reverse_proxy traefik-service:80
}
Rate Limiting
example.com {
rate_limit {
zone dynamic {
key {remote_host}
events 100
window 1m
}
}
reverse_proxy traefik-service:80
}
Custom Error Pages
example.com {
handle_errors {
respond "{err.status_code} {err.status_text}"
}
reverse_proxy traefik-service:80
}
Health Checks
example.com {
reverse_proxy traefik-service:80 {
health_uri /health
health_interval 10s
health_timeout 5s
}
}
Quick Reference Commands
# Get Caddy pod name
kubectl get pods -n default -l app=caddy
# Reload config
kubectl exec -n default deployment/caddy -- caddy reload --config /etc/caddy/Caddyfile
# View current config
kubectl exec -n default deployment/caddy -- cat /etc/caddy/Caddyfile
# Check certificates
kubectl exec -n default deployment/caddy -- caddy list-certificates
# Restart Caddy
kubectl rollout restart deployment/caddy -n default
# Watch logs
kubectl logs -n default -f deployment/caddy
# Get LoadBalancer IP
kubectl get svc caddy -n default -o jsonpath='{.status.loadBalancer.ingress[0].ip}'
Checklist for New Service
- DNS A/AAAA record points to Caddy LoadBalancer IP
- Domain added to Caddy ConfigMap
- Caddy reloaded successfully
- Traefik IngressRoute created (HTTP only)
- Backend service accessible from Traefik
- SSL certificate acquired (check logs)
- HTTPS access working from browser
- HTTP redirects to HTTPS (Caddy default behavior)
Notes
- Caddy automatically obtains and renews SSL certificates
- Certificates stored in
/datavolume (must be persistent) - Reload is graceful - no connection drops
- Caddy handles HTTP→HTTPS redirect automatically
- Use staging CA for testing to avoid rate limits
- Wildcard certificates require DNS challenge (more complex setup)