From 1eb01464e19944b14f858861c7714c46e05b5a70 Mon Sep 17 00:00:00 2001 From: jackjohn7 <70782491+jackjohn7@users.noreply.github.com> Date: Sat, 28 Mar 2026 18:35:54 -0500 Subject: [PATCH] feat: ralph, waybar, formatted --- flake.nix | 2 +- modules/features/hyprland/default.nix | 117 ++++--- modules/features/hyprland/hyprland.conf | 42 ++- modules/features/layers/base.nix | 95 ++--- modules/features/layers/cursors.nix | 78 +++-- modules/features/layers/development.nix | 93 ++++- modules/features/layers/fonts.nix | 29 +- modules/features/layers/gaming.nix | 35 +- modules/features/layers/pipewire.nix | 35 +- modules/features/layers/user.nix | 31 +- modules/features/layers/users/jingo.nix | 12 +- modules/features/layers/users/jingus.nix | 13 +- modules/features/layers/wallpapers.nix | 56 +-- modules/features/librewolf.nix | 77 +++-- modules/features/niri.nix | 207 ++++++----- modules/features/noctalia.nix | 15 +- modules/features/ralph.nix | 26 ++ .../waybar/config/cffi_example/.gitignore | 1 + .../waybar/config/cffi_example/README.md | 38 ++ .../waybar/config/cffi_example/main.c | 70 ++++ .../waybar/config/cffi_example/meson.build | 13 + .../config/cffi_example/waybar_cffi_module.h | 95 +++++ modules/features/waybar/config/config.jsonc | 210 +++++++++++ .../features/waybar/config/icons/meson.build | 6 + .../waybar-privacy-audio-input-symbolic.svg | 4 + .../waybar-privacy-audio-output-symbolic.svg | 2 + .../waybar-privacy-screen-share-symbolic.svg | 7 + .../config/icons/waybar_icons.gresource.xml | 8 + modules/features/waybar/config/mediaplayer.py | 196 +++++++++++ modules/features/waybar/config/power_menu.xml | 28 ++ modules/features/waybar/config/style.css | 327 ++++++++++++++++++ modules/features/waybar/default.nix | 30 ++ modules/hosts/desktop/configuration.nix | 120 +++---- modules/hosts/desktop/default.nix | 3 +- .../hosts/desktop/hardware-configuration.nix | 66 ++-- modules/hosts/laptop/configuration.nix | 265 +++++++------- modules/hosts/laptop/default.nix | 3 +- .../hosts/laptop/hardware-configuration.nix | 67 ++-- 38 files changed, 1913 insertions(+), 609 deletions(-) create mode 100644 modules/features/ralph.nix create mode 100644 modules/features/waybar/config/cffi_example/.gitignore create mode 100644 modules/features/waybar/config/cffi_example/README.md create mode 100644 modules/features/waybar/config/cffi_example/main.c create mode 100644 modules/features/waybar/config/cffi_example/meson.build create mode 100644 modules/features/waybar/config/cffi_example/waybar_cffi_module.h create mode 100644 modules/features/waybar/config/config.jsonc create mode 100644 modules/features/waybar/config/icons/meson.build create mode 100644 modules/features/waybar/config/icons/waybar-privacy-audio-input-symbolic.svg create mode 100644 modules/features/waybar/config/icons/waybar-privacy-audio-output-symbolic.svg create mode 100644 modules/features/waybar/config/icons/waybar-privacy-screen-share-symbolic.svg create mode 100644 modules/features/waybar/config/icons/waybar_icons.gresource.xml create mode 100755 modules/features/waybar/config/mediaplayer.py create mode 100644 modules/features/waybar/config/power_menu.xml create mode 100644 modules/features/waybar/config/style.css create mode 100644 modules/features/waybar/default.nix diff --git a/flake.nix b/flake.nix index 284b6dc..eda2776 100644 --- a/flake.nix +++ b/flake.nix @@ -18,5 +18,5 @@ }; }; - outputs = inputs: inputs.flake-parts.lib.mkFlake {inherit inputs;} (inputs.import-tree ./modules); + outputs = inputs: inputs.flake-parts.lib.mkFlake { inherit inputs; } (inputs.import-tree ./modules); } diff --git a/modules/features/hyprland/default.nix b/modules/features/hyprland/default.nix index aa32bc5..a9ad502 100644 --- a/modules/features/hyprland/default.nix +++ b/modules/features/hyprland/default.nix @@ -1,60 +1,75 @@ -{ self, inputs, ... }: { - flake.nixosModules.hyprland = { pkgs, lib, config, ... }: { - imports = [ self.nixosModules.cursors ]; - - options.hyprland-users = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "List of users to configure hyprland for"; - }; - - config = { - # System-level configuration - programs.hyprland.enable = true; - - environment.systemPackages = with pkgs; [ - waybar - hyprpaper - wofi - kitty - firefox - dolphin - wl-clipboard - brightnessctl - playerctl - grim - xdg-desktop-portal-hyprland - xdg-desktop-portal-gtk - gnome-keyring - seahorse +{ self, inputs, ... }: +{ + flake.nixosModules.hyprland = + { + pkgs, + lib, + config, + ... + }: + { + imports = [ + self.nixosModules.cursors + self.nixosModules.waybar + self.nixosModules.wallpapers ]; - services.gnome.gnome-keyring.enable = true; - services.dbus.packages = [ pkgs.gnome-keyring pkgs.gcr ]; - programs.seahorse.enable = true; + options.hyprland-users = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of users to configure hyprland for"; + }; - xdg.portal = { - enable = true; - extraPortals = [ - pkgs.xdg-desktop-portal-gtk - pkgs.xdg-desktop-portal-hyprland + config = { + # System-level configuration + programs.hyprland.enable = true; + + environment.systemPackages = with pkgs; [ + waybar + hyprpaper + wofi + kitty + firefox + wl-clipboard + brightnessctl + playerctl + grim + xdg-desktop-portal-hyprland + xdg-desktop-portal-gtk + gnome-keyring + seahorse + flameshot ]; - configPackages = [ pkgs.xdg-desktop-portal-gnome ]; - }; - # Configure hjem for specified users - hjem = lib.mkIf (config.hyprland-users != []) { - users = lib.genAttrs config.hyprland-users (username: { + services.gnome.gnome-keyring.enable = true; + services.dbus.packages = [ + pkgs.gnome-keyring + pkgs.gcr + ]; + programs.seahorse.enable = true; + + xdg.portal = { enable = true; - files = { - ".config/hypr/hyprland.conf".source = ./hyprland.conf; - ".config/hypr/hyprpaper.conf".source = ./hyprpaper.conf; - }; - }); - }; + extraPortals = [ + pkgs.xdg-desktop-portal-gtk + pkgs.xdg-desktop-portal-hyprland + ]; + configPackages = [ pkgs.xdg-desktop-portal-gnome ]; + }; - # Enable cursors for hyprland users - cursor-users = lib.mkDefault config.hyprland-users; + # Configure hjem for specified users + hjem = lib.mkIf (config.hyprland-users != [ ]) { + users = lib.genAttrs config.hyprland-users (username: { + enable = true; + files = { + ".config/hypr/hyprland.conf".source = ./hyprland.conf; + ".config/hypr/hyprpaper.conf".source = ./hyprpaper.conf; + }; + }); + }; + + # Enable cursors for hyprland users + cursor-users = lib.mkDefault config.hyprland-users; + }; }; - }; } diff --git a/modules/features/hyprland/hyprland.conf b/modules/features/hyprland/hyprland.conf index ebd5316..80b83c6 100644 --- a/modules/features/hyprland/hyprland.conf +++ b/modules/features/hyprland/hyprland.conf @@ -32,7 +32,7 @@ $menu = wofi --show drun # exec-once = $terminal # exec-once = nm-applet & exec-once = hyprctl setcursor Bibata-Modern-Ice 24 -exec-once = waybar & hyprpaper +exec-once = waybar & flameshot & hyprpaper # This exports the necessary variables for Electron to find the Keyring exec-once = dbus-update-activation-environment --systemd WAYLAND_DISPLAY XDG_CURRENT_DESKTOP # This starts the daemon and makes it the "Secret Service" provider @@ -197,9 +197,9 @@ input { } # https://wiki.hyprland.org/Configuring/Variables/#gestures -gestures { - workspace_swipe = false -} +# gestures { +# workspace_swipe = false +# } # Example per-device config # See https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs for more @@ -291,11 +291,35 @@ bindl = , XF86AudioPrev, exec, playerctl previous # See https://wiki.hyprland.org/Configuring/Workspace-Rules/ for workspace rules # Example windowrule -windowrulev2 = workspace 2, class:^(firefox)$ -windowrulev2 = workspace 4, class:^(vesktop)$ +windowrule { + name = firefox-on-w2 + match:class = ^(firefox)$ + workspace = 2 +} +windowrule { + name = vesktop-on-w4 + match:class = ^(vesktop)$ + workspace = 4 +} -# Ignore maximize requests from apps. You'll probably like this. -windowrule = suppressevent maximize, class:.* +windowrule { + # Ignore maximize requests from all apps. You'll probably like this. + name = suppress-maximize-events + match:class = .* + + suppress_event = maximize +} # Fix some dragging issues with XWayland -windowrule = nofocus,class:^$,title:^$,xwayland:1,floating:1,fullscreen:0,pinned:0 +windowrule { + # Fix some dragging issues with XWayland + name = fix-xwayland-drags + match:class = ^$ + match:title = ^$ + match:xwayland = true + match:float = true + match:fullscreen = false + match:pin = false + + no_focus = true +} diff --git a/modules/features/layers/base.nix b/modules/features/layers/base.nix index 7284b91..aa01534 100644 --- a/modules/features/layers/base.nix +++ b/modules/features/layers/base.nix @@ -1,52 +1,53 @@ -{ self, inputs, ... }: { - flake.nixosModules.base = { pkgs, lib, ... }: { - imports = [ inputs.hjem.nixosModules.default ]; +{ self, inputs, ... }: +{ + flake.nixosModules.base = + { pkgs, lib, ... }: + { + imports = [ inputs.hjem.nixosModules.default ]; - nixpkgs.overlays = [ inputs.millennium.overlays.default ]; - # Set your time zone. - time.timeZone = "America/Chicago"; + nixpkgs.overlays = [ inputs.millennium.overlays.default ]; + # Set your time zone. + time.timeZone = "America/Chicago"; - # Select internationalisation properties. - i18n.defaultLocale = "en_US.UTF-8"; + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + + i18n.extraLocaleSettings = { + LC_ADDRESS = "en_US.UTF-8"; + LC_IDENTIFICATION = "en_US.UTF-8"; + LC_MEASUREMENT = "en_US.UTF-8"; + LC_MONETARY = "en_US.UTF-8"; + LC_NAME = "en_US.UTF-8"; + LC_NUMERIC = "en_US.UTF-8"; + LC_PAPER = "en_US.UTF-8"; + LC_TELEPHONE = "en_US.UTF-8"; + LC_TIME = "en_US.UTF-8"; + }; + + # Enable the X11 windowing system. + services.xserver.enable = true; + + # Configure keymap in X11 + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; + + # Enable CUPS to print documents. + services.printing.enable = true; + + # Enable touchpad support (enabled default in most desktopManager). + # services.xserver.libinput.enable = true; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + # List services that you want to enable: - i18n.extraLocaleSettings = { - LC_ADDRESS = "en_US.UTF-8"; - LC_IDENTIFICATION = "en_US.UTF-8"; - LC_MEASUREMENT = "en_US.UTF-8"; - LC_MONETARY = "en_US.UTF-8"; - LC_NAME = "en_US.UTF-8"; - LC_NUMERIC = "en_US.UTF-8"; - LC_PAPER = "en_US.UTF-8"; - LC_TELEPHONE = "en_US.UTF-8"; - LC_TIME = "en_US.UTF-8"; }; - - # Enable the X11 windowing system. - services.xserver.enable = true; - - # Configure keymap in X11 - services.xserver.xkb = { - layout = "us"; - variant = ""; - }; - - # Enable CUPS to print documents. - services.printing.enable = true; - - - # Enable touchpad support (enabled default in most desktopManager). - # services.xserver.libinput.enable = true; - - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; - - # List services that you want to enable: - - }; } diff --git a/modules/features/layers/cursors.nix b/modules/features/layers/cursors.nix index 1d02ca5..6e83d0f 100644 --- a/modules/features/layers/cursors.nix +++ b/modules/features/layers/cursors.nix @@ -1,41 +1,49 @@ -{ self, inputs, ... }: { - flake.nixosModules.cursors = { pkgs, lib, config, ... }: { - options.cursor-users = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "List of users to configure cursors for"; - }; +{ self, inputs, ... }: +{ + flake.nixosModules.cursors = + { + pkgs, + lib, + config, + ... + }: + { + options.cursor-users = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of users to configure cursors for"; + }; - config = { - # Install cursor packages system-wide - environment.systemPackages = with pkgs; [ - bibata-cursors - ]; + config = { + # Install cursor packages system-wide + environment.systemPackages = with pkgs; [ + bibata-cursors + ]; - # Set up XDG data directories for cursor themes - environment.pathsToLink = [ "/share/icons" ]; + # Set up XDG data directories for cursor themes + environment.pathsToLink = [ "/share/icons" ]; - # Configure hjem for specified users - set cursor theme in user config - hjem = lib.mkIf (config.cursor-users != []) { - users = lib.genAttrs config.cursor-users (username: { - enable = true; - files = { - # GTK cursor settings - ".config/gtk-3.0/settings.ini".text = '' - [Settings] - gtk-cursor-theme-name=Bibata-Modern-Ice - gtk-cursor-theme-size=24 - ''; - # X11/Wayland cursor environment - ".config/environment.d/cursor.conf".text = '' - XCURSOR_THEME=Bibata-Modern-Ice - XCURSOR_SIZE=24 - HYPRCURSOR_THEME=Bibata-Modern-Ice - HYPRCURSOR_SIZE=24 - ''; - }; - }); + # Configure hjem for specified users - set cursor theme in user config + hjem = lib.mkIf (config.cursor-users != [ ]) { + users = lib.genAttrs config.cursor-users (username: { + enable = true; + files = { + # GTK cursor settings + ".config/gtk-3.0/settings.ini".text = '' + [Settings] + gtk-cursor-theme-name=Bibata-Modern-Ice + gtk-cursor-theme-size=24 + ''; + # X11/Wayland cursor environment + ".config/environment.d/cursor.conf".text = '' + XCURSOR_THEME=Bibata-Modern-Ice + XCURSOR_SIZE=24 + HYPRCURSOR_THEME=Bibata-Modern-Ice + HYPRCURSOR_SIZE=24 + ''; + }; + }); + }; }; }; - }; } diff --git a/modules/features/layers/development.nix b/modules/features/layers/development.nix index 047c657..6050395 100644 --- a/modules/features/layers/development.nix +++ b/modules/features/layers/development.nix @@ -1,10 +1,85 @@ -{ self, inputs, ... }: { - flake.nixosModules.development = { pkgs, lib, ... }: { - environment.systemPackages = with pkgs; [ - vim - git - zed-editor - opencode - ]; - }; +{ self, inputs, ... }: +{ + flake.nixosModules.development = + { pkgs, lib, ... }: + { + config = { + environment.systemPackages = with pkgs; [ + vim + git + zed-editor + opencode + direnv + nix-direnv + ]; + programs.zoxide = { + enable = true; + enableZshIntegration = true; + }; + programs.zsh = { + enable = true; + + # Nice features + enableCompletion = true; + enableAutosuggestions = true; + syntaxHighlighting.enable = true; + + # Optional prompt theme — Powerlevel10k is very popular + oh-my-zsh = { + enable = true; + plugins = [ + "git" + "direnv" + "z" + ]; + theme = "robbyrussell"; # or try "agnoster" + }; + + # HISTORY + histSize = 10000; + + # Extra config (this is appended at the end of .zshrc) + promptInit = '' + # Aliases + alias ll="ls -alF" + + # Load nix-direnv if available + if command -v direnv >/dev/null; then + eval "$(direnv hook zsh)" + fi + + # Better Ctrl-R incremental search + bindkey '^R' history-incremental-search-backward + + # Improve cd: automatically pushd to track dirs + setopt auto_pushd + setopt pushd_ignore_dups + + # Enable command correction + setopt correct + ''; + }; + + # Configure starship prompt + programs.starship = { + enable = true; + # enableZshIntegration = true; + settings = { + add_newline = false; + character = { + success_symbol = "[➜](bold green)"; + error_symbol = "[✗](bold red)"; + }; + directory.truncate_to_repo = false; + nix_shell = { + disabled = false; + symbol = "❄️ "; + format = "[$symbol$name]($style) "; + }; + git_branch.symbol = "🌿 "; + }; + }; + }; + + }; } diff --git a/modules/features/layers/fonts.nix b/modules/features/layers/fonts.nix index eb949ba..f81dd20 100644 --- a/modules/features/layers/fonts.nix +++ b/modules/features/layers/fonts.nix @@ -1,14 +1,17 @@ -{ self, inputs, ... }: { - flake.nixosModules.fonts = { pkgs, lib, ... }: { - fonts.packages = with pkgs; [ - noto-fonts - noto-fonts-cjk-sans - noto-fonts-color-emoji - liberation_ttf - nerd-fonts.martian-mono - dina-font - proggyfonts - ripgrep - ]; - }; +{ self, inputs, ... }: +{ + flake.nixosModules.fonts = + { pkgs, lib, ... }: + { + fonts.packages = with pkgs; [ + noto-fonts + noto-fonts-cjk-sans + noto-fonts-color-emoji + liberation_ttf + nerd-fonts.martian-mono + dina-font + proggyfonts + ripgrep + ]; + }; } diff --git a/modules/features/layers/gaming.nix b/modules/features/layers/gaming.nix index f05bf1b..fd8355e 100644 --- a/modules/features/layers/gaming.nix +++ b/modules/features/layers/gaming.nix @@ -1,18 +1,21 @@ -{ self, inputs, ... }: { - flake.nixosModules.gaming = { pkgs, lib, ... }: { - programs.steam = { - enable = true; - package = pkgs.millennium-steam; - gamescopeSession.enable = true; +{ self, inputs, ... }: +{ + flake.nixosModules.gaming = + { pkgs, lib, ... }: + { + programs.steam = { + enable = true; + package = pkgs.millennium-steam; + gamescopeSession.enable = true; + }; + programs.gamemode.enable = true; + environment.systemPackages = with pkgs; [ + mangohud + protonup-ng + heroic + ]; + environment.sessionVariables = { + STEAM_EXTRA_COMPAT_TOOLS_PATH = "/home/user/.steam/root/compatibilitytools.d"; + }; }; - programs.gamemode.enable = true; - environment.systemPackages = with pkgs; [ - mangohud - protonup-ng - heroic - ]; - environment.sessionVariables = { - STEAM_EXTRA_COMPAT_TOOLS_PATH = "/home/user/.steam/root/compatibilitytools.d"; - }; - }; } diff --git a/modules/features/layers/pipewire.nix b/modules/features/layers/pipewire.nix index b58f7ca..036a2cf 100644 --- a/modules/features/layers/pipewire.nix +++ b/modules/features/layers/pipewire.nix @@ -1,19 +1,22 @@ -{ self, inputs, ... }: { - flake.nixosModules.pipewire = { pkgs, lib, ... }: { - # Enable sound with pipewire. - services.pulseaudio.enable = false; - security.rtkit.enable = true; - services.pipewire = { - enable = true; - alsa.enable = true; - alsa.support32Bit = true; - pulse.enable = true; - # If you want to use JACK applications, uncomment this - #jack.enable = true; +{ self, inputs, ... }: +{ + flake.nixosModules.pipewire = + { pkgs, lib, ... }: + { + # Enable sound with pipewire. + services.pulseaudio.enable = false; + security.rtkit.enable = true; + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + # If you want to use JACK applications, uncomment this + #jack.enable = true; - # use the example session manager (no others are packaged yet so this is enabled by default, - # no need to redefine it in your config for now) - #media-session.enable = true; + # use the example session manager (no others are packaged yet so this is enabled by default, + # no need to redefine it in your config for now) + #media-session.enable = true; + }; }; - }; } diff --git a/modules/features/layers/user.nix b/modules/features/layers/user.nix index 94a9427..43fd392 100644 --- a/modules/features/layers/user.nix +++ b/modules/features/layers/user.nix @@ -1,15 +1,20 @@ - -{ self, inputs, ... }: { - flake.nixosModules.user = { pkgs, lib, ... }: { - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.jingus = { - isNormalUser = true; - description = "jingus"; - extraGroups = [ "networkmanager" "wheel" ]; - shell = pkgs.zsh; - packages = with pkgs; [ - # thunderbird - ]; +{ self, inputs, ... }: +{ + flake.nixosModules.user = + { pkgs, lib, ... }: + { + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.jingus = { + isNormalUser = true; + description = "jingus"; + extraGroups = [ + "networkmanager" + "wheel" + ]; + shell = pkgs.zsh; + packages = with pkgs; [ + # thunderbird + ]; + }; }; - }; } diff --git a/modules/features/layers/users/jingo.nix b/modules/features/layers/users/jingo.nix index 19ec2ac..d7053ea 100644 --- a/modules/features/layers/users/jingo.nix +++ b/modules/features/layers/users/jingo.nix @@ -1,5 +1,9 @@ -{ self, inputs, ... }: { - flake.nixosModules.user-jingo = { ... }: { - hyprland-users = [ "jingo" ]; - }; +{ self, inputs, ... }: +{ + flake.nixosModules.user-jingo = + { ... }: + { + hyprland-users = [ "jingo" ]; + wallpaper-users = [ "jingo" ]; + }; } diff --git a/modules/features/layers/users/jingus.nix b/modules/features/layers/users/jingus.nix index d768337..a3b3cde 100644 --- a/modules/features/layers/users/jingus.nix +++ b/modules/features/layers/users/jingus.nix @@ -1,6 +1,9 @@ -{ self, inputs, ... }: { - flake.nixosModules.user-jingus = { ... }: { - niri-users = [ "jingus" ]; - wallpaper-users = [ "jingus" ]; - }; +{ self, inputs, ... }: +{ + flake.nixosModules.user-jingus = + { ... }: + { + niri-users = [ "jingus" ]; + wallpaper-users = [ "jingus" ]; + }; } diff --git a/modules/features/layers/wallpapers.nix b/modules/features/layers/wallpapers.nix index ad02eb7..61ca8b8 100644 --- a/modules/features/layers/wallpapers.nix +++ b/modules/features/layers/wallpapers.nix @@ -1,30 +1,38 @@ -{ self, inputs, ... }: { - flake.nixosModules.wallpapers = { pkgs, lib, config, ... }: { +{ self, inputs, ... }: +{ + flake.nixosModules.wallpapers = + { + pkgs, + lib, + config, + ... + }: + { - options.wallpaper-users = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "List of users to include wallpapers for"; - }; + options.wallpaper-users = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of users to include wallpapers for"; + }; - options.wallpaper-destination = lib.mkOption { - type = lib.types.str; - default = "Pictures/Wallpapers"; - description = "Destination path for wallpapers"; - }; + options.wallpaper-destination = lib.mkOption { + type = lib.types.str; + default = "Pictures/Wallpapers"; + description = "Destination path for wallpapers"; + }; - config = { - hjem = lib.mkIf (config.wallpaper-users != []) { - users = lib.genAttrs config.wallpaper-users (username: { - enable = true; - files = { - "${config.wallpaper-destination}".source = pkgs.runCommand "wallpapers" {} '' - mkdir -p $out - cp -r ${../../../assets/wallpapers}/* $out/ - ''; - }; - }); + config = { + hjem = lib.mkIf (config.wallpaper-users != [ ]) { + users = lib.genAttrs config.wallpaper-users (username: { + enable = true; + files = { + "${config.wallpaper-destination}".source = pkgs.runCommand "wallpapers" { } '' + mkdir -p $out + cp -r ${../../../assets/wallpapers}/* $out/ + ''; + }; + }); + }; }; }; - }; } diff --git a/modules/features/librewolf.nix b/modules/features/librewolf.nix index 5f523e6..4b2262f 100644 --- a/modules/features/librewolf.nix +++ b/modules/features/librewolf.nix @@ -1,43 +1,46 @@ -{ self, inputs, ... }: { - flake.nixosModules.librewolf = { pkgs, lib, ... }: { - programs.firefox = { - enable = true; - package = pkgs.librewolf; - policies = { - SearchEngines = { - Default = "DuckDuckGo"; - PreventInstalls = true; - }; - DisableTelemetry = true; - DisableFirefoxStudies = true; - Preferences = { - "webgl.disabled" = false; - "privacy.resistFingerprinting" = false; - "privacy.clearOnShutdown.history" = false; - "privacy.clearOnShutdown.cookies" = false; - "network.cookie.lifetimePolicy" = 0; - "cookiebanners.service.mode.privateBrowsing" = 2; # Block cookie banners in private browsing - "cookiebanners.service.mode" = 2; # Block cookie banners - "privacy.donottrackheader.enabled" = true; - "privacy.fingerprintingProtection" = true; - "privacy.trackingprotection.emailtracking.enabled" = true; - "privacy.trackingprotection.enabled" = true; - "privacy.trackingprotection.fingerprinting.enabled" = true; - "privacy.trackingprotection.socialtracking.enabled" = true; - }; - ExtensionSettings = { - "jid1-ZAdIEUB7XOzOJw@jetpack" = { - install_url = "https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/latest.xpi"; - installation_mode = "force_installed"; +{ self, inputs, ... }: +{ + flake.nixosModules.librewolf = + { pkgs, lib, ... }: + { + programs.firefox = { + enable = true; + package = pkgs.librewolf; + policies = { + SearchEngines = { + Default = "DuckDuckGo"; + PreventInstalls = true; }; - "uBlock0@raymondhill.net" = { - install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; - installation_mode = "force_installed"; + DisableTelemetry = true; + DisableFirefoxStudies = true; + Preferences = { + "webgl.disabled" = false; + "privacy.resistFingerprinting" = false; + "privacy.clearOnShutdown.history" = false; + "privacy.clearOnShutdown.cookies" = false; + "network.cookie.lifetimePolicy" = 0; + "cookiebanners.service.mode.privateBrowsing" = 2; # Block cookie banners in private browsing + "cookiebanners.service.mode" = 2; # Block cookie banners + "privacy.donottrackheader.enabled" = true; + "privacy.fingerprintingProtection" = true; + "privacy.trackingprotection.emailtracking.enabled" = true; + "privacy.trackingprotection.enabled" = true; + "privacy.trackingprotection.fingerprinting.enabled" = true; + "privacy.trackingprotection.socialtracking.enabled" = true; + }; + ExtensionSettings = { + "jid1-ZAdIEUB7XOzOJw@jetpack" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/duckduckgo-for-firefox/latest.xpi"; + installation_mode = "force_installed"; + }; + "uBlock0@raymondhill.net" = { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/ublock-origin/latest.xpi"; + installation_mode = "force_installed"; + }; }; }; }; - }; - environment.etc."firefox/policies/policies.json".target = "librewolf/policies/policies.json"; - }; + environment.etc."firefox/policies/policies.json".target = "librewolf/policies/policies.json"; + }; } diff --git a/modules/features/niri.nix b/modules/features/niri.nix index ccadc63..6d8347f 100644 --- a/modules/features/niri.nix +++ b/modules/features/niri.nix @@ -1,113 +1,130 @@ -{ self, inputs, ... }: { - flake.nixosModules.niri = { pkgs, lib, config, ... }: { - imports = [ - self.nixosModules.cursors - self.nixosModules.wallpapers - ]; +{ self, inputs, ... }: +{ + flake.nixosModules.niri = + { + pkgs, + lib, + config, + ... + }: + { + imports = [ + self.nixosModules.cursors + self.nixosModules.wallpapers + ]; - options.niri-users = lib.mkOption { - type = lib.types.listOf lib.types.str; - default = []; - description = "List of users to configure niri for"; - }; - - config = { - programs.niri = { - enable = true; - package = self.packages.${pkgs.stdenv.hostPlatform.system}.myNiri; + options.niri-users = lib.mkOption { + type = lib.types.listOf lib.types.str; + default = [ ]; + description = "List of users to configure niri for"; }; - # Enable cursors for niri users - cursor-users = lib.mkDefault config.niri-users; + config = { + programs.niri = { + enable = true; + package = self.packages.${pkgs.stdenv.hostPlatform.system}.myNiri; + }; - # Set wallpaper destination explicitly - wallpaper-destination = "Pictures/Wallpapers"; + # Enable cursors for niri users + cursor-users = lib.mkDefault config.niri-users; + + # Set wallpaper destination explicitly + wallpaper-destination = "Pictures/Wallpapers"; + }; }; - }; - perSystem = { pkgs, lib, self', ... }: { - packages.myNiri = inputs.wrapper-modules.wrappers.niri.wrap { - inherit pkgs; - settings = { - spawn-at-startup = [ - (lib.getExe self'.packages.myNoctalia) - "steam" - ]; - xwayland-satellite.path = lib.getExe pkgs.xwayland-satellite; - input.keyboard = { - xkb.layout = "us"; - }; + perSystem = + { + pkgs, + lib, + self', + ... + }: + { + packages.myNiri = inputs.wrapper-modules.wrappers.niri.wrap { + inherit pkgs; + settings = { + spawn-at-startup = [ + (lib.getExe self'.packages.myNoctalia) + "steam" + ]; + xwayland-satellite.path = lib.getExe pkgs.xwayland-satellite; + input.keyboard = { + xkb.layout = "us"; + }; - layout = { - gaps = 24; - }; + layout = { + gaps = 24; + }; - cursor = { - xcursor-theme = "Bibata-Modern-Ice"; - xcursor-size = 24; - }; + cursor = { + xcursor-theme = "Bibata-Modern-Ice"; + xcursor-size = 24; + }; - binds = { - "Mod+R".spawn-sh = "${lib.getExe self'.packages.myNoctalia} ipc call launcher toggle"; - "Mod+Shift+W".spawn-sh = "librewolf"; - "Mod+Return".spawn-sh = lib.getExe pkgs.kitty; - "Mod+Shift+C".close-window = null; + binds = { + "Mod+R".spawn-sh = "${lib.getExe self'.packages.myNoctalia} ipc call launcher toggle"; + "Mod+Shift+W".spawn-sh = "librewolf"; + "Mod+Return".spawn-sh = lib.getExe pkgs.kitty; + "Mod+Shift+C".close-window = null; - # workspace binds - "Mod+1".focus-workspace = "w0"; - "Mod+2".focus-workspace = "w1"; - "Mod+3".focus-workspace = "w2"; - "Mod+4".focus-workspace = "w3"; - "Mod+5".focus-workspace = "w4"; - "Mod+6".focus-workspace = "w5"; - "Mod+7".focus-workspace = "w6"; - "Mod+8".focus-workspace = "w7"; - "Mod+9".focus-workspace = "w8"; - "Mod+0".focus-workspace = "w9"; + # workspace binds + "Mod+1".focus-workspace = "w0"; + "Mod+2".focus-workspace = "w1"; + "Mod+3".focus-workspace = "w2"; + "Mod+4".focus-workspace = "w3"; + "Mod+5".focus-workspace = "w4"; + "Mod+6".focus-workspace = "w5"; + "Mod+7".focus-workspace = "w6"; + "Mod+8".focus-workspace = "w7"; + "Mod+9".focus-workspace = "w8"; + "Mod+0".focus-workspace = "w9"; - "Mod+Shift+1".move-column-to-workspace = "w0"; - "Mod+Shift+2".move-column-to-workspace = "w1"; - "Mod+Shift+3".move-column-to-workspace = "w2"; - "Mod+Shift+4".move-column-to-workspace = "w3"; - "Mod+Shift+5".move-column-to-workspace = "w4"; - "Mod+Shift+6".move-column-to-workspace = "w5"; - "Mod+Shift+7".move-column-to-workspace = "w6"; - "Mod+Shift+8".move-column-to-workspace = "w7"; - "Mod+Shift+9".move-column-to-workspace = "w8"; - "Mod+Shift+0".move-column-to-workspace = "w9"; + "Mod+Shift+1".move-column-to-workspace = "w0"; + "Mod+Shift+2".move-column-to-workspace = "w1"; + "Mod+Shift+3".move-column-to-workspace = "w2"; + "Mod+Shift+4".move-column-to-workspace = "w3"; + "Mod+Shift+5".move-column-to-workspace = "w4"; + "Mod+Shift+6".move-column-to-workspace = "w5"; + "Mod+Shift+7".move-column-to-workspace = "w6"; + "Mod+Shift+8".move-column-to-workspace = "w7"; + "Mod+Shift+9".move-column-to-workspace = "w8"; + "Mod+Shift+0".move-column-to-workspace = "w9"; - # Navigation - "Mod+WheelScrollDown".focus-column-right = null; - "Mod+WheelScrollUp".focus-column-left = null; - "Mod+Ctrl+WheelScrollDown".focus-workspace-down = null; - "Mod+Ctrl+WheelScrollUp".focus-workspace-up = null; - }; + # Navigation + "Mod+WheelScrollDown".focus-column-right = null; + "Mod+WheelScrollUp".focus-column-left = null; + "Mod+Ctrl+WheelScrollDown".focus-workspace-down = null; + "Mod+Ctrl+WheelScrollUp".focus-workspace-up = null; + }; - window-rules = [ - { - geometry-corner-radius = 0; - } - { - matches = [ - { app-id = "zed"; } - ]; - default-column-width = { proportion = 1.0; }; - } - ]; + window-rules = [ + { + geometry-corner-radius = 0; + } + { + matches = [ + { app-id = "zed"; } + ]; + default-column-width = { + proportion = 1.0; + }; + } + ]; - workspaces = { - "w0" = {}; - "w1" = {}; - "w2" = {}; - "w3" = {}; - "w4" = {}; - "w5" = {}; - "w6" = {}; - "w7" = {}; - "w8" = {}; - "w9" = {}; + workspaces = { + "w0" = { }; + "w1" = { }; + "w2" = { }; + "w3" = { }; + "w4" = { }; + "w5" = { }; + "w6" = { }; + "w7" = { }; + "w8" = { }; + "w9" = { }; + }; }; }; }; - }; } diff --git a/modules/features/noctalia.nix b/modules/features/noctalia.nix index 17a3c6d..0d1e900 100644 --- a/modules/features/noctalia.nix +++ b/modules/features/noctalia.nix @@ -1,8 +1,11 @@ -{ self, inputs, ... }: { - perSystem = { pkgs, ... }: { - packages.myNoctalia = inputs.wrapper-modules.wrappers.noctalia-shell.wrap { - inherit pkgs; - settings = (builtins.fromJSON (builtins.readFile ./noctalia.json)).settings; +{ self, inputs, ... }: +{ + perSystem = + { pkgs, ... }: + { + packages.myNoctalia = inputs.wrapper-modules.wrappers.noctalia-shell.wrap { + inherit pkgs; + settings = (builtins.fromJSON (builtins.readFile ./noctalia.json)).settings; + }; }; - }; } diff --git a/modules/features/ralph.nix b/modules/features/ralph.nix new file mode 100644 index 0000000..7a61b05 --- /dev/null +++ b/modules/features/ralph.nix @@ -0,0 +1,26 @@ +{ self, inputs, ... }: +{ + perSystem = + { + pkgs, + lib, + self', + ... + }: + { + packages.ralph = pkgs.rustPlatform.buildRustPackage rec { + pname = "ralph-cli"; + version = "2.5.1"; + + src = pkgs.fetchFromGitHub { + owner = "mikeyobrien"; + repo = "ralph-orchestrator"; + rev = "v${version}"; + sha256 = "sha256-K3/nTun6mwFwYagKtQDlKsnTpoAMRy62x5TtfRMRjQc="; + }; + + cargoHash = "sha256-BuCM2CAXRR8GqUyFvgpAECVXdeafzuViiX8EtzbHGoY="; + doCheck = false; + }; + }; +} diff --git a/modules/features/waybar/config/cffi_example/.gitignore b/modules/features/waybar/config/cffi_example/.gitignore new file mode 100644 index 0000000..988107f --- /dev/null +++ b/modules/features/waybar/config/cffi_example/.gitignore @@ -0,0 +1 @@ +.cache/ \ No newline at end of file diff --git a/modules/features/waybar/config/cffi_example/README.md b/modules/features/waybar/config/cffi_example/README.md new file mode 100644 index 0000000..88396c1 --- /dev/null +++ b/modules/features/waybar/config/cffi_example/README.md @@ -0,0 +1,38 @@ +# C FFI module + +A C FFI module is a dynamic library that exposes standard C functions and +constants, that Waybar can load and execute to create custom advanced widgets. + +Most language can implement the required functions and constants (C, C++, Rust, +Go, Python, ...), meaning you can develop custom modules using your language of +choice, as long as there's GTK bindings. + +Symbols to implement are documented in the +[waybar_cffi_module.h](waybar_cffi_module.h) file. + +# Usage + +## Building this module + +```bash +meson setup build +meson compile -C build +``` + +## Load the module + +Edit your waybar config: +```json +{ + // ... + "modules-center": [ + // ... + "cffi/c_example" + ], + // ... + "cffi/c_example": { + // Path to the compiled dynamic library file + "module_path": "resources/custom_modules/cffi_example/build/wb_cffi_example.so" + } +} +``` diff --git a/modules/features/waybar/config/cffi_example/main.c b/modules/features/waybar/config/cffi_example/main.c new file mode 100644 index 0000000..7618de5 --- /dev/null +++ b/modules/features/waybar/config/cffi_example/main.c @@ -0,0 +1,70 @@ + +#include "waybar_cffi_module.h" + +typedef struct { + wbcffi_module* waybar_module; + GtkBox* container; + GtkButton* button; +} ExampleMod; + +// This static variable is shared between all instances of this module +static int instance_count = 0; + +void onclicked(GtkButton* button) { + char text[256]; + snprintf(text, 256, "Dice throw result: %d", rand() % 6 + 1); + gtk_button_set_label(button, text); +} + +// You must +const size_t wbcffi_version = 2; + +void* wbcffi_init(const wbcffi_init_info* init_info, const wbcffi_config_entry* config_entries, + size_t config_entries_len) { + printf("cffi_example: init config:\n"); + for (size_t i = 0; i < config_entries_len; i++) { + printf(" %s = %s\n", config_entries[i].key, config_entries[i].value); + } + + // Allocate the instance object + ExampleMod* inst = malloc(sizeof(ExampleMod)); + inst->waybar_module = init_info->obj; + + GtkContainer* root = init_info->get_root_widget(init_info->obj); + + // Add a container for displaying the next widgets + inst->container = GTK_BOX(gtk_box_new(GTK_ORIENTATION_HORIZONTAL, 5)); + gtk_container_add(GTK_CONTAINER(root), GTK_WIDGET(inst->container)); + + // Add a label + GtkLabel* label = GTK_LABEL(gtk_label_new("[Example C FFI Module:")); + gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(label)); + + // Add a button + inst->button = GTK_BUTTON(gtk_button_new_with_label("click me !")); + g_signal_connect(inst->button, "clicked", G_CALLBACK(onclicked), NULL); + gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(inst->button)); + + // Add a label + label = GTK_LABEL(gtk_label_new("]")); + gtk_container_add(GTK_CONTAINER(inst->container), GTK_WIDGET(label)); + + // Return instance object + printf("cffi_example inst=%p: init success ! (%d total instances)\n", inst, ++instance_count); + return inst; +} + +void wbcffi_deinit(void* instance) { + printf("cffi_example inst=%p: free memory\n", instance); + free(instance); +} + +void wbcffi_update(void* instance) { printf("cffi_example inst=%p: Update request\n", instance); } + +void wbcffi_refresh(void* instance, int signal) { + printf("cffi_example inst=%p: Received refresh signal %d\n", instance, signal); +} + +void wbcffi_doaction(void* instance, const char* name) { + printf("cffi_example inst=%p: doAction(%s)\n", instance, name); +} diff --git a/modules/features/waybar/config/cffi_example/meson.build b/modules/features/waybar/config/cffi_example/meson.build new file mode 100644 index 0000000..dcde104 --- /dev/null +++ b/modules/features/waybar/config/cffi_example/meson.build @@ -0,0 +1,13 @@ +project( + 'waybar_cffi_example', 'c', + version: '0.1.0', + license: 'MIT', +) + +shared_library('wb_cffi_example', + ['main.c'], + dependencies: [ + dependency('gtk+-3.0', version : ['>=3.22.0']) + ], + name_prefix: '' +) diff --git a/modules/features/waybar/config/cffi_example/waybar_cffi_module.h b/modules/features/waybar/config/cffi_example/waybar_cffi_module.h new file mode 100644 index 0000000..c1a82f5 --- /dev/null +++ b/modules/features/waybar/config/cffi_example/waybar_cffi_module.h @@ -0,0 +1,95 @@ +#pragma once + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/// Waybar ABI version. 2 is the latest version +extern const size_t wbcffi_version; + +/// Private Waybar CFFI module +typedef struct wbcffi_module wbcffi_module; + +/// Waybar module information +typedef struct { + /// Waybar CFFI object pointer + wbcffi_module* obj; + + /// Waybar version string + const char* waybar_version; + + /// Returns the waybar widget allocated for this module + /// @param obj Waybar CFFI object pointer + GtkContainer* (*get_root_widget)(wbcffi_module* obj); + + /// Queues a request for calling wbcffi_update() on the next GTK main event + /// loop iteration + /// @param obj Waybar CFFI object pointer + void (*queue_update)(wbcffi_module*); +} wbcffi_init_info; + +/// Config key-value pair +typedef struct { + /// Entry key + const char* key; + /// Entry value + /// + /// In ABI version 1, this may be either a bare string if the value is a + /// string, or the JSON representation of any other JSON object as a string. + /// + /// From ABI version 2 onwards, this is always the JSON representation of the + /// value as a string. + const char* value; +} wbcffi_config_entry; + +/// Module init/new function, called on module instantiation +/// +/// MANDATORY CFFI function +/// +/// @param init_info Waybar module information +/// @param config_entries Flat representation of the module JSON config. The data only available +/// during wbcffi_init call. +/// @param config_entries_len Number of entries in `config_entries` +/// +/// @return A untyped pointer to module data, NULL if the module failed to load. +void* wbcffi_init(const wbcffi_init_info* init_info, const wbcffi_config_entry* config_entries, + size_t config_entries_len); + +/// Module deinit/delete function, called when Waybar is closed or when the module is removed +/// +/// MANDATORY CFFI function +/// +/// @param instance Module instance data (as returned by `wbcffi_init`) +void wbcffi_deinit(void* instance); + +/// Called from the GTK main event loop, to update the UI +/// +/// Optional CFFI function +/// +/// @param instance Module instance data (as returned by `wbcffi_init`) +/// @param action_name Action name +void wbcffi_update(void* instance); + +/// Called when Waybar receives a POSIX signal and forwards it to each module +/// +/// Optional CFFI function +/// +/// @param instance Module instance data (as returned by `wbcffi_init`) +/// @param signal Signal ID +void wbcffi_refresh(void* instance, int signal); + +/// Called on module action (see +/// https://github.com/Alexays/Waybar/wiki/Configuration#module-actions-config) +/// +/// Optional CFFI function +/// +/// @param instance Module instance data (as returned by `wbcffi_init`) +/// @param action_name Action name +void wbcffi_doaction(void* instance, const char* action_name); + +#ifdef __cplusplus +} +#endif diff --git a/modules/features/waybar/config/config.jsonc b/modules/features/waybar/config/config.jsonc new file mode 100644 index 0000000..f3b550c --- /dev/null +++ b/modules/features/waybar/config/config.jsonc @@ -0,0 +1,210 @@ +// -*- mode: jsonc -*- +{ + // "layer": "top", // Waybar at top layer + "position": "bottom", // Waybar position (top|bottom|left|right) + "height": 30, // Waybar height (to be removed for auto height) + // "width": 1280, // Waybar width + "spacing": 4, // Gaps between modules (4px) + // Choose the order of the modules + "modules-left": ["hyprland/workspaces", "hyprland/mode", "custom/media"], + "modules-center": ["sway/window"], + "modules-right": [ + "mpd", + "idle_inhibitor", + "pulseaudio", + "network", + "power-profiles-daemon", + "cpu", + "memory", + "temperature", + "backlight", + "keyboard-state", + "sway/language", + "battery", + "battery#bat2", + "clock", + "tray", + "custom/power", + ], + // Modules configuration + "hyprland/workspaces": { + "disable-scroll": true, + "all-outputs": true, + "warp-on-scroll": false, + "format": "{icon}", + "format-icons": { + "1": "", + "2": "󰈹", + "3": "", + "4": "", + "5": "󰎚", + "6": "6", + "7": "6", + "8": "6", + "9": "6", + "0": "10", + // "urgent": "", + // "active": "", + "default": "", + }, + }, + "keyboard-state": { + "numlock": true, + "capslock": true, + "format": "{name} {icon}", + "format-icons": { + "locked": "", + "unlocked": "", + }, + }, + "hyprland/mode": { + "format": "{}", + }, + "mpd": { + "format": "{stateIcon} {consumeIcon}{randomIcon}{repeatIcon}{singleIcon}{artist} - {album} - {title} ({elapsedTime:%M:%S}/{totalTime:%M:%S}) ⸨{songPosition}|{queueLength}⸩ {volume}% ", + "format-disconnected": "Disconnected ", + "format-stopped": "{consumeIcon}{randomIcon}{repeatIcon}{singleIcon}Stopped ", + "unknown-tag": "N/A", + "interval": 5, + "consume-icons": { + "on": " ", + }, + "random-icons": { + "off": " ", + "on": " ", + }, + "repeat-icons": { + "on": " ", + }, + "single-icons": { + "on": "1 ", + }, + "state-icons": { + "paused": "", + "playing": "", + }, + "tooltip-format": "MPD (connected)", + "tooltip-format-disconnected": "MPD (disconnected)", + }, + "idle_inhibitor": { + "format": "{icon}", + "format-icons": { + "activated": "", + "deactivated": "", + }, + }, + "tray": { + // "icon-size": 21, + "spacing": 10, + // "icons": { + // "blueman": "bluetooth", + // "TelegramDesktop": "$HOME/.local/share/icons/hicolor/16x16/apps/telegram.png" + // } + }, + "clock": { + "timezone": "America/Chicago", + "tooltip-format": "{:%Y %B}\n{calendar}", + "format-alt": "{:%Y-%m-%d}", + }, + "cpu": { + "format": "{usage}% ", + "tooltip": false, + }, + "memory": { + "format": "{}% ", + }, + "temperature": { + // "thermal-zone": 2, + // "hwmon-path": "/sys/class/hwmon/hwmon2/temp1_input", + "critical-threshold": 80, + // "format-critical": "{temperatureC}°C {icon}", + "format": "{temperatureC}°C {icon}", + "format-icons": ["", "", ""], + }, + "backlight": { + // "device": "acpi_video1", + "format": "{percent}% {icon}", + "format-icons": ["", "", "", "", "", "", "", "", ""], + }, + "battery": { + "states": { + // "good": 95, + "warning": 30, + "critical": 15, + }, + "format": "{capacity}% {icon}", + "format-full": "{capacity}% {icon}", + "format-charging": "{capacity}% ", + "format-plugged": "{capacity}% ", + "format-alt": "{time} {icon}", + // "format-good": "", // An empty format will hide the module + // "format-full": "", + "format-icons": ["", "", "", "", ""], + }, + "battery#bat2": { + "bat": "BAT2", + }, + "power-profiles-daemon": { + "format": "{icon}", + "tooltip-format": "Power profile: {profile}\nDriver: {driver}", + "tooltip": true, + "format-icons": { + "default": "", + "performance": "", + "balanced": "", + "power-saver": "", + }, + }, + "network": { + // "interface": "wlp2*", // (Optional) To force the use of this interface + "format-wifi": "{essid} ({signalStrength}%) ", + "format-ethernet": "{ipaddr}/{cidr} ", + "tooltip-format": "{ifname} via {gwaddr} ", + "format-linked": "{ifname} (No IP) ", + "format-disconnected": "Disconnected ⚠", + "format-alt": "{ifname}: {ipaddr}/{cidr}", + }, + "pulseaudio": { + // "scroll-step": 1, // %, can be a float + "format": "{volume}% {icon} {format_source}", + "format-bluetooth": "{volume}% {icon} {format_source}", + "format-bluetooth-muted": " {icon} {format_source}", + "format-muted": " {format_source}", + "format-source": "{volume}% ", + "format-source-muted": "", + "format-icons": { + "headphone": "", + "hands-free": "", + "headset": "", + "phone": "", + "portable": "", + "car": "", + "default": ["", "", ""], + }, + "on-click": "pavucontrol", + }, + "custom/media": { + "format": "{icon} {text}", + "return-type": "json", + "max-length": 40, + "format-icons": { + "spotify": "", + "default": "🎜", + }, + "escape": true, + "exec": "$HOME/.config/waybar/mediaplayer.py 2> /dev/null", // Script in resources folder + // "exec": "$HOME/.config/waybar/mediaplayer.py --player spotify 2> /dev/null" // Filter player based on name + }, + "custom/power": { + "format": "⏻ ", + "tooltip": false, + "menu": "on-click", + "menu-file": "$HOME/.config/waybar/power_menu.xml", // Menu file in resources folder + "menu-actions": { + "shutdown": "shutdown", + "reboot": "reboot", + "suspend": "systemctl suspend", + "hibernate": "systemctl hibernate", + }, + }, +} diff --git a/modules/features/waybar/config/icons/meson.build b/modules/features/waybar/config/icons/meson.build new file mode 100644 index 0000000..05532d3 --- /dev/null +++ b/modules/features/waybar/config/icons/meson.build @@ -0,0 +1,6 @@ +gnome = import('gnome') + +app_resources += gnome.compile_resources('icon-resources', + 'waybar_icons.gresource.xml', + c_name: 'waybar_icons' +) diff --git a/modules/features/waybar/config/icons/waybar-privacy-audio-input-symbolic.svg b/modules/features/waybar/config/icons/waybar-privacy-audio-input-symbolic.svg new file mode 100644 index 0000000..6135689 --- /dev/null +++ b/modules/features/waybar/config/icons/waybar-privacy-audio-input-symbolic.svg @@ -0,0 +1,4 @@ + + + + diff --git a/modules/features/waybar/config/icons/waybar-privacy-audio-output-symbolic.svg b/modules/features/waybar/config/icons/waybar-privacy-audio-output-symbolic.svg new file mode 100644 index 0000000..10ad4f9 --- /dev/null +++ b/modules/features/waybar/config/icons/waybar-privacy-audio-output-symbolic.svg @@ -0,0 +1,2 @@ + + diff --git a/modules/features/waybar/config/icons/waybar-privacy-screen-share-symbolic.svg b/modules/features/waybar/config/icons/waybar-privacy-screen-share-symbolic.svg new file mode 100644 index 0000000..9738c57 --- /dev/null +++ b/modules/features/waybar/config/icons/waybar-privacy-screen-share-symbolic.svg @@ -0,0 +1,7 @@ + + + + + + + diff --git a/modules/features/waybar/config/icons/waybar_icons.gresource.xml b/modules/features/waybar/config/icons/waybar_icons.gresource.xml new file mode 100644 index 0000000..077049b --- /dev/null +++ b/modules/features/waybar/config/icons/waybar_icons.gresource.xml @@ -0,0 +1,8 @@ + + + + waybar-privacy-audio-input-symbolic.svg + waybar-privacy-audio-output-symbolic.svg + waybar-privacy-screen-share-symbolic.svg + + diff --git a/modules/features/waybar/config/mediaplayer.py b/modules/features/waybar/config/mediaplayer.py new file mode 100755 index 0000000..524d4d2 --- /dev/null +++ b/modules/features/waybar/config/mediaplayer.py @@ -0,0 +1,196 @@ +#!/usr/bin/env python3 +import gi +gi.require_version("Playerctl", "2.0") +from gi.repository import Playerctl, GLib +from gi.repository.Playerctl import Player +import argparse +import logging +import sys +import signal +import gi +import json +import os +from typing import List + +logger = logging.getLogger(__name__) + +def signal_handler(sig, frame): + logger.info("Received signal to stop, exiting") + sys.stdout.write("\n") + sys.stdout.flush() + # loop.quit() + sys.exit(0) + + +class PlayerManager: + def __init__(self, selected_player=None, excluded_player=[]): + self.manager = Playerctl.PlayerManager() + self.loop = GLib.MainLoop() + self.manager.connect( + "name-appeared", lambda *args: self.on_player_appeared(*args)) + self.manager.connect( + "player-vanished", lambda *args: self.on_player_vanished(*args)) + + signal.signal(signal.SIGINT, signal_handler) + signal.signal(signal.SIGTERM, signal_handler) + signal.signal(signal.SIGPIPE, signal.SIG_DFL) + self.selected_player = selected_player + self.excluded_player = excluded_player.split(',') if excluded_player else [] + + self.init_players() + + def init_players(self): + for player in self.manager.props.player_names: + if player.name in self.excluded_player: + continue + if self.selected_player is not None and self.selected_player != player.name: + logger.debug(f"{player.name} is not the filtered player, skipping it") + continue + self.init_player(player) + + def run(self): + logger.info("Starting main loop") + self.loop.run() + + def init_player(self, player): + logger.info(f"Initialize new player: {player.name}") + player = Playerctl.Player.new_from_name(player) + player.connect("playback-status", + self.on_playback_status_changed, None) + player.connect("metadata", self.on_metadata_changed, None) + self.manager.manage_player(player) + self.on_metadata_changed(player, player.props.metadata) + + def get_players(self) -> List[Player]: + return self.manager.props.players + + def write_output(self, text, player): + logger.debug(f"Writing output: {text}") + + output = {"text": text, + "class": "custom-" + player.props.player_name, + "alt": player.props.player_name} + + sys.stdout.write(json.dumps(output) + "\n") + sys.stdout.flush() + + def clear_output(self): + sys.stdout.write("\n") + sys.stdout.flush() + + def on_playback_status_changed(self, player, status, _=None): + logger.debug(f"Playback status changed for player {player.props.player_name}: {status}") + self.on_metadata_changed(player, player.props.metadata) + + def get_first_playing_player(self): + players = self.get_players() + logger.debug(f"Getting first playing player from {len(players)} players") + if len(players) > 0: + # if any are playing, show the first one that is playing + # reverse order, so that the most recently added ones are preferred + for player in players[::-1]: + if player.props.status == "Playing": + return player + # if none are playing, show the first one + return players[0] + else: + logger.debug("No players found") + return None + + def show_most_important_player(self): + logger.debug("Showing most important player") + # show the currently playing player + # or else show the first paused player + # or else show nothing + current_player = self.get_first_playing_player() + if current_player is not None: + self.on_metadata_changed(current_player, current_player.props.metadata) + else: + self.clear_output() + + def on_metadata_changed(self, player, metadata, _=None): + logger.debug(f"Metadata changed for player {player.props.player_name}") + player_name = player.props.player_name + artist = player.get_artist() + artist = artist.replace("&", "&") + title = player.get_title() + title = title.replace("&", "&") + + track_info = "" + if player_name == "spotify" and "mpris:trackid" in metadata.keys() and ":ad:" in player.props.metadata["mpris:trackid"]: + track_info = "Advertisement" + elif artist is not None and title is not None: + track_info = f"{artist} - {title}" + else: + track_info = title + + if track_info: + if player.props.status == "Playing": + track_info = " " + track_info + else: + track_info = " " + track_info + # only print output if no other player is playing + current_playing = self.get_first_playing_player() + if current_playing is None or current_playing.props.player_name == player.props.player_name: + self.write_output(track_info, player) + else: + logger.debug(f"Other player {current_playing.props.player_name} is playing, skipping") + + def on_player_appeared(self, _, player): + logger.info(f"Player has appeared: {player.name}") + if player.name in self.excluded_player: + logger.debug( + "New player appeared, but it's in exclude player list, skipping") + return + if player is not None and (self.selected_player is None or player.name == self.selected_player): + self.init_player(player) + else: + logger.debug( + "New player appeared, but it's not the selected player, skipping") + + def on_player_vanished(self, _, player): + logger.info(f"Player {player.props.player_name} has vanished") + self.show_most_important_player() + +def parse_arguments(): + parser = argparse.ArgumentParser() + + # Increase verbosity with every occurrence of -v + parser.add_argument("-v", "--verbose", action="count", default=0) + + parser.add_argument("-x", "--exclude", "- Comma-separated list of excluded player") + + # Define for which player we"re listening + parser.add_argument("--player") + + parser.add_argument("--enable-logging", action="store_true") + + return parser.parse_args() + + +def main(): + arguments = parse_arguments() + + # Initialize logging + if arguments.enable_logging: + logfile = os.path.join(os.path.dirname( + os.path.realpath(__file__)), "media-player.log") + logging.basicConfig(filename=logfile, level=logging.DEBUG, + format="%(asctime)s %(name)s %(levelname)s:%(lineno)d %(message)s") + + # Logging is set by default to WARN and higher. + # With every occurrence of -v it's lowered by one + logger.setLevel(max((3 - arguments.verbose) * 10, 0)) + + logger.info("Creating player manager") + if arguments.player: + logger.info(f"Filtering for player: {arguments.player}") + if arguments.exclude: + logger.info(f"Exclude player {arguments.exclude}") + + player = PlayerManager(arguments.player, arguments.exclude) + player.run() + + +if __name__ == "__main__": + main() diff --git a/modules/features/waybar/config/power_menu.xml b/modules/features/waybar/config/power_menu.xml new file mode 100644 index 0000000..aa2a42c --- /dev/null +++ b/modules/features/waybar/config/power_menu.xml @@ -0,0 +1,28 @@ + + + + + + Suspend + + + + + Hibernate + + + + + Shutdown + + + + + + + + Reboot + + + + diff --git a/modules/features/waybar/config/style.css b/modules/features/waybar/config/style.css new file mode 100644 index 0000000..bcfcb5c --- /dev/null +++ b/modules/features/waybar/config/style.css @@ -0,0 +1,327 @@ +* { + /* `otf-font-awesome` is required to be installed for icons */ + font-family: FontAwesome, Roboto, Helvetica, Arial, sans-serif; + font-size: 13px; +} + +window#waybar { + background-color: rgba(43, 48, 59, 0.5); + border-bottom: 3px solid rgba(100, 114, 125, 0.5); + color: #ffffff; + transition-property: background-color; + transition-duration: .5s; +} + +window#waybar.hidden { + opacity: 0.2; +} + +/* +window#waybar.empty { + background-color: transparent; +} +window#waybar.solo { + background-color: #FFFFFF; +} +*/ + +window#waybar.termite { + background-color: #3F3F3F; +} + +window#waybar.chromium { + background-color: #000000; + border: none; +} + +button { + /* Use box-shadow instead of border so the text isn't offset */ + box-shadow: inset 0 -3px transparent; + /* Avoid rounded borders under each button name */ + border: none; + border-radius: 0; +} + +/* https://github.com/Alexays/Waybar/wiki/FAQ#the-workspace-buttons-have-a-strange-hover-effect */ +button:hover { + background: inherit; + box-shadow: inset 0 -3px #ffffff; +} + +/* you can set a style on hover for any module like this */ +#pulseaudio:hover { + background-color: #a37800; +} + +#workspaces button { + padding: 0 5px; + background-color: transparent; + color: #ffffff; +} + +#workspaces button:hover { + background: rgba(0, 0, 0, 0.2); +} + +#workspaces button.focused, #workspaces button.active { + background-color: #64727D; + box-shadow: inset 0 -3px #ffffff; +} + +#workspaces button.urgent { + background-color: #eb4d4b; +} + +#mode { + background-color: #64727D; + box-shadow: inset 0 -3px #ffffff; +} + +#clock, +#battery, +#cpu, +#memory, +#disk, +#temperature, +#backlight, +#network, +#pulseaudio, +#wireplumber, +#custom-media, +#tray, +#mode, +#idle_inhibitor, +#scratchpad, +#power-profiles-daemon, +#mpd { + padding: 0 10px; + color: #ffffff; +} + +#window, +#workspaces { + margin: 0 4px; +} + +/* If workspaces is the leftmost module, omit left margin */ +.modules-left > widget:first-child > #workspaces { + margin-left: 0; +} + +/* If workspaces is the rightmost module, omit right margin */ +.modules-right > widget:last-child > #workspaces { + margin-right: 0; +} + +#clock { + background-color: #64727D; +} + +#battery { + background-color: #ffffff; + color: #000000; +} + +#battery.charging, #battery.plugged { + color: #ffffff; + background-color: #26A65B; +} + +@keyframes blink { + to { + background-color: #ffffff; + color: #000000; + } +} + +/* Using steps() instead of linear as a timing function to limit cpu usage */ +#battery.critical:not(.charging) { + background-color: #f53c3c; + color: #ffffff; + animation-name: blink; + animation-duration: 0.5s; + animation-timing-function: steps(12); + animation-iteration-count: infinite; + animation-direction: alternate; +} + +#power-profiles-daemon { + padding-right: 15px; +} + +#power-profiles-daemon.performance { + background-color: #f53c3c; + color: #ffffff; +} + +#power-profiles-daemon.balanced { + background-color: #2980b9; + color: #ffffff; +} + +#power-profiles-daemon.power-saver { + background-color: #2ecc71; + color: #000000; +} + +label:focus { + background-color: #000000; +} + +#cpu { + background-color: #2ecc71; + color: #000000; +} + +#memory { + background-color: #9b59b6; +} + +#disk { + background-color: #964B00; +} + +#backlight { + background-color: #90b1b1; +} + +#network { + background-color: #2980b9; +} + +#network.disconnected { + background-color: #f53c3c; +} + +#pulseaudio { + background-color: #f1c40f; + color: #000000; +} + +#pulseaudio.muted { + background-color: #90b1b1; + color: #2a5c45; +} + +#wireplumber { + background-color: #fff0f5; + color: #000000; +} + +#wireplumber.muted { + background-color: #f53c3c; +} + +#custom-media { + background-color: #66cc99; + color: #2a5c45; + min-width: 100px; +} + +#custom-media.custom-spotify { + background-color: #66cc99; +} + +#custom-media.custom-vlc { + background-color: #ffa000; +} + +#temperature { + background-color: #f0932b; +} + +#temperature.critical { + background-color: #eb4d4b; +} + +#tray { + background-color: #2980b9; +} + +#tray > .passive { + -gtk-icon-effect: dim; +} + +#tray > .needs-attention { + -gtk-icon-effect: highlight; + background-color: #eb4d4b; +} + +#idle_inhibitor { + background-color: #2d3436; +} + +#idle_inhibitor.activated { + background-color: #ecf0f1; + color: #2d3436; +} + +#mpd { + background-color: #66cc99; + color: #2a5c45; +} + +#mpd.disconnected { + background-color: #f53c3c; +} + +#mpd.stopped { + background-color: #90b1b1; +} + +#mpd.paused { + background-color: #51a37a; +} + +#language { + background: #00b093; + color: #740864; + padding: 0 5px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state { + background: #97e1ad; + color: #000000; + padding: 0 0px; + margin: 0 5px; + min-width: 16px; +} + +#keyboard-state > label { + padding: 0 5px; +} + +#keyboard-state > label.locked { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad { + background: rgba(0, 0, 0, 0.2); +} + +#scratchpad.empty { + background-color: transparent; +} + +#privacy { + padding: 0; +} + +#privacy-item { + padding: 0 5px; + color: white; +} + +#privacy-item.screenshare { + background-color: #cf5700; +} + +#privacy-item.audio-in { + background-color: #1ca000; +} + +#privacy-item.audio-out { + background-color: #0069d4; +} diff --git a/modules/features/waybar/default.nix b/modules/features/waybar/default.nix new file mode 100644 index 0000000..da5e800 --- /dev/null +++ b/modules/features/waybar/default.nix @@ -0,0 +1,30 @@ +{ self, inputs, ... }: +{ + flake.nixosModules.waybar = + { + pkgs, + lib, + config, + ... + }: + { + config = { + environment.systemPackages = with pkgs; [ + waybar + ]; + + # Configure hjem for specified users + hjem = lib.mkIf (config.hyprland-users != [ ]) { + users = lib.genAttrs config.hyprland-users (username: { + enable = true; + files = { + ".config/waybar/".source = pkgs.runCommand "waybar" { } '' + mkdir -p $out + cp -r ${./config}/* $out/ + ''; + }; + }); + }; + }; + }; +} diff --git a/modules/hosts/desktop/configuration.nix b/modules/hosts/desktop/configuration.nix index be57c75..a3e7cf4 100644 --- a/modules/hosts/desktop/configuration.nix +++ b/modules/hosts/desktop/configuration.nix @@ -1,8 +1,9 @@ { self, inputs, ... }: { - flake.nixosModules.desktopConfiguration = {pkgs, lib, ... }: { - imports = - [ + flake.nixosModules.desktopConfiguration = + { pkgs, lib, ... }: + { + imports = [ self.nixosModules.base self.nixosModules.pipewire self.nixosModules.fonts @@ -15,66 +16,69 @@ self.nixosModules.user-jingus ]; - programs.firefox.enable = true; - programs.zsh.enable = true; + programs.firefox.enable = true; + programs.zsh.enable = true; - # Enable Gnome and GDM for login management and some decent default apps - services.displayManager.gdm.enable = true; - services.desktopManager.gnome.enable = true; + # Enable Gnome and GDM for login management and some decent default apps + services.displayManager.gdm.enable = true; + services.desktopManager.gnome.enable = true; - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # List packages installed in system profile. To search, run: - # $ nix search wget - environment.systemPackages = with pkgs; [ - vesktop - pavucontrol - keepassxc - amberol - ]; + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vesktop + pavucontrol + keepassxc + amberol + ]; - nix.settings.experimental-features = [ "nix-command" "flakes" ]; + nix.settings.experimental-features = [ + "nix-command" + "flakes" + ]; - services.xserver.videoDrivers = [ "amdgpu" ]; + services.xserver.videoDrivers = [ "amdgpu" ]; - hardware.graphics = { - enable = true; - enable32Bit = true; + hardware.graphics = { + enable = true; + enable32Bit = true; + }; + + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; + + # Use latest kernel. + boot.kernelPackages = pkgs.linuxPackages_latest; + + networking.hostName = "nixos"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + + # Enable networking + networking.networkmanager.enable = true; + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.11"; # Did you read the comment? }; - - # Bootloader. - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; - - # Use latest kernel. - boot.kernelPackages = pkgs.linuxPackages_latest; - - networking.hostName = "nixos"; # Define your hostname. - # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. - - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - - # Enable networking - networking.networkmanager.enable = true; - - # Enable the OpenSSH daemon. - # services.openssh.enable = true; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - # This value determines the NixOS release from which the default - # settings for stateful data, like file locations and database versions - # on your system were taken. It‘s perfectly fine and recommended to leave - # this value at the release version of the first install of this system. - # Before changing this value read the documentation for this option - # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). - system.stateVersion = "25.11"; # Did you read the comment? - }; } diff --git a/modules/hosts/desktop/default.nix b/modules/hosts/desktop/default.nix index 4953c07..e8357f4 100644 --- a/modules/hosts/desktop/default.nix +++ b/modules/hosts/desktop/default.nix @@ -1,4 +1,5 @@ -{ self, inputs, ... }: { +{ self, inputs, ... }: +{ flake.nixosConfigurations.desktop = inputs.nixpkgs.lib.nixosSystem { modules = [ self.nixosModules.desktopConfiguration diff --git a/modules/hosts/desktop/hardware-configuration.nix b/modules/hosts/desktop/hardware-configuration.nix index 531067e..0672fd3 100644 --- a/modules/hosts/desktop/hardware-configuration.nix +++ b/modules/hosts/desktop/hardware-configuration.nix @@ -1,30 +1,50 @@ -{ self, inputs, ... }: { - flake.nixosModules.desktopHardware = { config, lib, pkgs, modulesPath, nixpkgs, ... }: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") +{ self, inputs, ... }: +{ + flake.nixosModules.desktopHardware = + { + config, + lib, + pkgs, + modulesPath, + nixpkgs, + ... + }: + { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") ]; - - boot.initrd.availableKernelModules = [ "nvme" "ahci" "xhci_pci" "usbhid" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; - - fileSystems."/" = - { device = "/dev/disk/by-uuid/7001a8e1-003d-4119-afbb-5d6d25759e08"; + + boot.initrd.availableKernelModules = [ + "nvme" + "ahci" + "xhci_pci" + "usbhid" + "usb_storage" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/7001a8e1-003d-4119-afbb-5d6d25759e08"; fsType = "ext4"; }; - - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/5752-EAAD"; + + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/5752-EAAD"; fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; + options = [ + "fmask=0077" + "dmask=0077" + ]; }; - - swapDevices = - [ { device = "/dev/disk/by-uuid/e87cbcca-c7c6-4e03-90e7-5852ab59f0b9"; } + + swapDevices = [ + { device = "/dev/disk/by-uuid/e87cbcca-c7c6-4e03-90e7-5852ab59f0b9"; } ]; - - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - }; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + }; } diff --git a/modules/hosts/laptop/configuration.nix b/modules/hosts/laptop/configuration.nix index 0fd636e..9682764 100644 --- a/modules/hosts/laptop/configuration.nix +++ b/modules/hosts/laptop/configuration.nix @@ -1,8 +1,9 @@ { self, inputs, ... }: { - flake.nixosModules.laptopConfiguration = {pkgs, lib, ... }: { - imports = - [ + flake.nixosModules.laptopConfiguration = + { pkgs, lib, ... }: + { + imports = [ self.nixosModules.laptopHardware self.nixosModules.base self.nixosModules.fonts @@ -13,133 +14,155 @@ self.nixosModules.user-jingo ]; - # Bootloader. - boot.loader.systemd-boot.enable = true; - boot.loader.efi.canTouchEfiVariables = true; + # Bootloader. + boot.loader.systemd-boot.enable = true; + boot.loader.efi.canTouchEfiVariables = true; - # Use latest kernel. - boot.kernelPackages = pkgs.linuxPackages_latest; + # Use latest kernel. + boot.kernelPackages = pkgs.linuxPackages_latest; - networking.hostName = "nixos"; # Define your hostname. - # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. + networking.hostName = "nixos"; # Define your hostname. + # networking.wireless.enable = true; # Enables wireless support via wpa_supplicant. - # Configure network proxy if necessary - # networking.proxy.default = "http://user:password@proxy:port/"; - # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; + # Configure network proxy if necessary + # networking.proxy.default = "http://user:password@proxy:port/"; + # networking.proxy.noProxy = "127.0.0.1,localhost,internal.domain"; - # Enable networking - networking.networkmanager.enable = true; + # Enable networking + networking.networkmanager.enable = true; - # Configure keymap in X11 - services.xserver.xkb = { - layout = "us"; - variant = ""; - }; + # Configure keymap in X11 + services.xserver.xkb = { + layout = "us"; + variant = ""; + }; - # Define a user account. Don't forget to set a password with ‘passwd’. - users.users.jingo = { - isNormalUser = true; - description = "j"; - extraGroups = [ "networkmanager" "wheel" "docker" "dialout" ]; - packages = with pkgs; []; - shell = pkgs.zsh; - }; + # Define a user account. Don't forget to set a password with ‘passwd’. + users.users.jingo = { + isNormalUser = true; + description = "j"; + extraGroups = [ + "networkmanager" + "wheel" + "docker" + "dialout" + ]; + packages = with pkgs; [ ]; + shell = pkgs.zsh; + }; - # Allow unfree packages - nixpkgs.config.allowUnfree = true; + # Allow unfree packages + nixpkgs.config.allowUnfree = true; - # List packages installed in system profile. To search, run: - # $ nix search wget - environment.systemPackages = with pkgs; [ - vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. - wget - git - kitty - wofi - firefox - waybar - wl-clipboard - ripgrep - emacs-pgtk - zsh - zellij - zip - unzip - gnome-keyring - usbutils - dfu-util - libsecret - seahorse - ]; - - programs.zsh.enable = true; - - - # Some programs need SUID wrappers, can be configured further or are - # started in user sessions. - # programs.mtr.enable = true; - # programs.gnupg.agent = { - # enable = true; - # enableSSHSupport = true; - # }; - - virtualisation.docker.enable = true; - # enable emulation for ARM (for cross-compiling for RaspberryPi) - boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; - - # List services that you want to enable: - services.displayManager.ly = { - enable = true; - }; - programs.seahorse.enable = true; - services.gnome.gnome-keyring.enable = true; - services.dbus = { - enable = true; - packages = [ pkgs.gnome-keyring pkgs.gcr ]; - }; - # Define udev rules for DFU devices - services.udev.extraRules = '' - # Generic DFU rule (for meshtastic thingy) - SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0666", GROUP="dialout" - SUBSYSTEM=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666", GROUP="dialout" - ''; - - # Enable the OpenSSH daemon. - # services.openssh.enable = true; - - # Open ports in the firewall. - # networking.firewall.allowedTCPPorts = [ ... ]; - # networking.firewall.allowedUDPPorts = [ ... ]; - # Or disable the firewall altogether. - # networking.firewall.enable = false; - - security.pam.services.ly.enableGnomeKeyring = true; - - nix.settings = { - experimental-features = [ "nix-command" "flakes" ]; - substituters = [ - "https://cache.nixos.org/" - "https://cache.garnix.io" + # List packages installed in system profile. To search, run: + # $ nix search wget + environment.systemPackages = with pkgs; [ + vim # Do not forget to add an editor to edit configuration.nix! The Nano editor is also installed by default. + fastfetch + wget + git + kitty + wofi + firefox + waybar + wl-clipboard + ripgrep + emacs-pgtk + zsh + zellij + zip + unzip + gnome-keyring + usbutils + dfu-util + libsecret + seahorse + gnupg + gowall + gimp3 + chatterino7 + mumble + (element-desktop.override { + commandLineArgs = "--password-store=gnome-libsecret"; + }) + self.packages.${pkgs.stdenv.hostPlatform.system}.ralph ]; - trusted-public-keys = [ - # Default NixOS cache key - "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" - # Garnix cache key - "cache.garnix.io:Lf0liRJ2oT5zekG0arzGcHtrIfuVjGrAG1MxRCBuFlA=" + + programs.zsh.enable = true; + + # Some programs need SUID wrappers, can be configured further or are + # started in user sessions. + # programs.mtr.enable = true; + # programs.gnupg.agent = { + # enable = true; + # enableSSHSupport = true; + # }; + + virtualisation.docker.enable = true; + # enable emulation for ARM (for cross-compiling for RaspberryPi) + boot.binfmt.emulatedSystems = [ "aarch64-linux" ]; + + # List services that you want to enable: + services.displayManager.ly = { + enable = true; + }; + programs.seahorse.enable = true; + services.gnome.gnome-keyring.enable = true; + services.dbus = { + enable = true; + packages = [ + pkgs.gnome-keyring + pkgs.gcr + ]; + }; + # Define udev rules for DFU devices + services.udev.extraRules = '' + # Generic DFU rule (for meshtastic thingy) + SUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", ATTRS{idProduct}=="ea60", MODE="0666", GROUP="dialout" + SUBSYSTEM=="usb", ATTRS{idVendor}=="303a", ATTRS{idProduct}=="1001", MODE="0666", GROUP="dialout" + ''; + + # Enable the OpenSSH daemon. + # services.openssh.enable = true; + + # Open ports in the firewall. + # networking.firewall.allowedTCPPorts = [ ... ]; + # networking.firewall.allowedUDPPorts = [ ... ]; + # Or disable the firewall altogether. + # networking.firewall.enable = false; + + security.pam.services.ly.enableGnomeKeyring = true; + + nix.settings = { + experimental-features = [ + "nix-command" + "flakes" + ]; + substituters = [ + "https://cache.nixos.org/" + "https://cache.garnix.io" + ]; + trusted-public-keys = [ + # Default NixOS cache key + "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" + # Garnix cache key + "cache.garnix.io:Lf0liRJ2oT5zekG0arzGcHtrIfuVjGrAG1MxRCBuFlA=" + ]; + download-buffer-size = 524288000; + }; + + # This value determines the NixOS release from which the default + # settings for stateful data, like file locations and database versions + # on your system were taken. It‘s perfectly fine and recommended to leave + # this value at the release version of the first install of this system. + # Before changing this value read the documentation for this option + # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). + system.stateVersion = "25.05"; # Did you read the comment? + + swapDevices = [ + { + device = "/dev/disk/by-label/swap"; # Or "/dev/sda2" + } ]; - download-buffer-size = 524288000; }; - - # This value determines the NixOS release from which the default - # settings for stateful data, like file locations and database versions - # on your system were taken. It‘s perfectly fine and recommended to leave - # this value at the release version of the first install of this system. - # Before changing this value read the documentation for this option - # (e.g. man configuration.nix or on https://nixos.org/nixos/options.html). - system.stateVersion = "25.05"; # Did you read the comment? - - swapDevices = [ { - device = "/dev/disk/by-label/swap"; # Or "/dev/sda2" - } ]; - }; } diff --git a/modules/hosts/laptop/default.nix b/modules/hosts/laptop/default.nix index 71f2e53..46d11cf 100644 --- a/modules/hosts/laptop/default.nix +++ b/modules/hosts/laptop/default.nix @@ -1,4 +1,5 @@ -{ self, inputs, ... }: { +{ self, inputs, ... }: +{ flake.nixosConfigurations.laptop = inputs.nixpkgs.lib.nixosSystem { modules = [ self.nixosModules.laptopConfiguration diff --git a/modules/hosts/laptop/hardware-configuration.nix b/modules/hosts/laptop/hardware-configuration.nix index 0affd77..41a043b 100644 --- a/modules/hosts/laptop/hardware-configuration.nix +++ b/modules/hosts/laptop/hardware-configuration.nix @@ -1,37 +1,56 @@ -{ self, inputs, ... }: { - flake.nixosModules.laptopHardware = { config, lib, pkgs, modulesPath, nixpkgs, ... }: { - imports = - [ (modulesPath + "/installer/scan/not-detected.nix") +{ self, inputs, ... }: +{ + flake.nixosModules.laptopHardware = + { + config, + lib, + pkgs, + modulesPath, + nixpkgs, + ... + }: + { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "sd_mod" ]; - boot.initrd.kernelModules = [ ]; - boot.kernelModules = [ "kvm-amd" ]; - boot.extraModulePackages = [ ]; + boot.initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "usb_storage" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.extraModulePackages = [ ]; - fileSystems."/" = - { device = "/dev/disk/by-uuid/78d511b1-8932-4af7-b74d-8194aeef0903"; + fileSystems."/" = { + device = "/dev/disk/by-uuid/78d511b1-8932-4af7-b74d-8194aeef0903"; fsType = "ext4"; }; - fileSystems."/boot" = - { device = "/dev/disk/by-uuid/776B-1FD9"; + fileSystems."/boot" = { + device = "/dev/disk/by-uuid/776B-1FD9"; fsType = "vfat"; - options = [ "fmask=0077" "dmask=0077" ]; + options = [ + "fmask=0077" + "dmask=0077" + ]; }; - swapDevices = - [ { device = "/dev/disk/by-uuid/a0077d83-9d7b-4ecd-b60b-2de46562d841"; } + swapDevices = [ + { device = "/dev/disk/by-uuid/a0077d83-9d7b-4ecd-b60b-2de46562d841"; } ]; - # Enables DHCP on each ethernet and wireless interface. In case of scripted networking - # (the default) this is the recommended approach. When using systemd-networkd it's - # still possible to use this option, but it's recommended to use it in conjunction - # with explicit per-interface declarations with `networking.interfaces..useDHCP`. - networking.useDHCP = lib.mkDefault true; - # networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true; + # Enables DHCP on each ethernet and wireless interface. In case of scripted networking + # (the default) this is the recommended approach. When using systemd-networkd it's + # still possible to use this option, but it's recommended to use it in conjunction + # with explicit per-interface declarations with `networking.interfaces..useDHCP`. + networking.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp1s0.useDHCP = lib.mkDefault true; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; - }; + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + }; }