Bản dựng tái lập của NixOS: tái dựng độc lập thành công ISO cài đặt tối thiểu
(discourse.nixos.org)- ISO cài đặt tối thiểu của NixOS đã được tái dựng độc lập và giống hệt từng bit với bản phân phối của Hydra, cho thấy có thể xác minh sự khớp giữa nhị phân phân phối và mã nguồn
- Lần xác minh này tái lập không chỉ các gói có trong ISO mà cả chính quá trình tạo ISO, kiểm tra phạm vi rộng hơn so với việc chỉ tái lập từng gói
- Việc tái dựng bắt đầu từ NixOS 20.03 VirtualBox appliance, sử dụng revision
63678e9f3d3acủanixpkgs, và tắt phụ thuộc vào bộ nhớ đệm nhị phân bằng--option substitute false - Nếu OVA năm 2020 hoặc
gitđược tải xuống có backdoor tinh vi, chúng vẫn có thể là vector tấn công, nên việc xác minh dựa trên một hệ thống được bootstrap hoàn toàn vẫn còn là việc cần làm - Tái dựng ISO tối thiểu là một cột mốc quan trọng, nhưng các nhiệm vụ tiếp theo là loại bỏ những giải pháp vòng tạm thời, tái lập thêm nhiều phương tiện cài đặt, xây dựng hạ tầng tái dựng độc lập định kỳ và công cụ chứng minh bản dựng
Khả năng tái lập được xác minh từ ISO tối thiểu
- Đã build lại độc lập
nixos-minimalISO build do Hydra công bố và thu được kết quả giống hệt từng bit - Phạm vi tái lập được chia thành hai trục
- Tất cả các gói đi vào ISO
- Chính quy trình build tạo ra ISO
- Các gói cần thiết để build ISO nhưng không nằm bên trong ISO cũng được build cùng, và không phụ thuộc vào nhị phân đã được cache
- Build có thể tái lập cung cấp một đường tin cậy để kiểm tra liệu nhị phân phân phối có trung thành với mã nguồn hay không, và có bị sửa đổi trong pipeline build như Hydra hay không
Quy trình tái dựng và giới hạn
- Việc tái dựng được thực hiện bằng cách khởi động NixOS 20.03 trong một VirtualBox appliance mới
- Cấp đủ CPU và bộ nhớ, rồi mở rộng đĩa lên khoảng 65GB
- Sau khi cài
git, clonenixpkgsvà checkout revision63678e9f3d3a - Với
--option substitute false, build các mục cần thiết trên máy cục bộ thay vì lấy từ bộ nhớ đệm nhị phân
- Quy trình có bao gồm các biện pháp tạm thời để né các vấn đề đã biết
- Vẫn còn các giới hạn về mặt niềm tin chuỗi cung ứng
- Nếu OVA năm 2020 hoặc
gitđược tải xuống có backdoor tinh vi, chúng vẫn có thể là vector tấn công - Sẽ tốt hơn nếu tái dựng trên một hệ thống được bootstrapped hoàn toàn, nhưng hiện vẫn chưa đạt tới giai đoạn đó
- Tiến triển liên quan đang tiếp tục trong thread dự án bảo mật chuỗi cung ứng nixpkgs
- Nếu OVA năm 2020 hoặc
Khác biệt giữa công bố năm 2021 và kết quả lần này
- Năm 2021 từng có công bố rằng ISO tối thiểu có thể tái lập 100%, nhưng khi đó mới chỉ tái lập riêng lẻ các gói cần cho build ISO, còn việc tái dựng ISO thực tế vẫn có khác biệt
- Nguyên nhân là các vấn đề còn tồn tại trong cache của Hydra và cách tạo ISO
- Sau đó, trong lúc các vấn đề được sửa, lại xuất hiện các hồi quy như vấn đề upstream của Python 3.10, và phải đến tuần này toàn bộ chuỗi mới trở lại trạng thái có thể xác minh
- Bước tiếp theo là loại bỏ các giải pháp vòng tạm thời, tái lập nhiều gói hơn, và tái lập các phương tiện cài đặt khác như Gnome ISO
- Cũng cần hạ tầng tái dựng độc lập định kỳ và các công cụ chia sẻ, tiêu thụ chứng minh bản dựng như trustix
1 bình luận
Các ý kiến trên Hacker News
Việc build lại ISO tối thiểu từ mã nguồn là một cột mốc ấn tượng trên hành trình hướng tới một hệ thống có thể build tái lập được dựa trên mã nguồn
Guix gần đây cũng đạt được một thành tựu trực giao nhưng ấn tượng không kém trên cùng hành trình: bootstrap toàn bộ toolchain compiler từ một binary 357 byte duy nhất có thể tái lập, không cần các blob compiler binary khác
Có lẽ một ngày không xa, hai hướng này sẽ được kết hợp để có thể build tái lập toàn bộ bản phân phối từ mã nguồn
https://guix.gnu.org/en/blog/2023/the-full-source-bootstrap-...
Điểm cốt lõi mà nhiều người không hiểu là mục tiêu không phải chứng minh rằng sản phẩm đầu ra đáng tin 100%, mà là chứng minh rằng sản phẩm đầu ra trung thành 100% với mã nguồn
Nghĩa là nếu phát hiện chuyện đáng ngờ như một backdoor bí mật, ta sẽ luôn có thể tái lập nó một cách dứt khoát
Về phía kẻ xấu, điều đó đồng nghĩa không còn chỗ để chạy, cũng không còn nơi để trốn
Có lẽ có thể tự tay ghi tài liệu cho toàn bộ 357 byte mã máy để con người hiểu được
Có thể đây là câu hỏi ngớ ngẩn vì tôi chưa từng làm việc kiểu này, nhưng tôi thắc mắc tại sao khả năng tái lập không phải là hành vi mặc định
Nếu đã biên dịch hai bản phần mềm từ cùng một mã nguồn, tôi không rõ điều gì ngăn chúng trở nên hoàn toàn giống nhau mỗi lần
Tôi biết có nhiều thành phần chuyển động, nhưng vẫn chưa thật sự hiểu khác biệt phát sinh như thế nào
Có thể xem danh sách các vấn đề thường gặp tại đây: https://reproducible-builds.org/docs/
Nhìn chung, điểm mấu chốt là các developer không kiểm thử xem build có tái lập được hay không
Nếu việc này được đưa vào kiểm thử release, thường thì nó sẽ tiếp tục được duy trì ở trạng thái tái lập được
Các ví dụ điển hình khiến build trở nên không tái lập một cách rõ ràng là timestamp và thông tin tác giả
Cũng có những chỗ âm thầm phá vỡ khả năng tái lập mặc định; chẳng hạn nhiều runtime không định nghĩa thứ tự các mục trong hashmap, và compiler đôi khi duyệt hashmap đó để tạo binary
Có thể có những tác vụ không độc lập với thứ tự, và tùy trạng thái CPU mà binary tạo ra hơi khác nhau, dù tất cả đều là kết quả đúng
Đôi khi nguyên nhân cũng là metadata phụ thuộc vào thời gian hoặc môi trường, hay thứ tự thực thi của thread
Xin lỗi vì tôi không rành, nhưng tôi từng nghĩ một trong những lý do chính để NixOS tồn tại là khả năng tái lập
Tôi tưởng những vấn đề như thế này đã được giải quyết rồi
Tôi chỉ dùng NixOS khoảng 2 giờ và muốn thử Hyprland; vì Hyprland cần cấu hình đôi chút nên tôi nghĩ dùng cấu hình của người khác trên NixOS sẽ dễ hơn so với các distro khác
Nhưng việc tìm cấu hình cũng khó, tôi tìm được khoảng 3 gist ngẫu nhiên trên GitHub nhưng không cái nào chạy, nên đã bỏ cuộc
Vì không phụ thuộc vào toàn bộ môi trường hệ thống như các distro thông thường, trong nhiều trường hợp nó đã tạo ra cùng một binary mỗi lần
Tuy nhiên bản thân quá trình build ở nhiều package có thể không mang tính quyết định, nên chỉ điều này không lập tức đem lại khả năng tái lập hoàn toàn
Nghĩa mà bạn đang nghĩ đến là khi dễ dàng build lại các package binary thì dùng cùng phiên bản dependency, cùng tùy chọn build, v.v.
Tức là không nên phát sinh lỗi biên dịch mới kiểu “trên laptop của tôi thì chạy được”
Nghĩa đang được nói ở đây là mọi artifact build trở thành binary giống nhau tới từng byte
Nó không được phụ thuộc vào tên máy, thời điểm biên dịch, thứ tự các file hoàn tất biên dịch trong build song song, v.v.; và hướng này khó hơn rất nhiều
Nếu chưa quen, thì trong tình huống “tôi muốn thứ gì đó chạy được ngay bây giờ”, nó gần như không phải là công cụ nên chọn
Khi nói “tái lập được” trong NixOS, ý nghĩa gần hơn là “với cùng mã Nix, có được cùng hành vi chương trình”
Nó giống với điều mọi người kỳ vọng ở Dockerfile, ở mức nhằm giải quyết các vấn đề như “trên máy tôi thì chạy được” hoặc “lần trước thì chạy được”
Trong khi đó, “build tái lập được” nhắm tới việc artifact được tạo trên các máy khác nhau giống nhau tới từng bit
Nhờ vậy có thể xác minh code có được build từ một tập mã nguồn cụ thể hay không, tạo thêm một lớp bảo mật
Tôi cũng tò mò bạn đã dùng từ khóa tìm kiếm nào khi tìm cấu hình
Tìm “nixos configuration” thì có các kết quả như https://github.com/search?q=nixos%20configuration&type=repos..., và chỉ riêng Hyprland cũng thấy khá nhiều như https://github.com/search?q=wayland.windowManager.hyprland&t...
Nên xem https://github.com/donovanglover/nix-config
Đây là cấu hình dựa trên Flake, có Hyprland và nhiều thứ khá ổn
Hiện tại NixOS không phải là công cụ phù hợp cho người yếu tay hoặc người thiếu thời gian
Hy vọng một ngày nào đó điều này sẽ thay đổi, nhưng nếu chịu khó vượt qua thì sẽ nhận được lợi ích
Không rõ bạn có dùng GitHub code search không
Có thể tìm các tùy chọn Home Manager liên quan ở đây: https://mipmip.github.io/home-manager-option-search/?query=h...
Sau đó tìm trên GitHub là được: https://github.com/search?utf8=%E2%9C%93&q=lang%3Anix+hyprla...
Một số tìm kiếm tùy chọn có thể gợi ý theo hướng người dùng casual hơn hoặc cao cấp hơn
Cần nhớ rằng tính tái lập của Nix / NixOS / Nixpkgs là tính tái lập của nguồn
Nếu nguồn thay đổi thì bạn sẽ được cảnh báo, nhưng điều đó khác với tính tái lập của binary, vốn có thể khác đi sau mỗi lần build
Tính tái lập binary của Nix / NixOS / Nixpkgs, ít nhất là về mặt hệ thống, thường không được kiểm thử kỹ
Guix, Arch Linux, Debian xử lý tính tái lập binary tốt hơn Nix / NixOS / Nixpkgs
Tài liệu: https://r13y.com/ (Nix*) / https://tests.reproducible-builds.org/debian/reproducible.ht... (Debian) / https://tests.reproducible-builds.org/archlinux/archlinux.ht... (Arch Linux) / https://data.guix.gnu.org/repository/1/branch/master/latest-... (Guix, có thể tải chậm; bản cache là https://archive.is/lTuPk)
Tính tái lập đầu vào nghĩa là “vô hiệu hóa cache hoàn hảo đối với đầu vào”
Nix và Guix làm điều này hoàn hảo theo thiết kế, và đôi khi còn gây ra quá nhiều lần rebuild
Debian và Arch Linux không xem đây là mối quan tâm chính, và xử lý vấn đề gói nào cần build lại khi một file nguồn cụ thể được cập nhật bằng các cách tạm thời như trigger rebuild thủ công
Tính tái lập đầu ra nghĩa là “quy trình build mang tính xác định và luôn tạo ra cùng một binary”, đây là chủ đề của bài gốc
Nix build package trong sandbox nên có ích, nhưng không phải giải pháp vạn năng
Ở điểm này Nix cũng cùng hội cùng thuyền với Debian và Arch Linux
Trên thực tế, các bản phân phối thường gửi patch giúp tăng tính tái lập lên upstream, và các bản phân phối khác cũng được hưởng lợi
Trong ngữ cảnh này, https://reproducible.nixos.org là đối ứng với các liên kết khác đã nêu; tôi đồng ý rằng báo cáo của Nix ít chi tiết hơn, nhưng điều đó không có nghĩa tính tái lập binary của Nix tệ hơn
Nếu đọc thành “Nix chỉ giỏi tính tái lập đầu vào, còn tính tái lập binary thì không giỏi” thì đó là sai
Chính cột mốc đó mới là điều đang được chúc mừng ở đây
Bài này không chỉ nói về binary, mà còn nói đến việc tái lập theo từng bit cả cách chúng được đóng gói thành ISO
r13y.com đã lỗi thời, và nếu nhớ không nhầm thì phần thiếu dưới 1% cũng là do một regression Python ở upstream
Tính tái lập của bản thân binary, nếu loại trừ phần đóng gói ISO, đã đạt được từ vài năm trước
Khi đi ra ngoài các package thuộc ISO lõi, việc so sánh trở nên phức tạp
Cách xử lý package có những khác biệt tinh tế nhưng quan trọng trong ngữ cảnh này; nhiều package kiểu có thể nằm trong AUR của Arch thì ở Nix lại là package thông thường, và phần lớn các package upstream dạng -bin đơn giản là không cần thiết trong Nix
Nhìn chung Nix giúp dễ tạo các build tái lập hơn, nhưng không phải lúc nào cũng khả thi bất kể Nix, và thường cần patch
Cộng thêm việc kho package mặc định của Nix có hơn 80.000 package, trong khi Arch có dưới 15.000 nếu không tính AUR, thì so sánh theo phần trăm không hữu ích lắm
Một hiểu lầm rất phổ biến là nghĩ rằng hash trong đường dẫn Nix store dựa trên output của build, nhưng thực ra nó dựa trên toàn bộ tất cả source và input dùng để build binary trong môi trường cô lập, bất kể đó có phải binary hay không
Vì vậy nó không đem lại đúng các lợi ích bảo mật mà mọi người kỳ vọng, nhưng đổi lại cho phép cả phần mềm không build tái lập được vẫn có thể dùng dưới dạng phân phối tương đối tái lập, với tính năng, thiết lập compiler, phiên bản dependency, user, cấu hình... giống nhau
Tức là kiểm tra xem khi build cùng một source trên các máy khác nhau thì binary có giống nhau không
Điểm chính là binary không thay đổi sau mỗi lần build
Cách test cũng nói rằng mỗi build được chạy hai lần ở các thời điểm khác nhau, trên phần cứng khác nhau và kernel khác nhau
Nhìn thì thấy ghi là tái lập được 85,6%: https://reproducible.archlinux.org
Không biết với NixOS, nơi có hơn 80.000 package trong repository chính thức, sẽ cần bao nhiêu công sức
Nếu xét mục tiêu hay thực tế của nixpkgs thì điều này hoàn toàn không đúng
Bài gốc nói về việc tái tạo một ISO tối thiểu dạng nhị phân chứa nhiều gói nhị phân
Thật mỉa mai đến buồn cười khi dự án OpenBSD đang miệt mài đi theo hướng hoàn toàn ngược lại
OpenBSD có các offset địa chỉ duy nhất và được ngẫu nhiên hóa cho mỗi lần cài đặt
Tôi hiểu rằng hai mục tiêu bản dựng tái lập được và bản cài đặt độc nhất là trực giao với nhau và có thể đạt được đồng thời, nhưng tính hai mặt này vẫn buồn cười
Hoặc cũng có thể ngẫu nhiên hóa offset khi chương trình khởi động để tăng bảo mật trong khi vẫn giữ được khả năng tái lập
Khi đó offset sẽ thay đổi mỗi lần chạy
Bản thân gói vẫn có thể tái lập được
Toàn bộ việc ngẫu nhiên hóa được thực hiện cục bộ sau khi tải gói xuống và xác minh checksum
Giờ thì tôi chỉ mong người bảo trì ký các gói, giống như gần như mọi bản phân phối Linux khác đã làm từ thập niên 90
Như vậy mọi người mới có thể phần nào biết rằng mã mà họ build là cùng một mã do những cá nhân đã biết gửi lên và rà soát
Trước khi chữ ký được chuẩn hóa, thật khó tưởng tượng việc dùng Nix trong môi trường production để bảo vệ thứ gì đó có giá trị
Phần lớn họ không đưa ra bảo đảm nào về nội dung gói
Kỳ vọng một bảo đảm có ý nghĩa từ chữ ký của họ giống như kỳ vọng nhân viên giao hàng hỗ trợ sản phẩm vậy
Cũng không cần phải tin rằng gói không bị đóng gói với ý đồ xấu
Vì Nix có các bản dựng tái lập được, nếu không muốn phụ thuộc vào cache nhị phân thì cứ xem derivation và tự build
Nội dung cốt lõi có độc hại hay không rốt cuộc là vấn đề giữa nhà phát triển và người dùng
Nếu các bản phân phối khác khiến người ta tin điều ngược lại, tôi nghĩ đó gần như là sự gây hiểu lầm
Ngoại lệ tôi nghĩ đến là Tails, nhưng Tails không rộng như Nix
Nhìn thì có vẻ Debian không còn làm thế nữa mà hệ thống build ký vào bản build, Fedora cũng không làm, Arch thì không chắc nhưng có vẻ cũng không
Hệ thống build của NixOS ký tất cả artifact build bằng khóa riêng của nó và xác minh chữ ký khi tải xuống
Nếu tiếp cận theo kiểu hoang tưởng, ít nhất Nix cũng giúp dễ dàng build trực tiếp từ mã nguồn mọi thứ
Đây là một cột mốc rất ấn tượng, xin chúc mừng những người đã làm được điều này
Ngay cả khi thực sự build lại ISO vẫn có khác biệt, và nguyên nhân được nói là do các vấn đề còn lại trong cache Hydra và cách ISO được tạo
Tôi tự hỏi có ai có thể giải thích họ đã sửa “cách ISO được tạo” như thế nào không
Trước đây tôi từng thử tạo ISO tái lập được nhưng không thể khiến hệ thống tệp tạo extent một cách quyết định
Bước cuối của quá trình đó tạo ISO trong thư mục
./result/isoCó vẻ thứ bạn đang tìm là lệnh mà bản build đó gọi, nhưng tôi không rõ bạn muốn tìm bước nào
Ví dụ lời gọi
xorrisonằm ở đây: https://github.com/NixOS/nixpkgs/blob/master/nixos/lib/make-...Để làm được việc này chẳng phải phải đánh lừa thời gian hệ thống sao?
Thời gian thường đi vào binary theo cách này hay cách khác
Phổ biến đến mức nhiều compiler đã triển khai SOURCE_DATE_EPOCH, một biến gần như là chuẩn trên thực tế để giả lập timestamp: https://reproducible-builds.org/docs/source-date-epoch/
Điều này chẳng phải giúp giải quyết vấn đề Ken Thompson viết trong “Reflections on Trusting Trust” sao?
Nếu có thể bootstrap hoàn toàn toàn bộ hệ thống từ mã nguồn, có vẻ sẽ khó hơn để cài những thứ như compiler bị cắm backdoor
Về lý thuyết vẫn có thể có một backdoor tinh vi trong môi trường nơi ISO được build
Nếu thật sự muốn giải quyết vấn đề đó, có thể xem Diverse Double Compiling(https://dwheeler.com/trusting-trust/) hoặc bootstrap toàn bộ môi trường(https://bootstrappable.org/)
Mục “cách tiếp cận trên có vấn đề bootstrap không?” trong bài viết cũng liên quan
Dù vậy, chỉ riêng việc tái lập bản build cũng đã giúp rất nhiều trong việc khiến kiểu tấn công đó ngày càng ít khả thi hơn
Gần đây vì công việc nên tôi ở trong hệ sinh thái Red Hat
Tôi tò mò điều này so với những thứ như Fedora Silverblue, Ansible, Fedora Silverblue + Ansible thì thế nào
Imagebuilder tuyên bố có khả năng tái lập, nhưng theo tôi biết thì phần lớn rpm được cài dưới dạng gói nhị phân chứ không phải từ mã nguồn
Vì vậy nếu tất cả gói đầu vào cũng không tái lập được thì đó không phải khả năng tái lập theo nghĩa nghiêm ngặt
Nếu phần giải thích về build gói từ mã nguồn, tạo image bản phân phối và xử lý khả năng tái lập không thật sự hợp với bạn thì có lẽ bạn không phải độc giả mục tiêu chính
Trong khi đó Ansible chỉ định các bước mà OS cần làm theo
Silverblue và Nix, ngoài điểm chung là đều là bản phân phối Linux, thì về bản chất là hai hướng tiếp cận độc lập với nhau
Silverblue là một nỗ lực nhằm thay đổi cách phân phối phần mềm bằng cách chỉ dùng container trên một host bất biến
Nếu bạn đang tìm một lựa chọn thay thế Ansible mô phỏng Nix ở một mức độ nào đó bằng Jsonnet và theo dõi trạng thái, Etcha đáng để xem qua: https://etcha.dev
Nix thì bất biến
Thay đổi mới được tạo hoàn toàn mới, và chỉ sau khi build thành công thì tất cả package mới được “liên kết tượng trưng” vào hệ thống hiện tại
Fedora Silverblue dựa trên ostree https://github.com/ostreedev/ostree
Nó hoạt động giống git đối với cây root, nhưng để áp dụng thay đổi thì phải khởi động lại toàn bộ hệ thống
Nix dùng cách liên kết tượng trưng các package, nên không cần khởi động lại hệ thống
Có giải thích chi tiết hơn ở đây: https://dataswamp.org/~solene/2023-07-12-intro-to-immutable-...