让代码协作平台走向联邦化

讲者:Anthony Wang
译者:Peaksol

译者注:该演讲最初由译者听译并制作视频字幕,之后编辑成本文。你也可以下载源字幕文件(.ass),使用合适的播放器配合原视频观看。

大家好,今天我来谈一谈联邦化的 forge。首先,我会讲解 forge 是什么,然后再讲“联邦化”是什么。

forge 就是用来进行代码托管以及协作的网站。比如说 GitHub 就是个很好的例子,它就是一个 forge。它是个专有的中心化 forge,但也常常拿来托管自由软件项目。现在大约 95% 以上的自由软件都托管在了 GitHub。当然,也有许多替代品,比如说 GitLab、Gitea、Forgejo 等等。

刚刚说的所有这些,都是 forge 软件。它们本身不是网站,而是可以下载的服务器软件。把它装上服务器运行,就有了一个 forge 网站。

当然,并非人人都想自己运行 forge 服务器,所以就有了许多网站,比如 Codeberg、Framagit,以及 KDE 的 GitLab 实例。这些 forge 和 forge 平台有很多。有的是自由软件,比如 Gitea 和 Forgejo,有的则是 GitHub。

现状

目前的情况是,它们都成了孤岛。如果我 Forgejo 实例上有个项目,而别人 GitLab 实例上有个项目,那么,如果要向别人的项目提交贡献,那我就得在别人的实例上创一个号,走一遍流程,然后才能在他们的 forge 上提交贡献。所以,目前任何这些 forge 之间都没有互通。

我也简单说一下为什么用 forge。forge 好处有很多,比如使用简单、工作流基于邮件、访问更加方便等。

你应该也知道 Git 本身已经是去中心化的了,但是 Git 只是为了一个目的专门设计的:那就是充当追踪代码和文件的工具。Git 在那方面做得很好,但它本身不能用来追踪 bug、提交 PR、管理 projects 等。Git 原本开发出来,是为了管理 Linux 内核的源代码的。而内核开发者还开了邮件列表用来接收补丁,他们还有 bug 追踪器等工具。所以,单独用 Git 不足以来开发软件,还需要其他工具来实现 bug 追踪、管理补丁 PR 等。而 forge 就提供了这些功能。

最后还要提一下,SourceHut 这个 forge 越来越流行了。它也确实在试着处理这个孤岛问题,让人们能够通过 SMTP 协议发邮件,与 SourceHut 上的项目交互。那种方法也有问题,我之后会解释。

去中心化的 Git(不包括 forge)

尽管 Git 本身是分布式的源代码管理系统,但它并不能提供访问权管理能力,也不能拿它来分享仓库。你要把它放在一个公开的服务器或者网站,其他人才能 clone 你的仓库。

而 Git-SSB、Radicle 这类项目能做的,就是托管你的 Git 仓库。但和一般的网站不一样,而是基于 P2P 网络之类的。

这些项目很有意思,但不是今天谈论的主题,因为它们更多是让你能够用 P2P 的方式来托管 Git 仓库,但并没有 bug 追踪或者 PR 功能,所以它们不是 forge。

目前的问题

接下来讲一讲,目前的情况下有什么问题。

你可能听过几年前 GitHub 的公告:为了遵守美国法律,GitHub 决定禁止伊朗等国家的开发者的访问。当然,它作为一个专有平台,还有其他许多问题。其他就不谈论了,你可以自己上网搜索,了解为什么 GitHub 不好。

今天来谈点更加有趣的。想想自由软件的开发是怎样进行的。这是全球化的大规模开发过程,全球各地的人都在为这些项目做贡献。

这个过程是十分去中心化的。这时,就没道理强迫大家用一个中心化的平台了。相反,我们想给大家更多选择,避免限制在单一服务商,允许大家用自己想用的 forge,而这些 forge 将能够相互通讯。这样,我们就能形成一个全球的去中心化网络来托管代码。要实现这一目标,就需要“联邦化”,也就是不同服务器之间的通讯。

ActivityPub 和联邦化

最近你应该听过 Mastodon。它就是一个用 ActivityPub 协议实现去中心化的社交媒体/微博平台。

ActivityPub 是一个非常通用的协议。它是基于参与者(actor)模型这种理论概念构建的。这种模型,由许多的 actor 组成,它们可以是人或者机器人之类的。所有这些人都可以相互发送信息,有收件箱和发件箱,就像邮箱一样。

ActivityPub 提供了一些指南,说明了 actor 之间发送什么特定消息,以及 actor 要如何处理这些消息及转发消息等。但总之,这个协议是十分通用的。它设计出来非常灵活和通用,所以,你用它并不足以构建一个应用程序,还要自己填补很多东西。

比如说,Mastodon 有很多 ActivityPub 扩展,在 ActivityPub 之上进行了很多开发,才实现了一个微博应用。所以 ActivityPub 是十分通用的,需要做很多工作才能实现有用的东西。

ForgeFed:ActivityPub 扩展

我们开发了一个叫 ForgeFed 的项目,它是一个 ActivityPub 协议的扩展。它由两大部分组成: vocabulary 和 behavior。这个网站上有 modeling vocabulary,但它们是十分相似的。

vocabulary 就像,比如说这里有一个仓库,我们想让这种通用的数据格式来代表各种 forge 的数据(比如说仓库、issue、补丁等)。如果不同的 forge 都实现 ForgeFed,那我们就需要他们发送的数据都遵循这种数据格式。比如说,对仓库而言,就有特定的表达方式。它是基于一种标准的,有很多例子可以参考。

behavior 的话,就像我们互发了消息,得到了这种通用消息格式(比如说我的 forge 收到了补丁或者 PR 消息),那么我的 forge 该干些什么,以及它应该产生什么连带效果。这就是这个协议的 behavior 部分规定的。

我们之所以需要这个协议,是因为 ActivityPub 协议过于通用,我们需要规定这些扩展。这样的话 forge 联邦的各种实现才能相互兼容、相互操作。

SMTP 联邦的问题

还得说说用 SMTP 实现联邦会出现的一些问题,因为这个协议也广泛用来实现联邦。

一是 SMTP 邮件受到了几家大公司的独占,比如说 Gmail 和 Microsoft Outlook 等。这是一种寡头垄断,或者说掌控邮件的只有几家公司。

而且,自托管邮箱也不容易。在家里的电脑上没法搭建一个邮箱服务器,然后用就它来收发邮件,因为邮件一直以来都面临 spam 问题。许多大型的邮箱服务提供商,采取了排斥性极强的反 spam 政策,这导致根本不可能在家里搭建邮箱服务器。

跨站透明协作

ForgeFed 实现了服务器之间的透明协作,即使这些服务器运行了不同的 forge 软件。我们要实现的目标就是,如果你要贡献到一个其他网站其他 forge 上的项目,你就应该感觉像在本地 forge 上贡献一样。

这里我也有一个小 demo,你可以提 issue、project、开 PR 或者发送补丁。你可以给 issue 等发评论,与不同 forge 上的人创建组织或团队。这些都是可能需要的功能。

而接下来两点,跨站搜索及发现项目、跨站迁移数据,就更加有意思了。

值得一提的是,Mastodon 并没有跨站搜索功能。Mastodon 早期设计就是这样的,你不能在你的实例上搜索,然后获得跨站搜索结果。最近有许多人尝试为 Mastodon、微博平台、Fediverse 开发跨站搜索,但遭到了人们的反对,因为许多这些全局搜索项目,都无差异地将无数帖子收录了进去。它们并没有筛选,所以很多人都不满意。

我们有一个简单的项目,叫 StarChart。不过我们最近没在开发这个项目,因为我们想先把前三项弄好。但是最终我们会开发出一个选择性加入的全局搜索。

如果你问许多自由软件开发者:即使 GitHub 是专有的,为什么还要用它?他们常常会说:因为每个人都在用它。我把我项目放上去,其他人就会发现它。毕竟 GitHub 有这种全局搜索功能。你可以输入搜索词,然后它就会返回许多项目,十分有用。人们就会想:如果转用这些联邦的 forge,就会错过这样的机会。但有了跨站搜索,我们应该就能提供这样的机会。

最后,我们想实现的是,能够尽可能简单地把帐号和仓库等,从一个服务器无缝迁移到另一个。

迁移的原因可能有很多。可能你现处的 forge 服务器改动了政策,你不喜欢了。可能是服务器有资金问题。可能他们不想你的身份和这个 forge 有关联。或者可能他们硬件出了问题,服务器不稳定,要关闭了。而 ForgeFed 的一个目的,就是扩展 ActivityPub 让你能够轻松将项目迁移到其他服务器。

发展生态

这仅仅是个开始。我们还有更远大的理想,就是从此发展一整个生态。

大家经常用 GitHub 还有另一个原因,那就是 GitHub 拥有巨大的生态。所有网站、app、工具都与 GitHub 兼容并集成。比如说,如果你想用 GitHub 的 CI 或构建系统,大家已经写了数千个插件,让你能够更轻松地用他们的 CI。而且许多网站都有 GitHub 集成,比如从 GitHub 导入。也有一些东西,制作出来只能与 GitHub 及其 API 兼容,所以他们给自己围上了高墙,多亏了这些只兼容 GitHub 生态的应用。

我们相信,有了 ForgeFed,我们可以做出类似的替代品,但是做得更好。由于我们有 ForgeFed 这个开放的协议,任何人或者任何代码协作工具或网站,都可以读 ForgeFed 的 spec,然后实现它。接着他们的网站或者工具也能添加 ForgeFed 支持。

由于他们的工具使用了这个可以相互操作的 ForgeFed 协议,所以就不会像 GitHub 一样,只能受限于那一个 API 下的 forge。

在未来,我们会有很多不同的 forge、很多不同的工具,它们都在 ForgeFed 之上,它们都有这种通用的数据格式和协议,所以他们都能够互相通讯和操作。这就是我们总的图景。

ForgeFed 实现

现在可以讲一讲实现了。目前,我们在做两个 ForgeFed 实现。

有一个实现是 Vervis,但并不是适合普通用户使用的,它更多是 ForgeFed 开发者测试和实验用的。

不过,我们还有第二个实现,就是一个叫 Forgejo 的 forge 软件。

这背后的故事可能有点复杂。原本我们是要在 Gitea 实现联邦化的,它是一个很流行的自托管式自由软件 forge。但不幸的是 Gitea 被一家盈利性公司收购了,接着一切都乱了套。最后,许多人就一起开了个新的分支,叫 Forgejo。所有联邦化开发者都去了 Forgejo。要做的事也很多,有 100 多项任务。任务很重,要在架构上做出很多改变。

Demo(见原视频)

现在我建立了两个 Forgejo 实例,这里有一个,还有第二个。第二个实例有一个仓库,这两个很容易区分,这个是亮色的,另一个是暗色的。这里有一个,那里也有一个。

这个亮色的有一个仓库,而我想做的就是,在这个实例,向另一个实例的仓库提交贡献。我们会让两个 forge 互相通讯。

先在这里登录,这个 forge 是完全空白的,我建起来当 demo 的。

目前这个联邦功能还没有 UI,因为我们想先把后端写好,不然没有后端,联邦也不能用。它最终的工作方式就是,把要贡献或搜索的项目地址复制一下,这里会有一个输入框,用于全局搜索。位置就在这里,但是还没实现。所以,我先手动进入 API endpoint。现在我们想在自己的实例上查看另一个项目,这是贡献的第一步。这个 API endpoint 有一点复杂。当然,这是因为我们还没做好前端,先用一下这个麻烦的方法,但有了 UI 就可以自动完成了。

可以看见,我这个帐号的用户名就是“a”,现在我在我自己的实例上看到了那个帐号的仓库。

我想发个 PR 提交贡献。就像平常一样,我们 fork 它,再发个 PR 过去。看,现在我要发到另一个实例去了。点击 Create Pull Request。

正常的话,就可以在这里看到这个 PR。然后再看看这里,也有了。可以看到改动的文件。成了,这就是这个 demo 实际工作的样子。亮色和暗色的两个 forge 能够互相通讯。

所以我就能在这里贡献另一个 forge 的 Hello World。这就是一个简单的 demo,演示了我们能做的许多事情之一。

现在我们完成了整个任务列表的 40%。但并不是 100% 完成了才能开始联邦化。但愿 Forgejo 项目能在两个多月之后实现能用的联邦。

ForgeFed 协议本身已经开发大概 5 年了,而这个一个特定的实现,迄今开发了 1 年多了。

未来规划

尽管 ForgeFed 协议我们已经开发了很久,但它还不是很完整。这两个项目的 vocabulary 都还没涵盖现在 forge 能做的所有事情。很多不同的东西都还没做完。而且,还有很多要应对或者注意的问题。

第一个问题就是 spam 和管理。任何去中心化的网络,都会有许多社会问题。好在有应对这些问题的范例。但可惜没有最好的方法来解决 spam 和管理问题。我们也一直在思考这个问题,因为我们得消灭 spam,建立一套良好的管理系统,这样才能让它更加易用、更加友好。

另一个经常出现在联邦系统的问题是,会有少数几个大型实例,或者协议的一个实现,出现独占的情况。比如对微博平台而言,那就是 Mastodon。Fediverse 里的大多数人用的都是它,它会对 spec 的发展方向有主导作用。有意思的是,ActivityPub 的 spec 基本上已经处于休眠期,但如果想建立一个微博应用,你实际上得遵循 Mastodon 的所有扩展。所以 Mastodon 很大程度上影响着社区的发展方向,这可能有很大的问题。

而且,Mastodon 也有三四个超大实例,大多数人都在那几个大型实例上。所以也有可能面临这样的情况:这些实例对整个网络有着很大的权利和影响,并且控制着整个网络的演进方向等。这种情况没有最优解法。但我们相信的是,通过迁移,将 一个 forge 上的数据导入另一个 forge,应该能缓解问题的严重性。如果许多人都在一个巨型 forge 实例上,而这个 forge 立下了颇受争议的政策,那如果人们可以轻松迁移数据,就能解决一部分问题。

下一点,就是自托管服务器时一般都会有的问题,大多数人都会感觉不方便。如果你想自托管 Forgejo,那有很多步骤要走,比如说买域名、买服务器,要么是买 VPS 或者用家里的电脑。但如果要用家里的电脑的话,就得进入路由器设置、配置端口转发等,做这些很复杂。

不过因为这是个一般性的问题,所以我们 ForgeFed 没有直接解决它,许多项目已经在着手解决了。比如说,有一些项目,能帮用户安装和运行服务器,而不用关心各种细节和项目维护。它们用打隧道的方法,这样的话,就算没公网 IP 地址也能在自己的设备上轻松搭建服务。

另一点值得考虑的问题是性能以及网络的伸缩性。许多自由软件项目的规模都十分庞大,比如说 Gitea 它有成千上万的 issue(好在大多数 issue 最后都关闭了),而且它还有几百位贡献者、几百个 PR。总之,这些项目十分庞大,需要非常注重伸缩性和性能。

举例来说,Mastodon 就容易出现问题。(我一直拿它来做类比,是因为它的情况很相似,同样使用了 ActivityPub 并且还进行了扩展。)假如你在 Mastodon 上发布了一条带链接的嘟文,那这条嘟文就会传播到全世界各地的服务器。然后,为了生成链接预览,所有这些服务器都会去访问这个链接。这样,数千个服务器都会同时向这个网站发送请求。可能这个网站的网络连接不好,于是,这一获取链接预览的行为,就对网站造成了 DDoS 攻击。所以这一点也是需要注意的。

我还想指出的是,Forgejo 实现以及 ForgeFed 协议本身,这两个项目都是 NLNet 资助的。NLNet 是一个荷兰的非盈利性组织,为这些自由软件项目提供了资助,所以我们有充足的资金支持。

观众问答

Q1:我对 Fediverse 很感兴趣,关注你的项目也有一段时间了。我想问的问题,也是 Fediverse 仍然存在的一个问题。就拿 ForgeFed 或者 Forgejo 当例子。假如我从联邦网络中众多的实例中,选了一个实例来托管我的项目,怎么才能保证它的可靠性呢?显然,我在 GitHub 上注册,一大原因就是,能保证我存的代码能一直在那里。所以,有没有计划能实现,如果一个实例不可靠了,能够简单地迁移实例,或者有没有解决这个问题的方法?当涉及到实例的时候,可靠性确实是个重要的问题。

A1:好问题。这就关联到了我刚刚说的,要尽可能简单地迁移。我们想做的就是,让你能将帐号下的所有仓库,从一个服务器迁移到另一个服务器。并且,有了这种通用的数据格式,也能十分轻松地建立镜像。比如说,现在 Forgejo 可以将一个仓库镜像到另一个仓库。不过,因为镜像是使用 Git 实现的,所以这只建立了代码的镜像,因为 Git 没有管理 bug 追踪或者 PR。有了 ForgeFed,它就延伸了 Git 的镜像,从而能够将项目所有issue 等,同样地镜像过去。所以,有了镜像功能,希望也能够提高 Forgejo 实例可靠性,就像备份一样。这样,数据就存在了多个实例上。

Q2:这个项目十分不错,意义非凡。我想知道,你有没有联系 Social Web Working Group,告诉他们这个项目?我之所以会这么问,是因为过去几周,有很多的讨论,除了把 ActivityPub 用在微博平台,还能用在什么地方,以及是要更新 ActivityPub,还是把它归入 ActivityStreams 里。 所以我想知道,你有没有联系他们。如果没有的话,推荐你联系一下。

A2:我个人还没联系他们。不过我肯定会考虑的。

Q3:比起自由软件用例的那个问题,这个问题应该没那么有趣。不过,所谓“访问控制”,就是说只允许网络中特定的人访问某些仓库吗?

A3:这个问题其实很有意思。在 ForgeFed 协议里,我们尝试用对象能力(object capability)模型来实现权限管理和访问控制。我想在 Forgejo 实现里,不会用到这些花样的对象能力等东西。不过,在协议方面,我们确实在这么做。

Q4:你刚刚谈到了跨站搜索。我不知道能不能实现,搜索的时候也使用到这个基于对象的东西。还是说,我理解错了?

A4:跨站搜索实际上是 ForgeFed 之外的独立的项目。我所说的对象能力模型,就是另一种管理权限等的方法。所以我想这两个东西应该没什么关联。

Q5:也许我完全搞错了,如果我有什么地方弄错了,还请纠正。你刚刚谈到了,跨站搜索有一个问题,而大家都想要 Mastodon 把它加上去。现在潜在的问题是,只有允许和禁止两个选项。所以,能不能给对象分配一些属性,这样我就能选择,只有在搜索这种类型的东西的时候,才能看到我的东西?刚刚谈论的话题,让我感觉和这个问题有点关联。

A5:我想我理解了。我其实并没有在开发这个跨站搜索,不过我觉得这是一个很有意思的探索方向。

Q6:似乎 ForgeFed 建立的标准,同时也能用于 Git-SSB 或者 Radicle,从而建立一个能与其他系统同时工作的 P2P 项目;两者都使用相同的系统、相同的 spec,并且联邦节点上的 forge能互动,相互操作。你有没有考虑过让它和另一个协议工作?

A6:我认为完全是可以的。不过我们主要的关注点是传统的 forge,也就是服务器上的,而不是 P2P 网络上的。但我认为 ForgeFed 完全有潜力用在 P2P 网络上。

Q7:SourceHut 那个基于 SMTP 的标准,是否和 ForgeFed 项目有任何关联?还是说那只是给一个特定的 forge,用来借 SMTP 自己做各种事情的?

A7:我实际上并没有仔细研究过 SourceHut,不过我觉得它应该确实在实现类似的东西。我想 SourceHut 参与了 ForgeFed 的早期开发,但那是好几年前了。我并不清楚,因为我是在大约一年前加入这个项目的。

Q8:有一些 forge 软件,比如说 Gerrit,工作方式有些不一样。相比 fork 并提交 PR,你可以提交补丁然后 cherry-pick。这种工作流有些不一样。你认为这要怎么和 ForgeFed 工作?

A8:这有些复杂。ForgeFed 尽量保持通用,尽量支持所有不同的工作流。实际上,它并不知道你用的是什么版本管理系统。我们的一位 ForgeFed 开发者对 Darcs 版本管理系统很感兴趣。所以,我认为理论上,所有这些工作流都会受到支持,并且能够相互操作。但实际上,不同的 forge 都有许多差异。所以,forge 之间的通讯,可能无法像预期一样工作,毕竟不同的 forge 都有不同之处。

Q9:我不太熟悉 ActivityPub 之类的东西。你认为能不能这样:假如有一个联邦化的 forge,你想给它发一个 PR 什么的。能不能单纯在本地的客户端这么做,向那个 forge 发送请求?

A9:我认为理论上可行。但考虑到 ActivityPub 通常的实现方式,这可能更加困难一些。你应该还需要在其他实现了 ForgeFed 的 forge 上有一个帐号,才能这么做。

Q10:在 Mastodon 上可以看 Pixelfed 帖子,也可以看 PeerTube 视频。有没有计划,或者能不能在 Mastodon 上看 PR,而不对 Mastodon 进行修改?还是说 Mastodon 有一个类型白名单,导致 PR 这类信息不能在上面显示?

A10:我有研究过这个问题。我们想的是,不止是 forge 之间相互操作,还要 Forgejo 和 Mastodon 之类的相互操作。然而,Mastodon 的源代码里确实有一个类型白名单。ActivityPub 里有一个 type array 支持,可能会有些用。有了这个,就可以给这个 activity 指定多个 type。可惜 Mastodon 也不支持 type array。而且,Forgejo 在实现 ForgeFed 时用到的库也不支持 type array。如果能实现,那应该很有帮助,但我不知道有没有解决方案。所以,我们也得给 Mastodon 贡献一个补丁,这样才能实现在 Mastodon 上对一个 issue 进行评论,或者看 PR。不过这是以后的事了。

Q10(续):这个 type array 是这样没错。我在写一个通用的 ActivityPub 只读客户端。它确实不支持 type array,只支持 string 类型的 type。

Q11:这个协议是否支持数字签名,来检查某些行为是否为用户所为?

A11:基本所有 ActivityPub 实现都有签名机制。ActivityPub 标准本身是没有签名机制的。是 Mastodon 先有,然后其他的为了兼容性才加上去的。所以,我们会增加签名机制,从而给 PR 等签名。


Copyright (C) Anthony Wang 2023
Copyright (C) Peaksol 2023-2024

This page is licensed under a Creative Commons Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) License.