Nix Flakes và các tính năng tương ứng trong Guix
(coopi.neocities.org)- Nix Flakes gộp phụ thuộc dự án, khóa phiên bản, lược đồ đầu ra và môi trường phát triển xoay quanh
flake.nixvàflake.lock, còn Guix cung cấp cùng loại tính năng thông qua tổ hợp các công cụ trực giao như channels, manifests,guix describe,guix shell,operating-system - Flakes cố định phụ thuộc bằng
inputstheo từng dự án vàflake.lockđược tạo tự động, còn Guix xây dựng môi trường có thể tái lập bằngguix describetheo từng người dùng,channels.scmghi commit trong dự án, vàguix time-machine - Tính thuần khiết được Flakes cưỡng chế bằng restricted evaluation, còn trong Guix thì đạt được theo thiết kế thông qua cấu trúc mô-đun Scheme, đầu vào tường minh và các container build cách ly
- Cấu trúc đầu ra: Flakes cung cấp attrset chuẩn như
packages,devShells,nixosConfigurations, trong khi Guix dùng các bản ghi Scheme và tệp minh bạch như<package>, manifest,operating-system, service để từng lệnh tiêu thụ trực tiếp - Tiêu chí lựa chọn: nếu bạn thích một điểm vào duy nhất và lược đồ chuẩn thì Flakes phù hợp hơn, còn nếu thích cách kết hợp các công cụ nhỏ và độc lập thì Guix sẽ hợp hơn
So sánh cốt lõi
- Không có một tính năng Guix đơn lẻ nào tương ứng trực tiếp với Nix flake; trong khi Nix Flakes giải quyết nhiều vấn đề bằng một tính năng lớn, Guix đáp ứng bằng sự kết hợp của các công cụ nhỏ hơn và trực giao hơn
- Guix tái sử dụng Nix daemon và chia sẻ các thành phần C++ phụ trách build isolation và store management
- Guix triển khai lại phần lớn những gì nằm phía trên Nix daemon, như ngôn ngữ, định nghĩa gói và hệ thống service, bằng Guile Scheme
- Guix và Nix chia sẻ định dạng derivation là ATerm và cùng chung nguồn gốc daemon, nhưng cấu trúc phía trên daemon được Guix tổ chức theo cách riêng của mình
- Guix có những khả năng mà Flakes cung cấp, nhưng thể hiện chúng dưới hình thức khác
Cấu trúc cơ bản của Nix Flake
- Nix flake là một source tree có tệp
flake.nixở thư mục gốc, thường ở dạng Git repository - Sự hiện diện của
flake.nixbiến source tree thành một flake, và tệp này có cấu trúc nhưdescription,inputs,outputs descriptionlà chuỗi để con người đọc được, mô tả nội dung mà flake cung cấpinputskhai báo dependencies như các flake khác, Git repo, tarball; Nix sẽ fetch, evaluate chúng rồi truyền vào hàmoutputsoutputslà một hàm nhận các input đã được resolve và input đặc biệtself, rồi trả về một attrset có cấu trúc chứa packages, dev shells, NixOS configurations, overlays, v.v.-
Cấu trúc ví dụ và các mục tiêu thực thi
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";tronginputsví dụ có nghĩa là lấy branchnixos-unstabletừ khoNixOS/nixpkgstrên GitHub- Flake ví dụ dùng
supportedSystems = [ "x86_64-linux" "aarch64-linux" "x86_64-darwin" ];vànixpkgs.lib.genAttrsđể tạo outputs cho nhiều CPU architecture khác nhau - Flakes yêu cầu ở mức
packages.<system>; trong ví dụ, packagedefaultdướipackagesđược định nghĩa bằngpkgs.buildGoModule src = ./.;nghĩa là dùng toàn bộ Git repository làm sourcedevShellslà định nghĩa development shell mànix developsẽ tham chiếu; trong ví dụ dùngpkgs.mkShellvàbuildInputs = with pkgs; [ go gopls gotools ];
-
flake.lockvà đánh giá thuần khiết- Khi chạy lệnh Nix với một flake, Nix sẽ tạo tệp JSON
flake.lockđể cố định mọi input và transitive input vào đúng revision flake.locklà lock file cho phép build reproducibility xuyên suốt giữa các máy và theo thời gian- Flakes cưỡng chế pure evaluation, nên
$NIX_PATH,builtins.currentSystemvà environment variables không thể được đưa vào một cách ngầm định; mọi thứ đều phải tường minh - Những gì Flakes thực hiện có thể được tóm gọn là: khai báo dependencies, ghim dependencies, cưỡng chế tính thuần khiết, cung cấp lược đồ đầu ra chuẩn, chia sẻ có thể tái lập và định nghĩa môi trường phát triển
- Khi chạy lệnh Nix với một flake, Nix sẽ tạo tệp JSON
Cách tiếp cận tương ứng của Guix
- Guix đã có sẵn lời giải cho phần lớn các tính năng của Flakes từ trước khi Flakes được đưa vào Nix 2.4 ngày 1 tháng 11 năm 2021
- Cơ chế channels của Guix được giới thiệu vào khoảng năm 2018~2019
- Cách tiếp cận của Guix mang tính orthogonal, không dùng một abstraction đơn khối duy nhất mà cho phép sử dụng từng công cụ một cách độc lập
-
Channels và khai báo phụ thuộc
- Trong Flake, dependencies được khai báo trực tiếp trong
flake.nix; trong ví dụ có dùngnixpkgs.url = "github:NixOS/nixpkgs/nixos-24.11";vàhome-manager.url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs";của Flake input khiếnhome-managerkhông lấynixpkgsinput riêng của nó mà dùngnixpkgscủa flake hiện tại, nhờ đó tránh tình huống phát sinh hai bản saonixpkgskhác nhau- channels của Guix là các Git repository chứa Guile modules; thường chứa package definitions, nhưng cũng có thể bao gồm services, cấu hình hệ thống và mã Scheme tùy ý
- Guix channels được khai báo trong
~/.config/guix/channels.scm, và file Scheme này trả về một danh sách các channel records guix pullsẽ fetch và compile tất cả channels, rồi làm cho các modules đó có thể dùng được trong mọi lệnhguix- Channels có thể dùng file
.guix-channelở root của repository để khai báo dependencies với các channels khác - Channel dependency của Guix channels nhìn chung tương tự
inputscủa flake, và khi chạyguix pullthì các transitive channel dependencies cũng được fetch cùng
- Trong Flake, dependencies được khai báo trực tiếp trong
-
Phụ thuộc theo dự án và phụ thuộc theo người dùng
- Flakes theo cách per-project, mỗi repository có
flake.nixvà inputs riêng; còn channels theo kiểu toàn hệ thống hoặc per-user, trong đóchannels.scmáp dụng cho mọi lần gọiguix - Flakes tự nhiên hỗ trợ các dự án khác nhau có các bộ dependency khác nhau; trong Guix, để đạt hiệu ứng tương tự người ta thường dùng
guix time-machinehoặc các profile tách biệt - Flakes dùng cú pháp giống URL như
github:NixOS/nixpkgs,git+https://...; còn channels dùng các Git URL thuần - Cú pháp Flake ergonomic hơn cho các tham chiếu nhanh, còn channels thì đơn giản và explicit hơn
- Flakes hỗ trợ các repository không có
flake.nixnhư non-flake inputs bằngflake = false; - Trong Guix, channel là một Git repository chứa các file Scheme nên không cần cơ chế opt-in đặc biệt; bất kỳ repository nào có Guile modules đều có thể trở thành channel
- Flakes theo cách per-project, mỗi repository có
Khóa phiên bản, tái lập và quay ngược thời gian
-
flake.lockflake.locklà một JSON graph, trong đó mọi input đều được pinning bằng commit hash chính xác và Nix sẽ kiểm tranarHash, tức hash của toàn bộ source tree đã fetchflake.lockđược commit vào repository, vì vậy những người clone sẽ nhận được cùng một phiên bản dependencyoriginaltrongflake.locklà đích đã yêu cầu, cònlockedlà đích thực tế nhận được- Hệ thống hai lớp của
flake.lockcho phép selective update nhưnix flake lock --update-input nixpkgs, tức chỉ cập nhật một input cụ thể và giữ nguyên phần còn lại
-
guix describevàguix time-machine- Guix ghi lại chính xác commit của mọi channel khi chạy
guix pull, vàguix describesẽ hiển thị thông tin này - Kết quả
guix describegồm số generation, ngày tháng, dấu current, tên channel, URL repository, branch và commit - Các channel commit đã được ghi nhận của Guix tương ứng với lock file, nhưng tồn tại dưới dạng Guile profile ở
~/.config/guix/currentchứ không phải là file trong thư mục dự án - Để chia sẻ môi trường có thể tái lập, trong Guix có thể dùng
guix time-machine guix time-machine --commit=8a1ab328 -- shell -m manifest.scmsẽ pin chính Guix vào một revision cụ thể rồi chạyguix shellbằng package definitions của revision đóguix time-machinesẽ download và compile revision đó nếu cần, rồi tạo một môi trường cô lập mà trong đó package definitions đúng với trạng thái của commit đó- Cũng có một mẫu dùng trong Guix là check in
channels.scmvới các commit đã pin vào repository dự án guix time-machine -C channels.scm -- shell -m manifest.scmsẽ dùngchannels.scmđi kèm repository để tái tạo chính xác môi trường
- Guix ghi lại chính xác commit của mọi channel khi chạy
-
Khác biệt giữa hai cách tiếp cận
flake.locklà automatic theo từng dự án, cònguix describelà automatic theo từng người dùngchannels.scmchứa các commit đã pin cung cấp cơ chế pinning theo dự án trong Guix, nhưng là cách làm thủ công- Guix đang cải thiện ergonomics của pinning theo dự án, nhưng workflow hiện tại vẫn cần thiết lập explicit hơn
flake.locklà một JSON graph machine-readable, còn đối tượng tương ứng trong Guix là file Scheme liệt kê các channels cùng commit hash- Cả hai cách đều đạt mục tiêu pinning dependency, nhưng flake lock có cấu trúc hơn vì là full dependency graph với các mục
originalvàlockedcho mọi transitive input guix time-machinelà tính năng không có direct flake equivalent; nó không chỉ pin các phiên bản dependency mà còn có thể chuyển sang một trạng thái lịch sử hoàn toàn khác của package collection
Mô hình tính thuần
- Flakes chạy trong ngữ cảnh đánh giá bị hạn chế, việc dùng
builtins.currentSystem,builtins.getEnv,$NIX_PATHbị cấm hoặc bị bỏ qua - Trong Flakes, mọi thứ đều phải đến từ các đầu vào đã khai báo, giúp khó phát sinh phụ thuộc ngoài ý muốn vào trạng thái ngầm định
- Đánh đổi của pure evaluation trong Flakes là cần các tham số
systemtường minh ở nhiều nơi để nhận diện hệ thống, đồng thời không thể đọc biến môi trường - Khi cần một lối thoát impure trong Flakes, phải truyền tường minh
--impure - Guix không cần một chế độ pure evaluation riêng, vì theo quy ước việc đánh giá vốn đã là thuần
- Các module Guile không truy cập biến môi trường trừ khi chúng được truyền vào một cách tường minh
- Guix không có thứ gì tương đương với
$NIX_PATH, và phân giải gói thông qua hệ thống module thay vì search path - Guix không có khái niệm tương đương
builtins.currentSystem, và các hệ thống được chỉ định tường minh bằng metadata của gói và cờ--system - Việc build trong Guix cũng là thuần, các bản build chạy trong các container cô lập chỉ nhìn thấy những đầu vào được khai báo tường minh
- Trong các bản build của Guix không có
/usr/bin,/etc, hay quyền truy cập mạng; ngoại lệ về truy cập mạng chỉ giới hạn ở fixed-output derivations - Cách sandbox build của Nix và Guix về bản chất dùng cùng một hướng tiếp cận
- Guix đạt được tính thuần ở cấp độ kiến trúc thông qua cấu trúc module Scheme, còn Flakes áp đặt tính thuần bằng cách chồng một chế độ đánh giá bị hạn chế lên trên một hệ thống vốn dĩ không thuần
Lược đồ đầu ra và mô hình dữ liệu
-
Lược đồ đầu ra của Flake
- Flakes định nghĩa một lược đồ chuẩn cho outputs, trong đó
packages.<system>.<name>được dùng bởinix build,devShells.<system>.<name>bởinix develop, vàapps.<system>.<name>bởinix run - Lược đồ đầu ra của Flake cũng có
nixosConfigurations.<name>,overlays.<name>,nixosModules.<name>,formatter.<system>,templates.<name>,checks.<system>.<name> - Việc chuẩn hóa lược đồ đầu ra của Flake giúp
nix build .,nix run,nix flake showtham chiếu tới các vị trí nhất quán, qua đó tăng khả năng khám phá - Nhược điểm của lược đồ đầu ra Flake là nó cứng nhắc; muốn thêm các kiểu đầu ra tùy ý thì cần sửa chính Nix, dù vẫn có một cơ chế mở rộng nhỏ
- Do tham số
<system>của Flake, hỗ trợ đa nền tảng phải được xử lý tường minh, và thường dùng các hàm hoặc thư viện hỗ trợ nhưforAllSystems,flake-utils,flake-parts
- Flakes định nghĩa một lược đồ chuẩn cho outputs, trong đó
-
Các kiểu dữ liệu hạng nhất trong Guix
- Guix không có một lược đồ đầu ra đơn nhất như Flakes, mà có các kiểu dữ liệu hạng nhất để nhiều lệnh có thể sử dụng
- Trong Guix, packages được định nghĩa bằng các record
<package>và đượcguix install,guix buildsử dụng - Trong Guix, manifests được định nghĩa bằng các tệp Scheme và được
guix shell -m,guix packagesử dụng - Trong Guix, cấu hình hệ thống được định nghĩa bằng
operating-systemvà đượcguix system reconfiguresử dụng - Trong Guix, cấu hình home được định nghĩa bằng
home-environmentvà đượcguix home reconfiguresử dụng - Trong Guix, services được định nghĩa bằng các record
<service>và được trườngservicescủaoperating-systemsử dụng - Trong Guix, channels là các repo Git và được
guix pullsử dụng - Trong Guix, các biến thể gói là các procedure Scheme và được
--with-input,--transformsử dụng
-
Tệp và định nghĩa gói
- Một dự án Guix có thể cung cấp kết hợp giữa channel chứa các định nghĩa gói,
manifest.scmcho phát triển,system.scmcho triển khai, cùng các khai báooperating-systemhoặchome-environment - Trong Guix, các tệp này không yêu cầu tệp entry point đặc biệt nào, mà đơn giản chỉ là các tệp Scheme định nghĩa các giá trị Scheme
- Trong Guix, chỉ cần chỉ định tệp cho subcommand
guixliên quan là lệnh sẽ xử lý, không cần ceremony riêng hay kiểm tra lược đồ - Ví dụ
manifest.scmkhai báo môi trường phát triển bằng cách truyền danh sách tên gói"guile","guile-git","guile-json"chospecifications->manifest - Ví dụ
mylib.scmđịnh nghĩa một record<package>, tương đương với Nix derivation trong Guix, và có thể truy vấn các trường của gói theo cách lập trình - Ví dụ định nghĩa gói có các trường
(name "mylib"),(version "0.1.0"),(source (local-file ".")),(build-system gnu-build-system),(inputs (list guile guile-git)),(home-page "https://example.com"),(license gpl3+) local-filecủa Guix lấy các tệp trong thư mục hiện tại tại thời điểm build, tương tựsrc = ./.;trong Nixgnu-build-systemcủa Guix dùng cách./configure && make && make install, và Guix cũng có các build system khác nhưcmake-build-system,python-build-system- Guix đặt mọi dependency ở dạng tường minh, khác với Nix nơi
stdenvngầm cung cấpgccvàcoreutils
- Một dự án Guix có thể cung cấp kết hợp giữa channel chứa các định nghĩa gói,
Môi trường phát triển
- Trong ví dụ
devShellscủa Flakes, sử dụngdevShells.x86_64-linux.default = pkgs.mkShell { buildInputs = with pkgs; [ go gopls gotools ]; shellHook = '' echo "Welcome to the devShell!" ''; }; mkShelltạo ra một derivation tạo môi trường shell khi được build;buildInputssẽ được thêm vàoPATHbên trong shell, cònshellHookchạy bash tùy ý khi vào shell- Có thể vào Flake dev shell bằng
nix develophoặcnix develop .#my-shellcho shell có tên - Môi trường phát triển của Guix có thể được định nghĩa trong
manifest.scmbằng cách truyền danh sách chuỗi package specification chospecifications->manifest - Ví dụ Guix manifest khai báo
"go","gopls","go-tools" - Có thể vào shell dựa trên Guix manifest bằng
guix shell -m manifest.scm - Guix cũng cho phép môi trường ad-hoc mà không cần file, chỉ bằng cách truyền tên package trên dòng lệnh như
guix shell go gopls go-tools guix shellhỗ trợ--containerđể cô lập hoàn toàn,--emulate-fhsđể chạy chương trình kỳ vọng bố cục filesystem Linux tiêu chuẩn, và--nestingđể chạy Guix bên trong container Guix- Guix manifests là các file Scheme độc lập, không được nhúng trong cấu trúc
flake.nixlớn hơn guix shellcó thể hoạt động cả khi không có file, nhưngnix developcần flake hoặcshell.nixcủa giao diện legacy- Flakes cung cấp các named dev shell như
devShells.x86_64-linux.test,devShells.x86_64-linux.default - Thay vì named dev shell, Guix manifests thường dùng các file riêng đặt song song như
manifest.scm,test-manifest.scm - Cả Nix Flakes và Guix đều hỗ trợ phát triển trong môi trường container hóa
Cấu hình hệ thống
-
NixOS và Flakes
- Trong ví dụ
nixosConfigurationscủa Flakes,nixpkgs.lib.nixosSystemnhận danh sách module NixOS để tạo ra một full system derivation bao gồm kernel, services, config files, v.v. - Lệnh ví dụ để triển khai NixOS dựa trên Flake là
nixos-rebuild switch --flake .#myhost - Ví dụ
nixosConfigurations.myhostbao gồmsystem = "x86_64-linux";vàmodules = [ ./configuration.nix home-manager.nixosModules.home-manager ]; - NixOS modules là một hệ thống module dùng cơ chế gộp theo mức ưu tiên thông qua
options,config,mkIf,mkDefault,mkForce - Hệ thống module của NixOS giải quyết mức ưu tiên ngay cả khi nhiều module cùng thiết lập một option, nên dễ tránh xung đột dù hàng chục module cùng đóng góp vào một cấu hình
- Trong ví dụ
-
Guix
operating-systemoperating-systemcủa Guix là một Scheme record chứ không phải function; mỗi field là một giá trị có tên và kiểu, được Guix kiểm tra hợp lệ- Lệnh ví dụ để triển khai hệ thống Guix là
guix system reconfigure config.scm - Ví dụ record
operating-systembao gồm(host-name "myhost"),(timezone "Etc/UTC"), cấu hình bootloader, file systems và services - Ví dụ cấu hình bootloader của Guix dùng
grub-efi-bootloadervới target"/boot/efi"; Guix hỗ trợ GRUB, U-Boot, v.v. - File systems của Guix được khai báo dưới dạng danh sách, còn
%base-file-systemscung cấp mặc định cho/dev,/proc,/sys, v.v. - Services của Guix tạo thành directed acyclic graph (DAG), và mỗi service có thể mở rộng các service khác
%base-servicescung cấp các service thiết yếu như Shepherd init system, syslog, networking, v.v.- Cấu hình hệ thống Guix không cần special output type; chỉ cần chỉ định cho
guix systemmột file trả về recordoperating-system - Cách kết hợp service của Guix giúp dễ viết service mới để nối vào hệ thống hiện có theo những cách linh hoạt
Khả năng khám phá và registry
- Flakes có
flake.nix, một điểm vào tiêu chuẩn để khai báo dependency của dự án, output và schema có thể khám phá được trong một file - Dự án Guix có thể dùng các file theo quy ước như
manifest.scm,channels.scm,guix.scm,package.scm - Có nỗ lực chuẩn hóa
guix.scmthành file dự án màguix shelltự động nhận diện, nhưng nó chưa được thiết lập vững chắc nhưflake.nix - Flakes có registry toàn cục flake-registry để ánh xạ tên ngắn sang URL; ví dụ gồm
nix run nixpkgs#hello,nix build github:NixOS/nixpkgs#firefox - Guix dùng package specification để có sự tiện lợi tương tự, ví dụ
guix shell hello,guix install firefox - Guix không có đối tượng tương đương registry để trỏ một kho Git bất kỳ bằng tên ngắn, mà dùng trực tiếp URL
- Nix registry từng là nguồn gây nhầm lẫn vì không phải lúc nào cũng rõ
nixpkgslà một mục registry, một đường dẫn cục bộ hay một mục tiêu khác nix flake showlà lệnh hiển thị mọi mục mà một flake cung cấp dưới dạng tree view- Guix có
guix searchcho package vàguix system searchcho service, nhưng không có lệnh tương ứng để hiển thị mọi mục mà một dự án hay repository cụ thể cung cấp; phải tự xem các file Scheme - Flakes có khả năng khám phá mạnh vì
nix flake showcho một cái nhìn nhất quán về những gì project cung cấp - Các dự án Guix mang tính ad-hoc hơn; bạn cần biết phải xem file nào và không có file điểm vào duy nhất được chuẩn hóa
- Guix có tính linh hoạt mạnh vì mọi thứ đều là Scheme, nên có thể định nghĩa và kết hợp bất cứ thứ gì mà không cần schema
Mô hình gói và viết lại đồ thị
- Trong Nix, gói là một hàm trả về derivation thông qua lời gọi
stdenv.mkDerivation { ... }, và kết quả đó là một tập thuộc tính mờ - Trong Guix, gói là một bản ghi
<package>, tức một cấu trúc dữ liệu minh bạch với các trường được đặt tên, nên có thể được kiểm tra, biến đổi và kết hợp bằng các thủ tục Scheme tiêu chuẩn - Các định nghĩa gói của Guix là các bản ghi minh bạch chứ không phải các hàm mờ, nên có thể thực hiện inspect và transform bằng chương trình mà không cần công cụ đặc biệt
- Trong Guix, vì packages là dữ liệu nên có thể dễ dàng thực hiện graph rewrites
- Trong Guix,
package-input-rewritingcó thể biểu diễn việc duyệt toàn bộ đồ thị phụ thuộc để thayperlbằngperl-minimal - Từ khóa
inheritcủa Guix định nghĩa lại một gói bằng cách kế thừa mọi trường củacoreutilsvà chỉ ghi đè các trường được chỉ định - Nix có overlays với mục đích tương tự, nhưng do giao diện hàm mờ nên việc kiểm tra và biến đổi khó hơn, khiến tính tiện dụng kém hơn
Cập nhật bảo mật, bootstrap, xác thực
- grafting của Guix cho phép áp dụng các bản cập nhật bảo mật vào cây phụ thuộc mà không cần build lại mọi gói phụ thuộc
- Khi các thư viện cấp thấp như glibc có lỗ hổng, Guix có thể viết lại các đường dẫn trong kho lưu trữ để thay bằng phiên bản đã vá
- Nix build lại mọi thứ trong tình huống cập nhật bảo mật, và với các cây phụ thuộc lớn thì thời gian build có thể chênh nhau tới hàng giờ
- Guix tập trung mạnh vào bootstrap dựa trên mã nguồn, cho phép build toàn bộ hệ thống từ một nền tảng tin cậy rất nhỏ
- Chuỗi bootstrap của Guix bắt đầu từ một hex assembler khoảng 500 byte, rồi tới trình biên dịch C
mesviết bằng Scheme,tcc, và toàn bộ GNU toolchain - Dự án bootstrappable builds bao quát các chi tiết đầy đủ về bootstrap toàn bộ từ mã nguồn
- Nix phụ thuộc vào nhiều binary seed hơn Guix
- Nếu không thể kiểm toán chuỗi bootstrap thì không thể xác minh hoàn toàn rằng hệ thống thực sự được build từ đúng mã nguồn dự định, vì vậy bootstrap toàn bộ từ mã nguồn rất quan trọng đối với độ tin cậy và khả năng kiểm chứng
- Guix channels hỗ trợ xác thực bằng mật mã theo mặc định
- Một Guix channel chỉ định một “introduction” gồm một commit cụ thể và chữ ký Ed25519 của nó, và Guix xác minh toàn bộ chuỗi chữ ký từ introduction đó đến commit hiện tại
- Flakes dùng HTTPS và hạ tầng GitHub làm mô hình tin cậy, đây là mô hình bảo mật khác với channel authentication bằng Ed25519 của Guix
Các đối ứng chính trong bảng tóm tắt
- Khai báo phụ thuộc: Flakes dùng
inputstrongflake.nix, còn Guix dùngchannels.scmvà.guix-channel - Cố định phụ thuộc: Flakes dùng
flake.locktự động theo từng dự án, còn Guix dùngguix describetự động theo từng người dùng vàchannels.scmchỉ định commit thủ công theo từng dự án - Đánh giá thuần được ép buộc trong flake mode, còn trong Guix đây là đặc tính vốn có theo thiết kế
- Lược đồ đầu ra: Flakes dùng attrset có cấu trúc trong
outputs, còn Guix dùng các Scheme record ad-hoc - Môi trường phát triển: Flakes dùng
devShellsvànix develop, còn Guix dùngmanifest.scmvàguix shell - Cấu hình hệ thống: Flakes dùng
nixosConfigurationsvà hệ thống module, còn Guix dùngoperating-systemvà DAG dịch vụ - Tính tái lập bằng một lệnh: Flakes có
nix build github:foo/bar, còn Guix có dạngguix time-machine -C channels.scm -- build - Cố định theo từng dự án: Flakes xử lý tự động bằng
flake.lock, còn Guix xử lý thủ công bằngchannels.scmcó chứa commit - Khả năng khám phá: Flakes dùng
nix flake show, còn Guix dựa vào việc kiểm tra module Scheme - Mô hình gói: Flakes/Nix là hàm mờ, còn Guix là record minh bạch
- Hệ thống init: Nix dùng systemd, còn Guix dùng GNU Shepherd
- Cập nhật bảo mật: Nix build lại toàn bộ, còn Guix dùng grafting nhanh
- Độ tin cậy bootstrap: Nix dựa vào binary seed, còn Guix dựa trên bootstrap toàn bộ từ mã nguồn
- Cập nhật có xác thực: Flakes dùng mô hình tin cậy HTTPS/GitHub, còn Guix dùng channel authentication bằng Ed25519
- Hỗ trợ FHS: Nix cung cấp
buildFHSUserEnv, còn Guix cung cấp--emulate-fhs - Hỗ trợ ngoài Linux: Nix có nix-darwin cho macOS, còn Guix được tổ chức quanh GNU Hurd
- Việc chỉ dùng phần mềm tự do: Nix không bắt buộc và có thể cấu hình, còn Guix tuân thủ FSDG
Kết luận
- Flakes và Guix giải quyết cùng một loại vấn đề về tính tái lập, quản lý phụ thuộc và khai báo hệ thống, nhưng với các triết lý kiến trúc khác nhau
- Flakes gần như là một tính năng đơn lẻ với một tệp, một lược đồ, một tệp khóa và một tập quy ước
- Guix là sự kết hợp của các công cụ trực giao như channels cho phân phối, manifests cho môi trường,
operating-systemcho cấu hình,guix time-machinecho tính tái lập, và các Scheme record cho những cấu trúc khác - Nếu bạn thích một cách chuẩn duy nhất, một tệp điểm vào duy nhất, một lược đồ đầu ra duy nhất và một định dạng khóa duy nhất, thì Flakes là lựa chọn tự nhiên
- Nếu bạn thích cách kết hợp các công cụ nhỏ, độc lập để mỗi công cụ làm tốt một việc theo triết lý Unix áp dụng vào quản lý gói, thì Guix sẽ phù hợp hơn
- Hai hệ sinh thái này phát triển xoay quanh ý tưởng rằng quản lý gói nên mang tính hàm, khai báo và có thể tái lập, và đang thúc đẩy cùng một ý tưởng đó bằng các cách triển khai khác nhau
1 bình luận
Ý kiến trên Lobste.rs
Trang này đọc trên di động quá khó chịu: chữ hơi nhỏ, và cứ cuộn là lại bị quấy rầy
Sau phần so sánh đầu tiên thì tôi không đọc nổi nữa, vì nó cứ bật ngược lên mục lục
Đọc xong bài mà tôi vẫn chưa hiểu rõ phải chỉ định và cố định dependency của dự án như thế nào. Nếu muốn phát hành và chia sẻ thì có vẻ phải tự tìm rồi điền commit hash của từng dependency bắc cầu vào
channels.scmtime-machinecó vẻ chỉ hoạt động với tập gói Guix, chứ không áp dụng cho dependency ngoài câyBạn cũng có thể chạy mã ở một thời điểm cũ của nixpkgs khá dễ, kiểu
nix run github:nixos/nixpkgs/<commit hash>#<package>Điểm lạ của Guix là nó không tách phiên bản bộ sưu tập gói với phiên bản trình quản lý gói. Muốn chạy gói cũ thì cũng sẽ chạy luôn cả bản phát hành Guix cũ, mà tôi không hiểu vì sao lại muốn thế
Bài viết nói flakes phải tự tìm commit để chỉ định thủ công, rồi ngay sau đó lại đưa ví dụ một lệnh Guix cũng phải chỉ định commit. Trong Nix flake cũng có thể ghi đè phiên bản nixpkgs bằng
--override-input, nhưng khá bẩn, nên đó cũng là một trong những điểm unflake đang cố cải thiệnThông thường bạn phát triển trong một môi trường
guix shellriêng, rồi đến lúc cần chia sẻ thì dùngguix describe -f channels > channels.scmđể ghi toàn bộ commit hash vàochannels.scmXem tài liệu declaring channel dependencies thì có thể chỉ định commit của dependency, nhưng có vẻ không có tùy chọn nào để xác minh rằng khi dependency đó lại có dependency tiếp thì phía bên kia cũng đã được cố định vào commit cụ thể
Ký hiệu
--commit=củatime-machineáp dụng cho kênh Guix, nhưng cũng có thể nạp thêm kênh từ tệp bằng-CĐiều này có lợi ở chỗ dù có thay đổi phá vỡ tương thích trong trình quản lý gói và bản ghi gói, bạn vẫn không mất lịch sử và tính tái lập
Tuy vậy, vì phải checkout nixpkgs ở từng commit nên chi phí xây dựng ban đầu sẽ rất lớn. Sau khi làm xong thì chi phí duy trì chỉ mục có lẽ sẽ thấp
Tôi đã báo cho coopi về vấn đề của trang và cả thread này, hy vọng sớm được sửa
Từ góc nhìn nghiêng hẳn về Guix, tôi cũng thấy như coopi nói, sẽ rất hay nếu Guix có một tệp/thư mục chuẩn giống Nix, kiểu một
flake.nixhoặc một thư mụcnix, để chứa mọi thứ. Nhưng có thể điều đó là bất khả thi vì muốn import mô-đun Scheme thì phải chỉ đúng đường dẫnBài Lobsters này đã chứa những gì tác giả muốn nói, nên có vẻ chỉ cần các thẻ
nixvàlisplà đủlinux. Đó là kernel duy nhất mà hai bên cùng có mà :P cònunixthì đúng là có thể không hợp như bạn nóiVí dụ kiểu thế này: Và cũng nên có lệnh
guix channelđể hỗ trợ tạo và quản lý kênh mớiTôi tò mò không biết Guix có tính năng ghi đè giá trị cố định của dependency bắc cầu như
.inputs.nixpkgs.followstrong Nix flake hay khôngNgoài ra, phần lớn mô tả của tác giả về Guix khiến tôi liên tưởng đến Nix thời trước flakes: không có điểm vào tiêu chuẩn, cấu trúc dùng kênh, v.v. Dù vậy, trong Guix có hệ thống định dạng và một ngôn ngữ thực sự, nên cùng một kiểu mẫu có lẽ bớt đau đầu hơn. Cảm giác như một dòng lịch sử thay thế đã có thể xuất hiện nếu Nix tốt hơn hoặc dùng ngôn ngữ khác
Tôi ngại giới thiệu bài này vì các vấn đề về khả năng sử dụng mà bình luận khác đã chỉ ra. Tôi dùng NoScript với mặc định tắt JavaScript nên không nhận ra
Dù vậy, bài này đến đúng lúc. Công ty tôi đang đi theo hướng dùng Nix rất nhiều và chúng tôi hơi vật lộn với flakes, mà phần giải thích trong bài này rõ ràng hơn hẳn những gì tôi từng đọc trước đó
Đây là phản hồi của Coopi: sáng nay có thay đổi nhưng vì công việc nên chưa kịp kiểm thử, và hóa ra là JavaScript có vấn đề
Trang này không dùng được trên iOS mobile. Có vẻ trang được tải ở phía dưới rồi ngay lập tức cuộn lên trên, và nếu tôi cuộn xuống quá một màn hình thì có gì đó bị kích hoạt và lại kéo ngược lên trên
Chế độ đọc vẫn hoạt động, nhưng phần tô sáng và các chi tiết kiểu dáng vốn khá ổn thì biến mất
Nói rằng những gì flakes làm cũng có thể làm bằng nhiều công cụ khác nhau của Guix là hợp lý, nhưng cũng nên chỉ ra rằng Nix từ lâu đã có và đến giờ vẫn có những công cụ nhỏ, trực giao để giải quyết cùng các vấn đề đó
Điều flakes mang lại là điểm vào dự án tiêu chuẩn và hệ sinh thái mà điều đó cho phép, ví dụ như registry. Bài viết cũng nói Guix không có phần này
Người dùng Guix có thể cho rằng không cần điểm vào tiêu chuẩn, và nhiều người dùng Nix từ trước đến nay cũng nghĩ vậy
Nhưng nói rằng có thể làm được flakes bằng một bộ công cụ trực giao thì nghe hơi giống lập luận rằng FreeBSD không cần hỗ trợ OCI vì jail là đủ cho mọi nhu cầu. Nó bỏ qua chuyện chính sự chuẩn hóa mới tạo điều kiện cho hệ sinh thái hình thành
Tôi rất quan tâm đến Guix và cũng đã đóng góp đôi chút, nên muốn so sánh vì sao việc build bằng
guix time-machinecùng vớichannels.scmlại chậm hơn nhiều so với việc đổi giá trị cố định của flake rồi đánh giá Nix. Nếu chỉ chậm khoảng 3 lần, ví dụ từ 5–10 giây thành 15–30 giây, thì tôi vẫn chấp nhận được, nhưng khi tôi thử thì còn cách rất xa mức đó