在Sailfish X(适用于Sony Xperia的Sailfish OS)上使用Nix
摘要
一份关于在适用于Sony Xperia设备的Sailfish OS上安装Nix包管理器的技术指南,涵盖文件系统布局、LVM分区以及F2FS相关注意事项。
<p><a href="https://lobste.rs/s/awqcgc/nix_on_sailfish_x_sailfish_os_for_sony">评论</a></p>
查看缓存全文
缓存时间: 2026/05/30 14:08
# Nix on Sailfish X(面向索尼Xperia的Sailfish OS)
来源:https://toast.al/posts/techlore/2026-05-30_nix-on-sailfish-os/
## 摘要
Sailfish OS 是一款部分开源的、基于GNU/Linux的移动操作系统,旨在与基于美国、侵犯隐私、让你不再真正拥有设备的、过度监护的 Android / iOS 双寡头竞争。这句话有点冗长,但我们必须正视一个事实:**我们**需要从这些巨型企业手中夺回我们的自由、隐私和主权。第一步是规划你的双寡头退出路径——虽然有不少 Linux 选项,但 Sailfish OS 是其中一种可行的选择,也是我选择的那一个(因为我喜欢索尼的硬件,而且你会想要一张 microSD 卡来支持 Linux 手机——如果不是因为 OEM 厂商从我们手中夺走了它的话)。我们将通过安装 Nix (https://nixos.org/) + Nixpkgs 来增强 Jolla 提供的少量软件包集合,这将使我们能够访问最大的软件包集合,其中大部分已编译为 `aarch64` 架构供使用!这是我选择(并推荐,因为这是我的做法)的设置,但读者可以自由发挥自由软件中“自由”的部分,进行修改。
## 简要背景
其实,我早就在我的设备上完成了这个设置,我很喜欢向人们展示*真正的* Nix 在手机上运行的新奇感(遗憾的是,NixOS 手机项目支持的设备不多),但事后看来,我会做一些改动。Sailfish OS 5.1.0.7 更新(收到通知时我超级兴奋!)最终对我来说出了问题——而且似乎还有很多其他用户也遇到了问题,所以他们撤回了该更新并发布了 5.1.0.8 补丁来帮助解决存储计算问题。我能够在不丢失任何数据的情况下恢复运行,但我决定通过裁剪空间/重建 Nix 分区来扩大根分区,因为我想要重新开始——我错误地使用了 Determinate Nix 安装程序而不是官方安装程序,在升级后被困在了他们的专有分支上,因为他们停止支持上游的 Nix 安装[\[\*\]](https://toast.al/posts/techlore/2026-05-30_nix-on-sailfish-os/#footnote-1)。不用说,我最好重新开始安装 Nix……同时做笔记。
## 铺设海底
### 设备布局、文件系统以及 Nix 的存放位置
在 Sailfish 方面,我们知道设备设置使用 LVM 来实现分离 `root` 和 `home` 的逻辑卷布局,其中 `home` 使用 LUKS 加密,两者都使用 ext4。但在这个布局中,`/nix` 需要一个位置。Nix 文件夹有一些特殊要求,值得深思:
- Nix 存储区永远不应包含明文敏感数据,因此无需加密开销
- 如果不设置限制,Nix 会膨胀并占用大量磁盘空间
- 总体而言,Nix 是一次写入、多次读取的 I/O,具有仅追加/不可变的行为,而不是修改文件
- 海量的小型 `*.drv` 和 `*.nar` 文件
考虑到这种工作负载,我会选择使用单独的 LVM 卷,以防止 Nix 无节制地增长超过我希望的大小,同时使用 F2FS (https://www.kernel.org/doc/html/latest/filesystems/f2fs.html) 文件系统,既不使用 fscrypt 也不使用 LUKS 加密。虽然 ext4 在这里是安全的默认选择(而且 Sailfish 仓库中确实有相关工具),并且差异正在缩小,但在这种情况下我还是无法放弃 F2FS,因为:
- 它对 NAND 闪存(如 eMMC 和 UFS)进行了优化
- `inline_data` 可以将 `.drv` 和 `.nar` 文件存储在 inode 中
- `inline_dentry` 有助于查询庞大的 `/nix/store`
- `atgc` 有助于识别热/冷数据,以减少写入的方式清理/移动数据
- `gc_merge` 仅在文件系统不处于压力下时才进行垃圾回收,或者更优的方法是,在 Nix 垃圾回收或执行大型 `home-manager` 构建后(`nixtamal refresh` 之后)脚本化混合 TRIM
- 未来如果我们获得超过 5.4.x 的 Linux 内核更新,可以添加像 `lz4` 这样的压缩功能,进一步减少写入和校验和压缩
缺点:
- F2FS 可以增长(离线),但不能缩小(这就是我们要重新开始的原因,但如果不是为了腾出空间给根分区扩展,我也不会动它)
- 无论是 Sailfish 还是 Chum 都不提供 `f2fs-tools`,所以我们需要手动构建;它不需要很长的构建时间或工具链,只是有点烦人(但好处是我们可以使用合适的 `mtune` 进行构建——并且拥有工具来格式化任何 microSD 卡,使其明确针对它进行优化)
- 恢复工具不那么好(但由于我们*不依赖* Nix,所以无所谓 🤷)
- 不如 ext4 那样“无聊”
中性的:
- 性能:取决于任务和驱动器,但每次我看到 ext4 和 F2FS 在基准测试中竞争时,实际使用中差异微乎其微——两者几乎每隔一个内核版本都会获得性能提升
TL;DR:我愿意承担构建 `f2fs-tools` 的成本,因为我知道内核不会对 F2FS 有任何问题,并且从长远来看,即使这类驱动器具有一些内建能力来帮助减少写入,它也能减少驱动器的磨损。
### 发现我们的恢复模式
**重要提示**:你应该已经按照 Sailfish X 安装指南 (https://jolla.com/sailfishxinstall/) 完成了安装。
就像经验丰富的 Android ROM 爱好者所认识的那样,鉴于这些设备曾是 Android 设备,我们需要通过刷写一些镜像来进行恢复。这些镜像将以 ZIP 压缩包的形式从 trials (https://shop.jolla.com/downloads/) 页面获取,或者通过购买许可证获取。
**注意**:出于某种奇怪的原因,他们只允许你在欧洲购买许可证?🤨
解压压缩包并进入其解压目录后,我们会得到:
```
$ find . -type f -iname "*.img"
./vendor_boot.img
./hybris-boot.img
./hybris-recovery.img
./dtbo.img
```
猜猜这些镜像中哪一个会被使用。Jolla 也发布了一份恢复指南 (https://docs.sailfishos.org/Support/Help_Articles/Recovery_Mode/),你应该遵循。
```
$ fastboot flash boot_a hybris-boot.img
$ fastboot flash boot_b hybris-boot.img
$ fastboot reboot
```
这将使我们的设备进入一种状态,一旦连接到一台能够使用 `telnet` 的机器,我们就可以用 `telnet 10.42.66.66`(或者屏幕上小字体显示的任意地址)拨号。执行 `telnet` 后,以最佳状态模仿 Trinity 的台词“I’m in” (https://www.youtube.com/watch?v=1eRxp_r9Qx4&t=53s),然后阅读屏幕上的菜单选项。我可能建议首先选择文件系统检查选项,以确保一切正常且快速完成。否则/之后,选择 shell 选项。你将进入一个 BusyBox 环境,工具非常有限,但这已经足够了,因为我们可以:
```
# chroot /rootfs
```
将自己 chroot 到 Sailfish OS 环境中,拥有其根工具。现在有了更多工具可供使用:
```
# lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT /dev/sda75
NAME SIZE FSTYPE MOUNTPOINT
sda75 101.8G LVM2_m
├─sailfish-root 5G ext4 /
└─sailfish-home 96.8G crypto
└─luks-$UUID 96.8G ext4 /home
# lvs
LV VG Attr LSize
root sailfish -wi-ao---- 5-ish-g
home sailfish -wi-ao---- rest-of-disk-g
# dmsetup ls
sailfish-root (253:0)
luks-$GUID (253:3)
sailfish-home (253:1)
```
我们现在可以看到已经有了 LVM 设置,这很好,因为我们可以添加一个新的逻辑卷。我们的 home 分区使用了 LUKS 加密。两者都使用 ext4,在这种情况下,我们获得了重要的 ext4 相关优势,即我们不仅可以在线缩小/增长,而且可以这样做;这很重要,因为我们需要 `chroot` 到 `/rootfs`,因为恢复环境中的 BusyBox 可惜没有附带执行操作所需的文件系统相关工具(尽管我猜你也许能够找到这些二进制文件并从挂载点运行它们,但我会坚持使用 `chroot`,因为这是经过充分验证的方法)。
**注意**:如果在线增长/缩小的能力对你很重要或听起来非常有用,只需将你的 Nix 分区设为 ext4 而不是 F2FS——我不会评判你,只是请记住要针对 Nix 工作负载调整它。不过,如果你在 microSD 上选择 ext4 而不是 F2FS,我可能会评判你…… 🙂
### 腾出空间
**提示**:由于我们正在调整 home 分区的大小,你**真的**应该考虑扩展 root 分区的大小,因为 5GB 在安装大约 2 个应用程序后就会变得非常紧张。
首先,需要多少空间?我计划将 `root` 扩展到 10 GB,将 `home` 缩小到 72 GB,剩下的 19.8 GB 分配给 `nix`。我知道未来可以扩展 `root` 或 `nix`,所以目前这应该足够了。目标是:
```
# lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT /dev/sda75
NAME SIZE FSTYPE MOUNTPOINT
sda75 101.8G LVM2_member
├─sailfish-root 10G ext4 /
├─sailfish-home 72G crypto_LUKS
│ └─luks-$UUID 72G ext4 /home
└─sailfish-nix 19.8G f2fs /nix
```
缩小 `home`:
```
# e2fsck -f /dev/mapper/sailfish-home
# resize2fs /dev/mapper/sailfish-home 72G
# lvreduce -L 72G /dev/sailfish/home
# cryptsetup resize sailfish-home
```
扩展 `root`:
```
# lvextend -L 10G /dev/sailfish/root
# resize2fs /dev/sailfish/root
```
创建 `nix`:
```
# lvcreate -l 100%FREE -n nix sailfish
```
由于空间已释放且有了卷,重新启动到完整的操作系统中完成剩余工作会更舒适/更容易,因为在那里更容易获取其他工具。
### 可能完成的任务:构建 `f2fs-tools`
> 啊,又来了
——Carl “CJ” Johnson,一个彻头彻尾的暴徒
现在是时候像我们的祖先那样构建一些软件了……
```
# pkcon refresh
# pkcon update
# pkcon install git
# cd /opt
# git clone https://git.kernel.org/pub/scm/linux/kernel/git/jaegeuk/f2fs-tools.git
# cd f2fs-tools
```
阅读 README 并跳过 SELinux,因为它对我们来说不是必需的(好吧,而且 Chum 和 Jolla 仓库之间存在版本不匹配问题,而这正是我们通过 Nix 要避免的——真是讽刺)……
```
# pkcon install autoconf make libtool libuuid-devel
# ./autogen.sh
# ./configure --without-selinux CFLAGS="-O2 -mcpu=cortex-a55+crypto"
# make -C lib -j4
# make -C fsck -j4
# make -C mkfs -j4
# make -C lib install
# make -C fsck install
# make -C mkfs install
# fsck.f2fs -V
fsck.f2fs 1.16.0 (2026-01-01)
# mkfs.f2fs -V
mkfs.f2fs 1.16.0 (2026-01-01)
```
任务:完成
### 设置 f2fs
```
# mkfs.f2fs -O extra_attr,flexible_inline_xattr,inode_checksum,sb_checksum,compression -l nix /dev/sailfish/nix
F2FS-tools: mkfs.f2fs Ver: 1.16.0 (2026-01-01)
Info: Debug level = 0
Info: Label = nix
Info: Trim is enabled
Info: Enable Compression
Info: [/dev/sailfish/nix] Disk Model: MT128GAXAU2U227X
Info: Segments per section = 1
Info: Sections per zone = 1
Info: sector size = 4096
Info: total sectors = 5191680 (20280 MB)
Info: block size = 4096
Info: zone aligned segment0 blkaddr: 512
Info: format version with
"Linux version 5.4.210-sodp (abuild@phost23) (Android (10087095, +pgo, +bolt, +lto, -mlgo, based on r487747c) clang version 17.0.2 (https://android.googlesource.com/toolchain/llvm-project d9f89f4d16663d5012e5c09495f3b30ece3d2362), LLD 17.0.2) #1 SMP PRE"
Info: [/dev/sailfish/nix] Discarding device
Info: This device doesn't support BLKSECDISCARD
Info: Discarded 20280 MB
Info: Overprovision ratio = 1.040%
Info: Overprovision segments = 109 (GC reserved = 103)
Info: format successful
```
**注意**:现在设置压缩标志,希望(尽管怀疑)未来可能会有内核更新允许使用它。
挂载它……
```
# mount -t f2fs /dev/mapper/sailfish-nix -o rw,noatime,nodiratime,compress_algorithm=lz4,inline_data,inline_dentry,inline_xattr /nix
# lsblk -o NAME,SIZE,FSTYPE,MOUNTPOINT,UUID /dev/sda75
NAME SIZE FSTYPE MOUNTPOINT UUID
sda75 101.8G LVM2_member ...
├─sailfish-root 10G ext4 / ...
├─sailfish-home 72G crypto_LUKS ...
│ └─luks-$UUID 72G ext4 /home ...
└─sailfish-nix 19.8G f2fs /nix $NIX_UUID
```
……复制该 UUID 并添加到 `fstab`:
```
# vi /etc/fstab
```
```
UUID=$NIX_UUID /nix f2fs defaults,rw,noatime,nodiratime,compress_algorithm=lz4,inline_data,inline_dentry,inline_xattr,x-initrd.mount 0 0
```
## 安装 Nix
### “选哪个 Nix?”
Nix、Lix、Snix、Determinate Nix 是一些流行的名字,但也许你从未想过要问这个问题。Snix 还没准备好。Determinate Nix 是专有的/不适合我的用例。我很想再试试 Lix,但它缺少实验性的 `blake3-hashes`,所以我不得不再次忽略它。这样就只剩下 Nix 了。结果有点无趣,但这确实意味着我们需要考虑使用哪个*安装程序*——更具体地说:**如果你不打算使用 Determinate Nix,就不要使用 Determinate Nix 安装程序**。我过去曾强烈推荐它,因为它确实提供了更好的用户体验,但最终它会让用户使用他们的分支。所以我们使用基本的安装程序:https://nixos.org/download/。
### 安装程序,我几乎不认……
这让我很困惑……你需要 GNU Bash(而不是 BusyBox 符号链接)来运行安装程序,因为官方安装程序使用了 Bash 特有的语法(许多脚本的通病)。你可能也需要这个(之后可以撤销,但作为符号链接一开始就有点可疑):
```
$ pkcon remove busybox-symlinks-bash
$ pkcon install gnu-bash
```
多用户设置:
```
# curl --proto '=https' --tlsv1.2 -L -o nix-installer.sh https://nixos.org/nix/install
# cat nix-installer.sh
... 确保这里没有意外内容
...
# chmod +x nix-installer
# ./nix-installer --daemon
...
好了!我们完成了!
试试吧!打开一个新的终端,然后输入:
$ nix-shell -p nix-info --run "nix-info -m"
感谢使用此安装程序。如果您有任何反馈或需要帮助,
请不要犹豫:
您可以在以下位置提交问题:
https://github.com/NixOS/nix/issues/new?labels=installer&template=installer.md
或者与社区联系:https://nixos.org/community
---- 提醒 -----------------------------------------------------------------
[ 1 ]
在重新启动活动的 shell 会话之前,Nix 不会工作。
```
```
# nix-shell -p nix-info --run "nix-info -m"
栈大小硬限制为 2097152,小于所需的 62914560。如果可能,请增加硬限制,例如使用 'ulimit -Hs 61440'。
- system: `"aarch64-linux"`
- host os: `Linux 5.4.210-sodp, Sailfish OS, 5.1.0.8 (Pispala), nobuild`
- multi-user?: `yes`
- sandbox: `yes`
- version: `nix-env (Nix) 2.34.7`
- channels(root): `"nixpkgs"`
- nixpkgs: `/nix/store/j45fm5ffm7agj6pbsvkqbq7778rrxadc-nixpkgs/nixpkgs`
```
添加实验性功能以获得良好体验:
```
echo "extra-experimental-features = nix-command fetch-tree blake3-hashes" >>/etc/nix/nix.conf
systemctl enable nix-daemon.service
systemctl restart nix-daemon.service
```
很棒。
### `home-manager`
是的,仍然使用 `home-manager`。即使它有缺点,像这样管理点文件(文本编辑器、CLI 工具、字体)是一个很好的用例。我有一个本地配置检出在 `~/nixcfg`。
```
# su defaultuser
$ cd ~/nixcfg
$ nix-build host/$HOSTNAME/home.nix
$ result/activate
```
遗憾的是,`home-manager --file` 选项不符合*我的*喜好,所以我只能构建激活脚本,然后运行它。将来,我应该编写一个脚本来运行这个……但也要在激活脚本运行之前禁用 F2FS 垃圾回收。
### `system-manager`
我很想再次使用它来处理系统级别的配置/软件包,但它只适用于实验性的 flakes。我已经接触过足够多的 flake Nix 代码,看到了它严重的设计缺陷,但也注意到它如何导致 Nix 用户编写质量不高(或不兼容)的 Nix 代码,最终我干脆将其剥离了。这并不是说 `system-manager` 的 Nix 代码像我刚才提到的那样糟糕,只是无法使用 `system-manager` 二进制文件配合稳定的 Nix 代码——据我所知,它要求配置必须是 flake 清单文件的非标准扩展。也许如果他们支持经典的 Nix(或者我深入研究如何在不使用 flakes 的情况下运行它,尽管他们的设计是锁定的),我会重新考虑。如果你知道其他方法,请告诉我。
相似文章
我喜欢的 NixOS 声明式安装方式
一份关于使用 nixos-anywhere 等工具通过网络声明式安装 NixOS 的指南,重点强调在版本控制下管理配置文件。
将我的 NAS 从 CoreOS/Flatcar Linux 迁移到 NixOS
Michael Stapelberg 详细介绍了他将一台 NAS 从 CoreOS/Flatcar Linux 迁移到 NixOS 的过程,涵盖了从 Docker 容器逐步过渡到原生 NixOS 模块的步骤,并附有实际示例。
NixOS 与密钥管理
教程介绍 NixOS 的密钥管理选项,比较 sops-nix、agenix 和 ragenix 工具,并提供使用 sops-nix 进行加密密钥管理的实际示例。
Lanzaboote – NixOS 安全启动
本文介绍了 Lanzaboote,这是一个用 Rust 编写的 UEFI UKI 存根,可为 NixOS 提供安全启动支持。它将签名检查推迟到 UEFI 阶段执行,同时保持内核和 initrd 与 UKI 二进制文件分离,从而解决了 NixOS 特有的启动挑战。
securix: 基于 NixOS 的安全操作系统。提供具有强隔离性、可重现性和策略驱动配置的强化环境
Sécurix 是一个基于 NixOS 的安全操作系统,由法国数字部门 (DINUM) 开发,用于强化环境,具有强隔离性、可重现性和策略驱动配置,目前处于 alpha 阶段。