From ae5ecbb4199844b2b7883d99cd04ef468a03247d Mon Sep 17 00:00:00 2001 From: "Henry J. Webster" Date: Thu, 30 Jul 2026 19:14:09 -0500 Subject: refactor: shared desktop profile for enzo + kusanagi profiles/desktop.nix becomes a username-agnostic shared base (niri, dconf, the dark-theme portal fix, greetd, pipewire base, gpg agent, graphics, Firefox with blank-home/no-bookmarks prefs, common desktop tools, font base). Both hosts now import it. Per-host desktop config splits into machines//desktop.nix: - enzo: Adwaita cursor + monospace, HiDPI console font, yambar, hwebs groups. - kusanagi (new file): GNOME/X11, printing/avahi/udisks2, pro-audio (rtkit/jack/32-bit), gpg ssh support, richer fonts, Bibata cursor, henz desktop groups, waybar/nm-applet. Shared profile is username-agnostic (enzo=hwebs, kusanagi=henz): shared desktop tools moved to environment.systemPackages, per-user groups stay in machine files. Firefox now owned by the shared profile, so its redundant enable is dropped from profiles/apps.nix. Dark theme + Firefox tweaks now apply to both hosts. Both configurations build. Assisted-by: Claude:claude-opus-4-8 --- machines/enzo/default.nix | 5 +- machines/enzo/desktop.nix | 126 ++++-------------------------------------- machines/kusanagi/default.nix | 1 + machines/kusanagi/desktop.nix | 119 +++++++++++++++++++++++++++++++++++++++ 4 files changed, 134 insertions(+), 117 deletions(-) create mode 100644 machines/kusanagi/desktop.nix (limited to 'machines') diff --git a/machines/enzo/default.nix b/machines/enzo/default.nix index 0e9d6e4..bcb92cb 100644 --- a/machines/enzo/default.nix +++ b/machines/enzo/default.nix @@ -3,8 +3,9 @@ { imports = [ - # enzo's own minimal desktop (not the shared profiles/desktop.nix). Add - # ../../profiles/dev.nix or apps.nix here, or one-off packages below, as needed. + # Shared desktop base + enzo-only extras. Add ../../profiles/dev.nix or + # apps.nix here, or one-off packages below, as needed. + ../../profiles/desktop.nix ./desktop.nix inputs.disko.nixosModules.disko diff --git a/machines/enzo/desktop.nix b/machines/enzo/desktop.nix index d92dda3..8375e13 100644 --- a/machines/enzo/desktop.nix +++ b/machines/enzo/desktop.nix @@ -1,135 +1,31 @@ -# Minimal niri desktop for enzo — deliberately separate from ../../profiles/desktop.nix -# so the laptop can grow on its own terms. Add to it (or switch to the shared -# profile) whenever you want more. +# enzo-only desktop extras. The shared niri/dark/audio/firefox base comes from +# ../../profiles/desktop.nix (imported in ./default.nix); this file holds just +# what's specific to the laptop. { pkgs, ... }: { - # --- Session / login --- - programs.niri.enable = true; - programs.dconf.enable = true; - - # Tell the desktop it's in dark mode. Apps read light/dark from - # xdg-desktop-portal's Settings interface (org.freedesktop.appearance - # color-scheme). This dconf default is the value the portal serves. - programs.dconf.profiles.user.databases = [ - { - settings."org/gnome/desktop/interface".color-scheme = "prefer-dark"; - } - ]; - - # Serve color-scheme from the *gtk* portal backend, not gnome. The niri module - # routes Settings to xdg-desktop-portal-gnome (its default), but that backend - # relies on gnome-settings-daemon — absent under bare niri — so it reports - # "no preference" and web content (LibreWolf's prefers-color-scheme) stays - # light even though GTK chrome follows the dark GTK theme. xdg-desktop-portal- - # gtk reads the dconf color-scheme above directly, so pinning Settings to it - # makes the portal actually report dark and content follows. This key merges - # into the niri module's xdg.portal.config.niri. - xdg.portal = { - extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; - config.niri."org.freedesktop.impl.portal.Settings" = "gtk"; - }; - - services.greetd = { - enable = true; - settings.default_session = { - command = "${pkgs.tuigreet}/bin/tuigreet --time --remember --cmd niri-session"; - user = "greeter"; - }; - }; - # Let tuigreet write its cache (for --remember). - systemd.services.greetd.serviceConfig = { - Type = "idle"; - StandardInput = "tty"; - StandardOutput = "tty"; - StandardError = "journal"; - TTYReset = true; - TTYVHangup = true; - TTYVTDisallocate = true; - }; - - # --- Graphics --- - hardware.graphics.enable = true; - - # --- Audio (playback only; no rtkit/jack — enzo isn't for recording). - # If you ever hear dropouts under load, add: security.rtkit.enable = true; - services.pulseaudio.enable = false; - services.pipewire = { - enable = true; - alsa.enable = true; - pulse.enable = true; - }; - - # --- Fonts (minimal) --- - # TODO move to common - fonts = { - enableDefaultPackages = true; - packages = with pkgs; [ - noto-fonts - nerd-fonts.symbols-only - adwaita-fonts - ]; - fontconfig = { - enable = true; - defaultFonts = { - monospace = [ "Adwaita Mono" ]; - }; - }; - }; + # --- Fonts: enzo's monospace (base font packages come from the shared profile) --- + fonts.fontconfig.defaultFonts.monospace = [ "Adwaita Mono" ]; + # --- Cursor --- environment.sessionVariables = { XCURSOR_THEME = "Adwaita"; XCURSOR_SIZE = "24"; }; - # Cursor theme referenced by XCURSOR_THEME / niri's xcursor-theme. Without this # package the Adwaita cursor files aren't on disk, so named shapes (e.g. the # link "pointer"/hand) fail to load and the cursor never changes on hover. - environment.systemPackages = [ pkgs.adwaita-icon-theme ]; + environment.systemPackages = with pkgs; [ + adwaita-icon-theme + yambar # text status bar + ]; - # --- User: groups + niri essentials --- + # --- User: desktop groups (niri essentials) --- users.users.hwebs.extraGroups = [ "audio" "input" ]; - # Firefox: blank home/new-tab and no bookmarks toolbar, delivered as an - # enterprise policy (no profile to manage). Dark theme is not configured here - # — it comes from the desktop portal (color-scheme dconf + Settings=gtk - # above), which Firefox honors for both chrome and web content. (LibreWolf was - # tried instead but forces content light via its fingerprinting protection - # even with resistFingerprinting off, so plain Firefox is the better fit.) - programs.firefox = { - enable = true; - preferencesStatus = "default"; - preferences = { - # Blank home page + blank new tab - "browser.startup.homepage" = "about:blank"; - "browser.startup.page" = 0; # 0 = blank on startup - "browser.newtabpage.enabled" = false; - # Hide the bookmarks toolbar - "browser.toolbars.bookmarks.visibility" = "never"; - }; - }; - - users.users.hwebs.packages = with pkgs; [ - ghostty # terminal - fuzzel # launcher - swaybg # wallpaper - xwayland-satellite # run X11 apps under niri - mako # notifications - libnotify # notify-send - yambar # text status bar - gnupg # gpg - pinentry-gnome3 # passphrase prompt for the gpg agent - ]; - - # --- GPG --- - # Agent + a GTK pinentry (works under niri). enableSSHSupport is left off so - # gpg-agent doesn't hijack the ssh-agent socket for your existing SSH key; - # turn it on only if you sign in via a GPG auth subkey. - programs.gnupg.agent.enable = true; - # --- Console / greeter font (HiDPI panel) --- # The eDP panel is high-density, so the kernel VT and tuigreet render with a # tiny 8x16 font. A large Terminus bitmap font makes the TTY and the greeter diff --git a/machines/kusanagi/default.nix b/machines/kusanagi/default.nix index 10531c2..c39db8e 100644 --- a/machines/kusanagi/default.nix +++ b/machines/kusanagi/default.nix @@ -6,6 +6,7 @@ { imports = [ ../../profiles/desktop.nix + ./desktop.nix ../../profiles/dev.nix ../../profiles/apps.nix ./hardware-configuration.nix diff --git a/machines/kusanagi/desktop.nix b/machines/kusanagi/desktop.nix new file mode 100644 index 0000000..368022e --- /dev/null +++ b/machines/kusanagi/desktop.nix @@ -0,0 +1,119 @@ +# kusanagi-only desktop extras. The shared niri/dark/audio/firefox base comes +# from ../../profiles/desktop.nix (imported in ./default.nix); this file holds +# the workstation's GNOME session, printing/scanning, pro-audio, richer fonts, +# and cursor theme. (Hardware-specific audio/NAS/server config lives in +# ./default.nix.) +{ pkgs, ... }: + +{ + # --- X11 + GNOME (alongside the niri session) --- + services.xserver.enable = true; + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; + services.displayManager.gdm.enable = false; + services.desktopManager.gnome.enable = true; + + # --- Printing / discovery / disks --- + services.printing = { + enable = true; + drivers = with pkgs; [ gutenprint ]; + }; + + # mDNS: printer discovery, and resolves kusanagi's *.local NAS names. + services.avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + }; + + # prevent auto-mounting optical disks + services.udisks2.enable = true; + + # --- Pro audio (extends the shared pipewire base) --- + security.rtkit.enable = true; + services.pipewire = { + alsa.support32Bit = true; + jack.enable = true; + wireplumber.enable = true; + }; + + # --- GPG: forward the ssh-agent socket (workstation signs/auths via GPG) --- + programs.gnupg.agent.enableSSHSupport = true; + + # --- Graphics: 32-bit for Steam/Wine --- + hardware.graphics.enable32Bit = true; + + # --- Fonts: workstation extras + defaults (base packages from shared) --- + fonts = { + packages = with pkgs; [ + noto-fonts-cjk-sans + noto-fonts-cjk-serif + inter + ibm-plex + public-sans + ]; + + fontconfig = { + defaultFonts = { + monospace = [ + "Berkeley Mono" + "Liberation Mono" + "Symbols Nerd Font" + ]; + sansSerif = [ + "Liberation Sans" + "Noto Sans" + ]; + serif = [ "Liberation Serif" ]; + emoji = [ "Nerd Font Symbols Only" ]; + }; + + # Force ui-sans-serif and system-ui to resolve correctly + localConf = '' + + + + + system-ui + + Liberation Sans + + + + ui-sans-serif + + Liberation Sans + + + + ''; + }; + + fontDir.enable = true; + }; + + # --- Cursor / renderer --- + environment.sessionVariables = { + GSK_RENDERER = "gl"; + XCURSOR_THEME = "Bibata-Modern-Classic"; + XCURSOR_SIZE = "24"; + HYPRCURSOR_THEME = "Bibata-Modern-Classic"; + HYPRCURSOR_SIZE = "24"; + }; + + # --- User: desktop groups (niri essentials + printing). Hardware groups + # (cdrom/optical/sg/scanner) stay in ./default.nix. --- + users.users.henz.extraGroups = [ + "audio" + "lp" + "input" + ]; + + # --- Desktop tools specific to kusanagi (shared ones come from the profile) --- + environment.systemPackages = with pkgs; [ + waybar + networkmanagerapplet + ]; +} -- cgit v1.3