文件
一個 專案

Caddyfile 概念

本文件將協助您詳細了解 HTTP Caddyfile。

  1. 結構
  2. 全域選項
  3. 位址
  4. 比對器
  5. 佔位符
  6. 片段
  7. 命名路由
  8. 註解
  9. 環境變數

結構

Caddyfile 的結構可以用視覺方式描述

Caddyfile structure

重點

  • 一個選用的 全域選項區塊 可以是檔案中的第一個項目。

  • 片段命名路由 可以選擇性地出現在下一行。

  • 否則,Caddyfile 的第一行永遠是網站要提供的 位址

  • 所有 指令比對器 必須 出現在網站區塊中。網站區塊之間沒有全域範圍或繼承。

  • 如果只有一個網站區塊,則其大括號 { } 是選用的。

Caddyfile 包含一個或多個網站區塊,這些區塊總是從網站的一個或多個 位址 開始。在位址之前出現的任何指令都會讓解析器感到混淆。

區塊

開啟和關閉一個區塊是用大括號完成的

... {
	...
}
  • 開括號 { 必須在其行尾,且前面有一個空格。

  • 閉括號 } 必須在它自己的行上。

當只有一個網站區塊時,大括號(和縮排)是可選的。這是為了方便快速定義單一網站,例如,這個

localhost

reverse_proxy /api/* localhost:9001
file_server

等同於

localhost {
	reverse_proxy /api/* localhost:9001
	file_server
}

當你只有一個網站區塊時;這是一個偏好的問題。

要使用同一個 Caddyfile 設定多個網站,你必須在每個網站周圍使用大括號來區分它們的設定

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

example2.com {
	reverse_proxy localhost:9000
}

如果一個請求符合多個網站區塊,則會選擇具有最特定匹配地址的網站區塊。請求不會串接進入其他網站區塊。

指令

指令 是功能性關鍵字,用於自訂網站的提供方式。它們必須出現在網站區塊中。例如,一個完整的檔案伺服器設定檔可能看起來像這樣

localhost {
	file_server
}

或一個反向代理伺服器

localhost {
	reverse_proxy localhost:9000
}

在這些範例中,file_serverreverse_proxy 是指令。指令是網站區塊中一行上的第一個字詞。

在第二個範例中,localhost:9000引數,因為它出現在指令後同一行上。

有時指令可以開啟它們自己的區塊。子指令出現在指令區塊中每行的開頭

localhost {
	reverse_proxy localhost:9000 localhost:9001 {
		lb_policy first
	}
}

這裡,lb_policyreverse_proxy 的子指令(它設定用於後端之間的負載平衡政策)。

除非另有說明,否則指令不能用於其他指令區塊中。例如,basicauth 不能用於 file_server 中,因為檔案伺服器不知道如何進行驗證;但你可以在 routehandlehandle_path 區塊中使用指令,因為它們特別設計為將指令分組在一起。

請注意,當 HTTP Caddyfile 被調整時,HTTP 處理常式會根據特定的預設 指令順序 排序,除非在 route 區塊中,因此指令出現的順序並不重要,除了在 route 區塊中。

符號和引號

在解析之前,Caddyfile 會被分析成代幣。空白在 Caddyfile 中很重要,因為代幣是由空白分隔的。

通常,指令會預期一定數量的引數;如果單一引數的值有空白,它會被分析成兩個獨立的代幣

directive abc def

這可能會造成問題並傳回錯誤或意外的行為。

如果 abc def 應該是單一引數的值,它需要被加上引號

directive "abc def"

如果你需要在帶引號的代幣中使用引號,也可以對引號進行跳脫

directive "\"abc def\""

若要避免跳脫引號,可以使用反引號 ` ` 來封裝令牌;例如

directive `{"foo": "bar"}`

在引號令牌內,所有其他字元都會被視為字面值,包括空格、標籤和換行符。因此,多行令牌是可行的

directive "first line
	second line"

Heredocs 也受支援:

example.com {
	respond <<HTML
		<html>
		  <head><title>Foo</title></head>
		  <body>Foo</body>
		</html>
		HTML 200
}

開啟 heredoc 標記必須以 << 開頭,後接任何文字(建議使用大寫字母)。關閉 heredoc 標記必須是相同的文字(在上述範例中,為 HTML)。開啟標記可以使用 \<< 進行跳脫以防止 heredoc 分析,視需要而定。

關閉標記可以縮排,這會導致每一行文字都移除這麼多的縮排(靈感來自 PHP),這對於在 區塊 內提升可讀性很有幫助,同時也能很好地控制令牌文字中的空白。尾隨換行符也會被移除,但可以在關閉標記前加入額外的空白行來保留它。

其他令牌可以作為指令的引數,緊接在關閉標記之後(例如在上述範例中,狀態碼 200)。

全域選項

Caddyfile 可以選擇以一個沒有金鑰的特殊區塊開始,稱為 全域選項區塊

{
	...
}

如果存在,它必須是設定檔中的第一個區塊。

它用於設定全域適用的選項,或不適用於任何特定網站。在其中,只能設定全域選項;無法在其中使用常規網站指令。

例如,啟用 debug 全域選項,這通常用於產生詳細記錄以進行疑難排解

{
	debug
}

閱讀全域選項頁面 以了解更多資訊。

位址

地址總是出現在網站區塊的最上方,通常是 Caddyfile 中的第一個項目。

以下是有效地址的範例

地址 效果
example.com 使用受管理的 公開信任憑證 的 HTTPS
*.example.com 使用受管理的 公開信任萬用字元憑證 的 HTTPS
localhost 使用受管理的 本地受信任憑證 的 HTTPS
http:// HTTP 萬用字元,受 http_port 影響
https:// HTTPS 萬用字元,受 https_port 影響
http://example.com 明確的 HTTP,使用 Host 比對器
example.com:443 HTTPS,因為比對到 https_port 預設值
:443 HTTPS 萬用字元,因為比對到 https_port 預設值
:8080 非標準埠上的 HTTP,沒有 Host 比對器
localhost:8080 非標準埠上的 HTTPS,因為有有效的網域
https://example.com:443 HTTPS,但 https://:443 都是多餘的
127.0.0.1 HTTPS,使用本地受信任的 IP 憑證
http://127.0.0.1 HTTP,使用 IP 位址 Host 比對器(拒絕 localhost

Caddy 可以從位址推論出您網站的 scheme、主機和埠。如果位址沒有埠,則 Caddyfile 會選擇與 scheme 相符的埠(如果已指定),否則會假設預設埠 443。

如果您指定主機名稱,則只有具有相符 Host 標頭的請求才會被接受。換句話說,如果網站位址是 localhost,則 Caddy 就不會比對傳送至 127.0.0.1 的請求。

可以使用萬用字元(*),但只能用來表示主機名稱的精確一個標籤。例如,*.example.com 比對得到 foo.example.com 但比對不到 foo.bar.example.com,而 * 比對得到 localhost 但比對不到 example.com。請參閱萬用字元憑證模式以取得實際範例。

若要比對所有主機,請省略位址的主機部分,例如,只要 https:// 即可。這在使用 依需求 TLS 時很有用,因為您事先不知道網域。

如果多個網站共用同一個定義,您可以將它們全部列在一起,使用空白或逗號分隔。以下三個範例是等效的

# Comma separated site addresses
localhost:8080, example.com, www.example.com {
	...
}

# Space separated site addresses
localhost:8080 example.com www.example.com {
	...
}

# Comma and new-line separated site addresses
localhost:8080,
example.com,
www.example.com {
	...
}

一個位址必須是唯一的;您不能指定同一個位址超過一次。

佔位符不能用在位址中,但您可以在其中使用 Caddyfile 風格的 環境變數

{$DOMAIN:localhost} {
	...
}

預設情況下,網站會繫結到所有網路介面。如果您想覆寫此設定,請使用 bind 指令default_bind 全域選項 來執行此操作。

比對器

HTTP 處理器 指令 預設套用於所有要求(除非另有說明)。

要求比對器 可用於依據特定條件分類要求。使用比對器,您可以明確指定特定指令套用於哪些要求。

對於支援比對器的指令,指令後的第 1 個參數為比對器代碼。以下是一些範例

root *           /var/www  # matcher token: *
root /index.html /var/www  # matcher token: /index.html
root @post       /var/www  # matcher token: @post

比對器代碼可以完全省略以比對所有要求;例如,如果下一個參數看起來不像路徑比對器,則不需要提供 *

閱讀要求比對器頁面以進一步了解。

佔位符

您可以在 Caddyfile 中使用任何 Caddy 佔位符,但為方便起見,您也可以使用一些等效的簡寫

簡寫 取代
{cookie.*} {http.request.cookie.*}
{client_ip} {http.vars.client_ip}
{dir} {http.request.uri.path.dir}
{err.*} {http.error.*}
{file_match.*} {http.matchers.file.*}
{file.base} {http.request.uri.path.file.base}
{file.ext} {http.request.uri.path.file.ext}
{file} {http.request.uri.path.file}
{header.*} {http.request.header.*}
{host} {http.request.host}
{hostport} {http.request.hostport}
{labels.*} {http.request.host.labels.*}
{method} {http.request.method}
{path.*} {http.request.uri.path.*}
{path} {http.request.uri.path}
{port} {http.request.port}
{query.*} {http.request.uri.query.*}
{query} {http.request.uri.query}
{re.*.*} {http.regexp.*.*}
{remote_host} {http.request.remote.host}
{remote_port} {http.request.remote.port}
{remote} {http.request.remote}
{rp.*} {http.reverse_proxy.*}
{scheme} {http.request.scheme}
{tls_cipher} {http.request.tls.cipher_suite}
{tls_client_certificate_der_base64} {http.request.tls.client.certificate_der_base64}
{tls_client_certificate_pem} {http.request.tls.client.certificate_pem}
{tls_client_fingerprint} {http.request.tls.client.fingerprint}
{tls_client_issuer} {http.request.tls.client.issuer}
{tls_client_serial} {http.request.tls.client.serial}
{tls_client_subject} {http.request.tls.client.subject}
{tls_version} {http.request.tls.version}
{upstream_hostport} {http.reverse_proxy.upstream.hostport}
{uri} {http.request.uri}
{vars.*} {http.vars.*}

片段

您可以定義稱為片段的特殊區塊,方法是給它們一個用括號括起來的名稱

(logging) {
	log {
		output file /var/log/caddy.log
		format json
	}
}

然後,您可以使用特殊的 import 指令在需要的地方重複使用它

example.com {
	import logging
}

www.example.com {
	import logging
}

import 指令也可以用於包含其他檔案。如果參數與定義的片段不符,它將嘗試作為檔案。它還支援 glob 以匯入多個檔案。特殊情況下,它可以出現在 Caddyfile 中的任何位置(作為另一個指令的參數除外),包括網站區塊之外

{
	email admin@example.com
}

import sites/*

您可以傳遞參數給匯入的組態(片段或檔案),並像這樣使用它們

(snippet) {
	respond "Yahaha! You found {args[0]}!"
}

a.example.com {
	import snippet "Example A"
}

b.example.com {
	import snippet "Example B"
}

閱讀 import 指令頁面 以瞭解更多資訊。

命名路由

⚠️ 實驗性質

命名路由使用與 片段 類似的語法;它們是定義在網站區塊之外的特殊區塊,以 &( 開頭,以 ) 結尾,中間有名稱。

&(app-proxy) {
	reverse_proxy app-01:8080 app-02:8080 app-03:8080
}

然後您可以在任何網站中重複使用此命名路由

example.com {
	invoke app-proxy
}

www.example.com {
	invoke app-proxy
}

如果在許多不同的網站中需要相同的路由,或者需要多個不同的比對條件來呼叫相同的路由,這對於減少記憶體使用量特別有用。

閱讀 invoke 指令頁面 以瞭解更多資訊。

註解

註解以 # 開頭,並持續到該行的結尾

# Comments can start a line
directive  # or go at the end

註解的雜湊字元 # 不能出現在令牌中間(即它必須前面有空格或出現在行的開頭)。這允許在 URI 或其他值中使用雜湊,而不需要引號。

環境變數

如果您的組態依賴於環境變數,您可以在 Caddyfile 中使用它們

{$ENV}

此形式的環境變數會在 Caddyfile 解析開始之前 替換,因此它們可以擴充為空值(即 "")、部分令牌、完整令牌,甚至多個令牌和行。

例如,環境變數 UPSTREAMS="app1:8080 app2:8080 app3:8080" 會擴充為多個 令牌

example.com {
	reverse_proxy {$UPSTREAMS}
}

當找不到環境變數時,可以使用 : 作為變數名稱和預設值之間的分隔符號,指定預設值

{$DOMAIN:localhost} {

}

如果您想 延後替換 環境變數直到執行階段,您可以使用 標準 {env.*} 佔位符。請注意,並非所有組態參數都支援這些佔位符,因為模組開發人員需要新增一行程式碼來執行替換。如果它似乎不起作用,請提交問題以請求支援。

例如,如果您已安裝 caddy-dns/cloudflare 外掛程式 並希望組態 DNS 挑戰,您可以像這樣將您的 CLOUDFLARE_API_TOKEN 環境變數傳遞給外掛程式

{
	acme_dns cloudflare {env.CLOUDFLARE_API_TOKEN}
}

如果您將 Caddy 作為 systemd 服務執行,請參閱 這些說明 以設定服務覆寫來定義您的環境變數。