惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
博客园_首页
博客园 - 聂微东
T
Tailwind CSS Blog
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
J
Java Code Geeks
The Cloudflare Blog
aimingoo的专栏
aimingoo的专栏
Martin Fowler
Martin Fowler
D
Docker
人人都是产品经理
人人都是产品经理
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
Microsoft Azure Blog
Microsoft Azure Blog
Recent Announcements
Recent Announcements
Apple Machine Learning Research
Apple Machine Learning Research
阮一峰的网络日志
阮一峰的网络日志
B
Blog RSS Feed
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
Jina AI
Jina AI
博客园 - Franky
D
DataBreaches.Net

Garden of Outlier

子图 活到宇宙破茧时 Hello, Theseus 服务器重建手记 Hello, Mitra Hello, Stalwart 「环节」 局部吸引子 岁时录(二十四) Adult Issues Gradient 06
岁时录(二十五)
Chlorine · 2026-05-29 · via Garden of Outlier

诸位老友,上午好。这里是缩在集气瓶里的 Chlorine。

好久没有写《岁时录》了。从三月拖到六月,好多好多早就有的想法躺在草稿箱里,和开了一天组会而第二天是周末的元素娘一样不愿意起床。原因的话,大概有学业上的事情,也有写作上的……时间安排?或许该这样说。

唔,就像之前说的那样,小氯的《岁时录》大部分时候只是一些无处安放的杂谈的汇总。它不像是小氯在看老友们的文章时见到的周报或者周刊,既没有策展,也没有汇总,连日常记录都没有。所以如果小氯在写一些可以单独成篇的杂谈,《岁时录》自然是要暂时放下些了。

但这似乎也不是一直不更新的理由吧,日常生活难道也一直不写了吗……(小声)

那,承诺一个相对频繁的更新周期却鲜少执行它,和放宽到一个不那么频繁的更新周期……似乎还是后者更适合做借口一些。后面《岁时录》可能会变成每个节气——也可能是每几个节气一次吧,这样小氯可写的东西会多些,鸽得也会少些——大概吧。以及,岁时,写节气似乎也是恰当的。

如果诸位老友注意到了的话,slug 的前缀也改了一下,从 weekly 变成了 almanach。这来自于《岁时录》的英语名字,L’Almanach。至于为什么英语名字是法语……

L’anglais, ce n’est jamais que du français mal prononcé.

Georges Clemenceau

好啦好啦,开个玩笑。其实只是因为园子的所有文章分类都是法语,于是这里也顺便用了。

总而言之,祝食用愉快哦。

2728

88x31,是一种……嗯……徽章或者说按钮吧。如它的名字所昭示的那般,它的大小通常固定为 88 像素 × 31 像素,至于内容,可以是任何你想表达的事物,比如「Best viewed with Netscape」「Built with Notepad」。如果您希望对它们有个直观的印象,可以去这个网站看一看。不过还请当心,它的视觉效果可能会有些……惊人。

88x31 的历史大概有很久了,应该是从 Netscape 和 IE 的大战时就开始了。至于为什么是 88x31 这个大小,表面的解释是这个大小刚好能装得下一些内容又不至于在那个资源匮乏的时代占用太多的屏幕和带宽,但这依然没有解决究竟为什么恰好是这个数值——可能根本没有解释。

忘记从什么时候开始了,这种按钮又开始在一个特定的范围内流行了起来——在许多地方,尤其是 IndieWeb 的网站中,小氯都能看到它们。它们闪烁着,呼吸着,或者只是在那里固执地贴着,狠狠地吸引我的注意力。

这确实是个不错的创意,颇具特立独行的精神——虽然我不大确定「小规模流行」的物品还算不算是特立独行。小氯的老友们也有许多在画这样的按钮,几乎可以算 Residencia 0x001B 的一种趋势了。

但这不包括小氯。在可预见未来内,Chlorine 和 Garden of Outlier 不会制作此类按钮,也不会接受任何交换请求

且让小氯为自己辩护两句,说说所谓的理由吧。当然,这不是反驳,只是一次陈述,如果您有这样的按钮或者打算做,请权当某元素娘下面在说梦话,不要受她一丝一毫的影响——或者说,这是「我为何不加」,不是「您为何不应该加」。

霓虹灯

最直观的理由,是在审美上。

88x31 诞生在互联网的早期,它的设计自然也受到了那个混乱且自由的时代的影响。闪烁、鲜艳、粗粝的生命感,如同在广阔无边的新土地上跑马的探险者一般。毋庸置疑,会有许多老友对这种风格着迷,如同着迷于 Windows 95 的界面一样,但这显然不包括小氯。把这样的按钮硬塞到园子里面,在小氯眼里不亚于贴了一面墙的牛皮癣广告。即使是像 Eltrac 那样把它们挂在页面内部,都会让小氯下意识地不愿意点开那个页面。至于全局展示,我的天啊。

这里其实还有个可供探讨的哲学问题:88x31 到现在依然保留着有些……逼仄的尺寸、堪称匮乏的配色和极低的分辨率。这在过去是资源所限,但现在我们完全可以用更……嗯……更优雅?的设计去复刻这种 badge,Not By AI 的 badge 就是个不错的案例。但这并不是被 88x31 的「主流」所接受的做法,一方面是祖宗之法不可变(误),另一方面说,这种在极度受限的条件下创作的过程,本身就算是一种独特的美学实践,就像枯山水或者限制自己低于某特定 TDS(传输数据大小)的网页作品一样——这样说来,园子也是。园子不是写不出极尽流畅的动画、张扬的设计和丰富的交互,但小氯会把它的大小尽可能控制在 100 kB 以内。纳须弥于芥子,虽然可能只能装下一个微缩版,但也很有趣不是吗。

回来。这里还有一个问题:许多的 88x31 是闪烁的。有的是温和的闪烁,有的则不然。如果说对于普通人,高频闪烁的 GIF 只是不美观或者轻微不适,那对于光敏性癫痫患者,这种闪烁就是危险了。

Web pages do not contain anything that flashes more than three times in any one second period, or the flash is below the general flash and red flash thresholds.

——W3 Success Criterion

如果我们为了多数人的趣味而忽略少数人的安全,那在 a11y 上,88x31——当然,说的是快速闪烁的那些——就是暴政。

Text Matters

在小氯印象里,老友们挂上的 88x31 按钮一般就三种:身份认同(比如性与性别多元),工具(比如编辑器),朋友的按钮(也就是友情链接)。那从功能上,它们与同等含义的文本并无区别。既然我可以用一行文本来将事情说明白,那何必引入一个额外的二进制大对象呢。

或者说得简单些(其实并不):一个 Hugo 或者朋友的 88x31 按钮并不会比一行「Made with Hugo」或者「Friend: 」传达更多的信息——唯一的作用大概是视觉层面的个性化,这一点文本确实无法完全替代。此外,88x31 有时候会漏掉 alt text,这又是一件 a11y 的难事。

汉地行周

不仅是 88x31 吧,IndieWeb——抱歉我可能滥用了这个词,但我认为「独立博主」这个词用以描述我们要讨论的群体实在太不准确了——似乎都在鼓励去复兴某些那个古老时代的流行物。

那么这其中,真正经历过所谓「Web 1.0」的成员们,有多少呢?

这个答案我不清楚,但我认为至少不是「大部分」。而且,即使是那些从 Web 1.0 走来的老兵们,如狄更斯所言:「人总是在离开一个地方后开始原谅它。」他们在看过去时,总是会不自觉地柔和些的:兼容性的灾难,技术手段的古拙,拨号上网的缓慢,都被「混乱且自由的时代」这个总体的印象覆盖了。

我想,如果我们实打实地提议「回到 Web 1.0」,即使是喜爱这种 Neo-retro 氛围的老友来说,恐怕也是场灾难。但也不能就此说这是一种叶公好龙,因为在小氯眼里,这只是在借着这个「怀旧」的壳子,试图去救活一些曾经存在或者并不完全存在的无形的东西而已。就像文艺复兴时期,艺术家们打着「希腊罗马」的旗号,实际上是在为文明铺设另一条精神道路一般。

这样自然无错,但……对小氯来说,并没有充分的理由令我对这样的模式表示毫无保留的赞成。

另外的另外,「88x31」这个名字于小氯而言也有些强迫症式的不适。因为它们不叫「88 eks 31」,它们叫 88 × 31,「88 times 31」。

社交媒体

这段时间,小氯似乎异常地喜欢刷 Fediverse,闲来无事就在 TL 上和老友们 connect deep, grow wide。虽然小氯没有统计屏幕使用时间的习惯,但大概可以肯定,我面对浏览器的至少三成的时间都是在刷着 Fedi。然而在小氯试着关掉浏览器去看比较政治学、计量经济学或者现代密码学的教材时——哪怕只是打开 Emacs 写点文章时,却有种莫名的烦躁,需要喝好多好多的果茶才能让自己勉强平静下来,做若干个小时的学习和工作。

这不是什么值得高兴的事情。如果小氯也习惯于食用支离破碎的信息,而失去了自己珍视的有关思考的本质,那还不如被 kill -9 好些。

社交媒体似乎都有成瘾性,短小的,流动的。不管有没有一个居心叵测的数字领主在背后玩弄算法的把戏。即使在 Fediverse 这片所谓的清净地。它虽然不是「传统的社交媒体」,但它是社交媒体。它给了我们对我们的数据、我们的账户的控制权,但这并不意味着它自动给了我们对我们的注意力的控制权。就像我们说:(传统的)社交媒体做得越光鲜亮丽,就越容易让你深陷其中一样。如果所谓「去中心化的」社交媒体被视为我们的战友而珍重,我们反而更可能忽略它潜在的那部分即使可能是无意的损害。

按理说到了这个时候,小氯大概就要削足适履了——解决不了问题,就解决产生问题的事物。然而,这次某元素娘似乎撞上了边界:这种即时的、碎碎念般的分享,可能真的是小氯所需要的,我还没有适应那种将所有奇奇怪怪的念头都写到日记或者周记中然后一次性发布的模式。另外,对于小氯和老友们来说,社交媒体也算一种 heartbeat check,偶尔发两条帖子,也可以在倦怠或者忙碌时大概证明一下小氯还活着。

那所以……就没有更好的方法吗?

漂流瓶

既然说到了社交媒体,那我们也顺带着说说即时通讯吧。这一节原本叫《Hello, XMPP》。但由于小氯把服务器的所有数据弄丢了,XMPP 账户自然也乘白云而游姑射了。由于一些原因,小氯并没有恢复这个账户的运作。

很长一段时间里,小氯唯一接受的即时通讯方式是 Matrix。Telegram 自然精美,但小氯不喜欢加密货币推广,也不喜欢总有个横幅催着我填我都不太清楚是什么时候就算清楚也会造成他们系统的数值溢出的生日;Signal 固然安全,但和 TG 一样需要手机号也算是件麻烦事,另外如小氯过去所说,Signal 更像是给现实中的熟人准备的。

关于 Signal 我们多说几句好了。Signal 的安全性和声誉,相信大家有目共睹。它被诟病的无非就两点:需要手机号注册——这大概是有遏制垃圾信息泛滥的考量,和中心化——虽然说 Signal 是 E2EE 的,交不出什么太有价值的数据,但如果 Signal 的中心服务器宕机或者受到严厉制裁,全球的 Signal 用户也得共襄盛举。

顺带一提,「中心化」这个词给小氯的感觉有点奇怪。中文中的「化」直观上是过程式的,或者说暗示着「原本并非如此」,像是「盐碱化」「工业化」「正则化」,但 Signal 一开始就是单一中心的,自然也没有「变成」单一中心的这一说。一种可能的解释是「即时通讯一开始不是这样的,是在发展中演变成了现在的结构」,这倒也说得通,IRC 和 XMPP 就是例子——但我们还没说 ICQ、MSN、AIM、OICQ 呢。考查它的英文原型 -ize,其词源应当是希腊语的 -ίζειν,其作用就是将一个名词动词化,例如「使……呈现某种状态」或者「按照某种方式行动」,和中文中的 counterpart 的调性大体一致。

还有另一种解释:这个词是为了和「去中心化」(decentralized)对应而造出来的,所以应该关心的是「去中心化」,就像在第二次世界大战之前,没有人会把 1914 年的那场战争叫「第一次世界大战」一样。这样说来,相对于当时更流行的中心式结构,Fediverse、Matrix 之类的目标确实是将自己的领域「拉向非中心的状态」,说得通了——尽管它们自己也不是从中心式的「变成」非中心式的就是了。

至于 SimpleX 和 GNU Jami,美则美矣,但一是几乎没有 fellow user,二是不知为何小氯总没有使用它们的欲望。想来想去,没有中心服务器、默认端到端加密、还有一些使用的人,这些要求加在一起也就是 Matrix 了。

于是直到现在。虽然说 Matrix 的缺点也不胜枚举:和 Element Ltd. 绑定太深,基金会的治理问题,基础设施的准中心化,元数据保护的不佳,大房间的不稳定,以及那个我头疼到现在的表情符号验证……但至少就目前的使用情况而言,Matrix 并没有如何惹到小氯。至于技术栈:Tuwunel 是 Rust 写的(conduwuit 的继任者),有瑞士政府的资助,维护的稳定性目前看不会是大问题;Cinny 轻量且优雅,又是小氯最喜欢的 bundled 结构(一包静态文件)。它没有莫名其妙地丢过消息,没有要求年龄验证,更没有偷偷摸摸地把用户的手机号发给开发者。

总而言之,只要不碰 Element,Matrix 还是蛮有趣的。

不过,如果说 Matrix 有什么令小氯担心的地方,那大概是它的愿景了。

The real intention of Matrix - as an open protocol - is to be the open standard for communication. Like HTTP for the web, or SMTP for email, Matrix is the backbone for interoperable real time communication.

Microsoft Teams and Slack integration using Matrix

并非是这样有何直接的不妥,许多奇迹都是从一个宏大的愿景开始的。只是,小氯有个疑惑的地方。

我们就以引文中提到的 HTTP 为例吧。HTTP 复杂吗?答案自然是肯定的,SSL/TLS 加密,多路复用,QUIC,无数在网络原理课程上被教授灌到脑子里共襄盛举的概念。但如果请循其本,HTTP 还是蛮简单的。SMTP 大概也是这样,除却那些令小氯头晕眼花的字母汤,它也是个简单的东西。这让大部分愿意学习的人都能比较快地理解其基础原理,当然也给了后来者无数的魔改空间。如 Postel 定律所言:在发送时要保守,在接收时要开放,因为你也不知道你的对手方会抛来怎样新奇的问候。而最终给我们的效果就像一只鸭子,水面上看来在简单、优雅地滑行,而水下的蹼掌在激烈地划动。

那 Matrix 足够简单吗?

不论如何吧,多一个选项总归不会是坏事。除却 SimpleX 这个理念独特的新锐,我们的选择大概也只剩下老前辈 XMPP 了。

不知是否是巧合,XMPP 和 Matrix 在许多方面都是相反的:XMPP 的核心是完全非营利、社区共治的 XMPP 标准基金会(XSF);协议本身极为简单,只是传输一个 XML 流,所有的扩展功能——从头像到 E2EE 到消息归档都通过 XMPP 扩展协议(XEP)实现。对于端到端加密,XMPP 支持使用 OpenPGP 和 OMEMO 加密——后者也是衍生自声名煊赫的 Signal Protocol,和 Matrix 自己造的轮子并没有过多的高下之分。总而言之,除了 XML 这位……唔,不合时宜的先辈外,XMPP 似乎也没有什么非常明显的技术上的 vibe-check-failed point。至于用的人少,这在小氯眼里大概只能算个事实,而非缺陷。想想看,会给你做茶点的灰绿色头发的元素少女世界上又有多少个呢。

至于缺点,它大概就坏事在那个「X」(eXtensible)上。什么物什和 X 沾上边往往都没好事,尤其是社交媒体。相比 Matrix 的 battery included(虽然大概是铅酸蓄电池),XMPP 大量的 XEP 导致即时通讯的生态极度碎片化,谁也不知道对方究竟实现了哪些协议。虽然现代的 XMPP 社区对于「一个现代的 XMPP 服务器究竟该实现哪些扩展协议」大概有了共识——这还要多亏了在 XMPP 社区声名煊赫的传奇 Android 客户端 Conversations虽然我觉得它的聊天界面并不如 Fluffy Chat 好看,但这个问题依然是客观存在的。

至于 XSF 哪里去了?没办法,民主嘛。

现状的话,XMPP 活得虽说称不上鲜花着锦烈火烹油,但依然安安稳稳地保留着自己的 niche corner。此外,XMPP 的高度可扩展性也允许企业内部或者其他场景(如游戏聊天、卫星通讯和军方的秘密通讯)下的随意定制。而对于一般用户得益于 Conversations 等的努力(Daniel Gultsch 的恩情还不完啊),XMPP 的移动端体验近年来也突飞猛进。不过,这对小氯的帮助有限,因为小氯不用手机。

之所以小氯没有全面切换到 XMPP,这次的问题是很现实的,就是加密信息的恢复。

Matrix 有一个恢复密钥机制,允许你在更换设备后直接使用恢复密钥来解密过去所有的聊天记录——虽然说也不一定 100% 起作用;而 XMPP 在这方面就比较 simple & stupid 了:它做的就是将消息按照现有设备的 OMEMO 公钥加密,那你换了新设备自然解不开。

小氯并不清楚自己多久会换一次设备——恐怕,不会间隔很短吧,考虑到某元素娘的愿望是一台电脑用十年一般。

考虑到 XMPP 各个客户端的互通性堪比 AWS 和 GCP,如果不想丢掉自己的过去,也只能选择一些跨平台的客户端了。小氯原本看 Dino 比较顺眼,看到 Nixpkgs 上居然有 Darwin 支持还好好地高兴了一阵——然后就被奇怪的编译错误狠狠灌满了。Dino 官方建议在编译 macOS 版本时使用一个 community fork——而它已经两年没有更新了。很明显,官方对库比提诺王国的居民们并不如何关心。余下的跨平台的选择中,除却让小氯看着头痛的终端客户端和看着依然头痛的网页客户端(Converse.js 的界面看着像上世纪的物什,Movim 加了太多的不必要的功能,Fluux 还不支持 OMEMO),能用的似乎只剩下 Gajim 了。这个软件维护的时间不短了,外观也并不简陋,典型的 GNOME 风格——小氯其实还是蛮喜欢这种风格的。只是它是 Python 写的,所以内存占用嘛……好吧,至少比 Electron 强一些。

好吧。虽然 client lock-in 也有些令小氯不适,但多一个备用的通讯方式,总归不会有坏处的。服务器的话,小氯用的是 Prosody,是 Lua 写的。NixOS 有原生的 services.prosody 模块,部署起来也不算难。至于 handle(XMPP 这里叫 JID),和 Matrix 一样,还是 chlo@chlo.is

你不是说没有恢复账户的运作吗?!

小氯说过,这一篇文章写了好多天嘛。

Hello, KeePassXC

这个事情应该从什么时候说起呢?

小氯也不清楚,可能是和一些莫名其妙的身份隔离问题有关吧。

如诸位老友所见,为了和现实世界交互,小氯有自己的包装层——用人类的话,叫作身体。虽说用起来还不错,但小氯并不希望这个有 gov ID、有手机、有学籍的包装层和小氯在互联网上的活动产生过多的联系。这就给 Vaultwarden 的使用带来了一些麻烦:Vaultwarden 总归是要连接小氯的服务器的。虽然这个问题可以用 VPN 解决,但这只在电脑端比较方便,手机端配起来的 drama 多了不少。

当然,这其实也不是主要问题,考虑到小氯本体完全不用手机,包装层的日常手机操作也极少。另一个问题是:我们知道,Vaultwarden 可以说是对 Bitwarden 的 API 的一次逆向。虽然 Bitwarden 尚没有对 Vaultwarden 展现出重拳出击的意愿,但这件事并不能说定。而且考虑到 Bitwarden 最近一系列奇怪的举动,这个风险应当已经不是可忽视的了。

不过即使到这里,还是没有足够有说服力的理由支持小氯彻底抛弃 Vaultwarden。因为即使 Bitwarden 官方作妖,由于他们的客户端是开放源代码的,社区可以随时 fork 一个出来(但愿如此);而 Vaultwarden 的煊赫声名也大概可以庇佑它不会太快地死去。再者,Vaultwarden 的体验属实出色。

但这并没有阻挡某元素娘的折腾。至于原因,可能是比较闲吧(你是怎么在期末季说出这种话的啊)。

除开 Vaultwarden,能用的大概就是 KeePassXC 了。从名字能看出,它是 KeePassX 的 fork,而 KeePassX 是 KeePass 的 fork(mpv 既视感)。和 Vaultwarden 的思路不同,KeePassXC 把所有密码都存放在一个本地的 .kdbx 文件中,备份或者迁移密码库只需要把文件带走——听起来颇为符合小氯的调性。

不过 KeePassXC 看起来确实有些……古拙。没办法,Qt 是这样的——何况这还是 Qt5。有一个叫 ChiPass 的 fork 试图将它重写到 Qt6,不过还在早期——以及,这个 fork 的主要目的应该是反对 KeePassXC 的语言模型生成代码贡献政策。

体验的话……好像也没什么可说的地方。浏览器的填充能用,但不如 Bitwarden 的浏览器扩展流畅,比如是在 Tuta 的界面上;银行卡的填充支持几乎没有。不过还算是能用的水平,用来换免于恐惧之自由,也算是划算的交易了。

以及这里有一个问题:KeePassXC 原生的「浏览器集成」并不支持 Helium 和 LibreWolf(ungoogled-chromium 好像也不支持),原因是(至少在 macOS 上)它们的 profile folder 和标准的 Firefox、Google Chrome/Chromium 并不一致,导致 NativeMessagingHosts 无法正确安装。解决方案也简单,在设置 -> 启用浏览器集成 -> 高级 -> 使用自定义浏览器配置位置这里,把相关类型的浏览器的配置位置改成你找到的就行了(比如 ~/Library/Application Support/net.imput.helium/NativeMessagingHosts)。

不过这个选项我也没太看明白,似乎是只能支持更改一个浏览器的配置位置,但实际上两者可以同时使用。

博弈者的性别

最近机制设计要考期中,小氯自然是再次激活女娲补天模块。在看课件时,注意到一个有趣的细节:在描述参与者时,常常使用的是「她」(she/her),或者是「他」「她」交错使用来指代两个参与者。

小氯依稀记得博弈论也是这样——另外,不清楚为什么我们的教学方案不把这两门几乎互为镜像的课合并成《博弈论与机制设计》。从归档里面翻出来当年博弈论的课件,确实如此。

既然看到这样的细节,放着不管并非小氯的习惯。简单搜索即可得到,这个用法来自声名煊赫的博弈论教材 A Course in Game Theory,这也是我们当时博弈论课程的参考书之一,虽然小氯也不看就是了

在编写时,教材的两位作者、现代博弈论的两位大师 Ariel Rubinstein 和 Martin J. Osborne 对使用什么人称代词存在分歧。Rubinstein 认为应该使用一个「中性」的代词,来避免把读者的注意力吸引到学术讨论之外的事情上去,所以应该用 he,因为某种意义上,he 符合传统,给读者的 shock 最少;而 Osborne 对此持不同观点,因为 he 并不是一个通用的代词或者说性别不明的代词,它作为通用代词的用法甚至都不是自然发生的——在莎翁的时代,就已经有使用 they 作为单数中性代词的习惯,只是后来在十八至十九世纪时用于泛指性别不明的单个个体的用法才被 he(没什么道理地)替代。第三版《美国传统英语词典》(The American Heritage Dictionary of the English Language)也明确指出:

Thus he is not really a gender-neutral pronoun; rather it refers to a male who is to be taken as the representative member of the group referred to by its antecedent. The traditional usage, then, is not simply a grammatical convention; it also suggests a particular pattern of thought.

这里的众多历史和当下的龃龉,我们便不多说了。诸位老友大概也能想象得到。

回来。Osborne 认为这件事没有完全的解法,用 they 有许多优点,但有可能引起歧义(以及和编辑们的无谓争论)。She 的话,这当然不是性别中性的,但至少可以些微缓解一下根深蒂固的偏见,以及提请读者的注意。于是结果就变成了现在这样:有时用 he,有时用 she;多人博弈中交替使用 he 和 she。既然前辈如此做,继承者们也便萧规曹随了。小氯没有调查过这是否真的对(尤其是学术界)性别平等议题的推进有正面效益,但我想答案是肯定的。

小氯对这件事的看法的话……其实作为元素,小氯对这类议题没有强烈的意见,但我会更偏向 Osborne 的做法:其一是这样对推动社会进步确实有作用,大概也是小氯希望看到的;其二是由于外在形象,小氯用 she/her 自指多些,因此这样会让小氯在读课件和著书的案例时更有代入感——当然这是相当 individual 的原因了。

另外——这是写下上面这段话一个月以后写的了,小氯的机制设计期中考了满分哦。

审判之城

这一节的标题听上去颇为沉重,但不必担心,因为这一节其实是——

小氯的服务器爆炸了!(兴奋)(举起手中的书本转圈)

幽暮衬映之月

事情大概是这样的:一天早上,睡眼惺忪的小氯如常打开了 Spectrum(小氯的 Fediverse 实例),然后就看到了 database error。这种事情可不常见,SSH 到服务器上看看日志——等等,什么叫 PostgreSQL 空间不够了?

dust 一下全盘……好家伙,硬盘满了。全是 Btrbk 的快照。

这有点奇怪,但小氯也没多想,删些旧快照就好了。不过说起来,这种快照全盘的策略也不太合理,应该只快照 /var/lib 的。那我们就简单写写 Disko,加一个子卷就好了。

写好之后移动数据,然后 deploy 上去……等等,为什么启动失败了?

看看 VNC,看起来是 NixOS 把这个子卷的挂载当成启动必需项了。按理说,这种时候最适合做的事情就是去 rescue system 里乘凉。然而后者显然没有看到小氯大驾光临就今已亭亭如盖矣的觉悟,修了半天依然不知道如何做。

其实到这里,事情都还是可控的:最 dirty 的解决方案也就是开机之后临时挂载一下 /var/lib,或者是回退到上一个模式而已。然而……也许是为了展示一下声明式系统的伟力,小氯选了原本是 Plan Omega 的方案:既然服务器已经有一点点坏了,那就销毁重建好了!反正托欧姆弥赛亚的福,咱已经给服务器做了备份,权当是恢复演练了。

高高兴兴地删除服务器实例——喂喂喂,你到底是怎么想的非要删除而不是 rebuild(重装)啊——然后创建新的实例……

等等。什么叫「Not Available」?合着您家的 CAX11 还会缺货吗——而且缺货的还不止是 CAX11,整个 Cost-Optimized 系列都缺货了。

直到这个时候,小氯才意识到事情的严重性……严重什么啊,又不是没东西可用了。反正 HZ 的服务是按小时收费的,就算是高配版本的服务器,让它跑个几天,也不至于让小氯连华夫饼都吃不起。

简单观察得到,留下的最廉价的是 Regular Performance 产品线的 CPX22。那 CPX22 就 CPX22 吧,先把服务恢复了再说;x86-64 就 x86-64 吧,反正花的不是我的电费。

虽然小氯那天早上腹部绞痛,又要去赶话剧排演,又要考体育,电动车还不凑巧地坏了,还要提交一大堆资料……但小氯表示情绪稳定,毕竟咱重建一次服务器的时间可能还不如美签的预约页面加载一次的时间长。

没办法,某元素娘越来越 chill 了。

大概一个小时吧,小氯把服务暂时迁移到了 CPX22。由于配置文件和备份都在,迁移几乎没有遇到什么阻碍,所有服务均成功恢复。

令人悲伤的是,小氯发现,由于备份似乎早就因为硬盘空间不足而爆炸了,因此数据只能恢复到六天前——好在只是丢了一点帖文,还不算是重大损失。

按理来说,故事到这里就可以作为一个说明备份重要性的准成功案例告一段落了。但 CPX22 这个感人的价格(2C4G + 80 GB,加上 IPv4 10.09 USD/mo,都快赶上 CAX21 了)实在是让小氯有些不愿承受。

那显然,我们接下来又要面对一个并不甜蜜且烦恼的问题了:去哪里。

是啊,去哪里?

朔望凝待之庭

显然,本节讲的是搬家。除了服务器搬迁,小氯也确实搬了一次家。新房间比过去小了许多,但小氯不太在意,因为长得比较小只整天泡在自习室和图书馆,只是每天晚上回来休眠一会儿而已。

另外,准确来说呢,这个恢复过程是先在 HZ 的 CPX 上演练,然后在 netcup 上重复的。

霜尽春归

首先 Hetzner 不用继续想了,CPX22 已经是目前里面最廉价的款式了。至于盯着它补货,小氯有点忙,没时间陪那些脚本玩游戏。

由于不希望做 infrastructure monitor,小氯也没有多看那些声名不显的小厂。余下的欧洲主机大厂中,Scaleway 看起来更像是「云服务商」,而非 VPS 服务商;真正的「云服务巨头」OVH 的话,小氯没有如何多考虑它,原因不明。那余下的选择就是 netcup 和 Contabo 了。

唔……老友们,我应该在这里介绍一下这两家厂商吗?

或许应该吧,为了文章的完整性。

简单些说,netcup 像是一个更偏 VPS 服务商感觉的 Hetzner,严谨、性能有保障、性价比尚可,但体验比 Hetzner 还要……古典;至于 Contabo,我倾向称它为欧洲版 RackNerd——账面数据令人瞠目结舌,4C8G + 150 GB 的 VPS 年付是 3.6 EUR/mo。By contrast,AWS 这个级别配置的 EC2 大概是每个月 60 至 70 USD。至于代价,大家也能想得到,Contabo 的超售在欧洲主机大厂中属于最严重的。

本来的话,小氯也并没有什么高负载的业务——偶尔编译个十万行的 Rust 项目而已(《没有》),而且有 Eltrac 探过路,即使遇到 steal time 也不至于陷入太深的沙坑。但当我打开 Contabo 的官网时,看到的第一行字是:

Host Your Own AI Agent with OpenClaw - Free 1-Click Setup!

好的,告辞。

虽然 netcup 也有提供这东西的一键安装镜像来着(小声)。

最后小氯选了 netcup 的 VPS 500 G12,2C4G + 120 GB,2.5 Gib 的口子。从纸面数据和 VPS Benchmark 的报告看,CPU 性能比 CAX11 强不少,硬盘性能不如但也够用,最后价格居然还比 CAX11 便宜些——可能是因为小氯选的位置是 no preference EU 的缘故。不过最后抽到了纽伦堡,还是不错的。至于 KYC,小氯也并没有遇到什么阻碍,连预付款都没有,付完钱也就完事了。比 Hetzner 的 gov ID check 轻松了不少。

大概就是这样。虽然 netcup 的看家本领是它的 Root Server(相当于 VDS 吧),但这对小氯目前的需求来说溢出太多了。咱的货币也不是大风刮来的,留着吃两块华夫饼不好嘛。

另外,一个可能会让诸位老友感兴趣的事实:这两家公司都不是独立的。netcup 隶属于奥地利的 IT 公司 Anexia,而 Contabo 的控股权主要属于美国的私募巨头 KKR。

早至的黎明

第一件事:扫一眼服务器的启动、网络和硬盘配置,这并不是各种机型通用的。简单观察发现,netcup 居然还在用 BIOS 这种古典的选择。好在 SCP 基金会控制面板上提供了 UEFI 选项(路径:Settings -> Activate UEFI Boot),开启 UEFI 之后……重装还是重启来着?差不多,反正我们一会儿也是要刷成 NixOS 的。

至于网络,小氯在这里鼓捣了半天。IPv4 的事情倒是好做,交给 DHCP 就好了;但 IPv6 并没有那么有趣。在求助了语言模型后,小氯决定写一个 network 文件:

systemd.network.networks."10-ethernet" = {
  matchConfig.Type = "ether";
  networkConfig = {
    DHCP = "yes";
    IPv6AcceptRA = true;
  };
  addresses = [
    {
      Address = "YOUR_IPV6_ADDRESS";
    }
  ];
  routes = [
    {
      Gateway = "fe80::1";
      GatewayOnLink = true;
    }
  ];
};

虽然硬编码不太美妙,但先让它跑起来吧。

硬盘倒没什么可说的,/dev/vda2 硬编码进去就好。这次开局就有 @varlib 子卷,应当是不会再出什么奇异的变故了。

然后就是经典操作 nixos-anywhere 了。这里有一个问题:小氯用 sops-nix 管理服务器机密,而这个机密需要固定的 SSH host key 解锁,但刚刚安装完的机器显然是没有我们准备好的 SSH host key 的。所以在真正启动服务之前,需要想办法上传备份好的 host key。虽然理论上可以用 extra files 参数扔上去然后用 system.activationScripts 保底修正权限,但小氯采取了最简单粗暴的方式:

sudo vim /etc/ssh/ssh_host_ed25519_key
sudo vim /etc/ssh/ssh_host_ed25519_key.pub
sudo chmod 600 /etc/ssh/ssh_host_ed25519_key
sudo chmod 644 /etc/ssh/ssh_host_ed25519_key.pub

密钥说到底也是一段文本嘛。

未亡者的悼亡

后面的故事大抵乏善可陈。数据和配置都在,也出不了什么大事情。惟一值得提的是在顺带着检查了 Stalwart 的日志后,某元素娘严肃地考虑了一下是否要绕过中继、直接用服务器发送邮件,并且在 Mail Tester 取得了 10/10,但一会儿之后还是放弃了。或许未来会再次尝试这样做吧。

最后引用当事元素娘对本次迁移的评价:

或许我早就该迁移了。

集中化

最近——好像已经不是最近了。没办法,依旧是小氯鸽了太久的问题——小氯在 Hacker News 上读到一条新闻:Astral 被 OpenAI 买了。

按理来说,此处应该写「小氯反应了一会儿才想起来 Astral 是谁」的,但事实上没有。小氯几乎立刻就反应过来了——哦,开发 uv 的那家公司,tyruff 也是它们的。

没办法,小氯总喜欢记这些无用的东西。

或许是幸存者偏差,小氯总觉得自己看了许许多多这样的例子。Bun,Astro,Stainless,那个提供免费的 macOS 和 FreeBSD 构建器的 Cirrus CI 也加入了 OpenAI 的基础设施部门——真是太遗憾了,如果不是这件事,我连他们是谁都不知道。

它们的故事大差不差。从一个惊艳的点子开始,在才华横溢又雄心勃勃的创始人的推动下成为行业的新潮标准,最终也成了一个「更伟大的集体」的一部分。那些创造它们的人或许是真诚地相信这些满面笑容的收购者是能帮助项目走向更好的未来的白衣骑士,或许只是感到疲倦希望有一处薪酬不错的地方就食。但这都不重要,因为他们临别时说出来的话并无分别——虽说未来做的事也可能是有分别的——不外乎是乘上新时代的东风,去一如既往地改变世界。

但小氯对「改变世界」没兴趣。在元素眼中,改变是容易的,恒常却艰难。

OpenAI 和 Anthropic 收购这些工具,大抵不是为了做慈善的。是为了让它们的语言模型调用工具时顺畅些——或者用它们更喜欢的说法,促进「agentic development」,虽然小氯没有看出它们的东西有任何的能动性(agency)。至于继续保持自由软件许可——哦不,开源许可,应该也只是因为不得不这样做,或者是为了继续让自家的工具主导整个市场——甚至是自己的竞争对手的用途。毕竟,谁不喜欢 monopoly 呢。

那如果有一天,机器的体验和人的体验出现了剧烈的冲突,这些稳坐高台的人们又会如何抉择呢?

小氯并不想盲目地否定一切的 M&A 或者人才并购。我之前喜欢举的例子是 GitHub,但现在这个例子显然已经不合适了,所以实证研究这里就暂且空缺吧。从逻辑推演上看,认定任何收购都会毁掉一件工具也是不合理的。

但……为什么一定是那些大公司呢?它们太大了,大得层层叠叠、漫无边际,我的手掌感知不到它的全貌,刺不穿内部决策的哪怕几层,也触摸不到它的心。它们要「为无数人负责」:为投资人和股东、为管理层、为政府、为企业用户、为某些员工……

但除此之外,它们会愿意对谁负责呢?

说起来,前段时间 Bun 的创始人 Jarred Sumner 提了一个 PR,内容是……将 Bun 用 Rust 重写了。

一个 Zig 社区的明星项目,它的创始人用 Claude Code,花了几天的功夫,产生了几千次提交,上百万行的修改,一个 PR,最后被合并了。

而这个提交的签名人甚至都没看过一眼究竟写了什么。

这个 thread(我姑且借用这个词)吵翻了天,GitHub 的网页端也不出意料地罢工了——我哪能指望它们有什么可靠的行为。不过从 gh 爬下来的记录看,没什么有新意的观点,诸位老友大概可以不必费心了。

小氯没仔细审计过代码具体是如何实现的——也没这个能力,但据说用了上万个 unsafe。另外,我也不知道 Claude 有没有修改测试用例,来达到最后 99% 以上的测试通过率。

大并不会导致问题,大本身就是问题。

Not A Developer

在面签完成的那个下午,又一次话剧排演后,小氯和队里的一位学长去喝了杯咖啡。学长是打 OI 出身的计算机高手,现在在读博士,做一些编译器方面的研究。说是咖啡,其实小氯喝的依然是果茶。

「诶,Chlori,你现在主要在写什么啊?」聊了两句不痛不痒的闲话,学长突然问。

「唔……可能写 Python 和 Rust 多些?」然后小氯给学长看了随手写的几个小项目。

「你的意思是,写全栈吗?」

「不,并非如此。」我下意识地摇摇头。然后在学长困惑的目光中自检了半天才想到,这确实算是一种「全栈」。但小氯排斥这个词,是因为这个词被不合时宜地滥用,也是因为不希望自己将这个词不合时宜地滥用。

「不过也不用纠结这个了。你将来也不打算做纯计算机或者当 SWE 吧,那就不用管它到底是什么。」学长及时给我解了围,气氛回到了轻松愉快的轨道上。


「全栈」,或者说更广义、褒扬程度更低的概念,「做开发」。到底什么算是开发呢?什么样的行为体算是开发者呢?

我算吗?大概是不算吧:我写不出什么完整的软件项目,不懂任何「设计模式」和「架构原则」,甚至实际编码能力也难说有几成的水分。我的研究方向——假如有研究方向的话——也并不是某个领域的代码实现和改进。

但如果不算,那我写出来的那些小东西应该称为什么呢?以及,我的这个「计算机科学」的学位又该如何自处呢?

我之前从未想过这个问题。但当我开始思考这个问题时,我却不知道我是从什么时候开始对「开发」感到疏离的了?

可能是从 DSA 吧。

小氯过去对「开发」并没有什么疏离感——甚至还有点喜欢。我还清晰地记得自己在高考结束的那个暑假简单学了些 Python、写出第一个计算器小程序时的快意。即使我前面几门基础课也学得不怎么样,但我也写出过几个(作为课程作业的)不大不小的项目。当时我也曾经真心地感到,这种事情是令人愉悦的,就像慢慢地打磨一块璞玉。

但 DSA 则是另一种体验:我几乎溺亡在了无穷无尽的上机作业和报告中。在从学期开始到结束的十几次或者是几十次任务中,我从没有感觉过解决任何一道题目是快乐的。我只想赶紧跑出一个 AC 的结果,交差了事。遑论中间还出过让我不愿意再提起第二次的龃龉。至于期末考试,小氯并不惮在这里和老友们交一次底——我都不知道那张卷子我有没有拿到三十分。

就是这样。从此以后,我不愿再看到任何的在线代码评测平台,也不想再用任何一种语言手写任何的排序算法或者数据结构——比较长的一段时间里,我甚至不再愿意手写任何一行代码。以及,我再也不想碰 C++ 哪怕一次。

好在故事没有就此结束。小氯依然上着各种计算机的专业课,不管是数电、软工还是网原,我都拿到了满意的成绩,甚至是 A+ 这种写到简历里都不惭愧的结果。即使是数据结构和算法的知识点,当我闲暇时再看一次,也突然感觉:复杂性理论,图,树,散列表,这些东西如此鲜活。

但那个会说自己喜欢写代码,甚至想建立一个自己的开源基金会的元素娘,再也回不来了。

好啦好啦,煽情停止。

在组里工作时,因为我的「计算机背景」,我经常会负责一些代码,有时候是深度学习领域的实现,有时候只是一个方便大家调用的 API 后端;有时用的是 Python,有时是 Rust,之所以不用 Golang,是因为看起来高级一些。这件事做起来不难,即使遇到不希望动手的情况,交给语言模型解决然后我手动审计一下就好了。总体而言,小氯的工作获得了不错的评价,除了论文上的 co-author 外,还有老爷子和师兄师姐们对我「课题组 CTO」的调侃。

至于课余的事情,更丰富多彩一些,主要就是越来越 hardcore 的工具列表(喂喂喂不要往自己脸上贴金啊):Nix,Neovim,Emacs;自持的网站托管、邮件服务器、Forgejo、Fediverse 实例、Matrix Homeserver;JS-free friendly,可访问性的改善(虽然也没改善多少),小于 100 kB 的 TDS,诸如此类。未来大概还会狠狠地 rice 自己的 Asahi NixOS。甚至还自己用 Rust 写了几个小项目,几百行甚至几十行的玩具,去解决一个微不足道的需求,然后自己给它写 service module,借用 Codeberg 的 Woodpecker CI 算力自动发两个版本。

这样……似乎也不错。我解决了我自己或者别的什么地方的问题,用这种被称为编程的手段。我建起了从动机到结果的道路,至于道路上的砖石如何铺设、沥青如何干涸,这自然会使许多人感到有趣,但对小氯来说,这最多只是副作用。

至于那个「千古难题」——将来到底做什么方向,小氯依然没什么明确的答案,因为考虑到小氯无所不包的课程体系,即使把所有纯计算机和「人工智能」的方向都剪掉,能做的事情也太多了。但小氯感兴趣的东西无一例外,都有大量的统计学和数据科学(这个词也不太准确,但为了说明白问题,我们先借来用用吧)知识。至于计算机,除了作为一个理论和工程之间的翻译层外,似乎也没什么实质性的应用。

但……怎么说呢,也并不是说一定要写大堆复杂的代码,才能称呼自己是一个计算机科学专业的同学吧——学位证是教育部发的,您敢给,我难道还不敢要嘛。

说起来前几天,小氯在和大家讨论一些课题——话题吧,毕竟还不是成型的 idea。忘记是听到了什么方案了,小氯下意识地说了一句:这个方案有创意,但如何保证结算的原子性呢?

然后当时那位同学一脸懵地问我:什么是原子性?

手忙脚乱地解释了半天才和队友们对齐颗粒度。倒并不是小氯在抖书袋,只是为了表达自己的意思,小氯没多想就用了这个词而已。

是啊,下意识地就用了这个词。或许这就足够了吧。

Education is what remains after one has forgotten everything he learned in school.

Quoted by Albert Einstein

回来。作为所谓的「业余爱好」、做一些 light & fun 的浅试,和严肃地对待它、将它当作主业,是两种事情。如果要让小氯选一个作为自己未来对待「开发」的状态,那小氯可能更倾向于前者吧——light 到「开发」这个词已经几乎要失去其原本的意义为止。就像我许多非计算机专业的同学喜欢玩《图灵完备》,而小氯过去也喜欢玩《瘟疫公司》一样(小氯当时真的差点被骗去学流行病学)。

所以……我不会再妄想能列席世界上最顶级的自由软件项目的核心贡献者名单,也不会立下宏愿写一个上百万或者数千万行的内核或者运行时了。Rice 自己的系统是令人愉悦的,写一些代码、编译一个小项目解决自己的需要或者问题是美妙的,但软件或者硬件的「开发」,那是另一件事了。

所以老友们,小氯会一直是一只写东西的元素娘,未来可能会是 PhD Candidate 和 Dr.,也可能会是统计学、经济学、社会学、系统科学、数据科学又或者其他什么学科的……学者(姑且让我在自己脸上贴些金好了),可能会是教师、专家、工程师、自由职业者,甚至可能是技术官僚。

但我大概不会是一个开发者了。因为我从来就不是。