No description
Find a file
TheDarkWizard 9682831d31
Pin the example to a commit instead of main
main.tar.gz is cached by nix for an hour, so pushed fixes kept looking
like no-ops while an old copy of this flake was served from cache.
A commit URL is unique and cannot be served stale.
2026-07-20 03:37:30 -05:00
examples Pin the example to a commit instead of main 2026-07-20 03:37:30 -05:00
files Port the GNOME edition to a NixOS flake 2026-07-20 03:13:13 -05:00
hosts Make the flake consumable and commit a lock 2026-07-20 03:25:26 -05:00
modules Let a machine override the edition's kernel, timezone and locale 2026-07-20 03:33:32 -05:00
.gitignore Port the GNOME edition to a NixOS flake 2026-07-20 03:13:13 -05:00
flake.lock Make the flake consumable and commit a lock 2026-07-20 03:25:26 -05:00
flake.nix Make the flake consumable and commit a lock 2026-07-20 03:25:26 -05:00
README.md Pin the example to a commit instead of main 2026-07-20 03:37:30 -05:00

monolith-nix

Monolith as a NixOS flake. GNOME edition, ported from the image side at monolith-os/monolith.

This is an experiment, not a replacement. Nothing here has been booted yet.

What this is

The image project builds 20 OS images nightly and users rebase onto them. This repo builds nothing. It is the config, and a machine assembles the system from it.

Normal use

Write /etc/nixos/flake.nix once. There is a copy at examples/etc-nixos-flake.nix:

{
  # Pinned to a commit, not main.tar.gz: nix caches tarball URLs for an hour, so
  # while this repo changes often main.tar.gz can hand back a stale copy and
  # make fixes look like they did nothing. Switch to main.tar.gz once settled.
  inputs.monolith.url = "tarball+https://forge.waywardinn.com/monolith-os/monolith-nix/archive/a79e906b2a5f79062984a4781d5aa3501773e0b4.tar.gz";

  outputs = { monolith, ... }: {
    # Name this after the machine's hostname. A fresh install is "nixos".
    nixosConfigurations.nixos = monolith.lib.mkEdition {
      edition = "gnome";
      modules = [
        ./hardware-configuration.nix

        {
          # UEFI. Check with: [ -d /sys/firmware/efi ] && echo UEFI || echo BIOS
          # For BIOS use boot.loader.grub.device = "/dev/vda"; instead.
          boot.loader.systemd-boot.enable = true;
          boot.loader.efi.canTouchEfiVariables = true;

          users.users.max = {
            isNormalUser = true;
            extraGroups = [ "wheel" "networkmanager" "libvirtd" ];
          };

          system.stateVersion = "25.11";
        }
      ];
    };
  };
}

Do not import the installer's configuration.nix. It is a complete system config, so its opinions collide with the edition's and you get a stream of option X is defined multiple times errors. Import only the machine facts, as above.

From then on, forever:

sudo nixos-rebuild switch             # apply now
sudo nixos-rebuild boot               # apply on next reboot
nix flake update --flake /etc/nixos   # pull newer Monolith and packages

No URLs, no flags. nixos-rebuild finds /etc/nixos/flake.nix on its own and picks the config matching the machine's hostname, which is why the output above is named after it.

switch is the normal one. boot only matters when you want the change to wait for a reboot, which is closer to how rebasing an image behaves.

One gotcha while this repo is changing often: your /etc/nixos/flake.lock pins this flake to an exact revision, so a rebuild keeps using the version you first fetched even after new commits land here. --refresh does NOT help, because a locked input stays locked. To pick up changes:

sudo nix flake update monolith --flake /etc/nixos   # move the pin
sudo nixos-rebuild switch

Or, bluntest and always works:

sudo rm /etc/nixos/flake.lock
sudo nixos-rebuild switch

Trying it without committing to anything

To build the demo machine straight from this repo, with its hardcoded disk layout and user:

nixos-rebuild build --flake 'tarball+https://forge.waywardinn.com/monolith-os/monolith-nix/archive/main.tar.gz#gnome'

build evaluates and compiles without touching the system, so it is the safe way to find out whether this config is currently broken.

Two footguns worth knowing, both hit while writing this:

  • Use tarball+https, not git+https. The git form needs git in the environment and a minimal NixOS install has none, giving error: executing "git": No such file or directory.
  • A remote flake cannot write a lock file, so this repo commits flake.lock. If you ever see cannot write modified lock file, the lock is missing or stale and needs regenerating with nix flake lock.

Layout

Here Image side
flake.nix no equivalent (this is what makes it consumable)
hosts/gnome.nix recipes/recipe-gnome.yml
modules/common.nix recipes/common.yml
modules/desktop-gnome.nix recipes/gnome.yml + zzz-monolith.gschema.override + files/gnome
modules/kernel.nix the CachyOS swap script in common.yml
modules/flatpaks.nix the default-flatpaks modules
modules/branding.nix logo/fastfetch bits of files/system

Before this boots

Nothing in here has been evaluated, let alone run. Known work:

  1. Extension attribute names are unverified. modules/desktop-gnome.nix lists gnomeExtensions.* packages using conventional names that were not checked against nixpkgs. Four are commented out because they probably do not exist there at all: Add to Steam, Restart To, GNOME 4x UI Improvements, and Bazaar Companion (the image installs that one from git). nixos-rebuild will name whichever are wrong.

  2. Brave Origin nightly is not packaged. nixpkgs has stable brave, which is what this uses. Options: package the nightly yourself, run the Brave flatpak, or accept stable. Every reference (favorites, mimeapps, the Super+B bind) currently points at stable Brave.

  3. Secure Boot is not wired up. The image signs the CachyOS kernel with a MOK key at build time and enrolls it via ujust. The NixOS equivalent is lanzaboote, which needs keys generated per machine. Until then, install with Secure Boot disabled.

  4. Disks are label based. hosts/gnome.nix mounts by filesystem label (monolith for btrfs, MONOLITH-ESP for the ESP) so the config is machine independent. Either format with those labels or replace that block with nixos-generate-config output. Declaring the layout with disko is the tidier end state.

  5. Plymouth is stock. The image ships a watermark for the spinner theme; matching it needs a small theme derivation.

  6. The user is hardcoded in hosts/gnome.nix. Change it.

Deliberate differences from the image

  • No mesa swap. The image swaps Fedora's mesa for Terra's because Fedora's lags. nixos-unstable is already current, so this is unnecessary.
  • No package removals. The image subtracts firefox, htop and toolbox from a populated Fedora base. Nothing is installed here unless named.
  • No tea download script, no pure-fish git clone. Both are packages.
  • No versionlocking. flake.lock pins everything by definition.
  • Steam via programs.steam rather than a layered RPM, which brings the FHS wrapper Steam needs on a non-FHS system.

Still missing from the image's feature set

  • monolith-adopt and the Secure Boot enrollment ujust recipes
  • the firstboot deployment labelling service and monolith-image-status, both of which are bootc specific and have no meaning here
  • Home Manager, which is the real answer to the /etc/skel problem that made monolith-adopt necessary in the first place