Iniciar una unidad systemd de nivel de usuario al arrancar

Complete todos los pasos descritos en página de configuración inicial antes de comenzar este tutorial. Asegúrese de haber creado el archivo ssh-key.pub siguiendo las instrucciones proporcionadas en prerequisites para el tutorial. Utilizaremos esta clave en el archivo de configuración de Butane que estamos a punto de escribir.

En este tutorial, configuraremos una unidad systemd a nivel de usuario para un usuario sin privilegios. Hay veces que es útil lanzar un systemd unit a nivel de usuario sin tener que acceder. Por ejemplo, desea lanzar un contenedor que suministra un servicio de red o ejecutar un trabajo HPC. Para esta configuración, añadiremos lo siguiente a una configuración de Butane:

  • Una unidad systemd de nivel de usuario: /home/sleeper/.config/systemd/user/linger-example.service.

  • Habilítelo como un servicio systemd a nivel de usuario.

Configuración de la unidad systemd

En este ejemplo, lanzaremos un servicio systemd para el usuario sleeper. Primero, crearemos un usuario:

variant: fcos
version: 1.6.0
passwd:
  users:
    - name: sleeper

Esto también creará el directorio de inicio para el usuario sleeper. Después, podemos agregar la unidad systemd:

variant: fcos
version: 1.6.0
storage:
  files:
    - path: /home/sleeper/.config/systemd/user/linger-example.service
      mode: 0644
      contents:
        inline: |
          [Unit]
          Description=A systemd user unit demo
          [Service]
          ExecStart=/usr/bin/sleep infinity
      user:
        name: sleeper
      group:
        name: sleeper

Los servicios del sistema se pueden habilitar directamente en las configuraciones de Butane, pero los servicios de nivel de usuario deben habilitarse manualmente por ahora:

variant: fcos
version: 1.6.0
storage:
  directories:
    - path: /home/sleeper/.config/systemd/user/default.target.wants
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
  links:
    - path: /home/sleeper/.config/systemd/user/default.target.wants/linger-example.service
      user:
        name: sleeper
      group:
        name: sleeper
      target: /home/sleeper/.config/systemd/user/linger-example.service
      hard: false

Configuramos la persistencia para la instancia de nivel de usuario de systemd para que se inicie directamente en el arranque y permanezca en ejecución:

variant: fcos
version: 1.6.0
storage:
  files:
    - path: /var/lib/systemd/linger/sleeper
      mode: 0644

Como los siguientes directorios aún no existen, tendremos que crearlos para indicarle a Ignition que establezca la propiedad y los permisos correctos:

variant: fcos
version: 1.6.0
storage:
  directories:
    - path: /home/sleeper/.config
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd/user
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd/user/default.target.wants
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper

Escribir la configuración Butane y convertirla a Ignition

La config Butane final, almacenada en user.bu, será:

variant: fcos
version: 1.6.0
passwd:
  users:
    - name: core
      ssh_authorized_keys_local:
        - ssh-key.pub
    - name: sleeper
storage:
  directories:
    - path: /home/sleeper/.config
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd/user
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
    - path: /home/sleeper/.config/systemd/user/default.target.wants
      mode: 0755
      user:
        name: sleeper
      group:
        name: sleeper
  files:
    - path: /var/lib/systemd/linger/sleeper
      mode: 0644
    - path: /home/sleeper/.config/systemd/user/linger-example.service
      mode: 0644
      contents:
        inline: |
          [Unit]
          Description=A systemd user unit demo
          [Service]
          ExecStart=/usr/bin/sleep infinity
      user:
        name: sleeper
      group:
        name: sleeper
  links:
    - path: /home/sleeper/.config/systemd/user/default.target.wants/linger-example.service
      user:
        name: sleeper
      group:
        name: sleeper
      target: /home/sleeper/.config/systemd/user/linger-example.service
      hard: false

Esta configuración se puede convertir a Ignition:

butane --pretty --strict --files-dir=./ user.bu --output user.ign

Pruebas

Tan sol como antes utilizaremos lo siguiente para arrancar la instancia:

# Configura la etiqueta SELinux correcta para conceder acceso al config
chcon --verbose --type svirt_home_t containers.ign

# Inicia una máquina virtual de Fedora CoreOS
virt-install --name=fcos --vcpus=2 --ram=2048 --os-variant=fedora-coreos-stable \
    --import --network=bridge=virbr0 --graphics=none \
    --qemu-commandline="-fw_cfg name=opt/com.coreos/config,file=${PWD}/user.ign" \
    --disk="size=20,backing_store=${PWD}/fedora-coreos.qcow2"

Entonces podemos verificar que la unidad ha sido iniciada bajo el systemd sleeper la instancia del usuario:

[core@localhost ~]$ sudo machinectl shell sleeper@
Conectado al host local. Pulse ^] tres veces dentro de 1 sg para salir de la sesión.
[sleeper@localhost ~]$ systemctl --user status
● localhost.localdomain
    State: running
    Units: 157 loaded (incl. loaded aliases)
     Jobs: 0 queued
   Failed: 0 units
    Since: Thu 2023-08-03 18:31:27 UTC; 23s ago
  systemd: 253.4-1.fc38
   CGroup: /user.slice/user-1001.slice/user@1001.service
           ├─app.slice
           │ └─linger-example.service
           │   └─1589 /usr/bin/sleep infinity
           └─init.scope
             ├─1489 /usr/lib/systemd/systemd --user
             └─1496 "(sd-pam)"
[sleeper@localhost ~]$ systemctl --user status linger-example.service
● linger-example.service - Una demostración de unidad de usuario en systemd
     Loaded: loaded (/var/home/sleeper/.config/systemd/user/linger-example.service; enabled; preset: disabled)
    Drop-In: /usr/lib/systemd/user/service.d
             └─10-timeout-abort.conf
     Active: active (running) since Thu 2023-08-03 18:31:27 UTC; 38s ago
   Main PID: 1589 (sleep)
      Tasks: 1 (limit: 2238)
     Memory: 224.0K
        CPU: 1ms
     CGroup: /user.slice/user-1001.slice/user@1001.service/app.slice/linger-example.service
             └─1589 /usr/bin/sleep infinity

Aug 03 18:31:27 localhost.localdomain systemd[1489]: Iniciando linger-example.service - Una demo de unidad para usuario de systemd.

Purga

Entonces puedes destruir la instancia. Primero, desconéctate desde la consola serie pulsando CTRL + ] y luego destruye la máquina:

virsh destroy fcos
virsh undefine --remove-all-storage fcos

Ahora puedes proceder con el siguiente tutorial.