Quá trình fork SteamOS cho PC phòng khách
(iliana.fyi)- SteamOS 3 “Holo” là bản phân phối dựa trên Arch dành cho Steam Deck, nhưng để sửa sự cố resume sau suspend trên PC phòng khách, tác giả phải revert một commit kernel và tự fork cả image rootfs
- Cấu trúc cập nhật dùng mô hình A/B: cài rootfs chỉ đọc mới vào phân vùng không hoạt động rồi khởi động lại;
/etcdùng overlayfs để giữ lại các thay đổi - Các bản vá kernel của Valve được xử lý theo quy trình clone bare Git repository từ source tarball như
linux-neptune-61-6.1.52.valve9-1.src.tar.gztrên mirror nguồn pacman, rồi build package bằng tag riêng và PKGBUILD - Việc repack rootfs gồm trích xuất
rootfs.img.caibxtừ SteamOS RAUC bundle để tạo image, đổi UUID Btrfs, thay package, đổibuildid, thay URL cập nhật và chứng chỉ RAUC, rồi đóng gói lại thành RAUC bundle - Khi web server riêng cung cấp
live.jsonvà thayQueryUrl,ImagesUrl,MetaUrlcủasteamos-atomupd, cả bản cài SteamOS hiện có cũng có thể cập nhật sang image tự xây dựng
Vì sao fork SteamOS cho PC phòng khách
- SteamOS 3 “Holo” là bản phân phối Linux dựa trên Arch của Valve Software dành cho máy chơi game PC cầm tay Steam Deck
- Cơ chế cập nhật là cấu trúc cập nhật nguyên tử A/B: tải rootfs chỉ đọc mới xuống phân vùng không hoạt động rồi khởi động lại vào phân vùng đó
- Người dùng có thể chạy
steamos-devmodeđể mở khóa rootfs và chuẩn hóa cơ sở dữ liệu pacman, từ đó thao tác như một bản phân phối Linux thông thường - Mục tiêu là tạo một bản fork đúng nghĩa có thể sửa trực tiếp image rootfs, thay vì dễ dàng đi đường vòng bằng
steamos-devmode - Trên PC phòng khách, SteamOS gần như hoạt động, nhưng chỉ không resume được sau suspend
- Trên cùng máy tính đó, các bản phân phối khác dùng mainline hoặc stable kernel đều resume sau suspend được
- Sau khi tìm được nguồn kernel của Valve và chạy
git bisect, tác giả phát hiện một commit có vẻ sửa resume sau suspend cho phần cứng Steam Deck lại gây lỗi trên PC này - Nhu cầu revert commit đó và tự build kernel là lý do trực tiếp của toàn bộ công việc
- Cũng có lựa chọn dùng trực tiếp Arch hoặc bản phân phối khác, nhưng nếu phải chỉnh sửa một bản Linux để chạy game, tác giả muốn dựa vào tập package đã được Valve kiểm thử hơn
Cấu trúc phân vùng và cập nhật của SteamOS
- Hệ thống SteamOS dùng 8 phân vùng
- EFI system partition chứa stage 1 bootloader và metadata chọn bộ phân vùng A/B
- Mỗi bộ A/B có GRUB là stage 2 bootloader, root filesystem và phân vùng
/var - Phần dung lượng đĩa còn lại được dùng cho một phân vùng
homeduy nhất
- Khi boot, nhiều pseudo-filesystem được mount thêm
- Gần 12 thư mục như
/var/log,/root,/nixđược bind mount từ/home/.steamos/offloadđể lưu dữ liệu bền vững
- Gần 12 thư mục như
/etcđược xử lý bằng overlayfs- Các thay đổi được lưu trong
/var/lib/overlays/etc/upper - Những mục thường cần còn lại trong
/etc, nhưmachine-idvà kết nối NetworkManager, được giữ lại - Các file cấu hình chưa bị chạm tới vẫn có thể được cập nhật
- Cách này xử lý đồng thời việc giữ lại cấu hình và cập nhật trong cấu trúc phân vùng A/B mà không cần logic của package manager
- Các thay đổi được lưu trong
- Cập nhật hệ thống bắt đầu khi Steam client hoặc người dùng terminal chạy
steamos-update- Lệnh này chạy chương trình Python
steamos-atomupd-client - Client gửi thông tin OS hiện tại và thiết lập kênh cập nhật của người dùng tới URL trong
/etc/steamos-atomupd/client.confđể kiểm tra có cập nhật mới hay không
- Lệnh này chạy chương trình Python
- Nếu có cập nhật mới, server trả về đường dẫn RAUC bundle
- Client tải bundle và chạy
rauc install - RAUC xác minh chữ ký bundle và tìm
rootfs.img.caibx casync extracttải các mảnh image mới xuống và ghi vào phân vùng rootfs không hoạt động- Script post-install đồng bộ chọn lọc dữ liệu từ
/varđang hoạt động sang/varkhông hoạt động, đồng thời đổi cấu hình stage 1 bootloader trong EFI system partition để boot vào bộ phân vùng mới
- Client tải bundle và chạy
Tạo package từ nguồn kernel của Valve
- Valve dùng một Linux kernel đã chỉnh sửa nhiều trong SteamOS, và mã nguồn có thể tải xuống
- Nguồn của image SteamOS hiện tại có thể tìm thấy trong
sources/holo-3.5vàsources/jupiter-3.5trên pacman mirror của Valve - Tại thời điểm viết, kernel của stable image là
6.1.52-valve9-1-neptune-61, và source tarball tương ứng có dung lượng 2.9GiB - Tarball lớn vì chứa toàn bộ Linux Git tree
- Bên trong tarball có
PKGBUILD,config,config-neptune,archlinux-linux-neptune/, v.v. archlinux-linux-neptune/không phải working tree thông thường có thể làm việc ngay, mà là bare repository
- Bên trong tarball có
- PKGBUILD trỏ source tới một GitLab repository riêng tư dạng
git+ssh://git@gitlab.steamos.cloud/jupiter/linux-integration.git#tag=$_tag- Không thể clone trực tiếp hay liên kết tới commit
- Có thể lấy snapshot chứa toàn bộ lịch sử commit của từng tag từ source của
makepkg - Nhờ cấu trúc này, tác giả có thể bisect commit làm hỏng suspend trên PC phòng khách
- Quy trình làm việc là clone bare repository thành working tree thông thường rồi duy trì branch và tag riêng
- Ví dụ là tạo
my-branchtừ tag6.1.52-valve9 - Các thay đổi riêng được đưa lên một Git host riêng, rồi sửa source trong PKGBUILD sang repository đó và tag riêng
- Repository ví dụ là linux
- Ví dụ là tạo
- Có thể tạo package kernel bằng
makepkgmakepkg MAKEFLAGS=-j$(nproc)hoặc cập nhật/etc/makepkg.confhữu ích khi không build trên VM nhỏ- Trong phạm vi đã xem, các package đặc thù SteamOS khác cũng dùng cấu trúc tương tự: Git repository làm source đầu tiên
- Để các bước sau dễ hơn, tác giả cấu hình pacman repo riêng
- Đặt package vào một thư mục, chạy
repo-add $REPO_NAME.db.tar.zst [PACKAGES...], rồi upload lên web host - Repo này về sau cũng giúp công cụ hoạt động bình thường nếu chạy
steamos-devmode
- Đặt package vào một thư mục, chạy
Lấy và mount root filesystem
- Vì không tìm được các script release engineering, tác giả chọn cách repack root filesystem hiện có theo nhu cầu
- Script không có phần mô tả hay chú thích nằm ở fauxlo
- Cách phổ biến để có SteamOS rootfs image là mua Steam Deck hoặc tải Steam Deck recovery image, nhưng cả hai đều yêu cầu đồng ý Steam End User License Agreement
- Phiên bản release hiện tại có thể xem trong snapshot JSON, có vẻ là fallback URL của hệ thống cập nhật
- Tại thời điểm viết, stable version là
20231122.1 - Cũng có snapshot JSON riêng cho kênh preview
- Tại thời điểm viết, stable version là
- Việc tải rootfs làm theo cùng trình tự với
steamos-atomupd-client- Tải file
.raucb, tức RAUC bundle - Trích xuất
rootfs.img.caibxtừ bundle, vốn là filesystem SquashFS - Dùng
casync extractđể lấy các mảnh từ.castrstore và tạorootfs.img - URL của
.castrstore được tạo bằng cách thay.raucbtrong URL RAUC bundle thành.castr - Hành vi này được hard-code trong
steamos-atomupd - Script tự động hóa nằm ở fetch-current.sh
- Tải file
- Các file
.img.zipvà.img.zstliền kề không phải rootfs mà là recovery image có thể boot riêng- Cũng có thể trích xuất phân vùng rootfs từ recovery image để dùng ở bước tiếp theo
- Tuy nhiên, nó không giống bit-for-bit với image nhận được qua RAUC và casync, và khi tạo lại update bundle thì dù sao cũng cần các công cụ đó
- Trước khi sửa rootfs, cần đổi filesystem UUID
- Nếu không đổi UUID khi cập nhật từ image SteamOS hiện có sang image tùy chỉnh, hai filesystem khác nhau sẽ có cùng UUID
- Trạng thái này có thể gây sự cố
- Ví dụ là
btrfstune -fu rootfs.img
- Valve dùng image Btrfs với nén zstd
- Để giữ nén trong lúc thay đổi, mount bằng
mount -o compress=zstd rootfs.img rootfs - SteamOS dùng thuộc tính subvolume
readonlycủa Btrfs, nên bỏ thuộc tính này bằngbtrfs property set -ts rootfs ro false
- Để giữ nén trong lúc thay đổi, mount bằng
- Sửa các package như Linux kernel có thể kích hoạt script yêu cầu
/devvà/proc- Mount
devtmpfsvàprocbên dưới rootfs - Mount tmpfs vào
/tmp,/run,/var,/homeđể tránh ghi vào những thư mục sẽ được mount trong hệ thống khi boot - Bind mount
/etc/resolv.confcủa host để việc phân giải tên trong chroot hoạt động
- Mount
Thay package và sửa metadata của image
- Repository riêng được thêm làm repo đầu tiên trong
/etc/pacman.conf- Như vậy package riêng được ưu tiên ngay cả khi repo của Valve có phiên bản mới hơn
- Sau này, nếu chạy
steamos-devmode, package riêng vẫn có thể được cài lại
- Ví dụ stanza repo dùng
[fauxlo],Server = https://fauxlo.ili.fyi/pacman/$arch,SigLevel = NeverSigLevel = Nevercho phép package không có chữ ký- Muốn cài package có chữ ký GPG thì phải điền pacman keyring
- Thay vì đụng vào keyring rỗng trong
/etc/pacman.d/gnupg, tác giả dùng cách điền keyring mới trên tmpfs
- Cài package bằng dạng
pacman --sysroot rootfs --noconfirm -Sy linux-neptune-61- Trong script thực tế, tác giả tránh
-yvà chỉ đồng bộ cơ sở dữ liệu repo riêng phía sau pacman - Cách này giữ trạng thái các repository khác cố định ở thời điểm image gốc được build
- Đây là lựa chọn nhằm giảm các thay đổi xuất hiện trong diff của image
- Trong script thực tế, tác giả tránh
steamos-atomupdđọc phiên bản image hiện tại và build ID từ/lib/steamos-atomupd/manifest.json; nếu không có thì dùng/etc/os-release- Nếu build ID của bản cập nhật do server cung cấp trùng với image hiện tại, cập nhật sẽ bị từ chối
- Nó cũng hữu ích để nhận biết đang chạy image nào
- Build ID bắt buộc phải theo định dạng
YYYYMMDD.N- Nếu không đúng định dạng,
steamos-atomupdsẽ thoát kèm Python traceback - Để tránh phải tăng thủ công, có thể đưa
HHMMSShoặc Unix timestamp vàoN - Sửa đồng thời
buildidtrongmanifest.jsonvàBUILD_IDtrongos-release - Đoạn Bash script cho việc này nằm trong repack.sh
- Nếu không đúng định dạng,
- RAUC dùng chứng chỉ X.509 cho cấu hình tin cậy
- Chứng chỉ được tin cậy nằm ở
/etc/rauc/keyring.pem - Một self-signed certificate đơn giản là đủ
- Cài chứng chỉ mới vào
rootfs/etc/rauc/keyring.pem
- Chứng chỉ được tin cậy nằm ở
- Cũng đổi các URL trong
rootfs/etc/steamos-atomupd/client.confsang server riêngQueryUrlImagesUrlMetaUrl
- Có thể thực hiện các thay đổi khác miễn là không vượt quá không gian 5GiB của image Btrfs
- Ví dụ, nếu muốn tìm thiết bị SteamOS trên mạng bằng
hostname.local, có thể xóarootfs/usr/lib/systemd/resolved.conf.d/00-disable-mdns.conf - Cũng có thể override bằng cấu hình overlay của
/etc, nhưng tác giả cho rằng cách đó phiền phức
- Ví dụ, nếu muốn tìm thiết bị SteamOS trên mạng bằng
- Nguyên tắc là không đưa vào rootfs những thay đổi có thể làm dễ dàng mà không cần image
- Có thể cài Firefox vào rootfs
- Nhưng mỗi bản cập nhật bảo mật của Firefox sẽ buộc phải repack lại image
Unmount rootfs và tạo RAUC bundle
- Khi sửa xong, đánh dấu filesystem lại là read-only
btrfs property set -ts rootfs ro true
- Loại bỏ các block không dùng bằng
fstrim -v rootfs umount --recursive rootfshữu ích khi unmount- Có thể xử lý luôn cả các pseudo-filesystem đã mount trước đó
- Trước khi tạo RAUC bundle, cần tạo casync store và blob index
- Ví dụ:
casync make --store=rootfs.img.castr bundle/rootfs.img.caibx rootfs.img
- Ví dụ:
- RAUC bundle cần ba file
manifest.raucmrootfs.img.caibxUUIDchứa filesystem UUID
manifest.raucmchứa thông tin update và rootfs imagecompatible=steamos-amd64version=$versionsha256sizefilename=rootfs.img.caibx
- Tạo file
UUIDbằngblkid -s UUID -o value rootfs.img >bundle/UUID - Sau khi chuẩn bị ba file, chạy
rauc bundle- Chỉ định chứng chỉ và key trong
--signing-keyring,--cert,--key - Kết quả là
rootfs.img.raucb
- Chỉ định chứng chỉ và key trong
- Upload
rootfs.img.raucbvàrootfs.img.caibxlên web server màImagesUrltrongclient.conftrỏ tới- Hai file này phải nằm trong cùng thư mục
Server cập nhật riêng và áp dụng
- Web server dùng cho
QueryUrlvàMetaUrlphải cung cấp file JSON - Với cấu hình đơn giản, chỉ một file
live.jsonlà đủ- Object
.minor.candidates[0].imagephải giống/lib/steamos-atomupd/manifest.jsonbên trong image update_pathlà đường dẫn mà update client sẽ nối sauImagesUrlđể tải bundle
- Object
- Ví dụ cấu hình Caddy rewrite các request mà
steamos-atomupdgửi tớiQueryUrlvàMetaUrlthànhlive.json- Rewrite
/updatesthành/live.json - Rewrite
/meta/*/*/*/*.jsonvà/meta/*/*/*/*/*.jsonthành/live.json - Dùng
file_server browse
- Rewrite
QueryUrlvàMetaUrlthực tế của SteamOS có vẻ có nhiều logic hơn, nhưng chỉ cấu hình này cũng đủ đểsteamos-atomupdtìm được cập nhật mới- Có logic tránh cập nhật nếu image đã được quảng bá đang là image hiện đang chạy
- Để cập nhật một bản cài SteamOS hiện có sang image riêng, chỉ cần sửa
/etc/rauc/keyring.pemvà/etc/steamos-atomupd/client.conf- Không cần
steamos-readonly disable - Các thay đổi sẽ nằm trong overlay của
/etc - Sau khi chạy
steamos-update, nên cân nhắc dọn các thay đổi đó khỏi/var/lib/overlays/etc/upper
- Không cần
- Có vẻ cũng có thể sửa một trong các recovery image của Valve để thay rootfs bằng image riêng và cài một bản SteamOS biến thể, nhưng phương pháp này chưa được kiểm thử
1 bình luận
Ý kiến trên Hacker News
Tôi thích những bài viết kiểu này, đi sâu tùy biến phần mềm/OS trên thiết bị mình sở hữu. Cũng mừng là trên Steam Deck không phải lo về Tivoization
Phần tôi thấy thú vị nhất trong bài là phân vùng
/nix. Tôi không biết Steam Deck hỗ trợ nixpkgs, tìm thêm thì thấy dù không phải cài đặt mặc định, vẫn có thể đưa nó lên thiết bị mà không cần fork toàn bộ OSKho Nix có thể đặt ở bất kỳ vị trí nào ghi được, rồi chỉ cần đổi
$PATHtrỏ tới thư mục symlink là đượcBài viết thật sự kỹ lưỡng và thú vị. Cá nhân tôi chắc chắn sẽ không làm tới mức này
Tôi chỉ từng đụng tới Linux hồi dùng Raspberry Pi, mà ngay cả vậy cũng chỉ khoảng 1%, nên thấy tác giả thật đáng nể
Tương tự https://github.com/kiler129/relax-intel-rmrr nhưng không phải repo của tôi
Nguyên nhân gốc chỉ có thể giải quyết bằng bản cập nhật ROM từ nhà sản xuất, nhưng chiếc DL360 cũ tôi dùng đã hết hỗ trợ từ HPE
Bản thân patch chỉ là thay đổi một dòng, nhưng cập nhật kernel thì phiền. Phải lấy SRPM, vì không có repo Git nên phải giải nén SRPM, áp patch rồi build và cài lại
Đã có các bản phân phối dựa trên các thành phần của SteamOS, tối ưu cho việc dùng PC với tay cầm. ChimeraOS còn bao gồm cả EmuDeck, công cụ bổ trợ cho Steam Deck, và trong môi trường của tôi nó chạy khá ổn
Tôi đã đặt mua GPU để chạy Steam Headless bằng một Docker image rất hay trên máy chủ NAS unRaid, rồi kết nối từ laptop Windows bằng client như Moonlight
Nếu chạy tốt thì tốt hơn nhiều so với việc mua thêm phần cứng desktop chơi game trong khi NAS hầu như nhàn rỗi. Tuy nhiên cần giữ thiết lập điện năng của card Nvidia ở trạng thái idle khi không dùng. Hy vọng có thể làm được bằng cách gọi
nvidia-persistenced1: https://github.com/Steam-Headless/docker-steam-headless
1: https://github.com/games-on-whales/gow
https://kubevirt.io/user-guide/virtual_machines/host-devices...
Chạy game theo kiểu khai báo, cloud-native cơ đấy!
kubectl apply -f crysis.yamlHôm nay tôi mới biết đến RAUC(https://rauc.io/). Trước đây tôi vẫn tò mò Valve triển khai cơ chế cập nhật A/B như thế nào
Có ai hơi nhớ favicon mưa sao băng của Netscape không?
Bài viết thú vị. Nâng cấp A/B có vẻ hơi quá mức. Nếu có vấn đề thì có thể boot một bản live distro, hoặc cài hệ thống khôi phục phiên bản cũ vào một phân vùng riêng
Vài năm gần đây tôi dùng NixOS rồi quay lại Arch; trước đó tôi cũng đã dùng Arch lâu rồi, và tôi nghĩ nỗi lo của tác giả là không đúng
Arch chắc chắn là một bản phân phối rất nghiêm túc và trưởng thành, còn đáng tin hơn Valve
Lý do tôi chuyển sang Arch là vì chất lượng gói. Repo chính cập nhật thật sự nhanh, còn AUR có rất nhiều gói hữu ích
Việc hệ thống tự động khôi phục sau khi nâng cấp lỗi gần như là yêu cầu bắt buộc đối với một OS ít cần quản trị ở thời điểm này
Tôi nhìn chung thấy chất lượng gói NixOS khá cao
Gần đây tôi có trong tay một thiết bị chơi game cầm tay là Legion Go nên đang tiếp xúc với Linux nhiều hơn. Trước đây tôi từng né vì nó trông như một kiểu lãng phí thời gian vá víu bất tận, và khả năng tương thích với những thứ tôi thật sự muốn dùng cũng hạn chế
Tôi bắt đầu tò mò khi đọc về hệ thống tập tin bất biến và chuyện Linux truyền thống dễ dàng trao quyền root cho đủ loại phần mềm tùy tiện
Hiện tôi đang dùng NixOS; đúng là nó có thể thành lãng phí thời gian để mày mò, nhưng rất tốt để khám phá. Có thể dễ dàng thử nhiều thành phần khác nhau, và nếu quyết định không giữ lại thì có thể gỡ sạch hoàn toàn, ngoại trừ mức độ làm bẩn
~/.config. Việc vá trước khi cài cũng chỉ là chuyện nhỏ, nên có thể dễ dàng thêm các bản vá kernel giúp chạy Linux trên phần cứng đặc thù như thiết bị chơi game cầm tayCó một cộng đồng NixOS tên Jovian đang tái cấu trúc các tarball SteamOS tùy ý của Valve thành các commit được gắn tag trên GitHub, nên bạn có thể xem qua mã nguồn như nhân viên Valve. Họ cũng làm sẵn để chỉ cần thêm vài dòng vào cấu hình Nix là có thể cài bản sao SteamOS của riêng mình lên trên NixOS
Rõ ràng họ là các chuyên gia Linux, và khi xem mã nguồn có thể thấy họ nhận các gói của Valve ở trạng thái chưa chỉnh sửa, ngoại trừ những tinh chỉnh đơn giản như kiểm tra thay vì hard-code vị trí nút nguồn
Nếu muốn trải nghiệm SteamOS thuần túy nhưng không muốn tự vận hành mirror cho hệ thống cập nhật của Valve, hoặc muốn khám phá mã nguồn Valve mà không phải tải tarball 3GB, Jovian rất đáng thử
Hướng dẫn cài đặt: https://jovian-experiments.github.io/Jovian-NixOS/getting-st...
Mirror mã nguồn Valve: https://github.com/orgs/Jovian-Experiments/repositories?type...
bazzite.gg cũng làm việc này rất tốt. Trên phần cứng AMD, 120Hz VRR hoạt động ngay, và cũng có thể thử nghiệm alpha hỗ trợ HDR
“Bazzite là một image OCI có thể dùng làm hệ điều hành thay thế cho Steam Deck, đồng thời là một môi trường giống SteamOS sẵn sàng để chơi game cho máy tính để bàn, PC home theater phòng khách và nhiều PC cầm tay”
https://github.com/ublue-os/bazzite/
Dù không quan tâm thì README cũng đáng xem. Danh sách những thứ được bao gồm dài khủng khiếp, và có rất nhiều mục trông khá hay và hữu ích, đặc biệt với game thủ hoặc streamer
Tôi chưa đào sâu đến mức có thể giải thích ngắn gọn và hoàn hảo chỉ bằng một bình luận HN, nhưng cốt lõi là đặt một bản phân phối Linux chỉ đọc, đã được xác minh ở root, rồi xếp các gói thành lớp lên trên. Cấu trúc này lấy rất nhiều cảm hứng từ container phía máy chủ
Mục tiêu là an toàn hơn, đáng tin cậy hơn, có thể tái lập và dễ tùy biến hơn so với Linux truyền thống. Bạn ghi các gói mong muốn vào manifest container; khi có bản nâng cấp, hệ thống chạy nâng cấp rồi cài lại các gói lên trên đó
https://universal-blue.org/guide/fork-your-own/
Và vì là OS bất biến, nếu có vấn đề thì cũng có thể rollback về image trước đó
Phần lớn là chơi trên Steam Deck hoặc chạy Bazzite trong máy ảo có áp dụng GPU passthrough, và nó được làm thật sự rất tốt
PC phòng khách cơ à; giờ người ta không còn hay dùng cách gọi HTPC hay “media center” nữa sao?