版权 © 2021 2022 docboon
October 10th,2021
修订历史 | ||
---|---|---|
修订 0.1 | 2021年11月2日. | <olderflower[AT]outlook. com> |
文档建立 |
版权声明
本作品由docboon完成,并声明以Creative Commons license (CC BY 4.0)许可发行。即您可以自由地:
- 共享 — 在任何媒介以任何形式复制、发行本作品
- 演绎 — 修改、转换或以本作品为基础进行创作在任何用途下,甚至商业目的。
惟须遵守下列条件:
- 署名 — 您必须给出本作品的署名,提供指向本许可协议的链接,同时标明是否(对本作品)作了修改。您可以用任何合理的方式来署名,但是不得以任何方式暗示许可人为您或您的使用背书。
- 没有附加限制 — 您不得适用法律术语或者 技术措施 从而限制其他人做许可协议允许的事情。
商标声明
Trademarks
PostScript® and PDF® are registered trademarks of Adobe Systems,Inc. Other trademarks mentioned in this document are the property of their respective owners.
Exported by docboon [http://docboon.io] , on 2022-10-27 at 08:48:01 . olderflower[AT]outlook. com
目录
插图清单
表格清单
在正文中会有一些诸如程序代码、系统命令或是屏幕输出一类的信息,为了能清晰地展示各种元素,本手册遵守下列排版约定。
字体约定,在正文中嵌入的一些系统命令、文件名、函数或是参数等使用有别于正文的字体:
等宽字体:程序片段、正文中出现的配置选项、变量、函数名等,我们采用等宽字体,样式如下:serverip
。
等宽微粗字体:表示由用户输入的系统命令。例如,在linux下,我们查网络接口信息的命令:ifconfig eth0。
等宽斜体:表示由用户输入的值或是一些需要设定的参数的值,例如,用户在浏览器里输入的一个url,用如下的样式显示:http://docboon.io
。
等宽微粗斜体字体:表示文件名、数据库名及新的术语等。例如,文件的名称用如下的样式来显示:myfirst.xml
。
提示、告诫类信息(admonitions),有一些内容是正文的补充或是对用户的一种提醒。为了能清晰地展示这部分内容,采用独立的“信息块”来呈现。一共有5种,分别为:
提示 | |
---|---|
可以使用apt-get upgrade来升级您的ubuntu或debian Linux系统。 |
注意 | |
---|---|
在运行apt-get upgrade之前,需要先运行用apt-get update命令。 |
重要 | |
---|---|
请及时升级系统补丁程序,这是保证系统处于安全状态的好方法。 |
小心 | |
---|---|
如果系统升级还没有完成,请不要重新启动您的电脑。 |
警告 | |
---|---|
在系统升级过程中千万不要关闭电源。 |
屏幕内容围栏及程序代码围栏:
屏幕内容围栏,有时候我们需要整块显示在屏幕上输出的内容,或者是键入的命令。例如,在linux下,我们使用ifconfig eth0命令来查网络接口信息:
$ ifconfig eth0 eth0: flags=4099<UP,BROADCAST,MULTICAST> mtu 1500 ether 98:fa:9b:db:b9:9f txqueuelen 1000 (以太网) RX packets 0 bytes 0 (0.0 B) RX errors 0 dropped 0 overruns 0 frame 0 TX packets 0 bytes 0 (0.0 B) TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0 device interrupt 16 memory 0xea300000-ea320000
程序代码围栏,对于一些程序代码,使用带有序号的样式来展示,例如,一段php代码:
1 <?php 2 class SimpleBook { 3 private $title; 4 5 function __construct($title_in) { 6 $this->title = $title_in; 7 } 8 9 function getTitle() {return $this->title;} 10 } 11 ?>
caddy目前是ZeroSSL在维护的一个开源项目。ZeroSSL[1]和Let's Encrypt[2]一样,是一个SSL证书颁发机构。Caddy属于web服务器界的新秀。用go语言开发。与其他的web服务器相比,因为有了ZeroSSL的加持,caddy最大的一个特点就是它自带TLS,能非常方便的部署HTTPS。按照官方步骤安装好了以后无需任何配置,就已经自带了https功能。同时,caddy也非常好地支持成诸如代理、负载均衡等功能。在HTTP/2协议上,caddy表现也非常好。和很多的开源软件一样,caddy的文档也并不是特别的全面,有一些选项和指令需要自己去实验才能明白具体如何使用。
caddy的另外一个特点,是可以通过nginx-adapter[3]模块来使用nginx的配置文件。caddy第一个版本发布于2015年4月,截至本文截稿,caddy的最新版本是2.4.5。
caddy针对不同的操作系统和平台都有不同的发行包。也有静态的已经编译好的二进制文件,可以直接下载使用。详细的安装请参考这个页面:https://caddyserver.com/docs/install。在这里我们仅给出二进制文件和deb的安装方式。
二进制包安装方式并不会将caddy安装为一个服务(service),仅仅是一个可以执行的程序。这种方式更适合开发和调试。直接到caddy的下载站点:https://caddyserver.com/download下载适合自己操作系统的压缩包就可以了。如果是Linux系统,将解压缩后的caddy命令复制到/usr/local/bin
目录下就可以了。例如:
cp caddy_linux_amd64 /usr/local/bin/caddy
在Debian、Ubuntu或Raspbian基于debian包的系统可以使用deb包的安装方式。这种方式会将caddy安装为一个systemd service,同时,caddy-api这个服务也会被自动安装。
Stable版本系统
$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/gpg.key' | \ sudo tee /etc/apt/trusted.gpg.d/caddy-stable.asc $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/stable/debian.deb.txt' | \ sudo tee /etc/apt/sources.list.d/caddy-stable.list $ sudo apt update $ sudo apt install caddy
Testing版本系统
$ sudo apt install -y debian-keyring debian-archive-keyring apt-transport-https $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/gpg.key' | \ sudo tee /etc/apt/trusted.gpg.d/caddy-testing.asc $ curl -1sLf 'https://dl.cloudsmith.io/public/caddy/testing/debian.deb.txt' | \ sudo tee /etc/apt/sources.list.d/caddy-testing.list $ sudo apt update $ sudo apt install caddy
作为概览,在本节我们从一些基础的方面展示如何使用caddy。
caddy的配置和大多数的web server不太一样。有三种不同的配置方式:
caddy的原生配置是JSON格式。使用JSON格式来配置caddy可以实现它的全部功能。如果不喜欢JSON的配置方式,也可是使用caddy所具备的“适配器(adapter)”功能来使用其他的配置格式。其中,Caddyfile就是“adapter”的一种。另外,caddy也可以通过使用“nginx adapter”来使用nginx的配置文件。
这是一种比较实用和便捷的方式。在这种方式下,使用Caddyfile
这个文件来配置系统。这个文件的配置语法比较容易阅读,并且也能够胜任大部分的使用场景。它的样子如下:
1 example.com 2 3 root * /var/www/wordpress 4 php_fastcgi unix//run/php/php-version-fpm.sock 5 file_server
这个文件可以保存于系统中的任何位置。只需在启动时使用如下命令进行指定就可以了。
caddy adapt --config /path/to/Caddyfile
caddy使用的配置文件是JSON格式的,其他格式的文件,例如Caddyfile,需要使用配置适配器将其转换为JSON格式。caddy利用这种机制可以使用其他类型的配置文件,目前支持8种:Caddyfile、nginx的配置文件、jsonc、josn5、yaml、cue、toml、及hcl
caddy可以通过一个管理端点(administration endpoint)来配置,这个管理端点是一套通过HTTP协议使用来使用的REST API。这个“管理端点”可以在配置文件中进行配置。它的默认使用地址是:localhost:2019
上面所说到的,是caddy的三种配置和管理的方式。在后面的章节会陆续进行说明。
如果是使用某种包管理方式安装的caddy,那么caddy已经是一个系统服务了,可能已经启动了。在开始这节的内容之前,建议先将caddy停止运行。可以使用caddy stop命令来停止caddy服务。下面,我们通过如下的几个实验来对caddy进行一个大致的了解。
目录
为了能更清晰地描述,我们在局域网中设立一台caddy服务器,我们称为Server,其内网IP地址是192.168.31.2/24,外网IP地址是192.168.1.2/24。我们在其上安装Debian Linux(V12)。
同时,我们需要在客户端(客户端使用了Ubuntu桌面系统)和caddy server端安装两个工具:
curl,即client-URL,可以认为是一个命令行的浏览器,在Debian/Ubuntu下使用apt-get install curl命令来安装。它的官方站点是https://curl.se/
jq 是一个基于命令行的、轻量级JSON文件处理工具,caddy的原生配置文件是JSON文件,我们需要用jq命令来将其格式化,以便于阅读。在Debian或Ubuntu下可通过apt-get install jq来安装。关于其更多内容请访问:https://stedolan.github.io/jq/。
在终端输入caddy命令,会显示help信息。如果想让caddy作为守护进程来运行,有两个子命令可以使用:run和start。在终端中输入caddy run或caddy start即可。run和start的区别是:
在配置文件为空的情况下,运行caddy run或caddy start之后,系统会开启一个本地的2019端口,这个端口就是caddy的API管理接口。可以通过这个接口对caddy完成很多的操作。
下面的内容就是使用caddy start启动系统之后的屏幕内容,通过使用netstat -ptuln命令,可以看到,caddy开启了本地的2019管理端口:
root@lognovel:~# caddy start 2021/11/08 05:46:38.499 INFO admin admin endpoint started {"address": "tcp/localhost:2019", \ "enforce_origin": false, "origins": ["localhost:2019", "[::1]:2019", "127.0.0.1:2019"]} 2021/11/08 05:46:38.499 INFO serving initial configuration Successfully started Caddy (pid=1850) - Caddy is running in the background root@lognovel:~# netstat -ptuln Active Internet connections (only servers) Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program name tcp 0 0 127.0.0.1:2019 0.0.0.0:* LISTEN 1850/caddy ... ...
注意 | |
---|---|
caddy所启动的2019端口L并非我们的web站点,而是“管理端点(administration endpoint)”,也就是caddy的API。在默认情况下,运行在本机的2019端口,并且只允许本机访问。可以使用curl localhost:2019/config/命令来查看系统配置。 |
在caddy的配置方式中,Caddyfile文件对人来说是比较容易阅读的。我们编辑一个文件,名为Caddyfile
(没有扩展名,C字母大写,其他字母小写!)。在Caddyfile
中加入如下内容:
:2015 respond "Hello, world!"
现在停止caddy的运行,使用(Ctrl+C),如果是运行在守护进程状态下的话可以使用caddy stop命令。然后,使用如下的命令再次运行caddy
caddy run
这个命令会在当前目录下寻找Caddyfile
文件,并直接加载它。如果Caddyfile
这个文件保存在其他位置,那需要指明具体的路径:
caddy run --config /path/to/Caddyfile
实际上,上面的命令是下面一行命令的缩写,省掉了--adapter caddyfile
,因为默认情况下caddy使用Caddyfile adapter,
caddy run --adapter caddyfile --config /path/to/Caddyfile
接下来,在另外一个终端中输入:curl https://localhost,就会看到”Hello World!“。
现在我们更改Caddyfile
,在其中定义两个站点,内容如下:
localhost { respond "Hello, world!" } localhost:2016 { respond "Goodbye, world!" }
我们使用API的方式将这些内容加载到系统中,使用如下的命令:
curl localhost:2019/load \ -X POST \ -H "Content-Type: text/caddyfile" \ --data-binary @Caddyfile
然后使用curl https://localhost:2016命令,便会看到“Goodbye, world!”
使用caddy run或caddy start启动caddy,不要带任何配置文件。现在caddy已经在“空转”了,我们使用Heredoc[4]的方式,通过API接口给它加载一些配置:
curl localhost:2019/load \ -X POST \ -H "Content-Type: application/json" \ -d @- << EOF { "apps": { "http": { "servers": { "hello": { "listen": [":2015"], "routes": [ { "handle": [{ "handler": "static_response", "body": "Hello, world!" }] } ] } } } } } EOF
把这个配置加载到caddy以后,我们在客户端使用浏览器访问caddy服务器的2015端口,http://192.168.31.2:2015
,或者也可以使用命令:curl http://192.168.31.2:2015。我们会看到“Hello, world!”
用Heredoc字符流的方式加载配置还是有点费劲的,前面的例子只是让我们知道caddy的这种工作方式。更常用的方式还是把配置写在一个文件中,然后再加载。
接下来我们把前面的配置内容写入到一个简单的JSON配置文件中,然后同样使用curl命令完成加载。文件名称为caddy.json
,其内容如下:
1 { 2 "apps": { 3 "http": { 4 "servers": { 5 "hello": { 6 "listen": [":2015"], 7 "routes": [ 8 { 9 "handle": [{ 10 "handler": "static_response", 11 "body": "Hello, world!" 12 }] 13 } 14 ] 15 } 16 } 17 } 18 } 19 }
现在使用如下的命令加载这个配置文件:
curl localhost:2019/load \ -X POST \ -H "Content-Type: application/json" \ -d @caddy.json
同样,我们可以在客户端通过浏览器或curl来访问一下2015端口:
curl http//192.168.31.2:2015
如果能看到Hello,world!那就代表刚才的配置文件已经生效了。
提示 | |
---|---|
实际上caddyAPI在大多数情况下,是为其他程序所设计的一种接口。 |
接下来我们更新一下caddy.json
文件,定义两个站点,一个在2015端口,一个在2016端口:
1 { 2 "apps": { 3 "http": { 4 "servers": { 5 "hello": { 6 "listen": [":2015"], 7 "routes": [ 8 { 9 "handle": [{ 10 "handler": "static_response", 11 "body": "Hello, world!" 12 }] 13 } 14 ] 15 }, 16 "bye": { 17 "listen": [":2016"], 18 "routes": [ 19 { 20 "handle": [{ 21 "handler": "static_response", 22 "body": "Goodbye, world!" 23 }] 24 } 25 ] 26 } 27 } 28 } 29 } 30 }
然后再次使用如下的命令来加载这个文件:
curl localhost:2019/load \ -X POST \ -H "Content-Type: application/json" \ -d @caddy.json
然后在客户端分别访问:http://192.168.31.2:2015
和http://192.168.31.2:2016
,会看到“Hello, world!”及“Goodbye, world!”。
提示 | |
---|---|
caddy.json 这个文件也可以通过命令行来使用:caddy start --config caddy.json |
使用API可以做很多的事情,包括导出配置和对配置进行细粒度的更改(而不是更新整个内容)。建议阅读更完整的API教程:https://caddyserver.com/docs/api-tutorial及https://caddyserver.com/docs/api
在caddy启动以后,我们随时都可以在caddy server上使用curl命令通过GET请求来查看配置:
curl localhost:2019/config/
这个命令直至输出的结果是JSON格式的,非常不易读,可以使用jq命令来将其格式化:
curl localhost:2019/config/ | jq
可以看出,输出的结果和我们的配置是一致的。可以使用这个命令将当前的配置导出。
现在我们已经知道Caddyfile会被转换为JSON格式。实际上Caddyfile的配置方式对人来说更友好、更简单一些。具体是使用JSON还是Caddyfile,要取决于具体的场景。caddy的官方网站有一张表格,可以供参考:
表 2.1. JSON vs. Caddyfile
JSON | Caddyfile |
---|---|
Full range of Caddy functionality | Most common parts of Caddy functionality |
Easy to generate | Easy to craft by hand |
Easily programmable | Difficult to automate |
Extremely expressive | Moderately expressive |
Allows config traversal | Cannot traverse within Caddyfile |
Partial config changes | Whole config changes only |
Can be exported | Cannot be exported |
Compatible with all API endpoints | Compatible with some API endpoints |
Documentation generated automatically | Documentation is hand-written |
Ubiquitous | Niche |
More efficient | More computational |
Kind of boring | Kind of fun |
其实,从上面的表格可以看出,如果比较精通JSON配置的话,似乎使用JSON还是更好的。
另外一点,就是在caddy配置管理中是使用API还是使用它的Caddyfile。其实可以同时使用,但他们官方并不推荐,他们推荐最好只使用一种。一种比较常见的组合是:JSON+API 或者 Caddyfile+CLI 。下面的表格可以让我们理解API和Caddyfile的一些区别:
表 2.2. API vs. config files
JSON | Caddyfile |
---|---|
Make config changes with HTTP requests | Make config changes with shell commands |
Easy to scale | Difficult to scale |
Difficult to manage by hand | Easy to manage by hand |
Really fun | Also fun |
启用静态的文件服务器(file server)有两种简单的方式:一种是通过命令行,一种是通过Caddyfile。
使用命令启动文件服务器,可以在终端中切换到站点所在的目录,例如:/var/www/html
,然后在这个目录下执行:caddy file-server,这样一个基本的静态文件服务器就在80端口开始运行了。如果在/var/www/html
目录下有个index.html
文件的话,在客户端的浏览器中输入:http://192.168.31.2/
就可以直接看到这个文件了。
如果想要caddy运行在其他的端口,可以使用caddy file-server --listen :2015这个命令。
如果目录中没有index.html
文件,并且想能够列出/var/www/html
中的文件,可以使用caddy file-server --browse这个命令。
如果想要使用指定的目录作为根目录,可以使用caddy file-server --root /path/to/yourSite这个命令。
为了说明反向代理,我们需要在Server1上安装一个web服务器。ip地址设置为192.168.31.10/24。
使用如下的命令:
caddy reverse-proxy --from :2016 --to 192.168.31.10:80
当我们在客户端的浏览器中输入http://192.168.31.2:2016
时,就会看到Server1站点的内容。
HTTPS对于caddy来说是一件非常容易的事情,当caddy安装好以后默认就带HTTPS了,只要有一个域名,就可以启用HTTPS了。我们使用lognovel.com这个域名来说明如何配置HTTPS。
建立一个根目录/usr/local/work/lognovel.com
,在这个目录里建立一个index.html
文件,Caddyfile
配置如下:
lognovel.com www.lognovel.com { root * /usr/local/work/lognovel.com file_server }
在浏览器中输入http://lognovel.com
或http://www.lognovel.com
,会看到index.html
里的内容。我们可以通过浏览器地址栏左的小锁icon来查看https证书的情况。
[4] Heredoc:向交互式命令传递多行文本或代码的一种方式,第一行是以可选命令开始,紧接着是重定向符号 <<, 你可以使用任何字符串作为分隔符,我们最常用的是 EOF(End Of File) 或者 END