This is guix-cookbook.es.info, produced by makeinfo version 6.8 from
guix-cookbook.es.texi.

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

   Se garantiza el permiso de copia, distribución y/o modificación de
este documento bajo los términos de la licencia de documentación libre
de GNU (GNU Free Documentation License), versión 1.3 o cualquier versión
posterior publicada por la Free Software Foundation; sin secciones
invariantes, sin textos de cubierta delantera ni trasera. Una copia de
la licencia está incluida en la sección titulada “GNU Free Documentation
License”.
INFO-DIR-SECTION Administración del sistema
START-INFO-DIR-ENTRY
* Libro de recetas de Guix: (guix-cookbook.es).  Tutoriales y ejemplos para
                                                   GNU Guix.
END-INFO-DIR-ENTRY


File: guix-cookbook.es.info,  Node: Top,  Next: Tutoriales de Scheme,  Up: (dir)

Libro de recetas de GNU Guix
****************************

Este documento presenta tutoriales y ejemplos detallados para GNU Guix,
una herramienta funcional de paquetes para el sistema GNU. Por favor
*note (guix.es)Top:: para detalles acerca del sistema, su API, y
conceptos relacionados.

   Este manual también está disponible en inglés (*note
(guix-cookbook)Top::), chino simplificado (*note
(guix-cookbook.zh_CN)Top::), francés (*note (guix-cookbook.fr)Top::),
alemán (*note (guix-cookbook.de)Top::), coreano (*note
(guix-cookbook.ko)Top::), italiano (*note (guix-cookbook.it)Top::),
portugués brasileño (*note (guix-cookbook.pt_BR)Top::), ruso (*note
(guix-cookbook.ru)Top::), eslovaco (*note (guix-cookbook.sk)Top::),
sueco (*note (guix-cookbook.sv)Top::) y tamil (*note
(guix-cookbook.ta)Top::). Si estás dispuesto a traducir este documento a
tu lengua materna, considera unirte a Weblate
(https://translate.codeberg.org/projects/guix/documentation-cookbook)
(*note (guix.es)Traduciendo Guix::).

* Menu:

* Tutoriales de Scheme::     ¡Conoce a tu nuevo lenguaje favorito!
* Empaquetado::              Tutoriales de empaquetado
* Configuración del sistema::  Personalizar el sistema GNU
* Contenedores::             Entornos aislados y sistemas anidados
* Máquinas virtuales::       Uso y configuración de máquinas virtuales
* Gestión avanzada de paquetes::  ¡Poder para los usuarios!
* Desarrollo de software::   Entornos, integración continua, etc.
* Gestión del entorno::      Control del entorno
* Reproducible Research::    A foundation for reproducible research.
* Instalación de Guix en un clúster::  Computación de alto rendimiento.
* Gestión del sistema Guix::  Especificidades de la gestión del sistema.

* Agradecimientos::          ¡Gracias!
* Licencia de documentación libre GNU::  La licencia de este documento.
* Índice de conceptos::      Conceptos.

 — La lista detallada de nodos —



Tutoriales de Scheme



* Curso acelerado de Scheme::  Curso acelerado de Scheme

Empaquetado



* Tutorial de empaquetado::  Un tutorial sobre cómo añadir paquetes a Guix.
* Packaging Workflows::      Real life examples on working with specific
                               build systems.

Tutorial de empaquetado



* Un paquete ``Hola Mundo''::  Un paquete “Hola Mundo”
* Ajuste::                   Ajuste
* Ejemplo ampliado::         Ejemplo ampliado
* Otros sistemas de construcción::  Otros sistemas de construcción
* Definición de paquetes programable y automatizada::  Definición de
                                                         paquetes programable
                                                         y automatizada
* Obtener ayuda::            Obtener ayuda
* Conclusión::               Conclusión
* Referencias::              Referencias

Ajuste



* Archivo local::            Archivo local
* Canales::                  Canales
* Jaqueo directo de revisión de código::  Jaqueo directo de revisión de
                                            código

Definición de paquetes programable y automatizada



* Importadores recursivos::  Importadores recursivos
* Actualizaciones automáticas::  Actualizaciones automáticas
* Herencia::                 Herencia

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

Configuración del sistema



* Inicio de sesión automático en un TTY específico::  Iniciar
                                                        automáticamente la
                                                        sesión de un usuario
                                                        en un TTY específico
* Personalización del kernel::  Creación y uso de un núcleo Linux
                                  personalizado en el sistema Guix.
* API de imagen del sistema Guix::  Personalización de imágenes para
                                      dirigirlas a plataformas específicas.
* Utilización de claves de seguridad::  Cómo utilizar claves de seguridad
                                          con Guix System.
* Tarea mcron de DNS dinámico::  Tarea para actualizar la dirección IP
                                   detrás de un nombre de anfitrión DuckDNS.
* Conexión a Wireguard VPN::  Conexión a una VPN Wireguard.
* Personalizar un gestor de ventanas::  Manejar la personalización de un
                                          gestor de ventanas en el sistema
                                          Guix.
* Ejecución de Guix en un servidor Linode::  Ejecución de Guix en un
                                               servidor Linode.
* Ejecución de Guix en un servidor Kimsufi::  Ejecución de Guix en un
                                                servidor Kimsufi.
* Instalar un montaje enlazado::  Instalar un ‘bind mount’ dentro de
                                    definición de sistemas de archivos.
* Obtener sustituciones desde Tor::  Configurar el daemon Guix para obtener
                                       sustituciones desde Tor.
* Instalar NGINX con Lua::   Configurar servidor de web NGINX para cargar
                               módulos Lua.
* Servidor de música con sonido Bluetooth::  Reproductor de música sin
                                               cabeceras con salida Bluetooth.

Personalizar un gestor de ventanas



* StumpWM::                  StumpWM
* Bloqueo de sesión::        Bloqueo de sesión

Bloqueo de sesión



* Xorg::                     Xorg

Contenedores



* Contenedores Guix::        Entornos perfectamente aislados
* Contenedores de Sistema Guix::  Un sistema interno a su sistema

Contenedores de Sistema Guix



* Un contenedor de base de datos::  Un contenedor de base de datos
* Red de Contenedor::        Red de Contenedor

Máquinas virtuales



* Puente de red para QEMU::  Puente de red para QEMU
* Red enrutada para libvirt::  Red enrutada para libvirt
* Red basada en NAT personal para libvirt::  Red basada en NAT personal para
                                               libvirt
* Referencias: Referencias de MV.  Más lecturas sobre máquinas virtuales.

Gestión avanzada de paquetes



* Perfiles Guix en práctica::  Estrategias para múltiples perfiles y
                                 declaraciones.

Perfiles Guix en práctica



* Configuración base con declaraciones::  Configuración base con
                                            declaraciones
* Paquetes requeridos::      Paquetes requeridos
* Perfil por defecto::       Perfil por defecto
* Los beneficios de declaraciones::  Los beneficios de declaraciones
* Perfiles reproducibles::   Perfiles reproducibles

Desarrollo de software



* Empezando::                Paso 0: utilizar ‘guix shell’.
* Compilar con Guix::        Paso 1: compilar su código.
* El repositorio como un canal::  Paso 2: ajustar el repo en un canal.
* Variantes de paquetes::    Bono: definir variantes.
* Configurar Integración Continua::  Paso 3: integración continua.
* Compilar manifiesto::      Bono: Manifiesto.
* Cobertura::                Resumen.

Gestión del entorno



* Entorno Guix por direnv::  Configurar entorno Guix con 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.

Instalación de Guix en un clúster



* Configurar un nodo de cabecera::  El nodo que ejecuta el daemon.
* Configurar nodos de cálculo::  Nodos cliente.
* Acceso a red de racimo::   Tratando con restricciones de acceso a red.
* Empleo del disco en racimo::  Consideraciones de uso del disco.
* Consideraciones de seguridad del racimo::  Conservar el racimo seguro.

Gestión del sistema Guix



* Modernizar Postgres para Cuirass::  Modernizar desde el postgres
                                        predeterminado.



File: guix-cookbook.es.info,  Node: Tutoriales de Scheme,  Next: Empaquetado,  Prev: Top,  Up: Top

1 Tutoriales de Scheme
**********************

GNU Guix está escrito en el lenguaje de programación de propósito
general Scheme, y muchas de sus características pueden ser accedidas y
manipuladas mediante programación. Puede utilizar Scheme para generar
definiciones de paquetes, para modificarlos, para construirlos, para
desplegar sistemas operativos completos, etc.

   Saber lo básico de cómo programar en Scheme desbloqueará muchas de
las características avanzadas que Guix proporciona — ¡y ni siquiera
necesita ser un programador experimentado para usarlas!

   ¡Empecemos!

* Menu:

* Curso acelerado de Scheme::  Curso acelerado de Scheme


File: guix-cookbook.es.info,  Node: Curso acelerado de Scheme,  Up: Tutoriales de Scheme

1.1 Curso acelerado de Scheme
=============================

Guix utiliza la implementación Guile de Scheme. Para empezar a jugar con
el lenguaje, instálelo con ‘guix install guile’ e inicie un
“REPL”—abreviatura de “read-eval-print loop”
(https://en.wikipedia.org/wiki/Read%E2%80%93eval%E2%80%93print_loop)—ejecutando
‘guile’ desde la línea de comandos.

   También puede ejecutar ‘guix shell guile -- guile’ si prefiere no
tener Guile instalado en su perfil de usuario.

   En los siguientes ejemplos, las líneas muestran lo que usted
escribiría en la REPL; las líneas que comienzan con “⇒” muestran los
resultados de la evaluación, mientras que las líneas que comienzan con
“⊣” muestran las cosas que se mostren. Para más detalles sobre la REPL,
*Note (guile)Using Guile Interactively::.

   • La sintaxis de Scheme se reduce a un árbol de expresiones (o
     _s-expression_ en la jerga de Lisp). Una expresión puede ser un
     literal como números y cadenas, o un compuesto que es una lista
     entre paréntesis de compuestos y literales. ‘#true’ y ‘#false’
     (abreviados ‘#t’ y ‘#f’) representan los booleanos “true” y
     “false”, respectivamente.

     Ejemplos de expresiones válidas:

          "¡Hola Mundo!"
          ⇒ "¡Hola Mundo!"

          17
          ⇒ 17

          (display (string-append "Hola " "Guix" "\n"))
          ⊣ Hola Guix
          ⇒ #<unspecified>

   • Este último ejemplo es una llamada a una función anidada en otra
     llamada a una función. Cuando se evalúa una expresión entre
     paréntesis, el primer término es la función y el resto son los
     argumentos pasados a la función. Cada función devuelve la última
     expresión evaluada como valor de retorno.

   • Las funciones anónimas—“procedimientos” en habla de Scheme— es
     declarado con el término ‘lambda’:

          (lambda (x) (* x x))
          ⇒ #<procedure 120e348 at <unknown port>:24:0 (x)>

     El procedimiento anterior devuelve el cuadrado de su argumento.
     Como todo es una expresión, la expresión ‘lambda’ devuelve un
     procedimiento anónimo, que a su vez puede aplicarse a un argumento:

          ((lambda (x) (* x x)) 3)
          ⇒ 9

     Procedimientos son valores usuales tan solo como números, cadenas,
     booleanos, y así todo.

   • Se puede asignar un nombre global a cualquier cosa con ‘define’:

          (define a 3)
          (define square (lambda (x) (* x x)))
          (square a)
          ⇒ 9

   • Los procedimientos pueden definirse de forma más concisa con la
     siguiente sintaxis:

          (define (square x) (* x x))

   • Se puede crear una estructura de lista con el procedimiento ‘list’:

          (list 2 a 5 7)
          ⇒ (2 3 5 7)

   • Se proporcionan procedimientos estándar por medio del módulo ‘(srfi
     srfi-1)’ para crear y procesar listados (*note proceso de listado:
     (guile)SRFI-1.). Aquí están algunos de los más útiles en acción:

          (use-modules (srfi srfi-1))  ;importa listado procesando procedimientos

          (append (list 1 2) (list 3 4))
          ⇒ (1 2 3 4)

          (map (lambda (x) (* x x)) (list 1 2 3 4))
          ⇒ (1 4 9 16)

          (delete 3 (list 1 2 3 4))        ⇒ (1 2 4)
          (filter odd? (list 1 2 3 4))     ⇒ (1 3)
          (remove even? (list 1 2 3 4))    ⇒ (1 3)
          (find number? (list "a" 42 "b")) ⇒ 42

     Notifique como el primer argumento a ‘map’, ‘filter’, ‘remove’, y
     ‘find’ es un procedimiento.

   • La comilla “quote” desactiva la evaluación de una expresión entre
     paréntesis: también invocado como expresión-S o “s-exp”
     (S-expression) en inglés: el primer término ahora es invocado sobre
     el otro términos (*note quote: (guile)Expression Syntax.). Por
     tanto efectivamente devuelve una lista de términos.

          '(display (string-append "Hola " "Guix" "\n"))
          ⇒ (display (string-append "Hola " "Guix" "\n"))

          '(2 a 5 7)
          ⇒ (2 a 5 7)

   • El ‘quasiquote’ (‘`’, una comilla hacia atrás) desactiva evaluación
     de una expresión entre paréntesis hasta retirar la comilla con
     ‘unquote’ (una coma ‘,’) la vuelve a activar. Por lo tanto, nos
     proporciona un control fino sobre lo que se evalúa y lo que no.

          `(2 a 5 7 (2 ,a 5 ,(+ a 4)))
          ⇒ (2 a 5 7 (2 3 5 7))

     Nótese que el resultado anterior es una lista de elementos mixtos:
     números, símbolos (aquí ‘a’) y el último elemento es una lista
     propiamente dicha.

   • Guix define una variante de expresiones-S sobre esteroides
     llamdados “expresiones-G” o “gexps”, la cual viene con una variante
     de ‘quasiquote’ y ‘unquote’: ‘#~’ (o ‘gexp’) y ‘#$’ (o ‘ungexp’).
     Le permite _representar código para ejecución posterior_.

     Por ejemplo, encontrará gexps en algunas definiciones de paquete
     donde proporcionen código a ser ejecutado durante el proceso de
     construcción del paquete. Parecido esto:

          (use-modules (guix gexp)           ;por tanto pudemos escribir gexps
                       (gnu packages base))  ;para 'coreutils'

          ;; Debajo es una expresión-G representando código escenificado.
          #~(begin
              ;; Invoca 'ls' desde el paquete definido por la variable
              ;;  'coreutils'.
              (system* #$(file-append coreutils "/bin/ls") "-l")

              ;; Crea esta directorio salida del paquete.
              (mkdir #$output))

     *Note (guix.es)Expresiones-G::, para más en gexps.

   • Pueden ser nombradas múltiples variables localmente con ‘let’
     (*note (guile)Local Bindings::):

          (define x 10)
          (let ((x 2)
                (y 3))
            (list x y))
          ⇒ (2 3)

          x
          ⇒ 10

          y
          error→ En el procedimiento module-lookup: Variable no vinculada: y

     Utilice ‘let*’ para permitir que las declaraciones de variables
     posteriores hagan referencia a definiciones anteriores.

          (let* ((x 2)
                 (y (* x 3)))
            (list x y))
          ⇒ (2 6)

   • “Palabras clave” son utilizados típicamente para identificar los
     parámetros nombrados de un procedimiento. Están prefijados por ‘#:’
     (hash, dos puntos) seguidos por caracteres alfanuméricos:
     ‘#:como-este’. *Note (guile)Keywords::.

   • El porcentaje ‘%’ es utilizado típicamente para variables locales
     de solo lectura en es estado de construcción. Note que es meramente
     una convención, como ‘_’ en C. Scheme trata ‘%’ exactamente lo
     mismo que cualquier otra letra.

   • Los módulos son creados con ‘define-module’ (*note (guile)Creating
     Guile Modules::). Por ejemplo

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

     define el módulo ‘guix build-system ruby’ el cual debe estar
     localizado en ‘guix/build-system/ruby.scm’ donde sea en la ruta de
     carga Guile. Depende en el módulo ‘(guix store)’ y exporta dos
     variables, ‘ruby-build’ y ‘ruby-build-system’.

     *Note (guix.es)Módulos de paquetes::, para info en módulos que
     define paquetes.

     Más allá: Scheme es un lenguaje que ha sido ampliamente utilizado
     para enseñar a programar y lo encontraría plenamente en material
     utilizándolo como un vehículo. Aquí está una selección de
     documentos para aprender más sobre Scheme:

        • A Scheme Primer
          (https://spritely.institute/static/papers/scheme-primer.html),
          por Christine Lemmer-Webber y el Instituto Spritely.

        • Structure and Interpretation of Computer Programs
          (https://sarabander.github.io/sicp/), por Harold Abelson y
          Gerald Jay Sussman, con Julie Sussman. Coloquialmente conocido
          como “SICP”, este libro es una referencia.

          Además puede instalarlo desde su equipo:

               guix install book-sicp info-reader
               info sicp

     Encontrará más libros, tutoriales y otros recursos en
     <https://schemers.org/>.


File: guix-cookbook.es.info,  Node: Empaquetado,  Next: Configuración del sistema,  Prev: Tutoriales de Scheme,  Up: Top

2 Empaquetado
*************

Este capítulo está dedicado para enseñanza de como añadir paquetes a la
colección de paquetes que viene con GNU Guix. Esto involucra escrbir
definiciones de paquete en Guile Scheme, organizándolos en módulos de
paquete, y construyéndolos.

* Menu:

* Tutorial de empaquetado::  Un tutorial sobre cómo añadir paquetes a Guix.
* Packaging Workflows::      Real life examples on working with specific
                               build systems.


File: guix-cookbook.es.info,  Node: Tutorial de empaquetado,  Next: Packaging Workflows,  Up: Empaquetado

2.1 Tutorial de empaquetado
===========================

GNU Guix destaca como el gestor de paquetes _hakeable_, principalmente
porque utiliza GNU Guile (https://www.gnu.org/software/guile/), un
potente lenguaje de programación de alto nivel, uno de los dialectos
Scheme (https://en.wikipedia.org/wiki/Scheme_%28programming_language%29)
de la familia Lisp
(https://en.wikipedia.org/wiki/Lisp_%28programming_language%29).

   Las definiciones de paquetes también se escriben en Scheme, lo cual
dota a Guix de algunas capacidades muy únicas, a diferencia de otros
gestores de empaquetado que utilizan guiones de intérpretes o lenguajes
sencillos.

   • Utilice funciones, estructuras, macros y toda la expresividad de
     Scheme para sus definiciones de paquetes.

   • La herencia facilita la personalización de un paquete heredando de
     él y modificando sólo lo que es necesario.

   • Procesamiento por lotes: se puede interpretar, filtrar y procesar
     toda la colección de paquetes. ¿Construir un servidor sin cabeza
     con todos los interfaces gráficos recortados? Es posible. ¿Quieres
     recompilar todo desde el código fuente utilizando indicadores de
     optimización específicos del compilador? Pase el argumento
     ‘#:make-flags "..."’ a la lista de paquetes. No sería exagerado
     pensar Gentoo USE indicadores
     (https://wiki.gentoo.org/wiki/USE_flag) aquí, pero esto va más
     allá: los cambios no tienen que ser pensados de antemano por el
     empaquetador, ¡pueden ser _programados_ por el usuario!

   El siguiente tutorial cubre todo lo básico sobre la creación de
paquetes con Guix. No asume mucho conocimiento del sistema Guix ni del
lenguaje Lisp. Sólo se espera que el lector esté familiarizado con la
línea de comandos y que tenga algunos conocimientos básicos de
programación.

* Menu:

* Un paquete ``Hola Mundo''::  Un paquete “Hola Mundo”
* Ajuste::                   Ajuste
* Ejemplo ampliado::         Ejemplo ampliado
* Otros sistemas de construcción::  Otros sistemas de construcción
* Definición de paquetes programable y automatizada::  Definición de
                                                         paquetes programable
                                                         y automatizada
* Obtener ayuda::            Obtener ayuda
* Conclusión::               Conclusión
* Referencias::              Referencias


File: guix-cookbook.es.info,  Node: Un paquete ``Hola Mundo'',  Next: Ajuste,  Up: Tutorial de empaquetado

2.1.1 Un paquete “Hola Mundo”
-----------------------------

La sección “Definición de paquetes” del manual introduce los fundamentos
del empaquetado Guix (*note (guix.es)Definición de paquetes::). En la
siguiente sección, repasaremos parcialmente esos fundamentos de nuevo.

   GNU Hello es un proyecto ficticio que sirve como ejemplo idiomático
de empaquetado. Utiliza el sistema de construcción de GNU (‘./configure
&& make && make install’). Guix ya proporciona una definición de paquete
que es un ejemplo perfecto para empezar. Puedes buscar su declaración
con ‘guix edit hello’ desde la línea de comandos. Veamos cómo queda:

     (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 "Hola, mundo GNU: Un ejemplo de paquete GNU")
         (description
          "GNU Hello imprime el mensaje \"Hello, world!\" y después sale.
     Sirve como un ejemplo de prácticas de codificación GNU estándar.  Por tanto, admite
     argumentos de línea comando, múltiples lenguajes, y más.")
         (home-page "https://www.gnu.org/software/hello/")
         (license gpl3+)))

   Como puede ver, muchos de estos es bastante sencillo. Pero
revisaremos los campos juntos:

‘name’
     El nombre del proyecto. Utilizando convenciones de Scheme,
     preferimos conservarlo en minúsculas, son puntuación y utilizando
     palabras con guion separado.

‘source’
     Este campo contiene una descripción del origen del código fuente.
     El registro ‘origin’ contiene estos campos:

       1. El método, aquí ‘url-fetch’ para descargar vía HTTP/FTP, pero
          otros métodos existen, tal como ‘git-fetch’ para repositorios
          Git.
       2. La URL, la cual es típicamente algún lugar ‘https://’ para
          ‘url-fetch’. Aquí el especial ‘mirror://gnu‘ refiere a un
          conjunto de lugares bien conocidos, todo los cuales puden ser
          utilzados por Guix para obtener la fuente, fallarían algunos
          de ellos.
       3. El checksum ‘sha256’ del archivo solicitado. Esto es esencial
          para asegurar la fuente no está corrompida. Note que Guix
          funciona con cadenas de base32, por tanto la invocación para
          la función ‘base32’.

‘build-system’

     Aquí es donde el poder de abstracción proporcionado por el lenguaje
     Scheme realmente brilla: en este caso, el ‘gnu-build-system’
     abstrae las famosas invocaciones al shell ‘./configure && make &&
     make install’. Otros sistemas de construcción incluyen el
     ‘trivial-build-system’ que no hace nada y requiere que el
     empaquetador programe todos los pasos de construcción, el
     ‘python-build-system’, el ‘emacs-build-system’, y muchos más (*note
     (guix.es)Sistemas de construcción::).

‘synopsis’
     Sería un sumario conciso de que el paquete hace. Para muchos
     paquetes un etiquetado desde la página inicial del proyecto puede
     ser utilizada como la sinopsis.

‘description’
     Lo mismo que la sinopsis, es propio reutilizar la descripción del
     proyecto desde la página inicial. Note que Guix utiliza sintaxis
     Texinfo.

‘home-page’
     Utilizar HTTPS si está disponible.

‘license’
     Consulte ‘guix/licenses.scm’ en la fuente del proyecto para un
     listado completo de licencias disponibles.

   ¡Es el momento de construir nuestro primer paquete! Nada fantástico
aquí por ahora: nos quedaremos con un maniquí ‘my-hello’, una copia de
la declaración arriba.

   Como con el “hola mundo“ ritualístico enseño con muchos lenguajes de
programación, esto posiblemente será la aproximación más “manual”.
Funcionaremos con una configuración ideal más tarde; por ahora iremos a
la rutina más simple.

   Guarda lo siguiente para un archivo ‘my-hello.scm’.

     (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 "Hola, mundo Guix: Un ejemplo personalizado de paquete Guix")
       (description
        "GNU Hello imprime el mensaje \"Hello, world!\" y después sale.
     Sirve como un ejemplo de prácticas de codificación GNU estándar. Por tanto, admite
     argumentos de línea de comando, múltiples lenguajes, y así el resto.")
       (home-page "https://www.gnu.org/software/hello/")
       (license gpl3+))

   Explicaremos el código adicional en un momento.

   Siéntete libre de jugar con los diferentes valores de los distintos
campos. Si cambia el código fuente, tendrá que actualizar la suma de
comprobación. De hecho, Guix se niega a construir nada si la suma de
comprobación dada no coincide con la suma de comprobación calculada del
código fuente. Para obtener la suma de comprobación correcta de la
declaración del paquete, tenemos que descargar el código fuente,
calcular la suma de comprobación sha256 y convertirla a base32.

   Afortunadamente, Guix puede automatizar esta tarea por nosotros; todo
lo que necesitamos es proporcionar la URI:

     $ guix download mirror://gnu/hello/hello-2.10.tar.gz

     Inicio de la descarga de /tmp/guix-file.JLYgL7
     Desde https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz...
     tras la redirección a `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

   En este caso concreto, la salida nos indica qué espejo se ha elegido.
Si el resultado del comando anterior no es el mismo que en el fragmento
anterior, actualice su declaración ‘my-hello’ en consecuencia.

   Tenga en cuenta que los paquetes tar de GNU vienen con una firma
OpenPGP, por lo que debería comprobar la firma de este tar con ‘gpg‘
para autenticarlo antes de continuar:

     $ guix download mirror://gnu/hello/hello-2.10.tar.gz.sig

     Inicio de la descarga de /tmp/guix-file.03tFfb
     Desde https://ftpmirror.gnu.org/gnu/hello/hello-2.10.tar.gz.sig...
     tras la redirección a `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: Firmado el dom 16 nov 2014 13:08:37 CET
     gpg:                usando RSA clave A9553245FDE9B739
     gpg: comprobando base de datos de confianza
     gpg: no se encuentran claves absolutamente fiables
     gpg: Firma correcta de "Sami Kerola <kerolasa@iki.fi>" [desconocido]
     gpg:                 alias "Sami Kerola (http://www.iki.fi/kerolasa/) <kerolasa@iki.fi>" [desconocido]
     gpg: ATENCIÓN: ¡Esta clave no está certificada por una firma de confianza!
     gpg:          No hay indicios de que la firma pertenezca al propietario.
     Huellas dactilares de la clave primaria: 8ED3 96E3 7E38 D471 A005  30D3 A955 3245 FDE9 B739

   Entonces puede ejecutar felizmente

     $ guix package --install-from-file=my-hello.scm

   ¡Ahora tendría ‘my-hello’ en su perfil!

     $ guix package --list-installed=my-hello
     my-hello	2.10	out
     /gnu/store/f1db2mfm8syb8qvc357c53slbvf1g9m9-my-hello-2.10

   Hemos llegado tan lejos como hemos podido sin ningún conocimiento de
Scheme. Antes de pasar a paquetes más complejos, ahora es el momento
adecuado para repasar tus conocimientos de Scheme. *Note Curso acelerado
de Scheme:: para ponerte al día.


File: guix-cookbook.es.info,  Node: Ajuste,  Next: Ejemplo ampliado,  Prev: Un paquete ``Hola Mundo'',  Up: Tutorial de empaquetado

2.1.2 Ajuste
------------

En el resto de este capítulo nos basaremos en algunos conocimientos
básicos de programación en Scheme. Ahora vamos a detallar las diferentes
configuraciones posibles para trabajar con paquetes Guix.

   Hay varias maneras de configurar un entorno de empaquetando para
Guix.

   Recomendado trabajar directamente en la copia de trabajo de código
Guix desde que lo hizo más fácil para cada uno de contribuir al
proyecto.

   Pero primero, miremos en otras posibilidades.

* Menu:

* Archivo local::            Archivo local
* Canales::                  Canales
* Jaqueo directo de revisión de código::  Jaqueo directo de revisión de
                                            código


File: guix-cookbook.es.info,  Node: Archivo local,  Next: Canales,  Up: Ajuste

2.1.2.1 Archivo local
.....................

Esto es lo que hicimos anteriormente con ‘my-hello’. Con los fundamentos
de Scheme que hemos cubierto, ahora estamos en condiciones de explicar
los trozos principales. Como se indica en ‘guix package --help’:

       -f, --install-from-file=ARCHIVO
                              instala el paquete al que el código en
                              ARCHIVO evalúa

   Por tanto la última expresión _debe_ devolver un paquete, el cual es
el caso en su ejemplo anterior.

   La expresión ‘use-modules’ indica cuáles de los módulos necesitamos
en el archivo. Los módulos son una colección de valores y
procedimientos. En otros lenguajes de programación suelen denominarse
“bibliotecas” o “paquetes”.


File: guix-cookbook.es.info,  Node: Canales,  Next: Jaqueo directo de revisión de código,  Prev: Archivo local,  Up: Ajuste

2.1.2.2 Canales
...............

Guix y su colección de paquetes pueden ampliarse a través de “canales”.
Un canal es un repositorio Git, público o no, que contiene archivos
‘.scm’ que proporcionan paquetes (*note (guix.es)Definición de
paquetes::) o servicios (*note (guix.es)Definición de servicios::).

   ¿Como pudiste ir a crear un canal? Primero, cree un directorio que
contendrá su archivos ‘.scm’, dicho ‘~/mi-canal’:

     mkdir ~/mi-canal

   Suponga que quiere añadir el paquete ‘my-hello’ que vimos
previamente; primero necesita algunos ajustes:

     (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 "Hola, mundo Guix: Un ejemplo personalizado de paquete Guix")
         (description
          "GNU Hello imprime el mensaje \"Hello, world!\" y después sale.
     Sirve como un ejemplo de prácticas de codificación GNU estándar.  Por tanto, admite
     argumentos de línea comando, múltiples lenguajes, y más.")
         (home-page "https://www.gnu.org/software/hello/")
         (license gpl3+)))

   Observe que hemos asignado el valor del paquete a un nombre de
variable exportado con ‘define-public’. Esto es efectivamente asignar el
paquete a la variable ‘my-hello’ para que pueda ser referenciado, entre
otros como dependencia de otros paquetes.

   Si utiliza ‘guix package --install-from-file=my-hello.scm’ sobre el
archivo de arriba, fallará porque la última expresión, ‘define-public’,
no devuelve un paquete. Si quiere utilizar ‘define-public’ en este caso
de uso sin embargo, asegura los finales de archivo con una evaluación de
‘my-hello’:

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

     my-hello

   Este último ejemplo no es muy típico.

   ¿Ahora como haces que el paquete visible a comandos ‘guix’ por tanto
puede privar sus paquetes? Necesita añadir el directorio para la ruta de
búsqueda utilizando la opción de línea de instrucción ‘-L’, como en
estos ejemplos:

     guix show -L ~/mi-canal my-hello
     guix build -L ~/mi-canal my-hello

   El paso final es convertir ‘~/my-channel’ en un canal real, haciendo
que tu colección de paquetes esté disponible sin problemas vía cualquier
comando ‘guix’. Para ello, primero tienes que convertirlo en un
repositorio Git:

     cd ~/mi-canal
     git init
     git add my-hello.scm
     git commit -m "Primer commit de mi canal."

   ¡Eso es, tiene un canal! Desde ese activo, puede añadir este canal a
su configuración de canal en ‘~/.config/guix/channels.scm’ (*note
(guix.es)Especificación de canales adicionales::); asumiendo conserva su
canal local para ahora, el ‘channels.scm’ parecería algo como esto:

     (append (list (channel
                     (name 'mi-canal)
                     (url (string-append "file://" (getenv "HOME")
                                         "/mi-canal"))))
             %default-channels)

   La próxima vez que ejecute ‘guix pull’, su canal será recogido y los
paquetes que defina estarán disponibles para todos los comandos ‘guix’,
incluso si no pasa ‘-L’. El comando ‘guix describe’ mostrará que Guix
está, de hecho, usando tanto el canal ‘mi-canal’ como el canal ‘guix’.

   *Note (guix.es)Creación de un canal::, para más detalles.


File: guix-cookbook.es.info,  Node: Jaqueo directo de revisión de código,  Prev: Canales,  Up: Ajuste

2.1.2.3 Jaqueo directo de revisión de código
............................................

Se recomienda trabajar directamente en el proyecto Guix: reduce la
fricción cuando llega el momento de enviar los cambios a la comunidad
para que ésta se beneficie de tu duro trabajo.

   A diferencia de la mayoría de las distribuciones de software, el
repositorio Guix contiene en un solo lugar tanto las herramientas
(incluido el gestor de paquetes) como las definiciones de los paquetes.
Esta elección se hizo para dar a los desarrolladores la flexibilidad de
modificar la API sin rupturas, actualizando todos los paquetes al mismo
tiempo. Esto reduce la inercia del desarrollo.

   Revise el repositorio Git (https://git-scm.com/) oficial:

     $ git clone https://git.guix.gnu.org/guix.git

   En el resto de este artículo, utilice ‘$GUIX_CHECKOUT’ para referir
al lugar del código.

   Siga las instrucciones en el manual (*note (guix.es)Contribución::)
para configurar el entorno del repositorio.

   Una vez que esté dispuesto, sería capaz de utilizar las definiciones
del paquete desde el entorno del repositorio.

   Siéntase libre de editar definiciones de paquete encontrada en
‘$GUIX_CHECKOUT/gnu/packages’.

   El guion ‘$GUIX_CHECKOUT/pre-inst-env’ le permite utilizar ‘guix’
sobre la colección del paquete del repositorio (*note (guix.es)Ejecutar
Guix antes de instalarlo::).

   • Busque paquetes, tales como Ruby:

            $ 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

   • Construye un paquete, aquí Ruby versión 2.1:

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

   • Instalarlo a su perfil de usuario:

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

   • Comprobar equivocaciones usuales:

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

   Guix se esfuerza en mantenimiento de un empaquetado estándar alto;
cuando contribuya al proyecto Guix, recuerde que

   • siga el estilo de codificación (*note (guix.es)Estilo de
     codificación::),
   • y revise el listado de comprobación desde el manual (*note
     (guix.es)Envío de parches::).

   Una vez que sea feliz con el resultado, es bienvenido para enviar su
contribución para hacerla parte de Guix. Este proceso además está
detallado en el manual. (*note (guix.es)Contribución::)

   ¡Es un esfuerzo de la comunidad tal que más se unan, lo mejor de
vuelve Guix!


File: guix-cookbook.es.info,  Node: Ejemplo ampliado,  Next: Otros sistemas de construcción,  Prev: Ajuste,  Up: Tutorial de empaquetado

2.1.3 Ejemplo ampliado
----------------------

El ejemplo “Hola Mundo” de arriba es tan simple como va. Los paquetes
pueden ser más complejos que eso y Guix puede manipular más escenarios
avanzados. Miremos en otro paquete, más sofisticado (ligeramente
modificado desde la fuente):

     (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)))
                     ;; Remove bundled software.
                     (snippet '(delete-file-recursively "deps"))))
           (build-system cmake-build-system)
           (outputs '("out" "debug"))
           (arguments
            `(#:tests? #true                         ; Ejecutar el conjunto de pruebas (por defecto)
              #:configure-flags '("-DUSE_SHA1DC=ON") ; SHA-1 detección de colisiones
              #: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")))))
                ;; Realiza comprobaciones más verbosas.
                (replace 'check
                  (lambda* (#:key tests? #:allow-other-keys)
                    (when tests?
                      (invoke "./libgit2_clar" "-v" "-Q"))))
                (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
            ;; Estas dos bibliotecas se encuentran en 'Requires.private' en libgit2.pc.
            (list openssl zlib))
           (home-page "https://libgit2.github.com/")
           (synopsis "Biblioteca que proporciona los métodos básicos de Git")
           (description
            "Libgit2 es una implementación portable en C puro de los métodos
     centrales de Git, proporcionada como una biblioteca enlazable reentrante
     con una API sólida, que permite escribir aplicaciones Git personalizadas a
     velocidad nativa en cualquier lenguaje con bindings.")
           ;; GPLv2 with linking exception
           (license license:gpl2))))

   (En aquellos casos eran solo querían configurar unos pocos campos
desde una definición de pquete, relativamente en herencia en vez de todo
copia-pega. Consulte a continuación.)

   Discutimos esos campos en profundidad.

2.1.3.1 El método ‘git-fetch’
.............................

A diferencia del método ‘url-fetch’, ‘git-fetch’ espera un
‘git-reference’ que toma un repositorio Git y un commit. El commit puede
ser cualquier referencia Git como etiquetas, por lo que si el ‘version’
está etiquetado, entonces puede usarse directamente. A veces la etiqueta
va precedida de ‘v’, en cuyo caso se usaría ‘(commit (string-append "v"
version))’.

   Para garantizar que el código fuente del repositorio Git se almacena
en un directorio con un nombre descriptivo, utilizamos ‘(file-name
(git-file-name name version))’.

   El procedimiento ‘git-version’ puede usarse para derivar la versión
cuando se empaquetan programas para una confirmación específica,
siguiendo las directrices de los contribuidores de Guix (*note
(guix.es)Versiones numéricas::).

   ¿Cómo se obtiene el hash ‘sha256’ que está ahí, te preguntarás?
Invocando ‘guix hash’ en una revisión de la confirmación deseada, de la
siguiente manera:

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

   ‘guix hash -rx’ calcula un hash SHA256 sobre el directorio completo,
excluyendo el sub-directorio ‘.git’ (*note (guix.es)Invocación de guix
hash::).

   En el futuro, ‘guix download’ ojalá sea capaz de hacer estos pasos
por usted, tan solo lo hace para descargas usuales.

2.1.3.2 Fragmentos
..................

Los fragmentos de código Scheme están entrecomillados (es decir, no
evaluado) que tienen un sentido de parcheo de la fuente. Son una
alternativa de Guix-y para los archvios tradicionales de tipo parche
(‘.patch’). Debido a la comilla, el código solamente es evaluado cuando
pase al daemon Guix para construcción. Allí puede tener tangos
fragmentos como se necesiten.

   Los fragmentos quizá necesiten módulos Guile adicionales los cuales
pueden ser importados desde el campo ‘modules’.

2.1.3.3 Entradas
................

Hay tres tipos diferentes de entrada. Las cortas:

native-inputs
     Requerido para construir pero no en tiempo de ejecución –
     instalando un paquete por un sustituto no instalaría estas
     entradas.
inputs
     Instalado en el almacén pero no en el perfil, así como estando
     presente en tiempo de construcción.
propagated-inputs
     Instalado en el almacén y en el perfil, además de estar presente en
     el momento de la construcción.

   *Note (guix.es)Referencia de package:: para más detalles.

   La distinción entre las distintas entradas es importante: si una
dependencia puede tratarse como una _entrada_ en lugar de como una
_entrada propagada_, debe hacerse así, o de lo contrario “contaminará”
el perfil de usuario sin una buena razón.

   Por ejemplo, un usuario que instala un programa gráfico que depende
de una herramienta de línea de comandos puede que sólo esté interesado
en la parte gráfica, por lo que no hay necesidad de forzar la
herramienta de línea de comandos en el perfil de usuario. La dependencia
es una preocupación para el paquete, no para el usuario. _Inputs_
permite gestionar las dependencias sin molestar al usuario añadiendo
archivos ejecutables (o bibliotecas) no deseados a su perfil.

   Lo mismo ocurre con _native-inputs_: una vez instalado el programa,
las dependencias en tiempo de construcción pueden ser recolectadas de
forma segura. También es importante cuando un sustituto está disponible,
en cuyo caso sólo el ‘inputs’ y ‘propagated-inputs’ será recuperado: el
‘native-inputs’ no son necesarios para instalar un paquete de un
sustituto.

     Nota: Aquí puede ver y esos fragmentos de código donde entradas de
     paquetes son escritos poco diferentemente, como así:

          ;; El "estilo más antiguo" para entradas.
          (inputs
           `(("libssh2" ,libssh2)
             ("http-parser" ,http-parser)
             ("python" ,python-wrapper)))

     Éste es el “estilo antiguo”, donde cada entrada en el listado se
     proporciona explícitamente como una etiqueta (una cadena). Todavía
     está mantenido pero recomendamos utilizar en su lugar el estilo
     anterior.

2.1.3.4 Salidas
...............

Tan solo como un paquete puede tener múltiples entradas, puede producir
además múltiples salidas.

   Cada salida corresponde a un directorio separado en el almacén.

   El usuario puede elegir cual salida para instalar; esto es útil para
ahorrar espacio o para evitar repartir el perfil de usuario cuando
ejecutables o bibliotecas no son deseados.

   La separación de salida es opcional. Cuando el campo ‘salidas’ se
dejan fuera, lo predeterminado y solamente la salida (el paquete
completo) está referenciado como ‘"out"’ (salida).

   Los nombres de salida separados típicos incluyen ‘defauilt’ y ‘doc’.

   Se advierte separar las salidas solo cuando es mostrada es peor si:
el tamaño de salida es significante (compara con ‘tamaño guix’) o en
caso de cuando el paquete es modular.

2.1.3.5 Argumentos del sistema de construcción
..............................................

Los ‘arguments’ son un valor de palabra clave utilizada para configurar
el proceso de construcción.

   El argumento ‘#:test?’ más simple puede ser utilizado para
deshabilitar la suite de test cuando construya el paquete. Esto es
mayormente útil cuando el paquete no capacita ningún suite de test. Es
recomendado fuertemente conservar la suite de test si hay una.

   Otro argumento común es ‘:crear-indicadores’, el cual especifica un
listado de indicadores para adjuntar cuando ejecute make, como haría
desde la línea de comando. Por instancia, los indicadores proporcionan

     #:make-flags (list (string-append "prefix=" (assoc-ref %outputs "salida"))
                        "CC=gcc")

   traducir en

     $ make CC=gcc prefix=/gnu/store/...-<salida>

   Estos establece el compilador C para ‘gcc’ y la variable ‘prefix’ (el
directorio de instalación en el lenguaje Make) para ‘(assoc-ref %outputs
"salida")’ la cual es una variable local de lado-de-construcción
apuntando al directorio destino dentro del almacenaje (alguna cosa como
‘/gnu/store/...-my-libgit2-20180408’).

   Similarmente, es posible poner los indicadores de configuración:

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

   La variable ‘%build-inputs’ también está generada en ámbito. Es una
tabla de asociación que asocia los nombres de entrada a sus directorios
de almacenaje.

   La palabra clave ‘phases’ crea listas de pasos secuenciales del
sistema de construcción. Las fases típicamente incluyen ‘unpack’,
‘configure’, ‘build’, ‘instalar’ y ‘check’. Para saber más sobre estas
fases, necesita trabajar fuera de la definición del sistema de
construcción apropiado en
‘$GUIX_CHECKOUT/guix/build/gnu-build-system.scm’:

     (define %standard-phases
       ;; Fases de construcción estándar, como un listado de parejas símbolo/procedimiento.
       (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)))

   O desde el REPL:

     (add-to-load-path "/ruta/para/guix/comprobente")
     ,use (guix build gnu-build-system)
     (map car %standard-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)

   Si desea conocer más sobre que sucede durante esas fases, consulte
los procedimientos asociados.

   Para instanciar, como esta escribe la definición de ‘unpack’
(desempaquetar) para el sistema compilador de GNU es:

     (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")

             ;; Conserva el sello horario y fecha (pone en la Epoch) en el árbol copiado tal que
             ;; las cosas funcionen determinísticamente.
             (copy-recursively source "."
                               #:keep-mtime? #t)
             ;; Hacer que los archivos fuente sean grabables, por conveniencia.
             (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)))))
             ;; Intenta cambiar en directorio heredado.
             (and=> (first-subdirectory ".") chdir))))

   Nota la invocación ‘chdir’: modifica el directorio de trabajo para
donde la fuente fue desempaquetada. Por tanto cada fase sigue el
desempaquetado (‘unpack’) utilizará la fuente como un directorio de
trabajo, el cual es porqué podemos trabajar directamente en los archivos
de fuentes. Esto es decir, a no ser que una fase posterior cambia el
directorio de trabajo a algo más.

   Modificamos el listado de fases ‘%standard-phases’ del sistema de
construcción con la macro ‘modify-phases’ como por el listado de
modificaciones especificadas, las cuales pueden tener los formularios
siguientes:

   • ‘(add-before PHASE NEW-PHASE PROCEDURE)’: Ejecute PROCEDURE
     nombrado NEW-PHASE antes que PHASE.
   • ‘(add-after PHASE NEW-PHASE PROCEDURE)’: Lo mismo, pero
     posteriores.
   • ‘(sustituye PHASE PROCEDURE)’.
   • ‘(elimina PHASE)’.

   La PROCEDIMIENTO admite los argumentos de palabra clave ‘entradas’ y
‘salidas’. Cada directorio de entrada (ya sea _nativo_, _propagado_ o
no) y salida se referencia por su nombre en esas variables. Así
‘(assoc-ref salidas "out")’ es el directorio de almacenamiento de la
salida principal del paquete. Un procedimiento de fase puede tener este
aspecto:

     (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")))
         ;; ... ))

   Su valor de retorno se ignora.

2.1.3.6 Puesta en escena del código
...................................

El lector astuto puede haber notado la sintaxis de comillas y comas en
el campo de argumentos. De hecho, el código de construcción en la
declaración del paquete no debe ser evaluado en el lado del cliente,
sino sólo cuando se pasa al daemon Guix. Este mecanismo de pasar código
entre dos procesos en ejecución se denomina code staging
(https://arxiv.org/abs/1709.00833).

2.1.3.7 Funciones de utilidad
.............................

Cuando personalizamos ‘phases’, a menudo necesitamos escribir código que
imite las invocaciones equivalentes del sistema (‘make’, ‘mkdir’, ‘cp’,
etc.) comúnmente usadas durante instalaciones regulares “al estilo
Unix”.

   Algunos como ‘chmod’ son nativos para Guile. *Note (guile):: para un
listado completo.

   Proporciona funciones ayudantes adicionales Guix las cual prueba
especialmente manipular en el contexto de gestor de paquete.

   Algunas de estas funciones pueden encontrarse en
‘$GUIX_CHECKOUT/guix/guix/build/utils.scm’. La mayoría de ellas reflejan
el comportamiento de los comandos tradicionales del sistema Unix:

‘which’
     Como la instrucción del sistema ‘which’.
‘find-files’
     Similar al comando de sistema ‘find’.
‘mkdir-p’
     Como ‘mkdir -p’, que crea todos los padres según sea necesario.
‘install-file’
     Similar a ‘install’ cuando se instala un archivo en un directorio
     (posiblemente inexistente). Guile tiene ‘copy-file’ que funciona
     como ‘cp’.
‘copy-recursively’
     Como ‘cp -r’.
‘delete-file-recursively’
     Como ‘rm -rf’.
‘invoke’
     Ejecuta un ejecutable. Esto sería utilizado en vez de ‘system*’.
‘with-directory-excursion’
     Ejecuta el cuerpo de un directorio de trabajo diferente,
     posteriormente restaura el directorio de trabajo anterior.
‘substitute*’
     Una función “‘sed’” similar.

   *Note (guix.es)Utilidades de construcción::, para más información
sobre estas utilidades.

2.1.3.8 Prefijo módulo
......................

La licencia en nuestro último ejemplo necesita un prefijo: esto se debe
a cómo el módulo ‘license’ fue importado en el paquete, como
‘#:use-module ((guix licenses) #:prefix license:)’. El mecanismo de
importación de módulos de Guile (*note (guile)Uso de módulos Guile::) da
al usuario control total sobre el espaciado de nombres: esto es
necesario para evitar conflictos entre, digamos, la variable ‘zlib’ de
‘licenses.scm’ (un valor _license_) y la variable ‘zlib’ de
‘compression.scm’ (un valor _package_).


File: guix-cookbook.es.info,  Node: Otros sistemas de construcción,  Next: Definición de paquetes programable y automatizada,  Prev: Ejemplo ampliado,  Up: Tutorial de empaquetado

2.1.4 Otros sistemas de construcción
------------------------------------

Lo que hemos visto hasta ahora cubre la mayoría de los paquetes que
utilizan un sistema de construcción distinto del ‘trivial-build-system’.
Este último no automatiza nada y te deja construir todo manualmente.
Esto puede ser más exigente y no lo cubriremos aquí por ahora, pero
afortunadamente rara vez es necesario recurrir a este sistema.

   Para los demás sistemas de construcción, como ASDF, Emacs, Perl, Ruby
y muchos más, el proceso es muy similar al del sistema de construcción
de GNU, excepto por algunos argumentos especializados.

   *Note (guix.es)Sistemas de construcción::, para más información sobre
sistemas de compilación, o consulte el código fuente en los directorios
‘$GUIX_CHECKOUT/guix/build’ y ‘$GUIX_CHECKOUT/guix/build-system’.


File: guix-cookbook.es.info,  Node: Definición de paquetes programable y automatizada,  Next: Obtener ayuda,  Prev: Otros sistemas de construcción,  Up: Tutorial de empaquetado

2.1.5 Definición de paquetes programable y automatizada
-------------------------------------------------------

No nos cansaremos de repetirlo: tener a mano un lenguaje de programación
completo nos capacita de formas que van mucho más allá de la gestión
tradicional de paquetes.

   Ilustraremos esto con algunas características asombrosas de Guix.

* Menu:

* Importadores recursivos::  Importadores recursivos
* Actualizaciones automáticas::  Actualizaciones automáticas
* Herencia::                 Herencia


File: guix-cookbook.es.info,  Node: Importadores recursivos,  Next: Actualizaciones automáticas,  Up: Definición de paquetes programable y automatizada

2.1.5.1 Importadores recursivos
...............................

Puedes encontrar algunos sistemas de construcción lo suficientemente
buenos como para que haya poco que hacer para escribir un paquete, hasta
el punto de que se vuelve repetitivo y tedioso después de un tiempo. Una
_razón de ser_ de los ordenadores es reemplazar a los seres humanos en
esas tareas aburridas. Así que vamos a decirle a Guix que haga esto por
nosotros y cree la definición de paquete de un paquete R desde CRAN (la
salida está recortada para ser concisos):

     $ 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
           "Este paquete proporciona una caja de herramientas de pruebas
     estadísticas robustas comunes, incluidas las descriptivas robustas,
     pruebas-t robustas, y ANOVA robusto.
     También está disponible como módulo para 'jamovi' (consulte
     <https://www.jamovi.org> para más información).  Walrus está baso en el
     paquete WRS2 de Patrick Mair, que a su vez se basa en los guiones y
     el trabajo de Rand Wilcox.  Estos análisis se describen en profundidad en el libro
     'Introducción a la estimación robusta y la comprobación de hipótesis'.")
         (licencia gpl3)))

   El importador recursivo no importará paquetes para los que Guix ya
tenga definiciones de paquetes, excepto para el primero.

   No todas las aplicaciones pueden empaquetarse de esta forma, sólo
aquellas que dependen de un número selecto de sistemas soportados. Lea
sobre la lista completa de importadores en la sección guix import del
manual (*note guix: (Manual de referencia de GNU Guix)Invocación de guix
import.).


File: guix-cookbook.es.info,  Node: Actualizaciones automáticas,  Next: Herencia,  Prev: Importadores recursivos,  Up: Definición de paquetes programable y automatizada

2.1.5.2 Actualizaciones automáticas
...................................

Guix puede ser lo suficientemente inteligente como para buscar
actualizaciones en los sistemas que conoce. Puede informar de
definiciones de paquetes obsoletas con

     $ guix refresh hola

   En la mayoría de los casos, actualizar un paquete a una versión más
reciente requiere poco más que cambiar el número de versión y la suma de
comprobación. Guix también puede hacerlo automáticamente:

     $ guix refresh saludo --update


File: guix-cookbook.es.info,  Node: Herencia,  Prev: Actualizaciones automáticas,  Up: Definición de paquetes programable y automatizada

2.1.5.3 Herencia
................

Si has empezado a navegar por las definiciones de paquetes existentes,
te habrás dado cuenta de que un número significativo de ellos tienen un
campo ‘inherit’:

     (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")))))

   Todos los campos no especificados son heredados desde el paquete
antecesor. Esto es muy conveniente para crear paquetes alternativos,
para instancia con opciones de fuentes, versión o compilación
diferentes.


File: guix-cookbook.es.info,  Node: Obtener ayuda,  Next: Conclusión,  Prev: Definición de paquetes programable y automatizada,  Up: Tutorial de empaquetado

2.1.6 Obtener ayuda
-------------------

Tristemente, algunas aplicaciones pueden ser cambiadas para empaquetar.
Algunas veces necesitan un parche para funcionar con la jerarquía del
sistema de archivo no estándar forzadas por el almacenaje. Algunas veces
las pruebas no funcionarán apropiadamente. (Pueden ser omitidos pero
esto no es lo recomentado.) Otras veces el paquete resultante no sería
reproducible.

   Estaría atascado, incapaz de figurar como reparar cualquier breve
problema de empaquetado, no dude preguntar a la comunidad para ayuda.

   Consulte la página inicial de Guix (https://guix.gnu.org/contact/)
para información sobre los listados de correo, IRC, etc.


File: guix-cookbook.es.info,  Node: Conclusión,  Next: Referencias,  Prev: Obtener ayuda,  Up: Tutorial de empaquetado

2.1.7 Conclusión
----------------

Este tutorial fue una muestra de caso de la gestión de empaquetado
sofisticado que lleva Guix. En este punto estamos restringidos
mayormente esta introducción sobre el ‘gnu-system’ el cual es una capa
de abstracción del núcleo en el cual están basadas más abstracciones
avanzadas.

   ¿donde vamos desde aquí? Siguiente quisimos deseccionar los internas
del sistema de construcción eliminando todas las abstracciones,
utilizando el ‘trivial-build-system’: esto nos proporcionaría una
comprensión a través del proceso antes de investigar algunas técnicas de
empaquetado más avanzado y casos del borde.

   Otras características los cuales exploran son la interactividad
editanto y depurando capacidades de Guix proporcionadas por el REPL de
Guile.

   Esas características de lujo son completamente opcionales y pueden
esperar; ahora es un buen momento para tomarse un merecido descanso. Con
lo que hemos presentado aquí deberías estar bien armado para empaquetar
muchos programas. Puede empezar ahora mismo y esperamos ver pronto sus
contribuciones.


File: guix-cookbook.es.info,  Node: Referencias,  Prev: Conclusión,  Up: Tutorial de empaquetado

2.1.8 Referencias
-----------------

   • La referencia de paquete dentro del manual
     (https://guix.gnu.org/manual/es/html_node/Definicion-de-paquetes.html)

   • La guía de jaqueo de Pjotr para GNU Guix
     (https://gitlab.com/pjotrp/guix-notes/blob/master/HACKING.org)

   • “GNU Guix: ¡Paquete sin un scheme!”
     (https://guix.gnu.org/guix-ghm-andreas-20130823.pdf), de Andreas
     Enge


File: guix-cookbook.es.info,  Node: Packaging Workflows,  Prev: Tutorial de empaquetado,  Up: Empaquetado

2.2 Packaging Workflows
=======================

The following sections provide real-life examples on working with
specific build systems, serving as extensions to the concise packaging
guidelines (*note (guix)Packaging Guidelines::).

* Menu:

* Packaging Rust Crates::    Packaging Rust Crates


File: guix-cookbook.es.info,  Node: Packaging Rust Crates,  Up: Packaging Workflows

2.2.1 Packaging Rust Crates
---------------------------

In preparation, add the following packages to our environment:

     $ guix shell rust rust:cargo cargo-audit cargo-license

* 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


File: guix-cookbook.es.info,  Node: Common Workflow for Rust Packaging,  Next: Cargo Workspaces and Development Snapshots,  Up: Packaging Rust Crates

2.2.1.1 Common Workflow for Rust Packaging
..........................................

In this example, we’ll package ‘cargo-audit’, which is published on the
crates.io (https://crates.io) Rust package repository. All its
dependencies are on crates.io as well.

  1. Since ‘cargo-audit’ is available on crates.io, we can generate a
     template via the crates.io importer (*note (guix)Invoking guix
     import::):

          $ guix import crate cargo-audit

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

          (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))))

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

  2. Unpack package source and navigate to the unpacked directory, then
     run the following commands:

          $ cargo generate-lockfile
          $ cargo audit
          $ cargo license

     ‘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 semantic versioning
     (https://semver.org/) scheme, it’s still acceptable.

     ‘cargo audit’ checks known vulnerabilities and ‘cargo license’
     checks licenses, for all the dependencies. We must have an
     acceptable output of ‘cargo audit’ and ensure all dependencies are
     licensed with our supported licenses (*note (guix)Defining
     Packages::).

  3. Import dependencies from the generated lockfile:

          $ 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

     ‘cargo-audit’ here must be consistent with the identifier used for
     ‘cargo-inputs’ invocation in the package definition.

     At this stage, the package ‘cargo-audit’ is buildable.

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

          $ ./pre-inst-env guix build cargo-audit
          ...
          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
          ...

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

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

     To unbundle most dependencies, a snippet is sufficient:

          (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")))

          (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\");~@
                                  }~%"))))))

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

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

          (define rust-ring-0.17.14 rust-ring-0.17)

     When one dependency can be safely removed, modify it to ‘#f’.

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

     To facilitate various tasks in the common workflow, several scripts
     are provided in the ‘etc/teams/rust’ directory of Guix source tree.


File: guix-cookbook.es.info,  Node: Cargo Workspaces and Development Snapshots,  Next: Using Rust Libraries in Other Build Systems,  Prev: Common Workflow for Rust Packaging,  Up: Packaging Rust Crates

2.2.1.2 Cargo Workspaces and Development Snapshots
..................................................

In this example, we’ll package ‘niri’, which depends on development
snapshots (also Cargo workspaces here).

   As we can’t ensure compatibility of a development snapshot, before
executing ‘cargo generate-lockfile’, we should modify ‘Cargo.toml’ to
pin it to a known working revision.

   To use our packaged development snapshots, it’s also necessary to
modify ‘Cargo.toml’ in a build phase, with a package-specific
substitution pattern.

     (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+)))

   ‘niri’ has Cargo workspace dependencies. When packaging a Cargo
workspace dependency, parameter ‘#:cargo-package-crates’ is required.

     (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))))

   Don’t forget to modify all workspace members in ‘(gnu packages
rust-crates)’:

     (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)
     ...
     (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)


File: guix-cookbook.es.info,  Node: Using Rust Libraries in Other Build Systems,  Prev: Cargo Workspaces and Development Snapshots,  Up: Packaging Rust Crates

2.2.1.3 Using Rust Libraries in Other Build Systems
...................................................

In this example, we’ll package ‘libchewing’, which combines two build
systems.

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

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

     (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+)))


File: guix-cookbook.es.info,  Node: Configuración del sistema,  Next: Contenedores,  Prev: Empaquetado,  Up: Top

3 Configuración del sistema
***************************

Guix ofrece un lenguaje flexible para configurar de forma declarativa su
sistema Guix. Esta flexibilidad puede resultar a veces abrumadora. El
propósito de este capítulo es demostrar algunos conceptos avanzados de
configuración.

   *note (guix)Configuración del sistema:: para una referencia completa.

* Menu:

* Inicio de sesión automático en un TTY específico::  Iniciar
                                                        automáticamente la
                                                        sesión de un usuario
                                                        en un TTY específico
* Personalización del kernel::  Creación y uso de un núcleo Linux
                                  personalizado en el sistema Guix.
* API de imagen del sistema Guix::  Personalización de imágenes para
                                      dirigirlas a plataformas específicas.
* Utilización de claves de seguridad::  Cómo utilizar claves de seguridad
                                          con Guix System.
* Tarea mcron de DNS dinámico::  Tarea para actualizar la dirección IP
                                   detrás de un nombre de anfitrión DuckDNS.
* Conexión a Wireguard VPN::  Conexión a una VPN Wireguard.
* Personalizar un gestor de ventanas::  Manejar la personalización de un
                                          gestor de ventanas en el sistema
                                          Guix.
* Ejecución de Guix en un servidor Linode::  Ejecución de Guix en un
                                               servidor Linode.
* Ejecución de Guix en un servidor Kimsufi::  Ejecución de Guix en un
                                                servidor Kimsufi.
* Instalar un montaje enlazado::  Instalar un ‘bind mount’ dentro de
                                    definición de sistemas de archivos.
* Obtener sustituciones desde Tor::  Configurar el daemon Guix para obtener
                                       sustituciones desde Tor.
* Instalar NGINX con Lua::   Configurar servidor de web NGINX para cargar
                               módulos Lua.
* Servidor de música con sonido Bluetooth::  Reproductor de música sin
                                               cabeceras con salida Bluetooth.


File: guix-cookbook.es.info,  Node: Inicio de sesión automático en un TTY específico,  Next: Personalización del kernel,  Up: Configuración del sistema

3.1 Inicio de sesión automático en un TTY específico
====================================================

Mientras que el manual de Guix explica el auto-login de un usuario a
_all_ TTYs (*note (guix)auto-login to TTY::), algunos pueden preferir
una situación, en la que un usuario se registra en un TTY con los otros
TTYs configurados para registrar diferentes usuarios o ninguno en
absoluto. Tenga en cuenta que uno puede auto-login un usuario a
cualquier TTY, pero por lo general es aconsejable evitar ‘tty1’, que,
por defecto, se utiliza para registrar advertencias y errores.

   Así es como se puede configurar el inicio de sesión automático para
un usuario en un tty:

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

     (define %mis-servicios
       (modify-services %base-services
         ;; ...
         (mingetty-service-type config =>
                                (auto-login-to-tty
                                 config "tty3" "alice"))))

     (operating-system
       ;; ...
       (services %mis-servicios))

   También se podría ‘compose’ (*note (guile)Higher-Order Functions::)
‘auto-login-to-tty’ para iniciar sesión de múltiples usuarios en
múltiples ttys.

   Por último, una nota de precaución. Configurar el inicio de sesión
automático en un TTY, significa que cualquiera puede encender tu
ordenador y ejecutar comandos como tu usuario habitual. Sin embargo, si
tienes una partición raíz cifrada, y por lo tanto ya necesitas
introducir una frase de contraseña cuando se inicia el sistema, el
inicio de sesión automático puede ser una opción conveniente.


File: guix-cookbook.es.info,  Node: Personalización del kernel,  Next: API de imagen del sistema Guix,  Prev: Inicio de sesión automático en un TTY específico,  Up: Configuración del sistema

3.2 Personalización del kernel
==============================

Guix es, en su núcleo, una distribución basada en fuentes con
sustituciones (*note (guix.es)Sustituciones::), y como tal la
construcción de paquetes desde su código fuente es una parte esperada de
las instalaciones y actualizaciones regulares de paquetes. Dado este
punto de partida, tiene sentido que se hagan esfuerzos para reducir la
cantidad de tiempo dedicado a la compilación de paquetes, y los
recientes cambios y actualizaciones en la construcción y distribución de
sustitutos sigue siendo un tema de discusión dentro de Guix.

   El núcleo, aunque no requiere una sobreabundancia de RAM para
construirse, tarda bastante tiempo en una máquina media. La
configuración oficial del kernel, como es el caso de muchas
distribuciones GNU/Linux, peca de inclusiva, y esto es realmente lo que
hace que la construcción tarde tanto tiempo cuando el kernel se compila
desde el código fuente.

   El núcleo de Linux, sin embargo, también puede describirse como un
paquete normal y corriente, y como tal puede personalizarse como
cualquier otro paquete. El procedimiento es un poco diferente, aunque
esto se debe principalmente a la naturaleza de cómo está escrita la
definición del paquete.

   La definición del paquete del núcleo ‘linux-libre’ es en realidad un
procedimiento que crea un paquete.

     (define* (make-linux-libre* version gnu-revision source supported-systems
                                 #:key
                                 (extra-version #f)
                                 ;; Una función que toma un arco y una variante.
                                 ;; Consulte kernel-config para ver un ejemplo.
                                 (configuration-file #f)
                                 (defconfig "defconfig")
                                 (extra-options (default-extra-linux-options version)))
       ...)

   El paquete ‘linux-libre’ actual es para la serie 5.15.x, y se declara
así:

     (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))

   Cualquier clave a la que no se le asignen valores hereda su valor por
defecto de la definición ‘make-linux-libre’. Al comparar los dos
fragmentos anteriores, observe el comentario de código que hace
referencia a ‘#:configuration-file’. Debido a esto, en realidad no es
fácil incluir una configuración personalizada del kernel desde la
definición, pero no te preocupes, hay otras maneras de trabajar con lo
que tenemos.

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

   A continuación se muestra un paquete de núcleo de muestra.

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

   En el mismo directorio que el fichero que define ‘my-linux-libre’ hay
un fichero llamado ‘defconfig’. De esta manera usted puede proporcionar
opciones del kernel que desea tener en el kernel resultante.

   La segunda forma de crear un núcleo personalizado es pasar un nuevo
valor a la palabra clave ‘extra-options’ del procedimiento
‘make-linux-libre’. La palabra clave ‘extra-options’ trabaja con otra
función definida justo debajo de ella:

     (define (default-extra-linux-options version)
       `(;; https://lists.gnu.org/archive/html/guix-devel/2014-04/msg00039.html
        ("CONFIG_DEVPTS_MULTIPLE_INSTANCES" . #true)
        ;; Módulos necesarios para 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"))

   Y en el script de configuración personalizado del paquete
‘make-linux-libre‘:

     ;; La aplicación funciona incluso cuando la opción no estaba
     ;; en el archivo. El último prevalece si se duplica.
     (let ((port (open-file ".config" "a"))
           (extra-configuration ,(config->string extra-options)))
       (display extra-configuration port)
       (close-port port))

     (invoke "make" "oldconfig")

   Así que al no proporcionar un archivo de configuración el ‘.config’
comienza en blanco, y luego escribimos en él la colección de indicadores
que queremos. Aquí hay otro kernel personalizado:

     (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: Accede al procedimiento interno 'make-linux-libre*', que es
       ;; privado y no tiene soporte, y es susceptible de cambiar en el futuro.
       ((@@ (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))

   En el ejemplo anterior ‘%file-systems’ es una colección de
indicadores que habilitan el soporte de diferentes sistemas de archivos,
‘%efi-support’ habilita el soporte EFI y ‘%emulation’ permite que una
máquina x86_64-linux actúe también en modo de 32 bits. El procedimiento
‘default-extra-linux-options’ es el definido anteriormente, que tuvo que
ser utilizado para evitar perder las opciones de configuración por
defecto de la palabra clave ‘extra-options’.

   Todo esto suena como que debería ser factible, pero ¿cómo se sabe
siquiera qué módulos son necesarios para un sistema en particular? Dos
lugares que pueden ser útiles para intentar responder a esta pregunta
son el Manual Gentoo
(https://wiki.gentoo.org/wiki/Handbook:AMD64/Installation/Kernel) y el
documentación del propio kernel
(https://www.kernel.org/doc/html/latest/admin-guide/README.html?highlight=localmodconfig).
De la documentación del kernel, parece que ‘make localmodconfig’ es el
comando que queremos.

   Para poder ejecutar ‘make localmodconfig’ primero necesitamos obtener
y desempaquetar el código fuente del kernel:

     tar xf $(guix build linux-libre --source)

   Una vez dentro del directorio que contiene el código fuente ejecute
‘touch .config’ para crear un ‘.config’ inicial vacío con el que
empezar. ‘make localmodconfig’ funciona viendo lo que ya tiene en
‘.config’ y le informa de lo que le falta. Si el archivo está en blanco
entonces te falta todo. El siguiente paso es ejecutar:

     guix shell -D linux-libre -- make localmodconfig

   y observe la salida. Tenga en cuenta que el archivo ‘.config’ sigue
estando vacío. La salida contiene generalmente dos tipos de
advertencias. La primera empieza por "WARNING" y puede ignorarse en
nuestro caso. El segundo dice:

     módulo pcspkr no tenía configuración CONFIG_INPUT_PCSPKR

   Para cada una de estas líneas, copia la parte ‘CONFIG_XXXX_XXXX’ en
el ‘.config’ del directorio, y añade ‘=m’, para que al final quede así:

     CONFIG_INPUT_PCSPKR=m
     CONFIG_VIRTIO=m

   Después de copiar todas las opciones de configuración, ejecute ‘make
localmodconfig’ de nuevo para asegurarse de que no tiene ninguna salida
que empiece por “module”. Después de todos estos módulos específicos de
la máquina quedan un par más que también son necesarios.
‘CONFIG_MODULES’ es necesario para que pueda construir y cargar módulos
por separado y no tener todo integrado en el núcleo. ‘CONFIG_BLK_DEV_SD’
es necesario para leer de discos duros. Es posible que haya otros
módulos que necesite.

   Sin embargo, este post no pretende ser una guía para configurar tu
propio kernel, así que si decides construir un kernel personalizado
tendrás que buscar otras guías para crear un kernel que se ajuste a tus
necesidades.

   La segunda forma de configurar el kernel hace un mayor uso de las
características de Guix y permite compartir segmentos de configuración
entre diferentes kernels. Por ejemplo, todas las máquinas que utilizan
EFI para arrancar tienen una serie de banderas de configuración EFI que
necesitan. Es probable que todos los kernels compartan una lista de
sistemas de ficheros a soportar. Mediante el uso de variables es más
fácil ver de un vistazo qué características están habilitadas y
asegurarse de no tener características en un núcleo pero que faltan en
otro.

   Sin embargo, no se ha hablado del initrd de Guix y su
personalización. Es probable que tenga que modificar el initrd en una
máquina que utilice un kernel personalizado, ya que ciertos módulos que
se espera que se construyan pueden no estar disponibles para su
inclusión en el initrd.


File: guix-cookbook.es.info,  Node: API de imagen del sistema Guix,  Next: Utilización de claves de seguridad,  Prev: Personalización del kernel,  Up: Configuración del sistema

3.3 API de imagen del sistema Guix
==================================

Históricamente, el sistema Guix se centra en una estructura
‘operating-system’. Esta estructura contiene varios campos que van desde
el gestor de arranque y la declaración del kernel hasta los servicios a
instalar.

   Dependiendo de la máquina de destino, que puede ir desde una máquina
‘x86_64’ estándar hasta un pequeño ordenador ARM de placa única como el
Pine64, las restricciones de la imagen pueden variar mucho. Los
fabricantes de hardware impondrán diferentes formatos de imagen con
varios tamaños de partición y desplazamientos.

   Para crear imágenes adecuadas para todas esas máquinas, es necesaria
una nueva abstracción: ese es el objetivo del registro ‘image’. Este
registro contiene toda la información necesaria para transformarse en
una imagen independiente, que puede arrancarse directamente en cualquier
máquina de destino.

     (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  ;tamaño en bytes como entero
                           (default 'guess))
       (operating-system   image-operating-system  ;<operating-system>
                           (default #f))
       (partitions         image-partitions ;list of <partición>
                           (default '()))
       (compression?       image-compression? ;boolean
                           (default #t))
       (volatile-root?     image-volatile-root? ;boolean
                           (default #t))
       (substitutable?     image-substitutable? ;boolean
                           (default #t)))

   Este registro contiene el sistema operativo a instanciar. El campo
‘format’ define el tipo de imagen y puede ser ‘efi-raw’, ‘qcow2’ o
‘iso9660’, por ejemplo. En el futuro, podría ampliarse a ‘docker’ u
otros tipos de imagen.

   Un nuevo directorio en las fuentes de Guix está dedicado a la
definición de imágenes. Por ahora hay cuatro archivos:

   • ‘gnu/system/images/hurd.scm’
   • ‘gnu/system/images/pine64.scm’
   • ‘gnu/system/images/novena.scm’
   • ‘gnu/system/images/pinebook-pro.scm’

   Echemos un vistazo a ‘pine64.scm’. Contiene la variable
‘pine64-barebones-os’ que es una definición mínima de un sistema
operativo dedicado a la placa Pine A64 LTS.

     (define pine64-barebones-os
       (operating-system
        (host-name "vignemale")
        (timezone "Europe/Paris")
        (locale "en_US.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 "my-root"))
                             (mount-point "/")
                             (type "ext4"))
                            %base-file-systems))
        (services (cons (service agetty-service-type
                                 (agetty-configuration
                                  (extra-options '("-L")) ; ningún carro detectado
                                  (baud-rate "115200")
                                  (term "vt100")
                                  (tty "ttyS0")))
                        %base-services))))

   Los campos ‘kernel’ y ‘bootloader’ apuntan a paquetes dedicados a
esta placa.

   Justo debajo, también se define la variable ‘pine64-image-type’.

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

   Utiliza un registro del que aún no hemos hablado, el registro
‘image-type’, definido de esta manera:

     (define-record-type* <image-type>
       image-type make-image-type
       image-type?
       (name           image-type-name) ;symbol
       (constructor    image-type-constructor)) ;<operating-system> -> <image>

   El objetivo principal de este registro es asociar un nombre a un
procedimiento que transforma un ‘operating-system’ en una imagen. Para
entender por qué es necesario, echemos un vistazo al comando que produce
una imagen a partir de un archivo de configuración ‘operating-system’:

     guix imagen del sistema my-os.scm

   Este comando espera una configuración ‘operating-system’ pero ¿cómo
debemos indicar que queremos una imagen dirigida a una placa Pine64?
Necesitamos proporcionar una información extra, el ‘image-type’, pasando
la bandera ‘--image-type’ o ‘-t’, de esta manera:

     guix system image --image-type=pine64-raw my-os.scm

   Este parámetro ‘image-type’ apunta al ‘pine64-image-type’ definido
anteriormente. Por lo tanto, al ‘operating-system’ declarado en
‘my-os.scm’ se le aplicará el procedimiento ‘(cut image-with-os
arm64-disk-image &lt;&gt;)’ para convertirlo en una imagen.

   La imagen resultante tiene este aspecto:

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

   que es la agregación del ‘operating-system’ definido en ‘my-os.scm’
al registro ‘arm64-disk-image’.

   Pero basta de locuras de esquemas. ¿Qué aporta esta API de imágenes
al usuario de Guix?

   Se puede ejecutar:

     mathieu@cervin:~$ guix system --list-image-types
     Los tipos de imagen disponibles son:

        - 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

   y escribiendo un archivo ‘operating-system’ basado en
‘pine64-barebones-os’, puede personalizar su imagen según sus
preferencias en un archivo (‘my-pine-os.scm’) como este:

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

     (let ((base-os pine64-barebones-os))
       (operating-system
         (inherit base-os)
         (timezone "America/Indiana/Indianapolis")
         (services
          (cons
           (service earlyoom-service-type
                    (earlyoom-configuration
                     (prefer-regexp "icecat|chromium")))
           (operating-system-user-services base-os)))))

   ejecuta:

     guix system image --image-type=pine64-raw my-pine-os.scm

   o,

     guix system image --image-type=hurd-raw my-hurd-os.scm

   para obtener una imagen que se puede escribir directamente en un
disco duro y arrancar desde ella.

   Sin cambiar nada a ‘my-hurd-os.scm’, invocando:

     guix system image --image-type=hurd-qcow2 my-hurd-os.scm

   producirá en su lugar una imagen Hurd QEMU.


File: guix-cookbook.es.info,  Node: Utilización de claves de seguridad,  Next: Tarea mcron de DNS dinámico,  Prev: API de imagen del sistema Guix,  Up: Configuración del sistema

3.4 Utilización de claves de seguridad
======================================

El uso de claves de seguridad puede mejorar su seguridad al proporcionar
una segunda fuente de autenticación que no puede ser fácilmente robada o
copiada, al menos para un adversario remoto (algo que usted tiene), al
secreto principal (una frase de contraseña – algo que usted conoce),
reduciendo el riesgo de suplantación.

   El ejemplo de configuración detallado a continuación muestra la
configuración mínima que debe realizarse en su sistema Guix para
permitir el uso de una llave de seguridad Yubico. Se espera que la
configuración pueda ser útil también para otras claves de seguridad, con
pequeños ajustes.

3.4.1 Configuración para su uso como autenticador de dos factores (2FA)
-----------------------------------------------------------------------

Para que sean utilizables, las reglas udev del sistema deben ampliarse
con reglas específicas para cada clave. A continuación se muestra cómo
ampliar sus reglas udev con el archivo de reglas udev
‘lib/udev/rules.d/70-u2f.rules’ proporcionado por el paquete ‘libfido2’
del módulo ‘(gnu packages security-token)’ y añadir su usuario al grupo
‘"plugdev"’ que utiliza:

     (use-package-modules ... security-token ...)
     ...
     (operating-system
      ...
      (users (cons* (user-account
                    (name "your-user")
                    (group "users")
                    (supplementary-groups
     		'("wheel" "netdev" "audio" "video"
                       "plugdev"))           ;<- added system group
                    (home-directory "/home/your-user"))
                   %base-user-accounts))
      ...
      (services
       (cons*
        ...
        (udev-rules-service 'fido2 libfido2 #:groups '("plugdev")))))

   Después de reconfigurar su sistema y volver a iniciar su sesión
gráfica para que el nuevo grupo esté en vigor para su usuario, puede
verificar que su clave es utilizable iniciando:

     guix shell ungoogled-chromium -- chromium chrome://settings/securityKeys

   y validando que la clave de seguridad se puede restablecer a través
del menú “Restablezca su clave de seguridad”. Si funciona, enhorabuena,
tu clave de seguridad está lista para ser utilizada con aplicaciones que
admitan la autenticación de dos factores (2FA).

3.4.2 Desactivar la generación de código OTP para un Yubikey
------------------------------------------------------------

Si utilizas una clave de seguridad Yubikey y te irritan los códigos OTP
espurios que genera cuando tocas inadvertidamente la clave (¡por
ejemplo, haciendo que te conviertas en un spammer en el canal ‘#guix’
cuando discutes desde tu cliente IRC favorito!), puedes desactivarla
mediante el siguiente comando ‘ykman’:

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

   Alternativamente, puede utilizar el comando ‘ykman-gui’ proporcionado
por el paquete ‘yubikey-manager-qt’ y desactivar completamente la
aplicación ‘OTP’ para la interfaz USB o, desde la vista ‘Applications
-&gt; OTP’, eliminar la configuración de la ranura 1, que viene
preconfigurada con la aplicación OTP de Yubico.

3.4.3 Requerir un Yubikey para abrir una base de datos KeePassXC
----------------------------------------------------------------

La aplicación de gestión de contraseñas KeePassXC tiene soporte para
Yubikeys, pero requiere la instalación de una regla udev para tu sistema
Guix y alguna configuración de la aplicación Yubico OTP en la llave.

   El archivo de reglas udev necesario proviene del paquete
‘yubikey-personalization’, y puede instalarse como:

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

   Después de reconfigurar tu sistema (y reconectar tu Yubikey), querrás
configurar la aplicación de desafío/respuesta OTP de tu Yubikey en su
ranura 2, que es la que utiliza KeePassXC. Es fácil hacerlo a través de
la herramienta de configuración gráfica Yubikey Manager, que se puede
invocar con:

     guix shell yubikey-manager-qt -- ykman-gui

   En primer lugar, asegúrese de que ‘OTP’ está activado en la pestaña
‘Interfaces’ y, a continuación, vaya a ‘Aplicaciones -&gt; OTP’ y haga
clic en el botón ‘Configurar’ de la sección ‘Táctil largo (ranura 2)’.
Seleccione ‘Reto-respuesta’, introduzca o genere una clave secreta y
haga clic en el botón ‘Finalizar’. Si tiene un segundo Yubikey que desea
utilizar como copia de seguridad, debe configurarlo de la misma manera,
utilizando la clave secreta _same_.

   Tu Yubikey ahora debería ser detectado por KeePassXC. Puede añadirse
a una base de datos accediendo al menú ‘Database -&gt; Database
Security...’ de KeePassXC, haciendo clic en el botón ‘Add additional
protection...’, luego en ‘Add Challenge-Response’, seleccionando la
clave de seguridad en el menú desplegable y haciendo clic en el botón
‘OK’ para completar la configuración.


File: guix-cookbook.es.info,  Node: Tarea mcron de DNS dinámico,  Next: Conexión a Wireguard VPN,  Prev: Utilización de claves de seguridad,  Up: Configuración del sistema

3.5 Tarea mcron de DNS dinámico
===============================

Si su ISP (Proveedor de Servicios de Internet) sólo proporciona
direcciones IP dinámicas, puede ser útil configurar un servicio DNS
(Sistema de Nombres de Dominio) dinámico (también conocido como DDNS
(DNS Dinámico)) para asociar un nombre de host estático a una dirección
IP pública pero dinámica (a menudo cambiante). Existen varios servicios
que pueden utilizarse para ello; en la siguiente tarea mcron, se utiliza
DuckDNS (https://duckdns.org). También debería funcionar con otros
servicios DNS dinámicos que ofrezcan una interfaz similar para
actualizar la dirección IP, como <https://freedns.afraid.org/>, con
pequeños ajustes.

   El trabajo mcron se proporciona a continuación, donde DOMAIN debe ser
sustituido por su propio prefijo de dominio, y el token proporcionado
por DuckDNS asociado a DOMAIN añadido al archivo
‘/etc/duckdns/DOMAIN.token’.

     (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/DOMAIN.token"
                                       get-string-all)))
                             (query-template (string-append "https://www.duckdns.org/"
                                                            "update?domains=DOMAIN"
                                                            "&token=~a&ip=")))
                         (http-get (format #f query-template token))))))
              "duckdns-update"
              #:user "nobody"))

   El trabajo entonces necesita ser añadido a la lista de trabajos mcron
para su sistema, usando algo como:

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


File: guix-cookbook.es.info,  Node: Conexión a Wireguard VPN,  Next: Personalizar un gestor de ventanas,  Prev: Tarea mcron de DNS dinámico,  Up: Configuración del sistema

3.6 Conexión a Wireguard VPN
============================

Para conectarse a un servidor VPN Wireguard necesita que el módulo del
kernel esté cargado en memoria y un paquete que proporcione herramientas
de red que lo soporten (por ejemplo, ‘wireguard-tools’ o
‘network-manager’).

   Aquí hay un ejemplo de configuración para Linux-Libre &lt; 5.6, donde
el módulo está fuera del árbol y necesita ser cargado
manualmente—siguientes revisiones del kernel lo tienen incorporado y por
lo tanto no necesitan dicha configuración:

     (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)))

   Después de reconfigurar y reiniciar el sistema, puede utilizar las
herramientas Wireguard o NetworkManager para conectarse a un servidor
VPN.

3.6.1 Uso de las herramientas Wireguard
---------------------------------------

Para probar la configuración de Wireguard es conveniente utilizar
‘wg-quick’. Sólo tiene que darle un archivo de configuración ‘wg-quick
up ./wg0.conf’; o poner ese archivo en ‘/etc/wireguard’ y ejecutar
‘wg-quick up wg0’ en su lugar.

     Nota: Se advierte que el autor describió este comando como un:
     "[...] script bash muy rápido y sucio [...]".

3.6.2 Uso de NetworkManager
---------------------------

Gracias al soporte de NetworkManager para Wireguard podemos conectarnos
a nuestra VPN usando el comando ‘nmcli’. Hasta este punto, esta guía
asume que está utilizando el servicio Network Manager proporcionado por
‘%desktop-services’. De lo contrario, necesitará ajustar su lista de
servicios para cargar ‘network-manager-service-type’ y reconfigurar su
sistema Guix.

   Para importar su configuración VPN ejecute el comando nmcli import:

     # nmcli connection import type wireguard file wg0.conf
     Conexión 'wg0' (edbee261-aa5a-42db-b032-6c7757c60fde) añadida correctamente

   Esto creará un archivo de configuración en
‘/etc/NetworkManager/wg0.nmconnection’. A continuación, conéctese al
servidor Wireguard:

     $ nmcli connection up wg0
     Conexión activada con éxito (ruta activa D-Bus: /org/freedesktop/NetworkManager/ActiveConnection/6)

   Por defecto NetworkManager se conectará automáticamente al arrancar
el sistema. Para cambiar este comportamiento es necesario editar la
configuración:

     # nmcli connection modify wg0 connection.autoconnect no

   For more specific information about NetworkManager and wireguard see
this post by thaller
(https://blogs.gnome.org/thaller/2019/03/15/wireguard-in-networkmanager/).


File: guix-cookbook.es.info,  Node: Personalizar un gestor de ventanas,  Next: Ejecución de Guix en un servidor Linode,  Prev: Conexión a Wireguard VPN,  Up: Configuración del sistema

3.7 Personalizar un gestor de ventanas
======================================

* Menu:

* StumpWM::                  StumpWM
* Bloqueo de sesión::        Bloqueo de sesión


File: guix-cookbook.es.info,  Node: StumpWM,  Next: Bloqueo de sesión,  Up: Personalizar un gestor de ventanas

3.7.1 StumpWM
-------------

Puedes instalar StumpWM con un sistema Guix añadiendo los paquetes
‘stumpwm’ y opcionalmente ‘`(,stumpwm "lib")’ a un fichero de
configuración del sistema, p.ej. ‘/etc/config.scm’.

   Un ejemplo de configuración puede ser similar a esto:

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

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

   Por defecto StumpWM utiliza fuentes X11, que podrían ser pequeñas o
pixeladas en su sistema. Puede solucionarlo instalando el módulo
‘sbcl-ttf-fonts’ de StumpWM contrib Lisp y añadiéndolo a los paquetes
del sistema Guix:

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

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

   A continuación, debe añadir el siguiente código a un archivo de
configuración de StumpWM ‘~/.stumpwm.d/init.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))


File: guix-cookbook.es.info,  Node: Bloqueo de sesión,  Prev: StumpWM,  Up: Personalizar un gestor de ventanas

3.7.2 Bloqueo de sesión
-----------------------

Dependiendo de tu entorno, bloquear la pantalla de tu sesión puede venir
incorporado o puede ser algo que tengas que configurar tú mismo. Si usas
un entorno de escritorio como GNOME o KDE, normalmente viene
incorporado. Si usas un gestor de ventanas sencillo como StumpWM o EXWM,
puede que tengas que configurarlo tú mismo.

* Menu:

* Xorg::                     Xorg


File: guix-cookbook.es.info,  Node: Xorg,  Up: Bloqueo de sesión

3.7.2.1 Xorg
............

Si usas Xorg, puedes usar la utilidad xss-lock
(https://www.mankier.com/1/xss-lock) para bloquear la pantalla de tu
sesión. xss-lock es activado por DPMS que desde Xorg 1.8 es
auto-detectado y activado si ACPI también está activado en tiempo de
ejecución del kernel.

   Para usar xss-lock, puedes simplemente ejecutarlo y ponerlo en
segundo plano antes de iniciar tu gestor de ventanas desde, por ejemplo,
su ‘~/.xsession’:

     xss-lock -- slock &
     exec stumpwm

   En este ejemplo, xss-lock utiliza ‘slock’ para realizar el bloqueo
real de la pantalla cuando determina que es apropiado, como cuando
suspendes tu dispositivo.

   Para que slock pueda ser un casillero de pantalla para la sesión
gráfica, necesita ser hecho setuid-root para que pueda autenticar
usuarios, y necesita un servicio PAM. Esto se puede lograr añadiendo el
siguiente servicio a su ‘config.scm’:

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

   Si bloquea manualmente su pantalla, por ejemplo, llamando
directamente a slock cuando desea bloquear su pantalla pero no
suspenderla, es una buena idea notificar a xss-lock sobre esto para que
no se produzcan confusiones. Esto puede hacerse ejecutando ‘xset s
activate’ inmediatamente antes de ejecutar slock.


File: guix-cookbook.es.info,  Node: Ejecución de Guix en un servidor Linode,  Next: Ejecución de Guix en un servidor Kimsufi,  Prev: Personalizar un gestor de ventanas,  Up: Configuración del sistema

3.8 Ejecución de Guix en un servidor Linode
===========================================

Para ejecutar Guix en un servidor alojado en Linode
(https://www.linode.com), comience con un servidor Debian recomendado.
Recomendamos usar la distribución por defecto para arrancar Guix. Crea
tus claves SSH.

     ssh-keygen

   Asegúrese de añadir su clave SSH para facilitar el inicio de sesión
en el servidor remoto. Esto se hace trivialmente a través de la interfaz
gráfica de Linode para añadir claves SSH. Vaya a su perfil y pulse en
añadir clave SSH. Copie en él la salida de:

     cat ~/.ssh/<nombre-usuario>_rsa.pub

   Apaga el Linode.

   En la pestaña Almacenamiento del Linode, re-dimensione el disco de
Debian para que sea más pequeño. Se recomiendan 30 GB de espacio libre.
A continuación, haga clic en "Añadir un disco", y rellene el formulario
con lo siguiente:

   • Etiqueta: «Guix»

   • Sistema de archivo: ext4

   • Ajústalo al tamaño restante

   En la pestaña Configuraciones, pulse «Editar» en el perfil Debian por
defecto. En «Asignación de dispositivos en bloque» pulse «Añadir un
dispositivo». Debe ser ‘/dev/sdc’ y puede seleccionar el disco «Guix».
Guarde los cambios.

   Ahora «Añadir una configuración», con lo siguiente:
   • Etiqueta: Guix

   • Kernel:GRUB 2 (¡está al final! Este paso es ¡IMPORTANTE!)

   • Asignación de dispositivos en bloque:

   • ‘/dev/sda’: Guix

   • ‘/dev/sdb’: swap

   • Dispositivo raíz: ‘/dev/sda’

   • Desactivar todos los ayudantes del sistema de archivos/arranque

   Ahora enciéndelo de nuevo, arrancando con la configuración de Debian.
Una vez que esté funcionando, conéctese a su servidor mediante ‘ssh
root@<YOUR-SERVER-IP-HERE>’. (Puede encontrar la dirección IP de su
servidor en la sección Resumen de su Linode.) Ahora puede ejecutar los
pasos de "instalar guix desde *note (guix.es)Instalación binaria::":

     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

   Ahora es el momento de escribir una configuración para el servidor.
La información clave está por debajo. Guarde el archivo resultante como
‘guix-config.scm’.

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

     (operating-system
       (host-name "my-server")
       (timezone "America/New_York")
       (locale "en_US.UTF-8")
       ;; Este tonto código generará el grub.cfg
       ;; sin instalar el gestor de arranque grub en el disco.
       (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"    ; Needed to find the disk
                             %base-initrd-modules))

       (users (cons (user-account
                     (name "janedoe")
                     (group "users")
                     ;; Añadir la cuenta al grupo "wheel
                     ;; makes it a sudoer.
                     (supplementary-groups '("wheel"))
                     (home-directory "/home/janedoe"))
                    %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
                             `(("janedoe" ,(local-file "janedoe_rsa.pub"))
                               ("root" ,(local-file "janedoe_rsa.pub"))))))
                  %base-services)))

   Sustituya los siguientes campos en la configuración anterior:
     (host-name "my-server")       ; sustitúyalo por el nombre de su servidor
     ; si eligió un servidor linode fuera de los EE.UU., entonces
     ; utilice tzselect para encontrar una cadena de zona horaria correcta
     (timezone "America/New_York") ; si es necesario, sustituya la zona horaria
     (name "janedoe")              ; sustitúyalo por su nombre de usuario
     ("janedoe" ,(local-file "janedoe_rsa.pub")) ; reemplace con su clave ssh
     ("root" ,(local-file "janedoe_rsa.pub")) ; reemplace con su clave ssh

   La última línea del ejemplo anterior le permite iniciar sesión en el
servidor como root y establecer la contraseña inicial de root (consulte
la nota al final de esta receta sobre el inicio de sesión de root). Una
vez hecho esto, puede eliminar esa línea de la configuración y volver a
configurarla para evitar el inicio de sesión de root.

   Copia tu clave pública ssh (eg: ‘~/.ssh/id_rsa.pub’) como
‘<TU-NOMBRE-DE-USUARIO-AQUÍ>_rsa.pub’ y pone ‘guix-config.scm’ en el
mismo directorio. En un nuevo terminal ejecute estos comandos.

     sftp root@<dirección ip del servidor remoto>
     put /path/to/files/<nombre-usuario>_rsa.pub .
     put /path/to/files/guix-config.scm .

   En tu primer terminal, monta la unidad guix:

     mkdir /mnt/guix
     mount /dev/sdc /mnt/guix

   Debido a la forma en que configuramos la sección del gestor de
arranque de guix-config.scm, sólo se instalará el fichero de
configuración de grub. Por lo tanto, necesitamos copiar algunas de las
otras cosas de GRUB ya instaladas en el sistema Debian:

     mkdir -p /mnt/guix/boot/grub
     cp -r /boot/grub/* /mnt/guix/boot/grub/

   Ahora inicialice la instalación de Guix:

     guix system init guix-config.scm /mnt/guix

   Bien, ¡apágalo! Ahora desde la consola de Linode, selecciona boot y
selecciona "Guix".

   Una vez que arranque, debería poder iniciar sesión a través de SSH.
(La configuración del servidor habrá cambiado sin embargo.) Puede
encontrar un error como:

     $ ssh root@<server ip address>
     @@@@@@@@@@@@@@@@@@@@@@@@@@@@@     ADVERTENCIA: ¡LA IDENTIFICACIÓN DEL HOST REMOTO HA CAMBIADO!      @@@@@@@@@@@@@@@@@@@@@@@@@@@@@ ¡ES POSIBLE QUE ALGUIEN ESTÉ HACIENDO ALGO DESAGRADABLE!
     ¡Alguien podría estar escuchándole en este momento (ataque de intermediario).!
     También es posible que se acabe de cambiar una clave de host.
     La huella digital de la clave ECDSA enviada por el host remoto es
     SHA256:0B+wp33w57AnKQuHCvQP0+ZdKaqYrI/kyU7CfVbS7R4.
     Póngase en contacto con el administrador del sistema.
     Añada la clave de host correcta en /home/joshua/.ssh/known_hosts para deshacerse de este mensaje.
     Clave ECDSA infractora en /home/joshua/.ssh/known_hosts:3
     La clave de host ECDSA para 198.58.98.76 ha cambiado y ha solicitado una comprobación estricta.
     Error en la verificación de la clave del host.

   O bien borra el archivo ‘~/.ssh/known_hosts’, o borra la linea
ofendida de inicio con su dirección IP de servidor.

   Asegúrate de establecer tu contraseña y la de root.

     ssh root@<dirección ip remota>
     passwd  ; para la contraseña de root
     passwd <nombre-usuario> ; para la contraseña de usuario

   Es posible que no pueda ejecutar los comandos anteriores en este
punto. Si tiene problemas para iniciar sesión de forma remota en su caja
linode a través de SSH, entonces es posible que aún tenga que establecer
su contraseña de root y de usuario inicialmente haciendo clic en la
opción “Lanzar Consola” en su linode. Elija “Glish” en lugar de
“Weblish”. Ahora usted debe ser capaz de ssh en la máquina.

   ¡Hurra! En este punto puede apagar el servidor, borrar el disco
Debian y redimensionar el Guix al resto del tamaño. ¡Enhorabuena!

   Por cierto, si la guardas como imagen de disco en este momento, ¡te
resultará muy fácil crear nuevas imágenes Guix! Puede que necesites
reducir el tamaño de la imagen Guix a 6144MB, para guardarla como
imagen. A continuación, puede cambiar el tamaño de nuevo al tamaño
máximo.


File: guix-cookbook.es.info,  Node: Ejecución de Guix en un servidor Kimsufi,  Next: Instalar un montaje enlazado,  Prev: Ejecución de Guix en un servidor Linode,  Up: Configuración del sistema

3.9 Ejecución de Guix en un servidor Kimsufi
============================================

Para ejecutar Guix en un servidor alojado en Kimsufi
(https://www.kimsufi.com/), haz clic en la pestaña netboot, selecciona
rescue64-pro y reinicia.

   OVH le enviará por correo electrónico las credenciales necesarias
para entrar por ssh en un sistema Debian.

   Ahora puede ejecutar los pasos "instalar guix desde *note
(guix)Instalación binaria::":

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

   Particionar los discos y formatearlos, primero parar el raid array:

     mdadm --stop /dev/md127
     mdadm --zero-superblock /dev/sda2 /dev/sdb2

   A continuación, limpie los discos y configurar las particiones, vamos
a crear una matriz RAID 1.

     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%

   Crea el array:

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

   Ahora cree sistemas de archivos en las particiones relevantes,
primero las particiones de arranque:

     mkfs.ext4  /dev/sda1
     mkfs.ext4  /dev/sdb1

   A continuación, la partición raíz:

     mkfs.ext4 /dev/md127

   Inicializar las particiones swap:

     mkswap /dev/sda3
     swapon /dev/sda3
     mkswap /dev/sdb3
     swapon /dev/sdb3

   Monte la unidad guix:

     mkdir /mnt/guix
     mount /dev/md127 /mnt/guix

   Ahora es el momento de escribir una declaración del sistema operativo
del archivo ‘os.scm’; aquí tiene una muestra:

     (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))))

       ;; Añadir un módulo de kernel para 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.
        "\
     Este es el sistema GNU en Kimsufi.  Bienvenido.\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"))

       ;; Paquetes instalados globalmente.
       (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 "SERVER-IP-ADDRESS/24"))))
     		    (routes (list (network-route
     				   (destination "default")
     				   (gateway "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 "SSH-KEY-NAME.PUB"
                                           "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))))))))

   No olvide sustituir el SERVER-IP-ADDRESS, SERVER-GATEWAY,
SSH-KEY-NAME y SSH-PUBLIC-KEY-CONTENT con sus propios valores.

   La puerta de enlace es la última IP utilizable de su bloque, por lo
que si tiene un servidor con una IP de ‘37.187.79.10’ entonces su puerta
de enlace será ‘37.187.79.254’.

   Transfiera su declaración de sistema operativo ‘os.scm’ en el
servidor a través de ‘scp’ o comandos ‘sftp’.

   Ahora sólo queda instalar Guix con un ‘guix system init’ y reinicia.

   Sin embargo, primero necesitamos configurar un chroot, porque la
partición raíz del sistema de rescate está montada en una partición aufs
y si intentas instalar Guix fallará en el paso de instalación de GRUB
quejándose de la ruta canónica de "aufs".

   Instala los paquetes que se utilizarán en el chroot:

     guix install bash-static parted util-linux-with-udev coreutils guix

   A continuación, ejecute lo siguiente para crear los directorios
necesarios para el chroot:

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

   Copie el host resolv.conf en el chroot:

     cp /etc/resolv.conf etc/

   Montar dispositivos de bloque, el almacén y su base de datos y la
configuración guix actual:

     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/

   Chroot en /mnt e instalar el sistema:

     chroot /mnt/ /bin/bash

     guix system init /root/os.scm /guix

   Por último, desde la interfaz de usuario web (UI), cambia ‘netboot’
por ‘boot to disk’ y reinicia (también desde la UI web).

   Espera unos minutos e intenta hacer ssh con ‘ssh
guix@DIRECCIÓN-IP-DEL-SERVIDOR> -i PATH-TO-YOUR-SSH-KEY’.

   Deberías tener un sistema Guix funcionando en Kimsufi; ¡enhorabuena!


File: guix-cookbook.es.info,  Node: Instalar un montaje enlazado,  Next: Obtener sustituciones desde Tor,  Prev: Ejecución de Guix en un servidor Kimsufi,  Up: Configuración del sistema

3.10 Instalar un montaje enlazado
=================================

Para enlazar el montaje de un sistema de archivos, primero hay que
establecer algunas definiciones antes de la sección ‘operating-system’
de la definición del sistema. En este ejemplo vamos a bind mount una
carpeta de una unidad de disco giratorio a ‘/tmp’, para ahorrar desgaste
en el SSD primario, sin dedicar una partición entera a ser montada como
‘/tmp’.

   En primer lugar, debe definirse la unidad de origen que aloja la
carpeta que deseamos montar de forma enlazada, para que el montaje
enlazado pueda depender de ella.

     (define source-drive ;; "source-drive" puede llamarse como quieras.
        (file-system
         (device (uuid "UUID goes here"))
         (mount-point "/path-to-spinning-disk-goes-here")
         (type "ext4"))) ;Asegúrese de establecer el tipo adecuado para su unidad..

   También debe definirse la carpeta de origen, para que guix sepa que
no se trata de un dispositivo de bloque normal, sino de una carpeta.
     ;; "source-directory" puede denominarse con cualquier nombre de variable válido.
     (define (%source-directory) "/path-to-spinning-disk-goes-here/tmp")

   Por último, dentro del ‘file-systems’ definición, debemos añadir el
propio montaje.

     (file-systems (cons*

                     ...<otras unidades omitidas para mayor claridad>...

                     ;; Debe coincidir con el nombre que le diste a la unidad de origen en la definición anterior.
                     source-drive

                     (file-system
                      ;; Asegúrese de que "directorio-fuente" coincide con su definición anterior.
                      (device (%source-directory))
                      (mount-point "/tmp")
                      ;; Estamos montando una carpeta, no una partición, por lo que este tipo debe ser "none"
                      (type "none")
                      (flags '(bind-mount))
                      ;; Asegúrese de que "source-drive" coincide con el nombre que ha dado a la variable de la unidad..
                      (dependencies (list source-drive))
                      )

                      ...<otras unidades omitidas para mayor claridad>...

                     ))


File: guix-cookbook.es.info,  Node: Obtener sustituciones desde Tor,  Next: Instalar NGINX con Lua,  Prev: Instalar un montaje enlazado,  Up: Configuración del sistema

3.11 Obtener sustituciones desde Tor
====================================

El daemon Guix puede usar un proxy HTTP para obtener sustituciones, aquí
lo estamos configurando para obtenerlos vía Tor.

     Aviso: _No todos_ ¡El tráfico del daemon Guix irá a través de Tor!
     Sólo conexiones proxy HTTP/HTTPS; FTP, protocolo Git, SSH, etc
     seguirá pasando por la clearnet. De nuevo, esta configuración no es
     infalible, parte de su tráfico no será enrutado por Tor en
     absoluto. Utilícelo bajo su propia responsabilidad.

     Tenga en cuenta también que el procedimiento aquí descrito sólo se
     aplica a la sustitución de paquetes. Cuando actualice su
     distribución guix con ‘guix pull’, todavía necesitas usar
     ‘torsocks’ si quieres enrutar la conexión a los servidores de
     repositorios git de guix a través de Tor.

   El servidor de sustitutos de Guix está disponible como un servicio
Onion, si quiere usarlo para obtener sus sustitutos a través de Tor
configure su sistema como sigue:

     (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)
                           ;; ci.guix.gnu.org's Onion service
                           (substitute-urls "\
     https://4zwzi66wwdaalbhgnix55ea3ab4pvvw66ll2ow53kjub6se4q2bclcyd.onion")
                           (http-proxy "http://localhost:9250")))))))

   Esto mantendrá un proceso Tor en ejecución que proporciona un túnel
HTTP CONNECT que será utilizado por ‘guix-daemon’. El daemon puede usar
otros protocolos que HTTP(S) para obtener recursos remotos, las
peticiones que usen esos protocolos no pasarán por Tor ya que aquí sólo
estamos configurando un túnel HTTP. Tenga en cuenta que
‘substitutes-urls’ está usando HTTPS y no HTTP o no funcionará, es una
limitación del túnel de Tor; puede que quiera usar ‘privoxy’ en su lugar
para evitar tales limitaciones.

   Si no quiere obtener sustitutos siempre a través de Tor sino usarlo
sólo algunas veces, entonces omita el ‘guix-configuration’. Cuando desee
obtener un sustituto del túnel Tor ejecute:

     sudo herd set-http-proxy guix-daemon http://localhost:9250
     guix build \
       --substitute-urls=https://4zwzi66wwdaalbhgnix55ea3ab4pvvw66ll2ow53kjub6se4q2bclcyd.onion ...


File: guix-cookbook.es.info,  Node: Instalar NGINX con Lua,  Next: Servidor de música con sonido Bluetooth,  Prev: Obtener sustituciones desde Tor,  Up: Configuración del sistema

3.12 Instalar NGINX con Lua
===========================

NGINX podría ampliarse con scripts Lua.

   Guix proporciona al servicio NGINX la capacidad de cargar el módulo
Lua y paquetes Lua específicos, y responder a las peticiones evaluando
scripts Lua.

   El siguiente ejemplo demuestra la definición del sistema con la
configuración para evaluar ‘index.lua’ Lua en una petición HTTP al punto
final <http://localhost/hello>:

     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)

     (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 "/hello")
                                       (body (list #~(format #f "content_by_lua_file ~s;"
                                                             #$(local-file "index.lua"))))))))))))))


File: guix-cookbook.es.info,  Node: Servidor de música con sonido Bluetooth,  Prev: Instalar NGINX con Lua,  Up: Configuración del sistema

3.13 Servidor de música con sonido Bluetooth
============================================

MPD, Music Player Daemon, es una aplicación de servidor flexible para
reproducir música. Los programas cliente de distintas máquinas de la red
-un teléfono móvil, un portátil, una estación de trabajo de sobremesa-
pueden conectarse a él para controlar la reproducción de archivos de
audio de tu colección de música local. MPD descodifica los archivos de
audio y los reproduce en una o varias salidas.

   Por defecto MPD reproducirá en el dispositivo de audio por defecto.
En el siguiente ejemplo hacemos las cosas un poco más interesantes
configurando un servidor de música sin cabeza. No habrá interfaz gráfica
de usuario, ni daemon Pulseaudio, ni salida de audio local. En su lugar
configuraremos MPD con dos salidas: un altavoz bluetooth y un servidor
web para servir flujos de audio a cualquier reproductor multimedia de
streaming.

   La configuración de Bluetooth suele ser bastante frustrante. Tendrás
que emparejar tu dispositivo Bluetooth y asegurarte que se conecta
automáticamente en cuanto se enciende. El servicio del sistema Bluetooth
devuelto por el procedimiento ‘bluetooth-service’ proporciona la
infraestructura necesaria para configurar esto.

   Reconfigura su sistema con al menos los siguientes servicios y
paquetes:

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

   Inicia el servicio ‘bluetoooth’ y después utilice ‘bluetoothctl’ para
analizar dispositivos Bluetooth. Intente identificar su altavoz
Bluetooth y extraer el ID de dispositivo desde el listado del resultado
de dispositivos que estén indubitables por variedad desconcertante de
automatización del inicio de vecinos. Esto solo necesita ser realizado
una vez:

     $ bluetoothctl
     [NEW] Controlador 00:11:22:33:95:7F BlueZ 5.40 [predet.]

     [bluetooth]# power on
     [bluetooth]# Cambiando a encendido correcto

     [bluetooth]# agent on
     [bluetooth]# Agente registrado

     [bluetooth]# default-agent
     [bluetooth]# Solicitud de agente por defecto solicita correcta

     [bluetooth]# scan on
     [bluetooth]# Discovery started
     [CHG] Controller 00:11:22:33:95:7F Discovering: yes
     [NEW] Device AA:BB:CC:A4:AA:CD My Bluetooth Speaker
     [NEW] Device 44:44:FF:2A:20:DC My Neighbor's TV
     ...

     [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 Confiado: sí
     Cambiando AA:BB:CC:A4:AA:CD confianza lograda

     [bluetooth]#
     [bluetooth]# conecta a AA:BB:CC:A4:AA:CD
     Intentando conectar a AA:BB:CC:A4:AA:CD
     [bluetooth]# [CHG] Dispositivo AA:BB:CC:A4:AA:CD RSSI: -63
     [CHG] Dispositivo AA:BB:CC:A4:AA:CD Conectado: sí
     Conexión lograda

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

   Enhorabuena, ¡ya puedes conectarte automáticamente a tu altavoz
Bluetooth!

   Ahora es el momento de configurar ALSA para utilizar el módulo
_bluealsa_ Bluetooth, para que puedas definir un dispositivo ALSA pcm
correspondiente a tu altavoz Bluetooth. Para un servidor headless usar
_bluealsa_ con un dispositivo Bluetooth fijo es probablemente más
sencillo que configurar Pulseaudio y su comportamiento de conmutación de
flujos. Configuramos ALSA creando un ‘alsa-configuration’ personalizado
para el ‘alsa-service-type’. La configuración declarará un tipo ‘pcm’
‘bluealsa’ del módulo ‘bluealsa’ proporcionado por el paquete
‘bluez-alsa’ y, a continuación, definirá un dispositivo ‘pcm’ de ese
tipo para el altavoz Bluetooth.

   Todo lo que queda entonces es hacer que MPD envíe datos de audio a
este dispositivo ALSA. También añadimos una salida MPD secundaria que
hace que los archivos de audio reproducidos actualmente estén
disponibles como un flujo a través de un servidor web en el puerto 8080.
Cuando se activa, un dispositivo de la red puede escuchar el flujo de
audio conectando cualquier reproductor multimedia al servidor HTTP del
puerto 8080, independientemente del estado del altavoz Bluetooth.

   Lo que sigue es el esquema de una declaración ‘operating-system’ que
debería cumplir las tareas mencionadas:

     (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 "your-username")
                  (music-dir "/path/to/your/music")
                  (address "192.168.178.20")
                  (outputs (list (mpd-output
                                  (type "alsa")
                                  (name "MPD")
                                  (extra-options
                                   ;; Use the same name as in the ALSA
                                   ;; configuration below.
                                   '((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") ;no limit
                                     (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) ;we don't need it
                  (extra-options
                   #~(string-append "\
     # Declara sonido Bluetooth de dispositivo con tipo \"bluealsa\" desde módulo bluealsa
     pcm_type.bluealsa {
         lib \""
     #$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_pcm_bluealsa.so") "\"
     }

     # Declarar dispositivo de control tipo \"bluealsa\" desde el mismo módulo.
     ctl_type.bluealsa {
         lib \""
     #$(file-append bluez-alsa "/lib/alsa-lib/libasound_module_ctl_bluealsa.so") "\"
     }

     # Define el dispositivo de audio Bluetooth real.
     pcm.btspeaker {
         type bluealsa
         device \"AA:BB:CC:A4:AA:CD\" # unique device identifier
         profile \"a2dp\"
     }

     # Definir un controlador asociado.
     ctl.btspeaker {
         type bluealsa
     }
     "))))))

   Disfruta de la música con el cliente MPD de tu elección o con un
reproductor multimedia capaz de transmitir vía HTTP.


File: guix-cookbook.es.info,  Node: Contenedores,  Next: Máquinas virtuales,  Prev: Configuración del sistema,  Up: Top

4 Contenedores
**************

El núcleo Linux proporciona una serie de facilidades compartidas que
están disponibles para los procesos del sistema. Estas facilidades
incluyen una vista compartida sobre el sistema de archivos, otros
procesos, dispositivos de red, identidades de usuario y grupo, y algunas
otras. Desde Linux 3.19 un usuario puede elegir _unshare_ algunas de
estas facilidades compartidas para procesos seleccionados,
proporcionándoles a ellos (y a sus procesos hijos) una vista diferente
del sistema.

   Un proceso con un espacio de nombres ‘mount’ no compartido, por
ejemplo, tiene su propia vista sobre el sistema de archivos — sólo podrá
ver los directorios que han sido explícitamente vinculados en su espacio
de nombres mount. Un proceso con su propio espacio de nombres ‘proc’ se
considerará a sí mismo como el único proceso ejecutándose en el sistema,
ejecutándose como PID 1.

   Guix utiliza estas características del kernel para proporcionar
entornos totalmente aislados e incluso contenedores completos de Guix
System, máquinas virtuales ligeras que comparten el kernel del sistema
anfitrión. Esta característica es especialmente útil cuando se utiliza
Guix en una distribución extranjera para evitar la interferencia de
bibliotecas extranjeras o archivos de configuración que están
disponibles en todo el sistema.

* Menu:

* Contenedores Guix::        Entornos perfectamente aislados
* Contenedores de Sistema Guix::  Un sistema interno a su sistema


File: guix-cookbook.es.info,  Node: Contenedores Guix,  Next: Contenedores de Sistema Guix,  Up: Contenedores

4.1 Contenedores Guix
=====================

La forma más fácil de empezar es usar ‘guix shell’ con la opción
‘--container’. *Note (guix)Invocar guix shell:: para una referencia de
opciones válidas.

   El siguiente fragmento genera un proceso shell mínimo con la mayoría
de los espacios de nombres no compartidos con el sistema. El directorio
de trabajo actual es visible para el proceso, pero cualquier otra cosa
en el sistema de archivos no está disponible. Este aislamiento extremo
puede ser muy útil cuando se quiere descartar cualquier tipo de
interferencia de variables de entorno, bibliotecas instaladas
globalmente o archivos de configuración.

     guix shell --container

   Es un entorno sombrío, estéril, desolado. Encontrará que ni siquiera
los coreutils de GNU están disponibles aquí, así que para explorar este
páramo desierto necesita usar comandos de shell incorporados. Incluso el
normalmente gigantesco directorio ‘/gnu/store’ está reducido a una débil
sombra de sí mismo.

     $ echo /gnu/store/*
     /gnu/store/...-gcc-10.3.0-lib
     /gnu/store/...-glibc-2.33
     /gnu/store/...-bash-static-5.1.8
     /gnu/store/...-ncurses-6.2.20210619
     /gnu/store/...-bash-5.1.8
     /gnu/store/...-profile
     /gnu/store/...-readline-8.1.1

   No hay mucho que se pueda hacer en un entorno así, aparte de salir de
él. Puede utilizar <^D> o ‘exit’ para finalizar este entorno de shell
limitado.

   Puede hacer que otros directorios estén disponibles dentro del
entorno del contenedor; utilice ‘--expose=DIRECTORY’ para montar el
directorio dado como una ubicación de sólo lectura dentro del
contenedor, o utilice ‘--share=DIRECTORY’ para hacer que la ubicación
sea de escritura. Con un argumento de asignación adicional después del
nombre del directorio puede controlar el nombre del directorio dentro
del contenedor. En el siguiente ejemplo mapeamos ‘/etc’ en el sistema
anfitrión a ‘/el/host/etc’ dentro de un contenedor en el que están
instalados los coreutils de GNU.

     $ guix shell --container --share=/etc=/the/host/etc coreutils
     $ ls /the/host/etc

   Del mismo modo, puede evitar que el directorio de trabajo actual se
asigne al contenedor con la opción ‘--no-cwd’. Otra buena idea es crear
un directorio dedicado que servirá como directorio de inicio del
contenedor, y generar el shell del contenedor desde ese directorio.

   En un sistema ajeno se puede utilizar un entorno contenedor para
compilar software que no se puede enlazar con las bibliotecas del
sistema o con la cadena de herramientas del compilador del sistema. Un
caso de uso común en un contexto de investigación es instalar paquetes
desde una sesión de R. Fuera de un entorno de contenedor hay una buena
probabilidad de que la cadena de herramientas del compilador extranjero
y las bibliotecas del sistema incompatibles se encuentren primero, lo
que resulta en binarios incompatibles que no pueden ser utilizados por
R. En un shell de contenedor este problema desaparece, ya que las
bibliotecas del sistema y los ejecutables simplemente no están
disponibles debido al espacio de nombres ‘mount’ no compartido.

   Tomemos un manifiesto exhaustivo que proporciona un entorno de
desarrollo cómodo para su uso con R:

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

             ;; base packages
             "bash-minimal"
             "glibc-locales"
             "nss-certs"

             ;; Herramientas habituales de la línea de comandos, no sea que el contenedor esté demasiado vacío.
             "coreutils"
             "grep"
             "which"
             "wget"
             "sed"

             ;; Herramientas R markdown
             "pandoc"

             ;;Toolchain y bibliotecas comunes para "install.packages"
             "gcc-toolchain@10"
             "gfortran-toolchain"
             "gawk"
             "tar"
             "gzip"
             "unzip"
             "make"
             "cmake"
             "pkg-config"
             "cairo"
             "libxt"
             "openssl"
             "curl"
             "zlib"))

   Vamos a utilizar esto para ejecutar R dentro de un entorno de
contenedor. Por conveniencia compartimos el espacio de nombres ‘net’
para usar las interfaces de red del sistema anfitrión. Ahora podemos
construir paquetes de R desde el código fuente de la forma tradicional
sin tener que preocuparnos por desajustes ABI o incompatibilidades.

     $ guix shell --container --network --manifest=manifest.scm -- R

     R version 4.2.1 (2022-06-23) -- "Funny-Looking Kid"
     © 2022  La base de R para el cálculo estadístico
     ...
     > 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()))
     ...
     * installing *source* package 'Cairo' ...
     ...
     * DONE (Cairo)

     Los paquetes origien descargados están en
     	'/tmp/RtmpCuwdwM/downloaded_packages'
     > library("Cairo", lib=getwd())
     > # logrado!

   Usar shells contenedores es divertido, pero pueden volverse un poco
engorrosos cuando quieres ir más allá de un único proceso interactivo.
Algunas tareas se vuelven mucho más fáciles cuando se asientan sobre la
sólida base de un Sistema Guix adecuado y su rico conjunto de servicios
de sistema. La siguiente sección muestra cómo lanzar un Sistema Guix
completo dentro de un contenedor.


File: guix-cookbook.es.info,  Node: Contenedores de Sistema Guix,  Prev: Contenedores Guix,  Up: Contenedores

4.2 Contenedores de Sistema Guix
================================

The Guix System provides a wide array of interconnected system services
that are configured declaratively to form a dependable stateless GNU
System foundation for whatever tasks you throw at it. Even when using
Guix on a foreign distribution you can benefit from the design of Guix
System by running a system instance as a container. Using the same
kernel features of unshared namespaces mentioned in the previous
section, the resulting Guix System instance is isolated from the host
system and only shares file system locations that you explicitly
declare.

   Un contenedor del Sistema Guix difiere del proceso shell creado por
‘guix shell --container’ en varios aspectos importantes. Mientras que en
un shell contenedor el proceso de contenedor es un proceso shell Bash,
un contenedor Guix System ejecuta el Shepherd como PID 1. En un
contenedor de sistema todos los servicios del sistema (*note
(guix.es)Servicios::) están configurados tal y como lo estarían en un
Sistema Guix en una máquina virtual o en una máquina de metal desnudo -
esto incluye daemons gestionados por GNU Shepherd (*note
(guix.es)Servicios de Shepherd::) así como otros tipos de extensiones
del sistema operativo (*note (guix.es)Composición de servicios::).

   El aumento percibido en la complejidad de ejecutar un contenedor de
Sistema Guix se justifica fácilmente cuando se trata de aplicaciones más
complejas que tienen requisitos más altos o simplemente más rígidos en
sus contextos de ejecución—archivos de configuración, cuentas de usuario
dedicadas, directorios para cachés o archivos de registro, etc. En
Sistema Guix las demandas de este tipo de software se satisfacen
mediante el despliegue de servicios de sistema.

* Menu:

* Un contenedor de base de datos::  Un contenedor de base de datos
* Red de Contenedor::        Red de Contenedor


File: guix-cookbook.es.info,  Node: Un contenedor de base de datos,  Next: Red de Contenedor,  Up: Contenedores de Sistema Guix

4.2.1 Un contenedor de base de datos
------------------------------------

Un buen ejemplo podría ser un servidor de bases de datos PostgreSQL.
Gran parte de la complejidad de configurar un servidor de bases de datos
de este tipo se encapsula en esta declaración de servicio engañosamente
corta:

     (service postgresql-service-type
              (postgresql-configuration
               (postgresql postgresql-14)))

   Una declaración de sistema operativo completa para su uso con un
contenedor Guix System tendría este aspecto:

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

     (operating-system
       (host-name "container")
       (timezone "Europe/Berlin")
       (file-systems (cons (file-system
                             (device (file-system-label "does-not-matter"))
                             (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 "test")
                                 (create-database? #t))))))
               %base-services)))

   Con ‘postgresql-role-service-type’ definimos un rol “prueba” y
creamos una base de datos coincidente, para que podamos probar de
inmediato sin ninguna configuración manual adicional. La configuración
de ‘postgresql-config-file’ permite que un cliente de la dirección IP
10.0.0.1 se conecte sin requerir autenticación–una mala idea en sistemas
de producción, pero conveniente para este ejemplo.

   Vamos a construir un script que lanzará una instancia de este Sistema
Guix como contenedor. Escribe la declaración ‘operating-system’ de
arriba en un archivo ‘os.scm’ y luego usa ‘guix system container’ para
construir el lanzador. (*note (guix)Invocar sistema guix::).

     $ guix system container os.scm
     Se construirán las siguientes derivaciones:
       /gnu/store/...-run-container.drv
       ...
     compilando /gnu/store/...-run-container.drv...
     /gnu/store/...-run-container

   Ahora que tenemos un script lanzador podemos ejecutarlo para generar
el nuevo sistema con un servicio PostgreSQL en ejecución. Tenga en
cuenta que debido a algunas limitaciones aún no resueltas tenemos que
ejecutar el lanzador como usuario root, por ejemplo con ‘sudo’.

     $ sudo /gnu/store/...-run-container
     se ejecuta como PID 5983
     ...

   Ponga el proceso en segundo plano con <Ctrl-z> seguido de ‘bg’.
Observa el ID del proceso en la salida; lo necesitaremos para
conectarnos al contenedor más tarde. ¿Sabes qué? Vamos a intentar
conectarnos al contenedor ahora mismo. Utilizaremos ‘nsenter’, una
herramienta proporcionada por el paquete ‘util-linux’:

     $ guix shell util-linux
     $ sudo nsenter -a -t 5983
     root@container /# pgrep -a postgres
     49 /gnu/store/...-postgresql-14.4/bin/postgres -D /var/lib/postgresql/data --config-file=/gnu/store/...-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

   El servicio PostgreSQL se está ejecutando en el contenedor.


File: guix-cookbook.es.info,  Node: Red de Contenedor,  Prev: Un contenedor de base de datos,  Up: Contenedores de Sistema Guix

4.2.2 Red de Contenedor
-----------------------

¿De qué sirve un Sistema Guix ejecutando un servicio de base de datos
PostgreSQL como contenedor cuando sólo podemos hablar con él con
procesos originados en el contenedor? Sería mucho mejor si pudiéramos
hablar con la base de datos a través de la red.

   La forma más sencilla de hacerlo es crear un par de dispositivos
Ethernet virtuales conectados (conocidos como ‘veth’). Movemos uno de
los dispositivos (‘ceth-test’) al espacio de nombres ‘net’ del
contenedor y dejamos el otro extremo (‘veth-test’) de la conexión en el
sistema anfitrión.

     pid=5983
     ns="guix-test"
     host="veth-test"
     client="ceth-test"

     # Adjunta el nuevo espacio de nombre de red "guix-test" para el PID de contenedor.
     sudo ip netns attach $ns $pid

     # Crea la pareja de dispositivos
     sudo ip link add $host type veth peer name $client

     # Mueve el dispositivo cliente a la red de contenedor del espacio de nombre
     sudo ip link set $client netns $ns

   Entonces configure el lado del hospedaje:

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

   ... y entonces configuramos el lado de cliente:

     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

   En este punto el hospedaje puede alcanzar el contenedor en la
dirección IP 10.0.0.2, y el contenedor puede alcanzar el hospedador en
la IP 10.0.0.1. Esto es todo lo que necesitamos para el servidor de
datos base dentro del contenedor desde el sistema hospedaje en la parte
externa.

     $ psql -h 10.0.0.2 -U test
     psql (14.4)
     Teclee "help" para ayuda

     test=> CREATE TABLE hello (who TEXT NOT NULL);
     CREATE TABLE
     test=> INSERT INTO hello (who) VALUES ('world');
     INSERT 0 1
     test=> SELECT * FROM hello;
       who
     -------
      world
     (1 row)

   Ahora eso está hecho con esta demostración breve::

     sudo kill $pid
     sudo ip netns del $ns
     sudo ip link del $host


File: guix-cookbook.es.info,  Node: Máquinas virtuales,  Next: Gestión avanzada de paquetes,  Prev: Contenedores,  Up: Top

5 Máquinas virtuales
********************

Guix puede producir imágenes de disco (*note (guix)Invoking guix
system::) que pueden ser usadas con soluciones de máquinas virtuales
como virt-manager, GNOME Boxes o la más desnuda QEMU, entre otras.

   El objetivo de este capítulo es proporcionar ejemplos prácticos
relacionados con el uso y la configuración de máquinas virtuales en un
sistema Guix.

* Menu:

* Puente de red para QEMU::  Puente de red para QEMU
* Red enrutada para libvirt::  Red enrutada para libvirt
* Red basada en NAT personal para libvirt::  Red basada en NAT personal para
                                               libvirt
* Referencias: Referencias de MV.  Más lecturas sobre máquinas virtuales.


File: guix-cookbook.es.info,  Node: Puente de red para QEMU,  Next: Red enrutada para libvirt,  Up: Máquinas virtuales

5.1 Puente de red para QEMU
===========================

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 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
‘ping’ do _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.

5.1.1 Creating a network bridge interface
-----------------------------------------

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

     # nmcli con add type bridge con-name br0 ifname br0

   Para que este puente forme parte de su red, debe asociar su puente de
red con la interfaz Ethernet utilizada para conectarse con la red.
Suponiendo que su interfaz se llama ‘enp2s0’, se puede utilizar el
siguiente comando para hacerlo:

     # nmcli con add type bridge-slave ifname enp2s0 master br0

     Importante: Solamente los interfaces Ethernet pueden ser añadidos a
     un puente. Para interfaces sin hilo, considere que la apropiación
     de red de enrrutado en *Note Red enrutada para libvirt::.

   Por defecto, el puente de red permitirá sus invitados que obtenga su
dirección IP por medio de DHCP, si disponible en su red local. Por
simplificar, esto es que usaremos aquí. Para encontrar fácilmente el
invitado, puede ser configurador para advertir su nombres de hospedajes
por medio de mDNS.

5.1.2 Configura el guion ayudante del puente QEMU
-------------------------------------------------

QEMU viene con un programa de ayuda para hacer uso convenientemente de
una interfaz de puente de red como un usuario sin privilegios *note
(QEMU)Opciones de red::. El binario se debe hacer root setuid para un
funcionamiento correcto; esto se puede lograr mediante la adición a la
‘privileged-programs’ campo de su (host) ‘sistema-operativo’ definición,
como se muestra a continuación:

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

   El archivo ‘/etc/qemu/bridge.conf’ también se debe hacer para
permitir la interfaz bridge, ya que el valor predeterminado es denegar
todo. Para ello, añada lo siguiente a la lista de servicios:

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

5.1.3 Invocar QEMU con las opciones de línea de comandos adecuadas
------------------------------------------------------------------

Cuando invoque a QEMU, las siguientes opciones estarían proporcionadas
tales que el puente de red es utilizado, tras haber seleccionado una
dirección MAC única para el invitado.

     Importante: Por defecto, se utiliza una única dirección MAC para
     todos los invitados, a menos que se proporcione. Si no se
     proporcionan direcciones MAC diferentes a cada máquina virtual que
     utilice el puente, se producirán problemas de red.

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

   Para generar direcciones MAC que tienen el prefijo QEMU registrado,
el siguiente fragmento puede ser empleado:

     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

5.1.4 Asuntos de red causados por Docker
----------------------------------------

Si utilizas Docker en su máquina, puede experimentar problemas de
conectividad cuando intente utilizar un puente de red, el cual está
causado por Docker además de confiar en puentes de red y configuración
en sus propias reglas de enrutado. La solución es añadir el siguiente
fragmento de ‘iptables’ a su declaración de ‘sistema-operativo’:

     (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
     "))


File: guix-cookbook.es.info,  Node: Red enrutada para libvirt,  Next: Red basada en NAT personal para libvirt,  Prev: Puente de red para QEMU,  Up: Máquinas virtuales

5.2 Red enrutada para libvirt
=============================

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 (*note Puente de red para QEMU::). In this
case, the next best option is to use a _virtual network switch_ with
static routing and to configure a libvirt-powered virtual machine to use
it (via the ‘virt-manager’ GUI for example). This is similar to the
default mode of operation of QEMU/libvirt, except that instead of using
NAT (Network Address Translation), it relies on static routes to join
the VM (virtual machine) IP address to the 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.

5.2.1 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 libvirt Wiki article on Virtual Networking
(https://wiki.libvirt.org/VirtualNetworking.html) for more details on
the modes of operation, management and implementation of virtual network
switches.

   The ‘virsh’ command, provided by the ‘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
‘192.168.1.0/24’ network, you could opt to use e.g. ‘192.168.2.0/24’.
Define an XML file, e.g. ‘/tmp/virbr0.xml’, containing the following:

     <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>

   Then create and configure the interface using the ‘virsh’ command, as
root:

     virsh net-define /tmp/virbr0.xml
     virsh net-autostart virbr0
     virsh net-start virbr0

   The ‘virbr0’ interface should now be visible e.g. via the ‘ip
address’ command. It will be automatically started every time your
libvirt virtual machine is started.

5.2.2 Configuring the static routes for your virtual bridge
-----------------------------------------------------------

If you configured your virtual machine to use your newly created
‘virbr0’ virtual bridge interface, it should already receive an IP via
DHCP such as ‘192.168.2.15’ and be reachable from the server hosting it,
e.g. via ‘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 ‘192.168.1.0/24’ and the router
configuration web page may be accessible via e.g. the
<http://192.168.1.1> page. On a router running the libreCMC
(https://librecmc.org/) firmware, you would navigate to the Network →
Static Routes page
(<https://192.168.1.1/cgi-bin/luci/admin/network/routes>), and you would
add a new entry to the ‘Static IPv4 Routes’ with the following
information:

‘Interfaz’
     lan
‘Destino’
     192.168.2.0
‘Máscara de red IPv4’
     255.255.255.0
‘Puerta de enlace IPv4’
     SERVER-IP
‘Tipo de enrutamiento’
     unicast

   where 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 ‘ping gnu.org’ to
verify that it functions correctly.


File: guix-cookbook.es.info,  Node: Red basada en NAT personal para libvirt,  Next: Referencias de MV,  Prev: Red enrutada para libvirt,  Up: Máquinas virtuales

5.3 Red basada en NAT personal para libvirt
===========================================

As mentioned in the preceding section (*note Red enrutada para
libvirt::), libvirt allows virtual networks to be defined via XML files
and managed by the ‘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.

5.3.1 Creating the virtual network bridge
-----------------------------------------

The ‘static-networking-service-type’ can be used to create a virtual
network bridge and assign an IP address to it:

     (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")))))))

5.3.2 Running dnsmasq for the virtual network bridge
----------------------------------------------------

The ‘dnsmasq-service-type’ can be used to provide DNS and DHCP for
guests connected to this virtual network switch:

     (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"))))

5.3.3 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 ‘nftables-service-type’ to do this:

     (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\"
       }
     }
     "))))

   Ensure that you have IPv4 forwarding enabled (you can use
‘sysctl-service-type’ for this).


File: guix-cookbook.es.info,  Node: Referencias de MV,  Prev: Red basada en NAT personal para libvirt,  Up: Máquinas virtuales

5.4 Referencias
===============

   • The (unofficial) libvirt Networking Handbook
     (https://jamielinux.com/docs/libvirt-networking-handbook/index.html)
     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.


File: guix-cookbook.es.info,  Node: Gestión avanzada de paquetes,  Next: Desarrollo de software,  Prev: Máquinas virtuales,  Up: Top

6 Gestión avanzada de paquetes
******************************

Guix is a functional package manager that offers many features beyond
what more traditional package managers can do. To the uninitiated, those
features might not have obvious use cases at first. The purpose of this
chapter is to demonstrate some advanced package management concepts.

   *note (guix)Package Management:: for a complete reference.

* Menu:

* Perfiles Guix en práctica::  Estrategias para múltiples perfiles y
                                 declaraciones.


File: guix-cookbook.es.info,  Node: Perfiles Guix en práctica,  Up: Gestión avanzada de paquetes

6.1 Perfiles Guix en práctica
=============================

Guix provides a very useful feature that may be quite foreign to
newcomers: “profiles”. They are a way to group package installations
together and all users on the same system are free to use as many
profiles as they want.

   Whether you’re a developer or not, you may find that multiple
profiles bring you great power and flexibility. While they shift the
paradigm somewhat compared to _traditional package managers_, they are
very convenient to use once you’ve understood how to set them up.

     Nota: This section is an opinionated guide on the use of multiple
     profiles. It predates ‘guix shell’ and its fast profile cache
     (*note (guix)Invoking guix shell::).

     In many cases, you may find that using ‘guix shell’ to set up the
     environment you need, when you need it, is less work that
     maintaining a dedicated profile. Your call!

   If you are familiar with Python’s ‘virtualenv’, you can think of a
profile as a kind of universal ‘virtualenv’ that can hold any kind of
software whatsoever, not just Python software. Furthermore, profiles are
self-sufficient: they capture all the runtime dependencies which
guarantees that all programs within a profile will always work at any
point in time.

   Multiple profiles have many benefits:

   • Clean semantic separation of the various packages a user needs for
     different contexts.

   • Multiple profiles can be made available into the environment either
     on login or within a dedicated shell.

   • Profiles can be loaded on demand. For instance, the user can use
     multiple shells, each of them running different profiles.

   • Isolation: Programs from one profile will not use programs from the
     other, and the user can even install different versions of the same
     programs to the two profiles without conflict.

   • Deduplication: Profiles share dependencies that happens to be the
     exact same. This makes multiple profiles storage-efficient.

   • Reproducible: when used with declarative manifests, a profile can
     be fully specified by the Guix commit that was active when it was
     set up. This means that the exact same profile can be set up
     anywhere and anytime
     (https://guix.gnu.org/blog/2018/multi-dimensional-transactions-and-rollbacks-oh-my/),
     with just the commit information. See the section on *note Perfiles
     reproducibles::.

   • Easier upgrades and maintenance: Multiple profiles make it easy to
     keep package listings at hand and make upgrades completely
     frictionless.

   Concretely, here follows some typical profiles:

   • The dependencies of a project you are working on.

   • Your favourite programming language libraries.

   • Laptop-specific programs (like ‘powertop’) that you don’t need on a
     desktop.

   • TeXlive (this one can be really useful when you need to install
     just one package for this one document you’ve just received over
     email).

   • Games.

   Let’s dive in the set up!

* Menu:

* Configuración base con declaraciones::  Configuración base con
                                            declaraciones
* Paquetes requeridos::      Paquetes requeridos
* Perfil por defecto::       Perfil por defecto
* Los beneficios de declaraciones::  Los beneficios de declaraciones
* Perfiles reproducibles::   Perfiles reproducibles


File: guix-cookbook.es.info,  Node: Configuración base con declaraciones,  Next: Paquetes requeridos,  Up: Perfiles Guix en práctica

6.1.1 Configuración base con declaraciones
------------------------------------------

A Guix profile can be set up via a “manifest”. A manifest is a snippet
of Scheme code that specifies the set of packages you want to have in
your profile; it looks like this:

     (specifications->manifest
       '("package-1"
         ;; Version 1.3 of package-2.
         "package-2@1.3"
         ;; The "lib" output of package-3.
         "package-3:lib"
         ; ...
         "package-N"))

   *Note (guix)Writing Manifests::, for more information about the
syntax.

   We can create a manifest specification per profile and install them
this way:

     GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles
     mkdir -p "$GUIX_EXTRA_PROFILES"/my-project # if it does not exist yet
     guix package --manifest=/path/to/guix-my-project-manifest.scm \
      --profile="$GUIX_EXTRA_PROFILES"/my-project/my-project

   Here we set an arbitrary variable ‘GUIX_EXTRA_PROFILES’ to point to
the directory where we will store our profiles in the rest of this
article.

   Placing all your profiles in a single directory, with each profile
getting its own sub-directory, is somewhat cleaner. This way, each
sub-directory will contain all the symlinks for precisely one profile.
Besides, “looping over profiles” becomes obvious from any programming
language (e.g. a shell script) by simply looping over the
sub-directories of ‘$GUIX_EXTRA_PROFILES’.

   Note that it’s also possible to loop over the output of

     guix package --list-profiles

   although you’ll probably have to filter out ‘~/.config/guix/current’.

   To enable all profiles on login, add this to your ‘~/.bash_profile’
(or similar):

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

   Note to Guix System users: the above reflects how your default
profile ‘~/.guix-profile’ is activated from ‘/etc/profile’, that latter
being loaded by ‘~/.bashrc’ by default.

   You can obviously choose to only enable a subset of them:

     for i in "$GUIX_EXTRA_PROFILES"/my-project-1 "$GUIX_EXTRA_PROFILES"/my-project-2; do
       profile=$i/$(basename "$i")
       if [ -f "$profile"/etc/profile ]; then
         GUIX_PROFILE="$profile"
         . "$GUIX_PROFILE"/etc/profile
       fi
       unset profile
     done

   When a profile is off, it’s straightforward to enable it for an
individual shell without "polluting" the rest of the user session:

     GUIX_PROFILE="path/to/my-project" ; . "$GUIX_PROFILE"/etc/profile

   The key to enabling a profile is to _source_ its ‘etc/profile’ file.
This file contains shell code that exports the right environment
variables necessary to activate the software contained in the profile.
It is built automatically by Guix and meant to be sourced. It contains
the same variables you would get if you ran:

     guix package --search-paths=prefix --profile=$my_profile"

   Once again, see *note (guix)Invoking guix package:: for the command
line options.

   To upgrade a profile, simply install the manifest again:

     guix package -m /path/to/guix-my-project-manifest.scm \
      -p "$GUIX_EXTRA_PROFILES"/my-project/my-project

   To upgrade all profiles, it’s easy enough to loop over them. For
instance, assuming your manifest specifications are stored in
‘~/.guix-manifests/guix-$profile-manifest.scm’, with ‘$profile’ being
the name of the profile (e.g. "project1"), you could do the following in
Bourne shell:

     for profile in "$GUIX_EXTRA_PROFILES"/*; do
       guix package --profile="$profile" \
        --manifest="$HOME/.guix-manifests/guix-$profile-manifest.scm"
     done

   Each profile has its own generations:

     guix package -p "$GUIX_EXTRA_PROFILES"/my-project/my-project --list-generations

   You can roll-back to any generation of a given profile:

     guix package -p "$GUIX_EXTRA_PROFILES"/my-project/my-project --switch-generations=17

   Finally, if you want to switch to a profile without inheriting from
the current environment, you can activate it from an empty shell:

     env -i $(which bash) --login --noprofile --norc
     . my-project/etc/profile


File: guix-cookbook.es.info,  Node: Paquetes requeridos,  Next: Perfil por defecto,  Prev: Configuración base con declaraciones,  Up: Perfiles Guix en práctica

6.1.2 Paquetes requeridos
-------------------------

Activating a profile essentially boils down to exporting a bunch of
environmental variables. This is the role of the ‘etc/profile’ within
the profile.

   _Note: Only the environmental variables of the packages that consume
them will be set._

   For instance, ‘MANPATH’ won’t be set if there is no consumer
application for man pages within the profile. So if you need to
transparently access man pages once the profile is loaded, you’ve got
two options:

   • Either export the variable manually, e.g.
          export MANPATH=/path/to/profile${MANPATH:+:}$MANPATH

   • Or include ‘man-db’ to the profile manifest.

   The same is true for ‘INFOPATH’ (you can install ‘info-reader’),
‘PKG_CONFIG_PATH’ (install ‘pkg-config’), etc.


File: guix-cookbook.es.info,  Node: Perfil por defecto,  Next: Los beneficios de declaraciones,  Prev: Paquetes requeridos,  Up: Perfiles Guix en práctica

6.1.3 Perfil por defecto
------------------------

What about the default profile that Guix keeps in ‘~/.guix-profile’?

   You can assign it the role you want. Typically you would install the
manifest of the packages you want to use all the time.

   Alternatively, you could keep it “manifest-less” for throw-away
packages that you would just use for a couple of days. This way makes it
convenient to run

     guix install package-foo
     guix upgrade package-bar

   without having to specify the path to a profile.


File: guix-cookbook.es.info,  Node: Los beneficios de declaraciones,  Next: Perfiles reproducibles,  Prev: Perfil por defecto,  Up: Perfiles Guix en práctica

6.1.4 Los beneficios de declaraciones
-------------------------------------

Manifests let you “declare” the set of packages you’d like to have in a
profile (*note (guix)Writing Manifests::). They are a convenient way to
keep your package lists around and, say, to synchronize them across
multiple machines using a version control system.

   A common complaint about manifests is that they can be slow to
install when they contain large number of packages. This is especially
cumbersome when you just want get an upgrade for one package within a
big manifest.

   This is one more reason to use multiple profiles, which happen to be
just perfect to break down manifests into multiple sets of semantically
connected packages. Using multiple, small profiles provides more
flexibility and usability.

   Manifests come with multiple benefits. In particular, they ease
maintenance:

   • When a profile is set up from a manifest, the manifest itself is
     self-sufficient to keep a “package listing” around and reinstall
     the profile later or on a different system. For ad-hoc profiles, we
     would need to generate a manifest specification manually and
     maintain the package versions for the packages that don’t use the
     default version.

   • ‘guix package --upgrade’ always tries to update the packages that
     have propagated inputs, even if there is nothing to do. Guix
     manifests remove this problem.

   • When partially upgrading a profile, conflicts may arise (due to
     diverging dependencies between the updated and the non-updated
     packages) and they can be annoying to resolve manually. Manifests
     remove this problem altogether since all packages are always
     upgraded at once.

   • As mentioned above, manifests allow for reproducible profiles,
     while the imperative ‘guix install’, ‘guix upgrade’, etc. do not,
     since they produce different profiles every time even when they
     hold the same packages. See the related discussion on the matter
     (https://issues.guix.gnu.org/issue/33285).

   • Manifest specifications are usable by other ‘guix’ commands. For
     example, you can run ‘guix weather -m manifest.scm’ to see how many
     substitutes are available, which can help you decide whether you
     want to try upgrading today or wait a while. Another example: you
     can run ‘guix pack -m manifest.scm’ to create a pack containing all
     the packages in the manifest (and their transitive references).

   • Finally, manifests have a Scheme representation, the ‘<manifest>’
     record type. They can be manipulated in Scheme and passed to the
     various Guix APIs (https://en.wikipedia.org/wiki/Api).

   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 (*note (guix)Invoking guix gc::) and
ensures that they will still be available at any point in the future.
The ‘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 ‘GUIX_PROFILE=/the/profile; .
"$GUIX_PROFILE"/etc/profile’ as explained above: this guarantees that
our hacking environment will be available at all times.

   _Security warning:_ While keeping old profiles around can be
convenient, keep in mind that outdated packages may not have received
the latest security fixes.


File: guix-cookbook.es.info,  Node: Perfiles reproducibles,  Prev: Los beneficios de declaraciones,  Up: Perfiles Guix en práctica

6.1.5 Perfiles reproducibles
----------------------------

To reproduce a profile bit-for-bit, we need two pieces of information:

   • a manifest (*note (guix)Writing Manifests::);
   • a Guix channel specification (*note (guix)Replicating Guix::).

   Indeed, manifests alone might not be enough: different Guix versions
(or different channels) can produce different outputs for a given
manifest.

   You can output the Guix channel specification with ‘guix describe
--format=channels’ (*note (guix)Invoking guix describe::). Save this to
a file, say ‘channel-specs.scm’.

   On another computer, you can use the channel specification file and
the manifest to reproduce the exact same profile:

     GUIX_EXTRA_PROFILES=$HOME/.guix-extra-profiles
     GUIX_EXTRA=$HOME/.guix-extra

     mkdir -p "$GUIX_EXTRA"/my-project
     guix pull --channels=channel-specs.scm --profile="$GUIX_EXTRA/my-project/guix"

     mkdir -p "$GUIX_EXTRA_PROFILES/my-project"
     "$GUIX_EXTRA"/my-project/guix/bin/guix package \
      --manifest=/path/to/guix-my-project-manifest.scm \
      --profile="$GUIX_EXTRA_PROFILES"/my-project/my-project

   It’s safe to delete the Guix channel profile you’ve just installed
with the channel specification, the project profile does not depend on
it.


File: guix-cookbook.es.info,  Node: Desarrollo de software,  Next: Gestión del entorno,  Prev: Gestión avanzada de paquetes,  Up: Top

7 Desarrollo de software
************************

Guix is a handy tool for developers; ‘guix shell’, in particular, gives
a standalone development environment for your package, no matter what
language(s) it’s written in (*note (guix)Invoking guix shell::). 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 ‘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 ‘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(1).

* Menu:

* Empezando::                Paso 0: utilizar ‘guix shell’.
* Compilar con Guix::        Paso 1: compilar su código.
* El repositorio como un canal::  Paso 2: ajustar el repo en un canal.
* Variantes de paquetes::    Bono: definir variantes.
* Configurar Integración Continua::  Paso 3: integración continua.
* Compilar manifiesto::      Bono: Manifiesto.
* Cobertura::                Resumen.

   ---------- Footnotes ----------

   (1) This chapter is adapted from a blog post
(https://guix.gnu.org/en/blog/2023/from-development-environments-to-continuous-integrationthe-ultimate-guide-to-software-development-with-guix/)
published in June 2023 on the Guix web site.


File: guix-cookbook.es.info,  Node: Empezando,  Next: Compilar con Guix,  Up: Desarrollo de software

7.1 Empezando
=============

How do we go about “Guixifying” a repository? The first step, as we’ve
seen, will be to add a ‘guix.scm’ at the root of the repository in
question. We’ll take Guile (https://www.gnu.org/software/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 ‘guix.scm’
looks like the usual package definition (*note (guix)Defining
Packages::), just without the ‘define-public’ bit:

     ;; 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+))

   Quite a bit of boilerplate, but now someone who’d like to hack on
Guile now only needs to run:

     guix shell

   That gives them a shell containing all the dependencies of Guile:
those listed above, but also _implicit dependencies_ such as the GCC
tool chain, GNU Make, sed, grep, and so on. *Note (guix)Invoking guix
shell::, for more info on ‘guix shell’.

     The chef’s recommendation: Our suggestion is to create development
     environments like this:

          guix shell --container --link-profile

     ... or, for short:

          guix shell -CP

     That gives a shell in an isolated container, and all the
     dependencies show up in ‘$HOME/.guix-profile’, which plays well
     with caches such as ‘config.cache’ (*note (autoconf)Cache Files::)
     and absolute file names recorded in generated ‘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.


File: guix-cookbook.es.info,  Node: Compilar con Guix,  Next: El repositorio como un canal,  Prev: Empezando,  Up: Desarrollo de software

7.2 Level 1: Building with Guix
===============================

Now that we have a package definition (*note Empezando::), why not also
take advantage of it so we can build Guile with Guix? We had left the
‘source’ field empty, because ‘guix shell’ above only cares about the
_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 ‘source’
field, along these lines:

     (use-modules (guix)
                  (guix git-download)  ;for ‘git-predicate’
                  ...)

     (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?))
       ...)

   Here’s what we changed compared to the previous section:

  1. We added ‘(guix git-download)’ to our set of imported modules, so
     we can use its ‘git-predicate’ procedure.
  2. We defined ‘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.
  3. We set ‘source’ to a ‘local-file’
     (https://guix.gnu.org/manual/devel/en/html_node/G_002dExpressions.html#index-local_002dfile)—a
     recursive copy of the current directory (‘"."’), limited to files
     under version control (the ‘#:select?’ bit).

   From there on, our ‘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:

     guix build -f guix.scm

   But you can also build for another system (possibly after setting up
*note offloading: (guix)Daemon Offload Setup. or *note transparent
emulation: (guix)Virtualization Services.):

     guix build -f guix.scm -s aarch64-linux -s riscv64-linux

... or cross-compile:

     guix build -f guix.scm --target=x86_64-w64-mingw32

   You can also use “package transformations” to test package variants
(*note (guix)Package Transformation Options::):

     # 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

   Handy!


File: guix-cookbook.es.info,  Node: El repositorio como un canal,  Next: Variantes de paquetes,  Prev: Compilar con Guix,  Up: Desarrollo de software

7.3 Level 2: The Repository as a Channel
========================================

We now have a Git repository containing (among other things) a package
definition (*note Compilar con Guix::). Can’t we turn it into a
“channel” (*note (guix)Channels::)? After all, channels are designed to
ship package definitions to users, and that’s exactly what we’re doing
with our ‘guix.scm’.

   Turns out we can indeed turn it into a channel, but with one caveat:
we must create a separate directory for the ‘.scm’ file(s) of our
channel so that ‘guix pull’ doesn’t load unrelated ‘.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 ‘guix.scm’ symlink for the sake of
‘guix shell’:

     mkdir -p .guix/modules
     mv guix.scm .guix/modules/guile-package.scm
     ln -s .guix/modules/guile-package.scm guix.scm

   To make it usable as part of a channel, we need to turn our
‘guix.scm’ file into a “package module” (*note (guix)Package Modules::):
we do that by changing the ‘use-modules’ form at the top to a
‘define-module’ form. We also need to actually _export_ a package
variable, with ‘define-public’, while still returning the package value
at the end of the file so we can still use ‘guix shell’ and ‘guix build
-f guix.scm’. The end result looks like this (not repeating things that
haven’t changed):

     (define-module (guile-package)
       #:use-module (guix)
       #:use-module (guix git-download)   ;for ‘git-predicate’
       ...)

     (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?))
         ...))

     ;; Return the package object define above at the end of the module.
     guile

   We need one last thing: a ‘.guix-channel’ file
(https://guix.gnu.org/manual/devel/en/html_node/Package-Modules-in-a-Sub_002ddirectory.html)
so Guix knows where to look for package modules in our repository:

     ;; This file lets us present this repo as a Guix channel.

     (channel
       (version 0)
       (directory ".guix/modules"))  ;look for package modules under .guix/modules/

   To recap, we now have these files:

     .
     ├── .guix-channel
     ├── guix.scm → .guix/modules/guile-package.scm
     └── .guix
         └── modules
            └── guile-package.scm

   And that’s it: we have a channel! (We could do better and support
_channel authentication_
(https://guix.gnu.org/manual/devel/en/html_node/Specifying-Channel-Authorizations.html)
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
adding it to ‘~/.config/guix/channels.scm’
(https://guix.gnu.org/manual/devel/en/html_node/Specifying-Additional-Channels.html),
along these lines:

     (append (list (channel
                     (name 'guile)
                     (url "https://git.savannah.gnu.org/git/guile.git")
                     (branch "main")))
             %default-channels)

   After running ‘guix pull’, we can see the new package:

     $ 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
     [...]
     /gnu/store/axnzbl89yz7ld78bmx72vpqp802dwsar-guile-3.0.99-git-debug
     /gnu/store/r34gsij7f0glg2fbakcmmk0zn4v62s5w-guile-3.0.99-git

   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 ‘guix pack’
(*note (guix)Invoking guix pack::):

     # 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


File: guix-cookbook.es.info,  Node: Variantes de paquetes,  Next: Configurar Integración Continua,  Prev: El repositorio como un canal,  Up: Desarrollo de software

7.4 Bonus: Package Variants
===========================

We now have an actual channel, but it contains only one package (*note
El repositorio como un canal::). While we’re at it, we can define
“package variants” (*note (guix)Defining Package Variants::) in our
‘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:

     ;; This is the ‘.guix/modules/guile-package.scm’ file.

     (define-module (guile-package)
       ...)

     (define-public guile
       ...)

     (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

   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:

     guix build -L $PWD/.guix/modules guile-without-threads


File: guix-cookbook.es.info,  Node: Configurar Integración Continua,  Next: Compilar manifiesto,  Prev: Variantes de paquetes,  Up: Desarrollo de software

7.5 Level 3: Setting Up Continuous Integration
==============================================

The channel we defined above (*note El repositorio como un canal::)
becomes even more interesting once we set up “continuous integration”
(https://en.wikipedia.org/wiki/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:

     guix build -L $PWD/.guix/modules guile@3.0.99-git

   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 Cuirass
(https://guix.gnu.org/en/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 (*note (guix)Continuous
Integration::). Going back to our example, we give Cuirass a spec file
that goes like this:

     ;; 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))))

   It differs from what you’d do with other CI tools in two important
ways:

   • Cuirass knows it’s tracking _two_ channels, ‘guile’ and ‘guix’.
     Indeed, our own ‘guile’ package depends on many packages provided
     by the ‘guix’ channel—GCC, the GNU libc, libffi, and so on. Changes
     to packages from the ‘guix’ channel can potentially influence our
     ‘guile’ build and this is something we’d like to see as soon as
     possible as Guile developers.
   • Build results are not thrown away: they can be distributed as
     “substitutes” so that users of our ‘guile’ channel transparently
     get pre-built binaries! (*note (guix)Substitutes::, for background
     info on substitutes.)

   From a developer’s viewpoint, the end result is this status page
(https://ci.guix.gnu.org/jobset/guile) listing _evaluations_: each
evaluation is a combination of commits of the ‘guix’ and ‘guile’
channels providing a number of _jobs_—one job per package defined in
‘guile-package.scm’ times the number of target architectures.

   As for substitutes, they come for free! As an example, since our
‘guile’ jobset is built on ci.guix.gnu.org, which runs ‘guix publish’
(*note (guix)Invoking guix publish::) in addition to Cuirass, one
automatically gets substitutes for ‘guile’ builds from ci.guix.gnu.org;
no additional work is needed for that.


File: guix-cookbook.es.info,  Node: Compilar manifiesto,  Next: Cobertura,  Prev: Configurar Integración Continua,  Up: Desarrollo de software

7.6 Bonus: Build manifest
=========================

The Cuirass spec above is convenient: it builds every package in our
channel, which includes a few variants (*note Configurar Integración
Continua::). 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 “manifest” (*note (guix)Writing
Manifests::). The one we have for Guile has entries for the package
variants we defined above, as well as additional variants and cross
builds:

     ;; 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))

   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:

     ;; 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))))

   We changed the ‘(build ...)’ part of the spec to ‘'(manifest
".guix/manifest.scm")’ so that it would pick our manifest, and that’s
it!


File: guix-cookbook.es.info,  Node: Cobertura,  Prev: Compilar manifiesto,  Up: Desarrollo de software

7.7 Cobertura
=============

We picked Guile as the running example in this chapter and you can see
the result here:

   • ‘.guix-channel’
     (https://git.savannah.gnu.org/cgit/guile.git/tree/.guix-channel?id=cd57379b3df636198d8cd8e76c1bfbc523762e79);
   • ‘.guix/modules/guile-package.scm’
     (https://git.savannah.gnu.org/cgit/guile.git/tree/.guix/modules/guile-package.scm?id=cd57379b3df636198d8cd8e76c1bfbc523762e79)
     with the top-level ‘guix.scm’ symlink;
   • ‘.guix/manifest.scm’
     (https://git.savannah.gnu.org/cgit/guile.git/tree/.guix/manifest.scm?id=cd57379b3df636198d8cd8e76c1bfbc523762e79).

   These days, repositories are commonly peppered with dot files for
various tools: ‘.envrc’, ‘.gitlab-ci.yml’, ‘.github/workflows’,
‘Dockerfile’, ‘.buildpacks’, ‘Aptfile’, ‘requirements.txt’, and whatnot.
It may sound like we’re proposing a bunch of _additional_ files, but in
fact those files are expressive enough to _supersede_ most or all of
those listed above.

   With a couple of files, we get support for:

   • development environments (‘guix shell’);
   • pristine test builds, including for package variants and for
     cross-compilation (‘guix build’);
   • continuous integration (with Cuirass or with some other tool);
   • continuous delivery to users (_via_ the channel and with pre-built
     binaries);
   • generation of derivative build artifacts such as Docker images or
     Deb/RPM packages (‘guix pack’).

   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!


File: guix-cookbook.es.info,  Node: Gestión del entorno,  Next: Reproducible Research,  Prev: Desarrollo de software,  Up: Top

8 Gestión del entorno
*********************

Guix provides multiple tools to manage environment. This chapter
demonstrate such utilities.

* Menu:

* Entorno Guix por direnv::  Configurar entorno Guix con direnv


File: guix-cookbook.es.info,  Node: Entorno Guix por direnv,  Up: Gestión del entorno

8.1 Entorno Guix por direnv
===========================

Guix provides a ‘direnv’ package, which could extend shell after
directory change. This tool could be used to prepare a pure Guix
environment.

   The following example provides a shell function for ‘~/.direnvrc’
file, which could be used from Guix Git repository in
‘~/src/guix/.envrc’ file to setup a build environment similar to
described in *note (guix)Building from Git::.

   Create a ‘~/.direnvrc’ with a Bash code:

     # Thanks <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
         # Notice that we add shell variables to the function trigger.
         echo "$name \$*" >> "$target"
         chmod +x "$target"
       fi
     }

     use_guix()
     {
         # Set GitHub token.
         export GUIX_GITHUB_TOKEN="xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

         # Unset 'GUIX_PACKAGE_PATH'.
         export GUIX_PACKAGE_PATH=""

         # Recreate a garbage collector root.
         gcroots="$HOME/.config/guix/gcroots"
         mkdir -p "$gcroots"
         gcroot="$gcroots/guix"
         if [ -L "$gcroot" ]
         then
             rm -v "$gcroot"
         fi

         # Miscellaneous packages.
         PACKAGES_MAINTENANCE=(
             direnv
             git
             git:send-email
             git-cal
             gnupg
             guile-colorized
             guile-readline
             less
             ncurses
             openssh
             xdot
         )

         # Environment packages.
         PACKAGES=(help2man guile-sqlite3 guile-gcrypt)

         # Thanks <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[@]} "$@")"

         # Predefine configure flags.
         configure()
         {
             ./configure
         }
         export_function configure

         # Run make and optionally build something.
         build()
         {
             make -j 2
             if [ $# -gt 0 ]
             then
                 ./pre-inst-env guix build "$@"
             fi
         }
         export_function build

         # Predefine push Git command.
         push()
         {
             git push --set-upstream origin
         }
         export_function push

         clear                        # Clean up the screen.
         git-cal --author='Your Name' # Show contributions calendar.

         # Show commands help.
         echo "
     build          build a package or just a project if no argument provided
     configure      run ./configure with predefined parameters
     push           push to upstream Git repository
     "
     }

   Every project containing ‘.envrc’ with a string ‘use guix’ will have
predefined environment variables and procedures.

   Run ‘direnv allow’ to setup the environment for the first time.


File: guix-cookbook.es.info,  Node: Reproducible Research,  Next: Instalación de Guix en un clúster,  Prev: Gestión del entorno,  Up: Top

9 Using Guix for Reproducible Research
**************************************

Because it supports reproducible deployment, Guix is a solid foundation
for “reproducible research workflows”. This section is targeted at
scientists; it shows how to add Guix to one’s reproducible research
toolbox(1).

   With Guix as the basis of your computational workflow, you can get
what’s in essence _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.

   ---------- Footnotes ----------

   (1) This chapter is adapted from a blog post published on the
Guix-HPC web site in 2023.
(https://hpc.guix.info/blog/2023/06/a-guide-to-reproducible-research-papers/).


File: guix-cookbook.es.info,  Node: Setting Up the Environment,  Next: Recording the Environment,  Up: Reproducible Research

9.1 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 (*note (guix)Invoking guix shell::):

     guix shell -C python python-numpy -- python3 ./myscript.py

   The ‘-C’ flag here (or ‘--container’) instructs ‘guix shell’ to
create that environment in an isolated container with nothing but the
two packages you asked for. That way, if ‘./myscript.py’ needs more than
these two packages, it’ll fail to run and you’ll immediately notice. On
some systems ‘--container’ is not supported; in that case, you can
resort to ‘--pure’ instead.

   Perhaps you’ll find that you also need Pandas and add it to the
environment:

     guix shell -C python python-numpy python-pandas -- \
       python3 ./myscript.py

   If you fail to guess the name of the package (this one was easy!),
try ‘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:

     guix shell -C gcc-toolchain cmake coreutils grep sed make -- ...

   Or perhaps you’ll find that you could just as well provide a package
definition for your code—*note (guix)Defining Packages::, to learn more
on how to do that.

   Eventually, you’ll have a list of packages that satisfies your needs.

     What if a package is missing?: Guix and the main scientific
     channels provide about tens of thousands of packages
     (https://hpc.guix.info/browse). 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 (*note
     (guix)Defining Packages::) in a dedicated channel of yours (*note
     (guix)Creating a Channel::). For software in Python, R, and other
     high-level languages, most of the work can usually be automated by
     using ‘guix import’ (*note (guix)Invoking guix import::).

     Join the friendly Guix community (https://guix.gnu.org/contact/) to
     get help!


File: guix-cookbook.es.info,  Node: Recording the Environment,  Next: Ensuring Long-Term Source Code Archiving,  Prev: Setting Up the Environment,  Up: Reproducible Research

9.2 Step 2: Recording the Environment
=====================================

Now that you have that ‘guix shell’ command line with a list of
packages, the best course of action is to save it in a _manifest_
file—essentially a software bill of materials—that Guix can then ingest
(*note (guix)Writing Manifests::). The easiest way to get started is by
“translating” your command line into a manifest:

     guix shell python python-numpy python-pandas \
       --export-manifest > manifest.scm

   Put that manifest under version control! From there anyone can
redeploy the software environment described by the manifest and run code
in that environment:

     guix shell -C -m manifest.scm -- python3 ./myscript.py

   Here’s what ‘manifest.scm’ reads:

     ;; 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"))

   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 _pin Guix
itself_ , by capturing the current Guix channel commits with ‘guix
describe’ (*note (guix)Replicating Guix::):

     guix describe -f channels > channels.scm

   This ‘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, _at any time and on any
machine_, can now reproduce the exact same environment by running:

     guix time-machine -C channels.scm -- \
       shell -C -m manifest.scm -- \
       python3 ./myscript.py

   In this example we rely solely on the ‘guix’ channel, which provides
the Python packages we need. Perhaps some of the packages you need live
in other channels (https://hpc.guix.info/channels)—maybe ‘guix-cran’ if
you use R, maybe ‘guix-science’. That’s fine: ‘guix describe’ also
captures that.

   Of course do include a ‘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 _similar_
environment using different tools. It should probably be presented as
such, with the understanding that the only way to get the _same_
environment is to use Guix.


File: guix-cookbook.es.info,  Node: Ensuring Long-Term Source Code Archiving,  Next: Referencing the Software Environment,  Prev: Recording the Environment,  Up: Reproducible Research

9.3 Step 3: Ensuring Long-Term Source Code Archiving
====================================================

We insisted on version control before: for the ‘manifest.scm’ and
‘channels.scm’ files, but of course also for your own code. Our
recommendation is to have these two ‘.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. Software Heritage
(https://www.softwareheritage.org/) (SWH for short) is _the_ solution
for this: SWH archives public source code and provides unique intrinsic
identifiers to refer to it—“SWHIDs” (https://swhid.org). Guix itself is
connected to SWH (https://doi.org/10.1145/3641525.3663622) 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 Save Code Now
(https://archive.softwareheritage.org/save/) interface. SWH will process
the request asynchronously and eventually you’ll find your code has made
it into the archive (https://archive.softwareheritage.org/).


File: guix-cookbook.es.info,  Node: Referencing the Software Environment,  Prev: Ensuring Long-Term Source Code Archiving,  Up: Reproducible Research

9.4 Step 4: Referencing the Software Environment
================================================

This brings us to the last step: referring to our code _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 SWH’s own guide
(https://www.softwareheritage.org/howto-archive-and-reference-your-code/),
we’ll pick an ‘swh:dir’ kind of identifier, which refers to the
directory of the relevant revision/commit of our repository, and we’ll
keep _contextual info_ for clarity—that includes the original URL.
Putting it all together, we’ll conclude our paper with a sentence along
these lines:

     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
     ‘swh:1:dir:cc8919d7705fbaa31efa677ce00bef7eb374fb80;origin=https://gitlab.inria.fr/lcourtes-phd/edcc-2006-redone;visit=swh:1:snp:71a4d08ef4a2e8455b67ef0c6b82349e82870b46;anchor=swh:1:rev:36fde7e5ba289c4c3e30d9afccebbe0cfe83853a’
     (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).

   With this information, the reader can:

   • get the source code;
   • reproduce its software environment with ‘guix time-machine’ and run
     the code;
   • inspect and possibly modify both the code and its environment.

   Mission accomplished!


File: guix-cookbook.es.info,  Node: Instalación de Guix en un clúster,  Next: Gestión del sistema Guix,  Prev: Reproducible Research,  Up: Top

10 Instalación de Guix en un clúster
************************************

Guix is appealing to scientists and HPC (high-performance computing)
practitioners: it makes it easy to deploy potentially complex software
stacks, and it lets you do so in a reproducible fashion—you can redeploy
the exact same software on different machines and at different points in
time.

   In this chapter we look at how a cluster sysadmin can install Guix
for system-wide use, such that it can be used on all the cluster nodes,
and discuss the various tradeoffs(1).

     Nota: Here we assume that the cluster is running a GNU/Linux distro
     other than Guix System and that we are going to install Guix on top
     of it.

* Menu:

* Configurar un nodo de cabecera::  El nodo que ejecuta el daemon.
* Configurar nodos de cálculo::  Nodos cliente.
* Acceso a red de racimo::   Tratando con restricciones de acceso a red.
* Empleo del disco en racimo::  Consideraciones de uso del disco.
* Consideraciones de seguridad del racimo::  Conservar el racimo seguro.

   ---------- Footnotes ----------

   (1) This chapter is adapted from a blog post published on the
Guix-HPC web site in 2017
(https://hpc.guix.info/blog/2017/11/installing-guix-on-a-cluster/).


File: guix-cookbook.es.info,  Node: Configurar un nodo de cabecera,  Next: Configurar nodos de cálculo,  Up: Instalación de Guix en un clúster

10.1 Configurar un nodo de cabecera
===================================

The recommended approach is to set up one _head node_ running
‘guix-daemon’ and exporting ‘/gnu/store’ over NFS to compute nodes.

   Remember that ‘guix-daemon’ is responsible for spawning build
processes and downloads on behalf of clients (*note (guix)Invoking
guix-daemon::), and more generally accessing ‘/gnu/store’, which
contains all the package binaries built by all the users (*note
(guix)The Store::). “Client” here refers to all the Guix commands that
users see, such as ‘guix install’. On a cluster, these commands may be
running on the compute nodes and we’ll want them to talk to the head
node’s ‘guix-daemon’ instance.

   To begin with, the head node can be installed following the usual
binary installation instructions (*note (guix)Binary Installation::).
Thanks to the installation script, this should be quick. Once
installation is complete, we need to make some adjustments.

   Since we want ‘guix-daemon’ to be reachable not just from the head
node but also from the compute nodes, we need to arrange so that it
listens for connections over TCP/IP. To do that, we’ll edit the systemd
startup file for ‘guix-daemon’,
‘/etc/systemd/system/guix-daemon.service’, and add a ‘--listen’ argument
to the ‘ExecStart’ line so that it looks something like this:

     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

   For these changes to take effect, the service needs to be restarted:

     systemctl daemon-reload
     systemctl restart guix-daemon

     Nota: The ‘--listen=0.0.0.0’ bit means that ‘guix-daemon’ will
     process _all_ incoming TCP connections on port 44146 (*note
     (guix)Invoking guix-daemon::). This is usually fine in a cluster
     setup where the head node is reachable exclusively from the
     cluster’s local area network—you don’t want that to be exposed to
     the Internet!

   The next step is to define our NFS exports in ‘/etc/exports’
(https://linux.die.net/man/5/exports) by adding something along these
lines:

     /gnu/store    *(ro)
     /var/guix     *(rw, async)
     /var/log/guix *(ro)

   The ‘/gnu/store’ directory can be exported read-only since only
‘guix-daemon’ on the master node will ever modify it. ‘/var/guix’
contains _user profiles_ as managed by ‘guix package’; thus, to allow
users to install packages with ‘guix package’, this must be read-write.

   Users can create as many profiles as they like in addition to the
default profile, ‘~/.guix-profile’. For instance, ‘guix package -p
~/dev/python-dev -i python’ installs Python in a profile reachable from
the ‘~/dev/python-dev’ symlink. To make sure that this profile is
protected from garbage collection—i.e., that Python will not be removed
from ‘/gnu/store’ while this profile exists—, _home directories should
be mounted on the head node_ as well so that ‘guix-daemon’ knows about
these non-standard profiles and avoids collecting software they refer
to.

   It may be a good idea to periodically remove unused bits from
‘/gnu/store’ by running ‘guix gc’ (*note (guix)Invoking guix gc::). This
can be done by adding a crontab entry on the head node:

     root@master# crontab -e

... with something like this:

     # Every day at 5AM, run the garbage collector to make sure
     # at least 10 GB are free on /gnu/store.
     0 5 * * 1  /usr/local/bin/guix gc -F10G

   We’re done with the head node! Let’s look at compute nodes now.


File: guix-cookbook.es.info,  Node: Configurar nodos de cálculo,  Next: Acceso a red de racimo,  Prev: Configurar un nodo de cabecera,  Up: Instalación de Guix en un clúster

10.2 Configurar nodos de cálculo
================================

First of all, we need compute nodes to mount those NFS directories that
the head node exports. This can be done by adding the following lines to
‘/etc/fstab’ (https://linux.die.net/man/5/fstab):

     HEAD-NODE:/gnu/store    /gnu/store    nfs  defaults,_netdev,vers=3 0 0
     HEAD-NODE:/var/guix     /var/guix     nfs  defaults,_netdev,vers=3 0 0
     HEAD-NODE:/var/log/guix /var/log/guix nfs  defaults,_netdev,vers=3 0 0

... where HEAD-NODE is the name or IP address of your head node. From
there on, assuming the mount points exist, you should be able to mount
each of these on the compute nodes.

   Next, we need to provide a default ‘guix’ command that users can run
when they first connect to the cluster (eventually they will invoke
‘guix pull’, which will provide them with their “own” ‘guix’ command).
Similar to what the binary installation script did on the head node,
we’ll store that in ‘/usr/local/bin’:

     mkdir -p /usr/local/bin
     ln -s /var/guix/profiles/per-user/root/current-guix/bin/guix \
           /usr/local/bin/guix

   We then need to tell ‘guix’ to talk to the daemon running on our
master node, by adding these lines to ‘/etc/profile’:

     GUIX_DAEMON_SOCKET="guix://HEAD-NODE"
     export GUIX_DAEMON_SOCKET

   To avoid warnings and make sure ‘guix’ uses the right locale, we need
to tell it to use locale data provided by Guix (*note (guix)Application
Setup::):

     GUIX_LOCPATH=/var/guix/profiles/per-user/root/guix-profile/lib/locale
     export GUIX_LOCPATH

     # Here we must use a valid locale name.  Try "ls $GUIX_LOCPATH/*"
     # to see what names can be used.
     LC_ALL=fr_FR.utf8
     export LC_ALL

   For convenience, ‘guix package’ automatically generates
‘~/.guix-profile/etc/profile’, which defines all the environment
variables necessary to use the packages—‘PATH’, ‘C_INCLUDE_PATH’,
‘PYTHONPATH’, etc. Likewise, ‘guix pull’ does that under
‘~/.config/guix/current’. Thus it’s a good idea to source both from
‘/etc/profile’:

     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

   Last but not least, Guix provides command-line completion notably for
Bash and zsh. In ‘/etc/bashrc’, consider adding this line:

. /var/guix/profiles/per-user/root/current-guix/etc/bash_completion.d/guix

   Voilà!

   You can check that everything’s in place by logging in on a compute
node and running:

     guix install hello

   The daemon on the head node should download pre-built binaries on
your behalf and unpack them in ‘/gnu/store’, and ‘guix install’ should
create ‘~/.guix-profile’ containing the ‘~/.guix-profile/bin/hello’
command.


File: guix-cookbook.es.info,  Node: Acceso a red de racimo,  Next: Empleo del disco en racimo,  Prev: Configurar nodos de cálculo,  Up: Instalación de Guix en un clúster

10.3 Network Access
===================

Guix requires network access to download source code and pre-built
binaries. The good news is that only the head node needs that since
compute nodes simply delegate to it.

   It is customary for cluster nodes to have access at best to a _white
list_ of hosts. Our head node needs at least ‘ci.guix.gnu.org’ in this
white list since this is where it gets pre-built binaries from by
default, for all the packages that are in Guix proper.

   Incidentally, ‘ci.guix.gnu.org’ also serves as a _content-addressed
mirror_ of the source code of those packages. Consequently, it is
sufficient to have _only_ ‘ci.guix.gnu.org’ in that white list.

   Software packages maintained in a separate repository such as one of
the various HPC channels (https://hpc.guix.info/channels) are of course
unavailable from ‘ci.guix.gnu.org’. For these packages, you may want to
extend the white list such that source and pre-built binaries (assuming
this-party servers provide binaries for these packages) can be
downloaded. As a last resort, users can always download source on their
workstation and add it to the cluster’s ‘/gnu/store’, like this:

GUIX_DAEMON_SOCKET=ssh://compute-node.example.org \
  guix download http://starpu.gforge.inria.fr/files/starpu-1.2.3/starpu-1.2.3.tar.gz

   The above command downloads ‘starpu-1.2.3.tar.gz’ _and_ sends it to
the cluster’s ‘guix-daemon’ instance over SSH.

   Air-gapped clusters require more work. At the moment, our suggestion
would be to download all the necessary source code on a workstation
running Guix. For instance, using the ‘--sources’ option of ‘guix build’
(*note (guix)Invoking guix build::), the example below downloads all the
source code the ‘openmpi’ package depends on:

     $ guix build --sources=transitive openmpi

     ...

     /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
     …

   (In case you’re wondering, that’s more than 320 MiB of _compressed_
source code.)

   We can then make a big archive containing all of this (*note
(guix)Invoking guix archive::):

$ guix archive --export \
    `guix build --sources=transitive openmpi` \
    > openmpi-source-code.nar

   ... and we can eventually transfer that archive to the cluster on
removable storage and unpack it there:

$ guix archive --import < openmpi-source-code.nar

   This process has to be repeated every time new source code needs to
be brought to the cluster.

   As we write this, the research institutes involved in Guix-HPC do not
have air-gapped clusters though. If you have experience with such
setups, we would like to hear feedback and suggestions.


File: guix-cookbook.es.info,  Node: Empleo del disco en racimo,  Next: Consideraciones de seguridad del racimo,  Prev: Acceso a red de racimo,  Up: Instalación de Guix en un clúster

10.4 Disk Usage
===============

A common concern of sysadmins’ is whether this is all going to eat a lot
of disk space. If anything, if something is going to exhaust disk space,
it’s going to be scientific data sets rather than compiled
software—that’s our experience with almost ten years of Guix usage on
HPC clusters. Nevertheless, it’s worth taking a look at how Guix
contributes to disk usage.

   First, having several versions or variants of a given package in
‘/gnu/store’ does not necessarily cost much, because ‘guix-daemon’
implements deduplication of identical files, and package variants are
likely to have a number of common files.

   As mentioned above, we recommend having a cron job to run ‘guix gc’
periodically, which removes _unused_ software from ‘/gnu/store’.
However, there’s always a possibility that users will keep lots of
software in their profiles, or lots of old generations of their
profiles, which is “live” and cannot be deleted from the viewpoint of
‘guix gc’.

   The solution to this is for users to regularly remove old generations
of their profile. For instance, the following command removes
generations that are more than two-month old:

     guix package --delete-generations=2m

   Likewise, it’s a good idea to invite users to regularly upgrade their
profile, which can reduce the number of variants of a given piece of
software stored in ‘/gnu/store’:

     guix pull
     guix upgrade

   As a last resort, it is always possible for sysadmins to do some of
this on behalf of their users. Nevertheless, one of the strengths of
Guix is the freedom and control users get on their software environment,
so we strongly recommend leaving users in control.


File: guix-cookbook.es.info,  Node: Consideraciones de seguridad del racimo,  Prev: Empleo del disco en racimo,  Up: Instalación de Guix en un clúster

10.5 Security Considerations
============================

On an HPC cluster, Guix is typically used to manage scientific software.
Security-critical software such as the operating system kernel and
system services such as ‘sshd’ and the batch scheduler remain under
control of sysadmins.

   The Guix project has a good track record delivering security updates
in a timely fashion (*note (guix)Security Updates::). To get security
updates, users have to run ‘guix pull && guix upgrade’.

   Because Guix uniquely identifies software variants, it is easy to see
if a vulnerable piece of software is in use. For instance, to check
whether the glibc 2.25 variant without the mitigation patch against
“Stack Clash
(https://www.qualys.com/2017/06/19/stack-clash/stack-clash.txt)”, one
can check whether user profiles refer to it at all:

     guix gc --referrers /gnu/store/…-glibc-2.25

   This will report whether profiles exist that refer to this specific
glibc variant.


File: guix-cookbook.es.info,  Node: Gestión del sistema Guix,  Next: Agradecimientos,  Prev: Instalación de Guix en un clúster,  Up: Top

11 Gestión del sistema Guix
***************************

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:

* Modernizar Postgres para Cuirass::  Modernizar desde el postgres
                                        predeterminado.


File: guix-cookbook.es.info,  Node: Modernizar Postgres para Cuirass,  Up: Gestión del sistema Guix

11.1 Modernizar Postgres para 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 ‘pg_upgrade’
(https://www.postgresql.org/docs/current/pgupgrade.html) may be the
better choice. Handling the service and system upgrade as described in
this guide still applies, though.

  1. Stop and disable cuirass.

     Prevent the service from starting and failing after a
     reconfiguration:

     ‘sudo herd stop cuirass && sudo herd disable cuirass’

  2. Dump the database contents.

     ‘sudo su - postgres -s /bin/sh -c pg_dumpall > /tmp/pg.dump’

  3. 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 ‘(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.

          (service postgresql-service-type
                   (postgresql-configuration
                    (postgresql (@ (gnu packages databases) postgresql-15))))

     Note: If you for some reason didn’t read the text here but somewhat
     blindly followed the examples and _did upgrade to 16_, here’s how
     you reset the state:

       1. Delete the database instance files.

          They default to live under ‘/var/lib/postgres/data’.

       2. Re-initialize postgres.

          ‘sudo su - postgres -s /bin/sh -c 'pg_ctl init -D
          /var/lib/postgres/data'’

  4. Reconfigure your system.

     ‘sudo guix system reconfigure path/to/your/altered/config.scm’

  5. Restore database contents.

     ‘sudo su - postgres -s /bin/sh -c 'psql -d postgres -f
     /tmp/pg.dump'’

  6. Enable and start the service.

          sudo herd enable cuirass
          sudo herd start cuirass


File: guix-cookbook.es.info,  Node: Agradecimientos,  Next: Licencia de documentación libre GNU,  Prev: Gestión del sistema Guix,  Up: Top

12 Agradecimientos
******************

Guix is based on the Nix package manager (https://nixos.org/nix/), which
was designed and implemented by Eelco Dolstra, with contributions from
other people (see the ‘nix/AUTHORS’ file in Guix.) Nix pioneered
functional package management, and promoted unprecedented features, such
as transactional package upgrades and rollbacks, per-user profiles, and
referentially transparent build processes. Without this work, Guix would
not exist.

   The Nix-based software distributions, Nixpkgs and NixOS, have also
been an inspiration for Guix.

   GNU Guix itself is a collective work with contributions from a number
of people. See the ‘AUTHORS’ file in Guix for more information on these
fine people. The ‘THANKS’ file lists people who have helped by reporting
bugs, taking care of the infrastructure, providing artwork and themes,
making suggestions, and more—thank you!

   This document includes adapted sections from articles that have
previously been published on the Guix blog at
<https://guix.gnu.org/blog> and on the Guix-HPC blog at
<https://hpc.guix.info/blog>.


File: guix-cookbook.es.info,  Node: Licencia de documentación libre GNU,  Next: Índice de conceptos,  Prev: Agradecimientos,  Up: Top

Apéndice A Licencia de documentación libre GNU
**********************************************

                     Version 1.3, 3 November 2008

     Copyright © 2000, 2001, 2002, 2007, 2008 Free Software Foundation, Inc.
     <https://fsf.org/>

     Everyone is permitted to copy and distribute verbatim copies
     of this license document, but changing it is not allowed.

  0. PREAMBLE

     The purpose of this License is to make a manual, textbook, or other
     functional and useful document “free” in the sense of freedom: to
     assure everyone the effective freedom to copy and redistribute it,
     with or without modifying it, either commercially or
     noncommercially. Secondarily, this License preserves for the author
     and publisher a way to get credit for their work, while not being
     considered responsible for modifications made by others.

     This License is a kind of “copyleft”, which means that derivative
     works of the document must themselves be free in the same sense. It
     complements the GNU General Public License, which is a copyleft
     license designed for free software.

     We have designed this License in order to use it for manuals for
     free software, because free software needs free documentation: a
     free program should come with manuals providing the same freedoms
     that the software does. But this License is not limited to software
     manuals; it can be used for any textual work, regardless of subject
     matter or whether it is published as a printed book. We recommend
     this License principally for works whose purpose is instruction or
     reference.

  1. APPLICABILITY AND DEFINITIONS

     This License applies to any manual or other work, in any medium,
     that contains a notice placed by the copyright holder saying it can
     be distributed under the terms of this License. Such a notice
     grants a world-wide, royalty-free license, unlimited in duration,
     to use that work under the conditions stated herein. The
     “Document”, below, refers to any such manual or work. Any member of
     the public is a licensee, and is addressed as “you”. You accept the
     license if you copy, modify or distribute the work in a way
     requiring permission under copyright law.

     A “Modified Version” of the Document means any work containing the
     Document or a portion of it, either copied verbatim, or with
     modifications and/or translated into another language.

     A “Secondary Section” is a named appendix or a front-matter section
     of the Document that deals exclusively with the relationship of the
     publishers or authors of the Document to the Document’s overall
     subject (or to related matters) and contains nothing that could
     fall directly within that overall subject. (Thus, if the Document
     is in part a textbook of mathematics, a Secondary Section may not
     explain any mathematics.) The relationship could be a matter of
     historical connection with the subject or with related matters, or
     of legal, commercial, philosophical, ethical or political position
     regarding them.

     The “Invariant Sections” are certain Secondary Sections whose
     titles are designated, as being those of Invariant Sections, in the
     notice that says that the Document is released under this License.
     If a section does not fit the above definition of Secondary then it
     is not allowed to be designated as Invariant. The Document may
     contain zero Invariant Sections. If the Document does not identify
     any Invariant Sections then there are none.

     The “Cover Texts” are certain short passages of text that are
     listed, as Front-Cover Texts or Back-Cover Texts, in the notice
     that says that the Document is released under this License. A
     Front-Cover Text may be at most 5 words, and a Back-Cover Text may
     be at most 25 words.

     A “Transparent” copy of the Document means a machine-readable copy,
     represented in a format whose specification is available to the
     general public, that is suitable for revising the document
     straightforwardly with generic text editors or (for images composed
     of pixels) generic paint programs or (for drawings) some widely
     available drawing editor, and that is suitable for input to text
     formatters or for automatic translation to a variety of formats
     suitable for input to text formatters. A copy made in an otherwise
     Transparent file format whose markup, or absence of markup, has
     been arranged to thwart or discourage subsequent modification by
     readers is not Transparent. An image format is not Transparent if
     used for any substantial amount of text. A copy that is not
     “Transparent” is called “Opaque”.

     Examples of suitable formats for Transparent copies include plain
     ASCII without markup, Texinfo input format, LaTeX input format,
     SGML or XML using a publicly available DTD, and standard-conforming
     simple HTML, PostScript or PDF designed for human modification.
     Examples of transparent image formats include PNG, XCF and JPG.
     Opaque formats include proprietary formats that can be read and
     edited only by proprietary word processors, SGML or XML for which
     the DTD and/or processing tools are not generally available, and
     the machine-generated HTML, PostScript or PDF produced by some word
     processors for output purposes only.

     The “Title Page” means, for a printed book, the title page itself,
     plus such following pages as are needed to hold, legibly, the
     material this License requires to appear in the title page. For
     works in formats which do not have any title page as such, “Title
     Page” means the text near the most prominent appearance of the
     work’s title, preceding the beginning of the body of the text.

     The “publisher” means any person or entity that distributes copies
     of the Document to the public.

     A section “Entitled XYZ” means a named subunit of the Document
     whose title either is precisely XYZ or contains XYZ in parentheses
     following text that translates XYZ in another language. (Here XYZ
     stands for a specific section name mentioned below, such as
     “Acknowledgements”, “Dedications”, “Endorsements”, or “History”.)
     To “Preserve the Title” of such a section when you modify the
     Document means that it remains a section “Entitled XYZ” according
     to this definition.

     The Document may include Warranty Disclaimers next to the notice
     which states that this License applies to the Document. These
     Warranty Disclaimers are considered to be included by reference in
     this License, but only as regards disclaiming warranties: any other
     implication that these Warranty Disclaimers may have is void and
     has no effect on the meaning of this License.

  2. VERBATIM COPYING

     You may copy and distribute the Document in any medium, either
     commercially or noncommercially, provided that this License, the
     copyright notices, and the license notice saying this License
     applies to the Document are reproduced in all copies, and that you
     add no other conditions whatsoever to those of this License. You
     may not use technical measures to obstruct or control the reading
     or further copying of the copies you make or distribute. However,
     you may accept compensation in exchange for copies. If you
     distribute a large enough number of copies you must also follow the
     conditions in section 3.

     You may also lend copies, under the same conditions stated above,
     and you may publicly display copies.

  3. COPYING IN QUANTITY

     If you publish printed copies (or copies in media that commonly
     have printed covers) of the Document, numbering more than 100, and
     the Document’s license notice requires Cover Texts, you must
     enclose the copies in covers that carry, clearly and legibly, all
     these Cover Texts: Front-Cover Texts on the front cover, and
     Back-Cover Texts on the back cover. Both covers must also clearly
     and legibly identify you as the publisher of these copies. The
     front cover must present the full title with all words of the title
     equally prominent and visible. You may add other material on the
     covers in addition. Copying with changes limited to the covers, as
     long as they preserve the title of the Document and satisfy these
     conditions, can be treated as verbatim copying in other respects.

     If the required texts for either cover are too voluminous to fit
     legibly, you should put the first ones listed (as many as fit
     reasonably) on the actual cover, and continue the rest onto
     adjacent pages.

     If you publish or distribute Opaque copies of the Document
     numbering more than 100, you must either include a machine-readable
     Transparent copy along with each Opaque copy, or state in or with
     each Opaque copy a computer-network location from which the general
     network-using public has access to download using public-standard
     network protocols a complete Transparent copy of the Document, free
     of added material. If you use the latter option, you must take
     reasonably prudent steps, when you begin distribution of Opaque
     copies in quantity, to ensure that this Transparent copy will
     remain thus accessible at the stated location until at least one
     year after the last time you distribute an Opaque copy (directly or
     through your agents or retailers) of that edition to the public.

     It is requested, but not required, that you contact the authors of
     the Document well before redistributing any large number of copies,
     to give them a chance to provide you with an updated version of the
     Document.

  4. MODIFICATIONS

     You may copy and distribute a Modified Version of the Document
     under the conditions of sections 2 and 3 above, provided that you
     release the Modified Version under precisely this License, with the
     Modified Version filling the role of the Document, thus licensing
     distribution and modification of the Modified Version to whoever
     possesses a copy of it. In addition, you must do these things in
     the Modified Version:

       A. Use in the Title Page (and on the covers, if any) a title
          distinct from that of the Document, and from those of previous
          versions (which should, if there were any, be listed in the
          History section of the Document). You may use the same title
          as a previous version if the original publisher of that
          version gives permission.

       B. List on the Title Page, as authors, one or more persons or
          entities responsible for authorship of the modifications in
          the Modified Version, together with at least five of the
          principal authors of the Document (all of its principal
          authors, if it has fewer than five), unless they release you
          from this requirement.

       C. State on the Title page the name of the publisher of the
          Modified Version, as the publisher.

       D. Preserve all the copyright notices of the Document.

       E. Add an appropriate copyright notice for your modifications
          adjacent to the other copyright notices.

       F. Include, immediately after the copyright notices, a license
          notice giving the public permission to use the Modified
          Version under the terms of this License, in the form shown in
          the Addendum below.

       G. Preserve in that license notice the full lists of Invariant
          Sections and required Cover Texts given in the Document’s
          license notice.

       H. Include an unaltered copy of this License.

       I. Preserve the section Entitled “History”, Preserve its Title,
          and add to it an item stating at least the title, year, new
          authors, and publisher of the Modified Version as given on the
          Title Page. If there is no section Entitled “History” in the
          Document, create one stating the title, year, authors, and
          publisher of the Document as given on its Title Page, then add
          an item describing the Modified Version as stated in the
          previous sentence.

       J. Preserve the network location, if any, given in the Document
          for public access to a Transparent copy of the Document, and
          likewise the network locations given in the Document for
          previous versions it was based on. These may be placed in the
          “History” section. You may omit a network location for a work
          that was published at least four years before the Document
          itself, or if the original publisher of the version it refers
          to gives permission.

       K. For any section Entitled “Acknowledgements” or “Dedications”,
          Preserve the Title of the section, and preserve in the section
          all the substance and tone of each of the contributor
          acknowledgements and/or dedications given therein.

       L. Preserve all the Invariant Sections of the Document, unaltered
          in their text and in their titles. Section numbers or the
          equivalent are not considered part of the section titles.

       M. Delete any section Entitled “Endorsements”. Such a section may
          not be included in the Modified Version.

       N. Do not retitle any existing section to be Entitled
          “Endorsements” or to conflict in title with any Invariant
          Section.

       O. Preserve any Warranty Disclaimers.

     If the Modified Version includes new front-matter sections or
     appendices that qualify as Secondary Sections and contain no
     material copied from the Document, you may at your option designate
     some or all of these sections as invariant. To do this, add their
     titles to the list of Invariant Sections in the Modified Version’s
     license notice. These titles must be distinct from any other
     section titles.

     You may add a section Entitled “Endorsements”, provided it contains
     nothing but endorsements of your Modified Version by various
     parties—for example, statements of peer review or that the text has
     been approved by an organization as the authoritative definition of
     a standard.

     You may add a passage of up to five words as a Front-Cover Text,
     and a passage of up to 25 words as a Back-Cover Text, to the end of
     the list of Cover Texts in the Modified Version. Only one passage
     of Front-Cover Text and one of Back-Cover Text may be added by (or
     through arrangements made by) any one entity. If the Document
     already includes a cover text for the same cover, previously added
     by you or by arrangement made by the same entity you are acting on
     behalf of, you may not add another; but you may replace the old
     one, on explicit permission from the previous publisher that added
     the old one.

     The author(s) and publisher(s) of the Document do not by this
     License give permission to use their names for publicity for or to
     assert or imply endorsement of any Modified Version.

  5. COMBINING DOCUMENTS

     You may combine the Document with other documents released under
     this License, under the terms defined in section 4 above for
     modified versions, provided that you include in the combination all
     of the Invariant Sections of all of the original documents,
     unmodified, and list them all as Invariant Sections of your
     combined work in its license notice, and that you preserve all
     their Warranty Disclaimers.

     The combined work need only contain one copy of this License, and
     multiple identical Invariant Sections may be replaced with a single
     copy. If there are multiple Invariant Sections with the same name
     but different contents, make the title of each such section unique
     by adding at the end of it, in parentheses, the name of the
     original author or publisher of that section if known, or else a
     unique number. Make the same adjustment to the section titles in
     the list of Invariant Sections in the license notice of the
     combined work.

     In the combination, you must combine any sections Entitled
     “History” in the various original documents, forming one section
     Entitled “History”; likewise combine any sections Entitled
     “Acknowledgements”, and any sections Entitled “Dedications”. You
     must delete all sections Entitled “Endorsements.”

  6. COLLECTIONS OF DOCUMENTS

     You may make a collection consisting of the Document and other
     documents released under this License, and replace the individual
     copies of this License in the various documents with a single copy
     that is included in the collection, provided that you follow the
     rules of this License for verbatim copying of each of the documents
     in all other respects.

     You may extract a single document from such a collection, and
     distribute it individually under this License, provided you insert
     a copy of this License into the extracted document, and follow this
     License in all other respects regarding verbatim copying of that
     document.

  7. AGGREGATION WITH INDEPENDENT WORKS

     A compilation of the Document or its derivatives with other
     separate and independent documents or works, in or on a volume of a
     storage or distribution medium, is called an “aggregate” if the
     copyright resulting from the compilation is not used to limit the
     legal rights of the compilation’s users beyond what the individual
     works permit. When the Document is included in an aggregate, this
     License does not apply to the other works in the aggregate which
     are not themselves derivative works of the Document.

     If the Cover Text requirement of section 3 is applicable to these
     copies of the Document, then if the Document is less than one half
     of the entire aggregate, the Document’s Cover Texts may be placed
     on covers that bracket the Document within the aggregate, or the
     electronic equivalent of covers if the Document is in electronic
     form. Otherwise they must appear on printed covers that bracket the
     whole aggregate.

  8. TRANSLATION

     Translation is considered a kind of modification, so you may
     distribute translations of the Document under the terms of section
     4. Replacing Invariant Sections with translations requires special
     permission from their copyright holders, but you may include
     translations of some or all Invariant Sections in addition to the
     original versions of these Invariant Sections. You may include a
     translation of this License, and all the license notices in the
     Document, and any Warranty Disclaimers, provided that you also
     include the original English version of this License and the
     original versions of those notices and disclaimers. In case of a
     disagreement between the translation and the original version of
     this License or a notice or disclaimer, the original version will
     prevail.

     If a section in the Document is Entitled “Acknowledgements”,
     “Dedications”, or “History”, the requirement (section 4) to
     Preserve its Title (section 1) will typically require changing the
     actual title.

  9. TERMINATION

     You may not copy, modify, sublicense, or distribute the Document
     except as expressly provided under this License. Any attempt
     otherwise to copy, modify, sublicense, or distribute it is void,
     and will automatically terminate your rights under this License.

     However, if you cease all violation of this License, then your
     license from a particular copyright holder is reinstated (a)
     provisionally, unless and until the copyright holder explicitly and
     finally terminates your license, and (b) permanently, if the
     copyright holder fails to notify you of the violation by some
     reasonable means prior to 60 days after the cessation.

     Moreover, your license from a particular copyright holder is
     reinstated permanently if the copyright holder notifies you of the
     violation by some reasonable means, this is the first time you have
     received notice of violation of this License (for any work) from
     that copyright holder, and you cure the violation prior to 30 days
     after your receipt of the notice.

     Termination of your rights under this section does not terminate
     the licenses of parties who have received copies or rights from you
     under this License. If your rights have been terminated and not
     permanently reinstated, receipt of a copy of some or all of the
     same material does not give you any rights to use it.

  10. FUTURE REVISIONS OF THIS LICENSE

     The Free Software Foundation may publish new, revised versions of
     the GNU Free Documentation License from time to time. Such new
     versions will be similar in spirit to the present version, but may
     differ in detail to address new problems or concerns. See
     <https://www.gnu.org/copyleft/>.

     Each version of the License is given a distinguishing version
     number. If the Document specifies that a particular numbered
     version of this License “or any later version” applies to it, you
     have the option of following the terms and conditions either of
     that specified version or of any later version that has been
     published (not as a draft) by the Free Software Foundation. If the
     Document does not specify a version number of this License, you may
     choose any version ever published (not as a draft) by the Free
     Software Foundation. If the Document specifies that a proxy can
     decide which future versions of this License can be used, that
     proxy’s public statement of acceptance of a version permanently
     authorizes you to choose that version for the Document.

  11. RELICENSING

     “Massive Multiauthor Collaboration Site” (or “MMC Site”) means any
     World Wide Web server that publishes copyrightable works and also
     provides prominent facilities for anybody to edit those works. A
     public wiki that anybody can edit is an example of such a server. A
     “Massive Multiauthor Collaboration” (or “MMC”) contained in the
     site means any set of copyrightable works thus published on the MMC
     site.

     “CC-BY-SA” means the Creative Commons Attribution-Share Alike 3.0
     license published by Creative Commons Corporation, a not-for-profit
     corporation with a principal place of business in San Francisco,
     California, as well as future copyleft versions of that license
     published by that same organization.

     “Incorporate” means to publish or republish a Document, in whole or
     in part, as part of another Document.

     An MMC is “eligible for relicensing” if it is licensed under this
     License, and if all works that were first published under this
     License somewhere other than this MMC, and subsequently
     incorporated in whole or in part into the MMC, (1) had no cover
     texts or invariant sections, and (2) were thus incorporated prior
     to November 1, 2008.

     The operator of an MMC Site may republish an MMC contained in the
     site under CC-BY-SA on the same site at any time before August 1,
     2009, provided the MMC is eligible for relicensing.

ADDENDUM: How to use this License for your documents
====================================================

To use this License in a document you have written, include a copy of
the License in the document and put the following copyright and license
notices just after the title page:

       Copyright (C)  YEAR  YOUR NAME.
       Permission is granted to copy, distribute and/or modify this document
       under the terms of the GNU Free Documentation License, Version 1.3
       or any later version published by the Free Software Foundation;
       with no Invariant Sections, no Front-Cover Texts, and no Back-Cover
       Texts.  A copy of the license is included in the section entitled ``GNU
       Free Documentation License''.

   If you have Invariant Sections, Front-Cover Texts and Back-Cover
Texts, replace the “with...Texts.” line with this:

         with the Invariant Sections being LIST THEIR TITLES, with
         the Front-Cover Texts being LIST, and with the Back-Cover Texts
         being LIST.

   If you have Invariant Sections without Cover Texts, or some other
combination of the three, merge those two alternatives to suit the
situation.

   If your document contains nontrivial examples of program code, we
recommend releasing these examples in parallel under your choice of free
software license, such as the GNU General Public License, to permit
their use in free software.


File: guix-cookbook.es.info,  Node: Índice de conceptos,  Prev: Licencia de documentación libre GNU,  Up: Top

Índice de conceptos
*******************

[index]
* Menu:

* 2FA, autenticación de dos factores:    Utilización de claves de seguridad.
                                                              (line   6)
* abandonando un contenedor:             Contenedores Guix.   (line  35)
* bloqueo de sesión:                     Bloqueo de sesión.   (line   6)
* bluetooth, configuración ALSA:         Servidor de música con sonido Bluetooth.
                                                              (line   6)
* canal:                                 Canales.             (line   6)
* clave de seguridad, configuración:     Utilización de claves de seguridad.
                                                              (line   6)
* cluster installation:                  Instalación de Guix en un clúster.
                                                              (line   6)
* compartir directorios, contenedor:     Contenedores Guix.   (line  39)
* continuous integration (CI):           Configurar Integración Continua.
                                                              (line   6)
* desactivar yubikey OTP:                Utilización de claves de seguridad.
                                                              (line  60)
* development, with Guix:                Desarrollo de software.
                                                              (line   6)
* disk usage, on a cluster:              Empleo del disco en racimo.
                                                              (line   6)
* DNS dinámico, DDNS:                    Tarea mcron de DNS dinámico.
                                                              (line   6)
* empaquetar:                            Empaquetado.         (line   6)
* evitar el desajuste ABI, contenedor:   Contenedores Guix.   (line  57)
* exponer directorios, contenedor:       Contenedores Guix.   (line  39)
* Expresiones-G, sintaxis:               Curso acelerado de Scheme.
                                                              (line 123)
* expresión-S:                           Curso acelerado de Scheme.
                                                              (line  99)
* gexps, sintaxis:                       Curso acelerado de Scheme.
                                                              (line 123)
* high-performance computing, HPC:       Instalación de Guix en un clúster.
                                                              (line   6)
* HPC, high-performance computing:       Instalación de Guix en un clúster.
                                                              (line   6)
* Interfaz de puente de red:             Puente de red para QEMU.
                                                              (line   6)
* kimsufi, Kimsufi, OVH:                 Ejecución de Guix en un servidor Kimsufi.
                                                              (line   6)
* letras stumpwm:                        StumpWM.             (line  20)
* libvirt, virtual network switch:       Red enrutada para libvirt.
                                                              (line   6)
* license, GNU Free Documentation License: Licencia de documentación libre GNU.
                                                              (line   6)
* linode, Linode:                        Ejecución de Guix en un servidor Linode.
                                                              (line   6)
* lock files, for reproducibility:       Recording the Environment.
                                                              (line  39)
* mpd:                                   Servidor de música con sonido Bluetooth.
                                                              (line   6)
* networking, virtual bridge:            Red enrutada para libvirt.
                                                              (line   6)
* nginx, lua, openresty, resty:          Instalar NGINX con Lua.
                                                              (line   6)
* ocultar las bibliotecas del sistema, contenedor: Contenedores Guix.
                                                              (line  57)
* qemu, puente de red:                   Puente de red para QEMU.
                                                              (line   6)
* red de contenedor:                     Red de Contenedor.   (line   6)
* redes, puente:                         Puente de red para QEMU.
                                                              (line   6)
* reproducible research:                 Reproducible Research.
                                                              (line   6)
* Scheme, curso intensivo:               Curso acelerado de Scheme.
                                                              (line   6)
* security, on a cluster:                Consideraciones de seguridad del racimo.
                                                              (line   6)
* servidor de música, sin cabeza:        Servidor de música con sonido Bluetooth.
                                                              (line   6)
* software development, with Guix:       Desarrollo de software.
                                                              (line   6)
* stumpwm:                               StumpWM.             (line   6)
* sysadmin:                              Gestión del sistema Guix.
                                                              (line   6)
* system management:                     Gestión del sistema Guix.
                                                              (line   6)
* U2F, segundo factor universal:         Utilización de claves de seguridad.
                                                              (line   6)
* ubicaciones cartográficas, contenedor: Contenedores Guix.   (line  39)
* Virtual network bridge interface:      Red enrutada para libvirt.
                                                              (line   6)
* wm:                                    Personalizar un gestor de ventanas.
                                                              (line   6)
* yubikey, integración de keepassxc:     Utilización de claves de seguridad.
                                                              (line  77)



Tag Table:
Node: Top1383
Node: Tutoriales de Scheme9846
Node: Curso acelerado de Scheme10609
Node: Empaquetado19143
Node: Tutorial de empaquetado19752
Node: Un paquete ``Hola Mundo''22285
Node: Ajuste31144
Node: Archivo local31999
Node: Canales32853
Node: Jaqueo directo de revisión de código36910
Node: Ejemplo ampliado39758
Node: Otros sistemas de construcción57980
Node: Definición de paquetes programable y automatizada59021
Node: Importadores recursivos59724
Node: Actualizaciones automáticas62296
Node: Herencia62984
Node: Obtener ayuda64152
Node: Conclusión65000
Node: Referencias66236
Node: Packaging Workflows66748
Node: Packaging Rust Crates67154
Node: Common Workflow for Rust Packaging67793
Node: Cargo Workspaces and Development Snapshots74419
Node: Using Rust Libraries in Other Build Systems78693
Node: Configuración del sistema81771
Node: Inicio de sesión automático en un TTY específico84222
Node: Personalización del kernel86188
Node: API de imagen del sistema Guix96659
Node: Utilización de claves de seguridad104068
Node: Tarea mcron de DNS dinámico109410
Node: Conexión a Wireguard VPN111842
Node: Personalizar un gestor de ventanas114976
Node: StumpWM115341
Node: Bloqueo de sesión116946
Node: Xorg117483
Node: Ejecución de Guix en un servidor Linode118970
Node: Ejecución de Guix en un servidor Kimsufi127820
Node: Instalar un montaje enlazado135187
Node: Obtener sustituciones desde Tor137645
Node: Instalar NGINX con Lua140551
Node: Servidor de música con sonido Bluetooth142793
Node: Contenedores150807
Node: Contenedores Guix152443
Node: Contenedores de Sistema Guix158190
Node: Un contenedor de base de datos160219
Node: Red de Contenedor164651
Node: Máquinas virtuales166888
Node: Puente de red para QEMU167750
Node: Red enrutada para libvirt172643
Node: Red basada en NAT personal para libvirt176492
Node: Referencias de MV181448
Node: Gestión avanzada de paquetes181970
Node: Perfiles Guix en práctica182649
Node: Configuración base con declaraciones186200
Node: Paquetes requeridos190662
Node: Perfil por defecto191650
Node: Los beneficios de declaraciones192339
Node: Perfiles reproducibles196224
Node: Desarrollo de software197650
Ref: Desarrollo de software-Footnote-1199254
Node: Empezando199493
Node: Compilar con Guix203884
Node: El repositorio como un canal206958
Node: Variantes de paquetes212306
Node: Configurar Integración Continua214212
Node: Compilar manifiesto217477
Node: Cobertura221332
Node: Gestión del entorno223113
Node: Entorno Guix por direnv223458
Node: Reproducible Research226839
Ref: Reproducible Research-Footnote-1228048
Node: Setting Up the Environment228220
Node: Recording the Environment230644
Node: Ensuring Long-Term Source Code Archiving233791
Node: Referencing the Software Environment235429
Node: Instalación de Guix en un clúster237344
Ref: Instalación de Guix en un clúster-Footnote-1238579
Node: Configurar un nodo de cabecera238739
Node: Configurar nodos de cálculo242592
Node: Acceso a red de racimo245675
Node: Empleo del disco en racimo249153
Node: Consideraciones de seguridad del racimo251079
Node: Gestión del sistema Guix252220
Node: Modernizar Postgres para Cuirass252825
Node: Agradecimientos255337
Node: Licencia de documentación libre GNU256604
Node: Índice de conceptos281949

End Tag Table


Local Variables:
coding: utf-8
End:
