commit 9e1a7021e198ce468fb67527408182de90b49d64 Author: Lucas Seidelin Rosenvold Christensen Date: Fri Sep 18 14:59:24 2026 +0200 First tiny working commit diff --git a/Containerfile b/Containerfile new file mode 100644 index 0000000..2e98848 --- /dev/null +++ b/Containerfile @@ -0,0 +1,9 @@ +FROM quay.io/fedora/fedora-coreos:stable + +COPY post-install.sh /tmp/post-install.sh +COPY post-install/ /tmp/post-install/ +RUN chmod +x /tmp/post-install.sh \ + && /tmp/post-install.sh \ + && rm -rf /tmp/post-install.sh /tmp/post-install + +RUN bootc container lint diff --git a/Justfile b/Justfile new file mode 100644 index 0000000..0f0aa8b --- /dev/null +++ b/Justfile @@ -0,0 +1,19 @@ +image := "rosenvold-core" +tag := "latest" +fcos_stable := "quay.io/fedora/fedora-coreos:stable" + +# List available recipes +default: + @just --list + +# Build the bootc container image +build: + docker build -t {{image}}:{{tag}} -f Containerfile . + +# Build and validate the image with bootc container lint +test: build + docker run --rm {{image}}:{{tag}} bootc container lint + +# Remove the built image +clean: + docker rmi -f {{image}}:{{tag}} diff --git a/examples/rosenvold-core-autorebase.butane b/examples/rosenvold-core-autorebase.butane new file mode 100644 index 0000000..ea8a314 --- /dev/null +++ b/examples/rosenvold-core-autorebase.butane @@ -0,0 +1,52 @@ +variant: fcos +version: 1.4.0 +passwd: + users: + - name: core + ssh_authorized_keys: + - YOUR_SSH_PUB_KEY_HERE + password_hash: YOUR_GOOD_PASSWORD_HASH_HERE + groups: + - docker +storage: + directories: + - path: /etc/rosenvold-core-autorebase + mode: 0754 +systemd: + units: + - name: rosenvold-core-unsigned-autorebase.service + enabled: true + contents: | + [Unit] + Description=rosenvold-core autorebase to unsigned OCI and reboot + ConditionPathExists=!/etc/rosenvold-core-autorebase/unverified + ConditionPathExists=!/etc/rosenvold-core-autorebase/signed + After=network-online.target + Wants=network-online.target + [Service] + Type=oneshot + StandardOutput=journal+console + ExecStart=/usr/bin/rpm-ostree rebase --bypass-driver ostree-unverified-registry:ghcr.io/rosenvold-technology/rosenvold-core:stable + ExecStart=/usr/bin/touch /etc/rosenvold-core-autorebase/unverified + ExecStart=/usr/bin/systemctl disable rosenvold-core-unsigned-autorebase.service + ExecStart=/usr/bin/systemctl reboot + [Install] + WantedBy=multi-user.target + - name: rosenvold-core-signed-autorebase.service + enabled: true + contents: | + [Unit] + Description=rosenvold-core autorebase to signed OCI and reboot + ConditionPathExists=/etc/rosenvold-core-autorebase/unverified + ConditionPathExists=!/etc/rosenvold-core-autorebase/signed + After=network-online.target + Wants=network-online.target + [Service] + Type=oneshot + StandardOutput=journal+console + ExecStart=/usr/bin/rpm-ostree rebase --bypass-driver ostree-image-signed:docker://ghcr.io/rosenvold-technology/rosenvold-core:stable + ExecStart=/usr/bin/touch /etc/rosenvold-core-autorebase/signed + ExecStart=/usr/bin/systemctl disable rosenvold-core-signed-autorebase.service + ExecStart=/usr/bin/systemctl reboot + [Install] + WantedBy=multi-user.target diff --git a/post-install.sh b/post-install.sh new file mode 100755 index 0000000..4a172c1 --- /dev/null +++ b/post-install.sh @@ -0,0 +1,35 @@ +#!/bin/sh +set -ouex pipefail + +## Regular post-install (adapted from ublue-os/ucore's post-install-ucore-minimal.sh +## for a plain Fedora CoreOS base with no extra packages installed) +## +## Implementation: each step lives in its own function/file under +## post-install/lib/.sh; this script only sources them and runs the +## steps in order. + +SCRIPT_DIR="$(dirname -- "$0")" +LIB_DIR="$SCRIPT_DIR/post-install/lib" + +# shellcheck source=post-install/lib/mask_migration_motd_units.sh +. "$LIB_DIR/mask_migration_motd_units.sh" +# shellcheck source=post-install/lib/enable_docker_socket.sh +. "$LIB_DIR/enable_docker_socket.sh" +# shellcheck source=post-install/lib/disable_zincati.sh +. "$LIB_DIR/disable_zincati.sh" +# shellcheck source=post-install/lib/configure_automatic_updates.sh +. "$LIB_DIR/configure_automatic_updates.sh" +# shellcheck source=post-install/lib/set_default_timezone.sh +. "$LIB_DIR/set_default_timezone.sh" +# shellcheck source=post-install/lib/set_rosenvold_branding.sh +. "$LIB_DIR/set_rosenvold_branding.sh" +# shellcheck source=post-install/lib/install_welcome_motd.sh +. "$LIB_DIR/install_welcome_motd.sh" + +mask_migration_motd_units +enable_docker_socket +disable_zincati +configure_automatic_updates +set_default_timezone +set_rosenvold_branding +install_welcome_motd diff --git a/post-install/lib/configure_automatic_updates.sh b/post-install/lib/configure_automatic_updates.sh new file mode 100644 index 0000000..7d8df12 --- /dev/null +++ b/post-install/lib/configure_automatic_updates.sh @@ -0,0 +1,5 @@ +# Stage rpm-ostree updates automatically instead of only checking for them. +configure_automatic_updates() { + systemctl enable rpm-ostreed-automatic.timer + sed -i 's/#AutomaticUpdatePolicy.*/AutomaticUpdatePolicy=stage/' /etc/rpm-ostreed.conf +} diff --git a/post-install/lib/disable_zincati.sh b/post-install/lib/disable_zincati.sh new file mode 100644 index 0000000..71d9543 --- /dev/null +++ b/post-install/lib/disable_zincati.sh @@ -0,0 +1,4 @@ +# Disable zincati; bootc image updates replace FCOS's default auto-updater. +disable_zincati() { + systemctl disable zincati.service +} diff --git a/post-install/lib/enable_docker_socket.sh b/post-install/lib/enable_docker_socket.sh new file mode 100644 index 0000000..16fd3c9 --- /dev/null +++ b/post-install/lib/enable_docker_socket.sh @@ -0,0 +1,4 @@ +# Enable Docker's socket-activated daemon. +enable_docker_socket() { + systemctl enable docker.socket +} diff --git a/post-install/lib/install_welcome_motd.sh b/post-install/lib/install_welcome_motd.sh new file mode 100644 index 0000000..92db736 --- /dev/null +++ b/post-install/lib/install_welcome_motd.sh @@ -0,0 +1,16 @@ +# Drop the upstream FCOS tracker/discuss motd (no longer accurate once +# rebranded) and replace it with our own welcome banner. +install_welcome_motd() { + rm -f /usr/lib/motd.d/tracker.motd + cat >/usr/lib/motd.d/10-rosenvold-welcome.motd <<'EOF' +Rosenvold CoreOS +──────────────── + +A personal Fedora CoreOS derivative, managed via bootc. + + bootc status show the current deployment + bootc upgrade check for and stage updates + journalctl -xe view recent logs + +EOF +} diff --git a/post-install/lib/mask_migration_motd_units.sh b/post-install/lib/mask_migration_motd_units.sh new file mode 100644 index 0000000..6955e42 --- /dev/null +++ b/post-install/lib/mask_migration_motd_units.sh @@ -0,0 +1,6 @@ +# Mask the FCOS -> ostree-container migration motd units up front so a +# future FCOS release doesn't surprise us with them mid-boot. +mask_migration_motd_units() { + systemctl mask coreos-container-signing-migration-motd.service + systemctl mask coreos-oci-migration-motd.service +} diff --git a/post-install/lib/set_default_timezone.sh b/post-install/lib/set_default_timezone.sh new file mode 100644 index 0000000..d25dc7c --- /dev/null +++ b/post-install/lib/set_default_timezone.sh @@ -0,0 +1,4 @@ +# FCOS container images ship without /etc/localtime; default to UTC. +set_default_timezone() { + ln -sf ../usr/share/zoneinfo/UTC /etc/localtime +} diff --git a/post-install/lib/set_rosenvold_branding.sh b/post-install/lib/set_rosenvold_branding.sh new file mode 100644 index 0000000..63243da --- /dev/null +++ b/post-install/lib/set_rosenvold_branding.sh @@ -0,0 +1,11 @@ +# Branding: rosenvold-core is a personal Fedora CoreOS derivative, so +# identify as such rather than as upstream Fedora CoreOS. ID/VARIANT_ID are +# left alone so tooling that keys off "fedora" family detection still works. +set_rosenvold_branding() { + sed -i \ + -e 's/^NAME=.*/NAME="Rosenvold CoreOS"/' \ + -e 's/Fedora CoreOS/Rosenvold CoreOS/' \ + -e 's/^VARIANT=.*/VARIANT="Rosenvold CoreOS"/' \ + -e 's/^VARIANT_ID=.*/VARIANT_ID=rosenvold-core/' \ + /usr/lib/os-release +}