常用 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_files
与 route
包装在一起,以便 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(如果前端和后端之间的流量跨越不受信任的网络,这将非常有用)。