source: at-w96k/content/posts/reproducible-builds.org~@ 6596178

Last change on this file since 6596178 was 6596178, checked in by Mikhail Kirillov <w96k@…>, on Apr 21, 2022 at 7:34:43 AM

Add guix page. Add Articles page.

  • Property mode set to 100644
File size: 33.9 KB
Line 
1#+TITLE: Воспроизводимые сборки на примере GNU/Guix
2#+DATE: <2020-01-21 Вт>
3#+LANGUAGE: ru
4
5#+LATEX_CLASS_OPTIONS: [article,10pt]
6
7#+BEGIN_EXPORT latex
8\setcounter{secnumdepth}{0}
9#+END_EXPORT
10
11* Воспроизводимые сборки на примере GNU/Guix
12 #+BEGIN_abstract
13 Эта обзорная статья рассматривает концепцию воспроизводимых
14 сборок. Она не затрагивает глубокие технические детали. В качестве
15 демонстрации используется пакетный менеджер GNU/Guix.
16 #+END_abstract
17
18 Воспроизводимая сборка также называется детерменированной
19 компиляцией [fn:determinational-build]. Сборка называется
20 воспроизводимой, если исходный код, программное окружение и
21 инструкции сборки будут давать на выходе побитово идентичные копии
22 всех артефактов.
23
24 Соответствующее программное окружение, инструкции сборки и исходный
25 код также как и ожидаемый воспроизводимый артефакт определены
26 авторами ПО или дистрибьюторами. Артефакты сборки -- это часть
27 сборки, которая является основным ожидаемым результатом.
28
29** Термины
30 - Исходный код :: Берется из системы контроля версий
31 определенной ревизии или архива.
32
33 - Соответствующие аттрибуты среды сборки :: Включают в себя
34 зависимости и их версии, флаги конфигурации сборки и
35 переменные окружения.
36
37 - Артефакты :: Являются исполняемыми файлами, пакетами
38 дистрибутива или образами файловой системы. Обычно
39 не содержат в себе логов сборки или похожих на логи
40 вещей. Воспроизводимость артефактов достигается
41 путём побитового сравнивания при помощи
42 криптографических хеш-функций [fn:hash-function].
43
44 - Авторы и дистрибьюторы :: Лица, которые утверждают
45 воспроизводимость артефактов. Они могут быть авторами ПО,
46 сопровождающими дистрибутива или иным лицом, распространяющим
47 ПО.
48
49** Почему воспроизводимые сборки важны
50 #+ATTR_HTML: :width 500px
51 #+CAPTION: Логотип движения за воспроизводимые сборки
52 [[https://reproducible-builds.org/assets/images/logo-text.svg]]
53
54 Не смотря на то, что каждый может исследовать исходный код
55 свободного и открытого ПО на наличие вредоносных дыр, большая часть
56 этого ПО распространяется в виде собранных исполняемых файлов без
57 методов проверки соответствия с исходным кодом.
58
59 Это стимулирует нападки на разработчиков, которые выпускают ПО, не
60 только посредством традиционного использования эксплоитов, но также
61 в форме политического влияния или шантажа.
62
63 Это особенно важно для разработчиков, создающих ПО, связанное с
64 приватностью и безопасностью: атака на это ПО, обычно
65 компроментирует политические цели таких как: инакомыслящие,
66 журналисты, информаторы, а также любого, кто желает использовать
67 безопасные от репрессивного режима каналы связи.
68
69 Не смотря на то, что отдельно взятые разработчики кажутся
70 естественной мишенью, под удар также попадают инфраструктуры для
71 сборки, которые при успешной атаке предоставляют доступ к большому
72 числу компьютерных систем. Модифицирование собранных исполняемых
73 файлов в сборочной инфраструктуре вместо модифицирования исходного
74 кода делает эти изменения практически невидимыми для оригинальных
75 авторов и пользователей программы.
76
77 Целью воспроизводимых сборок является возможность проверки на факт
78 наличия уязвимостей и дыр в безопасности в процессе сборки. Один и
79 тот же вход гарантирет один и тот же выход. Это позволяет понять
80 находится перед нами оригинальная правильная или
81 скомпроментированная неправильная сборка. Это позволяет
82 предотвращать такие угрозы и атаки как можно раньше, так как любое
83 изменение будет быстро обнаружено.
84
85** Как добиться воспроизводимости
86 Достижение воспроизводимости сборок требует сотрудничества
87 нескольких ролей в производстве ПО.
88
89*** Создание детерменированного окружения сборки
90 Чтобы ПО могло быть воспроизводимым, исходный код не должен
91 создавать неконтроллируемые вариации в логе вывода.
92
93 Будет лучше, если пользователи обнаружат вариации, которые выдают
94 невоспроизводимые исполняемые файлы. Создание протокола для
95 тестов, который бы пересобирал программу в нужной вариации, сильно
96 поможет.
97
98*** Определение окружения сборки
99 Разные версии утилит для сборки скорее всего выдадут разный
100 результат, пользователи должны быть в состоянии воссоздать
101 окружение сборки. Это не обозначает, что сами утилиты для сборки
102 должны быть побитово идентичными, вернее результат их работы
103 должен оставаться одинаковым.
104
105 Окружение сборки может быть определено, пока ПО только
106 разрабатывается или поверх существующего процесса сборки.
107
108*** Дистрибуция окружения сборки
109 Пользователи должны знать какое окружение должно быть воссоздано,
110 чтобы собрать ПО.
111
112 Если окружение сборки уже определено или является частью исходного
113 кода, то дальнейшие шаги не требуются.
114
115 В остальных же случаях, необходимо поместить описание рядом с
116 исполняемыми файлами о том, как воспроизвести окружение.
117
118*** Предоставление протокола сравнения
119 Пользователи должны иметь легкий способ воссоздания окружения
120 сборки, получения исходного кода, проведения процесса сборки и
121 сравнения результата.
122
123 В идеале протокол сравнения должен быть прост в сравнении
124 исполняемых файлов. Сравнение байтов и криптографических хешей
125 легко реализовать и воспринимать.
126
127** Как проверить воспроизводимость
128 Техника, используемая в воспроизводимых сборках, называется Diverse
129 Double-Compilation[fn:diverse-double-compilation] и создана она
130 David A. Wheeler.
131
132 Алгоритм примерно следующий:
133 - Собрать в первый раз
134 - Сохранить результат
135 - Сделать максимальное количество изменений окружения
136 - Собрать второй раз
137 - Сравнить результаты
138
139 [[https://diffoscope.org/][diffoscope]] -- утилита, которая разработана для обнаружения проблем
140 в сравнении результатов сборки.
141
142 Список вариаций:
143 - Дата и время
144 - путь сборки
145 - hostname
146 - domain name
147 - Файловая система
148 - Переменные окружения
149 - Часовой пояс
150 - Язык
151 - Локаль
152 - Имя пользователя
153 - ID пользователя
154 - Группа пользователя
155 - ID группы
156 - Версия ядра
157 - umask,
158 - Тип CPU
159 - Количество ядер CPU
160
161 [[https://tests.reproducible-builds.org/debian/index_variations.html][Пример вариаций в Debian]]
162
163 [[https://packages.debian.org/sid/disorderfs][disorderfs]] -- утилита, помогающая тестировать файловую систему в
164 воспроизводимой манере.
165
166** Воспроизводимые сборки в GNU/Guix
167
168 #+CAPTION: Логотип GNU/Guix
169 [[https://upload.wikimedia.org/wikipedia/commons/8/81/Guix_logo.svg]]
170
171 GNU/GUIX /(произносится гикс ɡiːks)/ — функциональный пакетный
172 менеджер и операционная система, разработанные Ludovic Courtès и
173 сообществом GNU. Отличительной особенностью является использование
174 воспроизводимых сборок и наличие только [[https://www.gnu.org/philosophy/free-sw.ru.html][свободного ПО]]. Guix можно
175 поставить на существующий дистрибутив GNU/Linux или в качестве
176 отдельной системы на базе Linux или GNU Hurd. Раньше существовало
177 разделение менеджера пакетов Guix и операционной системы GuixSD.
178
179 Определения пакетов описываются на диалекте языка Scheme –
180 [[https://www.gnu.org/software/guile/][GNU/Guile]]. Большая часть исходников написана на нём же. Система
181 изначально была основана на Nix. Отличиями от Nix(OS) являются язык
182 для описания пакетов и сервисов, система инициализации ([[https://www.gnu.org/software/guile/][GNU
183 Shepherd]]), использование ядра [[https://www.fsfla.org/ikiwiki/selibre/linux-libre/][Linux-Libre]] (Linux без проприетарных
184 блобов) и отсутствие проприетарных пакетов.
185
186 Все пакеты Guix собраны из исходников, включая различные прошивки
187 (firmware), которые имеют тенденцию быть представлены в виде
188 предсобранных исполняемых файлов без предоставления доступа к
189 исходному коду. В Guix возможно получение предсобранных исполняемых
190 файлов в виде [[https://guix.gnu.org/manual/ru/html_node/Podstanovki.html#g_t_041f_043e_0434_0441_0442_0430_043d_043e_0432_043a_0438][подстановок]]. Эти подстановки представляют из себя
191 программы, собранные на отдельных машинах (build farm), одинаковый
192 результат которых вы получите, если бы собирали их на своей машине.
193
194 Guix собирает пакеты в [[https://guix.gnu.org/manual/ru/html_node/Osobennosti.html][полностью изолированном программном
195 окружении]] для максимизации воспроизводимости -- это важнейшая
196 особенность, унаследованная от пакетного менеджера [[http://nixos.org/nix/][Nix]].
197
198 Таким образом возможно очень малое количество вариаций между
199 различными экземплярами окружений сборки; список доступных файлов в
200 окружении, имя хоста, переменные окружения, локаль и так далее
201 полностью под контролем и недоступны для изменения.
202
203 Единственное, что может различаться -- это ядро и железо. Самый
204 популярный пример того, как детали "железа" могут просочиться в
205 процесс сборки -- временная метка (timestamp). К сожалению это
206 очень частое явление, которое используется в выводе сборки.
207
208 Подробнее о преимуществах GUIX в статье [[https://www.opennet.ru/docs/RUS/guix/][«Guix: Самая совершенная
209 операционная система»]][fn:guix-best].
210
211 Существует русскоязычная [[https://t.me/gnu_guix_ru][конференция пользователей Guix в Telegram]].
212
213*** Установка Guix
214 Нам понадобится Guix в качестве пакетного менеджера, он
215 предоставляет все инструменты для воспроизводимых сборок. Я
216 подразумеваю, что вы использует GNU/Linux дистрибутив. Вы можете
217 установить Guix, используя пакетный менеджер вашего дистрибутива:
218
219 [[https://aur.archlinux.org/packages/guix/][Arch Linux]] | [[https://packages.gentoo.org/packages/sys-apps/guix][Gentoo]]
220
221 Если в вашем дистрибутиве нет готового пакета с Guix, то это не
222 проблема. Guix возможно установить на любой дистрибутив GNU/Linux,
223 единственное требование -- иметь программы GNU tar и Xz. Для этого
224 необходимо воспользоваться инструкцией «[[https://guix.gnu.org/manual/ru/html_node/Binarnaya-ustanovka.html][Бинарная установка]]».
225
226 При установке Guix создаст директории в следующих местах:
227 - ~/gnu/store/~
228 - ~/var/guix/~
229 - ~~/.guix-profile/~
230
231 В ~/gnu/~ помещаются все собранные программы в так называемый
232 ~store~. Если программа предполагается к установке, то сначала она
233 собирается в ~store~, а далее линкуется в ~~/.guix-profile/~ и
234 помещается в переменную окружения PATH. Много версий программ
235 может существовать на одной системе без конфликтов и хранится в
236 store. Неиспользуемые программы могут быть удалены сборщиком
237 мусора ~guix gc~.
238
239 В отличии от большинства системных пакетных менеджеров (apt, dnf,
240 pacman, portage) guix не требует доступа суперпользователя для
241 функционирования. Guix, будучи функциональным пакетным менеджером,
242 не использует состояние системы, поэтому ему не надо лазать в
243 системные директории, для которых нужны права суперпользователя.
244
245*** GNU Hello
246
247 Рассмотрим программу [[https://www.gnu.org/software/hello/][GNU Hello]]. Это небольшая hello-world
248 программа, написанная на языке Си в соответствии со стилем и
249 практиками проекта GNU. Найдём ее описание при помощи
250 ~guix show hello~.
251
252 #+BEGIN_SRC bash
253 w96k ~$ guix show hello
254 name: hello
255 version: 2.10
256 outputs: out
257 systems: x86_64-linux i686-linux
258 dependencies:
259 location: gnu/packages/base.scm:73:2
260 homepage: https://www.gnu.org/software/hello/
261 license: GPL 3+
262 synopsis: Hello, GNU world: An example GNU package
263 description: GNU Hello prints the message "Hello, world!" and then exits.
264 It serves as an example of standard GNU coding practices. As such, it
265 + supports command-line arguments, multiple languages, and so on.
266 #+END_SRC
267
268 Если не знаете название пакета, то используйте команду для поиска ~guix search~.
269
270*** Определение пакета
271 :PROPERTIES:
272 :CUSTOM_ID: package_definition
273 :END:
274
275 Определение пакета[fn:guix-package-definition] можно найти в файле
276 ~~/.config/guix/current/share/guile/site/2.2/~ + строка
277 location (~location: gnu/packages/base.scm:73:2~). Для простоты взаимодействия с системой существует мод
278 для редактора [[https://www.gnu.org/software/emacs/][Emacs]] -- [[https://emacs-guix.gitlab.io/][emacs-guix]]. Из него можно проще
279 навигироваться по системе.
280
281 Пакет GNU Hello в Guix определен следующим образом[fn:gnu-guix-hello]:
282
283 #+BEGIN_SRC scheme
284 (define-public hello
285 (package
286 (name "hello")
287 (version "2.10")
288 (source (origin
289 (method url-fetch)
290 (uri (string-append "mirror://gnu/hello/hello-" version
291 ".tar.gz"))
292 (sha256
293 (base32
294 "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
295 (build-system gnu-build-system)
296 (synopsis "Hello, GNU world: An example GNU package")
297 (description
298 "GNU Hello prints the message \"Hello, world!\" and then exits. It
299 serves as an example of standard GNU coding practices. As such, it supports
300 command-line arguments, multiple languages, and so on.")
301 (home-page "https://www.gnu.org/software/hello/")
302 (license gpl3+)))
303 #+END_SRC
304
305 Это определение написано на языке [[https://www.gnu.org/software/guile/][GNU/Guile]], диалекте лиспа
306 Scheme. Вам не нужно понимать тонкости языка, чтобы его
307 использовать в Guix. Как мы видим пакет описан декларативно.
308
309 Разберем это определение на составные части.
310
311 #+BEGIN_SRC scheme
312 (package
313 (name "hello")
314 (version "2.10")
315 ...
316 #+END_SRC
317
318 Имя и версия пакета.
319
320 #+BEGIN_SRC scheme
321 (package
322 ...
323 (source (origin
324 (method url-fetch)
325 (uri (string-append "mirror://gnu/hello/hello-" version
326 ".tar.gz"))
327 (sha256
328 (base32
329 "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
330 ...
331 #+END_SRC
332
333 Источник пакета и его хеш-сумма. Источником пакета может являться
334 как гит репозиторий, так и обычная ссылка на архив. Если хеш-сумма
335 не совпадает, то guix не установит пакет. Строка mirror заменяет
336 строку на url доступного зеркала[fn:guix-mirrors].
337
338 #+BEGIN_SRC scheme
339 (package
340 ...
341 (build-system gnu-build-system)
342 ...
343 #+END_SRC
344
345 Система сборки[fn:guix-build-systems]. В Guix существуют несколько систем сборки,
346 содержащие инструкции и окружение сборки. В данном случае
347 подразумевается, что система сборки запустит команды ~./configure
348 && make && make check && make install~ и будет иметь
349 соответствующие утилиты.
350
351 #+BEGIN_SRC scheme
352 (package
353 ...
354 (synopsis "Hello, GNU world: An example GNU package")
355 (description
356 "GNU Hello prints the message \"Hello, world!\" and then exits. It
357 serves as an example of standard GNU coding practices. As such, it supports
358 command-line arguments, multiple languages, and so on.")
359 (home-page "https://www.gnu.org/software/hello/")
360 (license gpl3+))
361
362 #+END_SRC
363
364 Синопсис, описание, домашняя страница и лицензия. Информация,
365 полезная при поиске пакета.
366
367 Также определение пакета может содержать зависимости ~inputs~,
368 ~native-inputes~ и ~propogated-inputs~, но в нашем случае пакет
369 hello не содержит зависимостей. Если бы зависимости были, то они
370 бы собрались раньше пакета и были бы добавлены в окружение, а
371 зависимости зависимостей собрались бы еще раньше. Таким образом
372 образуется дерево зависимостей. Например дерево зависимостей
373 программы ~grep~.
374
375 #+CAPTION: дерево зависимостей программы grep
376 [[../../public/images/grep.png]]
377
378 Вы можете создать такую же визуализацию командой ~guix graph
379 grep | dot -Tpng > grep.png~. Для выполнения нужен установленный
380 пакет ~graphviz~.
381
382*** Загрузка исходного кода
383 Создадим отдельную директорию для нашей демонстрации и
384 переместимся в нее:
385
386 #+BEGIN_SRC bash
387 mkdir hello
388 cd hello
389 #+END_SRC
390
391 Загрузим исходный код при помощи команды ~guix download~ и ссылки
392 на пакет из [[file:#package_definition][определения пакета]] (необходимо подставить версию):
393
394 #+BEGIN_SRC bash
395 guix download -o hello.tar.gz mirror://gnu/hello/hello-2.10.tar.gz
396
397 Starting download of hello.tar.gz
398 From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
399 following redirection to `https://mirror.tochlab.net/pub/gnu/hello/hello-2.10.tar.gz`
400 709KiB 5.2MiB/s 00:00 [##################] 100.0%
401 hello.tar.gz
402 0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
403 #+END_SRC
404
405 Мы получили файл hello.tar.gz в текущей директории. Последняя
406 строка вывода консоли -- это хеш-сумма, которую мы видели в
407 определении пакета.
408
409*** Создание детерминированного окружения
410 Детерминированное окружение одно из требований для создания
411 воспроизводимых сборок. Для создания изолированного окружения
412 воспользуемся командой ~guix environment~:
413
414 #+BEGIN_SRC bash
415 guix environment hello --container
416 #+END_SRC
417
418 Флаг ~--container~ использует возможность ядра [[https://ru.wikipedia.org/wiki/%D0%9A%D0%BE%D0%BD%D1%82%D1%80%D0%BE%D0%BB%D1%8C%D0%BD%D0%B0%D1%8F_%D0%B3%D1%80%D1%83%D0%BF%D0%BF%D0%B0_(Linux)][cgroups]], которая
419 может не поддерживаться вашим процессором. Если это так, то
420 используется вместо ~--container~ флаг ~--pure~.
421
422 Выполнив данную команду Guix скачивает необходимые программы для
423 окружения сборки и перемещает нас в него. То есть нам доступны
424 только непосредственно программы для сборки (gnu-build-system) +
425 при наличии зависимостей -- собранные зависимости.
426
427 Строка ~[env]~ говорит о том, что вы находитесь в изолированном
428 окружении. Чтобы выйти из окружения, используйте сочетание клавиш
429 ~C-d~. Для дальнейшей работы оставайтесь в изолированном
430 окружении.
431
432*** Сборка
433 Разархивируем архив при помощи ~tar~ и переместимся в папку с
434 исходным кодом:
435 #+BEGIN_SRC bash
436 tar -xf hello.tar.gz
437
438 ls
439 hello-2.10 hello.tar.gz
440 cd hello-2.10
441 #+END_SRC
442
443 Далее соберем проект из серии команд:
444 1. ~./configure~
445 2. ~make~
446 3. ~make check~
447 4. ~make prefix=./dist install~
448
449 И так мы получили в директории ~dist~:
450 #+BEGIN_SRC bash
451 cd dist; cd bin;
452 ./hello
453 Hello, world!
454 #+END_SRC
455
456 Теперь можно выйти из виртуального окружения, нажав ~C-d~.
457
458*** Сборка через пакетный менеджер
459 Теперь вы примерно понимаете как происходит процесс сборки. Всё
460 что мы сделали уже реализовано пакетным менеджером, для повторения
461 всей процедуры используем ~guix build~:
462
463 #+BEGIN_SRC bash
464 guix build hello --check
465 #+END_SRC
466
467 На самом деле данная команда использует дополнительные шаги, но
468 основные -- те, что мы уже выполнили.
469
470*** Установка через пакетный менеджер
471 Основная команда для взаимодействия с пакетами ~guix package~[fn:guix-package-command], но
472 есть удобные алиасы ~guix install~ для установки и ~guix remove~
473 для удаления. Попробуем установить пакет hello:
474
475 #+BEGIN_SRC bash
476 guix install hello
477 hello
478 Здравствуй, мир!
479 # Я использую русскую локаль в системе, поэтому выводит на русском. В
480 # окружении сборки переменная LANG не настроена. Поменяем переменную
481 # окружения LANG на en_US
482 LANG=en_US hello
483 Hello, world!
484 #+END_SRC
485
486*** Проверка воспроизводимости
487 Для проверки существует команда ~guix challenge~. Она проверяет
488 совпадает ли хеш, собранной программы с тем, что находится на
489 сборочной ферме (build farm):
490
491 #+BEGIN_SRC bash
492 guix challenge hello -v
493 /gnu/store/kg9mirg6xbvzcp0a98v7326n1nvvwgsj-hello-2.10 contents match:
494 local hash: 101vrhsf9zrzkir4yz01934il2b8wp3z30cc8h0aymzdzbwrikq9
495 https://ci.guix.gnu.org/nar/lzip/kg9mirg6xbvzcp0a98v7326n1nvvwgsj-hello-2.10: 101vrhsf9zrzkir4yz01934il2b8wp3z30cc8h0aymzdzbwrikq9
496
497 1 store items were analyzed:
498 - 1 (100.0%) were identical
499 - 0 (0.0%) differed
500 - 0 (0.0%) were inconclusive
501 #+END_SRC
502
503 Наша сборка побитово идентична, а значит воспроизводима. Таким
504 образом мы рассмотрели воспроизводимые сборки на примере уже
505 существующей программы в репозитории Guix.
506
507*** Запись действий
508 #+BEGIN_EXPORT html
509 <span align="center">
510 <script id="asciicast-Ie61O6XaPHzu5O5WafFxA0Hsc" src="https://asciinema.org/a/Ie61O6XaPHzu5O5WafFxA0Hsc.js" async></script>
511 </span>
512 #+END_EXPORT
513
514** Воспроизводимые сборки в других дистрибутивах
515*** NixOS
516 #+CAPTION: Логотип Nix(OS)
517 [[https://nixos.wiki/nixos-logo-small.png]]
518
519 Дистрибутив GNU/Linux, которым вдохновлялся Guix.
520
521 #+BEGIN_QUOTE
522 1528 out of 1541 (99.16%) paths in the minimal installation image
523 are reproducible! [fn:nixos-reproducible]
524 #+END_QUOTE
525
526*** Debian
527 #+CAPTION: Логотип Debian
528 [[https://www.debian.org/logos/openlogo-100.jpg]]
529
530 Проект Reproducible Debian[fn:debian-reproducible] ставит целью
531 достижение воспроизводимости как можно большего числа пакетов в
532 дистрибутиве Debian. Достаточно много пакетов уже воспроизводимы:
533
534 [[https://tests.reproducible-builds.org/debian/unstable/amd64/stats_pkg_state.png]]
535
536*** Arch Linux
537 #+CAPTION: Логотип Arch Linux
538 [[https://www.archlinux.org/static/logos/archlinux-logo-dark-90dpi.ebdee92a15b3.png]]
539
540 Дистрибутив Arch Linux также старается использовать практику
541 воспроизводимых сборок[fn:arch-reproducible].
542
543 [[https://tests.reproducible-builds.org/archlinux/archlinux.png]]
544
545[fn:determinational-build: Детерминированная компиляция: https://ru.wikipedia.org/wiki/Детерминированная_компиляция]
546[fn:reproducible-builds: Сайт движения воспроизводимых сборок: https://reproducible-builds.org]
547[fn:hash-function: Что такое хеш-функция: https://ru.wikipedia.org/wiki/Хеширование]
548[fn:gnu-guix: Пакетный менеджер, а также свободный дистрибутив GNU/Linux с воспроизводимым ПО: https://guix.gnu.org/]
549[fn:gnu-nixos: Пакетный менеджер, а также открытый дистрибутив GNU/Linux с воспроизводимым ПО: https://nixos.org]
550[fn:debian-reproducible: Воспроизводимые сборки Debian: https://wiki.debian.org/ReproducibleBuilds/]
551[fn:arch-reproducible: Воспроизводимые сборки Arch Linux: https://tests.reproducible-builds.org/archlinux/archlinux.html]
552[fn:nixos-reproducible: Воспроизводимые сборки NixOS: https://r13y.com]
553[fn:guix-blog-1: Статья "Reproducible builds: a means to an end": https://guix.gnu.org/blog/2015/reproducible-builds-a-means-to-an-end/]
554[fn:guix-blog-2: Статья "Reproducible computations with Guix": https://guix.gnu.org/blog/2020/reproducible-computations-with-guix/]
555[fn:guix-best: Оригинал статьи «Guix: Самая совершенная операционная система»: https://ambrevar.xyz/guix-advance/index.html]
556[fn:gnu-guix-hello: Определение GNU Hello в Guix: https://git.savannah.gnu.org/cgit/guix.git/tree/gnu/packages/base.scm#n72]
557[fn:guix-mirrors: Зеркала пакетов Guix: https://paste.sr.ht/~w96k/8d0e03d5a7193dec95b6f0dc77682dab55d57e3d]
558[fn:guix-build-systems: Системы сборки в Guix: https://guix.gnu.org/manual/ru/html_node/Sistemy-sborki.html]
559[fn:guix-package-definition: Определение пакета в Guix: https://guix.gnu.org/manual/ru/html_node/Opisanie-paketov.html]
560[fn:guix-package-command: Команда guix package: https://guix.gnu.org/manual/ru/html_node/Vyzov-guix-package.html]
561[fn:diverse-double-compilation: Diverse Double-Compilation: https://dwheeler.com/trusting-trust/]
Note: See TracBrowser for help on using the repository browser.