#golang #caddy #HTTP server #短址服务 #docker

Caddy 简介 - 使用 caddy 实现短网址服务

摘要

caddyapachenginx 一样是 HTTP server 程序,具有配置简单、自动 HTTPS、默认 HTTP/2 等特性。使用 Golang 编写,单二进制文件没有其它依赖也可以很好的运行。本文以一个例子(短址服务)来介绍 caddy。

特性

在广泛使用 apachenginx 这两个成熟 HTTP server 的环境中,不敢说后来居上,能有自己的一席之地,说明有一些优秀的特性吸引着用户。其中就包括:

  • 方便得配置 : 相对于 apachenginx 需要的配置行数会少很多,且配置结构更清晰。
  • 自动完成 https 配置 : 在对安全需求加大的现在,caddy 配置 https 不需要额外的代码,感谢 Let’s Encrypt
  • 默认 HTTP/2 : HTTP/2 是多路复用的单一长连接,可以加快数据传输,不过首屏访问速度 http>http2>https 可参考: HTTP 2 下 NGINX 反向代理的一些探索
  • 多站点配置
  • 插件

安装

  1. 直接命令行安装

    $ curl https://getcaddy.com | bash -s personal
    
  2. 或者官网下载 https://caddyserver.com/download 官网下载

  3. 使用 docker 镜像

    $ docker run -d \
    	-v $(pwd)/Caddyfile:/etc/Caddyfile \
    	-v $HOME/.caddy:/root/.caddy \
    	-p 80:80 -p 443:443 \
    	abiosoft/caddy
    
  4. 当然,学习原码或试用稳定版本还不支持的功能,也可自行编译:

    $ go get github.com/mholt/caddy/caddy
    $ go get github.com/caddyserver/builds
    $ cd $GOPATH/src/github.com/mholt/caddy/caddy
    $ go run build.go
    

快速配置

在任意目录执行,实现当前目录的文件服务:

$ cat <<EOF > Caddyfile
localhost:8910 { # 开启文件服务
	gzip # 开启 gzip 压缩

	browse # 浏览器模式
}
EOF

配置完成之后只需要简单启动:

$ caddy

即可在浏览器中输入 http://localhost:8910 查看文件服务。 文件服务

要为当前目录成为可以解析 markdown 的服务也很容易,生成简易的 markdown 接口文档很有用, 只需要换成如下配置。

$ cat <<EOF > Caddyfile
localhost:8910 { # 开启文件服务
	gzip # 开启 gzip 压缩

	browse # 浏览器模式

	markdown / {
		ext .md .txt
	}
}
EOF

现在重新启动 caddy 你可以在当前文件夹下撰写 markdown 文档,如在 blog/features.md 中写入如下内容:

## 特性
在广泛使用 `apache` 和 `nginx` 这两个成熟 `HTTP server` 的环境中,不敢说后来居上,能有自己的一席之地,说明有一些优秀的特性吸引着用户。其中就包括:

- 方便得配置 : 相对于 `apache` 和 `nginx` 需要的配置行数会少很多,且配置结构更清晰。
- 自动完成 `https` 配置 : 在对安全需求加大的现在,`caddy` 配置 `https` 不需要额外的代码,感谢 [Let's Encrypt](https://letsencrypt.org/)
- 默认 `HTTP/2` : `HTTP/2` 是多路复用的单一长连接,可以加快数据传输,不过首屏访问速度 http>http2>https 可参考:[
HTTP 2 下 NGINX 反向代理的一些探索](https://www.v2ex.com/t/355624)
- 多站点配置
- 插件

浏览器中查看结果: features

线上配置

此小节介绍线上服务器如何配置以做到后台运行、简洁配置多站点、自动 https

系统不存在 www 用户与组的需要先创建。

$ groupadd www
$ useradd -g www www

创建需要的文件夹:

$ mkdir -p mkdir /etc/caddy
$ mkdir -p /etc/ssl/caddy
$ chown -R www:www /etc/caddy
$ chown -R www:www /etc/ssl/caddy
$ chmod 0770 /etc/ssl/caddy

/etc/caddy 用来存放服务器配置文件;/etc/ssl/caddy 用来存放证书相关文件。

可先把上一步的 Caddyfile 复制到 /etc/caddy 先作测试

创建 systemd 配置文件,实现自启动,创建文件 /etc/systemd/system/caddy.service 写入如下配置

也可以使用官方提供的,但是需要稍作修改

[Unit]
Description=Caddy HTTP/2 web server
Documentation=https://caddyserver.com/docs
After=network-online.target
Wants=network-online.target systemd-networkd-wait-online.service

[Service]
Restart=on-abnormal

User=www
Group=www

Environment=CADDYPATH=/etc/ssl/caddy

ExecStart=/usr/local/bin/caddy -log /data/logs/caddy.log -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp -email=zhoujiangangcom@gmail.com
ExecReload=/bin/kill -USR1 $MAINPID

KillMode=mixed
KillSignal=SIGQUIT
TimeoutStopSec=5s

LimitNOFILE=1048576
LimitNPROC=512

PrivateTmp=true
PrivateDevices=false
ProtectHome=true
ProtectSystem=full
ReadWriteDirectories=/etc/ssl/caddy


[Install]
WantedBy=multi-user.target

以上配置可能需要修改的地方

; caddy 运行的用户与组, root 权限太大,不推荐使用
User=www
Group=www

; 证书配置路径
Environment=CADDYPATH=/etc/ssl/caddy

; 启动脚本
; -log 将 caddy 程序运行时日志写到文件
; -agree 自动 https 的时候要用到,表示同意 Let's Encrypt 加密协议
; -conf Caddyfile 文件配置路径
; -root 程序运行的根目录
; -email 推荐加上,https 的时候要用到,方便撤销证书
ExecStart=/usr/local/bin/caddy -log /data/logs/caddy.log -agree=true -conf=/etc/caddy/Caddyfile -root=/var/tmp -email=zhoujiangangcom@gmail.com

...

; 证书配置路径
ReadWriteDirectories=/etc/ssl/caddy

创建 caddy 服务并启动:

$ systemctl enable caddy.service # 设置 caddy 服务自启动
$ systemctl start caddy.service  # 启动 caddy 服务
$ systemctl status caddy.service # 查看 caddy 状态

一个例子

介绍一个多 host 的短址服务来结束 caddy 的介绍。

可以了解到如下点: - 多 host 配置 - 301302 重定向 - access log - header 头部设置 - 请求唯一 id: request_id

Caddyfile 中可以直接配置多个 host,不过我为了后期方便修改,每个配置文件管理一个 host

创建配置文件夹:

mkdir -p /etc/caddy/conf.d

修改 /etc/caddy/Caddyfile 使得自动引入所有 /etc/caddy/conf.d/的配置, 如下:

import /etc/caddy/conf.d/*.conf

可在 /etc/caddy/conf.d/t.v2as.com.conf 写入如下配置文件:

t.v2as.com {

	request_id

    header / {
		Cache-Control "no-cache"
    }

	log / /data/logs/t.v2as.com.log "{combined} {mitm}" {
		rotate_size 100
		rotate_age  30
		rotate_keep 100
		rotate_compress
	}

	redir 301 {
		/tool	https://6cm.com
		/novel	https://2pm.me
	}

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

说明

  • request_id : 生成唯一的请求 ID, 对于企业中的链路追踪很有用。
  • header : 设置 Cache-Control "no-cache" 301 时浏览器会缓存,设置为不缓存,可以追踪到每次短址的请求情况,方便后期分析 access log
  • log : / 所有请求 写到 /data/logs/t.v2as.com.log 按照 “{combined} {mitm}” 格式写入这个日志文件中,具体解释可以看附录
  • redir : 匹配路径,可方便发送 [300-308] 除 306 外的重定向状态码。

可在 /etc/caddy/conf.d/ 文件夹下写其它配置文件,方便配置多个 host,如用 host 命令,则更加清晰明了。

重启 caddy 服务

$ systemctl restart caddy.service

可用 ps 查看是否已经启动

$ ps aux | grep caddy

小结

简单的短址就生成了,可以通过查看 access.log 来查看来源信息等,对于广告投放、来路统计很有意义。

当然需要自定义短址,可动态删改则需要再启动一个服务来进行转发。当转发服务在端口 8910 启动时,对于 caddy 配置这类的服务可用 proxy / 127.0.0.1:8910 进行配置。

整体来说,caddy 的配置可以说非常简洁,当然这里介绍的只是基础功能,官方还有很多优秀的插件像 http.hugo, http.jekyll 这样的博客插件,像 http.jwt 这样的 jwt 认证组件等。当然如果你熟悉 golang 还可以自己方便写插件,对比为 nginx 等服务写插件门槛会低很多。

附录

log 配置格式:

log path file [format] {
	rotate_size     mb
	rotate_age      days
	rotate_keep     count
	rotate_compress
	ipmask          ipv4_mask [ipv6_mask]
	except          paths...
}

combined 日志格式:

{remote} - {user} [{when}] \"{method} {uri} {proto}\" {status} {size} \"{>Referer}\" \"{>User-Agent}\"

{mitm} caddy 能够检测 https 的中间人攻击,可以把此值写在 head 头部以提醒用户,也可放在 access log 中。

Author Mo 最后更新: 2018-12-28 00:31:01