max / alloy
| 1 | #!/bin/sh |
| 2 | # alloy-layer-repos — fence the first boot's layering to the carried repo. |
| 3 | # |
| 4 | # alloy-layer-components.service installs the console and terminal from |
| 5 | # /usr/share/alloy/rpm, a file:// repo that ships on the medium precisely so an |
| 6 | # offline install produces a working machine (docs/STACK.md, Hotfixes). It did |
| 7 | # not. rpm-ostree refreshes metadata for every ENABLED repo before it |
| 8 | # depsolves, and the image leaves Fedora's own four enabled, so a first boot |
| 9 | # with no name resolution failed like this and left the machine with no |
| 10 | # console: |
| 11 | # |
| 12 | # error: Updating rpm-md repo 'fedora-cisco-openh264': Cannot prepare |
| 13 | # internal mirrorlist: Curl error (6): Could not resolve hostname for |
| 14 | # https://mirrors.fedoraproject.org/metalink?repo=fedora-cisco-openh264-43 |
| 15 | # |
| 16 | # Measured 2026-08-25 on an installed server-profile machine in qemu, and |
| 17 | # reproduced by hand afterwards, so it is not a boot-ordering race. |
| 18 | # |
| 19 | # WHY THE FLAGS ARE NOT THE ANSWER. Both levers rpm-ostree offers are refused |
| 20 | # outside a container build, which docs/STACK.md already records for the first |
| 21 | # of them: |
| 22 | # |
| 23 | # # rpm-ostree install --enablerepo=alloy-local alloy |
| 24 | # error: --enablerepo currently only works in a container build |
| 25 | # # rpm-ostree install --disablerepo="*" alloy |
| 26 | # error: --disablerepo currently only works in a container build |
| 27 | # |
| 28 | # `--cache-only` is not the answer either: it reads cached metadata and |
| 29 | # refreshes none, so on a machine that has never refreshed anything it answers |
| 30 | # `error: Packages not found: alloy` with the packages sitting on the disk. |
| 31 | # |
| 32 | # So the repo set the daemon reads is the only lever, and this moves it for the |
| 33 | # length of one transaction. `off` disables everything but the carried repo; |
| 34 | # `on` puts /etc back. Both are idempotent. |
| 35 | # |
| 36 | # WHY `on` COPIES FROM /usr/etc RATHER THAN FROM A BACKUP. /usr/etc is the |
| 37 | # image's own /etc, so it is authoritative and it is always there. A backup in |
| 38 | # /run is not: a machine that loses power between `off` and `on` comes back |
| 39 | # with the repos disabled and the backup gone. The unit runs `on` before `off` |
| 40 | # for that reason as well as after, so an interrupted first boot heals itself |
| 41 | # on the next one rather than leaving a machine whose repos are quietly off. |
| 42 | # |
| 43 | # WHAT IT DOES NOT LEAK. The deployment the transaction stages does not inherit |
| 44 | # the disabled files: measured by rebooting into it, where the enabled set is |
| 45 | # alloy-local plus Fedora's four, as on any other machine. ostree's /etc merge |
| 46 | # reads the state /etc is left in, and `on` runs before the reboot. |
| 47 | # |
| 48 | # NOT A USER-FACING REPO POLICY. Which repos an installed Alloy leaves enabled |
| 49 | # is unchanged by this, deliberately: `alloy pkg` layers Fedora packages, and a |
| 50 | # machine that ships them disabled is a machine where that quietly finds |
| 51 | # nothing. The fence exists for one transaction on one boot. |
| 52 | # |
| 53 | # Deliberately dependency-free, and on the boot path in front of the only thing |
| 54 | # that gives the machine a console: sh, sed, cp, a glob. Same argument as |
| 55 | # alloy-layer-notice's. |
| 56 | |
| 57 | |
| 58 | |
| 59 | REPOS=/etc/yum.repos.d |
| 60 | SHIPPED=/usr/etc/yum.repos.d |
| 61 | CARRIED=alloy-local.repo |
| 62 | |
| 63 | case "" in |
| 64 | off) |
| 65 | [ || |
| 66 | for; do |
| 67 | [ || continue |
| 68 | [ || continue |
| 69 | |
| 70 | done |
| 71 | ;; |
| 72 | on) |
| 73 | # A missing /usr/etc means this is not an ostree deployment at all, |
| 74 | # which is a dev box running the script by hand. Nothing to put back. |
| 75 | [ || |
| 76 | for; do |
| 77 | [ || continue |
| 78 | |
| 79 | done |
| 80 | ;; |
| 81 | *) |
| 82 | |
| 83 | |
| 84 | ;; |
| 85 | esac |
| 86 |