#+title: Droidnix: A Dendritic NixOS + Home Manager Configuration #+author: Henro Veijer #+options: toc:t num:nil htmlize:nil #+language: en #+html_head: #+HTML_HEAD: #+HTML_HEAD: * Shortcuts [[#introduction][Introduction]] [[#the-assets-folder][The Assets Folder]] [[#the-actual-code][The Actual Code]] --- * Introduction :intro: :PROPERTIES: :CUSTOM_ID: introduction :END: ** What is Droidnix Droidnix is a modular, declarative NixOS + Home Manager configuration system. It allows users to choose between =Hyprland= and =Mangowc= as their window manager, with shared and WM-specific configurations managed via Emacs Org and Nix Flakes. The project is designed for reproducibility, maintainability, and cross-machine compatibility. *** Installed components: **** Core **** Hyprland **** Mangowc *** Goals, project Structure, import hierarchy This project uses a **modular NixOS configuration** with **Hyprland** and **MangoWC** support, designed for **literate programming** and **cross-device reusability**. The Droidnix repository is organized into two main parts: 1. =.assets/=: Static, non-generated files (e.g., configs, scripts, themes). 2. Generated folders (=system=, =hyprland=, =mangowc=): NixOS and Home Manager configurations, generated from Org files. #+title: NixOS Configuration Structure * Root Level - =flake.nix= is the entry point and imports: - =generated/system/= - =generated/hyprland/= - Machine-specific configurations from =assets/machines/= * Generated Structure The =generated/= directory contains all generated configurations, divided into three main groups: =system=, =hyprland=, and =mangowc=. ** System (=generated/system/=) This directory contains system-wide configurations that are independent of the window manager. *** Applications (=applications/=) - =file_management/=: Configurations for file managers and storage solutions. - =gaming/=: Settings for gaming-related software. - =office_productivity/=: Configurations for office software. - =media_playback_editing/=: Settings for media playback and editing software. - =terminal_shell/=: Configurations for terminal emulators and shells. *** Development (=development/=) - =databases/=: Settings for local databases. - =devops_ci_cd/=: Configurations for DevOps tools. - =programming_languages/=: Settings for programming languages and their runtimes. - =virtualization/=: Configurations for virtualization and containerization tools. - =web_development/=: Settings for web development. *** System Management (=system_management/=) - =backups/=: Settings for backup software. - =bluetooth/=: Configurations for Bluetooth devices and services. - =power_management/=: Settings for power management. - =audio/=: Configurations for audio. - =hardware_sensors/=: Settings for hardware monitoring. - =logging_monitoring/=: Configurations for system logging and monitoring. - =login_manager/=: Settings for the login manager. - =monitor_setup/=: Configurations for display settings. - =networking/=: Settings for networking. - =printers_scanners/=: Configurations for printers and scanners. - =disk_management/=: Settings for disk management. - =security/=: Security-related configurations. - =system_updates/=: Settings for system updates and package management. ** Hyprland (=generated/hyprland/=) This directory contains configurations specific to Hyprland. - =animations_effects/=: Settings for window animations and visual effects. - =decorations/=: Configurations for window decorations. - =keyboard_binds/=: Keyboard shortcuts for Hyprland. - =notifications/=: Settings for notifications. - =statusbar_tray/=: Configurations for the status bar and system tray. - =task_launcher/=: Settings for task launchers. - =task_window_workspace_switcher/=: Configurations for switching between windows and workspaces. - =window_rules/=: Rules for window behavior. #+BEGIN_EXAMPLE <> #+END_EXAMPLE ** First Setup 1. Clone this repository. 2. Run the setup script: =./setup_droid=. 3. Edit =.assets/system/conf/base.conf= to choose your window manager (=wm = "hyprland"= or =wm = "mangowc"=). 4. Tangle this Org file to generate Nix configurations: =C-c C-v t= in Emacs or use this: =emacs README.org --batch -f org-babel-tangle && emacs --batch --eval "(setq org-html-htmlize-output-type nil)" README.org -f org-html-export-to-html= 5. Build and switch: =sudo nixos-rebuild switch --flake .#=. --- * The Assets Folder :assets: :PROPERTIES: :CUSTOM_ID: the-assets-folder :END: The =.assets/= folder contains all static files, such as configs, scripts, and themes. These files are not generated and can be edited directly. ** =.assets/system/= This folder contains files shared across both window managers, such as wallpapers, shell configs, and system scripts. - =conf/base.conf=: Defines the window manager choice and other global settings. - =scripts/=: System-wide scripts (e.g., utilities, helpers). ** =.assets/hyprland/= Hyprland-specific assets, including configs, themes, and scripts. - =conf/=: Hyprland configuration files (e.g., =hyprland.conf=). - =themes/=: Hyprland-specific theme scripts. - =scripts/=: Hyprland-specific scripts. ** =.assets/mangowc/= Mangowc-specific assets, including configs, themes, and scripts. - =conf/=: Mangowc configuration files. - =themes/=: Mangowc-specific theme scripts. - =scripts/=: Mangowc-specific scripts. ** =.assets/machines/= Machine-specific NixOS configurations (e.g., =configuration.nix= for =maindroid= and =traveldroid=). --- * The Actual Code :code: :PROPERTIES: :CUSTOM_ID: the-actual-code :END: This section contains the Org blocks for tangling Nix code into the generated folders. ** =flake.nix= The Nix flake definition for Droidnix. #+BEGIN_SRC nix :tangle flake.nix :noweb tangle :mkdirp yes :eval never-html { description = "Droidnix: A dendritic NixOS + Home Manager configuration"; inputs = { nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; home-manager = { url = "github:nix-community/home-manager"; inputs.nixpkgs.follows = "nixpkgs"; }; catppuccin = { url = "github:catppuccin/nix"; inputs.nixpkgs.follows = "nixpkgs"; }; stylix = { url = "github:nix-community/stylix"; inputs.nixpkgs.follows = "nixpkgs"; }; emacs-overlay = { url = "github:nix-community/emacs-overlay"; inputs.nixpkgs.follows = "nixpkgs"; }; zen-browser = { url = "github:youwen5/zen-browser-flake"; inputs.nixpkgs.follows = "nixpkgs"; }; hyprland.url = "github:hyprwm/Hyprland"; }; outputs = inputs@{ self, nixpkgs, home-manager, emacs-overlay, catppuccin, zen-browser, hyprland, stylix, ... }: let lib = nixpkgs.lib; system = "x86_64-linux"; user = import ./generated/out_of_tree/users/henrov.nix; machines = [ "traveldroid" "maindroid" ]; flakeRoot = ./.; # Define flakeRoot here in { nixosConfigurations = lib.genAttrs machines ( machine: lib.nixosSystem { inherit system; modules = [ # Import machine-specific configurations ./generated/out_of_tree/machines/traveldroid/top.nix # Anchoring all the other nixes ./generated/top.nix # Home Manager module inputs.home-manager.nixosModules.home-manager { home-manager.useGlobalPkgs = true; home-manager.useUserPackages = true; home-manager.extraSpecialArgs = { inherit user inputs flakeRoot; }; } ]; specialArgs = { inherit user inputs flakeRoot; }; } ); homeConfigurations = lib.genAttrs (map (machine: "${user.username}@${machine}") machines) ( userMachine: home-manager.lib.homeManagerConfiguration { inherit system; configuration = import ./user.nix { inherit inputs user flakeRoot; }; extraSpecialArgs = { inherit user inputs flakeRoot; }; } ); devShells.${system}.default = import ./generated/out_of_tree/terminal_shell/devshell.nix { inherit (nixpkgs.legacyPackages.${system}) mkShell; }; }; } #+END_SRC * First the nix-files that flake really needs and that do not fit wel in the hierarchical structure ** =generated/out_of_tree/users/top.nix= The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure. #+BEGIN_SRC nix :tangle generated/out_of_tree/users/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: { imports = [ ./user.nix ]; } #+END_SRC ** =generated/out_of_tree/users/user.nix= This is the default user, just search and replace henrov another name if you want to change #+BEGIN_SRC nix :tangle generated/out_of_tree/users/user.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, inputs, ... }: let user = import ./henrov.nix; in { home-manager.users.${user.username} = { home.stateVersion = "25.11"; home.username = user.username; home.homeDirectory = user.homeDirectory; home.packages = with pkgs; [ direnv git-extras ]; }; # Ensure the user is in the necessary groups users.users.${config.users.users.${user.username}.username} = { extraGroups = [ "networkmanager" ]; } #+END_SRC ** =generated/out_of_tree/users/henrov.nix= This is the default user, just search and replace henrov another name if you want to change #+BEGIN_SRC nix :tangle generated/out_of_tree/users/henrov.nix :noweb tangle :mkdirp yes :eval never-html { username = "henrov"; hashedPassword = "$6$ISAmsPLyFi7idYXr$VmZsq.zMsyh1irSkyDNqtorNXG0oEHbbMVqTii1t8bymvrQ5ZQmbdi4OiBNeNYe/huHGrojXM.3TST2fTLz0T."; homeDirectory = "/home/henrov"; stateVersion = "25.11"; locale = "nl_NL.UTF-8"; } #+END_SRC ** =generated/out_of_tree/terminal_shell/top.nix= This code defines a Nix shell environment (also called a "devShell") that you can enter using the nix develop command. When you enter this shell, Nix will provide the tools and dependencies listed in buildInputs. #+BEGIN_SRC nix :tangle generated/out_of_tree/terminal_shell/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot, ... }: { imports = [ ./devshell.nix inputs.home-manager.nixosModules.home-manager ]; } #+END_SRC ** =generated/out_of_tree/terminal_shell/devshell.nix= This code defines a Nix shell environment (also called a "devShell") that you can enter using the nix develop command. When you enter this shell, Nix will provide the tools and dependencies listed in buildInputs. #+BEGIN_SRC nix :tangle generated/out_of_tree/terminal_shell/devshell.nix :noweb tangle :mkdirp yes :eval never-html { mkShell, ... }: mkShell { buildInputs = with import {}; [ nil nixfmt-rfc-style ]; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/top.nix= This is the top of the machine hierarchy #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot, ... }: { imports = [ ./../../core/nix.nix ./../../core/stylix.nix ./../../core/gtk.nix ./../../core/terminal.nix ./boot.nix ./hardware-configuration.nix ./machine.nix ./dbus.nix ./audio.nix ./xdg.nix ./networking.nix inputs.home-manager.nixosModules.home-manager ]; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/hardware-configuration.nix= 1. Boot into NixOS Live ISO or your installed system. 2. Open a terminal. 3. Run: sudo nixos-generate-config --root /mnt (Omit --root /mnt if already running NixOS.) #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/hardware-configuration.nix :noweb tangle :mkdirp yes :eval never-html { hostname, pkgs, lib, modulesPath, user, config, ... }: { imports = [ # (modulesPath + "/installer/scan/not-detected.nix") #../../hardware/hardware.nix ]; boot.initrd.availableKernelModules = [ "xhci_pci" "nvme" "usb_storage" "sd_mod" "rtsx_usb_sdmmc" ]; boot.initrd.kernelModules = [ ]; boot.kernelModules = [ "kvm-intel" ]; boot.extraModulePackages = [ ]; fileSystems."/" = { device = "/dev/disk/by-uuid/69433a14-fbaf-401b-af85-cd1bbf02b4e2"; fsType = "ext4"; }; fileSystems."/boot" = { device = "/dev/disk/by-uuid/811D-0676"; fsType = "vfat"; options = [ "fmask=0077" "dmask=0077" ]; }; swapDevices = [ { device = "/dev/disk/by-uuid/b6c557c2-7682-460b-a5e7-8f6f2f429a3a"; } ]; nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/boot.nix= This file has most of the settings the control how the computer boots up. #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/boot.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, ... } : { boot = { initrd = { verbose = false; # its a lot of logs. dont need it, unless we do. kernelModules = [ ]; # no kernel modules on boot }; extraModulePackages = [ ]; # no extra packages on boot either kernelPackages = pkgs.linuxPackages_latest; # latest greatest linux kernel kernelParams = [ "silent" ]; # quiet those logs consoleLogLevel = 0; # quiten more logs plymouth.enable = true; # graphical boot animation instead supportedFilesystems = [ "ntfs" ]; # should see the ntfs (windows) loader = { systemd-boot.enable = true; # systemd-boot systemd-boot.configurationLimit = 10; efi.canTouchEfiVariables = true; # allow editing efi to edit the boot loader timeout = 5; # grub timeout to make a selection }; }; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/machine.nix= This is the top if the machine hierarchy #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/machine.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot, ... }: { options = { wm = lib.mkOption { type = lib.types.str; default = "hyprland"; description = "Type of window manager to use"; }; }; config = { # Minimal settings that must be defined here networking.hostName = "traveldroid"; wm.type = "hyprland"; # User configuration users.users.${user.username} = { isNormalUser = true; extraGroups = [ "wheel" "networkmanager" ]; hashedPassword = user.hashedPassword; home = user.homeDirectory; }; # Optional: Enable auto-login for testing #services.getty.autologinUser = user.username; }; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/dbus.nix= This sets the dbus implementation #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/dbus.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: { services.dbus = lib.mkForce { enable = true; # Force this to be true }; # Configure dbus-broker via its configuration file environment.etc."dbus-broker/launch.conf".text = '' [General] LogLevel=warning MaxConnectionsPerUser=2048 ''; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/networking.nix= This sets the networking. #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/networking.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: { networking = { useDHCP = lib.mkDefault true; networkmanager.enable = true; networkmanager.wifi.backend = "iwd"; wireless.iwd.enable = true; wireless.userControlled.enable = true; firewall = { enable = true; # KDE Connect: discovery + encrypted connections allowedTCPPortRanges = [ { from = 1714; to = 1764; } ]; allowedUDPPortRanges = [ { from = 1714; to = 1764; } ]; }; }; # Install NetworkManager and wofi environment.systemPackages = with pkgs; [ networkmanager wofi ]; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/bluetooth.nix= This sets the bluetooth implementation #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/bluetooth.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { # Enable Bluetooth hardware and daemon hardware.bluetooth = { enable = true; powerOnBoot = true; packages = with pkgs; [ bluez ]; }; # Enable Bluetooth audio support in PipeWire services.pipewire = { config.pulse = { bluez5.enable = true; }; }; # Optional: Additional Bluetooth settings hardware.bluetooth.extraConfig = '' AutoEnable=true DiscoverableTimeout=0 PairableTimeout=0 ''; # Install a graphical Bluetooth manager (optional) environment.systemPackages = with pkgs; [ blueman ]; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/audio.nix= This sets audiosystem for this machine #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/audio.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { services.pipewire = { enable = true; alsa.enable = true; # ALSA compatibility pulse.enable = true; # PulseAudio compatibility wireplumber.enable = true; # Session manager for PipeWire }; # Realtime privileges for pro audio (optional) security.rtkit.enable = true; } #+END_SRC ** =generated/out_of_tree/machines/traveldroid/xdg.nix= This sets the XDG implementation #+BEGIN_SRC nix :tangle generated/out_of_tree/machines/traveldroid/xdg.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { xdg.portal = { enable = true; config.system.default = [ "hyprland" "gtk" ]; }; } #+END_SRC ** =generated/out_of_tree/core/stylix.nix= This sets the stylix implementation #+BEGIN_SRC nix :tangle generated/out_of_tree/core/stylix.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, inputs, flakeRoot, ... }: let _ = builtins.trace ("Stylix enable = " + toString config.stylix.enable) null; in { imports = [ inputs.stylix.nixosModules.stylix ]; environment.systemPackages = with pkgs; [ feh # wallpaper target #gtk3 # GTK target # gtk4 # GTK target st # NVF / terminal target, or kitty ]; stylix = { enable = true; base16Scheme = "${flakeRoot}/assets/system/theming/stylix/catppuccin-mocha.yaml"; polarity = "dark"; }; } #+END_SRC ** =generated/out_of_tree/core/gtk.nix= Sets theming for GTK #+BEGIN_SRC nix :tangle generated/out_of_tree/core/gtk.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { environment.systemPackages = with pkgs; [ # feh # wallpaper target gtk3 # GTK target gtk4 # GTK target #st # NVF / terminal target, or kitty ]; # Stylix GTK target stylix.targets.gtk.enable = true; } #+END_SRC ** =generated/out_of_tree/core/terminal.nix= Sets theming for the terminal #+BEGIN_SRC nix :tangle generated/out_of_tree/core/terminal.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { # (NVF = Neovim/terminal flavor) stylix.targets.nvf.enable = true; # feh wallpaper integration stylix.targets.feh.enable = true; } #+END_SRC ** =generated/out_of_tree/core/nix.nix= I use the [[https://catppuccin.com/][Catppuccin]] almost everywhere. The nix module integrates almost automatically everywhere (except gtk). You'll notice the color values in multiple places outside this as well. #+BEGIN_SRC nix :tangle generated/out_of_tree/core/nix.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { nix.settings = { extra-experimental-features = [ "nix-command" "flakes" ]; }; } #+END_SRC * Now we reach the top of the hierarchy which will call all other imports ** =generated/top.nix= The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure. #+BEGIN_SRC nix :tangle generated/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: { imports = [ ./system/top.nix ./hyprland/top.nix # ./mangowc/top.nix ]; } #+END_SRC This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./hyprland.nix ./animations_effects/top.nix ./decorations/top.nix ./notifications/top.nix ./statusbar_tray/top.nix ./task_window_workspace_switcher/top.nix ./window_rules/top.nix ]; } #+END_SRC ** =generated/hyprland/hyprland.nix= The ./generated/top.nix file acts as an anchor or entry point for the entire chain of imports in the pyramid structure. #+BEGIN_SRC nix :tangle generated/hyprland/hyprland.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, flakeRoot, ... }: let hyprlandFiles = builtins.attrNames (builtins.readDir "${flakeRoot}/assets/hyprland/conf/hypr"); # Filter out hyprland.conf from the list of files to symlink otherHyprlandFiles = lib.filter (name: name != "hyprland.conf") hyprlandFiles; # Generate xdg.configFile entries for all files except hyprland.conf otherConfigs = lib.genAttrs otherHyprlandFiles (name: { target = "hypr/${name}"; source = "${flakeRoot}/assets/hyprland/conf/hypr/${name}"; }); in { programs.hyprland = { enable = true; }; home-manager.users.${user.username} = { home.stateVersion = "25.11"; home.username = user.username; home.homeDirectory = config.home-manager.users.${user.username}.homeDirectory or "/home/${user.username}"; wayland.windowManager.hyprland = { enable = true; settings.general."col.active_border" = lib.mkForce "0xff97cbcd 0xff89b4fa"; }; xdg.configFile = otherConfigs // { "hypr/hyprland.conf".text = '' ${builtins.readFile "${flakeRoot}/assets/hyprland/conf/hypr/hyprland.conf"} ''; "hypr/.keep".text = ""; }; }; } #+END_SRC ** =generated/hyprland/animations_effects/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/animations_effects/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/hyprland/decorations/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/decorations/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/hyprland/notifications/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/notifications/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/hyprland/statusbar_tray/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/statusbar_tray/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/hyprland/task_window_workspace_switcher/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/task_window_workspace_switcher/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/hyprland/window_rules/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/hyprland/window_rules/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./applications/top.nix ./core/top.nix ./development/top.nix ./system_management/top.nix ]; # .. put any code here } #+END_SRC ** =generated/system/applications/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./packages.nix ./flatpaks.nix ./accessibility/top.nix ./browsing/top.nix ./file_management/top.nix ./gaming/top.nix ./media_playback_editing/top.nix ./office_productivity/top.nix ./terminal_shell/top.nix ]; nixpkgs.config.allowUnfree = true; } #+END_SRC ** =generated/system/applications/browsing/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/browsing/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./zen-browser.nix # ./firefox.nix # ./vivaldi.nix ]; } #+END_SRC ** =generated/system/applications/browsing/zen-browser.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/browsing/zen-browser.nix :noweb tangle :mkdirp yes :eval never-html { config, lib, pkgs, flakeRoot, inputs, ... }: let zenBrowser = inputs.zen-browser.packages.${pkgs.stdenv.hostPlatform.system}.default; in { environment.systemPackages = [zenBrowser]; } #+END_SRC ** =generated/system/applications/packages.nix= This will import all packages listed in ./assets/system/apps/packlages.conf #+BEGIN_SRC nix :tangle generated/system/applications/packages.nix :noweb tangle :mkdirp yes :eval never-html { config, lib, pkgs, flakeRoot, inputs, ... }: let packagesConfPath = "${flakeRoot}/assets/system/apps/packages.conf"; raw = builtins.readFile packagesConfPath; # IMPORTANT: explicit "\n" so we never accidentally split into characters rawLines = lib.splitString "\n" raw; # Guard: if we accidentally split into characters, rawLines length ~= stringLength raw _guard = assert !( builtins.stringLength raw > 1 && builtins.length rawLines == builtins.stringLength raw ); true; cleanLine = l: let noCR = lib.replaceStrings [ "\r" ] [ "" ] l; noInlineComment = lib.head (lib.splitString "#" noCR); in lib.strings.trim noInlineComment; entries = builtins.filter (l: l != "") (map cleanLine rawLines); resolvePkg = name: let parts = lib.splitString "." name; found = lib.attrByPath parts null pkgs; in if found == null then throw '' packages.nix: package not found in pkgs Token : ${builtins.toJSON name} packages.conf : ${toString packagesConfPath} Hint : check the attribute name on search.nixos.org/packages '' else found; packages = builtins.seq _guard (map resolvePkg entries); in { environment.systemPackages = packages; } #+END_SRC ** =generated/system/applications/flatpaks.nix= This will import all packages listed in ./assets/system/apps/flatpaks.conf #+BEGIN_SRC nix :tangle generated/system/applications/flatpaks.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, flakeRoot, ... }: let moduleName = "install-flatpaks"; flatpakConfPath = "${flakeRoot}/assets/system/apps/flatpaks.conf"; raw = builtins.readFile flatpakConfPath; # Explicit "\n" so we never accidentally split into characters rawLines = lib.splitString "\n" raw; # Guard: if we accidentally split into characters, rawLines length ~= stringLength raw _guard = assert !(builtins.stringLength raw > 1 && builtins.length rawLines == builtins.stringLength raw); true; cleanLine = l: let noCR = lib.replaceStrings [ "\r" ] [ "" ] l; noInlineComment = lib.head (lib.splitString "#" noCR); in lib.strings.trim noInlineComment; entries = builtins.filter (l: l != "") (map cleanLine rawLines); # Flatpak app IDs are reverse-DNS style like org.example.App (at least 2 dots). # We'll validate and fail early with a clear message. dotCount = s: builtins.length (lib.splitString "." s) - 1; isValidId = s: (dotCount s) >= 2; # matches the error you're seeing: "at least 2 periods" _validate = builtins.seq _guard ( builtins.map ( id: if isValidId id then true else throw '' ${moduleName}: invalid Flatpak ID in flatpaks.conf (needs reverse-DNS with at least 2 dots) Token : ${builtins.toJSON id} flatpaks.conf : ${toString flatpakConfPath} Fix: remove stray tokens/headers, or comment them out with '#'. '' ) entries ); # Use validated entries flatpakApps = builtins.seq _validate entries; syncFlatpaks = pkgs.writeShellScript "sync-flatpaks" '' set -euo pipefail # Use the deployed config path (matches environment.etc below) CONF="/etc/flatpak/flatpaks.conf" if [[ -f "$CONF" ]]; then echo "flatpak-sync: using $CONF" else echo "flatpak-sync: WARNING: $CONF not found, using embedded list" fi if ! flatpak remotes --system --columns=name | grep -qx flathub; then flatpak remote-add --system --if-not-exists flathub https://dl.flathub.org/repo/flathub.flatpakrepo fi desired_apps=( ${lib.concatStringsSep "\n" (map (a: ''"${a}"'') flatpakApps)} ) for app in "''${desired_apps[@]}"; do if ! flatpak info --system "$app" >/dev/null 2>&1; then flatpak install --system -y --noninteractive flathub "$app" fi done ''; in { services.flatpak.enable = true; xdg.portal = { enable = true; }; # Deploy the config file for runtime visibility/debugging environment.etc."flatpak/flatpaks.conf".source = lib.mkForce flatpakConfPath; systemd.services.flatpak-sync = { description = "Install Flatpak apps listed in flatpaks.conf"; wantedBy = [ "multi-user.target" ]; wants = [ "network-online.target" ]; after = [ "network-online.target" ]; serviceConfig = { Type = "oneshot"; ExecStart = syncFlatpaks; }; restartTriggers = [ flatpakConfPath ]; path = [ pkgs.flatpak pkgs.coreutils pkgs.gnugrep pkgs.gnused ]; }; } #+END_SRC ** =generated/system/core/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/core/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./wayland.nix #./eww.nix ./waybar.nix ./login-tuigreeter.nix #./login-lightdm.nix ./fonts.nix ]; } #+END_SRC ** =generated/system/core/gtk.nix= Sewtting up GTK #+BEGIN_SRC nix :tangle generated/system/core/gtk.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, user, ... }: { home-manager.users.${user.username} = { gtk = { enable = true; theme = { name = "Catppuccin-Mocha-Standard-Blue-Dark"; package = pkgs.magnetic-catppuccin-gtk; }; iconTheme = { name = "Papirus-Dark"; package = pkgs.papirus-icon-theme; }; gtk3.extraConfig = { gtk-application-prefer-dark-theme = 1; }; gtk4.extraConfig = { gtk-application-prefer-dark-theme = 1; }; }; }; } #+END_SRC ** =generated/system/core/fonts.nix= This file installs and configures fonts #+BEGIN_SRC nix :tangle generated/system/core/fonts.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, ... }: { fonts.packages = with pkgs; [ pkgs.nerd-fonts.iosevka ]; } #+END_SRC ** =generated/system/core/eww.nix= This file installs and configures eww #+BEGIN_SRC nix :tangle generated/system/core/eww.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs, flakeRoot, user, ... }: let ewwConfigDir = "${config.home-manager.users.${user.username}.xdg.configHome}/eww"; # Dynamically read all files in assets/system/conf/eww/ ewwConfs = lib.genAttrs (builtins.attrNames (builtins.readDir "${flakeRoot}/assets/system/conf/eww")) (name: { text = builtins.readFile "${flakeRoot}/assets/system/conf/eww/${name}"; }); in { environment.systemPackages = with pkgs; [ eww ]; home-manager.users.${user.username} = { home.file = { "${ewwConfigDir}" = { source = "${flakeRoot}/assets/system/conf/eww"; recursive = true; }; }; home.sessionVariables = { EWW_BIN = "${pkgs.eww}/bin/eww"; }; # Start eww with Hyprland/MangoWC wayland.windowManager.hyprland.settings = lib.mkForce { exec-once = [ "eww daemon" ]; exec = [ "eww open-many ${ewwConfigDir}/widgets" ]; # Adjust as needed }; }; } #+END_SRC ** =generated/system/core/waybar.nix= This file installs and configures waybar #+BEGIN_SRC nix :tangle generated/system/core/waybar.nix :noweb tangle :mkdirp yes :eval never-html { lib, pkgs, config, flakeRoot, ... }: let username = "henrov"; waybar-config = pkgs.writeText "waybar-config" (builtins.readFile (flakeRoot + "/assets/system/conf/waybar/config")); waybar-style = pkgs.writeText "waybar-style" (builtins.readFile (flakeRoot + "/assets/system/conf/waybar/style.css")); in { programs.waybar = { enable = true; package = pkgs.waybar; }; systemd.user.services.waybar = { description = "Waybar (status bar for Wayland)"; wantedBy = [ "graphical-session.target" ]; after = [ "graphical-session.target" ]; serviceConfig = { Type = "simple"; ExecStart = "${config.programs.waybar.package}/bin/waybar -c ${waybar-config} -s ${waybar-style}"; Restart = "on-failure"; RestartSec = "5s"; }; }; # Create symlinks for config and style system.activationScripts.waybarSetup = lib.mkAfter '' mkdir -p /home/${username}/.config/waybar ln -sf ${waybar-config} /home/${username}/.config/waybar/config ln -sf ${waybar-style} /home/${username}/.config/waybar/style.css chown -R ${username}:users /home/${username}/.config/waybar ''; } #+END_SRC ** =generated/system/core/login-tuigreeter.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/core/login-tuigreeter.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, user, ... } : { environment.systemPackages = with pkgs; [ tuigreet ]; services.greetd = { enable = true; settings = { default_session = { command = pkgs.lib.mkForce "${pkgs.tuigreet}/bin/tuigreet --remember --time --time-format '%I:%M %p | %a • %h | %F'"; }; }; }; } #+END_SRC ** =generated/system/core/wayland.nix= This file sets up wayland #+BEGIN_SRC nix :tangle generated/system/core/wayland.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, ... }: { home-manager.users.${user.username} = { xdg.portal = { enable = true; extraPortals = with pkgs; [ xdg-desktop-portal-hyprland ]; config.hyprland = { "org.freedesktop.impl.portal.Screencast" = [ "hyprland" ]; }; }; home.packages = with pkgs; [ uwsm ]; }; } #+END_SRC ** =generated/system/development/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./databases/top.nix ./devops_ci_cd/top.nix ./programming_languages/top.nix ./virtualization/top.nix ./web_development/top.nix ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./audio/top.nix ./backups/top.nix ./bluetooth/top.nix ./disk_management/top.nix ./hardware_sensors/top.nix ./logging_monitoring/top.nix ./login_manager/top.nix ./monitor_setup/top.nix ./networking/top.nix ./power_management/top.nix ./printers_scanners/top.nix ./security/top.nix ./system_updates/top.nix ]; # .. put any code here } #+END_SRC ** =generated/system/applications/accessibility/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/accessibility/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/applications/file_management/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/file_management/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./thunar.nix ]; } #+END_SRC ** =generated/system/applications/file_management/thunar.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/file_management/thunar.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, ... }: let username = "henrov"; # vervang door je echte gebruikersnaam in { home-manager.users.${username} = { # Thunar and plugins home.packages = with pkgs; [ thunar thunar-volman thunar-archive-plugin thunar-media-tags-plugin tumbler ffmpegthumbnailer gvfs xdg-utils ]; # Default file manager xdg.mimeApps = { defaultApplications = { "inode/directory" = "Thunar.desktop"; }; }; }; } #+END_SRC ** =generated/system/applications/gaming/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/gaming/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/applications/media_playback_editing/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/media_playback_editing/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/applications/office_productivity/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/office_productivity/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/applications/terminal_shell/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./kitty.nix ./starship.nix ./zsh.nix ./emacs.nix ]; # .. put any code here } #+END_SRC ** =generated/system/applications/terminal_shell/kitty.nix= This file sets up Kitty terminal #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/kitty.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, flakeRoot, ... }: let kittyConf = "${flakeRoot}/assets/system/conf/kitty/kitty.conf"; kittyTheme = "${flakeRoot}/assets/system/conf/kitty/Catppuccin-Mocha.conf"; in { home-manager.users.${user.username} = { programs.kitty.enable = true; xdg.configFile."kitty/kitty.conf".source = kittyConf; xdg.configFile."kitty/Catppuccin-Mocha.conf".source = kittyTheme; }; } #+END_SRC ** =generated/system/applications/terminal_shell/starship.nix= This file sets up starship prompt #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/starship.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs, flakeRoot, ... }: let starshipConfig = lib.importTOML (flakeRoot + "/assets/system/conf/starship.toml"); in { programs.starship = { enable = true; settings = starshipConfig; }; } #+END_SRC ** =generated/system/applications/terminal_shell/zsh.nix= This sets up the zsh terminal #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/zsh.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs, ... }: { # --- NixOS Configuration --- environment.systemPackages = with pkgs; [ zsh git docker ]; # --- Home Manager Configuration --- home-manager.users.henrov = { programs.zsh = { enable = true; enableCompletion = true; # Enable oh-my-zsh and use its plugins oh-my-zsh = { enable = true; plugins = [ "git" "docker" "direnv" "zsh-autosuggestions" "zsh-syntax-highlighting" "zsh-completions" "zsh-history-substring-search" ]; theme = "agnoster"; # Fallback, overridden below }; # Source Nixpkgs-provided plugins explicitly initContent = '' # Source plugins installed by Nix source ${pkgs.zsh-autosuggestions}/share/zsh-autosuggestions/zsh-autosuggestions.zsh source ${pkgs.zsh-syntax-highlighting}/share/zsh-syntax-highlighting/zsh-syntax-highlighting.zsh source ${pkgs.zsh-history-substring-search}/share/zsh-history-substring-search/zsh-history-substring-search.zsh # Catppuccin Mocha theme for oh-my-zsh local mocha_base="#1E1E2E" local mocha_surface0="#313244" local mocha_text="#CDD6F4" local mocha_lavender="#B4BEFE" local mocha_blue="#89B4FA" local mocha_sapphire="#74C7EC" local mocha_teal="#94E2D5" local mocha_green="#A6E3A1" local mocha_yellow="#F9E2AF" local mocha_peach="#FAB387" local mocha_maroon="#EBA0AC" local mocha_red="#F38BA8" local mocha_mauve="#CBA6F7" local mocha_pink="#F5C2E7" local mocha_flamingo="#F2CDCD" local mocha_rosewater="#F5E0DC" # Prompt PROMPT='%{$fg[$mocha_blue]%}%n%{$reset_color%}@%{$fg[$mocha_peach]%}%m%{$reset_color%} %{$fg[$mocha_lavender]%}%~%{$reset_color%} %{$fg[$mocha_red]%}$%{$reset_color%} ' RPROMPT='%{$fg[$mocha_green]%}%T%{$reset_color%}' # Git prompt ZSH_THEME_GIT_PROMPT_PREFIX="%{$fg[$mocha_yellow]%}(%{$reset_color%}" ZSH_THEME_GIT_PROMPT_SUFFIX="%{$fg[$mocha_yellow]%})%{$reset_color%}" ZSH_THEME_GIT_PROMPT_DIRTY="%{$fg[$mocha_red]%}✗%{$reset_color%}" ZSH_THEME_GIT_PROMPT_CLEAN="%{$fg[$mocha_green]%}✓%{$reset_color%}" ZSH_THEME_GIT_PROMPT_AHEAD="%{$fg[$mocha_blue]%}⇡%{$reset_color%}" ZSH_THEME_GIT_PROMPT_BEHIND="%{$fg[$mocha_blue]%}⇣%{$reset_color%}" ZSH_THEME_GIT_PROMPT_UNTRACKED="%{$fg[$mocha_pink]%}?%{$reset_color%}" ZSH_THEME_GIT_PROMPT_STAGED="%{$fg[$mocha_sapphire]%}+%{$reset_color%}" ZSH_THEME_GIT_PROMPT_UNSTAGED="%{$fg[$mocha_red]%}!%{$reset_color%}" # Virtualenv/pyenv ZSH_THEME_VIRTUAL_ENV_PREFIX="(%{$fg[$mocha_teal]%}" ZSH_THEME_VIRTUAL_ENV_SUFFIX="%{$reset_color%})" # Right prompt with Git status RPROMPT='$(git_prompt_info) %{$fg[$mocha_green]%}%T%{$reset_color%}' # Set the custom theme ZSH_THEME="catppuccin-mocha" ''; }; # Home Manager packages (optional) home.packages = with pkgs; [ direnv git-extras ]; }; } #+END_SRC ** =generated/system/applications/terminal_shell/emacs.nix= This sets up the emacs terminal #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/emacs.nix :noweb tangle :mkdirp yes :eval never-html { pkgs, ... }: { # NixOS Configuration environment.systemPackages = with pkgs; [ # Add system-wide packages here, if any ]; # Home Manager Configuration for the user 'henrov' home-manager.users.henrov = { programs.emacs = { enable = true; package = pkgs.emacs-pgtk.override { withTreeSitter = true; }; # Group related packages for clarity and easier maintenance extraPackages = epkgs: with epkgs; [ # Tree-sitter and language support manualPackages.treesit-grammars.with-all-grammars rust-mode rustic nix-mode hcl-mode # UI/UX and navigation nerd-icons doom-modeline diminish eldoc eldoc-box pulsar which-key avy consult vertico marginalia crux shell-pop # Completion and snippets nerd-icons-corfu corfu cape orderless yasnippet yasnippet-snippets # Utilities and tools rg exec-path-from-shell eat f gptel nixpkgs-fmt envrc # Theming catppuccin-theme # Git magit # Editing and workflow expreg vundo puni # Error and side panel support sideline sideline-flymake sideline-eglot ]; }; # Home Manager session variables home.sessionVariables = { EDITOR = "emacs"; XDG_SCREENSHOTS_DIR = "~/screenshots"; }; /* # Home Manager file management home.file = { "emacs/early-init.el" = { source = ./early-init.el; target = ".emacs.d/early-init.el"; }; "emacs/init.el" = { source = ./init.el; target = ".emacs.d/init.el"; }; }; */ }; } #+END_SRC ** =generated/system/applications/terminal_shell/early-init.el= This helps set up the emacs terminal #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/early-init.el :noweb tangle :mkdirp yes :eval never-html ;;; package --- early init -*- lexical-binding: t -*- ;;; Commentary: ;;; Prevents white flash and better Emacs defaults ;;; Code: (set-language-environment "UTF-8") (setq-default default-frame-alist '((background-color . "#1e1e2e") (bottom-divider-width . 1) ; Thin horizontal window divider (foreground-color . "#bac2de") ; Default foreground color (fullscreen . maximized) ; Maximize the window by default (horizontal-scroll-bars . nil) ; No horizontal scroll-bars (left-fringe . 8) ; Thin left fringe (menu-bar-lines . 0) ; No menu bar (right-divider-width . 1) ; Thin vertical window divider (right-fringe . 8) ; Thin right fringe (tool-bar-lines . 0) ; No tool bar (undecorated . t) ; Remove extraneous X decorations (vertical-scroll-bars . nil)) ; No vertical scroll-bars user-full-name "Henrov henrov" ; ME! ;; memory configuration ;; Higher garbage collection threshold, prevents frequent gc locks, reset later gc-cons-threshold most-positive-fixnum ;; Ignore warnings for (obsolete) elisp compilations byte-compile-warnings '(not obsolete) ;; And other log types completely warning-suppress-log-types '((comp) (bytecomp)) ;; Large files are okay in the new millenium. large-file-warning-threshold 100000000 ;; dont show garbage collection messages at startup, will reset later garbage-collection-messages nil ;; native compilation package-native-compile t native-comp-warning-on-missing-source nil native-comp-async-report-warnings-errors 'silent ;; Read more based on system pipe capacity read-process-output-max (max (* 10240 10240) read-process-output-max) ;; scroll configuration scroll-margin 0 ; Lets scroll to the end of the margin scroll-conservatively 100000 ; Never recenter the window scroll-preserve-screen-position 1 ; Scrolling back and forth ;; frame config ;; Improve emacs startup time by not resizing to adjust for custom settings frame-inhibit-implied-resize t ;; Dont resize based on character height / width but to exact pixels frame-resize-pixelwise t ;; backups & files backup-directory-alist '(("." . "~/.backups/")) ; Don't clutter backup-by-copying t ; Don't clobber symlinks create-lockfiles nil ; Don't have temp files delete-old-versions t ; Cleanup automatically kept-new-versions 6 ; Update every few times kept-old-versions 2 ; And cleanup even more version-control t ; Version them backups delete-by-moving-to-trash t ; Dont delete, send to trash instead ;; startup inhibit-startup-screen t ; I have already done the tutorial. Twice inhibit-startup-message t ; I know I am ready inhibit-startup-echo-area-message t ; Yep, still know it initial-scratch-message nil ; I know it is the scratch buffer! initial-buffer-choice nil inhibit-startup-buffer-menu t inhibit-x-resources t initial-major-mode 'fundamental-mode pgtk-wait-for-event-timeout 0.001 ; faster child frames ad-redefinition-action 'accept ; dont care about legacy things being redefined inhibit-compacting-font-caches t ;; tabs tab-width 4 ; Always tab 4 spaces. indent-tabs-mode nil ; Never use actual tabs. ;; rendering cursor-in-non-selected-windows nil ; dont render cursors other windows ;; packages use-package-always-defer t load-prefer-newer t default-input-method nil use-dialog-box nil use-file-dialog nil use-package-expand-minimally t package-enable-at-startup nil use-package-enable-imenu-support t auto-mode-case-fold nil ; No second pass of case-insensitive search over auto-mode-alist. package-archives '(("melpa" . "https://melpa.org/packages/") ("gnu" . "https://elpa.gnu.org/packages/") ("nongnu" . "https://elpa.nongnu.org/nongnu/") ("melpa-stable" . "https://stable.melpa.org/packages/")) package-archive-priorities '(("gnu" . 99) ("nongnu" . 80) ("melpa" . 70) ("melpa-stable" . 50)) ) ;;; early-init.el ends here #+END_SRC ** =generated/system/applications/terminal_shell/init.el= This helps set up the emacs terminal #+BEGIN_SRC nix :tangle generated/system/applications/terminal_shell/init.el :noweb tangle :mkdirp yes :eval never-html ;;; package --- Summary - My minimal Emacs init file -*- lexical-binding: t -*- ;;; Commentary: ;;; Simple Emacs setup I carry everywhere ;;; Code: (setq custom-file (locate-user-emacs-file "custom.el")) (load custom-file 'noerror) ;; no error on missing custom file (require 'package) (package-initialize) (defun reset-custom-vars () "Resets the custom variables that were set to crazy numbers" (setopt gc-cons-threshold (* 1024 1024 100)) (setopt garbage-collection-messages t)) (use-package emacs :custom (native-comp-async-query-on-exit t) (read-answer-short t) (use-short-answers t) (enable-recursive-minibuffers t) (which-func-update-delay 1.0) (visible-bell nil) (custom-buffer-done-kill t) (whitespace-line-column nil) (x-underline-at-descent-line t) (imenu-auto-rescan t) (uniquify-buffer-name-style 'forward) (confirm-nonexistent-file-or-buffer nil) (create-lockfiles nil) (make-backup-files nil) (kill-do-not-save-duplicates t) (sentence-end-double-space nil) (treesit-enabled-modes t) :init ;; base visual (menu-bar-mode -1) ;; no menu bar (toggle-scroll-bar -1) ;; no scroll bar (tool-bar-mode -1) ;; no tool bar either (blink-cursor-mode -1) ;; stop blinking ;; font of the century (set-frame-font "Aporetic Sans Mono 12" nil t) :bind (("C-" . pixel-scroll-precision) ; dont zoom in please, just scroll ("C-" . pixel-scroll-precision) ; dont zoom in either, just scroll ("C-x k" . kill-current-buffer)) ; kill the buffer, dont ask :hook (text-mode . delete-trailing-whitespace-mode) (prog-mode . delete-trailing-whitespace-mode) (after-init . global-display-line-numbers-mode) ;; always show line numbers (after-init . column-number-mode) ;; column number in the mode line (after-init . size-indication-mode) ;; file size in the mode line (after-init . pixel-scroll-precision-mode) ;; smooth mouse scroll (after-init . electric-pair-mode) ;; i mean ... parens should auto create (after-init . reset-custom-vars) ) (use-package autorevert :ensure nil :custom (auto-revert-interval 3) (auto-revert-remote-files nil) (auto-revert-use-notify t) (auto-revert-avoid-polling nil) (auto-revert-verbose t) :hook (after-init . global-auto-revert-mode)) (use-package recentf :ensure nil :commands (recentf-mode recentf-cleanup) :hook (after-init . recentf-mode) :custom (recentf-auto-cleanup 'never) (recentf-exclude (list "\\.tar$" "\\.tbz2$" "\\.tbz$" "\\.tgz$" "\\.bz2$" "\\.bz$" "\\.gz$" "\\.gzip$" "\\.xz$" "\\.zip$" "\\.7z$" "\\.rar$" "COMMIT_EDITMSG\\'" "\\.\\(?:gz\\|gif\\|svg\\|png\\|jpe?g\\|bmp\\|xpm\\)$" "-autoloads\\.el$" "autoload\\.el$")) :config ;; A cleanup depth of -90 ensures that `recentf-cleanup' runs before ;; `recentf-save-list', allowing stale entries to be removed before the list ;; is saved by `recentf-save-list', which is automatically added to ;; `kill-emacs-hook' by `recentf-mode'. (add-hook 'kill-emacs-hook #'recentf-cleanup -90)) (use-package savehist :ensure nil :commands (savehist-mode savehist-save) :hook (after-init . savehist-mode) :custom (savehist-autosave-interval 600) (savehist-additional-variables '(kill-ring ; clipboard register-alist ; macros mark-ring global-mark-ring ; marks search-ring regexp-search-ring))) (use-package hl-line :ensure nil :custom (hl-line-sticky-flag nil) (global-hl-line-sticky-flag nil) :hook (after-init . global-hl-line-mode)) (use-package saveplace :ensure nil :commands (save-place-mode save-place-local-mode) :hook (after-init . save-place-mode) :custom (save-place-limit 400)) (use-package nerd-icons :custom ;; disable bright icon colors (nerd-icons-color-icons nil))hells.nix (use-package doom-modeline :custom (inhibit-compacting-font-caches t) ;; speed (doom-modeline-buffer-file-name-style 'relative-from-project) (doom-modeline-major-mode-icon nil) ;; distracting icons, no thank you (doom-modeline-buffer-encoding nil) ;; everything is utf-8 anyway (doom-modeline-buffer-state-icon nil) ;; the filename already shows me (doom-modeline-lsp nil) ;; lsp state is too distracting, too often :hook (after-init . doom-modeline-mode)) (load-theme 'catppuccin :no-confirm) (use-package diminish :demand t) ;; declutter the modeline (use-package eldoc :diminish eldoc-mode :custom (eldoc-echo-area-use-multiline-p nil)) ;; docs for everything (use-package eldoc-box :defer t :config (set-face-background 'eldoc-box-border (catppuccin-color 'green)) (set-face-background 'eldoc-box-body (catppuccin-color 'base)) :bind (("M-h" . eldoc-box-help-at-point))) (use-package pulsar :commands pulsar-global-mode pulsar-recenter-top pulsar-reveal-entry :init (defface pulsar-catppuccin `((default :extend t) (((class color) (min-colors 88) (background light)) :background ,(catppuccin-color 'sapphire)) (((class color) (min-colors 88) (background dark)) :background ,(catppuccin-color 'sapphire)) (t :inverse-video t)) "Alternative nord face for `pulsar-face'." :group 'pulsar-faces) :custom (pulsar-face 'pulsar-catppuccin) :hook (after-init . pulsar-global-mode)) (use-package which-key :commands which-key-mode :diminish which-key-mode :hook (after-init . which-key-mode)) (use-package expreg :bind ("M-m" . expreg-expand)) (use-package vundo) ;; undo tree ;; better structured editing (use-package puni :commands puni-global-mode :hook (after-init . puni-global-mode)) (use-package avy :bind ("M-i" . avy-goto-char-2) :custom (avy-background t)) (use-package consult :bind ("C-x b" . consult-buffer) ;; orig. switch-to-buffer ("M-y" . consult-yank-pop) ;; orig. yank-pop ("M-g M-g" . consult-goto-line) ;; orig. goto-line ("M-g i" . consult-imenu) ;; consult version is interactive ("M-g r" . consult-ripgrep) ;; find in project also works :custom (consult-narrow-key "<")) (use-package vertico :commands vertico-mode :custom (read-file-name-completion-ignore-case t) (read-buffer-completion-ignore-case t) (completion-ignore-case t) (enable-recursive-minibuffers t) (minibuffer-prompt-properties '(read-only t cursor-intangible t face minibuffer-prompt)) :init (vertico-mode) :hook (minibuffer-setup-hook . cursor-intangible-mode)) (use-package marginalia :commands marginalia-mode :hook (after-init . marginalia-mode)) (use-package crux :bind ("C-c M-e" . crux-find-user-init-file) ("C-c C-w" . crux-transpose-windows) ("C-c M-d" . crux-find-current-directory-dir-locals-file) ("C-a" . crux-move-beginning-of-line)) (use-package magit :bind (("C-M-g" . magit-status))) (use-package nerd-icons-corfu :commands nerd-icons-corfu-formatter :defines corfu-margin-formatters) (use-package corfu :commands global-corfu-mode :custom (corfu-cycle t) (corfu-auto t) (corfu-auto-delay 1) (corfu-auto-prefix 3) (corfu-separator ?_) :hook (after-init . global-corfu-mode) :config (add-to-list 'corfu-margin-formatters #'nerd-icons-corfu-formatter)) (use-package cape) (use-package orderless :custom (completion-styles '(orderless partial-completion basic)) (completion-category-defaults nil) (completion-category-overrides nil)) (use-package yasnippet :commands yas-global-mode :diminish yas-minor-mode :hook (after-init . yas-global-mode)) (use-package yasnippet-snippets :after yasnippet) (use-package exec-path-from-shell :commands exec-path-from-shell-initialize :custom (exec-path-from-shell-arguments nil) :hook (after-init . exec-path-from-shell-initialize)) (use-package nixpkgs-fmt :custom (nixpkgs-fmt-command "nixfmt")) (use-package eat :bind (("C-c e p" . eat-project) ("C-c e t" . eat))) (use-package f :demand t) (use-package envrc :commands envrc-global-mode :hook (after-init . envrc-global-mode)) (use-package gptel :commands gptel-make-anthropic f-read-text :config (gptel-make-anthropic "Claude" :stream t :key (f-read-text "/run/secrets/claude_key"))) (use-package sideline-flymake) (use-package sideline-eglot) (use-package sideline :custom (sideline-backends-right '(sideline-flymake sideline-eglot)) :hook (eglot-managed-mode . sideline-mode) (flymake-mode . sideline-mode)) (use-package eglot :custom (eglot-extend-to-xref t) (eglot-ignored-server-capabilities '(:inlayHintProvider)) (jsonrpc-event-hook nil) :hook (eglot-managed-mode . eldoc-box-hover-mode) (before-save . eldoc-format-buffer) :bind (:map eglot-mode-map ("C-c l a" . eglot-code-actions) ("C-c l r" . eglot-rename) ("C-c l h" . eldoc) ("C-c l g" . xref-find-references) ("C-c l w" . eglot-reconnect))) (use-package proced :custom (proced-auto-update-flag t) (proced-auto-update-interval 3) (proced-enable-color-flag t) (proced-show-remote-processes t)) (use-package org :ensure t :defer t :commands (org-mode org-capture org-agenda) :init (defvar org-journal-file "~/nextcloud/org/journal.org") (defvar org-archive-file "~/nextcloud/org/archive.org") (defvar org-notes-file "~/nextcloud/org/notes.org") (defvar org-inbox-file "~/nextcloud/org/inbox.org") (defvar org-work-file "~/nextcloud/org/work.org") (defun my/org-capture-project-target-heading () "Determine Org target headings from the current file's project path. This function assumes a directory structure like '~/projects/COMPANY/PROJECT/'. It extracts 'COMPANY' and 'PROJECT' to use as nested headlines for an Org capture template. If the current buffer is not visi ting a file within such a project structure, it returns nil, causing capture to default to the top of the file." (when-let* ((path (buffer-file-name))) ; Ensure we are in a file-visiting buffer (let ((path-parts (split-string path "/" t " "))) (when-let* ((projects-pos (cl-position "projects" path-parts :test #'string=)) (company (nth (+ 1 projects-pos) path-parts)) (project (nth (+ 2 projects-pos) path-parts))) ;; Return a list of headlines for Org to find or create. (list company project))))) :bind (("C-c c" . org-capture) ("C-c i" . org-store-link) ("C-c a" . org-agenda) :map org-mode-map ("C-c t" . org-toggle-inline-images) ("C-c l" . org-toggle-link-display)) :custom (org-agenda-files (list org-inbox-file org-journal-file)) (org-directory "~/nextcloud/org") (org-default-notes-file org-inbox-file) (org-archive-location (concat org-archive-file "::* From %s")) (org-log-done 'time) (org-log-into-drawer t) (org-hide-emphasis-markers t) (org-src-fontify-natively t) (org-src-tab-acts-natively t) (org-capture-templates '(("t" "Todo" entry (file org-inbox-file) "* TODO %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n)") ("j" "Journal" entry (file+olp+datetree org-journal-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n") ("n" "Note" entry (file org-notes-file) "* %?\n:PROPERTIES:\n:CREATED: %U\n:END:\n\n%a\n\n") ("p" "Project Task" item (file+function org-work-file my/org-capture-project-target-heading) "* TODO %? \n CLOCK: %U" )) ) :config ;; Enable syntax highlighting in code blocks (add-hook 'org-mode-hook 'turn-on-font-lock) (add-hook 'org-mode-hook 'org-indent-mode)) ;; extras (use-package comp-run :ensure nil :config (push "tramp-loaddefs.el.gz" native-comp-jit-compilation-deny-list) (push "cl-loaddefs.el.gz" native-comp-jit-compilation-deny-list)) (use-package rustic :custom (rustic-lsp-client 'eglot)) (provide 'init) ;;; init.el ends here #+END_SRC ** =generated/system/development/databases/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/databases/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/development/devops_ci_cd/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/devops_ci_cd/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/development/programming_languages/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/programming_languages/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/development/virtualization/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/virtualization/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/development/web_development/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/development/web_development/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/audio/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/audio/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/backups/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/backups/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/bluetooth/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/bluetooth/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/disk_management/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/disk_management/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/hardware_sensors/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/hardware_sensors/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/logging_monitoring/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/logging_monitoring/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/login_manager/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/login_manager/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/monitor_setup/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/monitor_setup/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/networking/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/networking/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/power_management/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/power_management/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/printers_scanners/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/printers_scanners/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/security/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/security/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/system_management/system_updates/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/system_management/system_updates/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ # No subfolders to import ]; # .. put any code here } #+END_SRC ** =generated/system/task_launcher/top.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/task_launcher/top.nix :noweb tangle :mkdirp yes :eval never-html { config, pkgs, lib, user, inputs, flakeRoot,... }: { imports = [ ./wofi.nix ]; # .. put any code here } #+END_SRC ** =generated/system/task_launcher/wofi.nix= This is top file of this level which contains just an import statement for all relevant files and/or the subfolder in this folder #+BEGIN_SRC nix :tangle generated/system/task_launcher/wofi.nix :noweb tangle :mkdirp yes :eval never-html { lib, config, pkgs, flakeRoot, user, ... }: let wofiConfigDir = "${config.home-manager.users.${user.username}.xdg.configHome}/wofi"; # Dynamically read all files in assets/hyprland/conf/wofi/ wofiConfs = lib.genAttrs (builtins.attrNames (builtins.readDir "${flakeRoot}/assets/system/conf/wofi")) (name: { text = builtins.readFile "${flakeRoot}/assets/system/conf/wofi/${name}"; }); in { environment.systemPackages = with pkgs; [ wofi ]; home-manager.users.${user.username} = { home.file = { # Map the files to their target paths in ~/.config/wofi/ "${wofiConfigDir}/config" = wofiConfs."wofi.conf"; # Use the actual filename "${wofiConfigDir}/style.css" = wofiConfs."theming.css"; # Use the actual filename }; home.sessionVariables = { WOFI_CONFIG = "${wofiConfigDir}/config"; WOFI_STYLE = "${wofiConfigDir}/style.css"; }; }; } #+END_SRC