文档
一个 项目

常用 Caddyfile 模式

此页面演示了一些完整且最简的 Caddyfile 配置,用于常见的用例。这些可以作为您自己的 Caddyfile 文档的有用起点。

这些不是可以直接使用的解决方案;您将必须自定义您的域名、端口/套接字、目录路径等。它们旨在说明一些最常见的配置模式。

静态文件服务器

example.com {
	root * /var/www
	file_server
}

通常,第一行是站点地址。root 指令指定站点的根路径(* 表示匹配所有请求,以便与路径匹配器区分开来)——如果您的站点不是当前工作目录,请更改路径。最后,我们启用静态文件服务器

反向代理

代理所有请求

example.com {
	reverse_proxy localhost:5000
}

仅代理路径以 /api/ 开头的请求,并为其他所有内容提供静态文件

example.com {
	root * /var/www
	reverse_proxy /api/* localhost:5000
	file_server
}

这使用请求匹配器来仅匹配以 /api/ 开头的请求,并将它们代理到后端。所有其他请求将从站点root使用静态文件服务器提供。这也取决于 reverse_proxy指令顺序中高于 file_server 的事实。

这里有更多reverse_proxy 示例

PHP

PHP-FPM

对于运行中的 PHP FastCGI 服务,类似这样的配置适用于大多数现代 PHP 应用程序

example.com {
	root * /srv/public
	encode
	php_fastcgi localhost:9000
	file_server
}

相应地自定义站点根目录;此示例假设您的 PHP 应用程序的 webroot 在 public 目录中——对磁盘上存在的文件的请求将通过file_server提供,其他任何内容都将路由到 index.php 以供 PHP 应用程序处理。

您有时可以使用 unix 套接字连接到 PHP-FPM

php_fastcgi unix//run/php/php8.2-fpm.sock

php_fastcgi 指令实际上只是几个配置片段的快捷方式。

FrankenPHP

或者,您可以使用 FrankenPHP,它是 Caddy 的一个发行版,它使用 CGO(Go 到 C 绑定)直接调用 PHP。这可能比使用 PHP-FPM 快 4 倍,如果您可以使用 worker 模式,效果会更好。

{
    frankenphp
    order php_server before file_server
}

example.com {
	root * /srv/public
    encode zstd br gzip
    php_server
}

重定向 www. 子域名

添加带有 HTTP 重定向的 www. 子域名

example.com {
	redir https://www.{host}{uri}
}

www.example.com {
}

移除

www.example.com {
	redir https://example.com{uri}
}

example.com {
}

要为多个域名一次性移除它;这使用 {labels.*} 占位符,它们是主机名的部分,从右侧 0 索引(例如 0=com, 1=example-one, 2=www

www.example-one.com, www.example-two.com {
	redir https://{labels.1}.{labels.0}{uri}
}

example-one.com, example-two.com {
}

尾部斜杠

您通常不需要自己配置此项;file_server 指令将通过 HTTP 重定向自动添加或删除请求中的尾部斜杠,具体取决于请求的资源是目录还是文件。

但是,如果需要,您仍然可以使用配置强制尾部斜杠。有两种方法可以做到这一点:内部或外部。

内部强制

这使用rewrite指令。Caddy 将在内部重写 URI 以添加或删除尾部斜杠

example.com {
	rewrite /add     /add/
	rewrite /remove/ /remove
}

使用重写,带有和不带有尾部斜杠的请求将是相同的。

外部强制

这使用redir指令。Caddy 将要求浏览器更改 URI 以添加或删除尾部斜杠

example.com {
	redir /add     /add/
	redir /remove/ /remove
}

使用重定向,客户端将必须重新发出请求,从而为一个资源强制执行单个可接受的 URI。

通配符证书

如果您需要使用相同的通配符证书服务多个子域名,最好的处理方法是使用像这样的 Caddyfile,利用handle 指令host 匹配器

*.example.com {
	tls {
		dns <provider_name> [<params...>]
	}

	@foo host foo.example.com
	handle @foo {
		respond "Foo!"
	}

	@bar host bar.example.com
	handle @bar {
		respond "Bar!"
	}

	# Fallback for otherwise unhandled domains
	handle {
		abort
	}
}

您必须启用 ACME DNS 挑战才能让 Caddy 自动管理通配符证书。

单页应用 (SPA)

当网页执行自己的路由时,服务器可能会收到大量针对服务器端不存在的页面的请求,但只要提供单个索引文件,这些页面就可以在客户端呈现。像这样架构的 Web 应用程序被称为 SPA 或单页应用程序。

主要思想是让服务器“尝试文件”以查看请求的文件是否在服务器端存在,如果不存在,则回退到索引文件,客户端在其中进行路由(通常使用客户端 JavaScript)。

典型的 SPA 配置通常如下所示

example.com {
	root * /srv
	encode
	try_files {path} /index.html
	file_server
}

如果您的 SPA 与 API 或其他仅限服务器端的端点耦合,您将需要使用 handle 块来专门处理它们

example.com {
	encode

	handle /api/* {
		reverse_proxy backend:8000
	}

	handle {
		root * /srv
		try_files {path} /index.html
		file_server
	}
}

如果您的 index.html 包含对带有哈希文件名的 JS/CSS 资产的引用,您可能需要考虑添加 Cache-Control 标头来指示客户端不要缓存它(以便如果资产更改,浏览器会获取新的资产)。由于 try_files 重写用于从与磁盘上的另一个文件不匹配的任何路径提供您的 index.html,您可以将 try_filesroute 包装在一起,以便 header 处理程序在重写之后运行(它通常会由于指令顺序而在之前运行)

route {
	try_files {path} /index.html
	header /index.html Cache-Control "public, max-age=0, must-revalidate"
}

Caddy 代理到另一个 Caddy

如果您有一个公开可访问的 Caddy 实例(我们称之为“前端”),以及另一个在您的私有网络中的 Caddy 实例(我们称之为“后端”)服务于您的实际应用程序,则可以使用reverse_proxy 指令来传递请求。

前端实例

foo.example.com, bar.example.com {
	reverse_proxy 10.0.0.1:80
}

后端实例

{
	servers {
		trusted_proxies static private_ranges
	}
}

http://foo.example.com {
	reverse_proxy foo-app:8080
}

http://bar.example.com {
	reverse_proxy bar-app:9000
}
  • 此示例服务于两个不同的域,并将两者都代理到同一个后端 Caddy 实例,端口为 80。您的后端实例以不同的方式服务于这两个域,因此它配置了两个单独的站点块。

  • 在后端,http:// 用于在端口 80 上接受 HTTP。前端实例终止 TLS,并且前端和后端之间的流量在私有网络上,因此无需重新加密。

  • 如果需要,您可以在后端实例上使用不同的端口,如 8080;只需将 :8080 附加到后端配置上每个站点地址,或者将http_port 全局选项设置为 8080

  • 在后端,trusted_proxies 全局选项用于告诉 Caddy 信任前端实例作为代理。这确保了真实客户端 IP 被保留。

  • 更进一步,您可以拥有多个后端实例,您可以在它们之间进行负载均衡。您可以使用前端实例上的acme_server设置 mTLS(相互 TLS),使其充当后端实例的 CA(如果前端和后端之间的流量跨越不受信任的网络,这将非常有用)。