Avvio di uno script al primo avvio tramite un servizio systemd

Assicurati di aver completato i passaggi descritti nella pagina di configurazione iniziale prima di iniziare questo tutorial.

In questo tutorial, eseguiremo uno script al primo avvio tramite un servizio systemd. Aggiungeremo quanto segue alla configurazione Butane dallo scenario precedente:

  • Aggiungi uno script in /usr/local/bin/public-ipv4.sh.

  • Configura un servizio systemd per eseguire lo script al primo avvio.

Scrittura dello script

Let’s write a small script that uses icanhazip.com to create an issue file to display as a prelogin message on the console and store it in public-ipv4.sh.

This is only an example to show how to run a service on boot. Do not use this if you don’t trust the owners of icanhazip.com.
cat <<'EOF' > public-ipv4.sh
#!/bin/bash
echo "Detected Public IPv4: is $(curl https://ipv4.icanhazip.com)" > \
    /etc/issue.d/50_public-ipv4.issue
EOF

This could be useful in cloud environments where you might have different public and private addresses.

We will store this script into /usr/local/bin/public-ipv4.sh when we provision the machine.

Writing the systemd service

We need to call the script from the previous section by using a systemd unit. Let’s write a systemd unit into the issuegen-public-ipv4.service file that does what we want, which is to execute on first boot and not again:

cat <<'EOF' > issuegen-public-ipv4.service
[Unit]
Before=systemd-user-sessions.service
Wants=network-online.target
After=network-online.target
ConditionPathExists=!/var/lib/issuegen-public-ipv4

[Service]
Type=oneshot
ExecStart=/usr/local/bin/public-ipv4.sh
ExecStartPost=/usr/bin/touch /var/lib/issuegen-public-ipv4
RemainAfterExit=yes

[Install]
WantedBy=multi-user.target
EOF

Writing the Butane config and converting to Ignition

We can now create a Butane config that will include the script and systemd unit file contents by picking up the local public-ipv4.sh and issuegen-public-ipv4.service files using local file references. The final Butane config, stored in services.bu, will be:

variant: fcos
version: 1.6.0
systemd:
  units:
    - name: serial-getty@ttyS0.service
      dropins:
      - name: autologin-core.conf
        contents: |
          [Service]
          # Override Execstart in main unit
          ExecStart=
          # Add new Execstart with `-` prefix to ignore failure`
          ExecStart=-/usr/sbin/agetty --autologin core --noclear %I $TERM
    - name: issuegen-public-ipv4.service
      enabled: true
      contents_local: issuegen-public-ipv4.service
storage:
  files:
    - path: /etc/hostname
      mode: 0644
      contents:
        inline: |
          tutorial
    - path: /etc/profile.d/systemd-pager.sh
      mode: 0644
      contents:
        inline: |
          # Tell systemd to not use a pager when printing information
          export SYSTEMD_PAGER=cat
    - path: /usr/local/bin/public-ipv4.sh
      mode: 0755
      contents:
        local: public-ipv4.sh
Check the Butane Examples and Configuration specifications for more details about local file includes.

With the files public-ipv4.sh, issuegen-public-ipv4.service, and services.bu in the current working directory we can now convert to Ignition:

butane --pretty --strict --files-dir=./ services.bu --output services.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 services.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}/services.ign" \
    --disk="size=20,backing_store=${PWD}/fedora-coreos.qcow2"

And view on the console that the Detected Public IPv4 is shown in the console output right before you are dropped to a login prompt:

Fedora CoreOS 38.20230709.3.0
Kernel 6.3.11-200.fc38.x86_64 on an x86_64 (ttyS0)

SSH host key: SHA256:tYHKk26+NZ/+ZytWLXClGz813PQJDGP/2+AiuZ8fiqk (ECDSA)
SSH host key: SHA256:jJASZec/91zXd4or0uiFsvsfaLC6viLronfxIwQlNCs (ED25519)
SSH host key: SHA256:2XlSZAehEu666fmXeM8d47lpIJd92MBOqgMazT4GsVw (RSA)
enp1s0: 192.168.124.150 fe80::475a:7a10:2302:b670
Ignition: ran on 2023/08/03 16:40:45 UTC (this boot)
Ignition: user-provided config was applied
No SSH authorized keys provided by Ignition or Afterburn
Detected Public IPv4: is 3.252.102.80
tutorial login: core (automatic login)

Fedora CoreOS 38.20230709.3.0
[core@tutorial ~]$

And the service shows it was launched successfully:

[core@tutorial ~]$ systemctl status --full issuegen-public-ipv4.service
● issuegen-public-ipv4.service
     Loaded: loaded (/etc/systemd/system/issuegen-public-ipv4.service; enabled; preset: enabled)
    Drop-In: /usr/lib/systemd/system/service.d
             └─10-timeout-abort.conf
     Active: active (exited) since Thu 2023-08-03 16:40:55 UTC; 1min 7s ago
    Process: 1423 ExecStart=/usr/local/bin/public-ipv4.sh (code=exited, status=0/SUCCESS)
    Process: 1460 ExecStartPost=/usr/bin/touch /var/lib/issuegen-public-ipv4 (code=exited, status=0/SUCCESS)
   Main PID: 1423 (code=exited, status=0/SUCCESS)
        CPU: 84ms

Aug 03 16:40:55 tutorial systemd[1]: Starting issuegen-public-ipv4.service...
Aug 03 16:40:55 tutorial public-ipv4.sh[1424]:   % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
Aug 03 16:40:55 tutorial public-ipv4.sh[1424]:                                  Dload  Upload   Total   Spent    Left  Speed
Aug 03 16:40:55 tutorial public-ipv4.sh[1424]: [158B blob data]
Aug 03 16:40:55 tutorial systemd[1]: Finished issuegen-public-ipv4.service.

Cleanup

Now let’s take down the instance for the next test. 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.