• Caddy部署与使用—踩坑总结


    Caddy部署与使用

    官方文档

    https://github.com/caddyserver/caddy
    
    • 1

    Caddy是什么

    相信大家都知道apache、nginx,那么caddy也一样,它是一个Web服务器,可以帮你托管你的Web服务,让其他人可以通过互联网访问。

    比如你想搭建一个博客,可以在互联网上被其他人访问,那么就可以使用caddy,相比nginx来说,它配置更简单。

    对于caddy,官方是这么定义的:

    Caddy 2 is a powerful, enterprise-ready, open source web server with automatic HTTPS written in Go

    Caddy是一个强大的、企业级的、开放源代码的web服务器,使用Go编写,并且可以自动HTTPS加密(其实就是自动配置TLS证书并管理)。

    安装Caddy
    得益于Go语言,caddy是一个独立的二进制包,所以它没有任何依赖,你可以直接从官网下载并安装它。

    docker-compose部署caddy并开启https请求

    创建目录(在root目录下)

    $ mkdir -p caddy/{conf,logs,www}
    $ cd caddy
    
    • 1
    • 2

    配置Caddyfile

    $ vi conf/Caddyfile
    
    • 1
    www.?????.net {
      gzip
      root /opt/www 
      timeouts 30s
      log /opt/logs/access.log
      proxy / localhost:8080  #根url 直接代理转发
      proxy /more localhost:8081 localhost:8082  #负载均衡
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    我自己的配置
    image-20220820203728669

    我想直接访问 www.???.net 就帮我代理转发到 localhost:8080,可以!我想直接访问 www.???.net 就帮我代理转发到 localhost:8080,可以!

    以上是在配置公网域名后的配置,还没有配置域名?那直接用 IP 就行,如下
    192.168.1.2:80 192.168.1.2:443 {
      gzip
      root /opt/www 
      tls self_signed  #自动签名,很重要
      timeouts 30s
      log /opt/logs/access.log
      proxy /other localhost:8080
    }
    
    自己看着修改
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    配置docker-compose.yml

    $ vi docker-compose.yml
    
    • 1
    
    version: '3.7'
    
    services:
      # http/2 server
      caddy:
        image: abiosoft/caddy
        container_name: caddy
        hostname: caddy
        domainname: caddy
        restart: always
        environment:
          - ACME_AGREE=true
          - TZ=Asia/Shanghai
          - agree
        volumes:
          - "/caddy/conf/Caddyfile:/etc/Caddyfile"
          - "/caddy/.caddy:/root/.caddy"
          - "/caddy/logs:/opt/logs"
          - "/caddy/www:/opt/www"
        ports:
          - "80:80"
          - "443:443"
          - "443:443/udp"
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    image-20220820204046620

    其中三个环境变量(environment)非常重要

    1、配置上海时区
    2、同意caddy自动配置ssl证书
    3、caddy需要的反馈邮箱

    启动

    $ docker-compose up -d
    $ docker logs -f caddy    # 查看日志
    
    • 1
    • 2

    测试

    随便复制个文件到 www 目录下,我复制了个图片bg.jpg,
    然后输入 https://192.168.1.2/bg.jpg

    image-20220820204858762

    Caddyfile配置详解

    Caddyfile 主要包含一些通用的配置,并将其抽到配置片段中,类似于 nginx 的 nginx.conf 主配置;在最后部分通过 import 关键字引入其他具体站点配置,类似 nginx 的 vhost 配置。

    # 授权认证服务
    http://auth-server.jianpeicn.com {
      reverse_proxy http://172.16.95.146:5000
    }
    
    
    # 基础服务
    http://management-server.jianpeicn.com {
      reverse_proxy /api/identity/*               http://172.16.95.146:5001
      reverse_proxy /api/multi-tenancy/*          http://172.16.95.146:5003
      reverse_proxy /api/identity-server/*        http://172.16.95.146:5002
      reverse_proxy /api/permission-management/*  http://172.16.95.146:5004
      reverse_proxy /api/storage/*                http://120.26.112.192:7020
      reverse_proxy /*                            http://172.16.95.146:7000
    }
    
    https://management-server.jianpeicn.com {
      tls internal
      reverse_proxy /api/identity/*               http://172.16.95.146:5001
      reverse_proxy /api/multi-tenancy/*          http://172.16.95.146:5003
      reverse_proxy /api/identity-server/*        http://172.16.95.146:5002
      reverse_proxy /api/permission-management/*  http://172.16.95.146:5004
      reverse_proxy /api/storage/*                http://120.26.112.192:7020
      reverse_proxy /*                            http://172.16.95.146:7000
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • tls: 是否使用htpps证书(内网使用internal,外网使用邮箱)
    • reverse_proxy: 代理地址

    配置片段

    Caddyfile 支持类似代码中 function 一样的配置片段,这些配置片段可以在任意位置被 import,同时可以接受参数,以下为配置片断示例:

    # 括号内为片段名称,可以自行定义
    (TLS) {
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    }
     
    # 在任意位置可以引用此片段从而达到配置复用
    import TLS
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    配置模块化

    import 指令除了支持引用配置片段以外,还支持引用外部文件,同时支持通配符,有了这个命令以后我们就可以方便的将配置文件进行模块化处理:

    # 引用外部的 /etc/caddy/*.caddy
    import /etc/caddy/*.caddy
    
    • 1
    • 2

    站点配置

    针对于站点域名配置,Caddyfile 比较自由化,其格式如下:

    地址 {
        站点配置
    }
    
    • 1
    • 2
    • 3

    关于这个 “地址” 接受多种格式,以下都为合法的地址格式:

    localhost
    
    example.com
    
    :443
    
    http://example.com
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    localhost:8080
    
    127.0.0.1
    
    [::1]:2015
    
    example.com/foo/*
    
    *.example.com
    
    http://
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    配置多个Web服务

    既然caddy是一个Web服务器,那么就不止可以托管一个Web站点,如果需要托管多个,怎么做呢?

    localhost {
        respond "Hello, world!"
    }
    localhost:2016 {
        respond "Goodbye, world!"
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    配置反向代理

    localhost
    reverse_proxy 127.0.0.1:9000
    
    • 1
    • 2

    以上示例,都是把https://localhost/ 的请求代理到127.0.0.1:9000 。

    以上http默认的是80端口,https默认的是443端口。当然,我们也可以换个端口,比如2016.

    :2016
    reverse_proxy 127.0.0.1:9000
    
    • 1
    • 2

    代理匹配的请求

    caddy作为一个强大的web服务器,其反向打理功能肯定不止以上这么简单。比如,我们不想代理全部的网络请求,而是只想代理匹配的怎么做呢?比如代理 /api 这个Path下的。

    reverse_proxy /api/*  {
        to 127.0.0.1:9000
    }
    
    • 1
    • 2
    • 3

    从以上示例可以看到,只需要在 reverse_proxy 指令后,加 /api/* 这个match即可,这和Nginx的 location 是非常相似的。

    代理到多个上游服务

    为了高可用,上游服务我们会部署多少,这样当一个有问题的时候,不会影响产品功能。下面我们看下Caddy是如何实现这一能力的。

    reverse_proxy node1:80 node2:80 node3:80
    
    • 1

    这样就会所有的请求,随机的反向代理到这三个node节点上了。
    当然我们还可以这样配置:

    reverse_proxy /api/*  {
        to node1:80 node2:80 node3:80
    }
    
    • 1
    • 2
    • 3

    当同时配置多个反向代理服务的时候,就有了负载均衡了。以上默认的情况下,是随机的,也就是caddy会随机的选择一个上游服务使用。

    Caddy的负载均衡

    只要定义了多个上游(upstream),Caddy的反向代理就会使用负载均衡的能力,,就是用了负载均衡,代码如下所示:

    reverse_proxy /api/*  {
        to node1:80 node2:80 node3:80
    }
    
    • 1
    • 2
    • 3

    以上这个配置,它的负载均衡策略(调度方式)默认是随机的,我们可以通过 lb_policy 来指定不同的负载均衡策略,比如

    reverse_proxy /api/*  {
        to node1:80 node2:80 node3:80
        lb_policy first
    }
    
    • 1
    • 2
    • 3
    • 4

    以上代码指定的是 first 的负责均衡策略,也就是选择第一个可用的上游。

    负载均衡策略

    除了 first 外,还有很多负载均衡策略以供我们选择,下面就为你分别介绍他们。
    
    1- first:选取第一个可用的上游
    
    2- random:随机选取一个可用的上游
    
    3- least_conn:选取当前请求数最少的上游,这个比较适合长连接的场景
    
    4- ip_hash:根据IP的Hash值选取一个固定的上游
    
    5- random_choose 
    
    :随机选取2个或者更多个上游,然后再从中选择负载最小的,n通常为2
    6- header:这个是根据请求头的Hash选取一个固定的上游,和 ip_hash 很像,只不过它是根据指定的请求头的值进行Hash,然后选取上游的。所以这里的用法是 header ,要指定一个请求头。
    
    7- uri_hash:这个也和 ip_hash 很像,只不过它是根据请求的URI进行Hash,然后选取一个上游。
    
    8- round_robin:这个策略是循环迭代,挨个使用一个个上游,每个上游都可以被用到,轮着来。
    
    9- cookie 
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21

    重试等待时间

    当你设置了多个上游主机,启用了负载均衡后,不可避免的会遇到上游服务不可用的情况,默认情况下,Caddy的处理是:当上游服务器不可用的时候,客户端的请求就没有可用的服务来相应,客户端就会报错。
    
    当然除了立即响应服务不可用,Caddy还提供了负责均衡的重试功能,这就是 lb_try_duration ,他可以设置一个重试的时间,比如1000毫秒。
    
    这是什么意思呢?如果你设置了lb_try_duration 为1000毫秒,那么Caddy的负载均衡在处理该客户端请求时,如果选用了一个不可用的上游服务,就会继续重试,一直到找到一个可用的上游或者到了设置的1000毫秒时间为止。
    
    也就是,这个时间,就是Caddy的负载平衡器尝试查找可用的上游主机时,客户端将等待最长时间
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    重试时间间隔

    有了重试等待时间,肯定也有重试时间间隔,因为正常的逻辑上来讲,不能马上去重试,因为马上重试的话,很大概率拿到的也是个不可用的上游主机,所以需要一个重试时间间隔,来控制重试的节奏,在Caddy中,就是 lb_try_interval ,默认是重试间隔是250ms,250毫秒。
    
    所以你可以看到, lb_try_interval 是结合着lb_try_duration 来使用的。lb_try_duration 是重试等待的总时间,而lb_try_interval 是在这段时间内,每隔多久重试一次。
    
    
    • 1
    • 2
    • 3
    • 4

    负载均衡示例非常简单,按照配置写即可

    # 按照ip hash 负载均衡
    reverse_proxy /api/*  {
        to node1:80 node2:80 node3:80
        lb_policy ip_hash
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5

    设置等待时间的话,可以这样:

    # 按照ip hash 负载均衡,重试等待时间为5秒
    reverse_proxy /api/*  {
        to node1:80 node2:80 node3:80
        lb_policy ip_hash
        lb_try_duration 5s
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    环境变量

    Caddyfile 支持直接引用系统环境变量,通过此功能可以将一些敏感信息从配置文件中剔除:

    # 引用环境变量 GANDI_API_TOKEN
    dns gandi {$GANDI_API_TOKEN}
    
    • 1
    • 2

    配置片段参数支持

    针对于配置片段,Caddyfile 还支持类似于函数代码的参数支持,通过参数支持可以让外部引用时动态修改配置信息:

    (LOG) {
        log {
            format json  {
                time_format "iso8601"
            }
            # "{args.0}" 引用传入的第一个参数,此处用于动态传入日志文件名称
            output file "{args.0}" {
                roll_size 100mb
                roll_keep 3
                roll_keep_for 7d
            }
        }
    }
     
    # 引用片段
    import LOG "/data/logs/mritd.com.log"
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    自动证书申请

    在启动 Caddy2 之前,如果目标域名(例如: www.example.com)已经解析到了本机,那么 Caddy2 启动后会尝试自动通过 ACME HTTP 挑战申请证书;如果期望使用 DNS 的方式申请证书则需要其他 DNS 插件支持,比如上面编译的 --with github.com/caddy-dns/gandi 为 gandi 服务商的 DNS 插件;关于使用 DNS 挑战的配置编写方式需要具体去看其插件文档,目前 gandi 的配置如下:

    tls {
     dns gandi {env.GANDI_API_TOKEN}
    }
    
    • 1
    • 2
    • 3

    配置完成后 Caddy2 会通过 ACME DNS 挑战申请证书,值得注意的是即使通过 DNS 申请证书默认也不会申请泛域名证书,如果想要调整这种细节配置请使用 json 配置或管理 API。

    (LOG) {
        log {
            # 日志格式参考 https://github.com/caddyserver/format-encoder 插件文档
            format formatted "[{ts}] {request>remote_addr} {request>proto} {request>method} <- {status} -> {request>host} {request>uri} {request>headers>User-Agent>[0]}"  {
                time_format "iso8601"
            }
            output file "{args.0}" {
                roll_size 100mb
                roll_keep 3
                roll_keep_for 7d
            }
        }
    }
     
    (TLS) {
        # TLS 配置采用 https://mozilla.github.io/server-side-tls/ssl-config-generator/ 生成,SSL Labs 评分 A+
        protocols tls1.2 tls1.3
        ciphers TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 TLS_ECDHE_ECDSA_WITH_CHACHA20_POLY1305_SHA256 TLS_ECDHE_RSA_WITH_CHACHA20_POLY1305_SHA256
    }
     
    (HSTS) {
        # HSTS (63072000 seconds)
        header / Strict-Transport-Security "max-age=63072000"
    }
     
    (ACME_GANDI) {
        # 从环境变量获取 GANDI_API_TOKEN
        dns gandi {$GANDI_API_TOKEN}
    }
     
    # 聚合上面的配置片段为新的片段
    (COMMON_CONFIG) {
        # 压缩支持
        encode zstd gzip
     
        # TLS 配置
        tls {
            import TLS
            import ACME_GANDI
        }
     
        # HSTS
        import HSTS
    }
     
    # 开启 HTTP3 实验性支持
    {
        servers :443 {
            protocol {
                experimental_http3
            }
        }
    }
     
    # 引入其他具体的站点配置
    import /etc/caddy/*.caddy
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56
    mritd.com.caddy

    mritd.com.caddy 为主站点配置,主站点配置内主要编写一些路由规则,TLS 等都从配置片段引入,这样可以保持统一。

    www.mritd.com {
        # 重定向到 mritd.com(默认 302)
        redir https://mritd.com{uri}
     
        # 日志
        import LOG "/data/logs/mritd.com.log"
     
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
     
    mritd.com {
        # 路由
        route /* {
            reverse_proxy mritd_com:80
        }
        # 日志
        import LOG "/data/logs/mritd.com.log"
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    mritd.me.caddy

    mritd.me.caddy 为老站点配置,目前主要将其 301 到新站点即可。

    www.mritd.me {
        # 重定向到 mritd.com
        # 最后的 "code" 支持三种参数
        # temporary => 302
        # permanent => 301
        # html => HTML document redirect
        redir https://mritd.com{uri} permanent
     
        # 日志
        import LOG "/data/logs/mritd.com.log"
     
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
     
    mritd.me {
        # 重定向
        redir https://mritd.com{uri} permanent
     
        # 日志
        import LOG "/data/logs/mritd.com.log"
     
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    采用以下大佬文章理解caddy这个服务
    www.mritd.me {
        # 重定向到 mritd.com
        # 最后的 "code" 支持三种参数
        # temporary => 302
        # permanent => 301
        # html => HTML document redirect
        redir https://mritd.com{uri} permanent
     
        # 日志
        import LOG "/data/logs/mritd.com.log"
     
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
     
    mritd.me {
        # 重定向
        redir https://mritd.com{uri} permanent
     
        # 日志
        import LOG "/data/logs/mritd.com.log"
     
        # TLS、HSTS、ACME 等通用配置
        import COMMON_CONFIG
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    采用以下大佬文章理解caddy这个服务

    image-20220820211704958

  • 相关阅读:
    测试/开发程序员为什么这么吃香,高薪的“孤独症患者“......
    自动化办公更简单了:新版python-office,有哪些更新?
    【QT】QMessageBox消息框的使用(16)
    更快更稳更安全!天翼云CDN了解一下
    FPGA——UART串口通信
    JVM之class文件结构剖析
    Spring依赖注入之@autowire注解详解
    ARM64 linux并发与同步之内存屏障
    IDEA创建SpringBoot的多模块项目教程
    网络安全渗透测试工具之skipfish
  • 原文地址:https://blog.csdn.net/tianmingqing0806/article/details/126444583