Layering packages via rpm-ostree as part of provisioning?

Maybe you’d wanted to layer a package via rpm-ostree as part of the Ignition process?

What I drafted now is doing it like this (adopted from here):

variant: fcos
version: 1.3.0
systemd:
  units:
    # installing nano as a layered package with rpm-ostree
    - name: layer-nano.service
      enabled: true
      contents: |
        [Unit]
        Description=Layer nano as with rpm-ostree
        # We run after `systemd-machine-id-commit.service` to ensure that
        # `ConditionFirstBoot=true` services won't rerun on the next boot.
        After=systemd-machine-id-commit.service

        [Service]
        Type=oneshot
        RemainAfterExit=yes
        ExecStart=/usr/bin/rpm-ostree install nano --reboot

        [Install]
        WantedBy=multi-user.target

If that works, I’ could contribute that to the Fedora documentation…

Do you think this would be another useful example? I could certainly contribute that…
Especially if the cgroups v2 thing is deleted when the change is long gone, maybe it could show a way to run custom stuff after systemd-machine-id-commit so it’s not re-done to often…

Maybe also show a full use case of using nano as your default editor?

variant: fcos
version: 1.3.0
storage:
  files:
    # use nano as default editor
    - path: /etc/profile.d/nano.sh
      overwrite: true
      contents:
        inline: |
          #/bin/sh
          export EDITOR=nano
systemd:
  units:
    # installing nano as a layered package with rpm-ostree
    - name: layer-nano.service
      enabled: true
      contents: |
        [Unit]
        Description=Layer nano as with rpm-ostree
        # We run after `systemd-machine-id-commit.service` to ensure that
        # `ConditionFirstBoot=true` services won't rerun on the next boot.
        After=systemd-machine-id-commit.service

        [Service]
        Type=oneshot
        RemainAfterExit=yes
        ExecStart=/usr/bin/rpm-ostree install nano --reboot

        [Install]
        WantedBy=multi-user.target

Do I miss something?

Oh yeah, maybe I miss a Condition… so it does not re-run, do I?

3 Likes

For this I guess, I would have to query rpm-ostree first. I saw it has a JSON interface and JSONPath, so I tried using that like this: $ rpm-ostree status --booted --jsonpath='$.deployments[?(@.booted == true)].packages[*]', but I’m either to stupid to use JSONPath or rpm-ostree or the online tools I used for comparison have a problem.

1 Like

In a cloud environment (thinking EC2 with autoscaling) I wonder how long that would take and how it would impact the server being “ready”. I’ve managed to manually download and install binaries with hash verification but it would be nice to see some documentation on this.

This is definitely useful. The upstream issue for support in Butane is Adding a package to OS install · Issue #81 · coreos/butane · GitHub.

See also Improve package layering UX · Issue #681 · coreos/fedora-coreos-tracker · GitHub

1 Like

Well… static binaries are not so nice and layering is IMHO better.

Thanks, yeah, I guess this is very useful.

However is there any solution for my rpm-ostree/condition problem already?
Or am I stupid and oneshot services do not re-run, and only run at provisioning once?

oneshot services run every boot. You should adapt those from the cgroups v2 example:

[Unit]
...
ConditionPathExists=!/var/lib/cgroups-v2-karg.stamp

[Service]
Type=oneshot
...
ExecStart=/bin/touch /var/lib/cgroups-v2-karg.stamp

1 Like

Oh of course, I did not see that…

Then I also don’t need to check whether the package is already installed or whatever…

So, as said…:

I’ve created a PR now:

:tada:

1 Like

Okay, also tested practically and I first got a network error with 34.20210427.3.0 – but I guess this is related to the usual networking problems:

rpm-ostree-install-nano.service - Layer nano with rpm-ostree
     Loaded: loaded (/etc/systemd/system/rpm-ostree-install-nano.service; enabled; vendor preset: enabled)
     Active: failed (Result: exit-code) since Mon 2021-05-24 10:29:15 UTC; 37min ago
    Process: 3775 ExecStart=/usr/bin/rpm-ostree install --allow-inactive nano (code=exited, status=1/FAILURE)
   Main PID: 3775 (code=exited, status=1/FAILURE)

May 24 10:29:13 ***** systemd[1]: Starting Layer nano with rpm-ostree...
May 24 10:29:15 ***** rpm-ostree[3775]: Checking out tree b4b2199...done
May 24 10:29:15 ***** rpm-ostree[3775]: Enabled rpm-md repositories: fedora-cisco-openh264 updates fedora
May 24 10:29:15 ***** rpm-ostree[3775]: Updating metadata for 'fedora-cisco-openh264'...done
May 24 10:29:15 ***** rpm-ostree[3775]: error: Updating rpm-md repo 'fedora-cisco-openh264': cannot update repo 'fedora-cisco-openh264': Cannot prepare internal mirrorlist: Curl error (6): Couldn't resolve host name for https://mirrors.fedoraproject.org/metalink?repo=fedora-cisco-openh264-34&arch=x86_64 [Could not resolve host: mirrors.fedoraproject.org]; Last error: Curl error (6): Couldn't resolve host name for https://mirrors.fedoraproject.org/metalink?repo=fedora-cisco-openh264-34&arch=x86_64 [Could not resolve host: mirrors.fedoraproject.org]
May 24 10:29:15 ***** systemd[1]: rpm-ostree-install-nano.service: Main process exited, code=exited, status=1/FAILURE
May 24 10:29:15 ***** systemd[1]: rpm-ostree-install-nano.service: Failed with result 'exit-code'.
May 24 10:29:15 ***** systemd[1]: Failed to start Layer nano with rpm-ostree.

Howver, one can simply start the service then again to correct this sudo systemctl start rpm-ostree-install-nano.service.

BTW my written doc is live now! :tada:

So here is the doc:
https://docs.fedoraproject.org/en-US/fedora-coreos/layering-packages/

Nice work!

1 Like

The solution has evolved and I think the best/latest is now in the official docs here (some of prior links above now invalid):

1 Like

Would that approach also work for provisioning CoreOS with zfs support?
From what I see here (GitHub - coreos/layering-examples, second example) the rpms would need to be built in a container first and the system then rebased.

Will this also work during provisioning if set up as a oneshot systemd unit?

I would like to provision a system that can mount zfs pools at first boot.