Flatpak 官网首页至今还写着一行醒目的承诺:"Build for every distro: create one app and distribute it to the entire Linux desktop market."支持列表里甚至特意标出了 Void Linux、Guix 和 Alpine——这三个发行版恰恰都不用 systemd。但最近 Flatpak 上游开始推进一项改动:将 systemd 作为运行时硬依赖引入。如果这条路线落地,官网那句承诺就不再成立,而整个 Linux 桌面应用的分发格局也会被重新搅动。
为什么 Flatpak 要绑上 systemd
Flatpak 的沙箱机制依赖几个关键组件:bubblewrap 做命名空间隔离,xdg-dbus-proxy 做 D-Bus 过滤,以及一系列用户会话服务(如 flatpak-session-helper)来协助端口转发、文档访问等。这些服务目前以独立守护进程的方式运行,启动和生命周期管理靠 Flatpak 自己的脚本处理,没有强绑定任何 init 系统。
问题在于,这种"自管生命周期"的模式在复杂桌面环境中越来越脆弱:用户会话挂起时守护进程没被正确清理、重启后状态残留、与登录管理器的协调靠猜测而非约定。systemd 提供了现成的解决方案——用户级 systemd 单元(user unit)在登录时自动启动、注销时自动停止,依赖关系和套接字激活都有声明式配置。上游开发者认为,与其继续维护一套脆弱的进程管理逻辑,不如直接用 systemd 的 user session 机制接管。
这不是一个突然的决定。早在 2022 年,Flatpak 就已经把 flatpak-session-helper 改写为 systemd user service,但当时还保留了 fallback 路径——没有 systemd 的系统可以继续用独立守护进程。新提案的核心变化是:移除 fallback,systemd 成为唯一路径。
被排除的三个发行版
Void Linux 用 runit,Alpine 用 OpenRC,Guix 用 GNU Shepherd。它们不是"小众玩具"——Alpine 是容器世界的基础镜像,Void 在轻量桌面用户中有稳定受众,Guix 是功能性包管理的标杆。它们选择不用 systemd,各有各的技术立场,但结果是一样的:用户会话中没有 systemd --user 运行。
如果 Flatpak 硬依赖 systemd user session,这些发行版上的 Flatpak 体验会直接断裂:
flatpak run启动应用时,沙箱辅助服务无法通过 systemd 启动- 现有的
flatpak-session-helperfallback 路径被删除 - 除非发行版维护者自行补丁维护旧路径,否则 Flatpak 将不可用
这不是"性能差一点"的问题,是"能不能跑"的问题。
看看改动涉及的具体代码
Flatpak 的 systemd user unit 文件目前长这样(以 flatpak-session-helper 为例):
# /usr/lib/systemd/user/flatpak-session-helper.service
[Unit]
Description=Flatpak session helper
Before=graphical-session.target
[Service]
Type=dbus
BusName=org.freedesktop.Flatpak.SessionHelper
ExecStart=/usr/lib/flatpak-session-helper
[Install]
WantedBy=graphical-session.target
关键点在 Before=graphical-session.target 和 WantedBy=graphical-session.target——这些是 systemd 用户会话的约定目标。没有 systemd --user 实例,这些 target 根本不存在,单元无法激活。
你可以检查自己当前系统是否已经在用 systemd user session:
# 检查 systemd --user 是否运行
ps -e | grep 'systemd --user'
# 查看当前 Flatpak 依赖的 user units
systemctl --user list-units 'flatpak*'
# 查看具体 unit 文件内容
systemctl --user cat flatpak-session-helper.service
在非 systemd 发行版上,第一条命令不会有输出——这就是断裂点。
如果你在非 systemd 系统上维护 Flatpak
对于 Void、Alpine、Guix 的维护者来说,有两条路:
路线 A:自行维护 fallback 分支。 从 Flatpak 仓库中剥离 systemd 硬依赖的补丁,保留独立守护进程启动方式。这是工作量最大的选择——每次 Flatpak 上游发布新版本,都要重新适配。但这是目前唯一能让 Flatpak 继续运行的方案。
一个最小化的 fallback 启动脚本可以这样写:
#!/bin/sh
# /etc/local.d/flatpak-session-helper.start
# Void Linux 的 runit local 服务目录下自动执行
# 启动 flatpak-session-helper 作为独立守护进程
exec /usr/lib/flatpak-session-helper &
#!/bin/sh
# /etc/local.d/flatpak-session-helper.stop
# 发送终止信号
kill $(pgrep flatpak-session-helper)
这只是一个粗糙的替代——它不处理用户会话边界、不处理 D-Bus 活跃检测、不处理套接字激活。systemd user unit 做的那些事,这里全靠手动。
路线 B:引入一个最小 systemd user session 层。 在不替换系统 init 的情况下,仅运行 systemd --user 来提供 Flatpak 需要的用户级服务管理。这在技术上可行——systemd --user 可以在不使用 systemd 作为系统 init 的环境下运行——但需要额外打包 systemd 的用户级组件,且与发行版的哲学立场冲突。
Alpine 的一个实验性方案如下:
# 安装最小 systemd 用户组件(不替换 OpenRC)
apk add systemd-standalone-systemd-user
# 手动启动 systemd --user(仅当前用户)
systemd-user &
这个包名是社区讨论中的提议,尚未正式进入 Alpine 仓库。实际操作中,你需要从 systemd 源码编译并只安装 user session 相关的二进制和 unit 文件,跳过系统级 init 组件。
distribution-agnostic 的承诺还值多少钱
Flatpak 当初的核心卖点就是"一个包跑在所有发行版上"。这个承诺有两层含义:
- 应用开发者不需要针对不同发行版打包——这一点仍然成立,Flatpak 的 runtime 机制没变。
- 所有发行版的用户都能运行 Flatpak 应用——这一点即将打破。
第一层是商业价值所在,Red Hat 和 GNOME 生态不会因为 Void Linux 用户无法运行 Flatpak 就改变路线。第二层是社区信任所在,而信任一旦打破,重新建立的成本远高于维护一个 fallback 路径。
更深层的问题是:Linux 桌面生态的"中立基础设施"正在缩小。PipeWire 替代 PulseAudio 时保留了兼容层,Wayland 替代 X11 时保留了 XWayland——这些过渡都给了非主流选择生存空间。Flatpak 如果直接砍掉 fallback,等于在声明"systemd 是 Linux 桌面的事实标准,其他选择不再被考虑"。
决策清单
如果你是发行版维护者或桌面环境决策者,现在需要评估这几件事:
- 确认当前 Flatpak 版本是否已包含 systemd 硬依赖。 检查源码中
session-helper的启动路径是否还有非 systemd 分支。 - 评估用户群体中 Flatpak 的使用比例。 Alpine 容器用户几乎不用 Flatpak,但 Alpine 桌面用户可能依赖它。
- 决定路线 A 还是路线 B。 路线 A 长期维护成本高但符合发行版哲学;路线 B 短期可行但引入了哲学矛盾。
- 向上游提交保留 fallback 的请求。 目前社区讨论仍在进行,技术决策尚未最终锁定,反馈窗口还在。
- 考虑替代方案。 Snap 的兼容性更差;AppImage 不提供沙箱;自行维护 Flatpak fallback 可能是最务实的选择。
Flatpak 的 systemd 依赖不是技术错误——它解决了真实的问题。但解决问题的方式,直接决定了 Linux 桌面是继续作为一个多元生态,还是加速收敛为单一技术栈。这个选择的影响范围,远超 Flatpak 本身。