在阿姆斯特丹体验 OpenBSD
ewintr.nl
在阿姆斯特丹体验 OpenBSD
2025年3月31日 有时候,初次接触时会感到一丝凉意。
$ nano
ksh: nano: not found
$ vim
ksh: vim: not found
几年前,我玩过一台古老的笔记本电脑,一台 Toshiba 300 CDT。 我记不太清具体配置了,但我记得它的内存只有 32 MB。 网络上的资料对此有所出入,也许存在不同的型号,但可以肯定的是,我们讨论的是兆字节,而不是千兆字节。 我当时想知道,是否有可能让这样一台古老的设备安全地连接到互联网,并用它来做一些“真正的事情”。 即使用途有限,它是否还能以某种方式发挥作用? 它发布于 1998 年。 在那个年代,人们使用待办事项清单、文字处理器,并且上网浏览网站。 为什么现在不行呢?
我首先研究了几种小型的 Linux 发行版,例如 Damn Small Linux 和 Puppy Linux。 不幸的是,这些对这台老机器来说负担太重了。 我开始尝试 Linux From Scratch,心想这应该是最基础、最精简的 Linux 了。 但这变成了一个独立的项目,我被其他类型的操作系统分散了注意力。 我尝试了 Haiku, Minix 等等很多系统。 这些都只是我现在能想起来的。 自然,我也接触了 the BSDs,但都无济于事。 没有什么能在这台古老的笔记本电脑上运行,内存限制是主要原因。
然而,OpenBSD 除外。 安装并看到它启动的那一刻,我感到很困惑。 经历了这么多次失败之后,这个系统竟然... 成功了? 真有意思。 我只是想要一个可以玩的东西,但因为我要将它连接到互联网,所以我想要一些安全且受支持的东西。 结果,唯一能用的操作系统竟然是人们口中最安全的操作系统。 这可能说明了简单和极简主义的优点。
但我并没有用它很长时间。 由于 一个安全特性,它需要 15 分钟才能启动。 我本可以禁用它,但学习 OpenBSD 变成了一项挑战。 对于 Linux 用户来说,它看起来非常熟悉。 但是,它的不同之处足以让我不断碰壁,一无所获。
$ pkg_add helix
pkg_add: pkg_add must be run as root
$ doas pkg_add helix
doas: doas is not enabled, /etc/doas.conf: No such file or directory
学习可能很困难。 学习是将新的事物纳入,并在你已有的世界模型中为它找到位置,将新事物与你已知的事物联系起来。 如果它真的是全新的,那可能会很困难。 在你的心理模型中,没有明显的位置来放置这个新事物。
你可能认为自己思想开放,能够灵活地学习新事物,但通常这只意味着你准备好接受各种大小的方形钉子。 如果你遇到一个圆形的钉子会怎么样? 可能需要经过几次失败的尝试,圆形的概念才会出现在你的脑海中。
$ doas rcctl restart relayd
(failed)
有时候你就是那个圆形的钉子。 拿 KYC 这个术语来说。 它代表 Know Your Customer(了解你的客户),这意味着组织必须采取措施来确保你,一个潜在的客户,不是一个骗子。 法律要求他们了解你是谁,以便他们能够确定是否可以与你建立业务关系。
对我来说,了解某人仅仅意味着和他们交谈。 最好是在喝啤酒或咖啡的时候。 对于许多公司来说,现在“了解你”意味着让你盯着你的网络摄像头,以便 AI 可以好好看看你。 或者提交你的护照扫描件,他们承诺会安全处理,因为你的隐私对他们来说非常非常重要。 不知何故,我从不相信他们说的。
当我开始寻找一种新的方式来托管这个网站时,因为我已经厌倦了在 之前的托管商 那里玩耍,现在想要一些简单而稳定的东西,我遇到了许多想以最尴尬的方式了解我的公司。 现在,购买欧洲产品很流行,但欧洲公司也一样。 没有灵魂的网站,上面有表格需要填写私密信息。 他们真的,真的很重视我的隐... 呵呵。
但后来我偶然发现了 OpenBSD.Amsterdam。 这是本地提供的 OpenBSD VM。 该组织承诺将他们收取的用于赞助 OpenBSD 开发的部分资金用于 OpenBSD 的开发,这很酷。 它给人的感觉是不废话且坚如磐石,就像操作系统本身一样。 我从未见过它背后的人,但我敢打赌他们喜欢咖啡或啤酒。
$ doas relayd -n
/etc/relayd.conf:37: cannot load keypair ewintr.nl for relay www4tls
/etc/relayd.conf:45: cannot load keypair ewintr.nl for relay www6tls
no actions, nothing to do
OpenBSD,它又出现了。 记住我之前使用旧笔记本电脑的经历,我想我需要再试一次。 毕竟,除了安全性之外,爱好者们总是对文档和专注于创建简单而连贯的系统赞不绝口。 也许我太早放弃了。 当然,我应该能够理解它吧? 我决定再试一次。
这个过程比预期的要困难。 最后我成功了。 你现在正在阅读的网页是由 OpenBSD 的 httpd
提供的。 打开你浏览器中的开发者工具进行验证。 但实现这一目标的过程比我预期的要长。 奇怪的是,回想起来,我无法告诉你为什么它花费了更多的精力,只能用适应圆形钉子的比喻来解释。
我会浏览文档来查找要运行的命令或要输入的配置,但得到的却是错误消息。 然后是一段疯狂搜索和反复试验的时期。 直到我最终做对了。 一旦它起作用了,我重新阅读了原始文档,发现答案一直都在那里。 清晰明了。 然而,不知何故,第一次它并没有被我注意到。 这种情况发生了好几次。
$ doas rcctl restart httpd
httpd(ok)
httpd(ok)
$ doas rcctl restart relayd
relayd(ok)
relayd(ok)
最初,我计划将这篇文章写成一个简单的菜谱。 只要按照这些步骤操作,你就可以立即运行你的网站。 但现在我知道它不会那样起作用。 至少不是对所有人。 相反,我将只给你我使用的资源列表和第一个有效的配置文件版本。 你需要添加的成分是一些时间和精力。
我认为这是值得的。 一切都感觉坚如磐石。 以最好的方式实现简单而枯燥的技术。 一种你可以依赖的东西。
让一切都沉淀一段时间。 给它一些时间。 一旦你习惯了,水就变得很舒服了。 美丽的,圆形的 pufferfish 在那里游泳。 它们很有趣。
资源
所有这些页面都讨论了相同的几个主题,但视角略有不同。 排名不分先后:
- httpd.conf(5) - man.openbsd.org
- relayd.conf(5) - man.openbsd.org
- Self-hosting a static site with OpenBSD, httpd, and relayd - citizen428.net
- OpenBSD httpd MIME types and feeds - lars-christian.com
- relayd(8) - man.openbsd.org
- Relayd: Web caching for httpd - doc.huc.fr.eu.org
- HTTP Caching - Fresh and stale based on age - developer.mozilla.org
- Relayd with SNI and TLS keypairs - findelabs.com
- Using OpenBSD relayd(8) as an Application Layer Gateway - www.tumfatig.net
- OpenBSD acme-client For Let's Encrypt Certificates - obsd.solutions
- acme-client(1) - man.openbsd.org
- httpd(8) - man.openbsd.org
- httpd/relayd behind a reverse proxy in OpenBSD - grosu.nl
- How to log client IP in httpd behind relayd - www.bsdhowto.ch
- OpenBSD relayd/httpd web server example - www.adyxax.org
- patterns(7) - man.openbsd.org
- relayd - how to set cache-control header by extension or content-type - old.reddit.com
- Reduce httpd web server bandwidth usage by serving compressed files - dataswamp.org
配置文件
这是我最终得到的配置。 记住,我是一个新手。 肯定有更好的方法可以做到这一点:
/etc/httpd.conf
types {
include "/usr/share/misc/mime.types"
}
# https 变体, 通过 relayd
server "ewintr.nl" {
listen on 127.0.0.1 port 8080
root "/htdocs/ewintr.nl" # 在文件系统中,这是 /var/www/htdocs/ewintr.nl,因为 httpd 在 jail 中运行
log style forwarded
gzip-static
# RSS 和 linklog 重定向
location match "/linklog/%d*/links%-([%d%-]*)" {
block return 302 "https://ewintr.nl/linklog/#links-%1"
}
location "/feed/" {
block return 302 "https://ewintr.nl/atom.xml"
}
# 较旧的重定向
location "/quick-go-test-clycle-with-reflex" {
block return 301 "https://ewintr.nl/posts/2020/quick-go-test-cycle-with-reflex/"
}
# (为了简洁,跳过了另外 30 多个)
}
# http 变体, 直接
server "ewintr.nl" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location "/*" {
block return 301 "https://ewintr.nl$REQUEST_URI"
}
}
# https 变体, 通过 relayd
sserver "vrijkorteverhalen.nl" {
listen on 127.0.0.1 port 8080
root "/htdocs/vrijkorteverhalen.nl"
log style forwarded
gzip-static
}
# http 变体, 直接
server "vrijkorteverhalen.nl" {
listen on * port 80
location "/.well-known/acme-challenge/*" {
root "/acme"
request strip 2
}
location "/*" {
block return 301 "https://vrijkorteverhalen.nl$REQUEST_URI"
}
}
/etc/relayd.conf
ext_addr4="46.23.93.208"
ext_addr6="2a03:6000:93f4:605::208"
local="127.0.0.1"
table <webhosts> { $local }
http protocol https {
match request path "/*.woff2" tag "CACHEYEAR"
match response tagged "CACHEYEAR" header set "Cache-Control" value "public, max-age=31536000"
match request path "/*.(css|png|jpg|jpeg)" tag "CACHEMONTH"
match response tagged "CACHEMONTH" header set "Cache-Control" value "public, max-age=2628000"
match request header set "X-Forwarded-For" value "$REMOTE_ADDR"
match request header set "X-Forwarded-Port" value "$REMOTE_PORT"
tls keypair "ewintr.nl"
tls keypair "vrijkorteverhalen.nl"
}
relay www4tls {
listen on $ext_addr4 port 443 tls
protocol https
forward to <webhosts> port 8080
}
relay www6tls {
listen on $ext_addr6 port 443 tls
protocol https
forward to <webhosts> port 8080
}
/etc/acme-client.conf
# 从 /etc/examples/acme-client.conf 复制示例并修改 domain 部分:
domain ewintr.nl {
#alternative names { secure.example.com }
domain key "/etc/ssl/private/ewintr.nl.key"
domain full chain certificate "/etc/ssl/ewintr.nl.fullchain.pem"
# 使用 staging 服务器进行测试,以避免过度的速率限制。
#sign with letsencrypt-staging
sign with letsencrypt
}
domain vrijkorteverhalen.nl {
#alternative names { secure.example.com }
domain key "/etc/ssl/private/vrijkorteverhalen.nl.key"
domain full chain certificate "/etc/ssl/vrijkorteverhalen.nl.fullchain.pem"
# 使用 staging 服务器进行测试,以避免过度的速率限制。
#sign with letsencrypt-staging
sign with letsencrypt
}
请注意,这些不是 relayd
可以自动发现的文件路径。 我需要添加这些符号链接:
# 在 /etc/ssl 中
ewintr.nl.crt -> ewintr.nl.fullchain.pem
vrijkorteverhalen.nl.crt -> vrijkorteverhalen.nl.fullchain.pem
Makefile
在网站项目中:
build:
zola build
gzip:
find public/ -type f \( -iname "*.html" -o -iname "*.txt" -o -iname "*.css" -o -iname "*.xml" \) -exec gzip -f -9k {} +
stage-drafts:
zola serve --drafts
stage:
zola serve
deploy: build gzip
rsync -a public/ ewintr.nl:/var/www/htdocs/ewintr.nl/
通过 RSS 订阅此站点