diff --git a/.gitignore b/.gitignore index 8703795..8199d78 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ cosign.key cosign.private /Containerfile +/.bluebuild-scripts_* diff --git a/README.md b/README.md index 351f8a0..5d78b16 100644 --- a/README.md +++ b/README.md @@ -1,43 +1,42 @@ -# randofin-os   [![bluebuild build badge](https://github.com/randogoth/randofin-os/actions/workflows/build.yml/badge.svg)](https://github.com/randogoth/randofin-os/actions/workflows/build.yml) +# Deinonyxus   [![bluebuild build badge](https://github.com/randogoth/deinonyxus/actions/workflows/build.yml/badge.svg)](https://github.com/randogoth/deinonyxus/actions/workflows/build.yml) -See the [BlueBuild docs](https://blue-build.org/how-to/setup/) for quick setup instructions for setting up your own repository based on this template. +*Deinonyxus* is a personal spin of the UBlue Bluefin DX image with experimental Nix package manager baked in (borrowed from the great [Daemonix](https://github.com/DXC-0/daemonix/) image) and a first-login bootstrap for `home-manager` packages. -After setup, it is recommended you update this README to describe your custom image. +## What’s inside +- Base: `ghcr.io/ublue-os/bluefin-dx:latest` without Cockpit, Docker, Firefox, VS Code +- Nix: multi-user install baked in; `nix-overlay.service` and `nix-daemon.service` enabled. +- First-login bootstrap: installs nix packages `uv micro vscodium mc` via `home-manager`. +- System packages added: `syncthing`, `waydroid`; +- System flatpaks added: Telegram Desktop, Waterfox -## Installation +## First login behavior +- Triggers for each non-root user on their first session. +- Writes state to `~/.local/state/deinonyxus/nixpkgs-init.done`; delete it to rerun. +- Bootstraps `~/.config/home-manager/home.nix` and runs `home-manager switch` with the package set above. -> [!WARNING] -> [This is an experimental feature](https://www.fedoraproject.org/wiki/Changes/OstreeNativeContainerStable), try at your own discretion. - -To rebase an existing atomic Fedora installation to the latest build: - -- First rebase to the unsigned image, to get the proper signing keys and policies installed: - ``` - rpm-ostree rebase ostree-unverified-registry:ghcr.io/randogoth/randofin-os:latest - ``` -- Reboot to complete the rebase: - ``` - systemctl reboot - ``` -- Then rebase to the signed image, like so: - ``` - rpm-ostree rebase ostree-image-signed:docker://ghcr.io/randogoth/randofin-os:latest - ``` -- Reboot again to complete the installation - ``` - systemctl reboot - ``` - -The `latest` tag will automatically point to the latest build. That build will still always use the Fedora version specified in `recipe.yml`, so you won't get accidentally updated to the next major version. - -## ISO - -If build on Fedora Atomic, you can generate an offline ISO with the instructions available [here](https://blue-build.org/learn/universal-blue/#fresh-install-from-an-iso). These ISOs cannot unfortunately be distributed on GitHub for free due to large sizes, so for public projects something else has to be used for hosting. - -## Verification - -These images are signed with [Sigstore](https://www.sigstore.dev/)'s [cosign](https://github.com/sigstore/cosign). You can verify the signature by downloading the `cosign.pub` file from this repo and running the following command: +## Install / Rebase +> [!WARNING] +> Uses the Fedora Atomic native container workflow. ```bash -cosign verify --key cosign.pub ghcr.io/randogoth/randofin-os +# First pull unsigned to get signing policy +rpm-ostree rebase ostree-unverified-registry:ghcr.io/randogoth/deinonyxus:latest +systemctl reboot + +# Then move to the signed image +rpm-ostree rebase ostree-image-signed:docker://ghcr.io/randogoth/deinonyxus:latest +systemctl reboot ``` + +The `latest` tag always tracks the latest build for the Fedora base set in `recipes/recipe.yml`. + +## Building locally +```bash +bluebuild build --recipe recipes/recipe.yml +``` + +## Signature verification +Images are signed with Sigstore/cosign. Verify with the repo's `cosign.pub`: +```bash +cosign verify --key cosign.pub ghcr.io/randogoth/deinonyxus +``` \ No newline at end of file diff --git a/files/scripts/example.sh b/files/scripts/example.sh deleted file mode 100644 index 1cded87..0000000 --- a/files/scripts/example.sh +++ /dev/null @@ -1,6 +0,0 @@ -#!/usr/bin/env bash - -# Tell this script to exit if there are any errors. -# You should have this in every custom script, to ensure that your completed -# builds actually ran successfully without any errors! -set -oue pipefail \ No newline at end of file diff --git a/files/scripts/install-nix.sh b/files/scripts/install-nix.sh new file mode 100755 index 0000000..05e0457 --- /dev/null +++ b/files/scripts/install-nix.sh @@ -0,0 +1,20 @@ +#!/usr/bin/env bash +set -euo pipefail + +rpm_url="https://nix-community.github.io/nix-installers/nix/x86_64/nix-multi-user-2.24.10.rpm" + +install -d /usr/share/nix-store /var/lib/nix-store /var/cache/nix-store /nix + +# Avoid systemd calls during RPM %post in the image build environment. +export SYSTEMD_OFFLINE=1 + +# Install the RPM; allow missing GPG key since we fetch directly by URL. +dnf install -y --nogpgcheck "$rpm_url" + +# Move the pre-populated store out of /nix so it can serve as the immutable lowerdir. +if compgen -G "/nix/*" >/dev/null; then + mv /nix/* /usr/share/nix-store/ +fi + +# The RPM %post handles sysusers/tmpfiles; if we ran with SYSTEMD_OFFLINE the +# post scripts are still executed, so no extra calls are needed here. diff --git a/files/scripts/nixpkgs.sh b/files/scripts/nixpkgs.sh new file mode 120000 index 0000000..a232a07 --- /dev/null +++ b/files/scripts/nixpkgs.sh @@ -0,0 +1 @@ +../system/usr/libexec/randofin-os/nixpkgs.sh \ No newline at end of file diff --git a/files/system/etc/modules-load.d/overlay.conf b/files/system/etc/modules-load.d/overlay.conf new file mode 100644 index 0000000..08047cf --- /dev/null +++ b/files/system/etc/modules-load.d/overlay.conf @@ -0,0 +1 @@ +overlay diff --git a/files/system/usr/bin/mount-nix-overlay.sh b/files/system/usr/bin/mount-nix-overlay.sh new file mode 100755 index 0000000..22ad012 --- /dev/null +++ b/files/system/usr/bin/mount-nix-overlay.sh @@ -0,0 +1,13 @@ +#!/usr/bin/env bash +set -euo pipefail + +mkdir -p /usr/share/nix-store /var/lib/nix-store /var/cache/nix-store /nix + +# Skip if already mounted to avoid errors on reload. +if mountpoint -q /nix; then + exit 0 +fi + +mount -t overlay overlay \ + -o lowerdir=/usr/share/nix-store,upperdir=/var/lib/nix-store,workdir=/var/cache/nix-store \ + /nix diff --git a/files/system/usr/bin/nix-toolbox-ensure b/files/system/usr/bin/nix-toolbox-ensure deleted file mode 100755 index 690afc4..0000000 --- a/files/system/usr/bin/nix-toolbox-ensure +++ /dev/null @@ -1,22 +0,0 @@ -#!/usr/bin/env bash -set -euo pipefail - -image_ref="${NIX_TOOLBOX_IMAGE:-ghcr.io/thrix/nix-toolbox:42}" -container_name="${NIX_TOOLBOX_CONTAINER:-nix-toolbox-42}" - -if ! command -v toolbox >/dev/null 2>&1; then - echo "toolbox not installed; skipping nix-toolbox setup" >&2 - exit 0 -fi - -if ! command -v podman >/dev/null 2>&1; then - echo "podman not installed; skipping nix-toolbox setup" >&2 - exit 0 -fi - -if podman container exists "$container_name"; then - exit 0 -fi - -echo "Creating $container_name from $image_ref" -distrobox create --name "$container_name" --image "$image_ref" diff --git a/files/system/usr/lib/systemd/system/nix-overlay.service b/files/system/usr/lib/systemd/system/nix-overlay.service new file mode 100644 index 0000000..df9b154 --- /dev/null +++ b/files/system/usr/lib/systemd/system/nix-overlay.service @@ -0,0 +1,14 @@ +[Unit] +Description=Mount OverlayFS for /nix +DefaultDependencies=no +After=local-fs.target +Before=nix-daemon.service +ConditionPathExists=/usr/bin/mount-nix-overlay.sh + +[Service] +Type=oneshot +ExecStart=/usr/bin/mount-nix-overlay.sh +RemainAfterExit=yes + +[Install] +WantedBy=multi-user.target diff --git a/files/system/usr/lib/systemd/user/default.target.wants/randofin-nixpkgs-init.service b/files/system/usr/lib/systemd/user/default.target.wants/randofin-nixpkgs-init.service new file mode 120000 index 0000000..5f245da --- /dev/null +++ b/files/system/usr/lib/systemd/user/default.target.wants/randofin-nixpkgs-init.service @@ -0,0 +1 @@ +../randofin-nixpkgs-init.service \ No newline at end of file diff --git a/files/system/usr/lib/systemd/user/nix-toolbox-create.service b/files/system/usr/lib/systemd/user/nix-toolbox-create.service deleted file mode 100644 index 686483a..0000000 --- a/files/system/usr/lib/systemd/user/nix-toolbox-create.service +++ /dev/null @@ -1,14 +0,0 @@ -[Unit] -Description=Ensure nix-toolbox container is available for this user -After=network-online.target -Wants=network-online.target - -[Service] -Type=oneshot -ExecStart=/usr/bin/nix-toolbox-ensure -RemainAfterExit=yes -Restart=on-failure -RestartSec=10 - -[Install] -WantedBy=default.target diff --git a/files/system/usr/lib/systemd/user/randofin-nixpkgs-init.service b/files/system/usr/lib/systemd/user/randofin-nixpkgs-init.service new file mode 100644 index 0000000..4e1ca95 --- /dev/null +++ b/files/system/usr/lib/systemd/user/randofin-nixpkgs-init.service @@ -0,0 +1,13 @@ +[Unit] +Description=Install Nix Home Manager and packages on first login +ConditionUser=!root +ConditionPathExists=!%h/.local/state/deinonyxus/nixpkgs-init.done + +[Service] +Type=oneshot +ExecStart=/usr/libexec/deinonyxus/nixpkgs.sh +ExecStartPost=/usr/bin/mkdir -p %h/.local/state/deinonyxus +ExecStartPost=/usr/bin/touch %h/.local/state/deinonyxus/nixpkgs-init.done + +[Install] +WantedBy=default.target diff --git a/files/system/usr/libexec/deinonyxus/nixpkgs.sh b/files/system/usr/libexec/deinonyxus/nixpkgs.sh new file mode 100755 index 0000000..dae46d0 --- /dev/null +++ b/files/system/usr/libexec/deinonyxus/nixpkgs.sh @@ -0,0 +1,23 @@ +#!/usr/bin/env bash +set -oue pipefail +nix run github:nix-community/home-manager/release-25.11 -- init --switch + +pkgs='uv micro vscodium mc' +f=~/.config/home-manager/home.nix +tmp="$(mktemp)" +{ + echo " home.packages = [" + for p in $pkgs; do echo " pkgs.$p"; done + echo " ];" +} > "$tmp" + +sed -i "/^[[:space:]]*home\.packages[[:space:]]*=[[:space:]]*\[/,/^[[:space:]]*];[[:space:]]*$/{ + /^[[:space:]]*home\.packages[[:space:]]*=/{ + r $tmp + } + d +}" "$f" + +rm -f "$tmp" + +home-manager switch diff --git a/recipes/recipe.yml b/recipes/recipe.yml index b9356c8..f169d3e 100644 --- a/recipes/recipe.yml +++ b/recipes/recipe.yml @@ -1,7 +1,7 @@ --- # yaml-language-server: $schema=https://schema.blue-build.org/recipe-v1.json # image will be published to ghcr.io// -name: randofin-os +name: deinonyxus # description will be included in the image's metadata description: This is my personal spin based on the latest bluefin image. @@ -18,10 +18,15 @@ modules: - source: system destination: / # copies files/system/* (* means everything inside it) into your image's root folder / + - type: script + scripts: + - install-nix.sh + - type: systemd - user: + system: enabled: - - nix-toolbox-create.service + - nix-overlay.service + - nix-daemon.service - type: dnf install: @@ -55,7 +60,6 @@ modules: # If no repo information is specified, Flathub will be used by default install: # system flatpaks we want all users to have and not remove - net.waterfox.waterfox - - com.vscodium.codium - org.telegram.desktop remove: # replace default Firefox with Waterfox - org.mozilla.firefox