···11+{
22+ self,
33+ config,
44+ pkgs,
55+ lib,
66+ ...
77+}:
88+{
99+ imports = [
1010+ ../../2configs
1111+ ../../2configs/desktops/sway/default.nix
1212+ ../../2configs/pipewire.nix
1313+ ../../2configs/network-manager.nix
1414+ self.wrapperModules.workspace-manager
1515+ ];
1616+1717+ krebs.build.host.name = "atlas";
1818+ system.stateVersion = "25.05";
1919+2020+ lass.workspace-manager.enable = true;
2121+2222+ nix.settings.trusted-users = [
2323+ "root"
2424+ "lass"
2525+ ];
2626+2727+ # Autostart straight into sway: greetd logs the main user in on boot with no
2828+ # prompt and execs sway (a login shell so the wrapped sway + session env from
2929+ # programs.sway are on PATH). default_session with a real user means every
3030+ # (re)start goes directly into the session — there is no greeter.
3131+ services.greetd = {
3232+ enable = true;
3333+ settings.default_session = {
3434+ command = "${lib.getExe pkgs.bash} --login -c sway";
3535+ user = config.users.users.mainUser.name;
3636+ };
3737+ };
3838+3939+ # Stateless box: no password/credential is baked into the image, so a screen
4040+ # lock could never be unlocked (swaylock PAM has nothing to accept). Disable
4141+ # the desktop's idle auto-lock (swayidle: lock after 120s, suspend-then-
4242+ # hibernate after 300s) and the lock service itself. The $mod+l / $mod+F11
4343+ # lock keybinds then start an empty lock.target and harmlessly do nothing.
4444+ systemd.user.services.swayidle.enable = lib.mkForce false;
4545+ systemd.user.services.swaylock.enable = lib.mkForce false;
4646+4747+ # Noctalia pops a one-time "Privacy Update" telemetry wizard whenever its
4848+ # cache (~/.cache/noctalia/shell-state.json) has an empty
4949+ # changelogState.lastSeenVersion (UpdateService.shouldShowTelemetryWizard,
5050+ # gated only on that cache — not on any setting). This box is stateless, so
5151+ # the cache is wiped every boot and the wizard returned on every start.
5252+ # Seed the cache before noctalia launches with the current version, so it
5353+ # treats the changelog/telemetry notice as already seen (and, since
5454+ # lastSeen == currentVersion, the changelog stays closed too).
5555+ systemd.user.services.noctalia-seed-state = {
5656+ description = "Seed noctalia changelog cache (suppress telemetry wizard on stateless boots)";
5757+ partOf = [ "sway-session.target" ];
5858+ wantedBy = [ "noctalia-shell.service" ];
5959+ before = [ "noctalia-shell.service" ];
6060+ serviceConfig = {
6161+ Type = "oneshot";
6262+ RemainAfterExit = true;
6363+ ExecStart = pkgs.writeShellScript "noctalia-seed-state" ''
6464+ set -eu
6565+ dir="''${XDG_CACHE_HOME:-$HOME/.cache}/noctalia"
6666+ f="$dir/shell-state.json"
6767+ ver="v${pkgs.noctalia-shell.version}"
6868+ mkdir -p "$dir"
6969+ if [ -s "$f" ]; then
7070+ ${pkgs.jq}/bin/jq --arg v "$ver" \
7171+ '.changelogState.lastSeenVersion = (if (.changelogState.lastSeenVersion // "") == "" then $v else .changelogState.lastSeenVersion end)' \
7272+ "$f" > "$f.tmp" && mv "$f.tmp" "$f"
7373+ else
7474+ ${pkgs.jq}/bin/jq -n --arg v "$ver" '{changelogState:{lastSeenVersion:$v}}' > "$f"
7575+ fi
7676+ '';
7777+ };
7878+ };
7979+}
···11+{
22+ modulesPath,
33+ pkgs,
44+ lib,
55+ ...
66+}:
77+{
88+ imports = [
99+ ./config.nix
1010+ (modulesPath + "/installer/scan/not-detected.nix")
1111+ # Two boot media from one config. Every entry in image.modules is applied
1212+ # to this config through its own extendModules, so the iso and netboot
1313+ # variants never see each other's fileSystems / bootloader definitions —
1414+ # no disabledModules or mkForce juggling needed.
1515+ #
1616+ # nixos-rebuild build-image --flake .#atlas --image-variant iso
1717+ # nix build .#nixosConfigurations.atlas.config.system.build.images.iso
1818+ # nix build .#atlas-netboot-root (kernel+initrd+ipxe for PXE)
1919+ (modulesPath + "/image/images.nix")
2020+ ];
2121+2222+ # Deliberately no image module at the toplevel: nixpkgs warns that doing so
2323+ # defines system.build.image and leaks the medium into every variant. That
2424+ # leaves the base config without a real boot medium, so these two
2525+ # placeholders exist only to let it evaluate; both image variants override
2626+ # the root with mkImageMediaOverride (priority 60), which wins over these.
2727+ # The base toplevel itself is never booted or deployed.
2828+ fileSystems."/" = {
2929+ device = "tmpfs";
3030+ fsType = "tmpfs";
3131+ };
3232+ boot.loader.grub.enable = lib.mkDefault false;
3333+3434+ # Live USB stick: store is a squashfs on the stick, root a tmpfs overlay on
3535+ # top. Stateless, nothing installed — dd it and boot.
3636+ #
3737+ # The built-in `iso` variant is iso-image.nix (not installation-cd-base):
3838+ # no nixos channel, no installer profile, no `nixos` autologin to fight
3939+ # greetd or clash with 2configs/pinned-registry.nix. Settings here merge
4040+ # into it, since image.modules is an attrsOf deferredModule.
4141+ image.modules.iso = {
4242+ # zstd keeps the squashfs small without a slow xz build.
4343+ isoImage.squashfsCompression = "zstd -Xcompression-level 6";
4444+ isoImage.makeEfiBootable = true;
4545+ isoImage.makeUsbBootable = true;
4646+ image.baseName = lib.mkForce "atlas";
4747+ image.fileName = lib.mkForce "atlas.iso";
4848+ };
4949+5050+ # PXE/netboot: iPXE pulls bzImage + initrd, so nothing has to be flashed to
5151+ # iterate. The whole store rides inside the initrd (~3.8 GB), which is why
5252+ # it has to be served over HTTP rather than TFTP — see nat-share --pxe/--http.
5353+ image.modules.netboot = {
5454+ imports = [ (modulesPath + "/installer/netboot/netboot.nix") ];
5555+ netboot.squashfsCompression = "zstd -Xcompression-level 6";
5656+ };
5757+5858+ nixpkgs.hostPlatform = "x86_64-linux";
5959+6060+ boot.kernelPackages = pkgs.linuxPackages_latest;
6161+6262+ # AMD Radeon (Navi 14 / RX 5500-class, PCI 1002:7340) -> amdgpu.
6363+ #
6464+ # amdgpu is deliberately NOT in boot.initrd.kernelModules: early-loading it
6565+ # tears down efifb before the GPU firmware is available in stage-1, which
6666+ # black-screens this card from the moment the kernel starts (measured: ~5min
6767+ # to reach systemd). Let udev load amdgpu in stage-2, where the firmware is
6868+ # present. hardware.amdgpu.initrd.enable is the same trap — it only adds the
6969+ # module and handles no firmware.
7070+ hardware.graphics.enable = true;
7171+ hardware.graphics.enable32Bit = true;
7272+ hardware.enableRedistributableFirmware = true;
7373+ services.xserver.videoDrivers = [ "amdgpu" ];
7474+ boot.kernelModules = [ "kvm-intel" ];
7575+7676+ # Boot the live image off a USB mass-storage device. (Inert for netboot,
7777+ # where iPXE has already fetched kernel+initrd before the kernel starts.)
7878+ boot.initrd.availableKernelModules = [
7979+ "xhci_pci"
8080+ "ehci_pci"
8181+ "ahci"
8282+ "usb_storage"
8383+ "uas"
8484+ "usbhid"
8585+ "sd_mod"
8686+ ];
8787+8888+ # Initrd size dominates boot for both media: GRUB reads it off USB at
8989+ # roughly 1 MB/s (measured: 59s loader phase vs 6.5s kernel + 4.5s initrd +
9090+ # 10s userspace), and for netboot it travels with the store image.
9191+ #
9292+ # It was 29 MB compressed / 83 MB unpacked, of which only 1.8 MB was kernel
9393+ # modules — the rest was the systemd-initrd closure (openssl, lvm2,
9494+ # cryptsetup, tpm2-tss, curl, krb5, bash-interactive). Stage 1 only has to
9595+ # find the boot medium and mount squashfs+overlay: no LUKS, no LVM, no TPM,
9696+ # no network. The scripted initrd drops that closure: 29 MB -> 11 MB.
9797+ boot.initrd.systemd.enable = lib.mkForce false;
9898+ boot.initrd.systemd.emergencyAccess = lib.mkForce false;
9999+ boot.initrd.services.lvm.enable = lib.mkForce false;
100100+101101+ # Name the onboard Intel NIC deterministically.
102102+ services.udev.extraRules = ''
103103+ SUBSYSTEM=="net", ATTR{address}=="70:85:c2:0e:ea:3c", NAME="et0"
104104+ '';
105105+106106+ # Stateless box: no clan secrets are deployed, so don't try to load an
107107+ # openssh host key from a vars path that will never exist on the live
108108+ # system. Let sshd generate an ephemeral key at boot instead.
109109+ services.openssh.hostKeys = lib.mkForce [
110110+ {
111111+ path = "/etc/ssh/ssh_host_ed25519_key";
112112+ type = "ed25519";
113113+ }
114114+ ];
115115+}