commit d0b4c83e5351b3a5c954924fcd978a0acc533dd0
parent b7f2bf438995f4afe2ff376ec6a040fde71980f9
Author: maydayv7 <maydayv7@gmail.com>
Date: Thu, 25 Jun 2026 23:57:06 +0530
feat: NIRI
Diffstat:
39 files changed, 1390 insertions(+), 849 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
@@ -2,6 +2,7 @@
### June
+- Use [`adw-catppuccin`](https://github.com/LuminarLeaf/adw-catppuccin) for Catppuccin GTK Theme
- Use Discord instead of Vesktop
- Script to update Minecraft mods
- Drop manually-packaged `wine` applications
@@ -16,7 +17,7 @@
- Add `auth`, `syncthing`, `mouse`
- Use Thunderbird for mail
- Upgrade to NixOS 26.05
-- Drop Niri & Pantheon
+- Drop Pantheon Desktop
- Support standalone `home-manager` configurations
- Refactor NixOS Configuration to use [dendritic](https://github.com/mightyiam/dendritic) pattern
- Switch back formatter to `alejandra`
diff --git a/README.md b/README.md
@@ -29,10 +29,6 @@ It also builds and deploys my website to [maydayv7.cc](https://maydayv7.cc).
| :------------------------------------------------: |
| _GNOME Desktop_ |
-|  |
-| :------------------------------------------------------: |
-| _Pantheon Desktop_ |
-
| Windows |
| :--------------------------------------------: |
|  |
@@ -61,6 +57,10 @@ It also builds and deploys my website to [maydayv7.cc](https://maydayv7.cc).
<details>
<summary><i>Older...</i></summary>
+|  |
+| :------------------------------------------------------: |
+| _Pantheon Desktop_ |
+
| [](https://www.reddit.com/r/unixporn/comments/19efxry/xfce_functional_and_beautiful/) |
| :-----------------------------------------------------------------------------------------------------------------------------------: |
| _XFCE Desktop_ |
diff --git a/files/vscode/settings.json b/files/vscode/settings.json
@@ -16,7 +16,6 @@
"extensions.ignoreRecommendations": true,
"files.autoSave": "onWindowChange",
"files.trimFinalNewlines": true,
- "security.workspace.trust.enabled": false,
"search.showLineNumbers": true,
"search.smartCase": true,
"search.useGlobalIgnoreFiles": true,
diff --git a/flake.lock b/flake.lock
@@ -1552,6 +1552,66 @@
"type": "github"
}
},
+ "niri": {
+ "inputs": {
+ "niri-stable": "niri-stable",
+ "niri-unstable": "niri-unstable",
+ "nixpkgs": [
+ "unstable"
+ ],
+ "nixpkgs-stable": [
+ "stable"
+ ],
+ "xwayland-satellite-stable": "xwayland-satellite-stable",
+ "xwayland-satellite-unstable": "xwayland-satellite-unstable"
+ },
+ "locked": {
+ "lastModified": 1782384742,
+ "narHash": "sha256-fJBFEDoUEc9ypRKIZBPXra7ueLwd0WIfcuVFmDbAItk=",
+ "owner": "epireyn",
+ "repo": "niri-flake",
+ "rev": "40aee95971fa832be1270557bef2de9b97a24c46",
+ "type": "github"
+ },
+ "original": {
+ "owner": "epireyn",
+ "repo": "niri-flake",
+ "type": "github"
+ }
+ },
+ "niri-stable": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1777115961,
+ "narHash": "sha256-ehSMsSpE+0k8r+2Vseu8kangsYxToZv3vinynsDp9zs=",
+ "owner": "niri-wm",
+ "repo": "niri",
+ "rev": "8ed0da44d974c32c6877d2f4630c314da0717ecb",
+ "type": "github"
+ },
+ "original": {
+ "owner": "niri-wm",
+ "ref": "v26.04",
+ "repo": "niri",
+ "type": "github"
+ }
+ },
+ "niri-unstable": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1781781064,
+ "narHash": "sha256-Ii/koEm/sRyg65qbAQWqEgboSEIhdH0EL4KglAc14p0=",
+ "owner": "niri-wm",
+ "repo": "niri",
+ "rev": "49fc6117fd6c043adaa2ead316b82db5ed735d36",
+ "type": "github"
+ },
+ "original": {
+ "owner": "niri-wm",
+ "repo": "niri",
+ "type": "github"
+ }
+ },
"nixcord": {
"inputs": {
"flake-compat": "flake-compat_4",
@@ -1756,6 +1816,7 @@
"import-tree": "import-tree",
"index": "index",
"minecraft": "minecraft",
+ "niri": "niri",
"nixcord": "nixcord",
"nixpkgs": [
"stable"
@@ -2126,6 +2187,39 @@
"repo": "xdg-desktop-portal-hyprland",
"type": "github"
}
+ },
+ "xwayland-satellite-stable": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1771195969,
+ "narHash": "sha256-BUE41HjLIGPjq3U8VXPjf8asH8GaMI7FYdgrIHKFMXA=",
+ "owner": "Supreeeme",
+ "repo": "xwayland-satellite",
+ "rev": "536bd32efc935bf876d6de385ec18a1b715c9358",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Supreeeme",
+ "ref": "v0.8.1",
+ "repo": "xwayland-satellite",
+ "type": "github"
+ }
+ },
+ "xwayland-satellite-unstable": {
+ "flake": false,
+ "locked": {
+ "lastModified": 1781226823,
+ "narHash": "sha256-28696iIw8uE0ZUyFTtzhEM8xMh85clCYypMxkvUi+sc=",
+ "owner": "Supreeeme",
+ "repo": "xwayland-satellite",
+ "rev": "8575d0ef55d70f9b4c46b6bffb3accf912217e1e",
+ "type": "github"
+ },
+ "original": {
+ "owner": "Supreeeme",
+ "repo": "xwayland-satellite",
+ "type": "github"
+ }
}
},
"root": "root",
diff --git a/flake.nix b/flake.nix
@@ -178,8 +178,28 @@
inputs.nixpkgs.follows = "nixpkgs";
};
- ## Hyprland
- # Core
+ # Desktop Shell
+ noctalia = {
+ url = "github:noctalia-dev/noctalia";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+
+ # Login Greeter
+ noctalia-greeter = {
+ url = "github:noctalia-dev/noctalia-greeter";
+ inputs.nixpkgs.follows = "nixpkgs";
+ };
+
+ # Niri
+ niri = {
+ url = "github:epireyn/niri-flake";
+ inputs = {
+ nixpkgs.follows = "unstable";
+ nixpkgs-stable.follows = "stable";
+ };
+ };
+
+ # Hyprland
hyprland = {
url = "github:hyprwm/hyprnix/92cabda9b41bdf13c488f9cd8b646f2b352b6b1a";
inputs = {
@@ -188,7 +208,6 @@
};
};
- # Plugins
hyprsplit = {
url = "github:maydayv7/hyprsplit";
# url = "github:shezdy/hyprsplit";
@@ -205,18 +224,6 @@
hyprland.follows = "hyprland";
};
};
-
- # Desktop Shell
- noctalia = {
- url = "github:noctalia-dev/noctalia";
- inputs.nixpkgs.follows = "nixpkgs";
- };
-
- # Login Greeter
- noctalia-greeter = {
- url = "github:noctalia-dev/noctalia-greeter";
- inputs.nixpkgs.follows = "nixpkgs";
- };
};
## Configuration ##
diff --git a/modules/apps/flatpak.nix b/modules/apps/flatpak.nix
@@ -58,7 +58,7 @@
};
Environment = {
"DCONF_USER_CONFIG_DIR" = ".config/dconf";
- "GTK_THEME" = config.gui.gtk.theme.name or "";
+ inherit (config.environment.variables) "GTK_THEME";
};
};
diff --git a/modules/apps/internet.nix b/modules/apps/internet.nix
@@ -55,26 +55,29 @@ in {
mail = ["thunderbird.desktop"];
};
- home.packages = with pkgs; [
- linux-wifi-hotspot
- openfortivpn
- teams-for-linux
- zapzap
- zoom-us
- ];
-
- home.persist = {
- files = [".config/zoomus.conf"];
- directories = [
- ".config/BraveSoftware"
- ".cache/BraveSoftware"
- ".thunderbird"
- ".cache/thunderbird"
- ".local/share/ZapZap"
- ".cache/ZapZap"
- ".zoom"
- ".cache/zoom"
+ home = {
+ packages = with pkgs; [
+ linux-wifi-hotspot
+ openfortivpn
+ teams-for-linux
+ zapzap
+ zoom-us
];
+
+ persist = {
+ files = [".config/zoomus.conf"];
+ directories = [
+ ".config/BraveSoftware"
+ ".cache/BraveSoftware"
+ ".thunderbird"
+ ".cache/thunderbird"
+ ".config/ZapZap"
+ ".local/share/ZapZap"
+ ".cache/ZapZap"
+ ".zoom"
+ ".cache/zoom"
+ ];
+ };
};
};
}
diff --git a/modules/apps/vscode/default.nix b/modules/apps/vscode/default.nix
@@ -16,16 +16,22 @@ in {
in {
# Environment
imports = [./_mutable.nix];
- xdg.mimeApps.defaultApplications = util.build.mime {
- code = ["code.desktop"];
- markdown = ["code.desktop"];
- text = ["code.desktop"];
+ xdg.mimeApps = let
+ mime = util.build.mime {
+ code = ["code.desktop"];
+ markdown = ["code.desktop"];
+ text = ["code.desktop"];
+ };
+ in {
+ defaultApplications = mime;
+ associations.added = mime;
};
home = {
persist.directories = [
".config/Code"
".vscode"
+ ".vscode-shared"
];
packages = with pkgs; [
nil
diff --git a/modules/desktop/hyprland/_features/files.nix b/modules/desktop/_wm/files.nix
diff --git a/modules/desktop/hyprland/_features/login.nix b/modules/desktop/_wm/login.nix
diff --git a/modules/desktop/hyprland/_features/media.nix b/modules/desktop/_wm/media.nix
diff --git a/modules/desktop/hyprland/_features/misc.nix b/modules/desktop/_wm/misc.nix
diff --git a/modules/desktop/_wm/shell.nix b/modules/desktop/_wm/shell.nix
@@ -0,0 +1,374 @@
+## Noctalia Shell
+{inputs ? null, ...}: {
+ home = {
+ config,
+ osConfig ? {},
+ lib,
+ ...
+ }: let
+ inherit (lib) mkDefault;
+ output = osConfig.gui.display or "eDP-1";
+ in {
+ imports = [inputs.noctalia.homeModules.default];
+ gui._unmanaged = ["noctalia-shell"];
+ home.persist.directories = [
+ ".cache/noctalia"
+ ".local/state/noctalia"
+ ];
+
+ programs.noctalia = {
+ enable = true;
+ systemd.enable = true;
+ settings = {
+ shell = {
+ font_family = config.stylix.fonts.sansSerif.name;
+ avatar_path = "~/.face";
+ clipboard_enabled = true;
+ clipboard_history_max_entries = 150;
+ polkit_agent = true;
+ launch_apps_as_systemd_services = true;
+ settings_show_advanced = true;
+ panel.launcher_session_search = true;
+ screen_corners = {
+ enabled = true;
+ size = 30;
+ };
+ shadow.direction = "center";
+ };
+
+ theme = {
+ source = "custom";
+ custom_palette = "stylix";
+ mode = "dark";
+ builtin = "Catppuccin";
+ templates = {
+ builtin_ids = ["qt"];
+ enable_builtin_templates = false;
+ enable_community_templates = false;
+ };
+ };
+
+ # Bar
+ bar.main = {
+ position = "top";
+ start = mkDefault ["session" "taskbar" "media"];
+ center = ["launcher" "clock" "control-center"];
+ end = [
+ "group:g2"
+ "recorder"
+ "clipboard"
+ "bluetooth"
+ "network"
+ "volume"
+ "brightness"
+ "battery"
+ "notifications"
+ ];
+ background_opacity = 0.75;
+ margin_edge = 0;
+ margin_ends = 0;
+ padding = 15;
+ radius = 0;
+ scale = 1.1;
+ thickness = 30;
+ widget_spacing = 14;
+ capsule_group = mkDefault [
+ {
+ id = "g2";
+ members = ["tray"];
+ }
+ ];
+ };
+
+ # Audio
+ audio = {
+ enable_overdrive = true;
+ enable_sounds = true;
+ sound_volume = 0.3;
+ };
+
+ # Widgets
+ widget = {
+ clock.anchor = true;
+ control-center.glyph = "menu";
+ network.show_label = false;
+ recorder.type = "noctalia/screen_recorder:recorder";
+ media = {
+ hide_when_no_media = true;
+ title_scroll = "on_hover";
+ };
+ taskbar = {
+ group_by_workspace = true;
+ inactive_opacity = 0.85;
+ scale = 1.1;
+ show_active_indicator = false;
+ workspace_label_placement = "inside";
+ };
+ };
+ system.monitor.enabled = true;
+
+ # Calendar
+ calendar = {
+ enabled = true;
+ account.personal_google.type = "google";
+ };
+
+ # Notifications
+ notification = {
+ enable_daemon = true;
+ layer = "overlay";
+ filter.power = {
+ enabled = true;
+ match = "poweralertd";
+ play_sound = true;
+ save_history = false;
+ show_toast = true;
+ };
+ };
+ osd = {
+ background_opacity = 0.75;
+ kinds = {
+ volume = true;
+ brightness = true;
+ wifi = true;
+ bluetooth = true;
+ power_profile = true;
+ caffeine = true;
+ dnd = true;
+ keyboard_layout = true;
+ };
+ };
+
+ # Screenshots
+ shell.screenshot = {
+ save_to_file = true;
+ copy_to_clipboard = true;
+ freeze_screen = true;
+ directory = "~/Pictures/Screenshots";
+ };
+
+ # Wallpaper
+ wallpaper = {
+ enabled = true;
+ fill_mode = "crop";
+ transition_on_startup = true;
+ default.path = osConfig.stylix.image or "";
+ };
+
+ # Desktop Widgets
+ desktop_widgets = {
+ schema_version = 2;
+ widget_order = ["desktop-widget-0000000000000001" "desktop-widget-0000000000000002"];
+ grid = {
+ cell_size = 16;
+ major_interval = 4;
+ visible = true;
+ };
+ widget = {
+ "desktop-widget-0000000000000001" = {
+ inherit output;
+ box_height = 352.0;
+ box_width = 368.0;
+ cx = 1328.0;
+ cy = 240.0;
+ rotation = 0.0;
+ type = "clock";
+ settings = {
+ background = false;
+ center_text = true;
+ clock_style = "analog";
+ format = "{:%H:%M:%S}";
+ shadow = true;
+ };
+ };
+ "desktop-widget-0000000000000002" = {
+ inherit output;
+ box_height = 112.0;
+ box_width = 240.0;
+ cx = 1392.0;
+ cy = 856.0;
+ rotation = 0.0;
+ type = "weather";
+ settings = {
+ background = false;
+ show_forecast = false;
+ };
+ };
+ };
+ };
+
+ # Screen Idle
+ idle.behavior = {
+ lock = {
+ enabled = true;
+ timeout = 300;
+ command = "noctalia:session lock";
+ };
+ screen-off = {
+ enabled = true;
+ timeout = 360;
+ command = "noctalia:dpms-off";
+ resume_command = "noctalia:dpms-on";
+ };
+ suspend = {
+ enabled = true;
+ timeout = 600;
+ action = "suspend";
+ lock_before_suspend = true;
+ };
+ };
+
+ # Lock Screen
+ lockscreen = {
+ enabled = true;
+ blurred_desktop = false;
+ blur_intensity = 0.0;
+ tint_intensity = 0.25;
+ fingerprint = false;
+ };
+
+ # Lockscreen Widgets
+ lockscreen_widgets = {
+ enabled = true;
+ schema_version = 2;
+ widget_order = [
+ "lockscreen-login-box@eDP-1"
+ "lockscreen-widget-0000000000000001"
+ "lockscreen-widget-0000000000000003"
+ ];
+ grid = {
+ cell_size = 16;
+ major_interval = 4;
+ visible = true;
+ };
+ widget = {
+ "lockscreen-login-box@${output}" = {
+ inherit output;
+ box_height = 70.0;
+ box_width = 400.0;
+ cx = 1280.0;
+ cy = 1477.0;
+ rotation = 0.0;
+ type = "login_box";
+ settings = {
+ background_color = "surface_variant";
+ background_opacity = 0.88;
+ background_radius = 12.0;
+ input_opacity = 1.0;
+ input_radius = 6.0;
+ show_login_button = true;
+ };
+ };
+ "lockscreen-widget-0000000000000001" = {
+ inherit output;
+ box_height = 256.0;
+ box_width = 736.0;
+ cx = 768.0;
+ cy = 352.0;
+ rotation = 0.0;
+ type = "clock";
+ settings.format = "{:%H:%M:%S}";
+ };
+ "lockscreen-widget-0000000000000003" = {
+ inherit output;
+ box_height = 192.0;
+ box_width = 368.0;
+ cx = 768.0;
+ cy = 640.0;
+ rotation = 0.0;
+ type = "media_player";
+ settings.hide_when_no_media = true;
+ };
+ };
+ };
+
+ # Night Light
+ nightlight = {
+ enabled = true;
+ temperature_day = 6500;
+ temperature_night = 4000;
+ };
+
+ # Weather
+ weather.enabled = true;
+ location = {
+ auto_locate = true;
+ sunset = "19:00";
+ sunrise = "06:00";
+ };
+
+ # Plugins
+ plugins = {
+ source = mkDefault [
+ {
+ name = "official";
+ kind = "git";
+ location = "https://github.com/noctalia-dev/official-plugins";
+ }
+ {
+ name = "community";
+ kind = "git";
+ location = "https://github.com/noctalia-dev/community-plugins";
+ }
+ ];
+ enabled = mkDefault [
+ "noctalia/screen_recorder"
+ "noctalia/timer"
+ ];
+ };
+ plugin_settings."noctalia/screen_recorder" = {
+ copy_to_clipboard = true;
+ video_source = "focused";
+ };
+ };
+
+ # Color Palette
+ customPalettes.stylix.dark = with config.lib.stylix.colors.withHashtag; {
+ primary = base0D;
+ onPrimary = base00;
+ secondary = base0E;
+ onSecondary = base00;
+ tertiary = base0C;
+ onTertiary = base00;
+ error = base08;
+ onError = base00;
+ surface = base00;
+ onSurface = base05;
+ surfaceVariant = base01;
+ onSurfaceVariant = base04;
+ outline = base03;
+ shadow = base00;
+ hover = base0C;
+ onHover = base00;
+ terminal = {
+ normal = {
+ black = base00;
+ red = base08;
+ green = base0B;
+ yellow = base0A;
+ blue = base0D;
+ magenta = base0E;
+ cyan = base0C;
+ white = base05;
+ };
+ bright = {
+ black = base03;
+ red = base08;
+ green = base0B;
+ yellow = base0A;
+ blue = base0D;
+ magenta = base0E;
+ cyan = base0C;
+ white = base07;
+ };
+ foreground = base05;
+ background = base00;
+ cursor = base05;
+ cursorText = base00;
+ selectionFg = base05;
+ selectionBg = base02;
+ };
+ };
+ };
+ };
+}
diff --git a/modules/desktop/_wm/style.nix b/modules/desktop/_wm/style.nix
@@ -0,0 +1,69 @@
+## Catppuccin Style
+{
+ inputs,
+ files ? null,
+ ...
+}: {
+ nixos = {pkgs, ...}: {
+ environment.systemPackages = [pkgs.custom.cursors];
+ stylix = {
+ base16Scheme = files.colors.catppuccin;
+ icons.package = pkgs.catppuccin-papirus-folders.override {
+ accent = "blue";
+ flavor = "macchiato";
+ };
+ };
+
+ # QT Theme
+ gui.qt = {
+ theme = "catppuccin-macchiato-blue";
+ package = pkgs.catppuccin-kvantum.override {
+ accent = "blue";
+ variant = "macchiato";
+ };
+ };
+ };
+
+ home = {
+ config,
+ lib,
+ pkgs,
+ options,
+ ...
+ }: let
+ inherit (lib) attrNames elem filter genAttrs hasPrefix;
+ theme = "${pkgs.custom.adw-catppuccin}/share/adw-catppuccin/macchiato";
+
+ # Use Catppuccin over Stylix
+ alias = {
+ qt = "kvantum";
+ discord = "vesktop";
+ zed = "zed-editor";
+ };
+ except = ["kitty"];
+ targets = filter (n: !hasPrefix "_" n) (attrNames options.stylix.targets);
+ derived = filter (t: elem (alias.${t} or t) (attrNames config.catppuccin) && !elem t except) targets;
+ in {
+ imports = [inputs.catppuccin.homeModules.catppuccin];
+ config = {
+ gui._unmanaged = derived ++ ["spicetify"];
+ catppuccin =
+ {
+ enable = true;
+ accent = "blue";
+ flavor = "macchiato";
+ hyprland.enable = false;
+ gtk.icon.enable = false;
+ firefox.force = true;
+ kvantum.enable = false;
+ }
+ // genAttrs except (_: {enable = false;});
+
+ # GTK Theme
+ gtk = {
+ gtk3.extraCss = builtins.readFile "${theme}/catppuccin-macchiato-blue-gtk3.css";
+ gtk4.extraCss = builtins.readFile "${theme}/catppuccin-macchiato-blue.css";
+ };
+ };
+ };
+}
diff --git a/modules/desktop/hyprland/_features/terminal.nix b/modules/desktop/_wm/terminal.nix
diff --git a/modules/desktop/hyprland/_features/text.nix b/modules/desktop/_wm/text.nix
diff --git a/modules/desktop/_wm/utils.nix b/modules/desktop/_wm/utils.nix
@@ -0,0 +1,98 @@
+## Utilities
+{util ? null, ...}: {
+ nixos = {pkgs, ...}: {
+ environment.systemPackages = with pkgs; [
+ # Apps
+ font-manager
+ gnome-clocks
+ gnome-disk-utility
+ overskride
+ qalculate-gtk
+ remmina
+ resources
+ smile
+
+ # Utilities
+ hyprpicker
+ nwg-displays
+ pwvucontrol
+ wev
+ wl-clipboard
+ wlr-randr
+
+ # Network Settings
+ (gnome-control-center.overrideAttrs (old: {
+ postInstall =
+ old.postInstall
+ + ''
+ dir=$out/share/applications
+ for panel in $dir/*
+ do
+ [ "$panel" = "$dir/gnome-network-panel.desktop" ] && continue
+ [ "$panel" = "$dir/gnome-wifi-panel.desktop" ] && continue
+ [ "$panel" = "$dir/gnome-wwan-panel.desktop" ] && continue
+ [ "$panel" = "$dir/gnome-sharing-panel.desktop" ] && continue
+ [ "$panel" = "$dir/gnome-wacom-panel.desktop" ] && continue
+ rm "$panel"
+ done
+ '';
+ }))
+ ];
+
+ ## Essential Utilities
+ # Power
+ services = {
+ power-profiles-daemon.enable = true;
+ upower.enable = true;
+ };
+
+ # Backlight
+ hardware.brillo.enable = true;
+
+ programs = {
+ # Phone Connect
+ kdeconnect.enable = true;
+
+ # Screen Record
+ gpu-screen-recorder.enable = true;
+ };
+ };
+
+ home = _: {
+ home = {
+ persist.directories = [
+ ".config/kdeconnect"
+ ".config/gpu-screen-recorder"
+ ".config/nwg-displays"
+ ".local/share/gpu-screen-recorder"
+ ];
+
+ file.".config/kwalletrc".text = ''
+ [Wallet]
+ Enabled=false
+ '';
+ };
+
+ # Phone Connect
+ services.kdeconnect = {
+ enable = true;
+ indicator = true;
+ };
+
+ xdg = {
+ mimeApps.defaultApplications = util.build.mime {
+ font = ["com.github.FontManager.FontViewer.desktop"];
+ };
+
+ # Network Settings
+ desktopEntries."org.gnome.Settings" = {
+ name = "Network Settings";
+ comment = "Gnome Control Center";
+ icon = "org.gnome.Settings";
+ exec = "env XDG_CURRENT_DESKTOP=gnome gnome-control-center";
+ categories = ["X-Preferences"];
+ terminal = false;
+ };
+ };
+ };
+}
diff --git a/modules/desktop/gnome/_main.nix b/modules/desktop/gnome/_main.nix
@@ -5,19 +5,9 @@
}: {
nixos = {pkgs, ...}: {
# Desktop Integration
- gui = {
- gtk.theme = {
- name = "adw-gtk3-dark";
- package = pkgs.adw-gtk3;
- };
-
- qt = {
- style = "kvantum";
- theme = {
- name = "KvLibadwaitaDark";
- package = pkgs.custom.kvlibadwaita;
- };
- };
+ gui.qt = {
+ theme = "KvLibadwaitaDark";
+ package = pkgs.custom.kvlibadwaita;
};
# Color Scheme
diff --git a/modules/desktop/hyprland/_features/shell.nix b/modules/desktop/hyprland/_features/shell.nix
@@ -1,412 +1,76 @@
-## Noctalia Shell
-{
- inputs ? null,
- files ? null,
- ...
-}: {
+## Shell Integration
+{files ? null, ...}: {
home = {
config,
- osConfig ? {},
lib,
pkgs,
...
- }: let
- output = osConfig.gui.display or "eDP-1";
- in {
- imports = [inputs.noctalia.homeModules.default];
- gui._unmanaged = ["noctalia-shell"];
- home.persist.directories = [
- ".cache/noctalia"
- ".local/state/noctalia"
- ];
-
- programs.noctalia = {
- enable = true;
- systemd.enable = true;
- settings = {
- shell = {
- font_family = config.stylix.fonts.sansSerif.name;
- avatar_path = "~/.face";
- clipboard_enabled = true;
- clipboard_history_max_entries = 150;
- polkit_agent = true;
- launch_apps_as_systemd_services = true;
- settings_show_advanced = true;
- panel.launcher_session_search = true;
- screen_corners = {
- enabled = true;
- size = 30;
- };
- shadow.direction = "center";
- };
-
- theme = {
- source = "custom";
- custom_palette = "stylix";
- mode = "dark";
- builtin = "Catppuccin";
- templates = {
- builtin_ids = ["qt"];
- enable_builtin_templates = false;
- enable_community_templates = false;
- };
- };
-
- # Bar
- bar.main = {
- position = "top";
- start = ["session" "taskbar" "group:g1" "media"];
- center = ["launcher" "clock" "control-center"];
- end = [
- "group:g2"
- "recorder"
- "clipboard"
- "bluetooth"
- "network"
- "volume"
- "brightness"
- "battery"
- "notifications"
- ];
- background_opacity = 0.75;
- margin_edge = 0;
- margin_ends = 0;
- padding = 15;
- radius = 0;
- scale = 1.1;
- thickness = 30;
- widget_spacing = 14;
- capsule_group = [
- {
- id = "g1";
- members = [
- "minimize"
- "maydayv7/hyprland-layout:indicator"
- "maydayv7/hyprland-submap:indicator"
- ];
- }
- {
- id = "g2";
- members = ["tray"];
- }
- ];
- };
-
- # Audio
- audio = {
- enable_overdrive = true;
- enable_sounds = true;
- sound_volume = 0.3;
- };
-
- # Widgets
- widget = {
- clock.anchor = true;
- control-center.glyph = "menu";
- network.show_label = false;
- recorder.type = "noctalia/screen_recorder:recorder";
- media = {
- hide_when_no_media = true;
- title_scroll = "on_hover";
- };
- taskbar = {
- group_by_workspace = true;
- inactive_opacity = 0.85;
- scale = 1.1;
- show_active_indicator = false;
- workspace_label_placement = "inside";
- };
-
- # Minimize Button
- minimize = {
- type = "custom_button";
- glyph = "arrow-bar-to-down";
- tooltip = "Minimize window";
- command = ''hyprctl dispatch 'hl.dsp.window.move({ workspace = "special:minimized", follow = false })' '';
- right_command = "hyprutils toggle minimized";
- };
- };
- system.monitor.enabled = true;
-
- # Calendar
- calendar = {
- enabled = true;
- account.personal_google.type = "google";
- };
-
- # Notifications
- notification = {
- enable_daemon = true;
- layer = "overlay";
- filter.power = {
- enabled = true;
- match = "poweralertd";
- play_sound = true;
- save_history = false;
- show_toast = true;
- };
- };
- osd = {
- background_opacity = 0.75;
- kinds = {
- volume = true;
- brightness = true;
- wifi = true;
- bluetooth = true;
- power_profile = true;
- caffeine = true;
- dnd = true;
- keyboard_layout = true;
- };
- };
-
- # Screenshots
- shell.screenshot = {
- save_to_file = true;
- copy_to_clipboard = true;
- freeze_screen = true;
- directory = "~/Pictures/Screenshots";
- };
-
- # Wallpaper
- wallpaper = {
- enabled = true;
- fill_mode = "crop";
- transition_on_startup = true;
- default.path = osConfig.stylix.image or "";
- };
-
- # Desktop Widgets
- desktop_widgets = {
- schema_version = 2;
- widget_order = ["desktop-widget-0000000000000001" "desktop-widget-0000000000000002"];
- grid = {
- cell_size = 16;
- major_interval = 4;
- visible = true;
- };
- widget = {
- "desktop-widget-0000000000000001" = {
- inherit output;
- box_height = 352.0;
- box_width = 368.0;
- cx = 1328.0;
- cy = 240.0;
- rotation = 0.0;
- type = "clock";
- settings = {
- background = false;
- center_text = true;
- clock_style = "analog";
- format = "{:%H:%M:%S}";
- shadow = true;
- };
- };
- "desktop-widget-0000000000000002" = {
- inherit output;
- box_height = 112.0;
- box_width = 240.0;
- cx = 1392.0;
- cy = 856.0;
- rotation = 0.0;
- type = "weather";
- settings = {
- background = false;
- show_forecast = false;
- };
- };
- };
- };
-
- # Screen Idle
- idle.behavior = {
- lock = {
- enabled = true;
- timeout = 300;
- command = "noctalia:session lock";
- };
- screen-off = {
- enabled = true;
- timeout = 360;
- command = "noctalia:dpms-off";
- resume_command = "noctalia:dpms-on";
- };
- suspend = {
- enabled = true;
- timeout = 600;
- action = "suspend";
- lock_before_suspend = true;
- };
- };
-
- # Lock Screen
- lockscreen = {
- enabled = true;
- blurred_desktop = false;
- blur_intensity = 0.0;
- tint_intensity = 0.25;
- fingerprint = false;
- };
-
- # Lockscreen Widgets
- lockscreen_widgets = {
- enabled = true;
- schema_version = 2;
- widget_order = [
- "lockscreen-login-box@eDP-1"
- "lockscreen-widget-0000000000000001"
- "lockscreen-widget-0000000000000003"
- ];
- grid = {
- cell_size = 16;
- major_interval = 4;
- visible = true;
- };
- widget = {
- "lockscreen-login-box@${output}" = {
- inherit output;
- box_height = 70.0;
- box_width = 400.0;
- cx = 1280.0;
- cy = 1477.0;
- rotation = 0.0;
- type = "login_box";
- settings = {
- background_color = "surface_variant";
- background_opacity = 0.88;
- background_radius = 12.0;
- input_opacity = 1.0;
- input_radius = 6.0;
- show_login_button = true;
- };
- };
- "lockscreen-widget-0000000000000001" = {
- inherit output;
- box_height = 256.0;
- box_width = 736.0;
- cx = 768.0;
- cy = 352.0;
- rotation = 0.0;
- type = "clock";
- settings.format = "{:%H:%M:%S}";
- };
- "lockscreen-widget-0000000000000003" = {
- inherit output;
- box_height = 192.0;
- box_width = 368.0;
- cx = 768.0;
- cy = 640.0;
- rotation = 0.0;
- type = "media_player";
- settings.hide_when_no_media = true;
- };
- };
- };
-
- # Night Light
- nightlight = {
- enabled = true;
- temperature_day = 6500;
- temperature_night = 4000;
- };
-
- # Weather
- weather.enabled = true;
- location = {
- auto_locate = true;
- sunset = "19:00";
- sunrise = "06:00";
- };
+ }: {
+ programs.noctalia.settings = {
+ # Bar
+ bar.main = {
+ start = ["session" "taskbar" "group:g1" "media"];
+ capsule_group = [
+ {
+ id = "g1";
+ members = [
+ "minimize"
+ "maydayv7/hyprland-layout:indicator"
+ "maydayv7/hyprland-submap:indicator"
+ ];
+ }
+ {
+ id = "g2";
+ members = ["tray"];
+ }
+ ];
+ };
- # Plugins
- plugins = {
- source = [
- {
- name = "official";
- kind = "git";
- location = "https://github.com/noctalia-dev/official-plugins";
- }
- {
- name = "community";
- kind = "git";
- location = "https://github.com/noctalia-dev/community-plugins";
- }
- {
- name = "local";
- kind = "path";
- location = files.hyprland.noctalia;
- }
- ];
- enabled = [
- "noctalia/screen_recorder"
- "noctalia/timer"
- "maydayv7/hyprland-submap"
- "maydayv7/hyprland-layout"
- ];
- };
- plugin_settings = let
- hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl";
- jq = lib.getExe pkgs.jq;
- socket2 = "${lib.getExe pkgs.socat} -u UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock -";
- in {
- "noctalia/screen_recorder" = {
- copy_to_clipboard = true;
- video_source = "focused";
- };
- "maydayv7/hyprland-submap".command = socket2;
- "maydayv7/hyprland-layout" = {
- command = socket2;
- layout_command = "${hyprctl} getoption -j general:layout";
- float_command = "${hyprctl} -j clients | ${jq} --argjson ws \"$(${hyprctl} -j activeworkspace | ${jq} .id)\" '[.[] | select(.workspace.id == $ws and .mapped)] as $w | (($w | length) > 0) and ($w | map(.floating) | all)'";
- };
- };
+ # Minimize Button
+ widget.minimize = {
+ type = "custom_button";
+ glyph = "arrow-bar-to-down";
+ tooltip = "Minimize window";
+ command = ''hyprctl dispatch 'hl.dsp.window.move({ workspace = "special:minimized", follow = false })' '';
+ right_command = "hyprutils toggle minimized";
};
- # Color Palette
- customPalettes.stylix.dark = with config.lib.stylix.colors.withHashtag; {
- primary = base0D;
- onPrimary = base00;
- secondary = base0E;
- onSecondary = base00;
- tertiary = base0C;
- onTertiary = base00;
- error = base08;
- onError = base00;
- surface = base00;
- onSurface = base05;
- surfaceVariant = base01;
- onSurfaceVariant = base04;
- outline = base03;
- shadow = base00;
- hover = base0C;
- onHover = base00;
- terminal = {
- normal = {
- black = base00;
- red = base08;
- green = base0B;
- yellow = base0A;
- blue = base0D;
- magenta = base0E;
- cyan = base0C;
- white = base05;
- };
- bright = {
- black = base03;
- red = base08;
- green = base0B;
- yellow = base0A;
- blue = base0D;
- magenta = base0E;
- cyan = base0C;
- white = base07;
- };
- foreground = base05;
- background = base00;
- cursor = base05;
- cursorText = base00;
- selectionFg = base05;
- selectionBg = base02;
+ # Plugins
+ plugins = {
+ source = [
+ {
+ name = "official";
+ kind = "git";
+ location = "https://github.com/noctalia-dev/official-plugins";
+ }
+ {
+ name = "community";
+ kind = "git";
+ location = "https://github.com/noctalia-dev/community-plugins";
+ }
+ {
+ name = "local";
+ kind = "path";
+ location = files.hyprland.noctalia;
+ }
+ ];
+ enabled = [
+ "noctalia/screen_recorder"
+ "noctalia/timer"
+ "maydayv7/hyprland-submap"
+ "maydayv7/hyprland-layout"
+ ];
+ };
+ plugin_settings = let
+ hyprctl = "${config.wayland.windowManager.hyprland.package}/bin/hyprctl";
+ jq = lib.getExe pkgs.jq;
+ socket2 = "${lib.getExe pkgs.socat} -u UNIX-CONNECT:$XDG_RUNTIME_DIR/hypr/$HYPRLAND_INSTANCE_SIGNATURE/.socket2.sock -";
+ in {
+ "maydayv7/hyprland-submap".command = socket2;
+ "maydayv7/hyprland-layout" = {
+ command = socket2;
+ layout_command = "${hyprctl} getoption -j general:layout";
+ float_command = "${hyprctl} -j clients | ${jq} --argjson ws \"$(${hyprctl} -j activeworkspace | ${jq} .id)\" '[.[] | select(.workspace.id == $ws and .mapped)] as $w | (($w | length) > 0) and ($w | map(.floating) | all)'";
};
};
};
diff --git a/modules/desktop/hyprland/_features/style.nix b/modules/desktop/hyprland/_features/style.nix
@@ -1,73 +0,0 @@
-## Catppuccin Style
-{
- inputs,
- files ? null,
- ...
-}: {
- nixos = {pkgs, ...}: {
- environment.systemPackages = [pkgs.custom.cursors];
- stylix = {
- base16Scheme = files.colors.catppuccin;
- icons.package = pkgs.catppuccin-papirus-folders.override {
- accent = "blue";
- flavor = "macchiato";
- };
- };
-
- gui = {
- gtk.theme = {
- name = "catppuccin-macchiato-blue-standard";
- package = pkgs.catppuccin-gtk.override {
- accents = ["blue"];
- variant = "macchiato";
- };
- };
-
- qt = {
- style = "kvantum";
- theme = {
- name = "catppuccin-macchiato-blue";
- package = pkgs.catppuccin-kvantum.override {
- accent = "blue";
- variant = "macchiato";
- };
- };
- };
- };
- };
-
- home = {
- config,
- lib,
- options,
- ...
- }: let
- inherit (lib) attrNames elem filter genAttrs hasPrefix;
-
- # Use Catppuccin over Stylix
- alias = {
- qt = "kvantum";
- discord = "vesktop";
- zed = "zed-editor";
- };
- except = ["kitty"];
- targets = filter (n: !hasPrefix "_" n) (attrNames options.stylix.targets);
- derived = filter (t: elem (alias.${t} or t) (attrNames config.catppuccin) && !elem t except) targets;
- in {
- imports = [inputs.catppuccin.homeModules.catppuccin];
- config = {
- gui._unmanaged = derived ++ ["spicetify"];
- catppuccin =
- {
- enable = true;
- accent = "blue";
- flavor = "macchiato";
- hyprland.enable = false;
- gtk.icon.enable = false;
- firefox.force = true;
- kvantum.enable = false;
- }
- // genAttrs except (_: {enable = false;});
- };
- };
-}
diff --git a/modules/desktop/hyprland/_features/utils.nix b/modules/desktop/hyprland/_features/utils.nix
@@ -6,118 +6,29 @@
}: {
nixos = {pkgs, ...}: {
environment.systemPackages = with pkgs; [
- # Apps
- font-manager
- gnome-clocks
- gnome-disk-utility
- overskride
- qalculate-gtk
- remmina
- resources
- smile
custom.kebihelp
- nwg-displays
-
- # Utilities
custom.hyprutils
unstable.pyprland
- hyprpicker
hyprshade
- pwvucontrol
- wev
- wl-clipboard
- wlr-randr
-
- # Network Settings
- (gnome-control-center.overrideAttrs (old: {
- postInstall =
- old.postInstall
- + ''
- dir=$out/share/applications
- for panel in $dir/*
- do
- [ "$panel" = "$dir/gnome-network-panel.desktop" ] && continue
- [ "$panel" = "$dir/gnome-wifi-panel.desktop" ] && continue
- [ "$panel" = "$dir/gnome-wwan-panel.desktop" ] && continue
- [ "$panel" = "$dir/gnome-sharing-panel.desktop" ] && continue
- [ "$panel" = "$dir/gnome-wacom-panel.desktop" ] && continue
- rm "$panel"
- done
- '';
- }))
];
-
- ## Essential Utilities
- # Power
- services = {
- power-profiles-daemon.enable = true;
- upower.enable = true;
- };
-
- # Backlight
- hardware.brillo.enable = true;
-
- programs = {
- # Phone Connect
- kdeconnect.enable = true;
-
- # Screen Record
- gpu-screen-recorder.enable = true;
- };
};
home = {config, ...}: {
- home = {
- persist.directories = [
- ".config/kdeconnect"
- ".config/gpu-screen-recorder"
- ".config/nwg-displays"
- ".local/share/gpu-screen-recorder"
- ];
-
- file = with files.hyprland; {
- ".config/kwalletrc".text = ''
- [Wallet]
- Enabled=false
- '';
-
- # Pyprland
- ".config/pypr/config.toml".text = pypr;
-
- # Keybinds Viewer
- ".config/kebihelp.json".text = util.build.theme {
- inherit (config.stylix) fonts;
- inherit (config.lib.stylix) colors;
- file = kebihelp;
- };
-
- # Shaders
- ".config/hypr/shaders" = {
- source = shaders;
- recursive = true;
- };
- };
- };
-
- # Phone Connect
- services.kdeconnect = {
- enable = true;
- indicator = true;
- };
-
- xdg = {
- mimeApps.defaultApplications = util.build.mime {
- font = ["com.github.FontManager.FontViewer.desktop"];
+ home.file = with files.hyprland; {
+ # Pyprland
+ ".config/pypr/config.toml".text = pypr;
+
+ # Keybinds Viewer
+ ".config/kebihelp.json".text = util.build.theme {
+ inherit (config.stylix) fonts;
+ inherit (config.lib.stylix) colors;
+ file = kebihelp;
};
- # Network Settings
- desktopEntries."org.gnome.Settings" = {
- name = "Network Settings";
- comment = "Gnome Control Center";
- icon = "org.gnome.Settings";
- exec = "env XDG_CURRENT_DESKTOP=gnome gnome-control-center";
- categories = ["X-Preferences"];
- terminal = false;
+ # Shaders
+ ".config/hypr/shaders" = {
+ source = shaders;
+ recursive = true;
};
};
};
diff --git a/modules/desktop/hyprland/_settings/main.nix b/modules/desktop/hyprland/_settings/main.nix
@@ -130,19 +130,6 @@ lib.mkIf (osConfig != null) (
bezier = "zoom";
}
{
- leaf = "layersIn";
- enabled = true;
- speed = 3;
- bezier = "crash";
- style = "slide";
- }
- {
- leaf = "layersOut";
- enabled = true;
- speed = 1.6;
- bezier = "zoom";
- }
- {
leaf = "specialWorkspace";
enabled = true;
speed = 3;
diff --git a/modules/desktop/hyprland/default.nix b/modules/desktop/hyprland/default.nix
@@ -10,7 +10,10 @@
base = import ../_base.nix {};
args = {inherit util files inputs;};
- features = builtins.map (p: import p args) (util.map.modules.list ./_features);
+ features = builtins.map (p: import p args) (
+ util.map.modules.list ../_wm
+ ++ util.map.modules.list ./_features
+ );
in {
flake.modules = {
nixos.hyprland.imports =
diff --git a/modules/desktop/niri/_features/main.nix b/modules/desktop/niri/_features/main.nix
@@ -0,0 +1,28 @@
+## Compositor
+_: {
+ nixos = {pkgs, ...}: {
+ # WM
+ programs.niri = {
+ enable = true;
+ package = pkgs.niri;
+ };
+
+ # Session
+ programs.uwsm = {
+ enable = true;
+ waylandCompositors.niri = {
+ prettyName = "Niri";
+ comment = "Niri compositor managed by UWSM";
+ binPath = "/run/current-system/sw/bin/niri";
+ };
+ };
+
+ # App Environment
+ xdg.portal.extraPortals = [pkgs.xdg-desktop-portal-gtk];
+ };
+
+ home = {pkgs, ...}: {
+ programs.niri.package = pkgs.niri;
+ home.persist.directories = [".config/niri"];
+ };
+}
diff --git a/modules/desktop/niri/_features/utils.nix b/modules/desktop/niri/_features/utils.nix
@@ -0,0 +1,12 @@
+## Utilities
+_: {
+ nixos = {pkgs, ...}: {
+ environment.systemPackages = with pkgs; [
+ # Screen Mirroring
+ wl-mirror
+
+ # XWayland Support
+ xwayland-satellite
+ ];
+ };
+}
diff --git a/modules/desktop/niri/_settings/apps.nix b/modules/desktop/niri/_settings/apps.nix
@@ -0,0 +1,149 @@
+_: {
+ config,
+ pkgs,
+ lib,
+ ...
+}: {
+ programs.niri.settings = {
+ ## Autostart
+ spawn-at-startup = let
+ exec = app: args:
+ [
+ "uwsm"
+ "app"
+ "-t"
+ "service"
+ "-u"
+ "${app}.service"
+ "--"
+ app
+ ]
+ ++ args;
+ in [
+ {
+ command = [
+ "uwsm"
+ "finalize"
+ "NIRI_SOCKET"
+ "DISPLAY"
+ ];
+ }
+ {command = exec "pcmanfm-qt" ["--desktop"];}
+ {command = [(lib.getExe pkgs.xwayland-satellite) ":0"];}
+ ];
+
+ ## Keybindings
+ binds = with config.lib.niri.actions; let
+ sh = spawn "sh" "-c";
+ runOnce = app: args: sh "pgrep ${app} || uwsm app -u ${app}.scope -- ${app} ${args}";
+ in {
+ # Applications
+ "Super+F" = {
+ action = spawn "nemo";
+ hotkey-overlay.title = "Files";
+ };
+
+ "Super+T" = {
+ action = spawn "kitty";
+ hotkey-overlay.title = "Terminal";
+ };
+
+ "Super+W" = {
+ action = spawn "firefox";
+ hotkey-overlay.title = "Browser";
+ };
+
+ "Super+Return" = {
+ action = runOnce "resources" "";
+ hotkey-overlay.title = "Task Manager";
+ };
+
+ "XF86Calculator" = {
+ action = spawn "qalculate-gtk";
+ hotkey-overlay.title = "Calculator";
+ };
+
+ # Shell
+ "Super+A" = {
+ action = sh "noctalia msg panel-toggle launcher";
+ hotkey-overlay.title = "Launcher";
+ };
+
+ "Super+Shift+A" = {
+ action = sh "noctalia msg settings-toggle";
+ hotkey-overlay.title = "Settings";
+ };
+
+ "Super+N" = {
+ action = sh "noctalia msg panel-toggle notifications";
+ hotkey-overlay.title = "Notifications";
+ };
+
+ "Super+V" = {
+ action = sh "noctalia msg panel-toggle clipboard";
+ hotkey-overlay.title = "Clipboard";
+ };
+
+ "Super+Escape" = {
+ action = sh "noctalia msg panel-toggle session";
+ hotkey-overlay.title = "Power Menu";
+ };
+
+ # Utilities
+ "Super+Shift+C" = {
+ action = runOnce "hyprpicker" "-arf hex";
+ hotkey-overlay.title = "Color Picker";
+ };
+
+ "Super+Shift+B" = {
+ action = runOnce "overskride" "";
+ hotkey-overlay.title = "Bluetooth Settings";
+ };
+
+ "Super+Shift+N" = {
+ action = sh "env XDG_CURRENT_DESKTOP=GNOME gnome-control-center wifi";
+ hotkey-overlay.title = "Network Settings";
+ };
+
+ "Super+Shift+P" = {
+ action = spawn "pwvucontrol";
+ hotkey-overlay.title = "Audio Settings";
+ };
+
+ "Super+D" = {
+ action = runOnce "nwg-displays" "";
+ hotkey-overlay.title = "Display Settings";
+ };
+
+ "Super+backslash" = {
+ action = spawn "smile";
+ hotkey-overlay.title = "Emoji Picker";
+ };
+ };
+
+ ## Window Rules
+ window-rules = [
+ {
+ matches = [{app-id = "qalculate-gtk";}];
+ open-floating = true;
+ default-column-width.proportion = 0.5;
+ default-window-height.proportion = 0.9;
+ default-floating-position = {
+ relative-to = "right";
+ x = 5;
+ y = 0;
+ };
+ }
+ {
+ matches = [
+ {app-id = "com.saivert.pwvucontrol";}
+ {app-id = "io.github.kaii_lb.Overskride";}
+ {app-id = "nwg-displays";}
+ {app-id = "org.gnome.Settings";}
+ {app-id = "gnome-control-center";}
+ ];
+ open-floating = true;
+ }
+ ];
+ };
+}
diff --git a/modules/desktop/niri/_settings/keybinds.nix b/modules/desktop/niri/_settings/keybinds.nix
@@ -0,0 +1,100 @@
+## Compositor Binds
+_: {
+ config,
+ pkgs,
+ lib,
+ ...
+}: let
+ inherit (builtins) concatLists genList listToAttrs toString;
+ inherit (lib) getExe;
+ brillo = getExe pkgs.brillo;
+in {
+ programs.niri.settings = {
+ input.power-key-handling.enable = false;
+ binds = with config.lib.niri.actions; let
+ sh = spawn "sh" "-c";
+ in
+ {
+ # Compositor
+ "Super+slash".action = show-hotkey-overlay;
+ "Alt+F4".action = close-window;
+ "Super+Q".action = close-window;
+ "Super+C".action = center-window;
+ "Super+Shift+F".action = fullscreen-window;
+ "Super+equal".action = switch-preset-column-width;
+ "Super+minus".action = switch-preset-window-height;
+ "Super+Shift+equal".action = maximize-column;
+ "Super+Shift+minus".action = set-column-width "+10%";
+ "Super+semicolon".action = toggle-window-floating;
+ "Super+apostrophe".action = switch-focus-between-floating-and-tiling;
+ "Super+Shift+Tab".action = toggle-column-tabbed-display;
+
+ "Super+Tab".action = toggle-overview;
+ "Super+Right".action = focus-column-or-monitor-right;
+ "Super+Left".action = focus-column-or-monitor-left;
+ "Super+Up".action = focus-window-or-workspace-up;
+ "Super+Down".action = focus-window-or-workspace-down;
+
+ "Super+Shift+Right".action = consume-or-expel-window-right;
+ "Super+Shift+Left".action = consume-or-expel-window-left;
+ "Super+Shift+Up".action = move-window-up-or-to-workspace-up;
+ "Super+Shift+Down".action = move-window-down-or-to-workspace-down;
+ "Super+Shift+Return".action = move-window-to-monitor-next;
+
+ # Screenshots
+ "Print".action = sh "noctalia msg screenshot-region";
+ "Shift+Print".action = sh "noctalia msg screenshot-fullscreen pick";
+ "Ctrl+Print".action.screenshot-window = [];
+
+ # Controls
+ "Super+L" = {
+ action = sh "noctalia msg session lock";
+ hotkey-overlay.title = "Lock Screen";
+ };
+
+ "XF86AudioPlay".action = sh "noctalia msg media toggle";
+ "XF86AudioPrev".action = sh "noctalia msg media previous";
+ "XF86AudioNext".action = sh "noctalia msg media next";
+ "XF86AudioMute".action = sh "noctalia msg volume-mute";
+ "XF86AudioRaiseVolume".action = sh "noctalia msg volume-up";
+ "XF86AudioLowerVolume".action = sh "noctalia msg volume-down";
+ "XF86MonBrightnessUp".action = sh "noctalia msg brightness-up";
+ "XF86MonBrightnessDown".action = sh "noctalia msg brightness-down";
+ "XF86KbdBrightnessUp".action = sh "${brillo} -k -A 10";
+ "XF86KbdBrightnessDown".action = sh "${brillo} -k -U 10";
+
+ # Mouse
+ "Super+Shift+MouseRight".action = switch-preset-window-width;
+ "Super+WheelScrollUp" = {
+ action = focus-workspace-up;
+ cooldown-ms = 150;
+ };
+ "Super+WheelScrollDown" = {
+ action = focus-workspace-down;
+ cooldown-ms = 150;
+ };
+ }
+ //
+ # Workspaces
+ listToAttrs (
+ concatLists (
+ genList (
+ n: let
+ num = n + 1;
+ snum = toString (n + 1);
+ in [
+ {
+ name = "Super+${snum}";
+ value.action = focus-workspace num;
+ }
+ {
+ name = "Super+Shift+${snum}";
+ value.action.move-window-to-workspace = num;
+ }
+ ]
+ )
+ 9
+ )
+ );
+ };
+}
diff --git a/modules/desktop/niri/_settings/main.nix b/modules/desktop/niri/_settings/main.nix
@@ -0,0 +1,87 @@
+## Compositor Settings
+_: {
+ config,
+ lib,
+ ...
+}: let
+ inherit (config.lib.stylix.colors) base04 base08;
+in {
+ programs.niri.settings = {
+ screenshot-path = "~/Pictures/Screenshots/%Y-%m-%d-%H%M%S.png";
+ environment.DISPLAY = ":0"; # XWayland Support
+ hotkey-overlay = {
+ skip-at-startup = true;
+ hide-not-bound = true;
+ };
+
+ # Use 'nwg-displays' to configure monitors
+ includes = with config.lib.niri.include; [
+ (optional "~/.config/niri/monitors.kdl")
+ (optional "~/.config/niri/workspaces.kdl")
+ ];
+
+ input = {
+ keyboard.numlock = true;
+ mouse.accel-profile = "flat";
+ warp-mouse-to-focus.enable = true;
+ workspace-auto-back-and-forth = true;
+ focus-follows-mouse = {
+ enable = true;
+ max-scroll-amount = "90%";
+ };
+ touchpad = {
+ tap = true;
+ natural-scroll = true;
+ dwt = false;
+ };
+ };
+
+ layout = {
+ tab-indicator = {
+ enable = true;
+ place-within-column = true;
+ };
+
+ default-column-width.proportion = 0.5;
+ preset-column-widths = [
+ {proportion = 1.0 / 3.0;}
+ {proportion = 0.5;}
+ {proportion = 2.0 / 3.0;}
+ {proportion = 0.85;}
+ ];
+ preset-window-heights = [
+ {proportion = 1.0 / 3.0;}
+ {proportion = 0.5;}
+ {proportion = 2.0 / 3.0;}
+ {proportion = 1.0;}
+ ];
+ };
+
+ # Mouse Gestures
+ gestures.hot-corners.enable = true;
+
+ # Window Switcher
+ recent-windows = {
+ enable = true;
+ open-delay-ms = 150;
+ highlight = {
+ active-color = "#${base04}";
+ urgent-color = "#${base08}";
+ padding = 30;
+ corner-radius = 7;
+ };
+ previews = {
+ max-height = 480;
+ max-scale = 0.5;
+ };
+ binds = let
+ ra = lib.mergeAttrsList config.lib.niri.actions.recent-windows;
+ in {
+ "Alt+Tab".action = ra.next-window;
+ "Alt+Shift+Tab".action = ra.previous-window;
+ "Alt+grave".action = ra.next-window {filter = "app-id";};
+ "Alt+Shift+grave".action = ra.previous-window {filter = "app-id";};
+ };
+ };
+ };
+}
diff --git a/modules/desktop/niri/_settings/style.nix b/modules/desktop/niri/_settings/style.nix
@@ -0,0 +1,67 @@
+## Style
+_: {
+ config,
+ osConfig ? null,
+ ...
+}: let
+ inherit (config.lib.stylix.colors.withHashtag) base00 base05 base0D;
+ fancy = osConfig.gui.fancy or false;
+in {
+ programs.niri.settings = {
+ prefer-no-csd = true;
+ overview.backdrop-color = base00;
+ layout = {
+ gaps = 7;
+ background-color = base00;
+ insert-hint.display.color = base05;
+
+ shadow = {
+ enable = true;
+ spread = 4;
+ softness = 8;
+ offset = {
+ x = 0;
+ y = 0;
+ };
+ };
+
+ border.width = 1;
+ focus-ring = {
+ enable = true;
+ width = 1;
+ active.color = base0D;
+ };
+
+ tab-indicator = {
+ position = "left";
+ length.total-proportion = 1.0;
+ width = 7;
+ gap = 7;
+ gaps-between-tabs = 7;
+ corner-radius = 7;
+ };
+ };
+
+ blur = {
+ enable = fancy;
+ passes = 2;
+ offset = 2;
+ noise = 0.02;
+ };
+
+ window-rules = [
+ {
+ clip-to-geometry = true;
+ draw-border-with-background = false;
+ geometry-corner-radius = let
+ radius = 7.0;
+ in {
+ bottom-left = radius;
+ bottom-right = radius;
+ top-left = radius;
+ top-right = radius;
+ };
+ }
+ ];
+ };
+}
diff --git a/modules/desktop/niri/default.nix b/modules/desktop/niri/default.nix
@@ -0,0 +1,37 @@
+## Niri WM ##
+{
+ config,
+ inputs,
+ ...
+}: let
+ inherit (config) util;
+ inherit (config.flake) files;
+ inherit (config.flake.modules) nixos homeManager;
+
+ base = import ../_base.nix {};
+ args = {inherit util files inputs;};
+ features = builtins.map (p: import p args) (
+ util.map.modules.list ../_wm
+ ++ util.map.modules.list ./_features
+ );
+in {
+ flake.modules = {
+ nixos.niri.imports =
+ [
+ (base.nixos or {})
+ nixos.qt
+ nixos.gtk
+ ]
+ ++ builtins.map (f: f.nixos or {}) features;
+
+ homeManager.niri.imports =
+ [
+ (base.home or {})
+ inputs.niri.homeModules.config
+ homeManager.qt
+ homeManager.gtk
+ ]
+ ++ builtins.map (f: f.home or {}) features
+ ++ builtins.map (p: import p args) (util.map.modules.list ./_settings);
+ };
+}
diff --git a/modules/gui/gtk.nix b/modules/gui/gtk.nix
@@ -3,40 +3,20 @@
inherit (config.flake) files;
in {
flake.modules = {
- nixos.gtk = {
- config,
- lib,
- pkgs,
- ...
- }: let
- cfg = config.gui.gtk;
- in {
- options.gui.gtk.theme = {
- name = lib.mkOption {
- description = "GTK+ Application Theme";
- type = lib.types.str;
- };
-
- package = lib.mkOption {
- description = "GTK+ Theme Package";
- type = lib.types.package;
- };
- };
-
- config = {
- # Environment Setup
- programs.dconf.enable = true;
- services.dbus.packages = [pkgs.dconf];
- environment = {
- systemPackages = [cfg.theme.package];
- variables."GTK_THEME" = cfg.theme.name;
- };
+ nixos.gtk = {pkgs, ...}: {
+ # Environment Setup
+ programs.dconf.enable = true;
+ services.dbus.packages = [pkgs.dconf];
+ environment = {
+ systemPackages = [pkgs.adw-gtk3];
+ variables."GTK_THEME" = "adw-gtk3-dark";
};
};
homeManager.gtk = {
config,
lib,
+ pkgs,
osConfig ? null,
...
}:
@@ -59,9 +39,14 @@ in {
# Theming
gui._unmanaged = ["gtk"];
dconf.settings."org/gnome/desktop/interface".color-scheme = "prefer-dark";
- gtk = {
+ gtk = let
+ theme = {
+ name = "adw-gtk3-dark";
+ package = pkgs.adw-gtk3;
+ };
+ in {
enable = true;
- inherit (osConfig.gui.gtk) theme;
+ inherit theme;
cursorTheme = config.stylix.cursor;
font = with config.stylix.fonts; {
inherit (sansSerif) package name;
@@ -70,7 +55,7 @@ in {
gtk3.extraConfig.gtk-application-prefer-dark-theme = 1;
gtk4 = {
- inherit (osConfig.gui.gtk) theme;
+ inherit theme;
extraConfig = {
gtk-application-prefer-dark-theme = 1;
diff --git a/modules/gui/qt.nix b/modules/gui/qt.nix
@@ -7,127 +7,58 @@ _: {
pkgs,
...
}: let
- inherit
- (lib)
- mkDefault
- mkIf
- mkMerge
- mkOption
- types
- ;
- inherit (config.gui) qt icons;
- inherit (config.stylix) fonts;
+ inherit (lib) mkOption types;
+ cfg = config.gui.qt;
in {
options.gui.qt = {
- style = mkOption {
- description = "QT Application Style";
- type = types.nullOr (
- types.enum [
- "gtk"
- "kvantum"
- "qtct"
- ]
- );
- default = null;
+ theme = mkOption {
+ description = "QT Application Theme";
+ type = types.str;
+ default = "";
};
- theme = {
- name = mkOption {
- description = "QT Application Theme";
- type = types.str;
- default = "";
- };
-
- package = mkOption {
- description = "QT Theme Package";
- type = types.package;
- default = pkgs.adwaita-qt;
- };
+ package = mkOption {
+ description = "QT Theme Package";
+ type = types.package;
+ default = pkgs.adwaita-qt;
};
};
- config = with qt.theme;
- mkMerge [
- {
- stylix.targets.qt.enable = false;
- qt = {
- enable = true;
- platformTheme = mkDefault "gtk2";
- };
- }
-
- (mkIf (qt.style == "gtk") {
- qt = {
- platformTheme = "gnome";
- style = "adwaita-dark";
- };
- })
-
- (mkIf (qt.style == "kvantum") {
- qt = {
- platformTheme = "qt5ct";
- style = "kvantum";
- };
-
- environment = {
- systemPackages = [package];
- etc."xdg/Kvantum/kvantum.kvconfig".text = ''
- [General]
- theme=${name}
- '';
- };
- })
-
- (mkIf (qt.style == "qtct") (
- let
- pkg = with pkgs; [
- darkly
- darkly-qt5
- ];
+ # Kvantum Style
+ config = {
+ stylix.targets.qt.enable = false;
+ qt = {
+ enable = true;
+ platformTheme = "qt5ct";
+ style = "kvantum";
+ };
- conf = version:
- lib.generators.toINI {} {
- Appearance = {
- style = "Lightly";
- standard_dialogs = "default";
- icon_theme = icons.name;
- custom_palette = true;
- color_scheme_path = "${package}/share/${version}/colors/${name}.conf";
- };
+ environment = {
+ systemPackages = [
+ cfg.package
+ pkgs.libsForQt5.qt5ct
+ pkgs.kdePackages.qt6ct
+ ];
- Fonts = let
- size = fonts.sizes.applications;
- in {
- fixed = "\"${fonts.monospace.name},${size},-1,5,50,0,0,0,0,0,Regular\"";
- general = "\"${fonts.sansSerif.name},${size},-1,5,50,0,0,0,0,0,Regular\"";
- };
- };
- in {
- qt.platformTheme = "qt5ct";
- environment = {
- systemPackages = pkg;
- etc = {
- "xdg/qt5ct/qt5ct.conf".text = conf "qt5ct";
- "xdg/qt6ct/qt6ct.conf".text = conf "qt6ct";
- };
- };
- }
- ))
- ];
+ etc."xdg/Kvantum/kvantum.kvconfig".text = ''
+ [General]
+ theme=${cfg.theme}
+ '';
+ };
+ };
};
homeManager.qt = {
config,
- lib,
osConfig ? {},
...
}: let
inherit (builtins) concatStringsSep map;
- qt = osConfig.gui.qt or {};
+ cfg = osConfig.gui.qt or {};
in {
gui._unmanaged = ["qt"];
- xdg.configFile."Kvantum" = lib.mkIf ((qt.style or null) == "kvantum") {
- source = "${qt.theme.package}/share/Kvantum";
+ xdg.configFile."Kvantum" = {
+ source = "${cfg.package}/share/Kvantum";
recursive = true;
};
diff --git a/modules/hosts/valkyrie/default.nix b/modules/hosts/valkyrie/default.nix
@@ -47,7 +47,7 @@
"wine"
"games"
#"libvirt"
- "hyprland"
+ "niri"
];
hmImports =
diff --git a/modules/system/user/_mutable.nix b/modules/system/user/_mutable.nix
@@ -49,12 +49,10 @@ in {
type = types.bool;
default = false;
description = ''
- Whether to copy the file without the read-only attribute instead of
- symlinking. If you set this to `true`, you must also set `force` to
- `true`. Mutable files are not removed when you remove them from your
- configuration.
- This option is useful for programs that don't have a very good
- support for read-only configurations.
+ Whether to copy the file without the read-only attribute instead of symlinking.
+ If you set this to 'true', you must also set 'force' to 'true'.
+ Mutable files are not removed when you remove them from your configuration.
+ This option is useful for programs that don't have a very good support for read-only configurations.
'';
};
})
@@ -79,7 +77,7 @@ in {
filterMutableFiles = filter (
file:
(file.mutable or false)
- && assertMsg file.force "if you specify `mutable` to `true` on a file, you must also set `force` to `true`"
+ && assertMsg file.force "if you specify 'mutable' to 'true' on a file, you must also set 'force' to 'true'"
);
mutableFiles = filterMutableFiles allFiles;
@@ -93,10 +91,7 @@ in {
'';
command =
- ''
-
- echo "Copying mutable home files for $HOME"
- ''
+ ''echo "Copying mutable home files for $HOME"''
+ concatLines (map toCommand mutableFiles);
in
hm.dag.entryAfter ["linkGeneration"] command;
diff --git a/packages/adw-catppuccin/default.nix b/packages/adw-catppuccin/default.nix
@@ -0,0 +1,31 @@
+{
+ lib,
+ pkgs,
+ ...
+}:
+with pkgs; let
+ metadata = import ./metadata.nix;
+in
+ stdenv.mkDerivation {
+ pname = "adw-catppuccin";
+ version = metadata.rev;
+
+ src = fetchFromGitHub {
+ owner = "LuminarLeaf";
+ repo = "adw-catppuccin";
+ inherit (metadata) rev sha256;
+ };
+
+ dontBuild = true;
+ installPhase = ''
+ mkdir -p $out/share/adw-catppuccin
+ cp -r ./themes/. $out/share/adw-catppuccin/
+ '';
+
+ meta = with lib; {
+ description = "Catppuccin port for Adwaita, compatible with libadwaita and adw-gtk3";
+ homepage = metadata.repo;
+ license = licenses.gpl3Only;
+ maintainers = ["maydayv7"];
+ };
+ }
diff --git a/packages/adw-catppuccin/metadata.nix b/packages/adw-catppuccin/metadata.nix
@@ -0,0 +1,5 @@
+{
+ repo = "https://github.com/LuminarLeaf/adw-catppuccin";
+ rev = "62b2e64ea6b1ccdca7c5eb566e52130c993f03e9";
+ sha256 = "sha256-wpB9gEIKaqOBMqHTpOFJdZWo0z+eg5s3gMwTkvcey8g=";
+}
diff --git a/scripts/hyprutils.nix b/scripts/hyprutils.nix
@@ -104,34 +104,17 @@ in
hyprshade on "$SHADER" && hyprctl seterror ""
;;
"touchpad")
- temp hyprutils_touchpad 1
- STATUS="$TEMP/status"
touchpad=$(hyprctl devices | grep touchpad | xargs)
-
- enable() {
- hyprctl eval 'hl.device({ name = "'"$touchpad"'", enabled = true })'
- printf "true" >"$STATUS"
- hyprnotify 1 "Touchpad Enabled"
- }
-
- disable() {
- hyprctl eval 'hl.device({ name = "'"$touchpad"'", enabled = false })'
- printf "false" >"$STATUS"
- hyprnotify 1 "Touchpad Disabled"
- }
-
- if ! [ -f "$STATUS" ]
- then
- disable
- else
- if [ "$(cat "$STATUS")" = "true" ]
- then
- disable
- elif [ "$(cat "$STATUS")" = "false" ]
- then
- enable
- fi
- fi
+ hyprctl eval '
+ if __touchpad_enabled == nil then __touchpad_enabled = true end
+ __touchpad_enabled = not __touchpad_enabled
+ hl.device({ name = "'"$touchpad"'", enabled = __touchpad_enabled })
+ hl.notification.create({
+ text = " Touchpad " .. (__touchpad_enabled and "Enabled" or "Disabled") .. " ",
+ duration = 1500,
+ icon = 1,
+ })
+ '
;;
"") fail "Expected an Option" ;;
*) fail "Unexpected Option 'toggle $2'" ;;
diff --git a/site/content/blog/hello.md b/site/content/blog/hello.md
@@ -2,7 +2,7 @@
title = "Hello World!"
description = "Upholding Tradition ;)"
date = 2022-02-15
-updated = 2026-01-01
+updated = 2025-12-15
[taxonomies]
tags = ["Misc"]
diff --git a/site/content/blog/nixos/prelude.md b/site/content/blog/nixos/prelude.md
@@ -1,7 +1,7 @@
+++
title = "Prelude"
description = "My NixOS Configuration"
-date = 2026-01-05
+date = 2025-12-15
[taxonomies]
series = ["NixOS Desktop"]
@@ -15,7 +15,7 @@ comments = true
# I don't know Linux
-Go away already.
+Go away.
If you’re looking for a beginner’s guide, this is not it. This is a postmortem of a bad idea that worked.
I sadly do not possess much time, and quite frankly, most of the rest of this page/series will go over your head.
@@ -32,7 +32,7 @@ But you also know the **fear**.
The fear that if you delete the wrong file, mess with the wrong package, or even upgrade to a new release, your computer might implode, and you'll have no idea how to get back to the way things were.
-> That's \*\*\*\*\*\*\* it I'm switching back to Windows forever
+> That's it I'm _\<redacted\>_ switching back to Windows forever
> --> **Me** ~~(right after the 69420th distro-hop that caused my system to crash and burn)~~
**NixOS is different.**
@@ -40,66 +40,64 @@ The fear that if you delete the wrong file, mess with the wrong package, or even
Basically, you define a **blueprint** - a single configuration file that describes exactly how you want your computer to function.
You want Firefox? You write `firefox` in the file. You wanna set your wallpaper? Just chuck it into the file.
-After you're done, [Nix](https://github.com/NixOS/nix) looks at it, nods, and builds your entire operating system from scratch to match exactly what you wrote.
+After you're done, [Nix](https://github.com/NixOS/nix) reads it, and builds your entire operating system to match exactly what you wrote.
If you mess up, you just undo the text in the file, and your computer goes back to being perfect.
And oh, lest I forget to mention, you’d never have to deal with the godforsaken dependency hell [^1].
---
-_Now that the theatrics are out of the way, let's proceed to see more of it_
+_And now for the theatrics..._
# The Descent into Madness
It started innocently enough. I just wanted a system that was **reproducible**.
I began with **Nix Flakes**, the "Gateway Drug" [^2] of the ecosystem.
-Instead of vaguely gesturing at a repository and hoping for the best, `flake.nix` locks every input dependency of my system to a specific commit hash.
-It is the ultimate insurance policy: if I compile this system today, or in about 10 years in the midst of an imminent meteor strike, I will get the exact same binary output.
+Instead of vaguely gesturing at a repository and hoping for the best, `flake.nix` declares every input my system depends on, and `flake.lock` pins each one to an exact revision.
+It is the ultimate insurance policy: if I build this system today, or in about 10 years in the midst of an imminent meteor strike, I will get the exact same system [^4].
But having a reproducible system wasn't enough. It had to be **obedient**.
I pulled in [**Home Manager**](https://github.com/nix-community/home-manager) because configuring the OS wasn't enough; I needed to micromanage my user config files too.
-Then came [**Stylix**](https://github.com/nix-community/stylix). I declare a single image and a color scheme, and Stylix brutally enforces this theme across everything. It forces CSS into [Waybar](https://github.com/Alexays/Waybar), recompiles all my app themes, and even bullies my terminal into submission.
-But why stop there? I grabbed [**Spicetify**](https://github.com/Gerg-L/spicetify-nix) to force Spotify to match my aesthetic, and [**Nixcord**](https://github.com/FlameFlag/nixcord) for Discord cuz the default grey was offending my eyes.
+Then came [**Stylix**](https://github.com/nix-community/stylix). I declare a single image and a color scheme, and Stylix enforces this theme across everything. It generates CSS for [Waybar](https://github.com/Alexays/Waybar), restyles all my apps, and even bullies my terminal into submission.
+But why stop there? I grabbed [**Spicetify**](https://github.com/Gerg-L/spicetify-nix) to force Spotify to match my aesthetic, and [**Nixcord**](https://github.com/FlameFlag/nixcord) for Discord cuz why the heck not.
**"Okay, it's pretty," you say. "But is it useful?"**
-You have no idea.
+You have no idea [^4].
I don't "install" development tools. I have a [directory](https://github.com/maydayv7/dotfiles/tree/main/shells) that defines isolated environments for C++, Python, JavaScript and so on.
When I `cd` into a project, [Direnv](https://direnv.net/) and [**Lorri**](https://github.com/nix-community/lorri) kick in, and the compiler, linter, LSP and whatnot along with all of their configuration just _appear_ in my shell. When I leave, they vanish.
-Every little thing is specified in code, from backups to network settings and even complex editor workflows (Thank you for your concern, but I very likey my trusty [VS Code](https://code.visualstudio.com/)).
+Every little thing is specified in code, from backups to network settings and even complex editor workflows (thanks for your concern, but I very likey my trusty [VS Code](https://code.visualstudio.com/)).
Heck, even my **_Printer_** configuration is defined in a Nix file.
-**Oh, you thought that would be enough to satiate me?**
+**Well what else do ya need?**
-Please.
+I still wanted to play games and run Android apps. A normal person would dual-boot or use an emulator.
-I needed to know that my system was _spiritually_ pure. So I formatted my drive with [ZFS](https://github.com/openzfs/zfs) (it's own [merits](https://itsfoss.com/what-is-zfs/) aside) and implemented [**Impermanence**](https://github.com/nix-community/impermanence).
-Every time I reboot, my root filesystem is nuked. Wiped. Gone. My OS is resurrected from a blank slate every boot, preserving only what I explicitly whitelist on a separate dataset.
-To manage secrets without them dying in the purge, I use [**sops-nix**](https://github.com/Mic92/sops-nix) to encrypt passwords and API keys using GPG, directly into my publicly hosted `git` repo, without leaking any sensitive data.
+I run [Waydroid](https://github.com/waydroid/waydroid) to run Android in a container.
+Then, for the _pièce de résistance_, I set up [VFIO](https://docs.kernel.org/driver-api/vfio.html) GPU Passthrough [^3]. I pass that GPU directly into a Windows VM and use [Looking Glass](https://looking-glass.io/) to stream the video output back to my PC screen with negligible latency.
+
+I've also declaratively configured [**Minecraft Servers**](https://github.com/Infinidoge/nix-minecraft) _(cuz that 2 week period happens every other month for me, don't judge)_.
**At this point most people would stop**
Well I didn't.
-I still wanted to play games and run Android apps. A normal person would dual-boot or use an emulator. I chose violence.
-
-I run [Waydroid](https://github.com/waydroid/waydroid) to virtualize Android directly on the Linux kernel.
-Then, for the _pièce de résistance_, I set up [VFIO](https://docs.kernel.org/driver-api/vfio.html) GPU Passthrough [^3]. I pass that GPU directly into a Windows Virtual Machine and use [Looking Glass](https://looking-glass.io/) to stream the video output back to my PC screen with negligible latency.
-
-I've also declaratively configured [**Minecraft Servers**](https://github.com/Infinidoge/nix-minecraft) (that 2 week period lasted for months actually, don't judge) and [Wine](https://www.winehq.org/) applications (shoutout to [Erosanix](https://github.com/emmanuelrosa/erosanix)).
+I needed to know that my system was _spiritually_ pure. So I formatted my drive with [ZFS](https://github.com/openzfs/zfs) (its own [merits](https://itsfoss.com/what-is-zfs/) aside) and implemented [**Impermanence**](https://github.com/nix-community/impermanence).
+Every time I reboot, my root dataset rolls back to an empty snapshot. Wiped. Gone. My OS comes back from a blank slate every boot, preserving only what I explicitly whitelist on a separate dataset.
+To manage secrets without em dying in the purge, I use [**sops-nix**](https://github.com/Mic92/sops-nix) to encrypt passwords and API keys using GPG, directly into my publicly hosted `git` repo, without leaking any sensitive data.
**The result of all this?**
-If I buy a new computer today, I don't spend a week installing drivers and recovering passwords.
+If I buy a new computer today, I don't spend a week installing drivers and recovering my workflow.
I clone my repository. I run one single command.
-And I go get a coffee. Soon as I return [^4], I spin up a AAA Windows game, displayed on a tiling Linux WM (heck even choose between [Hyprland](https://hypr.land/) and [Niri](https://github.com/YaLTeR/niri)), on a system that deletes and rebuilds itself on every boot.
+~~And I doomscroll~~. Soon as I return [^4], I spin up an AAA Windows game, displayed on a tiling Linux WM (heck, even choose between [Hyprland](https://hypr.land/) and [Niri](https://github.com/YaLTeR/niri)), on a system that deletes and rebuilds itself on every boot.
-God, I love NixOS.
+God, I love NixOS, and I hate it cuz now I can't go back to anything else.
# A Fair Warning
@@ -107,11 +105,11 @@ Before you rush off to install this magical operating system, we need to have a
**NixOS is hard.**
-And I don't mean "Linux is hard" kind of hard. Its more "I have to relearn how my computer works" kind of hard.
+And I don't mean "Linux is hard" kind of hard. Its more "I have to relearn how everything works" kind of hard.
- **It is not standard Linux**: Most tutorials you find on the internet simply will not work here. You can't just `apt install` your problems away.
-- **The Documentation is... sparse**: Sometimes you will be reading a manual, and sometimes you will be reading 5-year-old Reddit threads praying for an answer.
-- **Patience is key** (_or severe OCD tbh_): If you are not acquainted with the command line, programming languages, random crash logs, or want a computer that "just works" to play games or browse the web, consider yourself warned. Cuz this setup costs time, sanity, and a concerning amount of self-restraint to avoid mutilating your PC.
+- **The Documentation is... sparse**: Sometimes you will be reading a manual, and sometimes you will be reading 10-year-old Reddit threads praying for an answer.
+- **Patience is key** (_or severe OCD tbh_): If you are not acquainted with the command line, programming languages, random crash logs, or want a computer that "just works" to play games or browse the web, consider yourself warned. Cuz this setup costs time, sanity, and a concerning amount of self-restraint.
# Still Reading?