\input texinfo
@c ===========================================================================
@c
@c This file was generated with po4a. Translate the source file.
@c
@c ===========================================================================

@c -*-texinfo-*-

@c %**start of header
@setfilename guix-cookbook.sk.info
@documentencoding UTF-8
@documentlanguage sk
@settitle Receptár GNU Guix
@c %**end of header

@c Onion service for ci.guix.gnu.org.
@set SUBSTITUTE-TOR-URL https://4zwzi66wwdaalbhgnix55ea3ab4pvvw66ll2ow53kjub6se4q2bclcyd.onion

@copying
Copyright @copyright{} 2019, 2022 Ricardo Wurmus@* Copyright @copyright{}
2019 Efraim Flashner@* Copyright @copyright{} 2019 Pierre Neidhardt@*
Copyright @copyright{} 2020 Oleg Pykhalov@* Copyright @copyright{} 2020
Matthew Brooks@* Copyright @copyright{} 2020 Marcin Karpezo@* Copyright
@copyright{} 2020 Brice Waegeneire@* Copyright @copyright{} 2020 André
Batista@* Copyright @copyright{} 2020 Christine Lemmer-Webber@* Copyright
@copyright{} 2021 Joshua Branson@* Copyright @copyright{} 2022, 2023 Maxim
Cournoyer@* Copyright @copyright{} 2023-2025 Ludovic Courtès@* Copyright
@copyright{} 2023 Thomas Ieong@* Copyright @copyright{} 2024 Florian Pelz@*
Copyright @copyright{} 2025 45mg@* Copyright @copyright{} 2023 Marek
Felšöci@* Copyright @copyright{} 2023 Konrad Hinsen@* Copyright @copyright{}
2023 Philippe Swartvagher@*

Tento dokument môžete kopírovať, ďalej šíriť a/alebo upravovať pod
podmienkami licencie GNU Free Documentation License vo verzii 1.3 alebo v
akejkoľvek novšej verzii, ktorú vydáva Free Software Foundation; bez
nemenných oddielov, úvodnej strany a propagačného textu.  Kópia tejto
licencie je priložená v oddiele „GNU Free Documentation License“.
@end copying

@dircategory Správa systému
@direntry
* Receptár Guix: (guix-cookbook.sk).  Návody a príklady GNU Guix.
@end direntry

@titlepage
@title Receptár GNU Guix
@subtitle Návody na používanie funkcionálneho správcu balíkov GNU Guix a príklady z praxe
@author Vývojári GNU Guix

@page
@vskip 0pt plus 1filll

@insertcopying
@end titlepage

@contents

@c *********************************************************************
@node Top
@top Receptár GNU Guix

Tento dokument obsahuje návody a podrobné príklady použitia GNU@tie{}Guix,
funkcionálneho správcu balíkov napísaného pre systém GNU.  Získajte viac
podrobností o systéme, jeho API a súvisiacich pojmoch v @pxref{Top,,, guix,
GNU Guix reference manual}.

@c TRANSLATORS: You can replace the following paragraph with information on
@c how to join your own translation team and how to report issues with the
@c translation.
Táto príručka je dostupná aj v angličtine (@pxref{Top,,, guix-cookbook, GNU
Guix Cookbook}), čínštine (@pxref{Top,,, guix-cookbook.zh_CN, GNU Guix
烹饪书}), francúzštine (@pxref{Top,,, guix-cookbook.fr, Livre de recettes de
GNU Guix}), nemčine (@pxref{Top,,, guix-cookbook.de, GNU-Guix-Kochbuch}),
kórejčine (@pxref{Top,,, guix-cookbook.ko, GNU Guix 쿡북}), španielčine
(@pxref{Top,,, guix-cookbook.es, Libro de recetas de GNU Guix}), taliančine
(@pxref{Top,,, guix-cookbook.it, Ricettario di GNU Guix}), brazílskej
portugalčine (@pxref{Top,,, guix-cookbook.pt_BR, Livro de receitas do GNU
Guix}), ruštine (@pxref{Top,,, guix-cookbook.ru, GNU Guix Рецепты}),
švédčine (@pxref{Top,,, guix-cookbook.sv, Kokbok för GNU Guix}) a tamilčine
(@pxref{Top,,, guix-cookbook.ta, GNU Guix கையேடு}).  Ak chcete pomôcť s
prekladom tohto dokumentu do vášho rodného jazyka, pripojte sa k
@uref{https://translate.codeberg.org/projects/guix/documentation-cookbook,
Weblate} (@pxref{Translating Guix,,, guix, GNU Guix Reference Manual}).

@menu
* Návody na Scheme::         Zoznámte sa s vašim novým najobľúbenejším 
                               jazykom!
* Zadávanie balíkov::        Návody na zadávanie balíkov
* Nastavenie systému::       Prispôsobenie systému GNU
* Kontajnery::               Oddelené prostredia a vnorené systémy
* Virtuálne stroje::         Nastavenie a používanie virtuálnych strojov
* Pokročilá správa balíkov::  Moc pre používateľov!
* Vývoj programového vybavenia::  Prostredia, priebežné zaraďovanie, atď.
* Správa prostredí::         Kontrolné prostredie
* Reproducible Research::    A foundation for reproducible research.
* Inštalácia Guixu na zhluk počítačov::  Vysokovýkonné počítanie.
* Správa systému Guix::      Osobitosti správy systému.

* Poďakovanie::              Ďakujeme!
* Licencia GNU Free Documentation::  Licencia, ktorej podlieha tento 
                                       dokument.
* Zoznam pojmov::            Pojmy.

@detailmenu
 --- Podrobný zoznam uzlov ---



Návody na Scheme



* Zrýchlené školenie jazyka Scheme::  Zrýchlené školenie jazyka Scheme

Zadávanie balíkov



* Návod na zadávanie balíkov::  Návod na pridávanie balíkov do Guixu.
* Packaging Workflows::      Real life examples on working with specific 
                               build systems.

Návod na zadávanie balíkov



* Balík „Vitaj svet“::       Balík „Vitaj svet“
* Nastavenie::               Nastavenie
* Zložitejší príklad::       Zložitejší príklad
* Ďalšie zostavovacie systémy::  Ďalšie zostavovacie systémy
* Programovateľné a automatické zadávanie balíkov::  Programovateľné a 
                                                       automatické zadávanie 
                                                       balíkov
* Získavanie pomoci::        Získavanie pomoci
* Záver::                    Záver
* Odkazy::                   Odkazy

Nastavenie



* Miestny súbor::            Miestny súbor
* Kanály::                   Kanály
* Priamy zásah do git repozitára::  Priamy zásah do git repozitára

Programovateľné a automatické zadávanie balíkov



* Rekurzívne nahrávače::     Rekurzívne nahrávače
* Automatické aktualizácie::  Automatické aktualizácie
* Dedičnosť::                Dedičnosť

Packaging Workflows



* Packaging Rust Crates::    Packaging Rust Crates

Packaging Rust Crates



* Common Workflow for Rust Packaging::  Common Workflow for Rust Packaging
* Cargo Workspaces and Development Snapshots::  Cargo Workspaces and 
                                                  Development Snapshots
* Using Rust Libraries in Other Build Systems::  Using Rust Libraries in 
                                                   Other Build Systems

Nastavenie systému



* Automatické pripojenie k určitému TTY::  Automaticky pripojiť používateľa 
                                             k určitému TTY
* Prispôsobenie jadra::      Vytvorenie a používanie vlastného Linuxového 
                               jadra v systéme Guix.
* API pre vytváranie obrazov systému Guix::  Prispôsobenie obrazov 
                                               nezvyčajným platformám.
* Používanie bezpečnostných kľúčov::  Ako používať bezpečnostné kľúče so 
                                        systémom Guix.
* mcron úloha pre dynamický DNS::  Úloha na aktualizovanie IP adresy v 
                                     pozadí názvu hostiteľa DuckDNS.
* Pripojenie k Wireguard VPN::  Pripojenie k Wireguard VPN sieti.
* Prispôsobenie správcu okien::  Spravovať prispôsobenie správcu okien v 
                                   systéme Guix.
* Spúšťanie Guixu na serveri Linode::  Spúšťanie Guixu na serveri Linode.
* Spúšťanie Guixu na Kimsufi serveri::  Spúšťanie Guixu na Kimsufi serveri.
* Nastavenie podvojného pripojenia::  Nastavenie podvojného pripojenia v 
                                        zadaní systému súborov.
* Získavanie náhrad prostredníctvom Tor::  Nastavenie démona Guix na 
                                             získavanie náhrad cez Tor.
* Nastavenia NGINX a Lua::   Nastavenie web-servera NGINX na načítavanie Lua 
                               modulov.
* Hudobný server so zvukom cez Bluetooth::  Bezobrazovkový prehrávač hudby s 
                                              Bluetooth výstupom.

Prispôsobenie správcu okien



* StumpWM::                  StumpWM
* Uzamykanie sedenia::       Uzamykanie sedenia

Uzamykanie sedenia



* Xorg::                     Xorg

Kontajnery



* Kontajnery Guix::          Dokonale oddelené prostredia
* Kontajnery systému Guix::  Systém vo vašom systéme

Kontajnery systému Guix



* Databázový kontajner::     Databázový kontajner
* Prístup do siete vrámci kontajnera::  Prístup do siete vrámci kontajnera

Virtuálne stroje



* Sieťový most pre QEMU::    Sieťový most pre QEMU
* Smerovaná sieť pre libvirt::  Smerovaná sieť pre libvirt
* Custom NAT-based network for libvirt::  Custom NAT-based network for 
                                            libvirt
* References: VM References.  Further reading on virtual machines.

Pokročilá správa balíkov



* Profily Guix v praxi::     Postupy pre spravovanie viacerých profilov a 
                               balíkospisov.

Profily Guix v praxi



* Základné použitie balíkospisov::  Základné použitie balíkospisov
* Požadované balíky::        Požadované balíky
* Predvolený profil::        Predvolený profil
* Výhody balíkospisov::      Výhody balíkospisov
* Opakovateľné profily::     Opakovateľné profily

Vývoj programového vybavenia



* Začíname::                 Krok 0: použitie „guix shell“.
* Zostavovanie s Guixom::    Krok 1: zostavenie vášho kódu.
* Repozitár ako kanál::      Krok 2: premena repozitára na kanál.
* Obmeny balíkov::           Prídavok: Zadávanie obmien.
* Nastavenie priebežného zaraďovania::  Krok 3: priebežné zaraďovanie.
* Zostavovací balíkospis::   Prídavok: Balíkospis.
* Zhrnutie::                 Súhrn.

Správa prostredí



* Guix prostredie cez direnv::  Vytvoriť Guix prostredie pomocou direnv

Using Guix for Reproducible Research



* Setting Up the Environment::  Step 1: using `guix shell'.
* Recording the Environment::  Step 2: using `guix describe'.
* Ensuring Long-Term Source Code Archiving::  Step 3: Software Heritage.
* Referencing the Software Environment::  Step 4: SWHIDs.

Inštalácia Guixu na zhluk počítačov



* Nastavenie hlavného uzla::  Uzol, ktorý spúšťa démona.
* Nastavenie výpočtových uzlov::  Klientske uzly.
* Prístup do siete zhluku::  Správa obmedzení pre vstup do siete.
* Využitie diskového priestoru zhluku::  Úvahy o využití diskového 
                                           priestoru.
* Úvahy o zabezpečení zhluku::  Udržiavanie zhluku v bezpečí.

Správa systému Guix



* Aktualizovať Postgres pre Cuirass::  Upgrading from the default postgres.

@end detailmenu
@end menu

@c *********************************************************************
@node Návody na Scheme
@chapter Návody na Scheme

GNU@tie{}Guix je zapísaný v programovacom jazyku Scheme. K mnohým jeho
súčastiam je možné pristupovať a upravovať ich prostredníctvom
programovania.  Pomocou jazyka Scheme môžete zadávať, upravovať a zostavovať
balíky, nasadzovať celé operačné systémy, atď.

Poznať základy programovania v jazyku Scheme vám otvorí dvere k množstvu
pokročilých súčastí, ktoré Guix ponúka --- a to ani nemusíte byť skúseným
vývojárom, aby ste ich mohli využívať!

Poďme na to!

@menu
* Zrýchlené školenie jazyka Scheme::  Zrýchlené školenie jazyka Scheme
@end menu

@node Zrýchlené školenie jazyka Scheme
@section Zrýchlené školenie jazyka Scheme

@cindex Scheme, rýchlokurz

Guix používa Guile implementáciu jazyka Scheme. Ak si chcete tento jazyk
vyskúšať, nainštalujte si Guile pomocou @code{guix install guile} a spustite
@dfn{REPL},
tzv.
@uref{https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop,
@dfn{slučku čítaj-vykonaj-zobraz}}, zadaním @code{guile} v príkazovom
riadku.

Môžete tiež použiť príkaz @code{guix shell guile -- guile} ak nechcete
inštalovať Guile do vášho používateľského profilu.

Riadky v nasledovných príkladoch znázorňujú to, čo treba zadať v rámci REPL;
riadky začínajúce na „@result{}“ znázorňujú výsledok vykonania príkazu,
zatiaľ čo riadky začínajúce na „@print{}“ znázorňujú to čo sa zobrazí na
obrazovke. @xref{Using Guile Interactively,,, guile, GNU Guile Reference
Manual}, pre viac podrobností o REPL.

@itemize
@item
Skladbu jazyka Scheme si možno predstaviť ako strom výrazov (alebo ako
@emph{s-expression} v jazyku Lisp). Výrazom môže byť priama konštanta,
napr. číselná hodnota či reťazec znakov, alebo môže predstavovať zoznam
iných zložených prvkov a priamych konštánt ohraničený v
zátvorkách. @code{#true} a @code{#false} (skrátene @code{#t} a @code{#f})
znázorňujú logické hodnoty „pravda“ a „nepravda“.

Príklady platných výrazov:

@lisp
"Ahoj svet!"
@result{} "Ahoj svet!"

17
@result{} 17

(display (string-append "Ahoj " "Guix" "\n"))
@print{} Ahoj Guix
@result{} #<unspecified>
@end lisp

@item
Tento posledný príklad znázorňuje volanie funkcie vnorené do iného volania
funkcie. Pri vykonávaní výrazu v zátvorkách predstavuje prvá položka funkciu
a zvyšok sú parametre volania. Návratová hodnota každej funkcie je výsledok
vykonania posledného výrazu v nej.

@item
Bezmenné funkcie, alebo @dfn{postupy}, vo výrazive jazyka Scheme, sa
zadávajú pomocou člena @code{lambda}:

@lisp
(lambda (x) (* x x))
@result{} #<procedure 120e348 at <unknown port>:24:0 (x)>
@end lisp

Vyššie uvedená funkcia vracia druhú mocninu hodnoty jej parametra. Keďže
všetko sa považuje za výraz, aj výraz @code{lambda} vracia bezmennú funkciu,
ktorú je následne možné uplatniť na nejaký parameter:

@lisp
((lambda (x) (* x x)) 3)
@result{} 9
@end lisp

Postupy sú pravidelné hodnoty, rovnako ako čísla, reťazce, logické veličiny
a pod.

@item
Všetkému je možné prideliť globálny názov pomocou @code{define}:

@lisp
(define a 3)
(define druha-mocnina (lambda (x) (* x x)))
(druha-mocnina a)
@result{} 9
@end lisp

@item
Funkcie možno zadávať aj v kratšom tvare s použitím nasledovnej skladby:

@lisp
(define (druha-mocnina x) (* x x))
@end lisp

@item
Zoznam je možné vytvoriť pomocou funkcie @code{list}:

@lisp
(list 2 a 5 7)
@result{} (2 3 5 7)
@end lisp

@item
Modul @code{(srfi srfi-1)} ponúka obvyklé postupy na vytváranie a
spracovanie zoznamov (@pxref{SRFI-1, list processing,, guile, GNU Guile
Reference Manual}).  Viď príklady použitia tých najužitočnejších:

@lisp
(use-modules (srfi srfi-1))  ;načítať postupy na spracovanie zoznamov

(append (list 1 2) (list 3 4))
@result{} (1 2 3 4)

(map (lambda (x) (* x x)) (list 1 2 3 4))
@result{} (1 4 9 16)

(delete 3 (list 1 2 3 4))        @result{} (1 2 4)
(filter odd? (list 1 2 3 4))     @result{} (1 3)
(remove even? (list 1 2 3 4))    @result{} (1 3)
(find number? (list "a" 42 "b")) @result{} 42
@end lisp

Všimnite si, že prvým parametrom @code{map}, @code{filter}, @code{remove}, a
@code{find} je postup!

@item
@cindex S-výraz
@dfn{quote} (jednoduchá úvodzovka) zabraňuje vykonaniu výrazu v zátvorke,
ktorému sa tiež hovorí S-výraz alebo „s-exp“: prvá položka sa nevykoná ako
volanie funkcie s ostatnými položkami ako parametrami (@pxref{Expression
Syntax, quote,, guile, GNU Guile Reference Manual}). Výsledkom je teda
zoznam výrazov.

@lisp
'(display (string-append "Ahoj " "Guix" "\n"))
@result{} (display (string-append "Ahoj " "Guix" "\n"))

'(2 a 5 7)
@result{} (2 a 5 7)
@end lisp

@item
@code{quasiquote} (@code{`}, obrátená jednoduchá úvodzovka) zabraňuje
vykonaniu výrazu v zátvorke dovtedy, kým nie je jeho vykonanie opätovne
povolené pomocou @dfn{unquote} (@code{,}, čiarky). Týmto spôsobom dopodrobna
rozhodujeme o tom, čo sa vykoná a čo nie.

@lisp
`(2 a 5 7 (2 ,a 5 ,(+ a 4)))
@result{} (2 a 5 7 (2 3 5 7))
@end lisp

Všimnite si, že hore uvedený výsledok je zoznam rôznorodých položiek: čísel,
znakov (@code{a}) a posledná položka je tiež zoznam.

@item
@cindex G-výrazy, skladba
@cindex gvýrazy, skladba
@findex #~
@findex #$
@findex gexp
@findex odgvýraziť
Guix zavádza steroidmi napumpovanú podobu S-výrazov, takzvané
@dfn{G-výrazy}, alebo „gvýrazy“ (pôvodne „gexps“), prichádzajúce s odnožou
@code{quasiquote} a @code{unquote}, teda @code{#~} (alebo @code{gexp}) a
@code{#$} (alebo @code{ungexp}), ktoré umožňujú @emph{zaradiť kód na
neskoršie vykonanie}.

S gvýrazmi sa stretnete, napríklad, v zadaniach niektorých balíkov, kde
poskytujú kód, ktorý sa má vykonať až pri zostavovaní balíka.  Vyzerajú
takto:

@lisp
(use-modules (guix gexp)           ;aby sme mohli používať gvýrazy
             (gnu packages base))  ;kvôli „coreutils“

;; Nasleduje G-výraz zaradzujúci kód na neskoršie vykonanie.
#~(begin
    ;; Vykoná „ls“ z balíka určeného premennou
    ;; „coreutils“.
    (system* #$(file-append coreutils "/bin/ls") "-l")

    ;; Vytvoriť výstupný priečinok tohto balíka.
    (mkdir #$output))
@end lisp

Viď @ref{G-Expressions,,, guix, GNU Guix Reference Manual}, pre viac
podrobností o gvýrazoch.

@item
Pomocou @code{let} (@pxref{Local Bindings,,, guile, GNU Guile Reference
Manual}) môžeme zadať a pomenovať viacero miestnych premenných:

@lisp
(define x 10)
(let ((x 2)
      (y 3))
  (list x y))
@result{} (2 3)

x
@result{} 10

y
@error{} In procedure module-lookup: Unbound variable: y
@end lisp

Ak chcete, aby bolo možné v neskorších zadaniach premenných odkazovať na
predtým zadané premenné, použite @code{let*}.

@lisp
(let* ((x 2)
       (y (* x 3)))
  (list x y))
@result{} (2 6)
@end lisp

@item
@dfn{Kľúčové slová} sa bežne používajú na stotožnenie pomenovaných
parametrov funkcie. Začínajú sa @code{#:} (mriežkou a dvojbodkou), po
ktorých nasledujú písmenové či číselné znaky:
@code{#:takto}. @xref{Keywords,,, guile, GNU Guile Reference Manual}.

@item
Znak percento @code{%} je bežne používaný pre globálne premenné s prístupom
len na čítanie počas zostavovania. Všimnite si, že je to len všeobecným
zvykom, ako napr. @code{_} v jazyku C. Scheme spracúva  @code{%} ako
hocijaký iný znak.

@item
Moduly sa vytvárajú pomocou @code{define-module} (@pxref{Creating Guile
Modules,,, guile, GNU Guile Reference Manual}). Napríklad

@lisp
(define-module (guix build-system ruby)
  #:use-module (guix store)
  #:export (ruby-build
            ruby-build-system))
@end lisp

určuje modul @code{guix build-system ruby}, ktorý má byť umiestnený v
@file{guix/build-system/ruby.scm} niekde vo vyhľadávacej ceste Guilu. Závisí
na module @code{(guix store)} a určuje dve premenné, @code{ruby-build} a
@code{ruby-build-system}.

Viď @ref{Package Modules,,, guix, GNU Guix Reference Manual}, pre viac
podrobností o moduloch zadávajúcich balíky.
@end itemize

@quotation Dozvedieť sa viac
Scheme je jazyk, ktorý sa hojne využíva pri výuke programovania a sú na ňom
založené mnohé podklady.  V nasledovných dokumentoch sa môžete o Scheme
dozvedieť viac:

@itemize
@item
@uref{https://spritely.institute/static/papers/scheme-primer.html, @i{A
Scheme Primer}}, od Christine Lemmer-Webberovej a Spritely Institute.

@item
@c There used to be a copy at mitpress.mit.edu but it vanished.
@uref{https://sarabander.github.io/sicp/, @i{Structure and Interpretation of
Computer Programs}}, od Harolda Abelsona, Geralda Jay Sussmana a Julie
Sussmanovej.  Táto knižná príručka je bežne známa ako ``SICP''.

Môžete si ju tiež stiahnuť a prečítať na vašom počítači:

@example
guix install book-sicp info-reader
info sicp
@end example

@end itemize

Ďalšie knihy, návody ako aj iné druhy zdrojov nájdete na
@url{https://schemers.org/}.
@end quotation


@c *********************************************************************
@node Zadávanie balíkov
@chapter Zadávanie balíkov

@cindex zadávanie balíkov

Tento oddiel je zameraný na pridávanie nových balíkov do zbierky balíkov GNU
Guix, čo zahŕňa zadávanie balíkov v Guile Scheme, ich usporadúvanie do
modulov a zostavovanie.

@menu
* Návod na zadávanie balíkov::  Návod na pridávanie balíkov do Guixu.
* Packaging Workflows::      Real life examples on working with specific 
                               build systems.
@end menu

@node Návod na zadávanie balíkov
@section Návod na zadávanie balíkov

GNU Guix sa vyznačuje ako @emph{prispôsobiteľný} správca balíkov hlavne
preto, že používa @uref{https://www.gnu.org/software/guile/, GNU Guile},
výkonný vysokoúrovňový programovací jazyk, jedno z nárečí jazyka
@uref{https://en.wikipedia.org/wiki/Scheme_%28programming_language%29,
Scheme} z jazykovej rodiny
@uref{https://en.wikipedia.org/wiki/Lisp_%28programming_language%29, Lispu}.

Zadania balíkov sú rovnako písané v jazyku Scheme, čo dáva Guixu jedinečnú
výhodu v porovnaní s ostatnými správcami balíkov, ktoré používajú skripty
shellu alebo jednoduché programovacie jazyky.

@itemize
@item
Vo vašich zadaniach balíkov môžete využiť funkcie, štruktúry, makrá a všetku
schopnosť vyjadrovania jazyka Scheme.

@item
Dedičnosť zjednodušuje prispôsobovanie balíka tým, že umožňuje zdediť
vybraný jestvujúci balík a upraviť len to čo je potrebné.

@item
Dávkové spracovanie: celú zbierku balíkov je možné načítať, prefiltrovať a
spracovať. Potrebujete zostaviť server bez grafického rozhrania? Dá sa
to. Potrebujete opätovne zostaviť všetko zo zdrojových súborov s použitím
odlišných optimalizačných príznakov? Pridajte parameter @code{#:make-flags
"..."} do zoznamu balíkov. Tiež by nebolo od veci spomenúť
@uref{https://wiki.gentoo.org/wiki/USE_flag, Gentoo príznak USE}, ale to je
na dlhšie: tvorca balíkov nemusí vopred myslieť na tieto zmeny, pretože ich
môže neskôr @emph{naprogramovať} koncový používateľ!
@end itemize

Nasledovný návod vysvetľuje základy vytvárania balíkov s
Guixom. Nepredpokladá žiadnu znalosť systému Guix ani jazyka Lisp. Čitateľ
by však mal byť oboznámený s príkazovým riadkom a mať aspoň základnú znalosť
programovania.

@menu
* Balík „Vitaj svet“::       Balík „Vitaj svet“
* Nastavenie::               Nastavenie
* Zložitejší príklad::       Zložitejší príklad
* Ďalšie zostavovacie systémy::  Ďalšie zostavovacie systémy
* Programovateľné a automatické zadávanie balíkov::  Programovateľné a 
                                                       automatické zadávanie 
                                                       balíkov
* Získavanie pomoci::        Získavanie pomoci
* Záver::                    Záver
* Odkazy::                   Odkazy
@end menu

@node Balík „Vitaj svet“
@subsection Balík „Vitaj svet“

Oddiel „Zadávanie balíkov“ v príručke obsahuje základy tvorby balíkov s
Guixom (@pxref{Defining Packages,,, guix, GNU Guix Reference Manual}). V
nasledovnom oddieli si tieto základy z časti pripomenieme.

GNU@tie{}Hello je šablóna projektu, ktorá slúži ako základný príklad
zadávania balíkov. Využíva zostavovací systém GNU (@code{./configure && make
&& make install}). Guix už obsahuje zadanie príslušného balíka, ktoré
predstavuje vhodný odrazový bod. Môžete si zadanie balíka prezrieť zadaním
@code{guix edit hello} do príkazového riadku. Pozrime sa ako toto zadania
balíka vyzerá:

@lisp
(define-public hello
  (package
    (name "hello")
    (version "2.10")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/hello/hello-" version
                                  ".tar.gz"))
              (sha256
               (base32
                "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
    (build-system gnu-build-system)
    (synopsis "Hello, GNU world: An example GNU package")
    (description
     "GNU Hello prints the message \"Hello, world!\" and then exits.  It
serves as an example of standard GNU coding practices.  As such, it supports
command-line arguments, multiple languages, and so on.")
    (home-page "https://www.gnu.org/software/hello/")
    (license gpl3+)))
@end lisp

Ako môžete vidieť, tá najobsiahlejšia časť je dosť jednoduchá. Ale prejdime
si spoločne jednotlivé polia:

@table @samp
@item name
Názov projektu. Podľa všeobecných zvyklostí ho zapisujeme malými písmenami,
bez podčiarkovníkov a s použitím pomlčiek na oddelenie jednotlivých slov.

@item source
Toto pole obsahuje popis pôvodu zdrojového kódu. Záznam @code{origin}
obsahuje tieto polia:

@enumerate
@item Spôsob, v tomto prípade @code{url-fetch} pre stiahnutie prostredníctvom HTTP/FTP, ale poznáme
    aj iné spôsoby, ako napr. @code{git-fetch} pre Git repozitáre.
@item Prepojenie (URI), čo obyčajne predstavuje nejaké umiestnenie @code{https://} pre @code{url-fetch}. V tomto prípade
    zvláštne „mirror://gnu“ odkazuje na súbor dobre známych umiestnení, ktoré
môžu byť všetky použité na získanie zdrojového kódu ak by niektoré z nich
nebolo dostupné.
@item Kontrolný súčet @code{sha256} požadovaného súboru. Je dôležitý pre zaistenie
    celistvosti zdroja. Všimnite si, že Guix pracuje z base32 reťazcami, čo
vysvetľuje použitie funkcie @code{base32}.
@end enumerate

@item build-system

Práve tu má príležitosť zažiariť sila všeobecnosti jazyka Scheme: v tomto
prípade, @code{gnu-build-system} je zovšeobecnenie známych príkazov shellu
@code{./configure && make && make install}. Medzi ďalšie zostavovacie
systémy patrí @code{trivial-build-system}, ktorý nerobí nič a necháva na
programátorovi, aby zadal všetky potrebné kroky zostavenia,
@code{python-build-system}, @code{emacs-build-system} a mnohé ďalšie
(@pxref{Build Systems,,, guix, GNU Guix Reference Manual}).

@item synopsis
Toto by mal byť súhrnný popis toho, na čo balík slúži. Pri mnohých balíkoch
je vhodné použiť slogan zo stránky príslušného projektu.

@item description
Podobne ako v prípade súhrnného popisu je vhodné použiť popis projektu z
jeho domovskej stránky. Všimnite si, že Guix používa značkovanie Texinfo.

@item home-page
Použitie HTTPS prepojenie, ak je dostupné.

@item license
Viď @code{guix/licenses.scm} v zdrojovom kóde projektu pre zoznam všetkých
dostupných licencií.
@end table

Nastal čas na zostavenie nášho prvého balíka! Zatiaľ nič zvláštne:
spoľahneme sa jednoducho na kópiu vyššie uvedeného zadania @code{my-hello}.

Tak ako pri rituálnom „Ahoj svet“, ktorý sa vyučuje pri väčšine
programovacích jazykov, toto bude ten „najručnejší“ spôsob zadávania balíka,
ktorý použijete. Neskôr si ukážeme dokonalejší postup, no zatiaľ sa
vyberieme tou najjednoduchšou cestou.

Uložte nasledujúci obsah do súboru s názvom @file{my-hello.scm}.

@lisp
(use-modules (guix packages)
             (guix download)
             (guix build-system gnu)
             (guix licenses))

(package
  (name "my-hello")
  (version "2.10")
  (source (origin
            (method url-fetch)
            (uri (string-append "mirror://gnu/hello/hello-" version
                                ".tar.gz"))
            (sha256
             (base32
              "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
  (build-system gnu-build-system)
  (synopsis "Hello, Guix world: An example custom Guix package")
  (description
   "GNU Hello prints the message \"Hello, world!\" and then exits.  It
serves as an example of standard GNU coding practices.  As such, it supports
command-line arguments, multiple languages, and so on.")
  (home-page "https://www.gnu.org/software/hello/")
  (license gpl3+))
@end lisp

Dodatočné príkazy si vysvetlíme o chvíľu.

Neváhajte a vyskúšajte si, čo sa stane ak zmeníte hodnoty niektorých
polí. Ak zmeníte zdroj balíka, budete musieť aktualizovať aj kontrolný
súčet. Guix nezostaví nič ak daný kontrolný súčet neodpovedá kontrolnému
súčtu zdrojového kódu. Pre získanie správneho kontrolného súčtu potrebujeme
stiahnuť zdroj, vypočítať kontrolný súčet sha256 a previesť ho do base32.

Našťastie, Guix to môže urobiť za nás; všetko čo budeme potrebovať je
prepojenie (URI) zdroja:

@c TRANSLATORS: This is example shell output.
@example sh
$ guix download mirror://gnu/hello/hello-2.10.tar.gz

Starting download of /tmp/guix-file.JLYgL7
From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
following redirection to `https://mirror.ibcp.fr/pub/gnu/hello/hello-2.10.tar.gz'...
 …10.tar.gz  709KiB                                 2.5MiB/s 00:00 [##################] 100.0%
/gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i
@end example

V tomto konkrétnom prípade nám výstup hovorí, aké zrkadlo bolo vybraté. Ak
výsledok tohto príkazu nie je rovnaký ako v predchádzajúcom úryvku,
aktualizujte vaše zadanie @code{my-hello} podľa potreby.

Všimnite si, že archívy GNU balíkov sú poskytované spolu s OpenPGP podpisom,
takže by ste si jednoznačne mali overiť podpis tohto archívu pomocou „gpg“
predtým než budete pokračovať:

@c TRANSLATORS: This is example shell output.
@example sh
$ guix download mirror://gnu/hello/hello-2.10.tar.gz.sig

Starting download of /tmp/guix-file.03tFfb
From https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz.sig...
following redirection to `https://ftp.igh.cnrs.fr/pub/gnu/hello/hello-2.10.tar.gz.sig'...
 ….tar.gz.sig  819B                                                                                                                       1.2MiB/s 00:00 [##################] 100.0%
/gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig
0q0v86n3y38z17rl146gdakw9xc4mcscpk8dscs412j22glrv9jf
$ gpg --verify /gnu/store/rzs8wba9ka7grrmgcpfyxvs58mly0sx6-hello-2.10.tar.gz.sig /gnu/store/hbdalsf5lpf01x4dcknwx6xbn6n5km6k-hello-2.10.tar.gz
gpg: Podpis vytvorený Ne 16. november 2014, 13:08:37 CET
gpg:                pomocou RSA kľúča A9553245FDE9B739
gpg: Dobrý podpis od "Sami Kerola <kerolasa@@iki.fi>" neznáme
gpg:                 alias "Sami Kerola (http://www.iki.fi/kerolasa/) <kerolasa@@iki.fi>" neznáme
gpg: VAROVANIE: Tento kľúč nie certifikovaný dôveryhodným podpisom!
gpg:          Nič nenaznačuje tomu, že tento podpis patrí vlastníkovi kľúča.
Primárny fingerprint kľúča: 8ED3 96E3 7E38 D471 A005  30D3 A955 3245 FDE9 B739
@end example

Potom môžete spokojne spustiť

@c TRANSLATORS: Do not translate this command
@example sh
$ guix package --install-from-file=my-hello.scm
@end example

Teraz by ste už mali mať @code{my-hello} vo vašom profile!

@c TRANSLATORS: Do not translate this command
@example sh
$ guix package --list-installed=my-hello
my-hello	2.10	out
/gnu/store/f1db2mfm8syb8qvc357c53slbvf1g9m9-my-hello-2.10
@end example

Dostali sme sa tak ďaleko ako sa dalo bez znalosti Scheme. Predtým než
prejdeme k zložitejším balíkom si dáme rýchlokurz jazyka Scheme. Na začiatok
odporúčame @pxref{Zrýchlené školenie jazyka Scheme}.

@node Nastavenie
@subsection Nastavenie

V ďalších častiach tohto oddielu sa budeme spoliehať na vašu základnú
znalosť jazyka Scheme. Teraz si predstavíme rôzne možnosti práce s balíkmi
Guix.

Jestvuje viacero spôsobov nastavenia prostredia pre zadávanie balíkov Guix.

Odporúčame vám pracovať priamo v repozitári zdrojových súborov Guixu za
účelom jednoduchšieho prispievania do projektu.

Ale najprv sa pozrime na ostatné možnosti.

@menu
* Miestny súbor::            Miestny súbor
* Kanály::                   Kanály
* Priamy zásah do git repozitára::  Priamy zásah do git repozitára
@end menu

@node Miestny súbor
@subsubsection Miestny súbor

Toto je spôsob, ktorý sme práve použili v prípade @samp{my-hello}. Vďaka
základom Scheme, ktoré sme si predstavili, vám teraz môžeme vysvetliť tie
najdôležitejšie časti. Ako je uvedené v @code{guix package --help}:

@example
  -f, --install-from-file=SÚBOR
                         inštalovať balíky, ktoré sú výsledkom vyhodnotenia
                         kódu v SÚBORE
@end example

Teda, posledný výraz @emph{musí} vracať balík, čo pre náš skorší príklad aj
platí.

Výraz @code{use-modules} nám hovorí, ktoré moduly potrebujeme. Moduly
predstavujú zbierky hodnôt a funkcií. V iných programovacích jazykoch sa
všeobecne označujú ako „knižnice“ alebo „balíky“.

@node Kanály
@subsubsection Kanály

@cindex kanál
Guix a jeho zbierku balíkov možno rozšíriť pomocou @dfn{kanálov}.  Kanál je
Git repozitár, či už verejný alebo nie, obsahujúci @file{.scm} súbory
poskytujúce balíky (@pxref{Defining Packages,,, guix, GNU Guix Reference
Manual}) alebo služby (@pxref{Defining Services,,, guix, GNU Guix Reference
Manual}).

Ako vytvoriť kanál? Najprv vytvorte priečinok, ktorý bude obsahovať vaše
@file{.scm} súbory, napríklad @file{~/moj-kanal}:

@example
mkdir ~/moj-kanal
@end example

Predpokladajme, že chcete pridať balík @samp{my-hello}, s ktorým sme sa už
stretli. Bude však potrebovať niekoľko úprav:

@lisp
(define-module (my-hello)
  #:use-module (guix licenses)
  #:use-module (guix packages)
  #:use-module (guix build-system gnu)
  #:use-module (guix download))

(define-public my-hello
  (package
    (name "my-hello")
    (version "2.10")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnu/hello/hello-" version
                                  ".tar.gz"))
              (sha256
               (base32
                "0ssi1wpaf7plaswqqjwigppsg5fyh99vdlb9kzl7c9lng89ndq1i"))))
    (build-system gnu-build-system)
    (synopsis "Hello, Guix world: An example custom Guix package")
    (description
     "GNU Hello prints the message \"Hello, world!\" and then exits.  It
serves as an example of standard GNU coding practices.  As such, it supports
command-line arguments, multiple languages, and so on.")
    (home-page "https://www.gnu.org/software/hello/")
    (license gpl3+)))
@end lisp

Všimnite si, že sme tentokrát zadanie balíka uložili do verejnej premennej
@code{my-hello} pomocou @code{define-public}, na ktorú je možné odkazovať,
medzi iným aj ako na závislosť v rámci zadania nejakého ďalšieho balíka.

Ak spustíte @code{guix package --install-from-file=my-hello.scm} s použitím
vyššie uvedeného súboru, tak príkaz zlyhá, pretože posledný výraz,
@code{define-public}, nevracia balík. Ak aj napriek tomu chcete v tomto
prípade použiť @code{define-public}, uistite sa, že súbor končí vykonaním
@code{my-hello}:

@lisp
;; ...
(define-public my-hello
  ;; ...
  )

my-hello
@end lisp

Tento posledný príklad nie je veľmi bežný.

A teraz, ako možno tento balík zviditeľniť pre @command{guix} príkazy, aby
ste ho mohli vyskúšať? Musíte pridať priečinok @file{~/moj-kanal} k
prehľadávaným cestám pomocou voľby @option{-L} ako v týchto príkladoch:

@example
guix show -L ~/moj-kanal my-hello
guix build -L ~/moj-kanal my-hello
@end example

Posledným krokom je pretvoriť @file{~/moj-kanal} na ozajstný kanál
sprístupňujúc tak vašu zbierku balíkov akémukoľvek @command{guix} príkazu.
V prvom rade musíte z tohto priečinka spraviť Git repozitár:

@example
cd ~/moj-kanal
git init
git add my-hello.scm
git commit -m "Prvá úprava môjho kanála."
@end example

A to je všetko, práve ste vytvorili kanál! Teraz už môžete tento kanál
pridať do vášho nastavenia kanálov v @file{~/.config/guix/channels.scm}
(@pxref{Specifying Additional Channels,,, guix, GNU Guix Reference
Manual}). Predpokladajúc, že si váš kanál nateraz ponecháte vo vašom
počítači, bude súbor @file{channels.scm} vyzerať asi takto:

@lisp
(append (list (channel
                (name 'moj-kanal)
                (url (string-append "file://" (getenv "HOME")
                                    "/moj-kanal"))))
        %default-channels)
@end lisp

Nabudúce, keď spustíte @command{guix pull}, sa váš kanál vyzdvihne a balíky,
ktoré obsahuje sa sprístupnia pre všetky @command{guix} príkazy, a to aj bez
použitia voľby @option{-L}.  Príkaz @command{guix describe} potvrdí, že Guix
vskutku používa aj kanál @code{my-channel}, aj kanál @code{guix}.

Viď @ref{Creating a Channel,,, guix, GNU Guix Reference Manual}, pre viac
podrobností.

@node Priamy zásah do git repozitára
@subsubsection Priamy zásah do git repozitára

Odporúčame vám pracovať priamo v rámci projektu Guix: znižuje to čas
potrebný na odoslanie a zapracovanie vašich zmien do oficiálnej verzie
Guixu, aby aj ostatní mali úžitok z vašej ťažkej práce!

Na rozdiel od väčšiny softvérových distribúcií, repozitár Guixu obsahuje aj
nástroje (vrátane správcu balíkov) aj zadania balíkov. Vývojárom je takto
možné zaistiť pružnosť potrebnú pre upravovanie API bez toho, aby niečo
pokazili. Všetky zadania balíkov sa po každej úprave samy aktualizujú, čím
sa predíde zdržaniam vo vývoji.

Vytvorte si kópiu oficiálneho @uref{https://git-scm.com/, Git} repozitára:

@example
$ git clone https://git.guix.gnu.org/guix.git
@end example

Vo zvyšku tohto príspevku použijeme pri odkazovaní na túto kópiu premennú
@samp{$GUIX_CHECKOUT}.


Pre nastavenie prostredia repozitára postupujte podľa pokynov v príručke
(@pxref{Contributing,,, guix, GNU Guix Reference Manual}).

Keď budete pripravení, mali by ste byť schopní použiť zadania balíkov z
prostredia repozitára.

Nebojte sa upravovať zadania balíkov v @samp{$GUIX_CHECKOUT/gnu/packages}.

Skript @samp{$GUIX_CHECKOUT/pre-inst-env} vám umožňuje použiť @samp{guix} so
zbierkou balíkov v repozitári (@pxref{Running Guix Before It Is Installed,,,
guix, GNU Guix Reference Manual}).

@itemize
@item
Vyhľadávajte balíky, napríklad Ruby:

@example
  $ cd $GUIX_CHECKOUT
  $ ./pre-inst-env guix package --list-available=ruby
      ruby    1.8.7-p374      out     gnu/packages/ruby.scm:119:2
      ruby    2.1.6   out     gnu/packages/ruby.scm:91:2
      ruby    2.2.2   out     gnu/packages/ruby.scm:39:2
@end example

@item
Zostavte balík, v tomto prípade Ruby vo verzii 2.1:

@example
  $ ./pre-inst-env guix build --keep-failed ruby@@2.1
  /gnu/store/c13v73jxmj2nir2xjqaz5259zywsa9zi-ruby-2.1.6
@end example

@item
Nainštaluje ho do vášho používateľského profilu:

@example
  $ ./pre-inst-env guix package --install ruby@@2.1
@end example

@item
Overte si, či ste neurobili niektorú z častých chýb:

@example
  $ ./pre-inst-env guix lint ruby@@2.1
@end example
@end itemize

Guix sa usiluje udržať vysokú úroveň zadávania balíkov; pri prispievaní do
projektu Guix si zapamätajte, že je potrebné

@itemize
@item
dodržiavať spôsob kódovania (@pxref{Coding Style,,, guix, GNU Guix Reference
Manual}),
@item
a prejsť si kontrolný zoznam z príručky (@pxref{Submitting Patches,,, guix,
GNU Guix Reference Manual}).
@end itemize

Keď ste spokojní s výsledkom, privítame, ak nám zašlete váš príspevok, aby
sa mohol stať súčasťou Guixu. Tento postup je tiež opísaný v
príručke. (@pxref{Contributing,,, guix, GNU Guix Reference Manual})


Guix závisí od spoločného úsilia, preto čím viac ľudí prispeje, tým bude
Guix lepší!

@node Zložitejší príklad
@subsection Zložitejší príklad

Vyššie uvedený príklad zadania balíka „Ahoj svet“ je taký jednoduchý ako sa
len dá. Avšak, zadania balíkov môžu byť zložitejšie a Guix si poradí aj s
omnoho náročnejšími balíkmi. Pozrime sa teda na iné, zložitejšie zadanie
balíka (mierne upravené v porovnaní s pôvodným zadaním):

@lisp
(define-module (gnu packages version-control)
  #:use-module ((guix licenses) #:prefix license:)
  #:use-module (guix utils)
  #:use-module (guix packages)
  #:use-module (guix git-download)
  #:use-module (guix build-system cmake)
  #:use-module (gnu packages)
  #:use-module (gnu packages compression)
  #:use-module (gnu packages pkg-config)
  #:use-module (gnu packages python)
  #:use-module (gnu packages ssh)
  #:use-module (gnu packages tls)
  #:use-module (gnu packages web))

(define-public my-libgit2
  (let ((commit "e98d0a37c93574d2c6107bf7f31140b548c6a7bf")
        (revision "1"))
    (package
      (name "my-libgit2")
      (version (git-version "0.26.6" revision commit))
      (source (origin
                (method git-fetch)
                (uri (git-reference
                      (url "https://github.com/libgit2/libgit2/")
                      (commit commit)))
                (file-name (git-file-name name version))
                (sha256
                 (base32
                  "17pjvprmdrx4h6bb1hhc98w9qi6ki7yl57f090n9kbhswxqfs7s3"))
                (patches (search-patches "libgit2-mtime-0.patch"))
                (modules '((guix build utils)))
                ;; Odstrániť pribalený softvér.
                (snippet '(delete-file-recursively "deps"))))
      (build-system cmake-build-system)
      (outputs '("out" "debug"))
      (arguments
       `(#:tests? #true                         ; Preveriť výsledok zostavenia (predvolené).
         #:configure-flags '("-DUSE_SHA1DC=ON") ; Zisťovanie rozporov v odtlačkoch SHA-1
         #:phases
         (modify-phases %standard-phases
           (add-after 'unpack 'fix-hardcoded-paths
             (lambda _
               (substitute* "tests/repo/init.c"
                 (("#!/bin/sh") (string-append "#!" (which "sh"))))
               (substitute* "tests/clar/fs.h"
                 (("/bin/cp") (which "cp"))
                 (("/bin/rm") (which "rm")))))
           ;; Bohatší výstup pri preverovaní zostavenia
           (replace 'check\n"
             (lambda* (#:key tests? #:allow-other-keys)\n"
               (when tests?\n"
                 (invoke \"./libgit2_clar\" \"-v\" \"-Q\"))))\n"
           (add-after 'unpack 'make-files-writable-for-tests
             (lambda _ (for-each make-file-writable (find-files "." ".*")))))))
      (inputs
       (list libssh2 http-parser python-wrapper))
      (native-inputs
       (list pkg-config))
      (propagated-inputs
       ;; Tieto dve knižnice sa nachádzajú v „Requires.private“ v libgit2.pc.
       (list openssl zlib))
      (home-page "https://libgit2.github.com/")
      (synopsis "Library providing Git core methods")
      (description
       "Libgit2 is a portable, pure C implementation of the Git core methods
provided as a re-entrant linkable library with a solid API, allowing you to
write native speed custom Git applications in any language with bindings.")
      ;; GPLv2 s odkazovou výnimkou
      (license license:gpl2))))
@end lisp

(V prípade, že chcete zmeniť len pár polí v pôvodnom zadaní balíka by ste sa
mali spoľahnúť na dedičnosť namiesto skopírovania celého zadania. Viď
nižšie.)

Pozrime sa teraz na tieto polia zblízka.

@subsubsection spôsob @code{git-fetch}

Narozdiel od funkcie @code{url-fetch}, @code{git-fetch} vyžaduje
@code{git-reference}, ktorú určuje Git repozitár a príslušná úprava. Úpravou
sa rozumie akýkoľvek odkaz Git ako napríklad značka. Teda, ak je
@code{version} označená, tak je možné použiť priamo číslo verzie. Niekedy
majú značky verzií perdponu @code{v}. V tomto prípade môžete použiť
@code{(commit (string-append "v" version))}.

Aby sme sa uistili, že sa zdrojový kód z Git repozitára uloží do priečinka s
výstižným názvom, použijeme @code{(file-name (git-file-name name version))}.

Keď zadávate balík pre program s určitým číslom úpravy, môžete pre odvodenie
správneho označenia verzie použiť funkciu @code{git-version} podľa pokynov v
príručke prispievateľa do Guixu (@pxref{Version Numbers,,, guix, GNU Guix
Reference Manual}).

Pýtate sa ako získať správny odtlačok @code{sha256}? Vyvolaním @command{guix
hash} na miestnej kópii repozitára v požadovanej úprave, asi takto:

@example
git clone https://github.com/libgit2/libgit2/
cd libgit2
git checkout v0.26.6
guix hash -rx .
@end example

@command{guix hash -rx} vypočíta odtlačok SHA256 celého priečinka
nezahŕňajúc pod-priečinok @file{.git} (@pxref{Invoking guix hash,,, guix,
GNU Guix Reference Manual}).

Do budúcna bude snáď @command{guix download} schopný vykonávať tieto kroky
za vás, tak ako je tomu pri bežných sťahovaniach súborov.

@subsubsection Kusy kódu

Kusy kódu predstavujú malé časti Scheme kódu v úvodzovkách, t.j. bežne
nevykonávané, ktoré sa používajú na plátanie zdrojových súborov. Je to taká
Guixová náhrada za dobre známe @file{.patch} súbory. Vďaka úvodzovkám sa
daný kód vykoná len vtedy, keď sa odošle démonovi Guixu na zostavenie. V
praxi môžeme použiť toľko kusov kódu, koľko potrebujeme.

Kusy kódu môžu vyžadovať prídavné moduly Guilu, ktoré je možné načítať
pomocou poľa @code{modules}.

@subsubsection Vstupy

Jestvujú tri rôzne druhy vstupov. V skratke:

@table @asis
@item native-inputs
Vyžadované pri zostavovaní ale nie pri spúšťaní. V prípade inštalácie balíka
prostredníctvom náhrady sa tieto vstupy nebudú inštalovať.
@item inputs
Inštalované do úložiska ale nie do profilu a prítomné pri zostavovaní.
@item propagated-inputs
Inštalované do úložiska aj do profilu a prítomné pri zostavovaní.
@end table

@xref{package Reference,,, guix, GNU Guix Reference Manual} pre viac
podrobností.

Správne rozlišovanie medzi jednotlivými druhmi vstupov je dôležité: ak je
možné závislosť zaradiť ako @emph{input} namiesto @emph{propagated input},
tak by sa to tak malo urobiť. Inak bezdôvodne „znečistí“ používateľský
profil.

Napríklad, ak inštalujete grafický program, ktorý závisí na nejakom nástroji
spúšťanom v príkazovom riadku, tak vám pravdepodobne ide len o tú grafickú
časť. Nie je teda potrebné siliť inštaláciu nástroja spúšťaného v príkazovom
riadku do používateľského profilu. Závislosti sú spravované balíkmi a nie
používateľmi. @emph{Vstupy} umožňujú spravovať závislosti bez toho, aby to
nejako zaťažovalo používateľov pridávaním neužitočných programov či knižníc
do ich profilu.

Rovnako to platí aj pre @emph{native-inputs}: po inštalácii programu môžu
byť závislosti vyžadované pri zostavovaní bezpečne odstránené zberačom
odpadkov. Okrem toho, ak je dostupná binárna náhrada, stiahnu sa len
@emph{inputs} a @emph{propagated inputs}: @emph{native inputs} nie sú pri
inštalácii balíka prostredníctvom náhrady potrebné.

@quotation Poznámka
Tu a tam nájdete úryvky, v ktorých sú vstupy zapísané pomerne odlišne, teda
asi takto:

@lisp
;; „Pôvodný tvar“ zápisu vstupov
(inputs
 `(("libssh2" ,libssh2)
   ("http-parser" ,http-parser)
   ("python" ,python-wrapper)))
@end lisp

Toto je „pôvodný tvar“, v ktorom má každá položka zoznamu vstupov pridelenú
menovku (reťazec).  Tento tvar je stále podporovaný ale odporúčame vám
používať už len vyššie uvedený tvar.  Viď @ref{package Reference,,, guix,
GNU Guix Reference Manual} pre viac podrobností.
@end quotation

@subsubsection Výstupy

Tak ako môže mať balík viacero vstupov, môže mať aj viacero výstupov.

Každý výstup má osobitný priečinok v úložisku.

Používateľ si môže vybrať, ktorý výstup nainštaluje; pomáha to šetriť úložné
miesto a predchádzať znečisteniu používateľského profilu nechcenými
programami či knižnicami.

Oddeľovanie výstupov je voliteľné. Ak sa pole @code{outputs} vynechá,
predvoleným a jediným výstupom (celý balík) bude @code{"out"}.

Často vidíme oddelené výstupy s názvom @code{debug} alebo @code{doc}.

Oddelené výstupy by ste mali používať len vtedy, keď sa to oplatí: ak je
výstup značne veľký (možno porovnať pomocou @code{guix size}), alebo ak je
balík modulárny.

@subsubsection Argumenty zostavovacieho systému

Pole @code{arguments} obsahuje páry kľúč-hodnota používané pri nastavovaní
postupu zostavenia.

Ten najjednoduchší argument @code{#:tests?} možno použiť na vynechanie
testov po zostavení balíka. Je to užitočné najmä v prípade, keď balík
neobsahuje žiadnu testovaciu súpravu. Je dôrazne odporúčané ponechať
testovaciu súpravu povolenú, ak je nejaká dostupná.

Ďalším bežným argumentom je @code{:make-flags} určujúci zoznam dodatočných
príznakov, ktoré sa majú použiť pri spúšťaní nástroja make ako keby ste
pridali priamo do príkazového riadku. Napríklad, nasledovné príznaky

@lisp
#:make-flags (list (string-append "prefix=" (assoc-ref %outputs "out"))
                   "CC=gcc")
@end lisp

sú chápané ako

@example
$ make CC=gcc prefix=/gnu/store/...-<out>
@end example

Toto nastaví prekladač jazyka C na @code{gcc} a premennú @code{prefix}
(cieľový priečinok inštalácie v prípade nástroja Make) na @code{(assoc-ref
%outputs "out")}, čo predstavuje globálnu premennú prítomnú pri zostavovaní,
ktorá udáva cestu k cieľovému priečinku v úložisku (niečo ako
@file{/gnu/store/...-my-libgit2-20180408}).

Podobným spôsobom môžete nastaviť aj príznaky nastavenia:

@lisp
#:configure-flags '("-DUSE_SHA1DC=ON")
@end lisp

Dostupná je aj premenná @code{%build-inputs}. Predstavuje tabuľku, ktorá
priraďuje názvy vstupov k ich priečinkom v úložisku.

Kľúčové slovo @code{phases} predstavuje postupnosť krokov zostavovacieho
systému. Medzi bežné kroky patria @code{unpack}, @code{configure},
@code{build}, @code{install} a @code{check}. Ak chcete o týchto krokoch
zistiť viac, musíte nájsť to správne zadanie zostavovacieho systému v
@samp{$GUIX_CHECKOUT/guix/build/gnu-build-system.scm}:

@lisp
(define %standard-phases
  ;; Standard build phases, as a list of symbol/procedure pairs.
  (let-syntax ((phases (syntax-rules ()
                         ((_ p ...) `((p . ,p) ...)))))
    (phases set-SOURCE-DATE-EPOCH set-paths install-locale unpack
            bootstrap
            patch-usr-bin-file
            patch-source-shebangs configure patch-generated-file-shebangs
            build check install
            patch-shebangs strip
            validate-runpath
            validate-documentation-location
            delete-info-dir-file
            patch-dot-desktop-files
            make-dynamic-linker-cache
            install-license-files
            reset-gzip-timestamps
            compress-documentation)))
@end lisp

Alebo cez REPL:

@lisp
(add-to-load-path "/path/to/guix/checkout")
,use (guix build gnu-build-system)
(map car %standard-phases)
@result{} (set-SOURCE-DATE-EPOCH set-paths install-locale unpack bootstrap patch-usr-bin-file patch-source-shebangs configure patch-generated-file-shebangs build check install patch-shebangs strip validate-runpath validate-documentation-location delete-info-dir-file patch-dot-desktop-files make-dynamic-linker-cache install-license-files reset-gzip-timestamps compress-documentation)
@end lisp

Ak chcete vedieť čo sa počas jednotlivých krokov odohráva, preštudujte si
príslušné funkcie.

Napríklad, v čase písania týchto riadkov, bolo zadanie kroku @code{unpack} v
zostavovacom systéme GNU nasledovné:

@lisp
(define* (unpack #:key source #:allow-other-keys)
  "Unpack SOURCE in the working directory, and change directory within the
source.  When SOURCE is a directory, copy it in a sub-directory of the current
working directory."
  (if (file-is-directory? source)
      (begin
        (mkdir "source")
        (chdir "source")

        ;; Preserve timestamps (set to the Epoch) on the copied tree so that
        ;; things work deterministically.
        (copy-recursively source "."
                          #:keep-mtime? #t)
        ;; Make the source checkout files writable, for convenience.
        (for-each (lambda (f)
                    (false-if-exception (make-file-writable f)))
                  (find-files ".")))
      (begin
        (cond
         ((string-suffix? ".zip" source)
          (invoke "unzip" source))
         ((tarball? source)
          (invoke "tar" "xvf" source))
         (else
          (let ((name (strip-store-file-name source))
                (command (compressor source)))
            (copy-file source name)
            (when command
              (invoke command "--decompress" name)))))
        ;; Attempt to change into child directory.
        (and=> (first-subdirectory ".") chdir))))
@end lisp

Všimnite si volanie @code{chdir}: zmení súčasný priečinok na umiestnenie,
kde boli rozbalené zdrojové súbory. To znamená, že kroky nasledujúce po
@code{unpack} použijú priečinok so zdrojovými súbormi ako ich pracovný
priečinok. Preto môžeme priamo narábať so zdrojovými súbormi. Teda aspoň
dovtedy, kým niektorý ďalší krok nezmení pracovný priečinok na iný.

Zoznam krokov @code{%standard-phases} zostavovacieho systému upravujeme
pomocou makra @code{modify-phases} určujúceho aké úpravy sa majú vykonať, čo
môže vyzerať asi takto:

@itemize
@item
@code{(add-before @var{krok} @var{novy-krok} @var{funkcia})}: Spustiť
@var{funkcia} s názvom @var{novy-krok} pred @var{krok}.
@item
@code{(add-after @var{krok} @var{novy-krok} @var{funkcia})}: Tak isto, ale
za @var{krok}.
@item
@code{(replace @var{krok} @var{funkcia})}.
@item
@code{(delete @var{krok})}.
@end itemize

@var{Funkcia} prijíma parametre @code{inputs} a @code{outputs} v tvare
kľúčových slov.  Každý vstup (či už @emph{pôvodný}, @emph{rozšírený} alebo
nie) a výstupný priečinok je označený svojim názvom v týchto premenných.
Takže @code{(assoc-ref outputs "out")} predstavuje priečinok úložiska
hlavného výstupu balíka.  Funkcia kroku vyzerá nasledovne:

@lisp
(lambda* (#:key inputs outputs #:allow-other-keys)
  (let ((bash-directory (assoc-ref inputs "bash"))
        (output-directory (assoc-ref outputs "out"))
        (doc-directory (assoc-ref outputs "doc")))
    ;; ... ))
@end lisp

Its return value is ignored.

@subsubsection Oddialené vykonanie

Ak ste boli pozorní, mohli ste si všimnúť obrátenú úvodzovku a čiarku v poli
parametrov.  Vskutku, zdrojový kód zostavenia v zadaní balíka by sa nemal
vykonávať na strane klienta, ale až vtedy, keď sa odovzdá démonovi Guixu.
Toto odovzdávanie zdrojového kódu medzi dvoma procesmi nazývame
@uref{https://arxiv.org/abs/1709.00833, oddialené vykonanie}.

@subsubsection Pomocné funkcie

Pri prispôsobovaní @code{phases} budete často potrebovať funkcie
zodpovedajúce systémovým volaniam (@code{make}, @code{mkdir}, @code{cp},
atď.), ktoré sú zvyčajne dostupné na Unixových systémoch.

Niektoré z nich, ako napríklad @code{chmod}, sú priamo dostupné v jazyku
Guile.  Viď úplný zoznam v @ref{,,, guile, Guile reference manual}.

Guix poskytuje ďalšie pomocné funkcie, užitočné najmä v súvislosti so
správou balíkov.

Niektoré z týchto funkcií sa nachádzajú v
@samp{$GUIX_CHECKOUT/guix/guix/build/utils.scm}.  Väčšinou napodobňujú
správanie pôvodných Unixových systémových príkazov:

@table @code
@item which
Rovnaká ako systémový príkaz @samp{which}.
@item find-files
Podobná príkazu @samp{find}.
@item mkdir-p
Rovnaká ako príkaz @samp{mkdir -p}, ktorý v prípade potreby vytvorí aj
všetky nadradené priečinky.
@item install-file
Podobná ako príkaz @samp{install} na inštaláciu súboru do priečinka (aj
nejestvujúceho). Guile má funkciu @code{copy-file}, ktorá funguje ako príkaz
@samp{cp}.
@item copy-recursively
Ako @samp{cp -r}.
@item delete-file-recursively
Ako @samp{rm -rf}.
@item invoke
Vyvolať spustiteľný súbor.  Toto by ste mali používať namiesto
@code{system*}.
@item with-directory-excursion
Vykoná telo funkcie v odlišnom pracovnom priečinku a následne obnoví pôvodný
pracovný priečinok.
@item substitute*
Funkcia podobná príkazu @command{sed}.
@end table

Viď @ref{Build Utilities,,, guix, GNU Guix Reference Manual} pre viac
podrobností o pomocných funkciách.

@subsubsection Predpony modulov

Licencia v našom predošlom príklade je uvedená s predponou vzhľadom na
spôsob akým bol načítaný modul @code{licenses} v tomto balíku:
@code{#:use-module ((guix licenses) #:prefix license:)}.  Spôsob načítavania
modulov v Guile (@pxref{Using Guile Modules,,, guile, Guile reference
manual}) používateľovi dáva úplnú kontrolu nad menným priestorom.  Môže sa
tak predísť rozporom, povedzme, medzi premennou @samp{zlib} zo súboru
@samp{licenses.scm} (názov @emph{licencie}) a premennou @samp{zlib} zo
súboru @samp{compression.scm} (názov @emph{balíka}).

@node Ďalšie zostavovacie systémy
@subsection Ďalšie zostavovacie systémy

To čo sme doteraz videli pokrýva väčšinu balíkov využívajúcich iný
zostavovací systém ako je @code{trivial-build-system}, ktorý nič
neautomatizuje a nechá vás všetko zostaviť ručne.  Tento postup môže byť
náročnejší a zatiaľ sa tu ním nebudeme zaoberať.  Našťastie je nutné uchýliť
sa k nemu len zriedkavo.

Pri ostatných zostavovacích systémoch, ako sú ASDF, Emacs, Perl, Ruby a
mnoho ďalších, je postup, okrem niekoľkých zvláštnych parametrov, veľmi
podobný zostavovaciemu systému GNU.

Viď @ref{Build Systems,,, guix, GNU Guix Reference Manual} alebo zdrojový
kód v priečinkoch @samp{$GUIX_CHECKOUT/guix/build} a
@samp{$GUIX_CHECKOUT/guix/build-system} pre viac podrobností o zostavovacích
systémoch.

@node Programovateľné a automatické zadávanie balíkov
@subsection Programovateľné a automatické zadávanie balíkov

Nemôžme to nezdôrazniť: mať po ruke plnohodnotný programovací jazyk nám
umožňuje oveľa viac než len bežnú správu balíkov.

Ukážme si to na príklade niekoľkých úžasných súčastí Guixu!

@menu
* Rekurzívne nahrávače::     Rekurzívne nahrávače
* Automatické aktualizácie::  Automatické aktualizácie
* Dedičnosť::                Dedičnosť
@end menu

@node Rekurzívne nahrávače
@subsubsection Rekurzívne nahrávače

Niektoré zostavovacie systémy sú natoľko dobré, že toho na zadanie balíka
ani veľa netreba, a to až do takej miery, že sa vám zadávanie balíkov rýchlo
zunuje.  Jedným z dôvodov bytia počítačov je nahradiť ľudí pri vykonávaní
týchto nudných činností.  Nechajme teda Guix urobiť to za nás a vytvoriť
zadanie nejakého balíka R pochádzajúceho z CRANu (výstup bol skrátený pre
ušetrenie miesta):

@example
$ guix import cran --recursive walrus

(define-public r-mc2d
    ; ...
    (license gpl2+)))

(define-public r-jmvcore
    ; ...
    (license gpl2+)))

(define-public r-wrs2
    ; ...
    (license gpl3)))

(define-public r-walrus
  (package
    (name "r-walrus")
    (version "1.0.3")
    (source
      (origin
        (method url-fetch)
        (uri (cran-uri "walrus" version))
        (sha256
          (base32
            "1nk2glcvy4hyksl5ipq2mz8jy4fss90hx6cq98m3w96kzjni6jjj"))))
    (build-system r-build-system)
    (propagated-inputs
      (list r-ggplot2 r-jmvcore r-r6 r-wrs2))
    (home-page "https://github.com/jamovi/walrus")
    (synopsis "Robust Statistical Methods")
    (description
      "This package provides a toolbox of common robust statistical
tests, including robust descriptives, robust t-tests, and robust ANOVA.
It is also available as a module for 'jamovi' (see
<https://www.jamovi.org> for more information).  Walrus is based on the
WRS2 package by Patrick Mair, which is in turn based on the scripts and
work of Rand Wilcox.  These analyses are described in depth in the book
'Introduction to Robust Estimation & Hypothesis Testing'.")
    (license gpl3)))
@end example

Rekurzívny nahrávač nahrá len balíky, pre ktoré Guix ešte nemá zadanie,
okrem úplne prvého.

Takto vytvoriť zadania balíkov nie je možné pre všetky aplikácie, iba pre
tie, ktoré sa opierajú o vybraný počet podporovaných systémov.  Viď úplný
zoznam nahrávačov v príslušnom oddiele príručky (@pxref{Invoking guix
import,,, guix, GNU Guix Reference Manual}).

@node Automatické aktualizácie
@subsubsection Automatické aktualizácie

Guix môže byť dostatočne múdry na to, aby vyhľadal aktualizácie v systémoch,
ktoré pozná.  To, ktoré balíky sú zastarané možno zistiť pomocou

@example
$ guix refresh hello
@end example

Vo väčšine prípadov vyžaduje aktualizácia balíka na novšiu verziu len o
niečo viac ako zmeniť číslo verzie a kontrolný súčet.  Aj toto môže Guix
vykonať automaticky:

@example
$ guix refresh hello --update
@end example

@node Dedičnosť
@subsubsection Dedičnosť

Ak ste si už začali prezerať zadania jestvujúcich balíkov, možno ste si
všimli, že niektoré z nich obsahujú pole @code{inherit}:

@lisp
(define-public adwaita-icon-theme
  (package (inherit gnome-icon-theme)
    (name "adwaita-icon-theme")
    (version "3.26.1")
    (source (origin
              (method url-fetch)
              (uri (string-append "mirror://gnome/sources/" name "/"
                                  (version-major+minor version) "/"
                                  name "-" version ".tar.xz"))
              (sha256
               (base32
                "17fpahgh5dyckgz7rwqvzgnhx53cx9kr2xw0szprc6bnqy977fi8"))))
    (native-inputs (list `(,gtk+ "bin")))))
@end lisp

Všetky neupresnené polia sú zdedené z nadradeného balíka.  Je to veľmi
užitočné na vytváranie obmien balíkov, napr. s odlišným zdrojom, verziou
alebo voľbami zostavenia.

@node Získavanie pomoci
@subsection Získavanie pomoci

Nanešťastie, zadanie balíka môže byť pre niektoré aplikácie veľmi zložité.
Niekedy je potrebná záplata, aby mohla aplikácia fungovať v neobyčajnom
systéme súborov úložiska. Niekedy sa zase sústava testov nespúšťa správne
(môžete ich preskočiť ale neodporúča sa to).  Inokedy nie je výsledný balík
opakovateľný.

Keď už neviete ako ďalej a nie ste schopní prísť na to, ako vyriešiť nejakú
ťažkosť so zadávaním balíka, neváhajte požiadať o pomoc spoločenstvo.

Viď @uref{https://guix.gnu.org/contact/, Guix homepage} pre podrobnosti o
elektronických konferenciách, IRC, atď.

@node Záver
@subsection Záver

Tento návod vám predviedol vyumelkovanú správu balíkov, ktorou sa Guix
chváli.  V tejto chvíli sme tento úvod zúžili na @code{gnu-build-system}
predstavujúci ústrednú abstrakčnú vrstvu, na ktorej sú založené
pokročilejšie abstrakčné vrstvy.

Kam teraz? Ďalej by sme si mali posvietiť na vnútorné fungovanie
zostavovacích systémov vynechajúc všetky abstrakčné vrstvy prostredníctvom
@code{trivial-build-system}. Malo by nám to umožniť lepšie porozumieť
postupu zostavenia, skôr ako sa dostaneme k pokročilejším postupom a
výnimkám.

Ďalšie funkcie, ktoré sa oplatí preskúmať, sú interaktívna úprava a možnosti
ladenia Guixu poskytované cez Guile REPL@.

Tieto pokročilé funkcie sú len doplnkové a môžu počkať. Teraz je ten správny
čas na zaslúženú prestávku.  S tým, čo sme si ukázali, by ste si mali
vystačiť pri zadávaní balíkov pre mnoho programov.  Môžete sa do toho hneď
pustiť a dúfame, že nás vašim príspevkom potešíte už čoskoro!

@node Odkazy
@subsection Odkazy

@itemize
@item
@uref{https://guix.gnu.org/manual/en/html_node/Defining-Packages.html,
odvolávka na „package“ v príručke}

@item
@uref{https://gitlab.com/pjotrp/guix-notes/blob/master/HACKING.org, Pjotrova
príručka na prispôsobenie GNU Guix}

@item
@uref{https://guix.gnu.org/guix-ghm-andreas-20130823.pdf, „GNU Guix: Package
without a scheme!“}, od Andreasa Engeho
@end itemize

@node Packaging Workflows
@section Packaging Workflows

The following sections provide real-life examples on working with specific
build systems, serving as extensions to the concise packaging guidelines
(@pxref{Packaging Guidelines,,, guix, GNU Guix Reference Manual}).

@menu
* Packaging Rust Crates::    Packaging Rust Crates
@end menu

@node Packaging Rust Crates
@subsection Packaging Rust Crates

In preparation, add the following packages to our environment:

@example
$ guix shell rust rust:cargo cargo-audit cargo-license
@end example

@menu
* Common Workflow for Rust Packaging::  Common Workflow for Rust Packaging
* Cargo Workspaces and Development Snapshots::  Cargo Workspaces and 
                                                  Development Snapshots
* Using Rust Libraries in Other Build Systems::  Using Rust Libraries in 
                                                   Other Build Systems
@end menu

@node Common Workflow for Rust Packaging
@subsubsection Common Workflow for Rust Packaging

In this example, we'll package @code{cargo-audit}, which is published on the
@uref{https://crates.io, crates.io} Rust package repository.  All its
dependencies are on crates.io as well.

@enumerate
@item
Since @code{cargo-audit} is available on crates.io, we can generate a
template via the crates.io importer (@pxref{Invoking guix import,,, guix,
GNU Guix Reference Manual}):

@example
$ guix import crate cargo-audit
@end example

After manual editing, we'll have the following definiton:

@lisp
(define-public cargo-audit
  (package
    (name "cargo-audit")
    (version "0.21.2")
    (source
     (origin
       (method url-fetch)
       (uri (crate-uri "cargo-audit" version))
       (file-name (string-append name "-" version ".tar.gz"))
       (sha256
        (base32 "1a00yqpckkw86zh2hg7ra82c5fx0ird5766dyynimbvqiwg2ps0n"))))
    (build-system cargo-build-system)
    (arguments (list #:install-source? #f))
    (inputs (cargo-inputs 'cargo-audit))
    (home-page "https://rustsec.org/")
    (synopsis "Audit Cargo.lock for crates with security vulnerabilities")
    (description
     "This package provides a Cargo subcommand, @@command@{cargo audit@}, to
audit @@file@{Cargo.lock@} for crates with security vulnerabilities.")
    (license (list license:asl2.0 license:expat))))
@end lisp

The identifier used to invoke @code{cargo-inputs}, in this case
@code{'cargo-audit}, must be unique, usually matching the variable name of
the package.

@item
Unpack package source and navigate to the unpacked directory, then run the
following commands:

@example
$ cargo generate-lockfile
$ cargo audit
$ cargo license
@end example

@command{cargo generate-lockfile} updates dependencies to compatible
versions.  Applying it to all Rust applications helps reduce a great number
of Rust libraries we need to check later.  Although sometimes libraries may
fail to follow the @uref{https://semver.org/, semantic versioning} scheme,
it's still acceptable.

@command{cargo audit} checks known vulnerabilities and @command{cargo
license} checks licenses, for all the dependencies.  We must have an
acceptable output of @command{cargo audit} and ensure all dependencies are
licensed with our supported licenses (@pxref{Defining Packages,,, guix, GNU
Guix Reference Manual}).

@item
Import dependencies from the generated lockfile:

@example
$ guix import --insert=gnu/packages/rust-crates.scm \
      crate --lockfile=/path/to/Cargo.lock cargo-audit

# Or use short options, in this case the shell processes file names
# before passing them to Guix, allowing tilde expansion, for example.
$ guix import -i gnu/packages/rust-crates.scm \
      crate -f /path/to/Cargo.lock cargo-audit
@end example

@code{cargo-audit} here must be consistent with the identifier used for
@code{cargo-inputs} invocation in the package definition.

At this stage, the package @code{cargo-audit} is buildable.

@item
Finally we'll unbundle the vendored dependencies.  The lockfile importer
inserts @code{TODO REVIEW:} comments for libraries with high probability of
bundled dependencies.  @code{cargo-build-system} also performs additional
check for binary files in its @code{check-for-pregenerated-files} phase,
which usually indicates bundling:

@example
$ ./pre-inst-env guix build cargo-audit
@dots{}
starting phase `check-for-pregenerated-files'
Searching for binary files...
./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/dictionary-rust
./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/dictionary-rust-other
./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/lib.rs.zst
./guix-vendor/rust-async-compression-0.4.21.tar.gz/tests/artifacts/long-window-size-lib.rs.zst
./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_aclui.a
./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_activeds.a
./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_asycfilt.a
./guix-vendor/rust-winapi-i686-pc-windows-gnu-0.4.0.tar.gz/lib/libwinapi_amsi.a
@dots{}
@end example

Although Rust libraries are not publicly exported, we can still select them
via the Guix command-line interface via a Guile expression:

@example
$ guix build --expression='(@@@@ (gnu packages rust-crates) rust-ring-0.17.14)'
@end example

To unbundle most dependencies, a snippet is sufficient:

@lisp
(define rust-curl-sys-0.4.80+curl-8.12.1
  (crate-source "curl-sys" "0.4.80+curl-8.12.1"
                "0d7ppx4kq77hc5nyff6jydmfabpgd0i3ppjvn8x0q833mhpdzxsm"
                #:snippet '(delete-file-recursively "curl")))
@end lisp

@lisp
(define rust-bzip2-sys-0.1.13+1.0.8
  (crate-source "bzip2-sys" "0.1.13+1.0.8"
                "056c39pgjh4272bdslv445f5ry64xvb0f7nph3z7860ln8rzynr2"
                #:snippet
                '(begin
                   (delete-file-recursively "bzip2-1.0.8")
                   (delete-file "build.rs")
                   (with-output-to-file "build.rs"
                     (lambda _
                       (format #t "fn main() @{~@@
                        println!(\"cargo:rustc-link-lib=bz2\");~@@
                        @}~%"))))))
@end lisp

In a more complex case, where unbundling one dependency requires a build
process that involves other packages, we should make a full package in
@code{(gnu packages rust-sources)} first and reference it in the imported
definition.

For example, we have defined a @code{rust-ring-0.17} in @code{(gnu packages
rust-sources)}, then the imported definition in @code{(gnu packages
rust-crates)} should be modified to reference it.

@lisp
(define rust-ring-0.17.14 rust-ring-0.17)
@end lisp

When one dependency can be safely removed, modify it to @code{#f}.

@lisp
(define rust-openssl-src-300.4.2+3.4.1 #f)
@end lisp

To facilitate various tasks in the common workflow, several scripts are
provided in the @file{etc/teams/rust} directory of Guix source tree.
@end enumerate

@node Cargo Workspaces and Development Snapshots
@subsubsection Cargo Workspaces and Development Snapshots

In this example, we'll package @code{niri}, which depends on development
snapshots (also Cargo workspaces here).

As we can't ensure compatibility of a development snapshot, before executing
@command{cargo generate-lockfile}, we should modify @file{Cargo.toml} to pin
it to a known working revision.

To use our packaged development snapshots, it's also necessary to modify
@file{Cargo.toml} in a build phase, with a package-specific substitution
pattern.

@lisp
(define-public niri
  (package
   (name "niri")
   (version "25.02")
   (source (origin
             (method git-fetch)
             (uri (git-reference
                   (url "https://github.com/YaLTeR/niri")
                   (commit (string-append "v" version))))
             (file-name (git-file-name name version))
             (sha256
              (base32
               "0vzskaalcz6pcml687n54adjddzgf5r07gggc4fhfsa08h1wfd4r"))))
   (build-system cargo-build-system)
   (arguments
    (list #:install-source? #f
          #:phases
          #~(modify-phases %standard-phases
              (add-after 'unpack 'use-guix-vendored-dependencies
                (lambda _
                  (substitute* "Cargo.toml"
                    (("# version =.*")
                     "version = \"*\"")
                    (("git.*optional")
                     "version = \"*\", optional")
                    (("^git = .*")
                     "")))))))
   (native-inputs
    (list pkg-config))
   (inputs
    (cons* clang
           libdisplay-info
           libinput-minimal
           libseat
           libxkbcommon
           mesa
           pango
           pipewire
           wayland
           (cargo-inputs 'niri)))
   (home-page "https://github.com/YaLTeR/niri")
   (synopsis "Scrollable-tiling Wayland compositor")
   (description
    "Niri is a scrollable-tiling Wayland compositor which arranges windows in a
scrollable format.  It is considered stable for daily use and performs most
functions expected of a Wayland compositor.")
   (license license:gpl3+)))
@end lisp

@code{niri} has Cargo workspace dependencies.  When packaging a Cargo
workspace dependency, parameter @code{#:cargo-package-crates} is required.

@lisp
(define-public rust-pipewire-0.8.0.fd3d8f7
  (let ((commit "fd3d8f7861a29c2eeaa4c393402e013578bb36d9")
        (revision "0"))
    (package
      (name "rust-pipewire")
      (version (git-version "0.8.0" revision commit))
      (source
       (origin
         (method git-fetch)
         (uri (git-reference
               (url "https://gitlab.freedesktop.org/pipewire/pipewire-rs.git")
               (commit commit)))
         (file-name (git-file-name name version))
         (sha256
          (base32 "1hzyhz7xg0mz8a5y9j6yil513p1m610q3j9pzf6q55vdh5mcn79v"))))
      (build-system cargo-build-system)
      (arguments
       (list #:skip-build? #t
             #:cargo-package-crates
             ''("libspa-sys" "libspa" "pipewire-sys" "pipewire")))
      (inputs (cargo-inputs 'rust-pipewire-0.8.0.fd3d8f7))
      (home-page "https://pipewire.org/")
      (synopsis "Rust bindings for PipeWire")
      (description "This package provides Rust bindings for PipeWire.")
      (license license:expat))))
@end lisp

Don't forget to modify all workspace members in @code{(gnu packages
rust-crates)}:

@lisp
(define rust-pipewire-0.8.0.fd3d8f7 package:rust-pipewire-0.8.0.fd3d8f7)
(define rust-pipewire-sys-0.8.0.fd3d8f7 package:rust-pipewire-0.8.0.fd3d8f7)
@dots{}
(define rust-libspa-0.8.0.fd3d8f7 package:rust-pipewire-0.8.0.fd3d8f7)
(define rust-libspa-sys-0.8.0.fd3d8f7 package:rust-pipewire-0.8.0.fd3d8f7)
@end lisp

@node Using Rust Libraries in Other Build Systems
@subsubsection Using Rust Libraries in Other Build Systems

In this example, we'll package @code{libchewing}, which combines two build
systems.

When building Rust packages in other build systems, we need to add
@code{rust}, and @code{rust:cargo} to @code{native-inputs}, import and use
modules from both build systems, and apply necessary build phases from
@code{cargo-build-system}.

For cross-compilation support, we'll also add @code{rust-sysroot} created
with @code{(make-rust-sysroot (%current-target-system))} to
@code{native-inputs}, and set @code{#:cargo-target} for
@code{cargo-build-system}'s build phases.

@lisp
(define-public libchewing
  (package
    (name "libchewing")
    (version "0.9.1")
    (source
     (origin
       (method git-fetch)
       (uri (git-reference
             (url "https://github.com/chewing/libchewing")
             (commit (string-append "v" version))))
       (file-name (git-file-name name version))
       (sha256
        (base32 "0gh64wvrk5pn0fhmpvj1j99d5g7f7697rk96zbkc8l72yjr819z5"))))
    (build-system cmake-build-system)
    (arguments
     (list #:imported-modules
           (append %cmake-build-system-modules
                   %cargo-build-system-modules)
           #:modules
           '(((guix build cargo-build-system) #:prefix cargo:)
             (guix build cmake-build-system)
             (guix build utils))
           #:phases
           #~(modify-phases %standard-phases
               (add-after 'unpack 'prepare-cargo-build-system
                 (lambda args
                   (for-each
                    (lambda (phase)
                      (format #t "Running cargo phase: ~a~%" phase)
                      (apply (assoc-ref cargo:%standard-phases phase)
                             ;; For cross-compilation.
                             #:cargo-target #$(cargo-triplet)
                             args))
                    '(unpack-rust-crates
                      configure
                      check-for-pregenerated-files
                      patch-cargo-checksums)))))))
    (native-inputs
     (append
      (list rust `(,rust "cargo") )
      ;; For cross-compilation.
      (or (and=> (%current-target-system)
                 (compose list make-rust-sysroot))
          '())))
    (inputs
     (cons* corrosion ncurses sqlite (cargo-inputs 'libchewing)))
    (synopsis "Chinese phonetic input method")
    (description "Chewing is an intelligent phonetic (Zhuyin/Bopomofo) input
method, one of the most popular choices for Traditional Chinese users.")
    (home-page "https://chewing.im/")
    (license license:lgpl2.1+)))
@end lisp


@c *********************************************************************
@node Nastavenie systému
@chapter Nastavenie systému

Guix ponúka všestranný jazyk na deklaratívne nastavenie vášho systému Guix.
Táto všestrannosť sa môže niekedy zdať nadmerná.  Účelom tohto oddielu je
predstaviť niektoré pokročilé spôsoby nastavenia.

Viď úplnú odvolávku v @pxref{System Configuration,,, guix, GNU Guix
Reference Manual}.

@menu
* Automatické pripojenie k určitému TTY::  Automaticky pripojiť používateľa 
                                             k určitému TTY
* Prispôsobenie jadra::      Vytvorenie a používanie vlastného Linuxového 
                               jadra v systéme Guix.
* API pre vytváranie obrazov systému Guix::  Prispôsobenie obrazov 
                                               nezvyčajným platformám.
* Používanie bezpečnostných kľúčov::  Ako používať bezpečnostné kľúče so 
                                        systémom Guix.
* mcron úloha pre dynamický DNS::  Úloha na aktualizovanie IP adresy v 
                                     pozadí názvu hostiteľa DuckDNS.
* Pripojenie k Wireguard VPN::  Pripojenie k Wireguard VPN sieti.
* Prispôsobenie správcu okien::  Spravovať prispôsobenie správcu okien v 
                                   systéme Guix.
* Spúšťanie Guixu na serveri Linode::  Spúšťanie Guixu na serveri Linode.
* Spúšťanie Guixu na Kimsufi serveri::  Spúšťanie Guixu na Kimsufi serveri.
* Nastavenie podvojného pripojenia::  Nastavenie podvojného pripojenia v 
                                        zadaní systému súborov.
* Získavanie náhrad prostredníctvom Tor::  Nastavenie démona Guix na 
                                             získavanie náhrad cez Tor.
* Nastavenia NGINX a Lua::   Nastavenie web-servera NGINX na načítavanie Lua 
                               modulov.
* Hudobný server so zvukom cez Bluetooth::  Bezobrazovkový prehrávač hudby s 
                                              Bluetooth výstupom.
@end menu

@node Automatické pripojenie k určitému TTY
@section Automatické pripojenie k určitému TTY

Zatiaľ čo príručka pre Guix popisuje automatické prihlásenie jedného
používateľa ku @emph{všetkým} TTY (@pxref{auto-login to TTY,,, guix, GNU
Guix Reference Manual}), mohol by vám viac vyhovovať stav, keď je jeden
používateľ pripojený k jednému TTY a ostatné TTY sú nastavené na
prihlasovanie ďalších používateľov alebo nikoho.  Všimnite si, že jedného
používateľa je možné automaticky prihlásiť k akémukoľvek TTY. Avšak, je
lepšie vynechať @code{tty1}, ktorý je predvolene využívaný na zobrazovanie
varovaných a chybových hlásení.

Takto je možné nastaviť automatické prihlásenie jedného používateľa k
jednému TTY:

@lisp
(define (auto-login-to-tty config tty user)
  (if (string=? tty (mingetty-configuration-tty config))
        (mingetty-configuration
         (inherit config)
         (auto-login user))
        config))

(define %my-services
  (modify-services %base-services
    ;; @dots{}
    (mingetty-service-type config =>
                           (auto-login-to-tty
                            config "tty3" "alice"))))

(operating-system
  ;; @dots{}
  (services %my-services))
@end lisp

Tiež je možné použiť @code{compose} (@pxref{Higher-Order Functions,,, guile,
The Guile Reference Manual}) s @code{auto-login-to-tty} pre prihlásenie
viacerých používateľov k viacerým TTY.

Varovanie na koniec.  Nastavenie automatického prihlásenia k TTY znamená, že
ktokoľvek môže zapnúť váš počítač a spúšťať príkazy ako zvyčajný
používateľ.  Hoci, ak používate zašifrovaný koreňový systém a pri spustení
systému je nutné zadať heslo, automatické prihlásenie predstavuje praktickú
možnosť.


@node Prispôsobenie jadra
@section Prispôsobenie jadra

Guix je, vo svojom jadre, distribúcia založená na zdrojových súboroch a
náhradách (@pxref{Substitutes,,, guix, GNU Guix Reference Manual}).
Zostavovanie balíkov z ich zdrojových súborov je teda prirodzenou súčasťou
inštalácie a aktualizácie balíkov.  Vzhľadom na túto skutočnosť dáva zmysel
snaha o zníženie množstva času potrebného na zostavenie balíkov a nedávne
zmeny v zostavovaní a šírení náhrad sú aj naďalej súčasťou rozhovorov vrámci
projektu Guix.

Aj keď nevyžaduje veľké množstvo pamäte RAM, zostavenie jadra na priemerných
počítačoch môže trvať veľmi dlho.  Oficiálne nastavenie jadra, tak ako je to
v prípade mnohých iných distribúcií GNU/Linuxu, sa prikláňa k širšej ponuke
súčastí a to je to, čo spôsobuje, že zostavenie jadra zo zdrojových súborov
trvá tak dlho.

Avšak, aj samotné jadro Linuxu možno opísať ako balík a teda prispôsobiť ho
rovnako ako hociktorý iný balík.  Postup je mierne odlišný, aj keď hlavne
kvôli tomu ako je zadanie balíka napísané.

Balík jadra @code{linux-libre} je vlastne funkcia tvoriaca balík.

@lisp
(define* (make-linux-libre* version gnu-revision source supported-systems
                            #:key
                            (extra-version #f)
                            ;; Funkcia vyžadujúca označenie a druh architektúry.
                            ;; Viď príklad v kernel-config.
                            (configuration-file #f)
                            (defconfig "defconfig")
                            (extra-options (default-extra-linux-options version)))
  ...)
@end lisp

Terajší balík @code{linux-libre} pre vydania 5.15.x je zadaný nasledovne:

@lisp
(define-public linux-libre-5.15
  (make-linux-libre* linux-libre-5.15-version
                     linux-libre-5.15-gnu-revision
                     linux-libre-5.15-source
                     '("x86_64-linux" "i686-linux" "armhf-linux"
                       "aarch64-linux" "riscv64-linux")
                     #:configuration-file kernel-config))
@end lisp

Kľúče, ktoré nemajú pridelenú hodnotu dedia ich predvolenú hodnotu zo
zadania @code{make-linux-libre}.  Pri porovnávaní vyššie uvedených úryvkov
zdrojového kódu si všimnite komentár odvolávajúci sa na
@code{#:configuration-file}.  Kvôli tomu vlastne nie je jednoduché zahrnúť
do zadania svoje vlastné nastavenie jadra, ale nezúfajte, pretože jestvujú
ďalšie spôsoby ako pracovať s tým čo máme.

There are two ways to create a kernel with a custom kernel configuration.
The first is to provide a standard @file{defconfig} to
@code{customize-linux} procedure.  To produce such file you need to obtain
Linux source code, create a @file{.config} file (using @code{make
menuconfig} command, for example) or provide one you already have.  After
that you will need to run @code{make savedefconfig} command within the
kernel source tree---this will produce the @file{defconfig} file which we
will use to build a custom kernel.

Below is a sample kernel package.

@lisp
(define-public my-linux-libre
  (package
    (inherit (customize-linux
              #:linux linux-libre
              #:defconfig
              (local-file "defconfig")))
    (name "my-linux-libre")))
@end lisp

In the same directory as the file defining @code{my-linux-libre} is a file
named @file{defconfig}. This way you can provide kernel options you want to
have in the result kernel.

Druhý spôsob ako vytvoriť vlastné jadro je dať novú hodnotu kľúčovému slovu
@code{extra-options} funkcie @code{make-linux-libre}.  Kľúčové slovo
@code{extra-options} funguje s inou funkciou zadanou nižšie:

@lisp
(define (default-extra-linux-options version)
  `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
   ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true)
   ;; Moduly potrebné pre initrd:
   ("CONFIG_NET_9P" . m)
   ("CONFIG_NET_9P_VIRTIO" . m)
   ("CONFIG_VIRTIO_BLK" . m)
   ("CONFIG_VIRTIO_NET" . m)
   ("CONFIG_VIRTIO_PCI" . m)
   ("CONFIG_VIRTIO_BALLOON" . m)
   ("CONFIG_VIRTIO_MMIO" . m)
   ("CONFIG_FUSE_FS" . m)
   ("CONFIG_CIFS" . m)
   ("CONFIG_9P_FS" . m)))

(define (config->string options)
  (string-join (map (match-lambda
                      ((option . 'm)
                       (string-append option "=m"))
                      ((option . #true)
                       (string-append option "=y"))
                      ((option . #false)
                       (string-append option "=n")))
                    options)
               "\n"))
@end lisp

A vo vlastnom „configure“ skripte balíka „make-linux-libre“:

@lisp
;; Vkladanie na koniec funguje aj keď voľba v súbore nebola.
;; Pri viacnásobnom uvedení prevažuje to posledné.
(let ((port (open-file ".config" "a"))
      (extra-configuration ,(config->string extra-options)))
  (display extra-configuration port)
  (close-port port))

(invoke "make" "oldconfig")
@end lisp

Takže, neposkytnutie súboru nastavenia spôsobí, že je súbor @file{.config}
spočiatku prázdny. Potom doň zapíšeme voľby, ktoré chceme.  Viď ďalšie
vlastné zadanie jadra:

@lisp
(define %macbook41-full-config
  (append %macbook41-config-options
          %file-systems
          %efi-support
          %emulation
          ((@@@@ (gnu packages linux) default-extra-linux-options) version)))

(define-public linux-libre-macbook41
  ;; XXX: Prístup k funkcii „make-linux-libre*“, ktorá je súkromná,
  ;; neexportuje sa a v budúcnosti by sa mohla zmeniť.
  ((@@@@ (gnu packages linux) make-linux-libre*)
   (@@@@ (gnu packages linux) linux-libre-version)
   (@@@@ (gnu packages linux) linux-libre-gnu-revision)
   (@@@@ (gnu packages linux) linux-libre-source)
   '("x86_64-linux")
   #:extra-version "macbook41"
   #:extra-options %macbook41-config-options))
@end lisp

V hore uvedenom príklade je @code{%file-systems} zbierkou volieb
povoľujúcich podporu rôznych súborových systémov, @code{%efi-support}
povoľuje podporu EFI a @code{%emulation} povoľuje strojom x86_64-linux
pracovať v 32-bitovom režime.  Postup @code{default-extra-linux-options} je
ten, ktorý sme zadali už predtým, aby sme zabránili strate prednastavených
volieb kľúčového slova @code{extra-options}.

Všetko toto znie veľmi dobre, ale ako zistiť, ktoré moduly vyžaduje určitý
systém? Na túto otázku nám môžu pomôcť odpovedať dva zdroje:
@uref{https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel,
Príručka Gentoo} a
@uref{https://www.kernel.org/doc/html/latest/admin-guide/README.html?highlight=localmodconfig,
dokumentácia samotného jadra}.  Podľa dokumentácie jadra sa zdá, že
@code{make localmodconfig} je príkaz, ktorý hľadáme.

Skôr ako budeme môcť spustiť @code{make localmodconfig}, musíme stiahnuť a
rozbaliť zdrojové súbory jadra:

@example shell
tar xf $(guix build linux-libre --source)
@end example

V priečinku obsahujúcom zdrojové súbory spustite @code{touch .config} pre
vytvorenie počiatočného prázdneho @file{.config} súboru.  @code{make
localmodconfig} funguje tak, že zistí, čo ste už zadali do @file{.config} a
povie vám, čo vám ešte chýba.  Ak je súbor prázdny, tak vám chýba všetko.
Ďalším krokom je spustiť:

@example shell
guix shell -D linux-libre -- make localmodconfig
@end example

a pozrite si výstup.  Všimnite si, že súbor @file{.config} je stále
prázdny.  Výstup obvykle obsahuje dva druhy varovných správ.  Prvá začína
slovom „WARNING“ a v našom prípade si ju nemusíme všímať.  Druhá správa nám
hovorí, že:

@example shell
module pcspkr did not have configs CONFIG_INPUT_PCSPKR
@end example

Pre každý z týchto riadkov skopírujte časť @code{CONFIG_XXXX_XXXX} do
@file{.config} súboru priečinka a pridajte @code{=m} tak, aby nakoniec
vyzeral takto:

@example shell
CONFIG_INPUT_PCSPKR=m
CONFIG_VIRTIO=m
@end example

Po skopírovaní všetkých volieb nastavenia znova spustite @code{make
localmodconfig}, aby ste sa uistili, že výstup už neobsahuje žiadne správy
začínajúce slovom „module“.  Okrem všetkých týchto modulov vzťahujúcich sa k
stroju nám ostáva ešte niekoľko ďalších dôležitých modulov.
@code{CONFIG_MODULES} umožňuje zostavovať a načítavať moduly oddelene, aby
nemuseli byť zabudované do jadra.  @code{CONFIG_BLK_DEV_SD} umožňuje čítať
pevné disky.  Je tiež možné, že budete potrebovať aj iné moduly.

Tento príspevok nemá za úlohu vás previesť nastavením vášho vlastného
jadra. Ak sa rozhodnete zostaviť si vlastné jadro, budete si musieť nájsť
iné návody na vytvorenie jadra, ktoré vám bude vyhovovať.

Druhý spôsob nastavenia jadra využíva funkcie Guixu vo väčšej miere a
umožňuje vám zdieľať časti nastavenia medzi rôznymi jadrami.  Napríklad,
všetky stroje používajúce na zavádzanie EFI vyžadujú určitý počet volieb
nastavenia EFI.  Je tiež pravdepodobné, že viaceré jadrá budú zdieľať
podporu niekoľkých súborových systémov.  Použitím premenných je jednoduchšie
spozorovať, ktoré súčasti sú povolené a uistiť sa, či nie sú niektoré z nich
prítomné v jednom jadre ale v druhom chýbajú.

Nepozreli sme sa však na initrd a jeho prispôsobenie.  Je pravdepodobné, že
budete potrebovať prispôsobiť initrd na stroji s vlastným jadrom, keďže
niektoré moduly nemusia byť dostupné pre zahrnutie do initrd.

@node API pre vytváranie obrazov systému Guix
@section API pre vytváranie obrazov systému Guix

Z dejinného pohľadu je systém Guix sústredený okolo štruktúry
@code{operating-system}.  Táto štruktúra obsahuje rôzne polia počínajúc
zadaním zavádzača a jadra až k službám, ktoré sa majú nainštalovať.

Požiadavky na obraz sa môžu značne líšiť v závislosti na cieľovom stroji, čo
môže byť obvyklý @code{x86_64} alebo malý jednodoskový počítač ako
Pine64. Výrobcovia technického vybavenia presadzujú rôzne formáty obrazov s
rôznymi veľkosťami a umiestneniami oddielov.

Na vytváranie obrazov vhodných pre všetky tieto stroje je nevyhnutné ďalšie
zovšeobecnenie, čo je cieľom záznamu @code{image}.  Tento záznam obsahuje
všetky potrebné údaje k premene na samostatný obraz, ktorý je možno priamo
zaviesť na hocijakom cieľovom stroji.

@lisp
(define-record-type* <image>
  image make-image
  image?
  (name               image-name ;symbol
                      (default #f))
  (format             image-format) ;symbol
  (target             image-target
                      (default #f))
  (size               image-size  ;size in bytes as integer
                      (default 'guess))
  (operating-system   image-operating-system  ;<operating-system>
                      (default #f))
  (partitions         image-partitions ;list of <partition>
                      (default '()))
  (compression?       image-compression? ;boolean
                      (default #t))
  (volatile-root?     image-volatile-root? ;boolean
                      (default #t))
  (substitutable?     image-substitutable? ;boolean
                      (default #t)))
@end lisp

Tento záznam obsahuje operačný systém na zostavenie. Pole @code{format}
určuje druh obrazu a medzi jeho platné hodnoty patria @code{efi-raw},
@code{qcow2} alebo @code{iso9660}. V budúcnosti by sa mohli rozšíriť o
@code{docker} a ďalšie druhy obrazov.

Na zadávanie obrazov bol spomedzi zdrojových súborov Guixu vyhradený nový
priečinok. Zatiaľ sa v ňom nachádzajú štyri súbory:

@itemize @bullet
@item @file{gnu/system/images/hurd.scm}
@item @file{gnu/system/images/pine64.scm}
@item @file{gnu/system/images/novena.scm}
@item @file{gnu/system/images/pinebook-pro.scm}
@end itemize

Pozrime sa na @file{pine64.scm}. Obsahuje premennú
@code{pine64-barebones-os} predstavujúcu najmenšie možné zadanie operačného
systému určeného pre dosku @b{Pine A64 LTS}.

@lisp
(define pine64-barebones-os
  (operating-system
   (host-name "vignemale")
   (timezone "Europe/Bratislava")
   (locale "sk_SK.utf8")
   (bootloader (bootloader-configuration
                (bootloader u-boot-pine64-lts-bootloader)
                (targets '("/dev/vda"))))
   (initrd-modules '())
   (kernel linux-libre-arm64-generic)
   (file-systems (cons (file-system
                        (device (file-system-label "moj-korenovy-system"))
                        (mount-point "/")
                        (type "ext4"))
                       %base-file-systems))
   (services (cons (service agetty-service-type
                            (agetty-configuration
                             (extra-options '("-L")) ; bez zisťovania nosného signálu
                             (baud-rate "115200")
                             (term "vt100")
                             (tty "ttyS0")))
                   %base-services))))
@end lisp

Polia @code{kernel} a @code{bootloader} odkazujú na balíky určené pre túto
dosku.

Tesne pod nimi je zadaná aj premenná @code{pine64-image-type}.

@lisp
(define pine64-image-type
  (image-type
   (name 'pine64-raw)
   (constructor (cut image-with-os arm64-disk-image <>))))
@end lisp

Využíva záznam, o ktorom sme ešte nehovorili, a teda @code{image-type},
zadaný nasledovne:

@lisp
(define-record-type* <image-type>
  image-type make-image-type
  image-type?
  (name           image-type-name) ; znak
  (constructor    image-type-constructor)) ; <operating-system> -> <image>
@end lisp

Hlavným účelom tohto záznamu je priradiť názov funkcii pretvárajúcej
@code{operating-system} na obraz.  Aby sme pochopili, prečo je to dôležité,
pozrime sa na príkaz vytvárajúci obraz zo súboru nastavení
@code{operating-system}:

@example
guix system image moj-os.scm
@end example

Tento príkaz očakáva nastavenie druhu @code{operating-system}, ale ako by
sme mali určiť, že chceme obraz pre dosku Pine64? Musíme poskytnúť
doplňujúci údaj, @code{image-type}, pomocou voľby @code{--image-type} alebo
@code{-t} a to takto:

@example
guix system image --image-type=pine64-raw moj-os.scm
@end example

Tento @code{image-type} parameter odkazuje na @code{pine64-image-type}
uvedený vyššie. Na @code{operating-system} zadaný v @code{moj-os.scm} sa
teda použije funkcia @code{(cut image-with-os arm64-disk-image <>)} pre
vytvorenie obrazu.

Výsledný obraz vyzerá asi takto:

@lisp
(image
 (format 'disk-image)
 (target "aarch64-linux-gnu")
 (operating-system moj-os)
 (partitions
  (list (partition
         (inherit root-partition)
         (offset root-offset)))))
@end lisp

čo je združenie člena @code{operating-system} zadaného v @code{moj-os.scm}
so záznamom @code{arm64-disk-image}.

Stačilo už tohto Scheme šialenstva. Čo toto API prináša používateľom Guixu?

Môžete spustiť:

@example
mathieu@@cervin:~$ guix system --list-image-types
Dostupné druhy obrazov sú:

   - unmatched-raw
   - rock64-raw
   - pinebook-pro-raw
   - pine64-raw
   - novena-raw
   - hurd-raw
   - hurd-qcow2
   - qcow2
   - iso9660
   - uncompressed-iso9660
   - tarball
   - efi-raw
   - mbr-raw
   - docker
   - wsl2
   - raw-with-offset
   - efi32-raw
@end example

a vytvorením súboru druhu @code{operating-system}, založenom na
@code{pine64-barebones-os}, si môžete váš obraz prispôsobiť v súbore
(@file{moj-pine-os.scm}) asi takto:

@lisp
(use-modules (gnu services linux)
             (gnu system images pine64))

(let ((base-os pine64-barebones-os))
  (operating-system
    (inherit base-os)
    (timezone "Europe/Bratislava")
    (services
     (cons
      (service earlyoom-service-type
               (earlyoom-configuration
                (prefer-regexp "icecat|chromium")))
      (operating-system-user-services base-os)))))
@end lisp

spustite:

@example
guix system image --image-type=pine64-raw moj-os.scm
@end example

alebo

@example
guix system image --image-type=hurd-raw moj-hurd-os.scm
@end example

pre získanie obrazu, ktorý možno zapísať priamo na pevný disk a zaviesť.

Bezo zmeny v @code{moj-hurd-os.scm}, volanie:

@example
guix system image --image-type=hurd-qcow2 moj-hurd-os.scm
@end example

namiesto toho vytvorí Hurd QEMU obraz.

@node Používanie bezpečnostných kľúčov
@section Používanie bezpečnostných kľúčov
@cindex 2FA, dvojstupňové overenie
@cindex U2F, všeobecný druhý stupeň
@cindex bezpečnostný kľúč, nastavenie

Používanie bezpečnostných kľúčov môže zvýšiť vašu bezpečnosť tým, že
hlavnému predmetu utajenia (heslo - niečo, čo poznáte) poskytne podružný
zdroj overenia, ktorý nemožno jednoducho ukradnúť alebo skopírovať (niečo,
čo vlastníte), aspoň v prípade vzdialených protivníkov, čo znižuje riziko
krádeže totožnosti.

Nižšie uvedený podrobný príklad znázorňuje najstručnejšie možné nastavenie
potrebné pre umožnenie používania bezpečnostného kľúča Yubico v systéme
Guix.  Dúfame, že toto nastavenie bude, s menšími úpravami, možné použiť aj
pre iné bezpečnostné kľúče.

@subsection Nastavenie pre použitie v rámci dvojstupňového overenia (2FA)

Aby sa kľúč dal použiť, je nutné rozšíriť udev pravidlá systému o pravidlá
príznačné pre daný kľúč.  Nasledovný postup popisuje kroky pre rozšírenie
udev pravidiel prostredníctvom súboru udev pravidiel
@file{lib/udev/rules.d/70-u2f.rules} poskytovaného balíkom @code{libfido2} z
modulu @code{(gnu packages security-token)} a pre pridanie vášho
používateľského účtu do skupiny @samp{"plugdev"}, ktorú využíva:

@lisp
(use-package-modules ... security-token ...)
...
(operating-system
 ...
 (users (cons* (user-account
               (name "vas-pouzivatelsky-ucet")
               (group "users")
               (supplementary-groups
		'("wheel" "netdev" "audio" "video"
                  "plugdev"))           ;<- pridaná systémová skupina
               (home-directory "/home/vas-pouzivatelsky-ucet"))
              %base-user-accounts))
 ...
 (services
  (cons*
   ...
   (udev-rules-service 'fido2 libfido2 #:groups '("plugdev")))))
@end lisp

Znovunastavením systému a opätovným prihlásením do vášho grafického sedenia
uplatníte členstvo vášho používateľského účtu v novej skupine. Potom môžete
overiť použiteľnosť vášho kľúča spustením:

@example
guix shell ungoogled-chromium -- chromium chrome://settings/securityKeys
@end example

a potvrdením, že bezpečnostný kľúč sa dá vynulovať v ponuke „Vynulovať váš
bezpečnostný kľúč“.  Ak to funguje, blahoželáme! Váš bezpečnostný kľúč je
pripravený na použitie v aplikáciách podporujúcich dvojstupňové overenie
(2FA).

@subsection Vypnúť vytváranie OTP kódov pre Yubikey
@cindex vypnutie OTP pre yubikey
Ak používate bezpečnostný kľúč Yubikey a otravujú vás nesprávne OTP kódy,
ktoré vytvára, keď nedopatrením kľúč zmeníte (napr. z vás spraví
odosielateľa nevyžiadaných správ v kanáli @samp{#guix} zatiaľčo sa zhovárate
vo vašom obľúbenom IRC klientovi!), môžete to vypnúť nasledovným
@command{ykman} príkazom:

@example
guix shell python-yubikey-manager -- ykman config usb --force --disable OTP
@end example

Ďalšou možnosťou je použiť príkaz @command{ykman-gui} z balíka
@code{yubikey-manager-qt} a buď úplne vypnúť @samp{OTP} aplikáciu pre
rozhranie USB, alebo z @samp{Applications -> OTP} vymazať nastavenie zásuvky
1, prednastavenej aplikáciou Yubico OTP.

@subsection Požiadať o Yubikey na otvorenie KeePassXC databázy
@cindex yubikey, prepojenie s keepassxc
Správca hesiel KeePassXC podporuje kľúče Yubikeys, ale táto podpora si
vyžaduje inštaláciu udev pravidiel pre váš systém Guix a nastavenie
aplikácie Yubico OTP na vybraný kľúč.

Potrebný súbor udev pravidiel pochádza z balíka
@code{yubikey-personalization} a možno ho nainštalovať nasledovne:

@lisp
(use-package-modules ... security-token ...)
...
(operating-system
 ...
 (services
  (cons*
   ...
   (udev-rules-service 'yubikey yubikey-personalization))))
@end lisp

After reconfiguring your system (and reconnecting your Yubikey), you'll then
want to configure the OTP challenge/response application of your Yubikey on
its slot 2, which is what KeePassXC uses.  It's easy to do so via the
Yubikey Manager graphical configuration tool, which can be invoked with:

@example
guix shell yubikey-manager-qt -- ykman-gui
@end example

First, ensure @samp{OTP} is enabled under the @samp{Interfaces} tab, then
navigate to @samp{Applications -> OTP}, and click the @samp{Configure}
button under the @samp{Long Touch (Slot 2)} section.  Select
@samp{Challenge-response}, input or generate a secret key, and click the
@samp{Finish} button.  If you have a second Yubikey you'd like to use as a
backup, you should configure it the same way, using the @emph{same} secret
key.

Your Yubikey should now be detected by KeePassXC.  It can be added to a
database by navigating to KeePassXC's @samp{Database -> Database
Security...} menu, then clicking the @samp{Add additional protection...}
button, then @samp{Add Challenge-Response}, selecting the security key from
the drop-down menu and clicking the @samp{OK} button to complete the setup.

@node mcron úloha pre dynamický DNS
@section mcron úloha pre dynamický DNS

@cindex dynamic DNS, DDNS
If your @acronym{ISP, Internet Service Provider} only provides dynamic IP
addresses, it can be useful to setup a dynamic @acronym{DNS, Domain Name
System} (also known as @acronym{DDNS, Dynamic DNS}) service to associate a
static host name to a public but dynamic (often changing) IP address.  There
are multiple existing services that can be used for this; in the following
mcron job, @url{https://duckdns.org, DuckDNS} is used.  It should also work
with other dynamic DNS services that offer a similar interface to update the
IP address, such as @url{https://freedns.afraid.org/}, with minor
adjustments.

The mcron job is provided below, where @var{DOMAIN} should be substituted
for your own domain prefix, and the DuckDNS provided token associated to
@var{DOMAIN} added to the @file{/etc/duckdns/@var{DOMAIN}.token} file.

@lisp
(define duckdns-job
  ;; Update personal domain IP every 5 minutes.
  #~(job '(next-minute (range 0 60 5))
	 #$(program-file
            "duckdns-update"
            (with-extensions (list guile-gnutls) ;required by (web client)
              #~(begin
                  (use-modules (ice-9 textual-ports)
                               (web client))
                  (let ((token (string-trim-both
                                (call-with-input-file "/etc/duckdns/@var{DOMAIN}.token"
                                  get-string-all)))
                        (query-template (string-append "https://www.duckdns.org/"
                                                       "update?domains=@var{DOMAIN}"
                                                       "&token=~a&ip=")))
                    (http-get (format #f query-template token))))))
         "duckdns-update"
         #:user "nobody"))
@end lisp

The job then needs to be added to the list of mcron jobs for your system,
using something like:

@lisp
(operating-system
 (services
  (cons* (service mcron-service-type
           (mcron-configuration
             (jobs (list duckdns-job ...))))
         ...
         %base-services)))
@end lisp

@node Pripojenie k Wireguard VPN
@section Pripojenie k Wireguard VPN

Pre pripojenie k serveru Wireguard VPN je potrebné načítať príslušný modul
jadra ako aj balík poskytujúci sieťové nástroje, ktoré ho podporujú (napr.
@code{wireguard-tools} alebo @code{network-manager}).

Nasleduje príklad nastavenia pre jadrá Linux-Libre < 5.6, ktoré príslušný
modul nezahŕňajú a vyžadujú jeho ručné načítanie. V novších vydaniach jadra
je modul už zabudovaný a takéto nastavenie nie je potrebné:

@lisp
(use-modules (gnu))
(use-service-modules desktop)
(use-package-modules vpn)

(operating-system
  ;; …
  (services (cons (simple-service 'wireguard-module
                                  kernel-module-loader-service-type
                                  '("wireguard"))
                  %desktop-services))
  (packages (cons wireguard-tools %base-packages))
  (kernel-loadable-modules (list wireguard-linux-compat)))
@end lisp

Po znovunastavení a opätovnom spustení systému môžete použiť buď nástroje
Wireguard alebo NetworkManager pre pripojenie k VPN serveru.

@subsection Použitie nástrojov Wireguard

Pre vyskúšanie nastavenia Wireguard je vhodné použiť @command{wg-quick}.
Stačí mu poskytnúť súbor nastavení @command{wg-quick up ./wg0.conf}. Súbor
tiež môžete umiestniť do @file{/etc/wireguard} a namiesto predošlého príkazu
vykonať @command{wg-quick up wg0}.

@quotation Poznámka
Vedzte však, že autor tento príkaz opísal ako „[…] veľmi narýchlo napísaný
bash skript […]“.
@end quotation

@subsection Použitie nástroja NetworkManager

Vďaka podpore nástroja NetworkManager pre Wireguard sa môžeme k našej VPN
sieti pripojiť pomocou príkazu @command{nmcli}.  Tento návod predpokladá, že
používate službu NetworkManager, ktorú poskytujú @code{%desktop-services}.
V opačnom prípade budete musieť rozšíriť váš zoznam služieb o
@code{network-manager-service-type} a znovunastaviť váš systém Guix.

Pre načítanie vášho nastavenia VPN vykonajte nasledovný nmcli príkaz:

@example shell
# nmcli connection import type wireguard file wg0.conf
Connection 'wg0' (edbee261-aa5a-42db-b032-6c7757c60fde) successfully added
@end example

Týmto sa vytvorí súbor nastavení
@file{/etc/NetworkManager/wg0.nmconnection}.  Potom sa pripojte k serveru
Wireguard:

@example shell
$ nmcli connection up wg0
Connection successfully activated (D-Bus active path: /org/freedesktop/NetworkManager/ActiveConnection/6)
@end example

Predvolene sa NetworkManager sám pripojí pri spustení systému.  Toto
správanie môžete zmeniť v nastaveniach:

@example shell
# nmcli connection modify wg0 connection.autoconnect no
@end example

Podrobnejšie poznatky o nástroji NetworkManager a wireguard získate v
@uref{https://blogs.gnome.org/thaller/2019/03/15/wireguard-in-networkmanager/,tomto
príspevku od thallera}.

@node Prispôsobenie správcu okien
@section Prispôsobenie správcu okien
@cindex wm

@menu
* StumpWM::                  StumpWM
* Uzamykanie sedenia::       Uzamykanie sedenia
@end menu

@node StumpWM
@subsection StumpWM
@cindex stumpwm

StumpWM so systémom Guix môžete nainštalovať pridaním @code{stumpwm} a
nepovinne aj @code{`(,stumpwm "lib")} balíkov do súboru nastavení systému,
napr.@: @file{/etc/config.scm}.

Príklad nastavenia:

@lisp
(use-modules (gnu))
(use-package-modules wm)

(operating-system
  ;; …
  (packages (append (list sbcl stumpwm `(,stumpwm "lib"))
                    %base-packages)))
@end lisp

@cindex písma stumpwm
StumpWM predvolene používa písma X11, ktoré môžu byť primalé alebo
nedostatočne ostré.  Lepšie zobrazenie môžete docieliť nainštalovaním Lisp
modulu @code{sbcl-ttf-fonts} pre StumpWM, teda jeho pridaním k balíkom
systému Guix:

@lisp
(use-modules (gnu))
(use-package-modules fonts wm)

(operating-system
  ;; …
  (packages (append (list sbcl stumpwm `(,stumpwm "lib"))
                    sbcl-ttf-fonts font-dejavu %base-packages)))
@end lisp

Potom musíte pridať nasledovný kód do súboru nastavení StumpWM
@file{~/.stumpwm.d/init.lisp}:

@lisp
(require :ttf-fonts)
(setf xft:*font-dirs* '("/run/current-system/profile/share/fonts/"))
(setf clx-truetype:+font-cache-filename+ (concat (getenv "HOME")
                                                 "/.fonts/font-cache.sexp"))
(xft:cache-fonts)
(set-font (make-instance 'xft:font :family "DejaVu Sans Mono"
                                   :subfamily "Book" :size 11))
@end lisp

@node Uzamykanie sedenia
@subsection Uzamykanie sedenia
@cindex uzamykanie sedenia

V závislosti na vašom prostredí, uzamykanie obrazovky môže byť zabudované
alebo ho je potrebné nastaviť ručne. Ak používate prostredie pracovnej
plochy ako GNOME alebo KDE, uzamykanie je v ňom pravdepodobne zabudované. Ak
používate správcu okien ako StumpWM alebo EXWM, budete ho musieť nastaviť
ručne.

@menu
* Xorg::                     Xorg
@end menu

@node Xorg
@subsubsection Xorg

Ak používate Xorg, môžete využiť nástroj
@uref{https://www.mankier.com/1/xss-lock, xss-lock} pre uzamykanie vášho
sedenia.  xss-lock je vyvolaný DPMS, ktoré sa od Xorg 1.8 zisťuje a zapína
samo, ak je pri spúšťaní jadra povolené aj ACPI.

Použiť xss-lock môžete tak, že ho jednoducho spustíte na pozadí ešte pred
spustením vášho správcu okien, napríklad z vášho @file{~/.xsession}:

@example
xss-lock -- slock &
exec stumpwm
@end example

V tomto príklade sa xss-lock spolieha na @code{slock} pre uzamknutie
obrazovky, keď je to vhodné, napríklad, pri uspaní zariadenia.

Aby mohol slock uzamknúť obrazovku grafického sedenia, musí mať nastavený
setuid-root príznak pre potreby overenia totožnosti používateľov. slock tiež
vyžaduje službu PAM. Toto je možné zabezpečiť pridaním nasledovnej služby do
vášho @file{config.scm}:

@lisp
(service screen-locker-service-type
         (screen-locker-configuration
          (name "slock")
          (program (file-append slock "/bin/slock"))))
@end lisp

Pri ručnom uzamknutí obrazovky, napr. pri priamom vyvolaní slocku, keď
chcete uzamknúť obrazovku ale nechcete uspať počítač, je dobré o tom
oboznámiť aj xss-lock, aby nedošlo k omylu. Môžete tak urobiť vyvolaním
@code{xset s activate} tesne pred spustením slocku.

@node Spúšťanie Guixu na serveri Linode
@section Spúšťanie Guixu na serveri Linode
@cindex linode, Linode

Ak chcete spustiť Guix na serveri hosťovanom na
@uref{https://www.linode.com, Linode}, začnite s odporúčaným Debianovým
serverom.  Na zavedenie Guixu vám odporúčame použiť predvolenú distribúciu.
Vytvorte si kľúče SSH.

@example
ssh-keygen
@end example

Pridajte si SSH kľúč pre rýchle prihlasovanie na vzdialený server.  Vďaka
grafickému rozhraniu Linode je pridávanie SSH kľúčov veľmi jednoduché.
Choďte do vášho profilu a kliknite na Pridať SSH kľúč.  Tam potom skopírujte
výstup príkazu:

@example
cat ~/.ssh/<pouzivatel>_rsa.pub
@end example

Vypnite Linode.

Na karte „Storage“ (úložisko) v Linode zmenšite disk s Debianom.  Odporúča
sa 30 GB voľného priestoru.  Potom kliknite na „Add a disk“ (pridať disk) a
vyplňte formulár nasledujúcimi údajmi:

@itemize @bullet
@item
Label (menovka): "Guix"

@item
Filesystem (súborový systém): ext4

@item
Využite zvyšné voľné miesto
@end itemize

Na karte „Configurations“ (nastavenia) kliknite na „Edit“ (upraviť) pri
predvolenom profile Debianu.  Pod „Block Device Assignment“ (pridelenie
diskových zariadení) kliknite na „Add a Device“ (pridať zariadenie). Malo by
to byť @file{/dev/sdc} a môžete pridať disk „Guix“. Uložte zmeny.

Teraz „Add a Configuration“ (pridať nastavenie) s nasledovným:
@itemize @bullet
@item
Label (menovka): Guix

@item
Kernel (jadro): GRUB 2 (je to naspodku! Tento krok je @b{DÔLEŽITÝ!})

@item
Block device assignment (pridelenie diskových zariadení):

@item
@file{/dev/sda}: Guix

@item
@file{/dev/sdb}: swap (odkladací priestor)

@item
Root device (koreňové zariadenie): @file{/dev/sda}

@item
Vypnite všetky pomocné programy pre systém súborov a zavádzanie
@end itemize

Teraz opätovne spustite server s nastavením Debianu.  Po spustení sa k vášmu
serveru pripojte cez SSH pomocou @code{ssh
root@@@var{<IP-adresa-vasho-servera-tu>}} (IP adresu vášho servera môžete
nájsť v odseku „Summary“, t.j. zhrnutie, na Linode). Teraz môžete vykonať
inštalačné kroky z @pxref{Binary Installation,,, guix, GNU Guix}:

@example
sudo apt-get install gpg
wget https://sv.gnu.org/people/viewgpg.php?user_id=15145 -qO - | gpg --import -
wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
chmod +x guix-install.sh
./guix-install.sh
guix pull
@end example

Teraz je čas dať dohromady nastavenia servera.  Kľúčové poznatky sú uvedené
nižšie.  Uložte výsledný súbor ako @file{guix-config.scm}.

@lisp
(use-modules (gnu)
             (guix modules))
(use-service-modules networking
                     ssh)
(use-package-modules admin
                     package-management
                     ssh
                     tls)

(operating-system
  (host-name "moj-server")
  (timezone "Europe/Bratislava")
  (locale "sk_SK.UTF-8")
  ;; Tento kód vytvorí grub.cfg
  ;; bez inštalácie grubu na disk.
  (bootloader (bootloader-configuration
               (bootloader
                (bootloader
                 (inherit grub-bootloader)
                 (installer #~(const #true))))))
  (file-systems (cons (file-system
                        (device "/dev/sda")
                        (mount-point "/")
                        (type "ext4"))
                      %base-file-systems))


  (swap-devices (list "/dev/sdb"))


  (initrd-modules (cons "virtio_scsi"    ; Potrebné pre nájdenie disku
                        %base-initrd-modules))

  (users (cons (user-account
                (name "jozkomrkvicka")
                (group "users")
                ;; Pridá účet do skupiny „wheel“,
                ;; aby sa z neho stal sudoer.
                (supplementary-groups '("wheel"))
                (home-directory "/home/jozkomrkvicka"))
               %base-user-accounts))

  (packages (cons* openssh-sans-x
                   %base-packages))

  (services (cons*
             (service dhcp-client-service-type)
             (service openssh-service-type
                      (openssh-configuration
                       (openssh openssh-sans-x)
                       (password-authentication? #false)
                       (authorized-keys
                        `(("jozkomrkvicka" ,(local-file "jozkomrkvicka_rsa.pub"))
                          ("root" ,(local-file "jozkomrkvicka_rsa.pub"))))))
             %base-services)))
@end lisp

Nahraďte nasledovné polia vo vyššie uvedenom nastavení:
@lisp
(host-name "moj-server")       ; nahraďte názvom vášho servera
; ak si vyberiete Linode server mimo Slovenska, tak pomocou
; tzselect vyhľadajte správne nastavenie časového pásma
(timezone "Europe/Bratislava") ; v prípade potreby, nahraďte časové pásmo
(name "jozkomrkvicka")              ; nahraďte vašim používateľským menom
("jozkomrkvicka" ,(local-file "jozkomrkvicka_rsa.pub")) ; nahraďte vašim používateľským menom a SSH kľúčom
("root" ,(local-file "jozkomrkvicka_rsa.pub")) ; nahraďte vašim SSH kľúčom
@end lisp

Posledný riadok vo vyššie uvedenom príklade vám umožňuje prihlásiť sa na
server ako root a nastaviť prvotné heslo používateľa root (viď poznámku o
prihlasovaní používateľa root na konci receptu).  Po tomto môžete daný
riadok z nastavenia vymazať a znovunastaviť, aby ste zabránili prihlasovaniu
ako root.

Skopírujte váš verejný SSH kľúč (napr. @file{~/.ssh/id_rsa.pub}) do
@file{@var{<vase-pouzivatelske-meno-tu>}_rsa.pub} a premiestnite
@file{guix-config.scm} do rovnakého priečinka.  V novom príkazovom riadku
vykonajte nasledovné príkazy.

@example
sftp root@@<ip adresa vzdialeného servera>
put /cesta/k/súborom/<používateľ>_rsa.pub .
put /cesta/k/súborom/guix-config.scm .
@end example

Vo vašom prvom príkazovom riadku pripojte disk guix:

@example
mkdir /mnt/guix
mount /dev/sdc /mnt/guix
@end example

Kvôli spôsobu akým sme nastavili zavádzač v príslušnom oddieli
guix-config.scm sa nainštaluje iba súbor nastavení grubu.  Musíme, teda,
prekopírovať nejaké súbory zavádzača GRUB, ktoré už sú nainštalované v
systéme Debian:

@example
mkdir -p /mnt/guix/boot/grub
cp -r /boot/grub/* /mnt/guix/boot/grub/
@end example

Teraz nastavte inštaláciu Guixu do východzieho stavu:

@example
guix system init guix-config.scm /mnt/guix
@end example

Dobre, vypnite server! Cez príkazový riadok Linode spustite server a vyberte
„Guix“.

Po spustení by ste mali byť schopní prihlásiť sa cez SSH! (Nastavenie
servera ale bude zmenené.)  Môžete sa stretnúť s chybou ako je táto:

@example
$ ssh root@@<ip adresa servera>
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@    WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED!     @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the ECDSA key sent by the remote host is
SHA256:0B+wp33w57AnKQuHCvQP0+ZdKaqYrI/kyU7CfVbS7R4.
Please contact your system administrator.
Add correct host key in /home/jozkomrkvicka/.ssh/known_hosts to get rid of this message.
Offending ECDSA key in /home/jozkomrkvicka/.ssh/known_hosts:3
ECDSA host key for 198.58.98.76 has changed and you have requested strict checking.
Host key verification failed.
@end example

Buď odstráňte súbor @file{~/.ssh/known_hosts}, alebo vymažte dotknutý riadok
začínajúci IP adresou vášho servera.

Nezabudnite si nastaviť vaše heslo ako aj heslo používateľa root.

@example
ssh root@@<vzdialená ip adresa>
passwd  ; pre nastavenie hesla používateľa root
passwd <používateľ> ; pre nastavenie hesla daného používateľa
@end example

V tomto bode možno nebudete môcť vyššie uvedené príkazy vykonať.  Ak máte
ťažkosti so vzdialeným prihlásením cez SSH, tak možno budete musieť
používateľské heslá nastaviť kliknutím na možnosť „Launch Console“ (spustiť
príkazový riadok) vo vašom Linode.  Vyberte „Glish“ namiesto „Weblish“.
Teraz by ste už mali byť schopní prihlásiť sa do stroja.

Sláva! Teraz môžete server vypnúť, odstrániť disk s Debianom a rozšíriť disk
Guixom.  Blahoželáme!

Inak, ak teraz výsledok uložíte ako obraz disku, uľahčíte si tým spúšťanie
nových obrazov s Guixom! Pre uloženie ako obraz disku možno budete musieť
disk s Guixom zmenšiť na 6144 MB, ale potom ho môžete znovu rozšíriť na
pôvodnú veľkosť.

@node Spúšťanie Guixu na Kimsufi serveri
@section Spúšťanie Guixu na Kimsufi serveri
@cindex kimsufi, Kimsufi, OVH

To run Guix on a server hosted by @uref{https://www.kimsufi.com/, Kimsufi},
click on the netboot tab then select rescue64-pro and restart.

OVH will email you the credentials required to ssh into a Debian system.

Now you can run the "install guix from @pxref{Binary Installation,,, guix,
GNU Guix}" steps:

@example
wget https://git.savannah.gnu.org/cgit/guix.git/plain/etc/guix-install.sh
chmod +x guix-install.sh
./guix-install.sh
guix pull
@end example

Partition the drives and format them, first stop the raid array:

@example
mdadm --stop /dev/md127
mdadm --zero-superblock /dev/sda2 /dev/sdb2
@end example

Then wipe the disks and set up the partitions, we will create a RAID 1
array.

@example
wipefs -a /dev/sda
wipefs -a /dev/sdb

parted /dev/sda --align=opt -s -m -- mklabel gpt
parted /dev/sda --align=opt -s -m -- \
 mkpart bios_grub 1049kb 512MiB \
 set 1 bios_grub on
parted /dev/sda --align=opt -s -m -- \
 mkpart primary 512MiB -512MiB
 set 2 raid on
parted /dev/sda --align=opt -s -m -- mkpart primary linux-swap 512MiB 100%

parted /dev/sdb --align=opt -s -m -- mklabel gpt
parted /dev/sdb --align=opt -s -m -- \
     mkpart bios_grub 1049kb 512MiB \
     set 1 bios_grub on
parted /dev/sdb --align=opt -s -m -- \
     mkpart primary 512MiB -512MiB \
     set 2 raid on
parted /dev/sdb --align=opt -s -m -- mkpart primary linux-swap 512MiB 100%
@end example

Create the array:

@example
mdadm --create /dev/md127 --level=1 --raid-disks=2 \
  --metadata=0.90 /dev/sda2 /dev/sdb2
@end example

Now create file systems on the relevant partitions, first the boot
partitions:

@example
mkfs.ext4  /dev/sda1
mkfs.ext4  /dev/sdb1
@end example

Then the root partition:

@example
mkfs.ext4 /dev/md127
@end example

Initialize the swap partitions:

@example
mkswap /dev/sda3
swapon /dev/sda3
mkswap /dev/sdb3
swapon /dev/sdb3
@end example

Mount the guix drive:

@example
mkdir /mnt/guix
mount /dev/md127 /mnt/guix
@end example

Now is time to write an operating system declaration @file{os.scm} file;
here is a sample:

@lisp
(use-modules (gnu) (guix))
(use-service-modules networking ssh vpn virtualization sysctl admin mcron)
(use-package-modules ssh tls tmux vpn virtualization)

(operating-system
  (host-name "kimsufi")

  (bootloader (bootloader-configuration
	       (bootloader grub-bootloader)
	       (targets (list "/dev/sda" "/dev/sdb"))
	       (terminal-outputs '(console))))

  ;; Add a kernel module for RAID-1 (aka. "mirror").
  (initrd-modules (cons* "raid1"  %base-initrd-modules))

  (mapped-devices
   (list (mapped-device
          (source (list "/dev/sda2" "/dev/sdb2"))
          (target "/dev/md127")
          (type raid-device-mapping))))

  (swap-devices
   (list (swap-space
          (target "/dev/sda3"))
         (swap-space
          (target "/dev/sdb3"))))

  (issue
   ;; Default contents for /etc/issue.
   "\
This is the GNU system at Kimsufi.  Welcome.\n")

  (file-systems (cons* (file-system
		         (mount-point "/")
		         (device "/dev/md127")
		         (type "ext4")
		         (dependencies mapped-devices))
		       %base-file-systems))

  (users (cons (user-account
	        (name "guix")
	        (comment "guix")
	        (group "users")
	        (supplementary-groups '("wheel"))
	        (home-directory "/home/guix"))
	       %base-user-accounts))

  (sudoers-file
   (plain-file "sudoers" "\
root ALL=(ALL) ALL
%wheel ALL=(ALL) ALL
guix ALL=(ALL) NOPASSWD:ALL\n"))

  ;; Globally-installed packages.
  (packages (cons* tmux gnutls wireguard-tools %base-packages))
  (services
   (cons*
    (service static-networking-service-type
	     (list (static-networking
		    (addresses (list (network-address
				      (device "enp3s0")
				      (value "@var{server-ip-address}/24"))))
		    (routes (list (network-route
				   (destination "default")
				   (gateway "@var{server-gateway}"))))
		    (name-servers '("213.186.33.99")))))

    (service unattended-upgrade-service-type)

    (service openssh-service-type
	     (openssh-configuration
	      (openssh openssh-sans-x)
	      (permit-root-login #f)
	      (authorized-keys
	       `(("guix" ,(plain-file "@var{ssh-key-name.pub}"
                                      "@var{ssh-public-key-content}"))))))
    (modify-services %base-services
      (sysctl-service-type
       config =>
       (sysctl-configuration
	(settings (append '(("net.ipv6.conf.all.autoconf" . "0")
			    ("net.ipv6.conf.all.accept_ra" . "0"))
			  %default-sysctl-settings))))))))
@end lisp

Don't forget to substitute the @var{server-ip-address},
@var{server-gateway}, @var{ssh-key-name} and @var{ssh-public-key-content}
variables with your own values.

The gateway is the last usable IP in your block so if you have a server with
an IP of @samp{37.187.79.10} then its gateway will be @samp{37.187.79.254}.

Transfer your operating system declaration @file{os.scm} file on the server
via the @command{scp} or @command{sftp} commands.

Now all that is left is to install Guix with a @code{guix system init} and
restart.

However we first need to set up a chroot, because the root partition of the
rescue system is mounted on an aufs partition and if you try to install Guix
it will fail at the GRUB install step complaining about the canonical path
of "aufs".

Install packages that will be used in the chroot:

@example
guix install bash-static parted util-linux-with-udev coreutils guix
@end example

Then run the following to create directories needed for the chroot:

@example
cd /mnt && \
mkdir -p bin etc gnu/store root/.guix-profile/ root/.config/guix/current \
  var/guix proc sys dev
@end example

Copy the host resolv.conf in the chroot:

@example
cp /etc/resolv.conf etc/
@end example

Mount block devices, the store and its database and the current guix config:

@example
mount --rbind /proc /mnt/proc
mount --rbind /sys /mnt/sys
mount --rbind /dev /mnt/dev
mount --rbind /var/guix/ var/guix/
mount --rbind /gnu/store gnu/store/
mount --rbind /root/.config/ root/.config/
mount --rbind /root/.guix-profile/bin/ bin
mount --rbind /root/.guix-profile root/.guix-profile/
@end example

Chroot in /mnt and install the system:

@example
chroot /mnt/ /bin/bash

guix system init /root/os.scm /guix
@end example

Finally, from the web user interface (UI), change @samp{netboot} to
@samp{boot to disk} and restart (also from the web UI).

Wait a few minutes and try to ssh with @code{ssh
guix@@@var{server-ip-address>} -i @var{path-to-your-ssh-key}}

You should have a Guix system up and running on Kimsufi; congratulations!

@node Nastavenie podvojného pripojenia
@section Nastavenie podvojného pripojenia

Pre vytvorenie podvojného pripojenia systému súborov je najskôr nutné pridať
niekoľko zadaní do oddielu @code{operating-system} v zadaní systému.  Aby
sme nevyčerpávali hlavný SSD disk, v tomto príklade vytvoríme podvojné
pripojenie pre priečinok z pevného disku k @file{/tmp} bez nutnosti
vyhradenia celého jedného oddielu pre @file{/tmp}.

Po prvé, zdrojové zariadenie s priečinkom, pre ktorý chceme vytvoriť
podvojné pripojenie, musí byť dané, aby na ňom mohlo podvojné pripojenie
závisieť.

@lisp
(define zdrojove-zariadenie ;; „zdrojove-zariadenie“ môžete ľubovoľne nahradiť
   (file-system
    (device (uuid "sem príde UUID"))
    (mount-point "/sem-príde-cesta-k-pevnému-disku")
    (type "ext4"))) ;Uistite sa, že druh systému súborov zodpovedá tomu, čo je na disku.
@end lisp

Zdrojový priečinok musí byť taktiež určený, aby Guix vedel, že sa jedná o
priečinok, a nie o diskovú jednotku.
@lisp
;; „zdrojovy-priecinok“ môžete nahradiť ľubovoľným platným názvom premennej.
(define (%zdrojovy-priecinok) "/sem-príde-cesta-k-pevnému-disku/tmp")
@end lisp

Nakoniec musíme samotné pripojenie pridať do zadania @code{file-systems}.

@lisp
(file-systems (cons*

                ...<ostatné pripojenia sme vynechali>...

                ;; Musí sa zhodovať s názvom, ktorý ste pridelili zdrojovému
                ;; zariadeniu vyššie.
                zdrojove-zariadenie

                (file-system
                 ;; „zdrojovy-priecinok“ sa musí zhodovať s predošlým zadaním.
                 (device (%zdrojovy-priecinok))
                 (mount-point "/tmp")
                 ;; Pripájame priečinok, nie zväzok, takže tento druh
                 ;; musí byť „none“ (žiadny)
                 (type "none")
                 (flags '(bind-mount))
                 ;; „zdrojove-zariadenie“ sa musí zhodovať s predošlým zadaním.
                 (dependencies (list zdrojove-zariadenie))
                 )

                 ...<ostatné pripojenia sme vynechali>...

                ))
@end lisp

@node Získavanie náhrad prostredníctvom Tor
@section Získavanie náhrad prostredníctvom Tor

Démon Guixu môže na získavanie náhrad využívať HTTP proxy server. V tomto
prípade ho nastavíme tak, aby ich získaval cez Tor.

@quotation Upozornenie
@emph{Nie všetka} sieťová prevádzka démona Guixu bude prechádzať cez Tor!
Presmerované bude len HTTP/HTTPS; protokol Git, SSH, atď. pôjdu aj naďalej
cez otvorenú sieť.  Znova, toto nastavenie nie je dokonalé a časť vašej
prevádzky poputuje aj naďalej mimo siete Tor.  Použite ho na vlastné riziko.

Vedzte tiež, že opísaný postup sa vzťahuje len na náhrady balíkov. Ak chcete
pri aktualizovaní vašej distribúcie pomocou @command{guix pull} presmerovať
pripojenie ku git repozitáru Guixu cez Tor , budete musieť použiť
@command{torsocks}.
@end quotation

Server náhrad Guixu je dostupný ako Onion služba. Ak chcete náhrady získavať
cez Tor, nastavte váš systém nasledovne:

@lisp
(use-modules (gnu))
(use-service-module base networking)

(operating-system
  …
  (services
    (cons
      (service tor-service-type
              (tor-configuration
                (config-file (plain-file "tor-config"
                                         "HTTPTunnelPort 127.0.0.1:9250"))))
      (modify-services %base-services
        (guix-service-type
          config => (guix-configuration
                      (inherit config)
                      ;; Onion služba na ci.guix.gnu.org
                      (substitute-urls "\
@value{SUBSTITUTE-TOR-URL}")
                      (http-proxy "http://localhost:9250")))))))
@end lisp

Toto udrží spustený proces tor poskytujúci tunel HTTP CONNECT, ktorý použije
@command{guix-daemon}.  Démon môže využívať aj iné protokoly ako HTTP(S) pre
získavanie vzdialených zdrojov. Avšak požiadavky spoliehajúce sa na iné
protokoly nebudú prechádzať cez Tor, keďže tu nastavujeme len HTTP tunel.
Vedzte, že @code{substitutes-urls} využíva HTTPS. Kvôli obmedzeniu spojenému
s Tor tunelom by to cez HTTP nefungovalo. Takýmto obmedzeniam sa môžete
vyhnúť použitím @command{privoxy}.

Ak nechcete pre získavanie náhrad prechádzať cez Tor neustále ale iba
niekedy, preskočte @code{guix-configuration}. Keď budete chcieť získať
náhradu cez tunel Tor, spustite:

@example
sudo herd set-http-proxy guix-daemon http://localhost:9250
guix build \
  --substitute-urls=@value{SUBSTITUTE-TOR-URL} @dots{}
@end example

@node Nastavenia NGINX a Lua
@section Nastavenia NGINX a Lua
@cindex nginx, lua, openresty, resty

NGINX možno rozšíriť pomocou Lua skriptov.

Guix poskytuje NGINX službu so schopnosťou načítať Lua moduly a určité Lua
balíky ako aj odpovedať na požiadavky vyhodnocovaním Lua skriptov.

Nasledovný príklad znázorňuje zadanie systému s nastavením, ktoré vyhodnotí
Lua skript @file{index.lua} pri HTTP požiadavke na koncový bod
@uref{http://localhost/ahoj}:

@example
local shell = require "resty.shell"

local stdin = ""
local timeout = 1000  -- ms
local max_size = 4096  -- byte

local ok, stdout, stderr, reason, status =
   shell.run([[/run/current-system/profile/bin/ls /tmp]], stdin, timeout, max_size)

ngx.say(stdout)
@end example

@lisp
(use-modules (gnu))
(use-service-modules #;… web)
(use-package-modules #;… lua)
(operating-system
  ;; …
  (services
   ;; …
   (service nginx-service-type
            (nginx-configuration
             (modules
              (list
               (file-append nginx-lua-module "/etc/nginx/modules/ngx_http_lua_module.so")))
             (lua-package-path (list lua-resty-core
                                     lua-resty-lrucache
                                     lua-resty-signal
                                     lua-tablepool
                                     lua-resty-shell))
             (lua-package-cpath (list lua-resty-signal))
             (server-blocks
              (list (nginx-server-configuration
                     (server-name '("localhost"))
                     (listen '("80"))
                     (root "/etc")
                     (locations (list
                                 (nginx-location-configuration
                                  (uri "/ahoj")
                                  (body (list #~(format #f "content_by_lua_file ~s;"
                                                        #$(local-file "index.lua"))))))))))))))
@end lisp

@node Hudobný server so zvukom cez Bluetooth
@section Hudobný server so zvukom cez Bluetooth
@cindex mpd
@cindex hudobný server, bezobrazovkový
@cindex bluetooth, nastavenie ALSA

MPD, démon hudobného prehrávača, je pružná serverová aplikácia na
prehrávanie hudby.  Klientske programy na rôznych strojoch na sieti ---
mobilný telefón, prenosný počítač, stolný počítač --- sa k nej môžu pripojiť
a ovládať prehrávanie zvukových súborov z vašej miestnej hudobnej zbierky.
MPD číta zvukové súbory a prehráva ich na jednom alebo viacerých výstupoch.

Ak nie je nastavené inak, MPD prehráva na predvolenom zvukovom zariadení.  V
nižšie uvedenom príklade to spravíme trochu zaujímavejšie a nastavíme si
bezobrazovkový hudobný server.  Nepoužijeme grafické používateľské
rozhranie, démona Pulseaudio ani miestny zvukový výstup.  Namiesto toho
nastavíme MPD s dvomi výstupmi: s bluetooth reproduktorom a webovým serverom
poskytujúcim zvukové toky ľubovoľnému prehrávaču hudby.

Nastavenie Bluetooth býva otravné.  Budete musieť spárovať vaše Bluetooth
zariadenie a zabezpečiť, aby sa po zapnutí samo pripájalo.  Systémová
Bluetooth služba vrátená funkciou @code{bluetooth-service} poskytuje
podklady potrebné pre toto nastavenie.

Znovunastavte váš systém s aspoň týmito službami a balíkmi:

@lisp
(operating-system
  ;; …
  (packages (cons* bluez bluez-alsa
                   %base-packages))
  (services
   ;; …
   (dbus-service #:services (list bluez-alsa))
   (bluetooth-service #:auto-enable? #t)))
@end lisp

Spustite službu @code{bluetooth} a zistite Bluetooth zariadenia pomocou
@command{bluetoothctl}.  Pokúste sa stotožniť váš Bluetooth reproduktor a
vyberte jeho označenie z výsledného zoznamu zariadení, ktorý je nepochybne
plný rôznych hračičiek vašich susedov.  Toto je potrebné urobiť iba raz:

@example
$ bluetoothctl 
[NEW] Controller 00:11:22:33:95:7F BlueZ 5.40 [default]

[bluetooth]# power on
[bluetooth]# Changing power on succeeded

[bluetooth]# agent on
[bluetooth]# Agent registered

[bluetooth]# default-agent
[bluetooth]# Default agent request successful

[bluetooth]# scan on
[bluetooth]# Discovery started
[CHG] Controller 00:11:22:33:95:7F Discovering: yes
[NEW] Device AA:BB:CC:A4:AA:CD Môj Bluetooth reproduktor
[NEW] Device 44:44:FF:2A:20:DC TV môjho suseda
@dots{}

[bluetooth]# pair AA:BB:CC:A4:AA:CD
Attempting to pair with AA:BB:CC:A4:AA:CD
[CHG] Device AA:BB:CC:A4:AA:CD Connected: yes

[My Bluetooth Speaker]# [CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110b-0000-1000-8000-00xxxxxxxxxx
[CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110c-0000-1000-8000-00xxxxxxxxxx
[CHG] Device AA:BB:CC:A4:AA:CD UUIDs: 0000110e-0000-1000-8000-00xxxxxxxxxx
[CHG] Device AA:BB:CC:A4:AA:CD Paired: yes
Pairing successful

[CHG] Device AA:BB:CC:A4:AA:CD Connected: no

[bluetooth]# 
[bluetooth]# trust AA:BB:CC:A4:AA:CD
[bluetooth]# [CHG] Device AA:BB:CC:A4:AA:CD Trusted: yes
Changing AA:BB:CC:A4:AA:CD trust succeeded

[bluetooth]# 
[bluetooth]# connect AA:BB:CC:A4:AA:CD
Attempting to connect to AA:BB:CC:A4:AA:CD
[bluetooth]# [CHG] Device AA:BB:CC:A4:AA:CD RSSI: -63
[CHG] Device AA:BB:CC:A4:AA:CD Connected: yes
Connection successful

[My Bluetooth Speaker]# scan off
[CHG] Device AA:BB:CC:A4:AA:CD RSSI is nil
Discovery stopped
[CHG] Controller 00:11:22:33:95:7F Discovering: no
@end example

Blahoželáme, už sa môžete samočinne pripojiť k vášmu Bluetooth reproduktoru!

Teraz je čas nastaviť ALSA na používanie Bluetooth modulu @emph{bluealsa},
aby ste mohli určiť ALSA pcm zariadenie zodpovedajúce vášmu Bluetooth
reproduktoru.  Pre bezobrazovkový server je použitie @emph{bluealsa} s pevne
určeným Bluetooth zariadením pravdepodobne jednoduchšie ako nastavenie
Pulseaudia a prepínania tokov.  ALSA nastavíme vytvorením vlastného
nastavenia @code{alsa-configuration} pre druh @code{alsa-service-type}.
Nastavenie zadá @code{bluealsa} @code{pcm} druhu z modulu @code{bluealsa}
poskytovaného balíkom @code{bluez-alsa} a potom určí @code{pcm} zariadenie
daného druhu pre váš Bluetooth reproduktor.

Už zostáva len nastaviť MPD tak, aby odosielal zvukové údaje na toto ALSA
zariadenie.  Pridáme tiež podvojný MPD výstup, ktorý sprístupní práve
prehrávané zvukové súbory ako tok cez webový server na koncovom bode 8080.
Ak je zvukový tok dostupný, zariadenia na sieti ho môžu počúvať pripojením
ľubovoľného hudobného prehrávača ku koncovému bodu 8080 HTTP servera
nezávisle od stavu Bluetooth reproduktora.

Nasleduje náčrt zadania @code{operating-system}, ktoré by malo umožniť
vyššie uvedené úlohy:

@lisp
(use-modules (gnu))
(use-service-modules audio dbus sound #;… etc)
(use-package-modules audio linux #;… etc)
(operating-system
  ;; …
  (packages (cons* bluez bluez-alsa
                   %base-packages))
  (services
   ;; …
   (service mpd-service-type
            (mpd-configuration
             (user "vase-pouzivatelske-meno")
             (music-dir "/cesta/k/vašej/hudbe")
             (address "192.168.178.20")
             (outputs (list (mpd-output
                             (type "alsa")
                             (name "MPD")
                             (extra-options
                              ;; Použite rovnaký názov ako
                              ;; v nižšie uvedenom nastavení ALSA.
                              '((device . "pcm.btspeaker"))))
                            (mpd-output
                             (type "httpd")
                             (name "streaming")
                             (enabled? #false)
                             (always-on? #true)
                             (tags? #true)
                             (mixer-type 'null)
                             (extra-options
                              '((encoder . "vorbis")
                                (port    . "8080")
                                (bind-to-address . "192.168.178.20")
                                (max-clients . "0") ; bez obmedzení
                                (quality . "5.0")
                                (format  . "44100:16:1"))))))))
   (dbus-service #:services (list bluez-alsa))
   (bluetooth-service #:auto-enable? #t)
   (service alsa-service-type
            (alsa-configuration
             (pulseaudio? #false) ; nepotrebujeme ho!
             (extra-options
              #~(string-append "\
# Zadáva zvukové Bluetooth zariadenie druhu \"bluealsa\" z modulu bluealsa
pcm_type.bluealsa @{
    lib \""
#$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_pcm_bluealsa.so") "\"
@}

# Zadáva overovacie zariadenie druhu \"bluealsa\" z rovnakého modulu
ctl_type.bluealsa @{
    lib \""
#$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_ctl_bluealsa.so") "\"
@}

# Určuje zvukové Bluetooth zariadenie.
pcm.btspeaker @{
    type bluealsa
    device \"AA:BB:CC:A4:AA:CD\" # jedinečné označenie zariadenia
    profile \"a2dp\"
@}

# Určuje súvisiaci overovač.
ctl.btspeaker @{
    type bluealsa
@}
"))))))
@end lisp

Užite si hudbu s MPD klientom podľa vlastného výberu alebo s hudobným
prehrávačom schopným prijímať zvukové toky cez HTTP!


@c *********************************************************************
@node Kontajnery
@chapter Kontajnery

Linuxové jadro poskytuje určitý počet zdieľaných prostriedkov dostupných pre
systémové procesy.  Tieto prostriedky zahŕňajú zdieľaný pohľad na systém
súborov, ostatné procesy, sieťové zariadenia, používateľov, skupinové
totožnosti, a niekoľko ďalších.  Počínajúc Linuxom 3.19 sa môže používateľ
rozhodnúť prestať zdieľať niektoré z týchto zdieľaných prostriedkov pre
vybrané procesy poskytujúc im (a ich podprocesom) odlišný pohľad na systém.

Napríklad, proces s nezdieľanou oblasťou mien pripojení (@code{mount}) má
oddelený pohľad na súborový systém --- môže vidieť len priečinky, ktoré boli
výslovne pripojené k jeho oblasti mien pripojení.  Proces so svojou vlastnou
oblasťou mien procesov (@code{proc}) vidí seba samého ako jediný proces v
systéme, bežiaci pod PID 1.

Guix tieto schopnosti jadra využíva pre poskytovanie úplne oddelených
prostredí a tiež kontajnerov s plným systémom Guix, teda odľahčených
virtuálnych strojov zdieľajúcich jadro s hostiteľským systémom. Táto
vlastnosť je užitočná predovšetkým pri používaní Guixu na cudzích
distribúciách pre zabránenie vplyvu cudzích knižníc a súborov nastavení,
ktoré sú dostupné celosystémovo.

@menu
* Kontajnery Guix::          Dokonale oddelené prostredia
* Kontajnery systému Guix::  Systém vo vašom systéme
@end menu

@node Kontajnery Guix
@section Kontajnery Guix

Najľahším spôsobom ako začať je použitie príkazu @code{proc} s voľbou
@option{--container}.  @xref{Invoking guix shell,,, guix, GNU Guix Reference
Manual} pre popis dostupných volieb.

Nasledovný úryvok kódu spúšťa jednoduchý proces shellu s väčšinou oblastí
mien nezdieľaných so systémom.  Proces vidí súčasný pracovný priečinok, ale
zvyšok súborového systému je mu nedostupný.  Toto mimoriadne oddelenie sa
môže hodiť keď sa chcete zbaviť všetkých nechcených zásahov premenných
prostredia, celosystémovo nainštalovaných knižníc alebo súborov nastavení.

@example
guix shell --container
@end example

Je to čisté, holé a vyprahnuté prostredie.  Zistíte, že neobsahuje ani GNU
coreutils, takže pre prebádanie tejto pustiny musíte použiť vstavané príkazy
shellu.  Aj z obvykle obrovského priečinka @file{/gnu/store} zostal iba
tieň.

@example sh
$ echo /gnu/store/*
/gnu/store/@dots{}-gcc-10.3.0-lib
/gnu/store/@dots{}-glibc-2.33
/gnu/store/@dots{}-bash-static-5.1.8
/gnu/store/@dots{}-ncurses-6.2.20210619
/gnu/store/@dots{}-bash-5.1.8
/gnu/store/@dots{}-profile
/gnu/store/@dots{}-readline-8.1.1
@end example

@cindex opúšťanie kontajnera
V podobnom prostredí sa toho veľa urobiť nedá okrem toho, že ho opustíte.
Na to vám poslúži klávesová skratka @key{^D} alebo príkaz @command{exit}.

@cindex sprístupnenie priečinkov, kontajner
@cindex zdieľanie priečinkov, kontajner
@cindex mapovanie umiestnení, kontajner
V kontajneri môžete sprístupniť aj iné priečinky. Použite
@option{--expose=PRIEČINOK} pre podvojné pripojenie daného priečinka ku
kontajneru len na čítanie, alebo použite @option{--share=PRIEČINOK}, aby sa
do daného priečinka dalo aj zapisovať. Pridaním dodatočného parametra za
cestou k priečinku môžete ovládať názov priečinka vrámci kontajnera. V
nasledovnom príklade mapujeme @file{/etc} hostiteľského systému ako
@file{/hosť/etc} v kontajneri obsahujúcom GNU coreutils.

@example sh
$ guix shell --container --share=/etc=/hosť/etc coreutils
$ ls /hosť/etc
@end example

Tiež je možné zabrániť mapovaniu súčasného pracovného priečinka v kontajneri
pomocou voľby @option{--no-cwd}.  Ďalším dobrým nápadom je vytvorenie
vyhradeného priečinka, ktorý kontajneru poslúži ako domovský priečinok, v
ktorom sa spustí shell kontajnera.

@cindex skryť systémové knižnice, kontajner
@cindex vyhnúť sa rozporom v ABI, kontajner
Na cudzom systéme možno kontajnerové prostredie využiť na preklad programov,
ktoré nemožno spojiť so systémovými knižnicami alebo so systémovým vývojovým
reťazcom.  Obvyklým príkladom je oblasť výskumu, kde používatelia často
inštalujú balíky vrámci sedenia R.  Mimo kontajnerového prostredia je
pravdepodobné, že cudzí vývojový reťazec či nevhodné systémové knižnice budú
nájdené ako prvé. Výsledkom sú potom nevyhovujúce binárne súbory, ktoré R
nemôže využiť.  V kontajneri tento problém zaniká, keďže systémové knižnice
a spustiteľné súbory jednoducho nie sú prístupné kvôli nezdieľanej oblasti
mien pripojení @code{mount}.

Vezmime si zrozumiteľný balíkospis poskytujúci pohodlné vývojové prostredie
pre použitie s R:

@lisp
(specifications->manifest
  (list "r-minimal"

        ;; základné balíky
        "bash-minimal"
        "glibc-locales"
        "nss-certs"

        ;; Všeobecné nástroje príkazového riadka, bez ktorých by bol kontajner pripustý.
        "coreutils"
        "grep"
        "which"
        "wget"
        "sed"

        ;; Nástroje značkovacieho jazyka R
        "pandoc"

        ;; Vývojový reťazec a všeobecné knižnice pre „install.packages“
        "gcc-toolchain@@10"
        "gfortran-toolchain"
        "gawk"
        "tar"
        "gzip"
        "unzip"
        "make"
        "cmake"
        "pkg-config"
        "cairo"
        "libxt"
        "openssl"
        "curl"
        "zlib"))
@end lisp

Použime tento balíkospis pre spustenie R v kontajnerovom prostredí.  Pre
zjednodušenie zdieľame sieťovú oblasť mien @code{net} pre prístup k sieťovým
rozhraniam hostiteľského systému.  Teraz môžeme zostavovať balíky R zo
zdrojového kódu obvyklým spôsobom bez obáv o rozpory týkajúce sa ABI alebo o
iné ťažkosti.

@example sh
$ guix shell --container --network --manifest=balikospis.scm -- R

R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
Copyright (C) 2022 The R Foundation for Statistical Computing
@dots{}
> e <- Sys.getenv("GUIX_ENVIRONMENT")
> Sys.setenv(GIT_SSL_CAINFO=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
> Sys.setenv(SSL_CERT_FILE=paste0(e, "/etc/ssl/certs/ca-certificates.crt"))
> Sys.setenv(SSL_CERT_DIR=paste0(e, "/etc/ssl/certs"))
> install.packages("Cairo", lib=paste0(getwd()))
@dots{}
* installing *source* package 'Cairo' ...
@dots{}
* DONE (Cairo)

The downloaded source packages are in
	'/tmp/RtmpCuwdwM/downloaded_packages'
> library("Cairo", lib=getwd())
> # success!
@end example

Používanie kontajnerov je zábavné, ale pri viac ako jednom interaktívnom
procese sa môžu zdať ťažkopádne.  Niektoré úlohy sú oveľa ľahšie
zvládnuteľné ak sú založené na skalopevnom základe plného systému Guix a
jeho bohatej množine systémových služieb.  V ďalšom oddieli si ukážeme ako
spustiť plný systém Guix v kontajneri.


@node Kontajnery systému Guix
@section Kontajnery systému Guix

Systém Guix poskytuje široké pole systémových služieb s deklaratívnym
nastavením vzájomne prepojených tak, aby vytvárali spoľahlivý a bezstavový
základ GNU systému pre akékoľvek úlohy.  Aj pri použití Guixu na cudzej
distribúcií môžete využiť výhody systému Guix spustením systémovej inštancie
v podobe kontajnera.  Vďaka vlastnostiam nezdieľaných oblastí mien
spomínaných v predošlom oddieli je výsledná inštancia systému Guix oddelená
od hostiteľského systému a zdieľa s ním len tie umiestnenia súborového
systému, ktoré ste si výslovne zvolili.

Kontajner systému Guix sa od procesu shell vytvoreného pomocou @command{guix
shell --container} v mnohých ohľadoch líši.  Zatiaľčo v kontajnerovom shelle
je hlavným oddeleným procesom Bash, v kontajneri so systémom Guix beží pod
PID 1 Shepherd.  V tomto prípade sú tiež všetky systémové služby
(@pxref{Services,,, guix, GNU Guix Reference Manual}) nastavené tak, ako by
boli v systéme Guix vrámci virtuálneho stroja alebo na skutočnom
vybavení. To zahŕňa démonov spravovaných GNU@tie{}Shepherdom
(@pxref{Shepherd Services,,, guix, GNU Guix Reference Manual}) ako aj ďalšie
druhy rozšírení operačného systému (@pxref{Service Composition,,, guix, GNU
Guix Reference Manual}).

Pozorovanú zvýšenú zložitosť v používaní kontajnerov so systémom Guix možno
jednoducho zdôvodniť keď sa musíte vysporiadať so zložitými aplikáciami,
ktoré majú vyššie či len prísnejšie požiadavky na prostredie, v ktorom sú
spúšťané, napr. súbory nastavení, vyhradené používateľské účty, priečinky
vyrovnávacej pamäte, súbory záznamov a pod.  Systém Guix tento druh
požiadaviek spĺňa nasadením systémových služieb.


@menu
* Databázový kontajner::     Databázový kontajner
* Prístup do siete vrámci kontajnera::  Prístup do siete vrámci kontajnera
@end menu

@node Databázový kontajner
@subsection Databázový kontajner

Dobrým príkladom by mohol byť databázový server PostgreSQL.  Väčšina
zložitosti nastavenia takéhoto databázového servera je zhrnutá do nezvyčajne
krátkeho zadania príslušnej služby:

@lisp
(service postgresql-service-type
         (postgresql-configuration
          (postgresql postgresql-14)))
@end lisp

Úplné zadanie operačného systému pre použitie s kontajnerom systému Guix by
vyzeralo asi takto:

@lisp
(use-modules (gnu))
(use-package-modules databases)
(use-service-modules databases)

(operating-system
  (host-name "container")
  (timezone "Europe/Bratislava")
  (file-systems (cons (file-system
                        (device (file-system-label "co-ma-po-tom"))
                        (mount-point "/")
                        (type "ext4"))
                      %base-file-systems))
  (bootloader (bootloader-configuration
               (bootloader grub-bootloader)
               (targets '("/dev/sdX"))))
  (services
   (cons* (service postgresql-service-type
                   (postgresql-configuration
                    (postgresql postgresql-14)
                    (config-file
                     (postgresql-config-file
                      (log-destination "stderr")
                      (hba-file
                       (plain-file "pg_hba.conf"
                                   "\
local	all	all			trust
host	all	all	10.0.0.1/32 	trust"))
                      (extra-config
                       '(("listen_addresses" "*")
                         ("log_directory"    "/var/log/postgresql")))))))
          (service postgresql-role-service-type
                   (postgresql-role-configuration
                    (roles
                     (list (postgresql-role
                            (name "skuska")
                            (create-database? #t))))))
          %base-services)))
@end lisp

Pomocou @code{postgresql-role-service-type} zadáme úlohu „skuska“ a
vytvoríme príslušnú databázu tak, aby sme všetko mohli priamo vyskúšať bez
ďalšieho ručného zasahovania.  Nastavenia v @code{postgresql-config-file}
umožňujú klientom pripájať sa z IP adresy 10.0.0.1 bez overenia --- zlý
nápad pre systémy vo výrobnom nasadení ale vhodný pre tento príklad.

Zostavme skript, ktorý spustí inštanciu systému Guix v podobe
kontajnera. Uložte horeuvedené zadanie pre @code{operating-system} do súboru
@file{os.scm} a potom použite @command{guix system container} pre zostavenie
spúšťača.  (@pxref{Invoking guix system,,, guix, GNU Guix Reference
Manual}).

@example
$ guix system container os.scm
Zostavia sa nasledovné odvodeniny:
  /gnu/store/@dots{}-run-container.drv
  @dots{}
building /gnu/store/@dots{}-run-container.drv...
/gnu/store/@dots{}-run-container
@end example

Teraz, keď už máme skript spúšťača, môžeme ho použiť pre spustenie nového
systému s bežiacou PostgreSQL službou.  Vedzte, že kvôli doposiaľ
neodstráneným obmedzeniam, musíme spúšťač spustiť ako root, napr. pomocou
@command{sudo}.

@example
$ sudo /gnu/store/@dots{}-run-container
systémový kontajner beží pod PID 5983
@dots{}
@end example

Presuňte proces do pozadia pomocou @key{Ctrl-z} nasledovaným @command{bg}.
Zaznamenajte si označenie procesu na výstupe; neskôr ho budeme potrebovať
pre pripojenie ku kontajneru.  Viete čo? Skúsme sa pripojiť ku kontajneru už
teraz.  Použijeme @command{nsenter}, nástroj poskytovaný balíkom
@code{util-linux}:

@example
$ guix shell util-linux
$ sudo nsenter -a -t 5983
root@@container /# pgrep -a postgres
49 /gnu/store/@dots{}-postgresql-14.4/bin/postgres -D /var/lib/postgresql/data --config-file=/gnu/store/@dots{}-postgresql.conf -p 5432
51 postgres: checkpointer
52 postgres: background writer
53 postgres: walwriter
54 postgres: autovacuum launcher
55 postgres: stats collector
56 postgres: logical replication launcher
root@@container /# exit
@end example

Služba PostgreSQL beží v kontajneri!


@node Prístup do siete vrámci kontajnera
@subsection Prístup do siete vrámci kontajnera
@cindex nastavenie siete v kontajneri

Na čo nám je systém Guix, na ktorom v kontajneri beží databázová služba
PostgreSQL, ku ktorej môžeme pristupovať len prostredníctvom procesov
spustených v kontajneri? Bolo by oveľa lepšie, keby sme k databáze mohli
pristupovať cez sieť.

Najjednoduchším spôsobom ako to dosiahnuť, je vytvoriť pár spojených
virtuálnych Ethernet zariadení (známych ako @code{veth}).  Jedno zo
zariadení (@code{ceth-skuska}) presunieme do oblasti názvov @code{net} nášho
kontajnera a to druhý koniec (@code{veth-skuska}) pripojenia ponecháme na
hostiteľskom systéme.

@example
pid=5983
ns="guix-skuska"
host="veth-skuska"
client="ceth-skuska"

# Pripojiť novú oblasť mien „guix-skuska“ k PID kontajnera.
sudo ip netns attach $ns $pid

# Vytvoriť pár zariadení.
sudo ip link add $host type veth peer name $client

# Presunúť klientske zariadenie do oblasti mien kontajnera.
sudo ip link set $client netns $ns
@end example

Potom nastavíme hostiteľa:

@example
sudo ip link set $host up
sudo ip addr add 10.0.0.1/24 dev $host
@end example

@dots{}a klienta:

@example
sudo ip netns exec $ns  ip link set lo up
sudo ip netns exec $ns  ip link set $client up
sudo ip netns exec $ns  ip addr add 10.0.0.2/24 dev $client
@end example

V tomto bode má hostiteľ dosah na klienta cez IP adresu 10.0.0.2 a kontajner
má dosah na hostiteľa cez IP 10.0.0.1.  To je všetko čo potrebujeme pre
spojenie sa s databázovým serverom v kontajneri z vonkajšieho prostredia
hostiteľského systému.

@example
$ psql -h 10.0.0.2 -U skuska
psql (14.4)
Type "help" for help.

skuska=> CREATE TABLE ahoj (kto TEXT NOT NULL);
CREATE TABLE
skuska=> INSERT INTO ahoj (kto) VALUES ('svet');
INSERT 0 1
skuska=> SELECT * FROM ahoj;
  kto
-------
 svet
(1 row)
@end example

Keď už sme skončili s týmto krátkym príkladom, trochu upracme:

@example
sudo kill $pid
sudo ip netns del $ns
sudo ip link del $host
@end example

@c *********************************************************************
@node Virtuálne stroje
@chapter Virtuálne stroje

Guix can produce disk images (@pxref{Invoking guix system,,, guix, GNU Guix
Reference Manual}) that can be used with virtual machines solutions such as
virt-manager, GNOME Boxes or the more bare QEMU, among others.

This chapter aims to provide hands-on, practical examples that relates to
the usage and configuration of virtual machines on a Guix System.

@menu
* Sieťový most pre QEMU::    Sieťový most pre QEMU
* Smerovaná sieť pre libvirt::  Smerovaná sieť pre libvirt
* Custom NAT-based network for libvirt::  Custom NAT-based network for 
                                            libvirt
* References: VM References.  Further reading on virtual machines.
@end menu

@node Sieťový most pre QEMU
@section Sieťový most pre QEMU
@cindex Network bridge interface
@cindex networking, bridge
@cindex qemu, network bridge

By default, QEMU uses a so-called ``user mode'' host network back-end, which
is convenient as it does not require any configuration.  Unfortunately, it
is also quite limited.  In this mode, the guest @abbr{VM, virtual machine}
can access the network the same way the host would, but it cannot be reached
from the host.  Additionally, since the QEMU user networking mode relies on
ICMP, ICMP-based networking tools such as @command{ping} do @emph{not} work
in this mode.  Thus, it is often desirable to configure a network bridge,
which enables the guest to fully participate in the network.  This is
necessary, for example, when the guest is to be used as a server.

@subsection Creating a network bridge interface

There are many ways to create a network bridge.  The following command shows
how to use NetworkManager and its @command{nmcli} command line interface
(CLI) tool, which should already be available if your operating system
declaration is based on one of the desktop templates:

@example sh
# nmcli con add type bridge con-name br0 ifname br0
@end example

To have this bridge be part of your network, you must associate your network
bridge with the Ethernet interface used to connect with the network.
Assuming your interface is named @samp{enp2s0}, the following command can be
used to do so:

@example sh
# nmcli con add type bridge-slave ifname enp2s0 master br0
@end example

@quotation Important
Only Ethernet interfaces can be added to a bridge.  For wireless interfaces,
consider the routed network approach detailed in @xref{Smerovaná sieť pre libvirt}.
@end quotation

By default, the network bridge will allow your guests to obtain their IP
address via DHCP, if available on your local network.  For simplicity, this
is what we will use here.  To easily find the guests, they can be configured
to advertise their host names via mDNS.

@subsection Configuring the QEMU bridge helper script

QEMU comes with a helper program to conveniently make use of a network
bridge interface as an unprivileged user @pxref{Network options,,, QEMU,
QEMU Documentation}.  The binary must be made setuid root for proper
operation; this can be achieved by adding it to the
@code{privileged-programs} field of your (host) @code{operating-system}
definition, as shown below:

@example lisp
(privileged-programs
 (cons (privileged-program
         (program (file-append qemu "/libexec/qemu-bridge-helper"))
         (setuid? #t))
       %default-privileged-programs))
@end example

The file @file{/etc/qemu/bridge.conf} must also be made to allow the bridge
interface, as the default is to deny all.  Add the following to your list of
services to do so:

@example lisp
(extra-special-file "/etc/qemu/host.conf"
                    (plain-file "host.conf" "allow br0\n"))
@end example

@subsection Invoking QEMU with the right command line options

When invoking QEMU, the following options should be provided so that the
network bridge is used, after having selected a unique MAC address for the
guest.

@quotation Important
By default, a single MAC address is used for all guests, unless provided.
Failing to provide different MAC addresses to each virtual machine making
use of the bridge would cause networking issues.
@end quotation

@example sh
$ qemu-system-x86_64 [...] \
    -device virtio-net-pci,netdev=user0,mac=XX:XX:XX:XX:XX:XX \
    -netdev bridge,id=user0,br=br0 \
    [...]
@end example

To generate MAC addresses that have the QEMU registered prefix, the
following snippet can be employed:

@example sh
mac_address="52:54:00:$(dd if=/dev/urandom bs=512 count=1 2>/dev/null \
                           | md5sum \
                           | sed -E 's/^(..)(..)(..).*$/\1:\2:\3/')"
echo $mac_address
@end example

@subsection Networking issues caused by Docker

If you use Docker on your machine, you may experience connectivity issues
when attempting to use a network bridge, which are caused by Docker also
relying on network bridges and configuring its own routing rules.  The
solution is add the following @code{iptables} snippet to your
@code{operating-system} declaration:

@example lisp
(service iptables-service-type
             (iptables-configuration
              (ipv4-rules (plain-file "iptables.rules" "\
*filter
:INPUT ACCEPT [0:0]
:FORWARD DROP [0:0]
:OUTPUT ACCEPT [0:0]
-A FORWARD -i br0 -o br0 -j ACCEPT
COMMIT
"))
@end example

@node Smerovaná sieť pre libvirt
@section Smerovaná sieť pre libvirt
@cindex Virtual network bridge interface
@cindex networking, virtual bridge
@cindex libvirt, virtual network switch

If the machine hosting your virtual machines is connected wirelessly to the
network, you won't be able to use a true network bridge as explained in the
preceding section (@pxref{Sieťový most pre QEMU}).  In this case, the next
best option is to use a @emph{virtual network switch} with static routing
and to configure a libvirt-powered virtual machine to use it (via the
@command{virt-manager} GUI for example).  This is similar to the default
mode of operation of QEMU/libvirt, except that instead of using @abbr{NAT,
Network Address Translation}, it relies on static routes to join the
@abbr{VM, virtual machine} IP address to the @abbr{LAN, local area
network}.  This provides two-way connectivity to and from the virtual
machine, which is needed for exposing services hosted on the virtual
machine.

@subsection Creating a virtual network switch

A virtual network switch consists of a virtual network device called a
`virtual bridge', DHCP server (dnsmasq) and firewall rules (iptables). See
the @url{https://wiki.libvirt.org/VirtualNetworking.html, libvirt Wiki
article on Virtual Networking} for more details on the modes of operation,
management and implementation of virtual network switches.

The @command{virsh} command, provided by the @code{libvirt} package, makes
it very easy to create a virtual switch.  You first need to choose a network
subnet for your virtual switch; if your home LAN is in the
@samp{192.168.1.0/24} network, you could opt to use e.g.@:
@samp{192.168.2.0/24}.  Define an XML file, e.g.@: @file{/tmp/virbr0.xml},
containing the following:

@example
<network>
  <name>virbr0</name>
  <bridge name="virbr0" />
  <forward mode="route"/>
  <ip address="192.168.2.0" netmask="255.255.255.0">
    <dhcp>
      <range start="192.168.2.1" end="192.168.2.254"/>
    </dhcp>
  </ip>
</network>
@end example

Then create and configure the interface using the @command{virsh} command,
as root:

@example
virsh net-define /tmp/virbr0.xml
virsh net-autostart virbr0
virsh net-start virbr0
@end example

The @samp{virbr0} interface should now be visible e.g.@: via the @samp{ip
address} command.  It will be automatically started every time your libvirt
virtual machine is started.

@subsection Configuring the static routes for your virtual bridge

If you configured your virtual machine to use your newly created
@samp{virbr0} virtual bridge interface, it should already receive an IP via
DHCP such as @samp{192.168.2.15} and be reachable from the server hosting
it, e.g.@: via @samp{ping 192.168.2.15}.  There's one last configuration
needed so that the VM can reach the external network: adding static routes
to the network's router.

In this example, the LAN network is @samp{192.168.1.0/24} and the router
configuration web page may be accessible via e.g.@: the
@url{http://192.168.1.1} page.  On a router running the
@url{https://librecmc.org/, libreCMC} firmware, you would navigate to the
@clicksequence{Network @click{} Static Routes} page
(@url{https://192.168.1.1/cgi-bin/luci/admin/network/routes}), and you would
add a new entry to the @samp{Static IPv4 Routes} with the following
information:

@table @samp
@item Interface
lan
@item Target
192.168.2.0
@item IPv4-Netmask
255.255.255.0
@item IPv4-Gateway
@var{server-ip}
@item Route type
unicast
@end table

where @var{server-ip} is the IP address of the machine hosting the VMs,
which should be static.

After saving/applying this new static route, external connectivity should
work from within your VM; you can e.g.@: run @samp{ping gnu.org} to verify
that it functions correctly.

@node Custom NAT-based network for libvirt
@section Custom NAT-based network for libvirt

As mentioned in the preceding section (@pxref{Smerovaná sieť pre libvirt}),
libvirt allows virtual networks to be defined via XML files and managed by
the @command{virsh} command.  The details of the creation and removal of
virtual network switches are handled by libvirt, so the user does not have
to deal with them.

However, libvirt's handling of virtual network switches can sometimes clash
with more complex networking setups.  In particular, the iptables rules
inserted by libvirt for switches operating in the NAT mode can clash with
existing iptables/nftables rules, leading to insecure or broken packet
filtering.

In such cases, the only solution is to manually set up a virtual network
switch.  This section will provide instructions on how to do so using Guix
System services.

@subsection Creating the virtual network bridge

The @code{static-networking-service-type} can be used to create a virtual
network bridge and assign an IP address to it:

@example lisp
(service static-networking-service-type
         (list (static-networking
                ;; The default provision is 'networking; if you're using any
                ;; other service with this provision, such as
                ;; `network-manager-service-type`, then you need to change the
                ;; default.
                (provision '(static-networking))
                (links
                 (list (network-link
                        (name "virbr0")
                        (type 'bridge)
                        (arguments '()))))
                (addresses
                 (list (network-address
                        (device "virbr0")
                        (value "192.168.10.1/24")))))))
@end example

@subsection Running dnsmasq for the virtual network bridge

The @code{dnsmasq-service-type} can be used to provide DNS and DHCP for
guests connected to this virtual network switch:

@example lisp
(service dnsmasq-service-type
         (dnsmasq-configuration
          ;; You can have multiple instances of `dnsmasq-service-type` as long
          ;; as each one has a different shepherd-provision.
          (shepherd-provision '(dnsmasq-virbr0))
          (extra-options (list
                          ;; Only bind to the virtual bridge. This
                          ;; avoids conflicts with other running
                          ;; dnsmasq instances.
                          "--except-interface=lo"
                          "--interface=virbr0"
                          "--bind-dynamic"
                          ;; IPv4 addresses to offer to VMs. This
                          ;; should match the chosen subnet.
                          "--dhcp-range=192.168.10.2,192.168.10.254"))))
@end example

@subsection Configuring NAT for the virtual network switch

If you intend to use the virtual network switch in NAT mode, you will need
to use nftables (or iptables) rules to set up IP masquerading.  The
following example shows how to use @code{nftables-service-type} to do this:

@example lisp
(service nftables-service-type
         (nftables-configuration
          (ruleset
           (plain-file "nftables.conf"
                       "\
table inet filter @{

  chain input @{
    type filter hook input priority filter; policy drop;
    # Add your existing packet filtering rules here...
    iifname virbr0 udp dport 67 counter accept comment \"allow dhcp on virbr0\"
    iifname virbr0 meta l4proto @{tcp, udp@} th dport 53 accept \\
        comment \"allow dns on virbr0\"
  @}

  chain forward @{
    type filter hook forward priority filter; policy drop;
    # Add your existing forwarding rules here...
    iifname virbr0 accept comment \"allow outbound traffic from virbr0\"
    oifname virbr0 ct state @{established, related @} accept \\
        comment \"allow established traffic to virbr0\"
  @}

@}

table inet nat @{
  chain postrouting @{
    type nat hook postrouting priority srcnat; policy accept;
    # Add your existing nat rules here...
    iifname virbr0 ip daddr @{ 224.0.0.0/24, 255.255.255.255/32 @} return \\
        comment \"don't masquerade to reserved address blocks\"
    iifname virbr0 oifname != virbr0 masquerade \\
        comment \"masquerade all outgoing traffic from VMs\"
  @}
@}
"))))
@end example

Ensure that you have IPv4 forwarding enabled (you can use
@code{sysctl-service-type} for this).

@node VM References
@section Odkazy

@itemize
@item
@uref{https://jamielinux.com/docs/libvirt-networking-handbook/index.html,
The (unofficial) libvirt Networking Handbook}@* Note that this resource is
rather outdated at the time of writing (as of March 2025, it was last
updated in 2015).  Nevertheless, the authors of this chapter have found it
to be a valuable source of information.
@end itemize

@c *********************************************************************
@node Pokročilá správa balíkov
@chapter Pokročilá správa balíkov

Guix je funkcionálny správca balíkov, ktorý ponúka omnoho viac možností než
tradiční správcovia balíkov.  Tieto možnosti nemusia mať pre nezasvätených
zdanlivé využitie.  Účelom tohto oddielu je predstaviť niekoľko pokročilých
pojmov správy balíkov.

@pxref{Package Management,,, guix, GNU Guix Reference Manual}.

@menu
* Profily Guix v praxi::     Postupy pre spravovanie viacerých profilov a 
                               balíkospisov.
@end menu

@node Profily Guix v praxi
@section Profily Guix v praxi

Guix má veľmi užitočnú schopnosť, o ktorej noví používatelia málokedy vedia:
@dfn{profily}.  Sú spôsobom ako zoskupiť inštalácie balíkov a všetci
používatelia rovnakého systému môžu používať toľko rôznych profil, koľko len
chcú.

Či už ste vývojár alebo nie, profily vám môžu poskytnúť veľa možností.
Napriek tomu, že sa od @emph{tradičných správcov balíkov} myšlienkovo líšia,
môžu byť veľmi užitočné, keď sa s nimi naučíte pracovať.

@quotation Poznámka
This section is an opinionated guide on the use of multiple profiles.  It
predates @command{guix shell} and its fast profile cache (@pxref{Invoking
guix shell,,, guix, GNU Guix Reference Manual}).

In many cases, you may find that using @command{guix shell} to set up the
environment you need, when you need it, is less work that maintaining a
dedicated profile.  Your call!
@end quotation

Ak ste oboznámení s @samp{virtualenv} v Pythone, môžete si profily
predstaviť ako všeobecné @samp{virtualenv}, ktoré môžu obsahovať ľubovoľné
programové vybavenie, a nie len to založené na Pythone.  Okrem toho, profily
sú sebestačné: zachytávajú všetky závislosti potrebné pre beh programov, čo
zaručuje, že všetky programy v profile budú fungovať vždy a v každom čase.

Viacero profilov má mnoho výhod:

@itemize
@item
Jasné významové oddelenie rozličných balíkov, ktoré využívate v rôznych
súvislostiach.

@item
Viacero profilov možno v prostredí sprístupniť buď pri prihlásení, alebo
vrámci vyhradeného shellu.

@item
Profily možno načítať na požiadanie.  Napríklad, môžete používať viacero
shellov a v každom z nich môže bežať iný profil.

@item
Oddelenie: Programy z jedného profilu nebudú používať programy z
druhého. Môžete tiež nainštalovať rôzne vydania rovnakých programov do dvoch
rôznych profilov bez vzájomných rozporov.

@item
Znásobenie: Profily môžu zdieľať rovnaké závislosti, čo umožňuje ušetriť
úložné miesto.

@item
Opakovateľné: pri použití so zadaným balíkospisom môže byť profil jasne
určený úpravou Guixu, ktorá bola použitá pri jeho spustení.  To znamená, že
ten istý profil možno
@uref{https://guix.gnu.org/blog/2018/multi-dimensional-transactions-and-rollbacks-oh-my/,
napodobniť kdekoľvek a kedykoľvek} iba na základe údaju o použitej úprave.
Viď oddiel @ref{Opakovateľné profily}.

@item
Jednoduchšie aktualizácie a spravovanie: Pri viacerých profiloch je
jednoduché udržiavať zoznamy balíkov poruke a zaistiť ich bezstarostné
aktualizovanie.
@end itemize

Niekoľko príznačných a často používaných profilov:

@itemize
@item
Závislosti projektu, na ktorom pracujete.

@item
Knižnice vášho obľúbeného programovacieho jazyka.

@item
Programy príznačné pre prenosný počítač (ako @samp{powertop}), ktoré
nepotrebujete na stolnom počítači.

@item
@TeX{}live (tento sa môže zvlášť hodiť, keď potrebujete nainštalovať len
jeden balík pre dokument, ktorý vám práve prišiel elektronickou poštou).

@item
Hry.
@end itemize

Ponorme sa do toho!

@menu
* Základné použitie balíkospisov::  Základné použitie balíkospisov
* Požadované balíky::        Požadované balíky
* Predvolený profil::        Predvolený profil
* Výhody balíkospisov::      Výhody balíkospisov
* Opakovateľné profily::     Opakovateľné profily
@end menu

@node Základné použitie balíkospisov
@subsection Základné použitie balíkospisov

Guixovský profil možno nastaviť pomocou @dfn{balíkospisu}. Balíkospis je
kúsok kódu určujúci množinu balíkov, ktorú chcete zahrnúť do vášho profilu;
vyzerá takto:

@lisp
(specifications->manifest
  '("balik-1"
    ;; Vydanie 1.3 balíka balik-2.
    "balik-2@@1.3"
    ;; Výstup „lib“ balíka balik-3.
    "balik-3:lib"
    ; ...
    "balik-N"))
@end lisp

@xref{Writing Manifests,,, guix, GNU Guix Reference Manual} pre viac
podrobností o skladbe.

Môžeme si vytvoriť balíkospis pre každý profil a nainštalovať ich
nasledovne:

@example
GUIX_DOPLNKOVE_PROFILY=$HOME/.guix-extra-profiles
mkdir -p "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt # ak ešte nejestvuje
guix package --manifest=/cesta/ku/guix-balikospis-mojho-projektu.scm \
 --profile="$GUIX_DOPLNKOVE_PROFILY"/moj-projekt/moj-projekt
@end example

Tu sme si nastavili premennú s ľubovoľne zvoleným názvom
@samp{GUIX_DOPLNKOVE_PROFILY} odkazujúcu na priečinok, do ktorého si uložíme
naše profily vrámci tohto článku.

Dáva zmysel uložiť si všetky svoje profily do jedného priečinka, v ktorom má
každý z nich pridelený osobitný podpriečinok.  Takto bude každý podpriečinok
obsahovať symbolické odkazy presne jedného profilu.  Okrem toho, bude ľahké
získať zoznam profilov v hociktorom programovacom jazyku (napr.@: skript
shellu) pomocou jednoduchej slučky prechádzajúcej podpriečinkami v
@samp{GUIX_DOPLNKOVE_PROFILY}.

Všimnite si, že slučkou tiež možno prechádzať výstup

@example
guix package --list-profiles
@end example

aj keď budete pravdepodobne musieť vynechať @file{~/.config/guix/current}.

Pre nastavenie všetkých profilov po prihlásení, pridajte toto do vášho
@file{~/.bash_profile} (alebo podobného súboru):

@example
for i in $GUIX_DOPLNKOVE_PROFILY/*; do
  profile=$i/$(basename "$i")
  if [ -f "$profile"/etc/profile ]; then
    GUIX_PROFILE="$profile"
    . "$GUIX_PROFILE"/etc/profile
  fi
  unset profile
done
@end example

Poznámka pre používateľov systému Guix: horeuvedené odráža to, ako sa váš
predvolený profil @file{~/.guix-profile} nastavuje z @file{/etc/profile},
ktorý je predvolene načítaný vrámci @file{~/.bashrc}.

Môžete sa samozrejme rozhodnúť, že z nich načítate len niektoré:

@example
for i in "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt-1 "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt-2; do
  profile=$i/$(basename "$i")
  if [ -f "$profile"/etc/profile ]; then
    GUIX_PROFILE="$profile"
    . "$GUIX_PROFILE"/etc/profile
  fi
  unset profile
done
@end example

Keď je profil vypnutý, je jednoduché ho zapnúť vo vyhradenom shelle bez
„znečistenia“ zvyšku sedenia:

@example
GUIX_PROFILE="cesta/k/moj-projekt" ; . "$GUIX_PROFILE"/etc/profile
@end example

Kľúčovým krok pri zapnutí profilu je @emph{načítanie} jeho súboru
@samp{etc/profile}. Tento súbor obsahuje kód shellu, ktorý nastaví tie
správne premenné prostredia potrebné pre spojazdnenie programov v profile.
Je vytvoreným samotným Guixom a určený na načítanie pomocou príkazu
@code{source}.  Obsahuje rovnaké premenné ako tie, ktoré by ste získali
vykonaním:

@example
guix package --search-paths=prefix --profile=$moj_profil"
@end example

Viď voľby príkazu v @ref{Invoking guix package,,, guix, GNU Guix Reference
Manual}.

Profil môžete aktualizovať opätovnou inštaláciou balíkospisu:

@example
guix package -m /cesta/ku/guix-balikospis-mojho-projektu.scm \
 -p "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt/moj-projekt
@end example

Ak chcete aktualizovať všetky profily, môžete ich jednoducho prechádzať
slučkou.  Napríklad, predpokladajúc, že váš balíkospis je uložený v
@file{~/.guix-manifests/guix-$profil-balikospis.scm}, kde @samp{$profil} je
názov profilu (napr.@: „projekt1“), pomocou shellu môžete vykonať
nasledovné:

@example
for profile in "$GUIX_DOPLNKOVE_PROFILY"/*; do
  guix package --profile="$profil" \
   --manifest="$HOME/.guix-manifests/guix-$profil-balikospis.scm"
done
@end example

Každý profil má svoje vlastné pokolenia:

@example
guix package -p "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt/moj-projekt --list-generations
@end example

Môžete sa vrátiť ku ktorémukoľvek pokoleniu daného profilu:

@example
guix package -p "$GUIX_DOPLNKOVE_PROFILY"/moj-projekt/moj-projekt --switch-generations=17
@end example

Konečne, ak chcete prepnúť na iný profil bez zdedenia súčasné prostredia,
môžete ho zapnúť v prázdnom shelle:

@example
env -i $(which bash) --login --noprofile --norc
. moj-projekt/etc/profile
@end example

@node Požadované balíky
@subsection Požadované balíky

Zapnutie profilu znamená hlavne nastavenie množstva premenných prostredia.
Toto je úloha pre @samp{etc/profile} vrámci profilu.

@emph{Poznámka: Nastavujú sa len premenné prostredia balíkov, ktoré ich používajú.}

Napríklad, @samp{MANPATH} nebude nastavená ak profil neobsahuje aplikáciu,
ktorá túto premennú priamo využíva.  Takže, ak chcete po zapnutí profilu
jednoducho pristupovať k stránkam pomocníka, máte dve možnosti:

@itemize
@item
Buď nastavíte túto premennú prostredia ručne, napr.
@example
export MANPATH=/cesta/ku/profilu$@{MANPATH:+:@}$MANPATH
@end example

@item
Alebo pridajte @samp{man-db} do balíkospisu profilu.
@end itemize

To isté platí aj pre @samp{INFOPATH} (môžete nainštalovať
@samp{info-reader}), @samp{PKG_CONFIG_PATH} (nainštalujte
@samp{pkg-config}), atď.

@node Predvolený profil
@subsection Predvolený profil

A čo s predvoleným profilom, ktorý Guix uchováva v @file{~/.guix-profile}?

Môžete mu prideliť ľubovoľnú úlohu.  Mohli by ste doň nainštalovať
balíkospis balíkov, ktoré chcete mať stále poruke.

Ďalšia možnosť je, že doň nebudete inštalovať žiaden balíkospis a profil vám
poslúži len pre dočasné balíky. V tomto prípade môžete jednoducho vykonať

@example
guix install balik-jablko
guix upgrade balik-hruska
@end example

bez nutnosti uvádzať cestu k profilu.

@node Výhody balíkospisov
@subsection Výhody balíkospisov

Manifests let you @dfn{declare} the set of packages you'd like to have in a
profile (@pxref{Writing Manifests,,, guix, GNU Guix Reference Manual}).
They are a convenient way to keep your package lists around and, say, to
synchronize them across multiple machines using a version control system.

Medzi časté sťažnosti používateľov patrí, že inštalácia balíkospisov
obsahujúcich veľké množstvo balíkov môže trvať veľmi dlho.  Je to otravné
hlavne vtedy, keď potrebujete aktualizovať iba jeden balík vrámci dlhého
balíkospisu.

Je to ďalší dôvod pre používanie viacerých profilov, čo umožňuje rozdelenie
balíkospisov do viacerých množín významovo prepojených balíkov.  Používanie
viacerých, menších profilov tiež vedie k väčšej prispôsobiteľnosti a
pohodlnejšej práci.

Balíkospisy prinášajú mnoho výhod.  Predovšetkým, zjednodušujú údržbu:

@itemize
@item
Pri nastavení profilu z balíkospisu, on samotný stačí na uschovanie zoznamu
balíkov poruke a na opätovnú inštaláciu profilu niekedy inokedy alebo na
inom systéme.  V prípade dočasných účelových profilov by sme museli vytvoriť
zadanie balíkospisu ručne a udržiavať správne verzie tých balíkov, pri
ktorých nebola použitá ich predvolená verzia.

@item
@code{guix package --upgrade} sa pokúša o aktualizáciu balíkov s rozšírenými
vstupmi aj vtedy, keď to nie je potrebné.  Guixové balíkospisy touto
nevýhodou netrpia.

@item
Pri čiastočnej aktualizácii profilu sa môžu vyskytnúť rozpory (kvôli
rozličným závislostiam medzi aktualizovanými a neaktualizovanými balíkmi),
ktoré je obvykle náročné vyriešiť ručne.  Pri balíkospisoch k tomu
nedochádza, keďže všetky balíky sa aktualizujú súčasne.

@item
Ako už bolo spomenuté, balíkospisy umožňujú napodobniteľné profily, zatiaľčo
príkazy @code{guix install}, @code{guix upgrade}, a pod. nie, pretože
zakaždým vytvárajú nové profily, aj keď obsahujú rovnaké balíky.  Viď
@uref{https://issues.guix.gnu.org/issue/33285, súvisiacu rozpravu}.

@item
Zadania balíkospisov môžu využiť aj iné príkazy @samp{guix}.  Napríklad,
pomocou @code{guix weather -m balikospis.scm} môžete zistiť dostupné
množstvo náhrad a lepšie sa rozhodnúť, či chcete vykonať aktualizáciu už
dnes, alebo chvíľu počkáte.  Ďalší príklad: @code{guix pack -m
balikospis.scm} vám umožní vytvoriť súpravu obsahujúcu všetky balíky
balíkospisu (a ich závislosti).

@item
Nakoniec, balíkospisy sú zapísané v jazyku Scheme, ako záznamy druhu
@samp{<manifest>}.  Možno s nimi, teda, v Scheme aj narábať a používať ich s
rozličnými
@uref{https://sk.wikipedia.org/wiki/Application_programming_interface, API}
Guixu.
@end itemize

It's important to understand that while manifests can be used to declare
profiles, they are not strictly equivalent: profiles have the side effect
that they ``pin'' packages in the store, which prevents them from being
garbage-collected (@pxref{Invoking guix gc,,, guix, GNU Guix Reference
Manual})  and ensures that they will still be available at any point in the
future.  The @command{guix shell} command also protects recently-used
profiles from garbage collection; profiles that have not been used for a
while may be garbage-collected though, along with the packages they refer
to.

To be 100% sure that a given profile will never be collected, install the
manifest to a profile and use @code{GUIX_PROFILE=/the/profile;
. "$GUIX_PROFILE"/etc/profile} as explained above: this guarantees that our
hacking environment will be available at all times.

@emph{Bezpečnostné upozornenie:} Napriek tomu, že je uchovávanie starých
profilov šikovné, zapamätajte si, že zastarané balíky nemusia obsahovať
najnovšie bezpečnostné záplaty.

@node Opakovateľné profily
@subsection Opakovateľné profily

Napodobnenie profilu bit-po-bite vyžaduje dva údaje:

@itemize
@item
a manifest (@pxref{Writing Manifests,,, guix, GNU Guix Reference Manual});
@item
a Guix channel specification (@pxref{Replicating Guix,,, guix, GNU Guix
Reference Manual}).
@end itemize

Vskutku, samotný balíkospis nestačí: rozdielne verzie Guixu (alebo rozdielne
kanály) môžu viesť k odlišných výsledkom pre daný balíkospis.

You can output the Guix channel specification with @samp{guix describe
--format=channels} (@pxref{Invoking guix describe,,, guix, GNU Guix
Reference Manual}).  Save this to a file, say @samp{channel-specs.scm}.

Na inom počítači môžete toto určenie kanálov spolu s balíkospisom použiť na
napodobnenie presne toho istého profilu:

@example
GUIX_DOPLNKOVE_PROFILY=$HOME/.guix-doplnkove-profily
GUIX_DOPLNKY=$HOME/.guix-doplnky

mkdir -p "$GUIX_DOPLNKY"/moj-projekt
guix pull --channels=urcenie-kanalov.scm --profile="$GUIX_DOPLNKY/moj-projekt/guix"

mkdir -p "$GUIX_DOPLNKOVE_PROFILY/moj-projekt"
"$GUIX_DOPLNKY"/moj-projekt/guix/bin/guix package \
 --manifest=/cesta/ku/guix-balikospis-mojho-projektu.scm \
 --profile="$GUIX_DOPLNKOVE_PROFILY"/moj-projekt/moj-projekt
@end example

Profil kanálu Guix, ktorý ste práve nainštalovali môžete bezpečne odstrániť,
profil projektu na ňom nezávisí.

@node Vývoj programového vybavenia
@chapter Vývoj programového vybavenia

@cindex development, with Guix
@cindex software development, with Guix
Guix is a handy tool for developers; @command{guix shell}, in particular,
gives a standalone development environment for your package, no matter what
language(s) it's written in (@pxref{Invoking guix shell,,, guix, GNU Guix
Reference Manual}).  To benefit from it, you have to initially write a
package definition and have it either in Guix proper, or in a channel, or
directly in your project's source tree as a @file{guix.scm} file.  This last
option is appealing: all developers have to do to get set up is clone the
project's repository and run @command{guix shell}, with no arguments.

Development needs go beyond development environments though.  How can
developers perform continuous integration of their code in Guix build
environments? How can they deliver their code straight to adventurous users?
This chapter describes a set of files developers can add to their repository
to set up Guix-based development environments, continuous integration, and
continuous delivery---all at once@footnote{This chapter is adapted from a
@uref{https://guix.gnu.org/en/blog/2023/from-development-environments-to-continuous-integrationthe-ultimate-guide-to-software-development-with-guix/,
blog post} published in June 2023 on the Guix web site.}.

@menu
* Začíname::                 Krok 0: použitie „guix shell“.
* Zostavovanie s Guixom::    Krok 1: zostavenie vášho kódu.
* Repozitár ako kanál::      Krok 2: premena repozitára na kanál.
* Obmeny balíkov::           Prídavok: Zadávanie obmien.
* Nastavenie priebežného zaraďovania::  Krok 3: priebežné zaraďovanie.
* Zostavovací balíkospis::   Prídavok: Balíkospis.
* Zhrnutie::                 Súhrn.
@end menu

@node Začíname
@section Začíname

How do we go about ``Guixifying'' a repository? The first step, as we've
seen, will be to add a @file{guix.scm} at the root of the repository in
question. We'll take @uref{https://www.gnu.org/software/guile,Guile} as an
example in this chapter: it's written in Scheme (mostly) and C, and has a
number of dependencies---a C compilation tool chain, C libraries, Autoconf
and its friends, LaTeX, and so on. The resulting @file{guix.scm} looks like
the usual package definition (@pxref{Defining Packages,,, guix, GNU Guix
Reference Manual}), just without the @code{define-public} bit:

@lisp
;; The ‘guix.scm’ file for Guile, for use by ‘guix shell’.

(use-modules (guix)
             (guix build-system gnu)
             ((guix licenses) #:prefix license:)
             (gnu packages autotools)
             (gnu packages base)
             (gnu packages bash)
             (gnu packages bdw-gc)
             (gnu packages compression)
             (gnu packages flex)
             (gnu packages gdb)
             (gnu packages gettext)
             (gnu packages gperf)
             (gnu packages libffi)
             (gnu packages libunistring)
             (gnu packages linux)
             (gnu packages pkg-config)
             (gnu packages readline)
             (gnu packages tex)
             (gnu packages texinfo)
             (gnu packages version-control))

(package
  (name "guile")
  (version "3.0.99-git")                          ;funky version number
  (source #f)                                     ;no source
  (build-system gnu-build-system)
  (native-inputs
   (append (list autoconf
                 automake
                 libtool
                 gnu-gettext
                 flex
                 texinfo
                 texlive-base                 ;for "make pdf"
                 texlive-epsf
                 gperf
                 git
                 gdb
                 strace
                 readline
                 lzip
                 pkg-config)

           ;; When cross-compiling, a native version of Guile itself is
           ;; needed.
           (if (%current-target-system)
               (list this-package)
               '())))
  (inputs
   (list libffi bash-minimal))
  (propagated-inputs
   (list libunistring libgc))

  (native-search-paths
   (list (search-path-specification
          (variable "GUILE_LOAD_PATH")
          (files '("share/guile/site/3.0")))
         (search-path-specification
          (variable "GUILE_LOAD_COMPILED_PATH")
          (files '("lib/guile/3.0/site-ccache")))))
  (synopsis "Scheme implementation intended especially for extensions")
  (description
   "Guile is the GNU Ubiquitous Intelligent Language for Extensions,
and it's actually a full-blown Scheme implementation!")
  (home-page "https://www.gnu.org/software/guile/")
  (license license:lgpl3+))
@end lisp

Quite a bit of boilerplate, but now someone who'd like to hack on Guile now
only needs to run:

@lisp
guix shell
@end lisp

That gives them a shell containing all the dependencies of Guile: those
listed above, but also @emph{implicit dependencies} such as the GCC tool
chain, GNU@ Make, sed, grep, and so on.  @xref{Invoking guix shell,,, guix,
GNU Guix Reference Manual}, for more info on @command{guix shell}.

@quotation The chef's recommendation
Our suggestion is to create development environments like this:

@example
guix shell --container --link-profile
@end example

@noindent
... or, for short:

@example
guix shell -CP
@end example

That gives a shell in an isolated container, and all the dependencies show
up in @code{$HOME/.guix-profile}, which plays well with caches such as
@file{config.cache} (@pxref{Cache Files,,, autoconf, Autoconf}) and absolute
file names recorded in generated @code{Makefile}s and the likes. The fact
that the shell runs in a container brings peace of mind: nothing but the
current directory and Guile's dependencies is visible inside the container;
nothing from the system can possibly interfere with your development.
@end quotation

@node Zostavovanie s Guixom
@section Level 1: Building with Guix

Now that we have a package definition (@pxref{Začíname}), why not
also take advantage of it so we can build Guile with Guix? We had left the
@code{source} field empty, because @command{guix shell} above only cares
about the @emph{inputs} of our package---so it can set up the development
environment---not about the package itself.

To build the package with Guix, we'll need to fill out the @code{source}
field, along these lines:

@lisp
(use-modules (guix)
             (guix git-download)  ;for ‘git-predicate’
             @dots{})

(define vcs-file?
  ;; Return true if the given file is under version control.
  (or (git-predicate (current-source-directory))
      (const #t)))                                ;not in a Git checkout

(package
  (name "guile")
  (version "3.0.99-git")                          ;funky version number
  (source (local-file "." "guile-checkout"
                      #:recursive? #t
                      #:select? vcs-file?))
  @dots{})
@end lisp

Here's what we changed compared to the previous section:

@enumerate
@item
We added @code{(guix git-download)} to our set of imported modules, so we
can use its @code{git-predicate} procedure.
@item
We defined @code{vcs-file?} as a procedure that returns true when passed a
file that is under version control. For good measure, we add a fallback case
for when we're not in a Git checkout: always return true.
@item
We set @code{source} to a
@uref{https://guix.gnu.org/manual/devel/en/html_node/G_002dExpressions.html#index-local_002dfile,@code{local-file}}---a
recursive copy of the current directory (@code{"."}), limited to files under
version control (the @code{#:select?} bit).
@end enumerate

From there on, our @file{guix.scm} file serves a second purpose: it lets us
build the software with Guix. The whole point of building with Guix is that
it's a ``clean'' build---you can be sure nothing from your working tree or
system interferes with the build result---and it lets you test a variety of
things. First, you can do a plain native build:

@example
guix build -f guix.scm
@end example

But you can also build for another system (possibly after setting up
@pxref{Daemon Offload Setup, offloading,, guix, GNU Guix Reference Manual}
or @pxref{Virtualization Services, transparent emulation,, guix, GNU Guix
Reference Manual}):

@lisp
guix build -f guix.scm -s aarch64-linux -s riscv64-linux
@end lisp

@noindent
@dots{} or cross-compile:

@lisp
guix build -f guix.scm --target=x86_64-w64-mingw32
@end lisp

You can also use @dfn{package transformations} to test package variants
(@pxref{Package Transformation Options,,, guix, GNU Guix Reference Manual}):

@example
# What if we built with Clang instead of GCC?
guix build -f guix.scm \
  --with-c-toolchain=guile@@3.0.99-git=clang-toolchain

# What about that under-tested configure flag?
guix build -f guix.scm \
  --with-configure-flag=guile@@3.0.99-git=--disable-networking
@end example

Handy!

@node Repozitár ako kanál
@section Level 2: The Repository as a Channel

We now have a Git repository containing (among other things) a package
definition (@pxref{Zostavovanie s Guixom}).  Can't we turn it into a
@dfn{channel} (@pxref{Channels,,, guix, GNU Guix Reference Manual})? After
all, channels are designed to ship package definitions to users, and that's
exactly what we're doing with our @file{guix.scm}.

Turns out we can indeed turn it into a channel, but with one caveat: we must
create a separate directory for the @code{.scm} file(s) of our channel so
that @command{guix pull} doesn't load unrelated @code{.scm} files when
someone pulls the channel---and in Guile, there are lots of them! So we'll
start like this, keeping a top-level @file{guix.scm} symlink for the sake of
@command{guix shell}:

@lisp
mkdir -p .guix/modules
mv guix.scm .guix/modules/guile-package.scm
ln -s .guix/modules/guile-package.scm guix.scm
@end lisp

To make it usable as part of a channel, we need to turn our @file{guix.scm}
file into a @dfn{package module} (@pxref{Package Modules,,, guix, GNU Guix
Reference Manual}): we do that by changing the @code{use-modules} form at
the top to a @code{define-module} form. We also need to actually
@emph{export} a package variable, with @code{define-public}, while still
returning the package value at the end of the file so we can still use
@command{guix shell} and @command{guix build -f guix.scm}. The end result
looks like this (not repeating things that haven't changed):

@lisp
(define-module (guile-package)
  #:use-module (guix)
  #:use-module (guix git-download)   ;for ‘git-predicate’
  @dots{})

(define vcs-file?
  ;; Return true if the given file is under version control.
  (or (git-predicate (dirname (dirname (current-source-directory))))
      (const #t)))                                ;not in a Git checkout

(define-public guile
  (package
    (name "guile")
    (version "3.0.99-git")                          ;funky version number
    (source (local-file "../.." "guile-checkout"
                        #:recursive? #t
                        #:select? vcs-file?))
    @dots{}))

;; Return the package object define above at the end of the module.
guile
@end lisp

We need one last thing: a
@uref{https://guix.gnu.org/manual/devel/en/html_node/Package-Modules-in-a-Sub_002ddirectory.html,@code{.guix-channel}
file} so Guix knows where to look for package modules in our repository:

@lisp
;; This file lets us present this repo as a Guix channel.

(channel
  (version 0)
  (directory ".guix/modules"))  ;look for package modules under .guix/modules/
@end lisp

To recap, we now have these files:

@lisp
.
├── .guix-channel
├── guix.scm → .guix/modules/guile-package.scm
└── .guix
    └── modules
       └── guile-package.scm
@end lisp

And that's it: we have a channel! (We could do better and support
@uref{https://guix.gnu.org/manual/devel/en/html_node/Specifying-Channel-Authorizations.html,@emph{channel
authentication}} so users know they're pulling genuine code. We'll spare you
the details here but it's worth considering!) Users can pull from this
channel by
@uref{https://guix.gnu.org/manual/devel/en/html_node/Specifying-Additional-Channels.html,adding
it to @code{~/.config/guix/channels.scm}}, along these lines:

@lisp
(append (list (channel
                (name 'guile)
                (url "https://git.savannah.gnu.org/git/guile.git")
                (branch "main")))
        %default-channels)
@end lisp

After running @command{guix pull}, we can see the new package:

@example
$ guix describe
Generation 264  May 26 2023 16:00:35    (current)
  guile 36fd2b4
    repository URL: https://git.savannah.gnu.org/git/guile.git
    branch: main
    commit: 36fd2b4920ae926c79b936c29e739e71a6dff2bc
  guix c5bc698
    repository URL: https://git.guix.gnu.org/guix.git
    commit: c5bc698e8922d78ed85989985cc2ceb034de2f23
$ guix package -A ^guile$
guile   3.0.99-git      out,debug       guile-package.scm:51:4
guile   3.0.9           out,debug       gnu/packages/guile.scm:317:2
guile   2.2.7           out,debug       gnu/packages/guile.scm:258:2
guile   2.2.4           out,debug       gnu/packages/guile.scm:304:2
guile   2.0.14          out,debug       gnu/packages/guile.scm:148:2
guile   1.8.8           out             gnu/packages/guile.scm:77:2
$ guix build guile@@3.0.99-git
[@dots{}]
/gnu/store/axnzbl89yz7ld78bmx72vpqp802dwsar-guile-3.0.99-git-debug
/gnu/store/r34gsij7f0glg2fbakcmmk0zn4v62s5w-guile-3.0.99-git
@end example

That's how, as a developer, you get your software delivered directly into
the hands of users! No intermediaries, yet no loss of transparency and
provenance tracking.

With that in place, it also becomes trivial for anyone to create Docker
images, Deb/RPM packages, or a plain tarball with @command{guix pack}
(@pxref{Invoking guix pack,,, guix, GNU Guix Reference Manual}):

@example
# How about a Docker image of our Guile snapshot?
guix pack -f docker -S /bin=bin guile@@3.0.99-git

# And a relocatable RPM?
guix pack -f rpm -R -S /bin=bin guile@@3.0.99-git
@end example

@node Obmeny balíkov
@section Bonus: Package Variants

We now have an actual channel, but it contains only one package (@pxref{Repozitár ako kanál}).  While we're at it, we can define @dfn{package
variants} (@pxref{Defining Package Variants,,, guix, GNU Guix Reference
Manual}) in our @file{guile-package.scm} file, variants that we want to be
able to test as Guile developers---similar to what we did above with
transformation options. We can add them like so:

@lisp
;; This is the ‘.guix/modules/guile-package.scm’ file.

(define-module (guile-package)
  @dots{})

(define-public guile
  @dots{})

(define (package-with-configure-flags p flags)
  "Return P with FLAGS as additional 'configure' flags."
  (package/inherit p
    (arguments
     (substitute-keyword-arguments (package-arguments p)
       ((#:configure-flags original-flags #~(list))
        #~(append #$original-flags #$flags))))))

(define-public guile-without-threads
  (package
    (inherit (package-with-configure-flags guile
                                           #~(list "--without-threads")))
    (name "guile-without-threads")))

(define-public guile-without-networking
  (package
    (inherit (package-with-configure-flags guile
                                           #~(list "--disable-networking")))
    (name "guile-without-networking")))


;; Return the package object defined above at the end of the module.
guile
@end lisp

We can build these variants as regular packages once we've pulled the
channel. Alternatively, from a checkout of Guile, we can run a command like
this one from the top level:

@lisp
guix build -L $PWD/.guix/modules guile-without-threads
@end lisp

@node Nastavenie priebežného zaraďovania
@section Level 3: Setting Up Continuous Integration

@cindex continuous integration (CI)
The channel we defined above (@pxref{Repozitár ako kanál})  becomes
even more interesting once we set up
@uref{https://en.wikipedia.org/wiki/Continuous_integration, @dfn{continuous
integration}} (CI). There are several ways to do that.

You can use one of the mainstream continuous integration tools, such as
GitLab-CI. To do that, you need to make sure you run jobs in a Docker image
or virtual machine that has Guix installed. If we were to do that in the
case of Guile, we'd have a job that runs a shell command like this one:

@lisp
guix build -L $PWD/.guix/modules guile@@3.0.99-git
@end lisp

Doing this works great and has the advantage of being easy to achieve on
your favorite CI platform.

That said, you'll really get the most of it by using
@uref{https://guix.gnu.org/en/cuirass,Cuirass}, a CI tool designed for and
tightly integrated with Guix. Using it is more work than using a hosted CI
tool because you first need to set it up, but that setup phase is greatly
simplified if you use its Guix System service (@pxref{Continuous
Integration,,, guix, GNU Guix Reference Manual}).  Going back to our
example, we give Cuirass a spec file that goes like this:

@lisp
;; Cuirass spec file to build all the packages of the ‘guile’ channel.
(list (specification
        (name "guile")
        (build '(channels guile))
        (channels
         (append (list (channel
                         (name 'guile)
                         (url "https://git.savannah.gnu.org/git/guile.git")
                         (branch "main")))
                 %default-channels))))
@end lisp

It differs from what you'd do with other CI tools in two important ways:

@itemize
@item
Cuirass knows it's tracking @emph{two} channels, @code{guile} and
@code{guix}. Indeed, our own @code{guile} package depends on many packages
provided by the @code{guix} channel---GCC, the GNU libc, libffi, and so
on. Changes to packages from the @code{guix} channel can potentially
influence our @code{guile} build and this is something we'd like to see as
soon as possible as Guile developers.
@item
Build results are not thrown away: they can be distributed as
@dfn{substitutes} so that users of our @code{guile} channel transparently
get pre-built binaries! (@pxref{Substitutes,,, guix, GNU Guix Reference
Manual}, for background info on substitutes.)
@end itemize

From a developer's viewpoint, the end result is this
@uref{https://ci.guix.gnu.org/jobset/guile,status page} listing
@emph{evaluations}: each evaluation is a combination of commits of the
@code{guix} and @code{guile} channels providing a number of
@emph{jobs}---one job per package defined in @file{guile-package.scm} times
the number of target architectures.

As for substitutes, they come for free! As an example, since our
@code{guile} jobset is built on ci.guix.gnu.org, which runs @command{guix
publish} (@pxref{Invoking guix publish,,, guix, GNU Guix Reference Manual})
in addition to Cuirass, one automatically gets substitutes for @code{guile}
builds from ci.guix.gnu.org; no additional work is needed for that.

@node Zostavovací balíkospis
@section Bonus: Build manifest

The Cuirass spec above is convenient: it builds every package in our
channel, which includes a few variants (@pxref{Nastavenie priebežného zaraďovania}).  However, this might be insufficiently expressive in some
cases: one might want specific cross-compilation jobs, transformations,
Docker images, RPM/Deb packages, or even system tests.

To achieve that, you can write a @dfn{manifest} (@pxref{Writing Manifests,,,
guix, GNU Guix Reference Manual}).  The one we have for Guile has entries
for the package variants we defined above, as well as additional variants
and cross builds:

@lisp
;; This is ‘.guix/manifest.scm’.

(use-modules (guix)
             (guix profiles)
             (guile-package))   ;import our own package module

(define* (package->manifest-entry* package system
                                   #:key target)
  "Return a manifest entry for PACKAGE on SYSTEM, optionally cross-compiled to
TARGET."
  (manifest-entry
    (inherit (package->manifest-entry package))
    (name (string-append (package-name package) "." system
                         (if target
                             (string-append "." target)
                             "")))
    (item (with-parameters ((%current-system system)
                            (%current-target-system target))
            package))))

(define native-builds
  (manifest
   (append (map (lambda (system)
                  (package->manifest-entry* guile system))

                '("x86_64-linux" "i686-linux"
                  "aarch64-linux" "armhf-linux"
                  "powerpc64le-linux"))
           (map (lambda (guile)
                  (package->manifest-entry* guile "x86_64-linux"))
                (cons (package
                        (inherit (package-with-c-toolchain
                                  guile
                                  `(("clang-toolchain"
                                     ,(specification->package
                                       "clang-toolchain")))))
                        (name "guile-clang"))
                      (list guile-without-threads
                            guile-without-networking
                            guile-debug
                            guile-strict-typing))))))

(define cross-builds
  (manifest
   (map (lambda (target)
          (package->manifest-entry* guile "x86_64-linux"
                                    #:target target))
        '("i586-pc-gnu"
          "aarch64-linux-gnu"
          "riscv64-linux-gnu"
          "i686-w64-mingw32"
          "x86_64-linux-gnu"))))

(concatenate-manifests (list native-builds cross-builds))
@end lisp

We won't go into the details of this manifest; suffice to say that it
provides additional flexibility. We now need to tell Cuirass to build this
manifest, which is done with a spec slightly different from the previous
one:

@lisp
;; Cuirass spec file to build all the packages of the ‘guile’ channel.
(list (specification
        (name "guile")
        (build '(manifest ".guix/manifest.scm"))
        (channels
         (append (list (channel
                         (name 'guile)
                         (url "https://git.savannah.gnu.org/git/guile.git")
                         (branch "main")))
                 %default-channels))))
@end lisp

We changed the @code{(build @dots{})} part of the spec to @code{'(manifest
".guix/manifest.scm")} so that it would pick our manifest, and that's it!

@node Zhrnutie
@section Zhrnutie

We picked Guile as the running example in this chapter and you can see the
result here:

@itemize
@item
@uref{https://git.savannah.gnu.org/cgit/guile.git/tree/.guix-channel?id=cd57379b3df636198d8cd8e76c1bfbc523762e79,@code{.guix-channel}};
@item
@uref{https://git.savannah.gnu.org/cgit/guile.git/tree/.guix/modules/guile-package.scm?id=cd57379b3df636198d8cd8e76c1bfbc523762e79,@code{.guix/modules/guile-package.scm}}
with the top-level @file{guix.scm} symlink;
@item
@uref{https://git.savannah.gnu.org/cgit/guile.git/tree/.guix/manifest.scm?id=cd57379b3df636198d8cd8e76c1bfbc523762e79,@code{.guix/manifest.scm}}.
@end itemize

These days, repositories are commonly peppered with dot files for various
tools: @code{.envrc}, @code{.gitlab-ci.yml}, @code{.github/workflows},
@code{Dockerfile}, @code{.buildpacks}, @code{Aptfile},
@code{requirements.txt}, and whatnot. It may sound like we're proposing a
bunch of @emph{additional} files, but in fact those files are expressive
enough to @emph{supersede} most or all of those listed above.

With a couple of files, we get support for:

@itemize
@item
development environments (@command{guix shell});
@item
pristine test builds, including for package variants and for
cross-compilation (@command{guix build});
@item
continuous integration (with Cuirass or with some other tool);
@item
continuous delivery to users (@emph{via} the channel and with pre-built
binaries);
@item
generation of derivative build artifacts such as Docker images or Deb/RPM
packages (@command{guix pack}).
@end itemize

This a nice (in our view!) unified tool set for reproducible software
deployment, and an illustration of how you as a developer can benefit from
it!


@c *********************************************************************
@node Správa prostredí
@chapter Správa prostredí

Guix poskytuje viacero nástrojov na správu prostredí.  Táto kapitola ich
predstavuje.

@menu
* Guix prostredie cez direnv::  Vytvoriť Guix prostredie pomocou direnv
@end menu

@node Guix prostredie cez direnv
@section Guix prostredie cez direnv

Guix poskytuje balík @samp{direnv}, ktorým možno rozšíriť prostredie shellu
po zmene priečinka.  Tento nástroj sa dá využiť na prípravu čistého
prostredia Guix.

Nasledovný príklad poskytuje shellovskú funkciu pre súbor
@file{~/.direnvrc}, ktorú možno použiť z Git repozitára Guixu v súbore
@file{~/src/guix/.envrc} na nastavenie vývojového prostredia podobnému tomu,
ktoré je opísané v @pxref{Building from Git,,, guix, GNU Guix Reference
Manual}.

Vytvorte súbor @file{~/.direnvrc} obsahujúci nasledovný kód Bash:

@example
# Vďaka <https://github.com/direnv/direnv/issues/73#issuecomment-152284914>
export_function()
@{
  local name=$1
  local alias_dir=$PWD/.direnv/aliases
  mkdir -p "$alias_dir"
  PATH_add "$alias_dir"
  local target="$alias_dir/$name"
  if declare -f "$name" >/dev/null; then
    echo "#!$SHELL" > "$target"
    declare -f "$name" >> "$target" 2>/dev/null
    # Všimnite si, že pridávame premenné shellu do spúšťača funkcie.
    echo "$name \$*" >> "$target"
    chmod +x "$target"
  fi
@}

use_guix()
@{
    # Nastaviť žetón pre GitHub.
    export GUIX_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

    # Vyčistiť „GUIX_PACKAGE_PATH“.
    export GUIX_PACKAGE_PATH=""

    # Opätovne vytvoriť koreň zberača odpadkov.
    gcroots="$HOME/.config/guix/gcroots"
    mkdir -p "$gcroots"
    gcroot="$gcroots/guix"
    if [ -L "$gcroot" ]
    then
        rm -v "$gcroot"
    fi

    # Doplnkové balíky.
    PACKAGES_MAINTENANCE=(
        direnv
        git
        git:send-email
        git-cal
        gnupg
        guile-colorized
        guile-readline
        less
        ncurses
        openssh
        xdot
    )

    # Balíky prostredia.
    PACKAGES=(help2man guile-sqlite3 guile-gcrypt)

    # Vďaka <https://lists.gnu.org/archive/html/guix-devel/2016-09/msg00859.html>
    eval "$(guix shell --search-paths --root="$gcroot" --pure \
     --development guix $@{PACKAGES[@@]@} $@{PACKAGES_MAINTENANCE[@@]@} "$@@")"

    # Vopred zadať voľby nastavenia.
    configure()
    @{
        ./configure
    @}
    export_function configure

    # Spustiť „make“ a možno niečo zostaviť.
    build()
    @{
        make -j 2
        if [ $# -gt 0 ]
        then
            ./pre-inst-env guix build "$@@"
        fi
    @}
    export_function build

    # Vopred zadať Git príkaz pre odoslanie zmien.
    push()
    @{
        git push --set-upstream origin
    @}
    export_function push

    clear                        # Vyčistiť obrazovku.
    git-cal --author='Vaše meno' # Zobraziť kalendár zmien.

    # Zobraziť pomocníka príkazov.
    echo "
build          zostaviť balík alebo iba projekt ak nebol poskytnutý žiaden parameter
configure      vykonať ./configure s predvolenými voľbami
push           odoslať zmeny do vzdialeného repozitára Git
"
@}
@end example

Každý projekt obsahujúci @file{.envrc} s reťazcom @code{use guix} bude mať
vopred pripravené premenné prostredia a funkcie.

Vykonajte @command{direnv allow} pre prvé nastavenie prostredia.


@c *********************************************************************
@node Reproducible Research
@chapter Using Guix for Reproducible Research

@cindex reproducible research
Because it supports reproducible deployment, Guix is a solid foundation for
@dfn{reproducible research workflows}.  This section is targeted at
scientists; it shows how to add Guix to one's reproducible research
toolbox@footnote{This chapter is adapted from a
@uref{https://hpc.guix.info/blog/2023/06/a-guide-to-reproducible-research-papers/,
blog post published on the Guix-HPC web site in 2023.}.}.

With Guix as the basis of your computational workflow, you can get what's in
essence @emph{executable provenance meta-data}: it's like the list of
package name/version pairs some provide as an appendix to their publication,
except more precise and immediately deployable.

This section is a guide in just four steps on how to make your computational
experiments reproducible using Guix, and how to provide that information in
your research paper.

@menu
* Setting Up the Environment::  Step 1: using `guix shell'.
* Recording the Environment::  Step 2: using `guix describe'.
* Ensuring Long-Term Source Code Archiving::  Step 3: Software Heritage.
* Referencing the Software Environment::  Step 4: SWHIDs.
@end menu

@node Setting Up the Environment
@section Step 1: Setting Up the Environment

The first step is to identify precisely what packages you need in your
software environment to run your computational experiment.

Assuming you have a Python script that uses NumPy, you can start by creating
an environment that contains these two packages and to run your code in that
environment (@pxref{Invoking guix shell,,, guix, GNU Guix Reference
Manual}):

@example
guix shell -C python python-numpy -- python3 ./myscript.py
@end example

The @code{-C} flag here (or @code{--container}) instructs @command{guix
shell} to create that environment in an isolated container with nothing but
the two packages you asked for.  That way, if @command{./myscript.py} needs
more than these two packages, it'll fail to run and you'll immediately
notice.  On some systems @code{--container} is not supported; in that case,
you can resort to @code{--pure} instead.

Perhaps you'll find that you also need Pandas and add it to the environment:

@example
guix shell -C python python-numpy python-pandas -- \
  python3 ./myscript.py
@end example

If you fail to guess the name of the package (this one was easy!), try
@code{guix search}.

Environments for Python, R, and similar high-level languages are relatively
easy to set up.  For C/C++ code, you may need more packages:

@example
guix shell -C gcc-toolchain cmake coreutils grep sed make -- @dots{}
@end example

Or perhaps you'll find that you could just as well provide a package
definition for your code---@pxref{Defining Packages,,, guix, GNU Guix
Reference Manual}, to learn more on how to do that.

Eventually, you'll have a list of packages that satisfies your needs.

@quotation What if a package is missing?
Guix and the main scientific channels provide about
@uref{https://hpc.guix.info/browse, tens of thousands of packages}.  Yet,
there's always the possibility that the one package you need is missing.

In that case, you will need to provide a definition for it (@pxref{Defining
Packages,,, guix, GNU Guix Reference Manual}) in a dedicated channel of
yours (@pxref{Creating a Channel,,, guix, GNU Guix Reference Manual}).  For
software in Python, R, and other high-level languages, most of the work can
usually be automated by using @command{guix import} (@pxref{Invoking guix
import,,, guix, GNU Guix Reference Manual}).

Join @uref{https://guix.gnu.org/contact/,the friendly Guix community} to get
help!
@end quotation

@node Recording the Environment
@section Step 2: Recording the Environment

Now that you have that @code{guix shell} command line with a list of
packages, the best course of action is to save it in a @emph{manifest}
file---essentially a software bill of materials---that Guix can then ingest
(@pxref{Writing Manifests,,, guix, GNU Guix Reference Manual}).  The easiest
way to get started is by ``translating'' your command line into a manifest:

@example
guix shell python python-numpy python-pandas \
  --export-manifest > manifest.scm
@end example

Put that manifest under version control! From there anyone can redeploy the
software environment described by the manifest and run code in that
environment:

@example
guix shell -C -m manifest.scm -- python3 ./myscript.py
@end example

Here's what @file{manifest.scm} reads:

@lisp
;; What follows is a "manifest" equivalent to the command line you gave.
;; You can store it in a file that you may then pass to any 'guix' command
;; that accepts a '--manifest' (or '-m') option.

(specifications->manifest
  (list "python" "python-numpy" "python-pandas"))
@end lisp

It's a code snippet that lists packages.  Notice that there are no version
numbers! Indeed, these version numbers are specified in package definitions,
located in Guix channels.  To allow others to reproduce the exact same
environment as the one you're running, you need to @emph{pin Guix itself} ,
by capturing the current Guix channel commits with @command{guix describe}
(@pxref{Replicating Guix,,, guix, GNU Guix Reference Manual}):

@example
guix describe -f channels > channels.scm
@end example

@cindex lock files, for reproducibility
This @code{channels.scm} file is similar in spirit to ``lock files'' that
some deployment tools employ to pin package revisions. You should also keep
it under version control in your code, and possibly update it once in a
while when you feel like running your code against newer versions of its
dependencies. With this file, anyone, @emph{at any time and on any machine},
can now reproduce the exact same environment by running:

@example
guix time-machine -C channels.scm -- \
  shell -C -m manifest.scm -- \
  python3 ./myscript.py
@end example

In this example we rely solely on the @code{guix} channel, which provides
the Python packages we need. Perhaps some of the packages you need live
@uref{https://hpc.guix.info/channels,in other channels}---maybe
@code{guix-cran} if you use R, maybe @code{guix-science}.  That's fine:
@code{guix describe} also captures that.

Of course do include a @file{README} file giving the exact command to run
the code. Not everyone uses Guix so it can be helpful to also provide
minimal non-Guix setup instructions: which package versions are used, how
software is built, etc. As we have seen, such instructions would likely be
inaccurate and inconvenient to follow at best. Yet, it can be a useful
starting point to someone trying to recreate a @emph{similar} environment
using different tools. It should probably be presented as such, with the
understanding that the only way to get the @emph{same} environment is to use
Guix.

@node Ensuring Long-Term Source Code Archiving
@section Step 3: Ensuring Long-Term Source Code Archiving

We insisted on version control before: for the @file{manifest.scm} and
@file{channels.scm} files, but of course also for your own code. Our
recommendation is to have these two @file{.scm} files in the same repository
as the code they're about.

Since the goal is enabling reproducibility, source code availability is a
prime concern.  Source code hosting services come and go and we don't want
our code to vanish in a whim and render our published research work
unverifiable. @uref{https://www.softwareheritage.org/,Software Heritage}
(SWH for short) is @emph{the} solution for this: SWH archives public source
code and provides unique intrinsic identifiers to refer to
it---@uref{https://swhid.org, @dfn{SWHIDs}}.  Guix itself is
@uref{https://doi.org/10.1145/3641525.3663622,connected to SWH} to (1)@
ensure that the source code of its packages is archived, and (2)@ to fall
back to downloading from the SWH archive should code vanish from its
original site.

Once your own code is available in a public version-control repository, such
as a Git repository on your lab's hosting service, you can ask SWH to
archive it by going to its
@uref{https://archive.softwareheritage.org/save/,Save Code Now} interface.
SWH will process the request asynchronously and eventually you'll find your
code has made it into @uref{https://archive.softwareheritage.org/,the
archive}.

@node Referencing the Software Environment
@section Step 4: Referencing the Software Environment

This brings us to the last step: referring to our code @emph{and} software
environment in our beloved paper.  We already have all our code and Guix
files in the same repository, which is archived on SWH.  Thanks to SWH, we
now have a SWHID, which uniquely identifies the relevant revision of our
code.

Following
@uref{https://www.softwareheritage.org/howto-archive-and-reference-your-code/,SWH's
own guide}, we'll pick an @code{swh:dir} kind of identifier, which refers to
the directory of the relevant revision/commit of our repository, and we'll
keep @emph{contextual info} for clarity---that includes the original
URL. Putting it all together, we'll conclude our paper with a sentence along
these lines:

@quotation Example
The source code used to produce this study, as well as instructions to run
it in the right software environment using GNU@ Guix, is archived on
Software Heritage as
@uref{https://archive.softwareheritage.org/swh:1:dir:cc8919d7705fbaa31efa677ce00bef7eb374fb80;origin=https://gitlab.inria.fr/lcourtes-phd/edcc-2006-redone;visit=swh:1:snp:71a4d08ef4a2e8455b67ef0c6b82349e82870b46;anchor=swh:1:rev:36fde7e5ba289c4c3e30d9afccebbe0cfe83853a,@code{swh:1:dir:cc8919d7705fbaa31efa677ce00bef7eb374fb80;origin=https://gitlab.inria.fr/lcourtes-phd/edcc-2006-redone;visit=swh:1:snp:71a4d08ef4a2e8455b67ef0c6b82349e82870b46;anchor=swh:1:rev:36fde7e5ba289c4c3e30d9afccebbe0cfe83853a}}.
@end quotation

With this information, the reader can:

@itemize
@item
get the source code;
@item
reproduce its software environment with @code{guix time-machine} and run the
code;
@item
inspect and possibly modify both the code and its environment.
@end itemize

Mission accomplished!

@c *********************************************************************
@node Inštalácia Guixu na zhluk počítačov
@chapter Inštalácia Guixu na zhluk počítačov

@cindex inštalácia na zhluk počítačov
@cindex vysokovýkonné počítanie, HPC
@cindex HPC, vysokovýkonné počítanie
Guix môže zaujať vedcov a odborníkov na @acronym{HPC, vysokovýkonné
počítanie}: umožňuje jednoduchšie a opakovateľné nasadenie zložitých sústav
programov---môžete opätovne nasadiť to isté programové vybavenie na rôzne
stroje a v rôznych časových odstupoch.

V tejto kapitole sa pozrieme na to, ako môže systémový správca zhluku
počítačov nainštalovať Guix na celosystémovej úrovni tak, aby ho bolo možné
využiť na všetkých uzloch zhluku, a povieme si aj rôznych
ústupkoch@footnote{Táto kapitola je založená na
@uref{https://hpc.guix.info/blog/2017/11/installing-guix-on-a-cluster/,
príspevku zverejnenom na stránke Guix-HPC v roku 2017}.}.

@quotation Poznámka
V tomto prípade predpokladáme, že na zhluku počítačov beží distribúcia
GNU/Linuxu iná než systém Guix, a že budeme Guix inštalovať na ňu.
@end quotation

@menu
* Nastavenie hlavného uzla::  Uzol, ktorý spúšťa démona.
* Nastavenie výpočtových uzlov::  Klientske uzly.
* Prístup do siete zhluku::  Správa obmedzení pre vstup do siete.
* Využitie diskového priestoru zhluku::  Úvahy o využití diskového 
                                           priestoru.
* Úvahy o zabezpečení zhluku::  Udržiavanie zhluku v bezpečí.
@end menu

@node Nastavenie hlavného uzla
@section Nastavenie hlavného uzla

Odporúčaný postup je nastaviť jeden @emph{hlavný uzol}, kde bude bežať
@command{guix-daemon}, a @file{/gnu/store} uzlom sprístupniť cez NFS.

Zapamätajte si, že @command{guix-daemon} je zodpovedný za spúšťanie
zostavovacích procesov a sťahovaní v mene klientov (@pxref{Invoking
guix-daemon,,, guix, GNU Guix Reference Manual}), a v širšom ohľade za
prístup ku @file{/gnu/store}, ktoré obsahuje binárne súbory všetkých balíkov
zostavené každým z používateľov.  „Klient“ tu odkazuje na všetky Guix
príkazy prístupné pre používateľov, ako @code{guix install}.  Na zhluku
počítačov môžu tieto príkazy bežať na výpočtových uzloch a musia byť v
spojení s @code{guix-daemon} na hlavnom uzle.

Na začiatok, inštaláciu na hlavný uzol možno vykonať podľa obvyklého postupu
(@pxref{Binary Installation,,, guix, GNU Guix Reference Manual}).  Vďaka
inštalačnému skriptu by to malo byť rýchle.  Po dokončení inštalácie musíme
vykonať niekoľko prispôsobení.

Pretože chceme, aby bol @code{guix-daemon} dostupný nie len z hlavného uzla,
ale aj z výpočtových uzlov, musíme to zariadiť tak, aby zisťoval
prichádzajúce pripojenia cez TCP/IP.  Upravíme, teda, spúšťací súbor systemd
@file{/etc/systemd/system/guix-daemon.service} pre @code{guix-daemon} a
pridáme voľbu @code{--listen} na riadok s @code{ExecStart} asi takto:

@c Since Debian Buster, \ is documented to split lines.
@c https://manpages.debian.org/buster/systemd/systemd.exec.5.en.html
@c Use it in PDF and Info versions to avoid cut-off at the page border.
@ifnothtml
@example
ExecStart=/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon \
    --build-users-group=guixbuild \
    --listen=/var/guix/daemon-socket/socket --listen=0.0.0.0
@end example
@end ifnothtml
@ifhtml
@example
ExecStart=/var/guix/profiles/per-user/root/current-guix/bin/guix-daemon --build-users-group=guixbuild --listen=/var/guix/daemon-socket/socket --listen=0.0.0.0
@end example
@end ifhtml

Pre uplatnenie zmien musíme službu opätovne spustiť:

@example
systemctl daemon-reload
systemctl restart guix-daemon
@end example

@quotation Poznámka
@code{--listen=0.0.0.0} znamená, že @code{guix-daemon} spracuje
@emph{všetky} TCP pripojenia prichádzajúce cez koncový bod 44146
(@pxref{Invoking guix-daemon,,, guix, GNU Guix Reference Manual}). V prípade
zhluku počítačov, kde je hlavný uzol prístupný výhradne z miestnej, je to
vyhovujúce. Nechcete, predsa, aby bol @code{guix-daemon} prístupný aj z
internetu!
@end quotation

Ďalším krokom je sprístupnenie úložiska cez NFS v
@uref{https://linux.die.net/man/5/exports,@file{/etc/exports}} asi takto:

@example
/gnu/store    *(ro)
/var/guix     *(rw, async)
/var/log/guix *(ro)
@end example

Priečinok @file{/gnu/store} môže byť sprístupnený len na čítanie, keďže
@command{guix-daemon} na hlavnom uzle ho nikdy nebude upravovať.
@file{/var/guix} obsahuje @emph{profily používateľov}, ktoré spravuje
@code{guix package}. Aby mohli používatelia inštalovať s @code{guix
package}, toto umiestnenie musí zostať prístupné aj na čítanie, aj na zápis.

Používatelia si môžu okrem predvoleného profilu @file{~/.guix-profile}
vytvoriť toľko profilov, koľko len chcú.  Napríklad, @code{guix package -p
~/dev/python-dev -i python} nainštaluje Python do profilu prístupného cez
symbolický odkaz @code{~/dev/python-dev}.  Aby sme sa uistili, že sa zberač
odpadkov tomuto profilu vyhne---t.j., že Python nebude z @file{/gnu/store}
odstránený pokiaľ sa profil používa---@emph{domovské priečinky by tiež mali
byť pripojené k rovnakému uzlu}. @code{guix-daemon} tak bude vedieť o týchto
neobvyklých profiloch a zabráni vyčisteniu programového vybavenia, na ktoré
odkazujú.

Môže byť užitočné pravidelne odstraňovať nepoužívané súbory z
@file{/gnu/store} pomocou @command{guix gc} (@pxref{Invoking guix gc,,,
guix, GNU Guix Reference Manual}). Nastavíte to pridaním vstupu contrab na
hlavný uzol:

@example
root@@master# crontab -e
@end example

@noindent
… s niečím takýmto:

@example
# Každé ráno o 5:00 spustiť zberač odpadkov a zabezpečiť,
# že v /gnu/store je aspoň 10 GB voľného miesta.
0 5 * * 1  /usr/local/bin/guix gc -F10G
@end example

S hlavným uzlom sme hotoví! Pozrime sa teraz na výpočtové uzly.

@node Nastavenie výpočtových uzlov
@section Nastavenie výpočtových uzlov

Predovšetkým musíme na výpočtových uzloch pripojiť NFS priečinky
sprístupnené hlavným uzlom.  Môžeme tak urobiť pridaním nasledovných riadkov
do @uref{https://linux.die.net/man/5/fstab,@file{/etc/fstab}}:

@example
@var{hlavny-uzol}:/gnu/store    /gnu/store    nfs  defaults,_netdev,vers=3 0 0
@var{hlavny-uzol}:/var/guix     /var/guix     nfs  defaults,_netdev,vers=3 0 0
@var{hlavny-uzol}:/var/log/guix /var/log/guix nfs  defaults,_netdev,vers=3 0 0
@end example

@noindent
… kde @var{hlavny-uzol} je názov alebo IP adresa vášho hlavného uzla.
Potom, predpokladajúc, že prípojné body sú prítomné, by ste mali byť schopní
pripojiť každý z nich ku výpočtovým uzlom.

Ďalej musíme používateľom poskytnúť predvolený @command{guix} príkaz, ktorý
môžu spustiť po prvom prihlásení k zhluku počítačov (nakoniec si spustením
@command{guix pull} vytvoria „vlastný“ @command{guix} príkaz).  Podobne ako
to inštalačný skript zariadil na hlavnom uzle, uložíme ho do
@file{/usr/local/bin}:

@example
mkdir -p /usr/local/bin
ln -s /var/guix/profiles/per-user/root/current-guix/bin/guix \
      /usr/local/bin/guix
@end example

Potom musíme @code{guixu} povedať, aby bol v spojení s démonom bežiacim na
hlavnom uzle, pridaním týchto riadkov do @code{/etc/profile}:

@example
GUIX_DAEMON_SOCKET="guix://@var{hlavny-uzol}"
export GUIX_DAEMON_SOCKET
@end example

Aby sme predišli varovným správam a uistili sa, že @code{guix} používa
správne miestne jazykové nastavenie, musíme ho nastaviť na používanie údajov
poskytovaných Guixom (@pxref{Application Setup,,, guix, GNU Guix Reference
Manual}):

@example
GUIX_LOCPATH=/var/guix/profiles/per-user/root/guix-profile/lib/locale
export GUIX_LOCPATH

# Tu musíme použiť platný názov miestneho jazykového nastavenia.
# Dostupné nastavenia môžete zobraziť pomocou „ls $GUIX_LOCPATH/*“.
LC_ALL=sk_SK.utf8
export LC_ALL
@end example

For convenience, @code{guix package} automatically generates
@file{~/.guix-profile/etc/profile}, which defines all the environment
variables necessary to use the packages---@code{PATH},
@code{C_INCLUDE_PATH}, @code{PYTHONPATH}, etc.  Likewise, @command{guix
pull} does that under @file{~/.config/guix/current}.  Thus it's a good idea
to source both from @code{/etc/profile}:

@example
for GUIX_PROFILE in "$HOME/.config/guix/current" "$HOME/.guix-profile"
do
  if [ -f "$GUIX_PROFILE/etc/profile" ]; then
    . "$GUIX_PROFILE/etc/profile"
  fi
done
@end example

Konečne, Guix poskytuje dopĺňanie príkazov hlavne pre Bash a zsh.  Zvážte
pridanie nasledovného riadka do @code{/etc/bashrc}:

@verbatim
. /var/guix/profiles/per-user/root/current-guix/etc/bash_completion.d/guix
@end verbatim

A je to!

Prihláste sa na jeden z výpočtových uzlov a overte či všetko pracuje správne
spustením:

@example
guix install hello
@end example

Démon na hlavnom uzle by mal vašim menom stiahnuť pred-zostavené binárne
súbory a rozbaliť ich v @file{/gnu/store}. @command{guix install} by mal
vytvoriť @file{~/.guix-profile} obsahujúci príkaz
@file{~/.guix-profile/bin/hello}.

@node Prístup do siete zhluku
@section Prístup do siete

Guix vyžaduje prístup do siete pre sťahovanie zdrojových kódov a
pred-zostavených binárnych súborov.  Dobrá správa je, že táto podmienka
platí len pre hlavný uzol, keďže koná aj v mene výpočtových uzlov.

Uzly v zhluku počítačov majú obvykle prístup len k hostiteľom zaradeným na
@emph{bielej listine}.  Pre náš hlavný uzol je dôležité na túto bielu
listinu zaradiť aspoň @code{ci.guix.gnu.org}, odkiaľ predvolene získava
pred-zostavené náhrady pre všetky balíky prítomné v samotnom Guixe.

@code{ci.guix.gnu.org} naschvál slúži aj ako @emph{zrkadlo s asociatívnym
prístupom} pre získavanie zdrojových kódov balíkov.  Preto stačí na bielu
listinu pridať @emph{len} @code{ci.guix.gnu.org}.

Balíky spravované vrámci iných repozitárov, napr. v rozličných
@uref{https://hpc.guix.info/channels, HPC kanáloch}, samozrejme nie sú na
@code{ci.guix.gnu.org} dostupné.  Pre zahrnutie týchto balíkov môžete bielu
listinu rozšíriť tak, aby bolo možné sťahovať príslušné zdrojové kódy a
pred-zostavené binárne súbory (predpokladajúc, že tieto servery tretej
strany pred-zostavené binárne súbory pre dotknuté balíky poskytujú).  Ako
poslednú možnosť si používatelia môžu zdrojový kód stiahnuť na svojom
počítači a potom ho takto pridať do @file{/gnu/store} na zhluku počítačov:

@verbatim
GUIX_DAEMON_SOCKET=ssh://vypoctovy-uzol.priklad.sk \
  guix download http://starpu.gforge.inria.fr/files/starpu-1.2.3/starpu-1.2.3.tar.gz
@end verbatim

Horeuvedený príkaz stiahne @code{starpu-1.2.3.tar.gz} @emph{a} cez SSH ho
odošle démonovi @code{guix-daemon} na zhluku počítačov.

Zhluky počítačov odpojené od vonkajšej siete vyžadujú väčšie úsilie.  V
tejto chvíli vám odporúčame stiahnuť všetok potrebný zdrojový kód na
pracovnej stanici s Guixom.  V nižšie uvedenom príklade uvádzame ako sa dá
stiahnuť všetok zdrojový kód, na ktorom závisí balík @code{openmpi} pomocou
voľby @option{--sources} príkazu @command{guix build} (@pxref{Invoking guix
build,,, guix, GNU Guix Reference Manual}):

@example
$ guix build --sources=transitive openmpi

@dots{}

/gnu/store/xc17sm60fb8nxadc4qy0c7rqph499z8s-openmpi-1.10.7.tar.bz2
/gnu/store/s67jx92lpipy2nfj5cz818xv430n4b7w-gcc-5.4.0.tar.xz
/gnu/store/npw9qh8a46lrxiwh9xwk0wpi3jlzmjnh-gmp-6.0.0a.tar.xz
/gnu/store/hcz0f4wkdbsvsdky3c0vdvcawhdkyldb-mpfr-3.1.5.tar.xz
/gnu/store/y9akh452n3p4w2v631nj0injx7y0d68x-mpc-1.0.3.tar.gz
/gnu/store/6g5c35q8avfnzs3v14dzl54cmrvddjm2-glibc-2.25.tar.xz
/gnu/store/p9k48dk3dvvk7gads7fk30xc2pxsd66z-hwloc-1.11.8.tar.bz2
/gnu/store/cry9lqidwfrfmgl0x389cs3syr15p13q-gcc-5.4.0.tar.xz
/gnu/store/7ak0v3rzpqm2c5q1mp3v7cj0rxz0qakf-libfabric-1.4.1.tar.bz2
/gnu/store/vh8syjrsilnbfcf582qhmvpg1v3rampf-rdma-core-14.tar.gz
…
@end example

(Pre lepšiu predstavu, jedná sa o približne 320@ MiB @emph{stlačeného}
zdrojového kódu.)

Všetko to potom môžme zbaliť do jedného veľkého stlačeného súboru
(@pxref{Invoking guix archive,,, guix, GNU Guix Reference Manual}):

@verbatim
$ guix archive --export \
    `guix build --sources=transitive openmpi` \
    > openmpi-zdrojovy-kod.nar
@end verbatim

@dots{} presunúť na zhluk počítačov na vymeniteľnom zariadení a rozbaliť:

@verbatim
$ guix archive --import < openmpi-zdrojovy-kod.nar
@end verbatim

Tento postup je potrebné zopakovať zakaždým, keď potrebujeme na zhluk
počítačov preniesť ďalší zdrojový kód.

V čase keď bolo toto napísané, nemali vedecké zariadenia zapojené do
Guix-HPC zhluky počítačov neprístupné z vonkajšej siete. Ak s takýmto
nastavením máte skúsenosti, radi by sme si vypočuli vašu spätnú väzbu a
návrhy.

@node Využitie diskového priestoru zhluku
@section Využitie úložného priestoru

@cindex využitie úložného priestoru, na zhluku počítačov
Spoločnou otázkou systémových správcov je, či to všetko zožerie veľa
úložného priestoru.  Ak má niečo vyčerpať miesto na disku, tak to budú skôr
vedecké údaje ako zostavené programové vybavenie---to je naša viac ako
desaťročná skúsenosť s používaním Guixu na vysokovýkonných zhlukoch
počítačov.  Avšak, stojí za to pozrieť sa na to, ako Guix vplýva na využitie
úložného priestoru.

V prvom rade, uchovávanie viacerých verzií daného balíka v @file{/gnu/store}
nutne nestojí veľa, pretože @command{guix-daemon} si dokáže účinne poradiť s
ukladaním podvojných súborov a spomínané verzie balíkov pravdepodobne
zdieľajú veľké množstvo rovnakých súborov.

Ako sme už spomínali, odporúčame nastaviť si cron úlohu, ktorá by pravidelne
spúšťala @code{guix gc}, čo odstráni @emph{nepotrebné} programové vybavenie
z @file{/gnu/store}. Avšak, používatelia si aj tak môžu vo svojich profiloch
uchovávať veľké množstvo programov a predošlých pokolení profilov, ktoré sa
z pohľadu @command{guix gc} nedajú odstrániť.

Riešením pre používateľov je pravidelne odstraňovať staré pokolenia
profilov. Napríklad, nasledovný príkaz odstráni pokolenia, ktoré sú staršie
ako dva mesiace:

@example
guix package --delete-generations=2m
@end example

Podobne je dobré nabádať používateľov, aby si pravidelne aktualizovali
profil, čo zníži počet verzií daných balíkov uložených v @file{/gnu/store}:

@example
guix pull
guix upgrade
@end example

V krajnom prípade môžu systémoví správcovia niektoré z týchto úkonov vykonať
aj v mene používateľov. Napriek tomu, jednou z myšlienok Guixu je slobodné
zaobchádzanie a úplný dohľad nad prostrediami s programovým vybavením, takže
dôrazne odporúčame nechať používateľom voľnú ruku.

@node Úvahy o zabezpečení zhluku
@section Úvahy o zabezpečení

@cindex bezpečnosť, na zhluku počítačov
Vrámci vysokovýkonného zhluku počítačov sa Guix obvykle využíva na správu
vedecky zameraného programového vybavenia.  Pre bezpečnosť nevyhnutné
vybavenie ako je jadro operačného systému a služby ako @code{sshd} a
plánovač dávkových úloh zostávajú pod dohľadom systémových správcov.

Projekt Guix má dobré výsledky v oblasti včasného poskytovania aktualizácií
zabezpečenia (@pxref{Security Updates,,, guix, GNU Guix Reference Manual}).
Aktualizácie sa získavajú vykonaním @code{guix pull && guix upgrade}.

Vďaka tomu, že Guix osobitne označuje rozličné verzie programov, je
jednoduché zistiť, či sa používa nejaký zraniteľný program. Napríklad,
pomocou nasledovného príkazu môžeme zistiť, či niektorý z používateľských
profilov odkazuje na glibc@ 2.25 bez zaplátanej zraniteľnosti
„@uref{https://www.qualys.com/2017/06/19/stack-clash/stack-clash.txt,Stack
Clash}“:

@example
guix gc --referrers /gnu/store/…-glibc-2.25
@end example

Takto sa dozvieme, či jestvujú profily, ktoré odkazujú na presne túto verziu
glibc.

@c *********************************************************************
@node Správa systému Guix
@chapter Správa systému Guix
@cindex system management
@cindex sysadmin

Since Guix does not handle packaging, system configuration and services the
way other (more ``classical'') distributions do, some workflows tend to
unfold slightly different as we are used to and need slight adjustment.
This chapter intends to help with such manners.

@menu
* Aktualizovať Postgres pre Cuirass::  Upgrading from the default postgres.
@end menu

@node Aktualizovať Postgres pre Cuirass
@section Aktualizovať Postgres pre Cuirass

With the deprecation of the default value for the postgres package in
postgresql-configuration (see b93434e656eba4260df82158a96c295000d3ff44),
system upgrades need some manual action before they can take place.  Here's
a handy guide on how to.

Please note that this is a straight-forward way for smaller datasets.  For
larger databases
@url{https://www.postgresql.org/docs/current/pgupgrade.html,
@code{pg_upgrade}} may be the better choice.  Handling the service and
system upgrade as described in this guide still applies, though.

@enumerate
@item
Stop and disable cuirass.

Prevent the service from starting and failing after a reconfiguration:

    @code{sudo herd stop cuirass && sudo herd disable cuirass}

@item
Dump the database contents.

    @code{sudo su - postgres -s /bin/sh -c pg_dumpall > /tmp/pg.dump}

@item
Add or alter the postgres service.

Depending on whether your postgres service is defined implicitly (through
the dependency from the cuirass service) or its own entry in your operating
system's @code{(services)} property, you need to either add or alter the
already existing configuration to reflect your intended version upgrade.

Be careful not to upgrade directly to postgres-16 -- cuirass service for
some reason doesn't like that.  I had to find and purge the relevant files
and then re-initialize after a failed upgrade to postgres 16.

@lisp
(service postgresql-service-type
         (postgresql-configuration
          (postgresql (@@ (gnu packages databases) postgresql-15))))
@end lisp

Note: If you for some reason didn't read the text here but somewhat blindly
followed the examples and @emph{did upgrade to 16}, here's how you reset the
state:

@enumerate
@item
Delete the database instance files.

They default to live under @file{/var/lib/postgres/data}.

@item
Re-initialize postgres.

@code{sudo su - postgres -s /bin/sh -c 'pg_ctl init -D /var/lib/postgres/data'}
@end enumerate

@item
Reconfigure your system.

@code{sudo guix system reconfigure path/to/your/altered/config.scm}

@item
Restore database contents.

@code{sudo su - postgres -s /bin/sh -c 'psql -d postgres -f /tmp/pg.dump'}

@item
Enable and start the service.

@example
sudo herd enable cuirass
sudo herd start cuirass
@end example

@end enumerate


@c *********************************************************************
@node Poďakovanie
@chapter Poďakovanie

Guix je založený na @uref{https://nixos.org/nix/, správcovi balíkov Nix},
ktorý navrhol a vytvoril Eelco Dolstra v spolupráci s ďalšími ľudmi (viď
súbor @file{nix/AUTHORS} v Guixe).  Nix je pionierom vo funkcionálnej správe
balíkov a predstavil nebývalé možnosti akými sú nedeliteľne vykonávané
aktualizácie a návraty do pôvodného stavu, profily pre každého používateľa
zvlášť, jasné a pochopiteľné zostavovacie postupy.  Bez tejto práce by Guix
nevznikol.

Guix čerpá aj z na Nixe založených riešení, Nixpkgs a NixOS.

Samotný GNU@tie{}Guix je spoločným úsilím, ku ktorému prispieva množstvo
ľudí.  Viď súbor @file{AUTHORS} v Guixe pre viac podrobností o týchto
skvelých ľuďoch.  Súbor @file{THANKS} obsahuje zoznam ľudí, ktorí pomohli
nahlásením chýb, obstaraním technického vybavenia, vytvorením výtvarných
prvkov a motívov, zaslaním návrhov, atď. Ďakujeme!

Tento receptár zahŕňa časti prevzaté z článkov zverejnených vrámci blogu
Guix na @uref{https://guix.gnu.org/blog} a blogu Guix-HPC na
@uref{https://hpc.guix.info/blog}.


@c *********************************************************************
@node Licencia GNU Free Documentation
@appendix Licencia GNU Free Documentation
@cindex licencia, GNU Free Documentation License
@include fdl-1.3.texi

@c *********************************************************************
@node Zoznam pojmov
@unnumbered Zoznam pojmov
@printindex cp

@bye

@c Local Variables:
@c ispell-local-dictionary: "american";
@c End:
