当前位置: 首页 > Linux

比Nginx更强大的Web服务器

时间:2023-04-06 02:02:37 Linux

Caddy介绍Caddy是一个用Go编写的Web服务器,类似于Nginx,Caddy提供了更强大的功能,随着v2的发布,Caddy已经可以作为中小型Web服务器使用另一种选择;使用Caddy相对于Nginx的优势如下:自动HTTPS证书申请(ACMEHTTP/DNS挑战),自动证书更新和OCSP装订等更高的安全性包括但不限于TLS配置和内存安全如此友好和强大的配置文件支持API动态调整配置(如果有人可以建一个Dashboard)支持HTTP3(QUIC)支持动态后端,比如连接Consul,作为k8singress等后端多种负载策略和健康检测等。它是用Go自己写的,并且高度模块化的系统易于扩展(CoreDNS是基于Caddy1开发的)...目前个人印象中Caddy唯一的缺点就是性能没有Nginx高,但这是一个问题不同意见;由于提供的便利性,当性能可以接受时,完全有理由切换到Caddy。编译Caddy2注意:在Caddy1时代,Caddy官方发布的预编译二进制文件是不允许商用的。Caddy2之后,都已经切换到Apache2.0License。Caddy2官方默认提供了预编译的二进制文件和自定义构建下载页面,但是当我们需要集成一些第三方插件时,还是需要使用官方的xcaddy自己编译;下面是具体编译过程:Golang环境安装本部分默认编译环境为Ubuntu20.04系统,同时使用root用户。其他环境请自行调整相关目录和配置;科学上网相关的配置在编译的时候自行处理,也可以直接用国外的VPS服务器编译。首先下载go语言的SDK包,其他平台可以从https://golang.org/dl/下载对应的包:wgethttps://golang.org/dl/go1.15.6.linux-amd64.tar。gz下载完成后,解压并配置相关变量:#unziptar-zxvfgo1.15.6.linux-amd64.tar.gz#移动到任意目录mkdir-p/opt/devtoolsmvgo/opt/devtools/go#create去相关目录mkdir-p${HOME}/gopath/{src,bin,pkg}#调整变量配置,在shell初始化配置中加入以下变量#bash用户请编辑~/.bashrc#zsh用户请编辑~/.zshrcexportGOROOT='/opt/devtools/go'exportGOPATH="${HOME}/gopath"exportGOPROXY='https://goproxy.cn'#如果科学上网问题已经解决,GOPROXY变量可以删除,否则可能会出问题ReactionexportPATH="${GOROOT}/bin:${GOPATH}/bin:${PATH}"#让配置生效#bash用户替换为~/.之后在命令行执行goversion,返回如下成功:bleem?~goversiongoversiongo1.15.6linux/amd64安装xcaddy按照官方文档执行goget-ugithub.com/caddyserver/xcaddy/cmd/只需安装xcaddy:bleem?~goget-ugithub.com/caddyserver/xcaddy/cmd/xcaddygo:downloadinggithub.com/caddyserver/xcaddyv0.1.7go:foundgithub.com/caddyserver/xcaddy/cmd/xcaddy在github.com/caddyserver/xcaddyv0.1.7go:down加载github.com/Masterminds/semver/v3v3.1.0go:github.com/Masterminds/semver/v3升级=>v3.1.1go:下载github.com/Masterminds/semver/v3v3.1.1......安装完成后,应该可以直接在命令行执行xcaddy命令:#xcaddy不提供完整的命令行支持,所以`--help`是正常报错bleem?~xcaddy--helpgo:无法匹配“全部”:工作目录不是模块的一部分2021/01/0712:15:56[错误]exec[golist-m-f={{if.Replace}}{{.Path}}=>{{.Replace}}{{end}}all]:退出状态1:编译Caddy2前,系统需要安装jq、curl、git命令。如果没有,请使用aptinstall-ycurlgitjq命令安装;自编译的目的是为了增加第三方插件的方便性,其中官方列出的插件可以从下载页面获取:其他插件可以从GitHub上找或者自己写。整理好这些插件列表后,只需要使用xcaddy编译即可:#获取最新版本号,其实直接去GitHub真实页面复制一下就可以了#这个是转换成脚本的方便自动导出version=$(curl-s"https://api.github.com/repos/caddyserver/caddy/releases/latest"|jq-r.tag_name)#使用xcaddy编译xcaddybuild${version}--output./caddy_${version}--withgithub.com/abiosoft/caddy-exec--withgithub.com/caddy-dns/cloudflare--withgithub.com/caddy-dns/dnspod--withgithub.com/caddy-dns/duckdns--withgithub.com/caddy-dns/gandi--withgithub.com/caddy-dns/route53--withgithub.com/greenpau/caddy-auth-jwt--withgithub.com/greenpau/caddy-auth-portal--withgithub.com/greenpau/caddy-trace--withgithub.com/hairyhenderson/caddy-teapot-modulewith--github.com/kirsch33/realip--withgithub.com/porech/caddy-maxmind-geolocation--withgithub.com/caddyserver/format-encoder--withgithub.com/mholt/caddy-webdav编译过程日志如下如下稍等会生成编译后的二进制文件:编译成功后,可以使用list-modules子命令查看添加的插件是否成功编译到caddy中:bleem?~./caddy_v2.3.0list-modulesadmin.api.loadadmin.api.metricscaddy.adapters.caddyfilecaddy.listeners.tlscaddy.logging.encoders.consolecaddy.logging.encoders.filtercaddy.logging.encoders.filter.deletecaddy.logging.encoders.filter.ip_maskcaddy.logging.encoders.格式化的caddy.logging.encoders.jsoncaddy.logging.encoders.logfmtcaddy.logging.encoders.single_fieldcaddy.logging.writers.discardcaddy.logging.writers.filecaddy.logging.writers.netcaddy.logging.writers.stderrcaddy.logging.writers.stdoutcaddy.storage.file_systemdns.providers.cloudflaredns.providers。dnspoddns.providers.duckdnsdns.providers.gandidns.providers.route53exechttphttp.authentication.hashes.bcrypthttp.authentication.hashes.scrypthttp.authentication.providers.http_basichttp.authentication.providers.jwt...安装Caddy2主机安装主机安装Caddy2需要由systemd保护。好在Caddy2官方提供了各种平台的安装包和systemd配置文件仓库;目前推荐的方式是直接使用包管理器安装标准版Caddy2,然后替换自编译的可执行文件:#安装标准版Caddy2sudoaptinstall-ydebian-keyringdebian-archive-keyringapt-transport-httpscurl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/cfg/gpg/gpg.155B6D79CA56EA34.key'|sudoapt-keyadd-curl-1sLf'https://dl.cloudsmith.io/public/caddy/stable/cfg/setup/config.deb.txt?distro=debian&version=any-version'|sudotee-a/etc/apt/sources.list.d/caddy-stable.listsudoaptupdatesudoaptinstallcaddy#替换二进制文件systemctlstopcaddyrm-f/usr/bin/caddymv./caddy_v2.3.0/usr/bin/caddyDocker安装Docker用户可以通过Dockerfile自己编译镜像,目前我写了一个基于xcaddy的Dockerfile,如有其他插件需要集成,自行修改重新编译;目前Dockerfile预编译镜像已经推送到DockerHub,镜像名称为mritd/caddyConfigurationCaddy2Caddy2配置文件的核心使用的是json,但是json可读性不强,所以官方维护了一个转换器来抽象出一种名为Caddyfile的新配置格式;Caddyfile的完整语法可以参考官方文档https://caddyserver.com/docs/...,本文只是做一些基本用法的例子。ConfigurationfragmentCaddyfilesupportsconfigurationfragmentssimilartothefunctioninthecode.Theseconfigurationfragmentscanbeimportedatanypositionandcanacceptparameters.Thefollowingareexamplesofconfigurationfragments:#Bracketsarefragmentnames,whichcanbedefinedbyyourself(TLS){protocolstls1.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配置模块化import指令除了支持引用配置片段以外,还支持引用外部文件,同时支持通配符,Withthiscommand,wecaneasilymodularizetheconfigurationfile:#referenceexternal/etc/caddy/*.caddyimport/etc/caddy/*.caddysiteconfigurationisforsitedomainnameconfiguration,Caddyfileismoreliberal,itsformatisasfollows:Address{Siteconfiguration}Regardingthis"address",multipleformatsareaccepted,andthefollowingarelegaladdressformats:localhostexample.com:443http://example.comlocalhost:8080127.0.0.1[::1]:2015example.com/foo/**.example.comhttp://environmentvariableCaddyfilesupportsdirectreferencetosystemenvironmentvariables,throughwhichsomesensitiveinformationcanberemovedfromtheconfigurationfile:#referenceenvironmentvariableGANDI_API_TOKENdnsgandi{$GANDI_API_TOKEN}configurationfragmentParametersupportisaimedatconfigurationfragments.Caddyfilealsosupportsparametersupportsimilartofunctioncodes.Throughparametersupport,configurationinformationcanbedynamicallymodifiedwhenexternalreferencesaremade:(LOG){log{formatjson{time_foRMAT"ISO8601"}#"{args.0}"引用传入的第一个参数,这里用来动态传递日志文件名输出文件"{args.0}"{roll_size100MBROLL_KEEP3ROLL_KEEP_FOR7D}}}}}}}}#QuotefragmentimportLOG"/data/logs/mritd.com.log"自动申请证书在启动Caddy2之前,如果目标域名(例如:www.example.com)已经解析到本机,那么Caddy2会在启动后尝试通过ACMEHTTP挑战自动申请证书;如果要使用DNS申请证书,需要其他DNS插件支持,比如上面编译的--withgithub.com/caddy-dns/gandi就是gandi服务商的DNS插件;关于使用DNS挑战配置的写法需要详细阅读其插件文档。gandi当前配置如下:tls{dnsgandi{env.GANDI_API_TOKEN}}配置完成后,Caddy2会通过ACMEDNS挑战申请证书。值得注意的是,即使默认通过DNS申请证书,也不会申请泛域名证书。如果要调整此详细配置,请使用json配置或管理API完整的模块化配置示例。了解了上面的基本配置信息后,我们就可以实际编写站点配置了;下面是一个网站的基础Caddy配置示例:目录结构:caddy├──Caddyfile├──mritd.com.caddy└──mritd.me.caddyCaddyfileCaddyfile主要包含一些常用的配置,并将其提取成配置片段,类似于nginxnginx.conf的主要配置;最后一部分通过import关键字导入其他具体的站点配置,类似于nginx的vhost配置。(LOG){log{#日志格式参考https://github.com/caddyserver/format-encoder插件文档formatformatted[{ts}]{request>remote_addr}{request>proto}{request>method}<-{status}->{request>host}{request>uri}{request>headers>user-agent>[0]}“{time_format”iso8601“}outputfile”{args.0}{args.0}{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_SHA256TLS_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}}}#Introduceotherspecificsiteconfigurationsimport/etc/caddy/*.caddymritd.com.caddymritd.com.caddyisthemainsiteconfiguration,andthemainsiteconfigurationmainlywritessomeroutingrules,TLSetc.areimportedfromtheconfigurationfragment,soastomaintainaunifiedwww.mritd.com{#Redirecttomritd.com(default302)redirhttps://mritd.com{uri}#LogimportLOG"/data/logs/mritd.com.log"#GeneralconfigurationssuchasTLS,HSTS,ACME,etc.importCOMMON_CONFIG}mritd.com{#Routingroute/*{reverse_proxymritd_com:80}#LogimportLOG"/data/logs/mritd.com.log"S,HSTS,ACMEandothercommonconfigurationsimportCOMMON_CONFIG}mritd.me.caddymritd.me.caddyisconfiguredfortheoldsite,andcurrentlyitismainly301tothenewsite.www.mritd.me{#重定向到mritd.com#最后一个“code”支持三个参数#temporary=>302#permanent=>301#html=>HTMLdocumentredirectredirhttps://mritd.com{uri}permanent#日志importLOG"/data/logs/mritd.com.log"#TLS、HSTS、ACME等通用配置importCOMMON_CONFIG}mritd.me{#重定向redirhttps://mritd.com{uri}permanent#logimportLOG"/data/logs/mritd.com.log"#TLS,HSTS,ACME等通用配置importCOMMON_CONFIG}启动和reload配置文件写完后,可以通过systemctlstart启动caddyserver球童;每次配置修改后,可以使用systemctlreloadcaddy重新加载配置。重载过程中,caddy不会重启(实际调用的是caddyreload命令)。当配置文件写错时,重载只会失败,不会影响正在运行的caddyserver。小结本文仅列举一些简单的Caddy使用示例。在强大插件的配合下,Caddy可以实现各种“神奇”的功能。这些功能依赖于复杂的Caddy配置。caddy配置需要仔细阅读官方文档。关于Caddyfile的每个配置部分在文档中都有详细描述。值得一提的是,Caddy本身内置了丰富的插件,比如内置“file_server”,内置各种负载均衡策略等,这些插件可以组合起来实现一些复杂的功能;Caddy是用go写的,官方也给出了相比Nginx通过Lua或者C开发编写插件,Caddy的插件开发上手容易多了;Caddy本身内置了数据存储、动态后端、配置文件转换等功能。扩展接口,为开发具有特定需求的扩展打下了良好的基础。总之,总的来说,在可以接受Caddy2的性能损失的情况下,Caddy2是与Nginx相比的绝佳选择。振祥警告说,各种新功能可以满足现代网站的需求。原文:https://mritd.com/2021/01/07/...