steamdeck只读系统的处理方案,在readonly状态下尽情使用steamos
hmlc
编辑于 2022年11月15日 06:36
收录于文集
共1篇

本文完全是鼠鼠的个人理解和折腾经历,如有错误感谢指出!

前言:

        前不久因为pixel slate更新chromeOS v107导致crouton容器出了很多问题,用crostini容器凑合了好几天时,正好steam deck终于过关开始派送了,到手后直接换上提前备好的2T SN740开始体验基于arch的steamOS 3.0,准备用其搭建一个docker+node的开发环境。

        结果刚上手就发现了一个很重要的问题,之前各处宣传的桌面模式等同于普通linux桌面环境的体验,这一点是不完全正确的!因为steamos3.0为了原子更新采用了只读系统

v社官方steamos桌面模式-常见问题

        集成在SteamOS3.0桌面模式KDE环境下的discover软件管理中心,只能下载flatpak包格式的应用,这是一种将依赖全部打包并在沙盒中运行软件的技术。.

        而如果你想要像正常archlinux一样通过pacman安装软件包时,哪怕是root也是没有写入权限,因为steamos3.0是只读系统

        v社官方给了 sudo steamos-readonly disable 的命令去关闭只读,虽然这样你就可以正常使用了,但是安装的内容却有可能会在下次steamos更新后被移除,这样如果你想在steamdeck的桌面模式上搞开发啊或者折腾其他都会受到限制,那么最简单的方法就是在每次更新后重新用pacman等安装你所需要的软件,即使可以编写自动脚本也少不了时间成本,何况很多数据可能还需要备份。


        经过了两天的探索折腾,来分享一下解决方案。

        首先我们应该先去了解一下steamos3.0,steamos明明是只读系统,为什么却可以使用flatpak安装软件,直接sudo提权修改etc目录下的文件等行为呢?

此处贴上大佬的博客,收获到了很多 =>https://www.svenknebel.de/posts/2022/5/2/  

steamos恢复镜像目录结构-home

        文中对steamos的系统目录结构做了分析,其更新可能采用了A/B分区策略, 并且提到了home目录(用户)下的.steamos目录

使用mount命令查看挂载

       直接说结论,根目录 / 挂载为btrfs格式,/opt,/root,/srv,/usr/local,/opt,/var下的部分子目录,这些全是由systemd处理挂载的ext4格式,实际位置在/home/.steamos/offload下    

        这些目录下的文件因为都在home下所以都是更新后可保留的,其中/var/lib下只有/flatpak/docker 、/systemd三个文件夹用于挂载,/flatpak文件夹就是用来保留discover商店安装的flatpak应用数据的,这样就不会受到更新影响,v社还贴心的在lib下预留了/docker文件夹,我猜就是有考虑到让用户关闭只读安装docker也能在系统更新后保留镜像容器。

        在/etc,v社做了个overlayfs(堆叠文件系统),在只读的系统上叠了一层可写层,实际目录则是在/var/lib/overlays/etc,而这个overlays并不在上面说的home目录里,是在/var分区,是的,/var是单独挂载的一个分区,只有部分子目录源自/home/.steamos,鉴于A/B分区的更新模式,暂时还不好判断/var分区有没有划分A/B区(还未体验过更新),reddit上的信息是etc的修改大部分都有保留,我将在收到更新后测试

        也就是说系统更新后不受影响的看似只有/home,其实还有/home下的.steamos文件夹挂载到系统目录的部分。而官方的overlayfs层也给出了在readonly的系统下写入文件的方法(下文提到的rwfus)。

追加图:测试各个目录的权限

    可以知道/usr下只有/local不是readonly(源自.steamos),/var不是readonly,虽然也是挂载上去的,但并不源自home分区的.steamos,自然源自/var子目录的/etc也不是readonly,这些目录都是可以在root权限下进行读写操作的(Permission denied说明我没在root用户下权限不够)

那么知道了系统更新后不受影响的目录有哪些后来看一下解决方案吧!


正题:

四种针对readonly文件系统的解决方案


  1. Homebrew,安装Homebrew本身需要 sudo,所以更新后可能不会存在。

  2. Rwfus ,通过OverlayFS在只读文件系统之上创建一个可写层,这样就可以让 pacman                正常工作,还可以做到更多。github=>https://github.com/ValShaped/rwfus

  3. distrobox,通过rootless模式的podman运行其他发行版linux,共享文件目录,                    可以打开带GUI应用程序。github=>https://github.com/89luca89/distrobox

  4. 摆烂 or 编写脚本简化每次更新后的重新安装操作


其中最推荐3号方案distrobox,但是rootless的podman也不能用来跑docker啊?

所以还是需要2号方案去本机环境起docker。

1号方案homebrew可能用mac的比较了解,但即使可以把东西安装在home目录,命令本身是需要sudo提权安装的,更新后可能不存在。

虽然上了github仓库地址,还是来简单讲一下吧!


distrobox:

    distrobox是一个精美的包装器,使用podman创建和启动与主机高度集成的容器,能用容器运行各种linux发行版,能在不可变操作系统上提供可变环境,在用户目录设置提供本地特权环境。有点类似chromeos的crouton,chroot容器环境

这是distrobox官方提供的steamos3.0,rootless环境的教程

=>https://github.com/89luca89/distrobox/blob/main/docs/posts/install_rootless.md

这是gamingonlinux社区提供的教程

=>https://www.gamingonlinux.com/2022/09/distrobox-can-open-up-the-steam-deck-to-a-whole-new-world/


这是鼠鼠我参照着写的图文教程

使用curl命令安装distrobox脚本,不能忘记最后的追加参数,这是安装到/home/deck/.local下的

代码块
JavaScript
自动换行
复制代码
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/install | sh -s -- --prefix ~/.local
复制成功

使用curl命令安装podman脚本,这也是安装到/home/deck/.local/podman下的

代码块
Shell
自动换行
复制代码
curl -s https://raw.githubusercontent.com/89luca89/distrobox/main/extras/install-podman | sh -s -- --prefix ~/.local
复制成功

然后为/.local/bin和/.local/podman/bin目录添加用户级的环境变量

文件位于/home/deck/.bashrc

代码块
Shell
自动换行
复制代码
export PATH=$HOME/.local/bin:$PATH

export PATH=$HOME/.local/podman/bin:$PATH

xhost +si:localuser:$USER
复制成功


现在打开终端就可以使用distrobox和podman命令了!如果提示command not found可以手动在终端先输入一次。

通过distrobox create命令创建容器

代码块
Shell
自动换行
复制代码
distrobox create -i ubuntu:22.04
复制成功

此处我安装的是ubuntu22.04版本,默认会去docker拉取镜像,慢的话需要用clash配合加速。

代码块
Shell
自动换行
复制代码
distrobox enter ubuntu-22-04
复制成功

创建好后的容器名字会是ubuntu-22-04,其他版本命名规则类似,使用enter进入容器

此处左下的用户已经切换为ubuntu

接下来你就可以在此终端使用单独的ubuntu了,于是我随手就是一个apt install。

screenfetch

很轻松的构建了node开发环境,你也可以在ubuntu下安装chrome,vscode,只要用xhost给了权限,是能通过dbus打卡GUI界面的,这点和chromeOS,crostini容器,root用户需要xhost加权情况类似。

用node16.18跑vue3+nestjs练手项目

创建多个容器

容器内的vscode,可以看到标题的ubuntu18.04

可以选择创建自己常用的不同的linux发行版!平滑过渡使用体验


distrobox这种类似chroot容器的方案还是比较简单的,但是Docker该怎么办呢?我还有数据库和nginx没跑那。用无守护进程,无root权限的podman,拉取docker打包的ubuntu镜像并创建容器,然后在容器中再跑个需要守护进程和root权限的docker?虽然都是跑在steamos这个5.13版本内核上的,但是显然有问题。那么我的选择还是只能在本机环境用pacman去安装docker并用systemctl启用守护进程。接下来就是Rwfus的部分了!

Rwfus:

rwfus脚本是在只读环境上挂载一层overlayfs去写入文件,默认挂载 /usr,/etc/pacman.d ,/var/lib/pacman 和 /var/cache/pacman,这样你就可以让 pacman 正常工作,这一点和官方挂载/etc的思路是一样的,只不过将目录设置在了/home/.steamos下,保证了更新后能保留。

而且为整个/usr挂载了overlayfs,这让很多必须关闭只读才能修改的行为成为可能。

比如用clash for windows的设置直接安装service服务,启动全局的tun模式

使用了rwfus后,直接在软件内安装服务并启用

可以说如果v社官方后续更新能将overlayfs不止用于/etc,而是整个只读系统,再根据A/B分区切换将用户数据挂载到新版本系统上,那么steamos可能会更加好用


官方git仓库

=>https://github.com/ValShaped/rwfus

接下来又是鼠鼠我的踩坑图文 用法很简单,git clone仓库地址,cd目录,也可以直接从release下载最新版本

代码块
Shell
自动换行
复制代码
git clone https://github.com/ValShaped/rwfus.git
cd rwfus
复制成功

注意!此处追加重要的一步!

  • 如果你的steamdecks是使用了官方恢复镜像还原的系统,使用main分支的脚本会出现问题,必须切换到dev分支再运行安装脚本!如果不确定可以两个分支的脚本都跑一下,记得切换之前使用--remove命令删除掉安装的残留,

切换分支命令=>git checkout dev

翻译后的兼容性警告文本,此问题在3天前的dev分支修复

  • dev分支是创建了一个4GB的btrfs文件目录去做挂载,和main分支不同!main分支的文件默认在/home/.rwfus下,dev分支的文件在/opt/rwfus下,之前提到过/opt是从home目录挂载到系统的,也就是说是在/home/.steamos/opt/rwfus下,会发现一个4GB的btrfs镜像

作者对于dev分支的回复(谷歌翻译)

注:2022/11.13日晚已发布最新版本0.4.0,dev的功能已合并至main,下文将新增新版本教程

0.4.0版本readme自动翻译

  • 0.4.0版本创建了一个默认8GB的btrfs硬盘镜像去做挂载,默认在/opt/rwfus下,之前提到过/opt是从/home下的目录挂载到系统目录的,也就是说是在/home/.steamos/opt/rwfus下,会发现一个8GB的btrfs镜像,这个镜像的大小和目录是可以在配置文件里修改

  • 新版本会自动设置pacman,不需要手动初始化了

  • 因为官方有挂载/usr/local,新版本会检测是否启用了此目录,如果有启用,安装后会保留该路径

  • 现在可以使用--backup和--restore命令来备份和还原用于挂载overlayfs层的btrfs镜像

确定完脚本分支开始安装

代码块
Shell
自动换行
复制代码
sudo ./rwfus -iI
复制成功

运行rwfus脚本,此处--install和-i是一样的

-I将脚本安装到/usr/local/bin,图中已标明在/home/.steamos下(更新后文件保留)

-i是安装,-I(大写i)是将脚本到/usr/local/bin,这样可以直接全局使用rwfus命令,而且这个目录有提到过官方直接是从/home/.steamos挂载的.

mount命令确认下overlayfs挂载情况

接下来需要立刻操作下pacman

新版本会自动设置pacman,可以不用操作一下命令

代码块
Shell
自动换行
复制代码
sudo pacman-key --init

sudo pacman-key --populate

sudo pacman -Sy
复制成功

注意!作者建议不要使用任何-Su -Syu -Syyu等更新命令

自动翻译后的rwfus使用pacman时注意事项

config,位于/etc/opt目录下,可自己设定位置

--gen-config可以初始化生成一个config模板

config中还可以设置需要创建overlayfs的目录(还未测试,目前场景默认的几个目录够用,等更新后确认下var分区再做考虑,毕竟v社官方将docker存放位置也放在了home下)

截于2022.11.15,适用于0.4.0版本

更多的命令请参考官方仓库readme

接下来就可以在steamos-readonly status处于enable的状态(只读)使用pacman命令啦!

=>sudo pacman -S docker docker-compose

跑起docker-compose脚本启动容器化的数据库和nginx服务

给steamos也安装个screenfetch跑一下

练手项目完整的跑起来了

        这就是我目前在readonly模式下进行写入操作,并搭建开发环境的方案。需要用到守护进程或者本机root权限的应用就通过rwfus脚本使用pacman安装,其他rootless环境能搞定的就用distrobox的podman容器,切换不同的linux发行版,更自由的安装应用软件,来摆脱flatpak的限制。

        这样理论上可以在steamos更新后保留数据,但是目前还没有更新发布也不想切换到beta通道,听说测试通道已经支持任天堂布局了(很急),总之是希望有需要的兄弟尝试下,看场景选择使用哪个工具,distrobox和rwfus可以应用于不同的场景,但也可以同时使用,大大的拓展steamos3.0只读系统的实用性!


        其实习惯了chromeOS的这种多容器系统的方案 (目前仅维护状态的chroot容器脚本crouton,谷歌目前官推的lxc容器crostini,还有安卓容器),折腾起steamOS3.0的时候理解起来轻松了不少,也得感谢github上的开源大佬们提供的解决方案!希望v社官方后续也能提供一些方案,毕竟在.steamos/var/lib目录下还有空的docker文件夹,加上win的双系统引导,我认为steam deck能成为一个更方便的便携电脑

最后来个两台设备的合影。

pixel slate /// steam deck