从 Nginx 迁移到 Caddy

文章目录

  1. After
  2. Before

我的家庭内网中部署了若干 http 服务,为了使用方便,统一使用 Nginx 做了反代以及 https 证书分配,最近我发现 Caddy 在我的使用场景下比 Nginx 更简洁、方便管理。

After

我的家庭内网是在 2024 年搭建的,当时为了给 Nginx 反代配置 h3 和 https 证书自动更新,费了好大一番手脚。 尤其是这个 https 证书自动更新,更是让我吃了一番苦头。

刚开始我便尝试使用过 Traefik 和 Caddy,因为它们两可以自动托管并更新 https 证书。我的域名托管在 Cloudflare 上,因此需要通过 DNS-01 来生成证书。

但在初期的部署过程中,Traefik、Caddy、ACME.sh 都存在获取不到 DNS 记录导致超时的问题,我百般排查不得其解。

排查良久后认为是 DNS 的问题,使用 AI 结合 go-acme 做了一个生成 https 证书的网关程序:https://github.com/vhvy/acme-gateway-go

原理也很简单,在 Docker 容器内通过 iptables 劫持 lego 客户端的 DNS 请求,强制递归转发给 Cloudflare 的 DoH,以便获取最新的 DNS 记录信息。

问题虽然是解决了,但我总觉得这套配置太过冗余,直到前不久,我发现了 Caddy 的 propagation_timeout 参数。

Before

Caddy 的 propagation_timeout 参数可以跳过 DNS 传播检查,直接让 ACME 服务器去 Cloudflare 那边查询,免去了本地 DNS 各种异常的问题。

说干就干,结合 AI 花了半小时将 Nginx 迁移到了 Caddy,不得不说 Caddy 的配置真的是简洁,h3websockets 不用任何额外配置,https 证书续期配置也非常方便,Caddy 真好用!

需要注意的是,Caddy 没有直接集成 Cloudflare 的 DNS Challenge 服务,需要手动编译,或者使用社区提供的 Docker 镜像: ghcr.io/caddy-dns/cloudflare

在内网环境下,还可以使用静态文件服务提供生成的泛域名证书,让一些不需要反代的服务如 Mikrotik Web 服务、群晖 NAS 等也可以方便的定时拉取并更新证书。

这里贴一下我的大概配置:

Docker compose 配置文件:

services:
  caddy:
    image: ghcr.io/caddy-dns/cloudflare:v0.2.4
    container_name: caddy
    restart: unless-stopped
    network_mode: host
    env_file: ./.env
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile:ro
      - ./data:/data
      - ./config:/config

Caddy 配置文件:

{
	email example@example.com
}

(cf) {
	tls {
		dns cloudflare {env.CF_API_TOKEN}
		propagation_delay 60s
		propagation_timeout -1
	}
}

(insecure_tls) {
	transport http {
		tls_insecure_skip_verify
	}
}

*.example.com {
	import cf
	abort
}

demo.example.com {
	reverse_proxy 192.168.1.111:36180
}

demo2.example.com {
	redir / /web 301
	reverse_proxy https://192.168.1.112:44233 {
		import insecure_tls
	}
}

# curl https://ssl.example.com/example.com/cert.key
# curl https://ssl.example.com/example.com/cert.crt

ssl.example.com {
	root * /data/caddy/certificates/acme-v02.api.letsencrypt.org-directory

	@cert {
		remote_ip 192.168.1.0/24
		header X-Token "THISISMYTOKEN"
		path_regexp c ^/([^/]+)/cert\.(crt|key)$
	}

	handle @cert {
		rewrite * /wildcard_.{re.c.1}/wildcard_.{re.c.1}.{re.c.2}
		file_server
	}

	handle {
		respond 404
	}
}

Powered By Hexo & Theme Veni