前几天用 Netmaker 的时候发现它用 Caddy 替换掉了 Nginx,用了后发现确实简单好用,就安利一下。
Caddy 是一个强大的、可扩展的平台,用 Go 编写,可以为你的站点、服务和应用程序提供服务。如果你是 Caddy 的新手,你服务网络的方式将会改变。
大多数人使用 Caddy 作为网络服务器或代理,但在其核心,Caddy 是一个服务器的服务器(a server of servers)。通过必要的模块,它可以承担任何长时间运行的进程的角色!
配置是动态的和可通过 Caddy 的 API 导出 。虽然不需要配置文件,但是您仍然可以使用它们; 大多数人最喜欢的配置 Caddy 的方法是使用 Caddyfile。配置文档的格式通过配置适配器采用多种形式,但 Caddy 的本地配置语言是 JSON。
Caddy 为所有主流平台编译,并且没有运行时依赖项。
我们建议每个人不管经验如何都要看一下我们的入门指南。它将为你提供一个全面的视角来看待你的新网络服务器,这对你继续学习是无价的。本教程将探索使用 Caddy 的基础知识,并帮助您在更高的层次上熟悉它。
目的:
先决条件
caddy 及 curl(安装 Caddy 可以参考这里)要启动 Caddy 作为一个守护程序,使用 run 子命令:
caddy run
默认情况下,Caddy 的配置(“ config”)为空。我们可以使用另一个终端访问管理 API 来验证这一点:
curl localhost:2019/config/
{% note info %}
ℹ️ 信息:
上面地址不是你的网站,localhost:2019 是用来控制 Caddy 的管理端点,并被默认限制为本机访问。
我们可以通过给它一个配置来使 Caddy 变得有用。这可以通过多种方式完成,但是我们将在下一节使用 curl 向 /load 端点发出 POST 请求。
为了准备我们的请求,我们需要做一个配置。
将其保存到 JSON 文件中(例如 caddy.JSON) :
{
"apps": {
"http": {
"servers": {
"example": {
"listen": [":2015"],
"routes": [
{
"handle": [{
"handler": "static_response",
"body": "Hello, world!"
}]
}
]
}
}
}
}
}
然后上传:
curl localhost:2019/load \
-X POST \
-H "Content-Type: application/json" \
-d @caddy.json
我们可以通过如下命令验证 Caddy 将我们的新配置应用到另一个 GET 请求:
curl localhost:2019/config/
然后测试新的配置:
$curl localhost:2015
Hello, world!
如果你看到 Hello, world! 那恭喜了,成功了!确保配置按预期的方式工作总是一个好主意,尤其是在部署到生产环境之前。
另一种配置 Caddy 的方法是 Caddyfile。上面我们在 JSON 编写的配置可以简单地表达为:
:2015
respond "Hello, world!"
将其保存到工作目录文件中名为 Caddyfile (无扩展名)的文件中。
如果 Caddy 已经在运行, (Ctrl + c)停止它,然后运行:
caddy adapt
或者你把 Caddyfile 存储在别的地方,或者给它取了别的名字:
caddy adapt --config /path/to/Caddyfile
您将看到 JSON 输出! 这里发生了什么?
我们只是使用配置适配器将 Caddyfile 转换为 Caddy 的原生 JSON 结构。
虽然我们可以获得这个输出并发出另一个 API 请求,但是我们可以跳过所有这些步骤,因为 caddy 命令可以为我们完成这些操作。如果工作目录中有一个叫 Caddyfile 的文件,并且没有指定其他配置,Caddy 会加载 Caddyfile,为我们改编,然后马上运行。
现在当前文件夹中有一个 Caddyfile,让我们再次运行 caddy:
caddy run
或者如果你的 Caddyfile 在其他地方:
caddy run --config /path/to/Caddyfile
(如果调用的是不以“ Caddyfile”开头的其他名称,则需要指定 --adapter caddyfile)
正如你所看到的,有几种方法可以让你使用初始配置启动 Caddy:
--config flag (可选项,带有--adapter flag)-resume flag (如果先前加载了配置)现在您知道了,Caddyfile 刚刚为您转换为 JSON。
Caddyfile 看起来比 JSON 简单,但是你应该一直使用它吗?每种方法都有利有弊。答案取决于您的需求和用例。
| JSON | Caddyfile |
|---|---|
| 完整的 Caddy 功能 | 最常见的 Caddy 功能部件 |
| 易于生成 | 易于手工制作 |
| 易于编程 | 难以自动化 |
| 非常有表现力 | 适度的表达 |
| 允许配置遍历 | 不能在 Caddyfile 间转换 |
| 部分配置更改 | 只能修改整个配置 |
| 可以导出 | 无法导出 |
| 与所有 API 端点兼容 | 与某些 API 端点兼容 |
| 自动生成的文档 | 文档是手写的 |
| 无处不在 | 小众 |
| 更有效率 | 更多的计算 |
| 有点无聊 | 挺有意思的 |
| 了解更多:JSON 结构 | 了解更多:Caddyfile 文档 |
您将需要决定哪一个最适合您的用例。
需要注意的是,JSON 和 Caddyfile (以及任何其他支持的配置适配器)都可以与 Caddy 的 API 一起使用。然而,如果您使用 JSON,您将获得 Caddy 的全部功能和 API 特性。如果使用配置适配器,使用 API 加载或更改配置的唯一方法是 /load 端点。
{% note info %}
ℹ️ 信息:
实际上,即使是配置文件也要经过 Caddy 的 API 端点,命令只是为您包装了这些 API 调用。
您还需要决定您的工作流是基于 API 的还是基于 CLI 的。(您可以在同一台服务器上同时使用 API 和配置文件,但我们不推荐这样做: 最好有一个真实的来源。)
| API | 配置文件 |
|---|---|
| 使用 HTTP 请求修改配置 | 使用 shell 命令修改配置 |
| 易于扩大规模 | 难以规模化 |
| 手工操作难度大 | 易于手工操作 |
| 真的很有趣 | 也很有趣 |
| 了解更多:API 教程 | 了解更多:Caddyfile 教程 |
{% note info %}
ℹ️ 信息:
使用 API 手动管理服务器配置完全可以通过适当的工具实现,例如: 任何 REST 客户端应用程序
或配置文件工作流的选择与配置适配器的使用是正交的: 你可以使用 JSON,但存储在一个文件中,并使用命令行界面; 相反,你也可以使用 Caddyfile 与 API。
但是大多数人会使用 json + api 或 Caddyfile + CLI 组合。
如您所见,Caddy 非常适合于各种各样的用例和部署!
因为 Caddy 是一个服务器,所以它可以无限期地运行。这意味着在执行 caddy run 之后,终端不会解除阻塞,直到进程终止(通常使用 Ctrl + c)。
虽然 caddy run 是最常见的,通常是推荐的(特别是在进行系统服务时!),你也可以选择使用 caddy start 启动 Caddy,并让它在后台运行:
caddy start
这将允许您再次使用您的终端,这在一些交互式无头环境中非常方便。
然后你必须自己停止这个过程,因为 Ctrl + c 不会为你停止:
caddy stop
或者使用 API 的/stop 端点。
您的服务器可以执行零停机时间配置重载/更改。
加载或更改配置的所有 API 端点都是完美的,并且没有停机时间。
但是,在使用命令行时,可能很容易使用 Ctrl + c 来停止服务器,然后再重新启动服务器以获取新的配置。不要这样做: 停止和启动服务器与配置更改是正交的,并将导致停机。
相反,使用 caddy reload 命令来优雅地修改配置:
caddy reload
这实际上只是在引擎盖下使用了 API。它将加载并在必要时将配置文件调整为 JSON,然后在不停机的情况下优雅地替换活动配置。
如果加载新配置时出现任何错误,Caddy 将回滚到上次工作的配置。
{% note info %}
ℹ️ 信息:
从技术上讲,新配置是在停止旧配置之前启动的,因此在很短的时间内,两个配置都在运行!如果新配置失败,它将中止一个错误,而旧配置则根本不会停止
在终端中,切换到站点的根目录并运行:
caddy file-server
如果你得到一个权限错误,这可能意味着你的操作系统不允许你绑定到低端口---- 所以改用高端口:
caddy file-server --listen :2015
然后在浏览器中打开
如果你没有索引文件,但是你想要显示一个文件列表,可以使用 --browse 选项:
caddy file-server --browse
您可以使用另一个文件夹作为站点根目录:
caddy file-server --root ~/mysite
在站点的根目录中,创建一个名为 Caddyfile 的文件,其中包含以下内容:
localhost
file_server
或:
localhost
file_server browse
或
localhost
root * /home/me/mysite
file_server
分别对应以上的几个命令。
本教程假设您有一个运行在 127.0.0.1:9000 上的后端 HTTP 服务。
很直白,直接能看明白:
caddy reverse-proxy --to 127.0.0.1:9000
如果你没有权限绑定到低端口,你可以从高端口代理:
caddy reverse-proxy --from :2016 --to 127.0.0.1:9000
直接上配置:
localhost
reverse_proxy 127.0.0.1:9000
caddy run 运行即可
更改代理的地址很容易:
:2016
reverse_proxy 127.0.0.1:9000
更改 Caddyfile 时,请确保重新加载 Caddy (或停止并重新启动它)。
使用反向代理指令以做很多事情。
本指南将向您展示如何立即使用完全自管理的 HTTPS 启动和运行。
{% note info %}
ℹ️ 信息:
在默认情况下,Caddy 对所有站点使用 HTTPS,只要在配置中提供了主机名。本教程假设您希望通过 HTTPS 获得一个公共受信任的站点(即不是“ localhost”) ,因此我们将使用一个公共域名和外部端口
先决条件:
caddy 和 curl在本教程中,将 example.com 替换为您的实际域名。
设置域名的 A/AAAA 记录指向服务器。您可以通过登录到您的 DNS 提供商和管理您的域名来做到这一点。
在继续之前,用权威 lookup 验证正确的记录。用你的域名替换 example.com,如果你使用的是 IPv6,把 type=A 替换为 type=AAAA:
curl "https://cloudflare-dns.com/dns-query?name=example.com&type=A" \
-H "accept: application/dns-json"
{% note info %}
ℹ️ 提示:
一切的前提是你是在 cloudflare 上买的这个域名。
如果不是的话,步骤会复杂一些。
参见这篇 域名在 DNSPod 上的证书申请方式
还要确保您的服务器在端口80和443上是可以从公共接口访问的。
{% note info %}
ℹ️ 提示:
如果您在您的家庭或其他受限制的网络,您可能需要转发端口或调整防火墙设置
所有我们需要做的是开始用您的域名配置 Caddy。有几种方法可以做到这一点。
这是获取 HTTPS 的最常用方法。
创建一个名为 Caddyfile (无扩展名)的文件,其中第一行是您的域名,例如:
example.com
respond "Hello, privacy!"
然后从同一个目录中运行:
caddy run
您将看到 Caddy 提供一个 TLS 证书,并通过 HTTPS 服务您的站点。这是可能的,因为你的网站在 Caddyfile 中的地址包含一个域名。
file-server 命令caddy file-server --domain example.com
可以了。
reverse-proxy 命令caddy reverse-proxy --from example.com --to localhost:9000
Caddy 吸引我的地方:
???
三人行, 必有我师; 知识共享, 天下为公. 本文由东风微鸣技术博客 EWhisper.cn 编写.
我正在编写一个包含C扩展的gem。通常当我写一个gem时,我会遵循TDD的过程,我会写一个失败的规范,然后处理代码直到它通过,等等......在“ext/mygem/mygem.c”中我的C扩展和在gemspec的“扩展”中配置的有效extconf.rb,如何运行我的规范并仍然加载我的C扩展?当我更改C代码时,我需要采取哪些步骤来重新编译代码?这可能是个愚蠢的问题,但是从我的gem的开发源代码树中输入“bundleinstall”不会构建任何native扩展。当我手动运行rubyext/mygem/extconf.rb时,我确实得到了一个Makefile(在整个项目的根目录中),然后当
我想这样组织C源代码:+/||___+ext||||___+native_extension||||___+lib||||||___(Sourcefilesarekeptinhere-maycontainsub-folders)||||___native_extension.c||___native_extension.h||___extconf.rb||___+lib||||___(Rubysourcecode)||___Rakefile我无法使此设置与mkmf一起正常工作。native_extension/lib中的文件(包含在native_extension.c中)将被完全忽略。
我有一个要在我的Rails3项目中使用的数组扩展方法。它应该住在哪里?我有一个应用程序/类,我最初把它放在(array_extensions.rb)中,在我的config/application.rb中我加载路径:config.autoload_paths+=%W(#{Rails.root}/应用程序/类)。但是,当我转到railsconsole时,未加载扩展。是否有一个预定义的位置可以放置我的Rails3扩展方法?或者,一种预先定义的方式来添加它们?我知道Rails有自己的数组扩展方法。我应该将我的添加到active_support/core_ext/array/conversion
我想编写一个ruby脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"
这个问题有两个部分。在RubyProgrammingLanguage一书中,有一个使用模块扩展字符串对象和类的示例(第8.1.1节)。第一个问题。为什么如果您使用新方法扩展类,然后创建该类的对象/实例,则无法访问该方法?irb(main):001:0>moduleGreeter;defciao;"Ciao!";end;end=>nilirb(main):002:0>String.extend(Greeter)=>Stringirb(main):003:0>String.ciao=>"Ciao!"irb(main):004:0>x="foobar"=>"foobar"irb(main):
假设我们有A、B、C类。Adefself.inherited(sub)#metaprogramminggoeshere#takeclassthathasjustinheritedclassA#andforfooclassesinjectprepare_foo()as#firstlineofmethodthenrunrestofthecodeenddefprepare_foo#=>prepare_foo()neededhere#somecodeendendBprepare_foo()neededhere#somecodeendend如您所见,我正在尝试将foo_prepare()调用注入
在Railcasts上,我注意到一个非常有趣的功能“转到符号”窗口。它像Command-T一样工作,但显示当前文件中可用的类和方法。如何在vim中获取它? 最佳答案 尝试:helptags有各种程序和脚本可以生成标记文件。此外,标记文件格式非常简单,因此很容易将sed(1)或类似的脚本组合在一起,无论您使用何种语言,它们都可以生成标记文件。轻松获取标记文件(除了下载生成器之外)的关键在于格式化样式而不是实际解析语法。 关于ruby-on-rails-Textmate'Gotosymbol
显然在Test::Unit中没有assert_false。您将如何通过扩展断言并添加文件config/initializers/assertions_helper.rb来添加它?这是最好的方法吗?我不想修改test/unit/assertions.rb。顺便说一句,我不认为这是多余的。我使用的是assert_equalfalse,something_to_evaluate。这种方法的问题是很容易意外使用assertfalse,something_to_evaluate。这将始终失败,不会引发错误或警告,并且会在测试中引入错误。 最佳答案
这个问题在这里已经有了答案:Unabletoinstallgem-Failedtobuildgemnativeextension-cannotloadsuchfile--mkmf(LoadError)(17个答案)关闭9年前。嘿,我正在尝试在一台新的ubuntu机器上安装rails。我安装了ruby和rvm,但出现“无法构建gemnative扩展”错误。这是什么意思?$sudogeminstallrails-v3.2.9(没有sudo表示我没有权限)然后它会输出很多“获取”命令,最终会出现这个错误:Buildingnativeextensions.Thiscouldtakeawhi
我在引擎样式插件中有一些代码,其中包含一些模型。在我的应用程序中,我想扩展其中一个模型。通过在初始值设定项中包含一个模块,我已经设法将实例和类方法添加到相关模型中。但是我似乎无法添加关联、回调等。我收到“找不到方法”错误。/libs/qwerty/core.rbmoduleQwertymoduleCoremoduleExtensionsmoduleUser#InstanceMethodsGoHere#ClassMethodsmoduleClassMethodshas_many:hits,:uniq=>true#nomethodfoundbefore_validation_on_crea