一行代码快速配置 Caddy 站点日志——复用 Caddy 配置段

使用 Caddy 的代码段(Snippet)和占位符,为每个站点更优雅地快速配置日志。

由于厌倦了手动申请和配置证书,所以昨天将主服务器上的 Nginx 换成了 Caddy,并放到了 Docker 中运行,同时使用 docker-compose 编排了 php 环境,干净统一的目录和简洁的 Caddyfile 配置文件,瞬间感觉强迫症都被治愈了。

日志配置

问题出在为每个站点配置日志上,由于要为大量站点配置日志,按照最原始的写法,是这样的:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
example.com {
    log {
        output file /log/example.com/access.log {
        roll_size 100MiB
        roll_local_time
        roll_keep 10
        roll_keep_for 2160h
        }
    }
}

网站一多,就要在配置文件中写许多重复的内容,优雅性瞬间降低,于是找到了官方文档中的 Snippets

Snippets

通过定义 Snippets,可以将一段重复使用的代码定义一个名字,需要使用的时候 import 一下即可,并且文档说它可以用在 Caddyfile 的几乎所有位置,具体的示例可以看文档中的 Snippets 部分

As a special case, it can appear almost anywhere within the Caddyfile.

很是方便,于是,日志部分变成了这个样子:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
(log_config) {
    roll_size 100MiB
    roll_local_time
    roll_keep 10
    roll_keep_for 2160h
}

example.com {
    log {
        output file /log/example.com/access.log {
            import log_config
        }
    }
    reverse_proxy 172.17.0.1:39004
}

怎么说呢,优雅了,但没有完全优雅。

能不能把日志输出目录中的域名也写到一段 Snippet 中,用一行代码配置呢?

占位符

于是在文档中找到了 Placeholders,但是,{host} 并不能出现在日志部分的配置中,会报错:

1
loading initial config: loading new config: setting up custom log 'log0': loading log writer module: loading module 'file': provision caddy.logging.writers.file: invalid filename for log file: unrecognized placeholder {http.request.host}

在社区中搜索,找到了一个同样的问题,然后,在这个问题被提出不到一天的时间里,francislavoie 提交了 PR,并在不到两周以后被合并到了主分支。

于是,现在我们可以真正优雅起来了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
(log) {
    log {
        output file /log/{args.0}/access.log {
            roll_size 100MiB
            roll_local_time
            roll_keep 10
            roll_keep_for 2160h
        }
    }
}

a.example.com {
    import log a.example.com
}

当 Snippets 支持传入参数了,那就可以做更多更优雅的事情了……比如访客白名单。

访客白名单

有几个网站,是只允许白名单内的 ip 访问的,之前的文章也提过使用 Caddy 配置权限控制。但同样的问题,站点一多,配置就会变的不够优雅:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
a.example.com {
    @ip_whitelist {
        remote_ip 1.1.1.1 2.2.2.2 3.3.3.3
    }

    route @ip_whitelist {
        reverse_proxy 172.17.0.1:12345
    }

    respond 403
}

现在可以这样做了:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
(rp_ipwl) {
    @ip_whitelist {
        remote_ip 47.100.33.217 81.68.234.172 49.235.83.254
    }

    route @ip_whitelist {
        reverse_proxy {args.0}
    }

    respond {args.1}
}

a.example.com {
    import rp_ipwl 172.17.0.1:12345 403
}

b.example.com {
    import rp_ipwl 172.17.0.1:23456 403
}

最后的废话

感觉 Caddy 对于个人用户真的十分友好啊,配置简洁方便,社区活跃,绝大部分问题都能在社区找到解决方案,越用越觉得优雅~