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

System services can be directly enabled in Butane configs but user level services have to be manually enabled for now:

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

We set up lingering for the systemd user level instance so that it gets started directly on boot and stays running:

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

As the following directories do not exist yet, we will have to create them to tell Ignition to set the right ownership and permissions:

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

Escribiremos la configuración Butane y la convertiremos a Ignition

The final Butane config, stored in user.bu, will be:

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

This config can be converted to Ignition:

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

Testing

Just as before we will use the following to boot the instance:

# Setup the correct SELinux label to allow access to the config
chcon --verbose --type svirt_home_t user.ign

# Start a Fedora CoreOS virtual machine
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"

We can then verify that the unit has been started under the sleeper systemd user instance:

[core@localhost ~]$ sudo machinectl shell sleeper@
Connected to the local host. Press ^] three times within 1s to exit session.
[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 - A systemd user unit demo
     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]: Started linger-example.service - A systemd user unit demo.

Vaciado

You can then take down the instance. First, disconnect from the serial console by pressing CTRL + ] and then destroy the machine:

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

You may now proceed with the next tutorial.