Caddy-用Go寫的新一代可延伸WebServer

2023-01-19 12:00:36

前幾天用 Netmaker 的時候發現它用 Caddy 替換掉了 Nginx,用了後發現確實簡單好用,就安利一下。

Caddy 是一個強大的、可延伸的平臺,用 Go 編寫,可以為你的站點、服務和應用程式提供服務。如果你是 Caddy 的新手,你服務網路的方式將會改變。

引言

大多數人使用 Caddy 作為網路伺服器或代理,但在其核心,Caddy 是一個伺服器的伺服器(a server of servers)。通過必要的模組,它可以承擔任何長時間執行的程序的角色!

設定是動態的和可通過 Caddy 的 API 匯出 。雖然不需要組態檔,但是您仍然可以使用它們; 大多數人最喜歡的設定 Caddy 的方法是使用 Caddyfile。設定檔案的格式通過設定介面卡採用多種形式,但 Caddy 的本地設定語言是 JSON

Caddy 為所有主流平臺編譯,並且沒有執行時依賴項。

新手指南

我們建議每個人不管經驗如何都要看一下我們的入門指南。它將為你提供一個全面的視角來看待你的新網路伺服器,這對你繼續學習是無價的。本教學將探索使用 Caddy 的基礎知識,並幫助您在更高的層次上熟悉它。

目的:

  • 執行守護行程
  • 試試 API
  • 給 Caddy 一個設定
  • 測試設定
  • 製作一個 Caddyfile
  • 使用設定介面卡(config adapter)
  • 從一個初始設定開始
  • 比較 JSON 和 Caddyfile
  • 比較 API 和組態檔
  • 在後臺執行
  • 零停機時間設定過載

先決條件

  • 已安裝 caddycurl(安裝 Caddy 可以參考這裡

要啟動 Caddy 作為一個守護程式,使用 run 子命令:

caddy run

預設情況下,Caddy 的設定(「 config」)為空。我們可以使用另一個終端存取管理 API 來驗證這一點:

curl localhost:2019/config/

{% note info %}
ℹ️ 資訊

上面地址不是你的網站,localhost:2019 是用來控制 Caddy 的管理端點,並被預設限制為本機存取。

我們可以通過給它一個設定來使 Caddy 變得有用。這可以通過多種方式完成,但是我們將在下一節使用 curl/load 端點發出 POST 請求。

你的第一個設定

為了準備我們的請求,我們需要做一個設定。

將其儲存到 JSON 檔案中(例如 caddy.JSON) :

{
	"apps": {
		"http": {
			"servers": {
				"example": {
					"listen": [":2015"],
					"routes": [
						{
							"handle": [{
								"handler": "static_response",
								"body": "Hello, world!"
							}]
						}
					]
				}
			}
		}
	}
}

然後上傳:

curl localhost:2019/load \
	-X POST \
	-H "Content-Type: application/json" \
	-d @caddy.json

我們可以通過如下命令驗證 Caddy 將我們的新設定應用到另一個 GET 請求:

curl localhost:2019/config/

然後測試新的設定:

$curl localhost:2015
Hello, world!

如果你看到 Hello, world! 那恭喜了,成功了!確保設定按預期的方式工作總是一個好主意,尤其是在部署到生產環境之前。

你的第一個 Caddyfile

另一種設定 Caddy 的方法是 Caddyfile。上面我們在 JSON 編寫的設定可以簡單地表達為:

:2015

respond "Hello, world!"

將其儲存到工作目錄檔案中名為 Caddyfile (無擴充套件名)的檔案中。

如果 Caddy 已經在執行, (Ctrl + c)停止它,然後執行:

caddy adapt

或者你把 Caddyfile 儲存在別的地方,或者給它取了別的名字:

caddy adapt --config /path/to/Caddyfile

您將看到 JSON 輸出! 這裡發生了什麼?

我們只是使用設定介面卡將 Caddyfile 轉換為 Caddy 的原生 JSON 結構。

雖然我們可以獲得這個輸出並行出另一個 API 請求,但是我們可以跳過所有這些步驟,因為 caddy 命令可以為我們完成這些操作。如果工作目錄中有一個叫 Caddyfile 的檔案,並且沒有指定其他設定,Caddy 會載入 Caddyfile,為我們改編,然後馬上執行。

現在當前資料夾中有一個 Caddyfile,讓我們再次執行 caddy:

caddy run

或者如果你的 Caddyfile 在其他地方:

caddy run --config /path/to/Caddyfile

(如果呼叫的是不以「 Caddyfile」開頭的其他名稱,則需要指定 --adapter caddyfile)

正如你所看到的,有幾種方法可以讓你使用初始設定啟動 Caddy:

  • 在工作目錄一個名為 Caddyfile 的檔案
  • --config flag (可選項,帶有--adapter flag)
  • --resume flag (如果先前載入了設定)

JSON vs. Caddyfile

現在您知道了,Caddyfile 剛剛為您轉換為 JSON。

Caddyfile 看起來比 JSON 簡單,但是你應該一直使用它嗎?每種方法都有利有弊。答案取決於您的需求和用例。

JSON Caddyfile
完整的 Caddy 功能 最常見的 Caddy 功能部件
易於生成 易於手工製作
易於程式設計 難以自動化
非常有表現力 適度的表達
允許設定遍歷 不能在 Caddyfile 間轉換
部分設定更改 只能修改整個設定
可以匯出 無法匯出
與所有 API 端點相容 與某些 API 端點相容
自動生成的檔案 檔案是手寫的
無處不在 小眾
更有效率 更多的計算
有點無聊 挺有意思的
瞭解更多:JSON 結構 瞭解更多:Caddyfile 檔案

您將需要決定哪一個最適合您的用例。

需要注意的是,JSON 和 Caddyfile (以及任何其他支援的設定介面卡)都可以與 Caddy 的 API 一起使用。然而,如果您使用 JSON,您將獲得 Caddy 的全部功能和 API 特性。如果使用設定介面卡,使用 API 載入或更改設定的唯一方法是 /load 端點

API vs. 組態檔

{% note info %}
ℹ️ 資訊

實際上,即使是組態檔也要經過 Caddy 的 API 端點,命令只是為您包裝了這些 API 呼叫。

您還需要決定您的工作流是基於 API 的還是基於 CLI 的。(您可以在同一臺伺服器上同時使用 API 和組態檔,但我們不推薦這樣做: 最好有一個真實的來源。)

API 組態檔
使用 HTTP 請求修改設定 使用 shell 命令修改設定
易於擴大規模 難以規模化
手工操作難度大 易於手工操作
真的很有趣 也很有趣
瞭解更多:API 教學 瞭解更多:Caddyfile 教學

{% note info %}
ℹ️ 資訊

使用 API 手動管理伺服器設定完全可以通過適當的工具實現,例如: 任何 REST 使用者端應用程式

或組態檔工作流的選擇與設定介面卡的使用是正交的: 你可以使用 JSON,但儲存在一個檔案中,並使用命令列介面; 相反,你也可以使用 Caddyfile 與 API。

但是大多數人會使用 json + api 或 Caddyfile + CLI 組合。

如您所見,Caddy 非常適合於各種各樣的用例和部署!

Start,stop,run

因為 Caddy 是一個伺服器,所以它可以無限期地執行。這意味著在執行 caddy run 之後,終端不會解除阻塞,直到程序終止(通常使用 Ctrl + c)。

雖然 caddy run 是最常見的,通常是推薦的(特別是在進行系統服務時!),你也可以選擇使用 caddy start 啟動 Caddy,並讓它在後臺執行:

caddy start

這將允許您再次使用您的終端,這在一些互動式無頭環境中非常方便。

然後你必須自己停止這個過程,因為 Ctrl + c 不會為你停止:

caddy stop

或者使用 API 的/stop 端點

重新載入設定

您的伺服器可以執行零停機時間設定過載/更改。

載入或更改設定的所有 API 端點都是完美的,並且沒有停機時間。

但是,在使用命令列時,可能很容易使用 Ctrl + c 來停止伺服器,然後再重新啟動伺服器以獲取新的設定。不要這樣做: 停止和啟動伺服器與設定更改是正交的,並將導致停機。

相反,使用 caddy reload 命令來優雅地修改設定:

caddy reload

這實際上只是在引擎蓋下使用了 API。它將載入並在必要時將組態檔調整為 JSON,然後在不停機的情況下優雅地替換活動設定。

如果載入新設定時出現任何錯誤,Caddy 將回滾到上次工作的設定。

{% note info %}
ℹ️ 資訊

從技術上講,新設定是在停止舊設定之前啟動的,因此在很短的時間內,兩個設定都在執行!如果新設定失敗,它將中止一個錯誤,而舊設定則根本不會停止

Caddy 常用功能

  1. 靜態檔案存取
  2. 反向代理
  3. HTTPS

靜態檔案存取

命令列方式

在終端中,切換到站點的根目錄並執行:

caddy file-server

如果你得到一個許可權錯誤,這可能意味著你的作業系統不允許你係結到低埠---- 所以改用高階口:

caddy file-server --listen :2015

然後在瀏覽器中開啟 (或 localhost:2015)檢視您的網站!

如果你沒有索引檔案,但是你想要顯示一個檔案列表,可以使用 --browse 選項:

caddy file-server --browse

您可以使用另一個資料夾作為站點根目錄:

caddy file-server --root ~/mysite

Caddyfile 方式

在站點的根目錄中,建立一個名為 Caddyfile 的檔案,其中包含以下內容:

localhost

file_server

或:

localhost

file_server browse

localhost

root * /home/me/mysite
file_server

分別對應以上的幾個命令。

反向代理

本教學假設您有一個執行在 127.0.0.1:9000 上的後端 HTTP 服務。

命令列方式

很直白,直接能看明白:

caddy reverse-proxy --to 127.0.0.1:9000

如果你沒有許可權繫結到低埠,你可以從高階口代理:

caddy reverse-proxy --from :2016 --to 127.0.0.1:9000

Caddyfile 方式

直接上設定:

localhost

reverse_proxy 127.0.0.1:9000

caddy run 執行即可

更改代理的地址很容易:

:2016

reverse_proxy 127.0.0.1:9000

更改 Caddyfile 時,請確保重新載入 Caddy (或停止並重新啟動它)。

使用反向代理指令以做很多事情。

HTTPS

本指南將向您展示如何立即使用完全自管理的 HTTPS 啟動和執行。

{% note info %}
ℹ️ 資訊

在預設情況下,Caddy 對所有站點使用 HTTPS,只要在設定中提供了主機名。本教學假設您希望通過 HTTPS 獲得一個公共受信任的站點(即不是「 localhost」) ,因此我們將使用一個公共域名和外部埠

先決條件:

  • 對 DNS 的基本瞭解
  • 註冊的公共域名
  • 對埠80和443的外部存取
  • 已安裝 caddycurl

在本教學中,將 example.com 替換為您的實際域名。

設定域名的 A/AAAA 記錄指向伺服器。您可以通過登入到您的 DNS 提供商和管理您的域名來做到這一點。

在繼續之前,用權威 lookup 驗證正確的記錄。用你的域名替換 example.com,如果你使用的是 IPv6,把 type=A 替換為 type=AAAA:

curl "https://cloudflare-dns.com/dns-query?name=example.com&type=A" \
  -H "accept: application/dns-json"

{% note info %}
ℹ️ 提示

一切的前提是你是在 cloudflare 上買的這個域名。
如果不是的話,步驟會複雜一些。
參見這篇 域名在 DNSPod 上的證書申請方式

還要確保您的伺服器在埠80和443上是可以從公共介面存取的。

{% note info %}
ℹ️ 提示

如果您在您的家庭或其他受限制的網路,您可能需要轉發埠或調整防火牆設定

所有我們需要做的是開始用您的域名設定 Caddy。有幾種方法可以做到這一點。

Caddyfile

這是獲取 HTTPS 的最常用方法。

建立一個名為 Caddyfile (無擴充套件名)的檔案,其中第一行是您的域名,例如:

example.com

respond "Hello, privacy!"

然後從同一個目錄中執行:

caddy run

您將看到 Caddy 提供一個 TLS 證書,並通過 HTTPS 服務您的站點。這是可能的,因為你的網站在 Caddyfile 中的地址包含一個域名。

file-server 命令

caddy file-server --domain example.com

可以了。

reverse-proxy 命令

caddy reverse-proxy --from example.com --to localhost:9000

總結

Caddy 吸引我的地方:

  1. 自動申請續約證書
  2. 簡單命令的 Caddyfile
  3. Go 編寫,Caddy 為所有主流平臺編譯,並且沒有執行時依賴項。