diff --git a/.envrc b/.envrc index 1e00ebb..8392d15 100644 --- a/.envrc +++ b/.envrc @@ -1,4 +1 @@ -watch_file flake.nix - -use flake - +use flake \ No newline at end of file diff --git a/.github/logo.svg b/.github/logo.svg deleted file mode 100644 index 0ec06d7..0000000 --- a/.github/logo.svg +++ /dev/null @@ -1,207 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - image/svg+xml - - - - - - - - - - - - - - - - - diff --git a/.gitignore b/.gitignore index 7ad6275..ded2432 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ /.direnv +.qmlls.ini diff --git a/TODO.md b/TODO.md deleted file mode 100644 index f3d4b07..0000000 --- a/TODO.md +++ /dev/null @@ -1,21 +0,0 @@ -## Todo - -This is a list of all the things I still have to fix/achive in this -configuration: - -- [ ] Fix apparmor -- [ ] Lanzaboote -- [ ] Remove all `with` -- [ ] better documentation -- [ ] Fix greetd -- [ ] ClamAV -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] -- [ ] diff --git a/default.nix b/default.nix new file mode 100644 index 0000000..f01ab85 --- /dev/null +++ b/default.nix @@ -0,0 +1,34 @@ +let + inherit (builtins) filter mapAttrs; + + # https://github.com/andir/npins?tab=readme-ov-file#using-the-nixpkgs-fetchers + src = import ./npins; + pkgs = import src.nixpkgs { }; + sources = mapAttrs (_: v: v { inherit pkgs; }) src; + + inherit (pkgs) lib; + inherit (lib.filesystem) listFilesRecursive; + inherit (lib.strings) hasSuffix; + + mkSystem = + hostname: + import (src.nixpkgs + "/nixos/lib/eval-config.nix") { + specialArgs = { + inherit sources; + self = ./.; + }; + modules = [ + # This is used to pre-emptively set the hostPlatform for nixpkgs. + # Also, we set the system hostname here. + { networking.hostName = hostname; } + ./hosts/common.nix + ./hosts/${hostname} + ] + ++ ((listFilesRecursive ./modules) |> filter (hasSuffix ".mod.nix")); + }; +in +{ + temperance = mkSystem "temperance"; + hermit = mkSystem "hermit"; + tower = mkSystem "tower"; +} diff --git a/docs/resizing.md b/docs/resizing.md deleted file mode 100644 index 36438fa..0000000 --- a/docs/resizing.md +++ /dev/null @@ -1,8 +0,0 @@ -## Resizing images using imagemagick - -I wanted to resize an image using imagemagick. - -To do this I had to run: -`magick lain.png -crop 1072x1448^ -gravity center -quality 90 sca.png` - -What does this do? diff --git a/flake.lock b/flake.lock deleted file mode 100644 index 85f7522..0000000 --- a/flake.lock +++ /dev/null @@ -1,605 +0,0 @@ -{ - "nodes": { - "aquamarine": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743265529, - "narHash": "sha256-QbjP15/2N+VJl0b5jxrrTc+VOt39aU4XrDvtP0Lz5ik=", - "owner": "hyprwm", - "repo": "aquamarine", - "rev": "1d2dbd72c2bbaceab031c592d4810f744741d203", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "aquamarine", - "type": "github" - } - }, - "crane": { - "locked": { - "lastModified": 1741148495, - "narHash": "sha256-EV8KUaIZ2/CdBXlutXrHoZYbWPeB65p5kKZk71gvDRI=", - "owner": "ipetkov", - "repo": "crane", - "rev": "75390a36cd0c2cdd5f1aafd8a9f827d7107f2e53", - "type": "github" - }, - "original": { - "owner": "ipetkov", - "repo": "crane", - "type": "github" - } - }, - "flake-compat": { - "flake": false, - "locked": { - "lastModified": 1696426674, - "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-compat_2": { - "flake": false, - "locked": { - "lastModified": 1733328505, - "narHash": "sha256-NeCCThCEP3eCl2l/+27kNNK7QrwZB1IJCrXfrbv5oqU=", - "owner": "edolstra", - "repo": "flake-compat", - "rev": "ff81ac966bb2cae68946d5ed5fc4994f96d0ffec", - "type": "github" - }, - "original": { - "owner": "edolstra", - "repo": "flake-compat", - "type": "github" - } - }, - "flake-parts": { - "inputs": { - "nixpkgs-lib": [ - "lanzaboote", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1740872218, - "narHash": "sha256-ZaMw0pdoUKigLpv9HiNDH2Pjnosg7NBYMJlHTIsHEUo=", - "owner": "hercules-ci", - "repo": "flake-parts", - "rev": "3876f6b87db82f33775b1ef5ea343986105db764", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "flake-parts", - "type": "github" - } - }, - "gitignore": { - "inputs": { - "nixpkgs": [ - "hyprland", - "pre-commit-hooks", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "gitignore_2": { - "inputs": { - "nixpkgs": [ - "lanzaboote", - "pre-commit-hooks-nix", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1709087332, - "narHash": "sha256-HG2cCnktfHsKV0s4XW83gU3F57gaTljL9KNSuG6bnQs=", - "owner": "hercules-ci", - "repo": "gitignore.nix", - "rev": "637db329424fd7e46cf4185293b9cc8c88c95394", - "type": "github" - }, - "original": { - "owner": "hercules-ci", - "repo": "gitignore.nix", - "type": "github" - } - }, - "hyprcursor": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1742215578, - "narHash": "sha256-zfs71PXVVPEe56WEyNi2TJQPs0wabU4WAlq0XV7GcdE=", - "owner": "hyprwm", - "repo": "hyprcursor", - "rev": "2fd36421c21aa87e2fe3bee11067540ae612f719", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprcursor", - "type": "github" - } - }, - "hyprgraphics": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1739049071, - "narHash": "sha256-3+7TpXMrbsUXSwgr5VAKAnmkzMb6JO+Rvc9XRb5NMg4=", - "owner": "hyprwm", - "repo": "hyprgraphics", - "rev": "175c6b29b6ff82100539e7c4363a35a02c74dd73", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprgraphics", - "type": "github" - } - }, - "hyprland": { - "inputs": { - "aquamarine": "aquamarine", - "hyprcursor": "hyprcursor", - "hyprgraphics": "hyprgraphics", - "hyprland-protocols": "hyprland-protocols", - "hyprland-qtutils": "hyprland-qtutils", - "hyprlang": "hyprlang", - "hyprutils": "hyprutils", - "hyprwayland-scanner": "hyprwayland-scanner", - "nixpkgs": [ - "nixpkgs" - ], - "pre-commit-hooks": "pre-commit-hooks", - "systems": [ - "systems" - ], - "xdph": "xdph" - }, - "locked": { - "lastModified": 1744214922, - "narHash": "sha256-136gjyhECXU5t9uFCpWsC4t50lUJnI4PJ9KZsNIaydg=", - "owner": "hyprwm", - "repo": "hyprland", - "rev": "0dc531c4a7d6849f2db61084497b3007e92f470b", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland", - "type": "github" - } - }, - "hyprland-protocols": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743714874, - "narHash": "sha256-yt8F7NhMFCFHUHy/lNjH/pjZyIDFNk52Q4tivQ31WFo=", - "owner": "hyprwm", - "repo": "hyprland-protocols", - "rev": "3a5c2bda1c1a4e55cc1330c782547695a93f05b2", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-protocols", - "type": "github" - } - }, - "hyprland-qt-support": { - "inputs": { - "hyprlang": [ - "hyprland", - "hyprland-qtutils", - "hyprlang" - ], - "nixpkgs": [ - "hyprland", - "hyprland-qtutils", - "nixpkgs" - ], - "systems": [ - "hyprland", - "hyprland-qtutils", - "systems" - ] - }, - "locked": { - "lastModified": 1737634706, - "narHash": "sha256-nGCibkfsXz7ARx5R+SnisRtMq21IQIhazp6viBU8I/A=", - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "rev": "8810df502cdee755993cb803eba7b23f189db795", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qt-support", - "type": "github" - } - }, - "hyprland-qtutils": { - "inputs": { - "hyprland-qt-support": "hyprland-qt-support", - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprland-qtutils", - "hyprlang", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1739048983, - "narHash": "sha256-REhTcXq4qs3B3cCDtLlYDz0GZvmsBSh947Ub6pQWGTQ=", - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "rev": "3504a293c8f8db4127cb0f7cfc1a318ffb4316f8", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprland-qtutils", - "type": "github" - } - }, - "hyprlang": { - "inputs": { - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1741191527, - "narHash": "sha256-kM+11Nch47Xwfgtw2EpRitJuORy4miwoMuRi5tyMBDY=", - "owner": "hyprwm", - "repo": "hyprlang", - "rev": "72df3861f1197e41b078faa3e38eedd60e00018d", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprlang", - "type": "github" - } - }, - "hyprutils": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1743950287, - "narHash": "sha256-/6IAEWyb8gC/NKZElxiHChkouiUOrVYNq9YqG0Pzm4Y=", - "owner": "hyprwm", - "repo": "hyprutils", - "rev": "f2dc70e448b994cef627a157ee340135bd68fbc6", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprutils", - "type": "github" - } - }, - "hyprwayland-scanner": { - "inputs": { - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1739870480, - "narHash": "sha256-SiDN5BGxa/1hAsqhgJsS03C3t2QrLgBT8u+ENJ0Qzwc=", - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "rev": "206367a08dc5ac4ba7ad31bdca391d098082e64b", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "hyprwayland-scanner", - "type": "github" - } - }, - "impermanence": { - "locked": { - "lastModified": 1737831083, - "narHash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=", - "owner": "nix-community", - "repo": "impermanence", - "rev": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "impermanence", - "type": "github" - } - }, - "lanzaboote": { - "inputs": { - "crane": "crane", - "flake-compat": "flake-compat_2", - "flake-parts": "flake-parts", - "nixpkgs": [ - "nixpkgs" - ], - "pre-commit-hooks-nix": "pre-commit-hooks-nix", - "rust-overlay": "rust-overlay" - }, - "locked": { - "lastModified": 1741442524, - "narHash": "sha256-tVcxLDLLho8dWcO81Xj/3/ANLdVs0bGyCPyKjp70JWk=", - "owner": "nix-community", - "repo": "lanzaboote", - "rev": "d8099586d9a84308ffedac07880e7f07a0180ff4", - "type": "github" - }, - "original": { - "owner": "nix-community", - "repo": "lanzaboote", - "type": "github" - } - }, - "nixpkgs": { - "locked": { - "lastModified": 1744098102, - "narHash": "sha256-tzCdyIJj9AjysC3OuKA+tMD/kDEDAF9mICPDU7ix0JA=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "c8cd81426f45942bb2906d5ed2fe21d2f19d95b7", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixos-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "pre-commit-hooks": { - "inputs": { - "flake-compat": "flake-compat", - "gitignore": "gitignore", - "nixpkgs": [ - "hyprland", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1742649964, - "narHash": "sha256-DwOTp7nvfi8mRfuL1escHDXabVXFGT1VlPD1JHrtrco=", - "owner": "cachix", - "repo": "git-hooks.nix", - "rev": "dcf5072734cb576d2b0c59b2ac44f5050b5eac82", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "git-hooks.nix", - "type": "github" - } - }, - "pre-commit-hooks-nix": { - "inputs": { - "flake-compat": [ - "lanzaboote", - "flake-compat" - ], - "gitignore": "gitignore_2", - "nixpkgs": [ - "lanzaboote", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1740915799, - "narHash": "sha256-JvQvtaphZNmeeV+IpHgNdiNePsIpHD5U/7QN5AeY44A=", - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "rev": "42b1ba089d2034d910566bf6b40830af6b8ec732", - "type": "github" - }, - "original": { - "owner": "cachix", - "repo": "pre-commit-hooks.nix", - "type": "github" - } - }, - "root": { - "inputs": { - "hyprland": "hyprland", - "impermanence": "impermanence", - "lanzaboote": "lanzaboote", - "nixpkgs": "nixpkgs", - "systems": "systems" - } - }, - "rust-overlay": { - "inputs": { - "nixpkgs": [ - "lanzaboote", - "nixpkgs" - ] - }, - "locked": { - "lastModified": 1741228283, - "narHash": "sha256-VzqI+k/eoijLQ5am6rDFDAtFAbw8nltXfLBC6SIEJAE=", - "owner": "oxalica", - "repo": "rust-overlay", - "rev": "38e9826bc4296c9daf18bc1e6aa299f3e932a403", - "type": "github" - }, - "original": { - "owner": "oxalica", - "repo": "rust-overlay", - "type": "github" - } - }, - "systems": { - "locked": { - "lastModified": 1689347949, - "narHash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=", - "owner": "nix-systems", - "repo": "default-linux", - "rev": "31732fcf5e8fea42e59c2488ad31a0e651500f68", - "type": "github" - }, - "original": { - "owner": "nix-systems", - "repo": "default-linux", - "type": "github" - } - }, - "xdph": { - "inputs": { - "hyprland-protocols": [ - "hyprland", - "hyprland-protocols" - ], - "hyprlang": [ - "hyprland", - "hyprlang" - ], - "hyprutils": [ - "hyprland", - "hyprutils" - ], - "hyprwayland-scanner": [ - "hyprland", - "hyprwayland-scanner" - ], - "nixpkgs": [ - "hyprland", - "nixpkgs" - ], - "systems": [ - "hyprland", - "systems" - ] - }, - "locked": { - "lastModified": 1741934139, - "narHash": "sha256-ZhTcTH9FoeAtbPfWGrhkH7RjLJZ7GeF18nygLAMR+WE=", - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "rev": "150b0b6f52bb422a1b232a53698606fe0320dde0", - "type": "github" - }, - "original": { - "owner": "hyprwm", - "repo": "xdg-desktop-portal-hyprland", - "type": "github" - } - } - }, - "root": "root", - "version": 7 -} diff --git a/flake.nix b/flake.nix index 9a4b1c2..ff42b87 100644 --- a/flake.nix +++ b/flake.nix @@ -1,53 +1,43 @@ { description = "My NixOS config flake"; - outputs = inputs: let - pkgs = inputs.nixpkgs.legacyPackages.x86_64-linux; - eachSystem = inputs.nixpkgs.lib.genAttrs (import inputs.systems); - pkgsFor = inputs.nixpkgs.legacyPackages; - in { - nixosConfigurations = import ./hosts inputs; - devShells.x86_64-linux.default = pkgs.callPackage ./shell.nix {}; + # No inputs, take this flakers - formatter.x86_64-linux = pkgs.alejandra; + outputs = + _: + let + sources = import ./npins; + nixpkgs = + (import sources.flake-compat { + src = sources.nixpkgs; + copySourceTreeToStore = false; + useBuiltinsFetchTree = true; + }).outputs; + inherit (nixpkgs) lib; + pkgsFor = nixpkgs.legacyPackages; + inputs = sources; + in + { + nixosConfigurations = import ./default.nix; - packages = eachSystem ( - system: { - inherit (import ./packages pkgsFor.${system}) fish helix kakoune; - } - ); + packages = lib.mapAttrs (_: pkgs: { + inherit + (import ./packages { + inherit inputs pkgs sources; + }) + fish + kakoune + ; + }) pkgsFor; + devShells = lib.mapAttrs (_: pkgs: { + default = pkgs.mkShellNoCC { + packages = [ + (pkgs.callPackage (sources.npins + "/npins.nix") { }) + ]; + env.NPINS_OVERRIDE_nichts = "."; + }; + }) pkgsFor; - apps = eachSystem (system: let - inherit (inputs.self.packages.${system}) fish helix; - in { - default = { - type = "app"; - program = "${fish}/bin/fish"; - }; - helix = { - type = "app"; - program = "${helix}/bin/hx"; - }; - }); - }; - inputs = { - # Unstable nixpkgs baby! - nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; - - systems.url = "github:nix-systems/default-linux"; - - impermanence.url = "github:nix-community/impermanence"; - - # secure booting - lanzaboote = { - url = "github:nix-community/lanzaboote"; - inputs.nixpkgs.follows = "nixpkgs"; + templates = import ./templates; }; - - hyprland = { - url = "github:hyprwm/hyprland"; - inputs.nixpkgs.follows = "nixpkgs"; - inputs.systems.follows = "systems"; - }; - }; } diff --git a/hosts/common.nix b/hosts/common.nix index 94824a7..0405615 100644 --- a/hosts/common.nix +++ b/hosts/common.nix @@ -3,44 +3,48 @@ # since these also get installed to server, # which should have a small attack surface. { - self, + lib, pkgs, ... -}: let - inherit (self.packages.${pkgs.stdenv.system}) helix fish; -in { - environment.systemPackages = builtins.attrValues { - inherit - (pkgs) - cachix - calc - difftastic - eza - gcc - git - httpie - inetutils - jujutsu - just - lazygit - links2 - linuxHeaders - neofetch - microfetch - mprocs - nmap - polkit - ripgrep - smartmontools - television - trash-cli - util-linux - wireguard-tools - zip - zoxide - ; - inherit helix fish; - }; +}: +let + inherit (lib.meta) hiPrioSet; +in +{ + environment.systemPackages = + builtins.attrValues { + inherit (pkgs) + cachix + calc + delta + difftastic + eza + gcc + git + httpie + inetutils + jujutsu + just + lazygit + linuxHeaders + neofetch + microfetch + mprocs + nmap + ripgrep + smartmontools + television + trash-cli + util-linux + w3m + wireguard-tools + zip + zoxide + ; + } + ++ builtins.attrValues (hiPrioSet { + }) + ++ [ (lib.hiPrio pkgs.uutils-coreutils-noprefix) ]; # helix as the only editor, a reasonable choice. - environment.sessionVariables.EDITOR = pkgs.lib.getExe' helix "hx"; + environment.variables.EDITOR = "hx"; } diff --git a/hosts/default.nix b/hosts/default.nix index 7a34711..12ee7fd 100644 --- a/hosts/default.nix +++ b/hosts/default.nix @@ -1,7 +1,12 @@ -inputs: let - inherit (inputs) self; +{ + sources, + nixpkgs, + self, + ... +}: +let inherit (builtins) filter map toString; - inherit (inputs.nixpkgs) lib; + inherit (nixpkgs) lib; inherit (lib.attrsets) recursiveUpdate; inherit (lib.filesystem) listFilesRecursive; inherit (lib.lists) concatLists flatten singleton; @@ -10,44 +15,41 @@ inputs: let # NOTE: This was inspired by raf, and I find this # to be quite a sane way of managing all modules in my flake. - mkSystem = { - system, - hostname, - ... - } @ args: + mkSystem = + { + system, + hostname, + ... + }@args: nixosSystem { - specialArgs = - recursiveUpdate - { - inherit lib; - inherit inputs; - inherit self; - } - (args.specialArgs or {}); + specialArgs = recursiveUpdate { + inherit lib; + inputs = sources; + inherit self; + } args.specialArgs or { }; modules = concatLists [ # This is used to pre-emptively set the hostPlatform for nixpkgs. # Also, we set the system hostname here. - [ - # self.nixosModules.user - ] (singleton { networking.hostName = hostname; nixpkgs.hostPlatform = system; }) - (flatten ( + ( concatLists [ + # configuration for the host, passed as an argument. (singleton ./${hostname}/default.nix) + # common configuration, which all hosts share. (singleton ./common.nix) - ( - filter (hasSuffix "module.nix") ( - map toString (listFilesRecursive ../modules) - ) - ) + # Import all files called module.nix from my modules directory. + (map toString (listFilesRecursive ../modules) |> filter (hasSuffix "module.nix")) + (map toString (listFilesRecursive ../modules) |> filter (hasSuffix ".mod.nix")) ] - )) + |> flatten + ) ]; }; -in { +in +{ temperance = mkSystem { system = "x86_64-linux"; hostname = "temperance"; @@ -61,4 +63,8 @@ in { system = "aarch64-linux"; hostname = "tower"; }; + # world = mkSystem { + # system = "x86_64-linux"; + # hostname = "world"; + # }; } diff --git a/hosts/hermit/configuration.nix b/hosts/hermit/configuration.nix index a33bdc4..c179d5e 100644 --- a/hosts/hermit/configuration.nix +++ b/hosts/hermit/configuration.nix @@ -2,38 +2,49 @@ lib, pkgs, ... -}: { +}: +{ # Time Zone time.timeZone = "Europe/Zurich"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; console.keyMap = "uk"; - security.polkit.enable = true; - programs.kdeconnect.enable = false; - programs.nix-ld.enable = false; boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; services = { fstrim.enable = lib.mkDefault true; thermald.enable = true; - auto-cpufreq.enable = true; - printing.enable = true; - avahi = { + }; + programs = { + nix-ld.enable = false; + gnupg.agent = { enable = true; - nssmdns4 = true; - openFirewall = true; + pinentryPackage = pkgs.pinentry-qt; }; }; modules = { - desktops.hyprland.enable = true; + wms.wayland.enable = true; + # desktops.niri.enable = true; + + theming = { + gtk.enable = true; + quickshell.enable = true; + }; + system = { - boot.systemd-boot.enable = true; + systemType = "laptop"; + isGraphical = true; + + boot = { + systemd-boot.enable = true; + lanzaboote.enable = true; + }; impermanence.enable = false; services = { owncloud.enable = true; }; hardware = { - nvidia.enable = true; + nvidia.enable = false; intel.enable = true; bluetooth = { enable = true; @@ -44,19 +55,15 @@ editors = { helix.enable = true; }; - # nushell.enable = true; - # starship.enable = true; - terminals = { - foot.enable = true; - }; }; sound.enable = true; }; services = { locate.enable = true; kanata.enable = true; - uwsm.enable = true; - greetd.enable = true; + uwsm.enable = false; + greetd.enable = false; + cups.enable = true; media.mpd = { enable = true; @@ -69,6 +76,7 @@ ssh.enable = true; btop.enable = true; nh.enable = true; + thunar.enable = true; }; }; system.stateVersion = "23.11"; diff --git a/hosts/hermit/filesystem/default.nix b/hosts/hermit/filesystem/default.nix index cef9c16..f751038 100644 --- a/hosts/hermit/filesystem/default.nix +++ b/hosts/hermit/filesystem/default.nix @@ -1,6 +1,7 @@ { config = { - boot.initrd.luks.devices."cryptroot".device = "/dev/disk/by-uuid/10318654-ed20-43f6-885d-35366a427581"; + boot.initrd.luks.devices."cryptroot".device = + "/dev/disk/by-uuid/10318654-ed20-43f6-885d-35366a427581"; fileSystems = { "/boot" = { device = "/dev/disk/by-uuid/5D7D-FC52"; @@ -10,17 +11,28 @@ "/" = { device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; fsType = "btrfs"; - options = ["compress=zstd" "noatime"]; + options = [ + "compress=zstd" + "noatime" + ]; }; "/nix" = { device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; fsType = "btrfs"; - options = ["subvol=nix" "compress=zstd" "noatime"]; + options = [ + "subvol=nix" + "compress=zstd" + "noatime" + ]; }; "/home" = { device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; fsType = "btrfs"; - options = ["subvol=home" "compress=zstd" "noatime"]; + options = [ + "subvol=home" + "compress=zstd" + "noatime" + ]; }; }; # swapDevices = [ diff --git a/hosts/hermit/hardware-configuration.nix b/hosts/hermit/hardware-configuration.nix index 406634d..e9442b8 100644 --- a/hosts/hermit/hardware-configuration.nix +++ b/hosts/hermit/hardware-configuration.nix @@ -6,16 +6,53 @@ lib, modulesPath, ... -}: { +}: +{ imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usb_storage" "sd_mod" "rtsx_pci_sdmmc"]; - boot.initrd.kernelModules = []; - boot.kernelModules = ["kvm-intel"]; - boot.kernelParams = ["mem_sleep_default=deep"]; - boot.extraModulePackages = []; + boot = { + initrd = { + availableKernelModules = [ + "xhci_pci" + "ahci" + "nvme" + "usb_storage" + "sd_mod" + "rtsx_pci_sdmmc" + ]; + kernelModules = [ ]; + }; + kernelModules = [ "kvm-intel" ]; + blacklistedKernelModules = [ + "nouveau" + "nvidia" + "nvidia_drm" + "nvidia_modeset" + ]; + + kernelParams = [ "mem_sleep_default=deep" ]; + extraModulePackages = [ ]; + extraModprobeConfig = '' + blacklist nouveau + options nouveau modeset=0 + ''; + }; + + services.udev.extraRules = '' + # Remove NVIDIA USB xHCI Host Controller devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c0330", ATTR{power/control}="auto", ATTR{remove}="1" + + # Remove NVIDIA USB Type-C UCSI devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x0c8000", ATTR{power/control}="auto", ATTR{remove}="1" + + # Remove NVIDIA Audio devices, if present + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x040300", ATTR{power/control}="auto", ATTR{remove}="1" + + # Remove NVIDIA VGA/3D controller devices + ACTION=="add", SUBSYSTEM=="pci", ATTR{vendor}=="0x10de", ATTR{class}=="0x03[0-9]*", ATTR{power/control}="auto", ATTR{remove}="1" + ''; # swapDevices = # [ { device = "/dev/disk/by-uuid/3518272e-1051-41e2-a7f0-f5c744e46789"; } @@ -26,8 +63,6 @@ # (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.wlp59s0.useDHCP = lib.mkDefault true; # Enable firmware updates via `fwupdmgr`. services.fwupd.enable = lib.mkDefault true; diff --git a/hosts/hermit/hardware/default.nix b/hosts/hermit/hardware/default.nix index 715273e..c09935b 100644 --- a/hosts/hermit/hardware/default.nix +++ b/hosts/hermit/hardware/default.nix @@ -1 +1 @@ -_: {imports = [./monitors.nix];} +_: { imports = [ ./monitors.nix ]; } diff --git a/hosts/hermit/kernel/default.nix b/hosts/hermit/kernel/default.nix index 5146fec..ccd6622 100644 --- a/hosts/hermit/kernel/default.nix +++ b/hosts/hermit/kernel/default.nix @@ -3,8 +3,10 @@ lib, pkgs, ... -}: let +}: +let xanmod_custom = callPackage ./xanmod.nix; -in { +in +{ boot.kernelPackages = xanmod_custom; } diff --git a/hosts/hermit/programs.nix b/hosts/hermit/programs.nix index b5b498f..afad470 100644 --- a/hosts/hermit/programs.nix +++ b/hosts/hermit/programs.nix @@ -1,29 +1,26 @@ -{ - self, - pkgs, - ... -}: { +{pkgs, ...}: { environment.systemPackages = builtins.attrValues { inherit (pkgs) + abook + aerc + aichat alsa-utils anki asciinema + bacon + brave cachix calc - # calibre + cargo-info cbonsai cinny-desktop cmus - comma difftastic - element - element-desktop - emacs30-pgtk + dua evince eza - firefox - fftw + fselect gcc gh grc @@ -34,67 +31,48 @@ httpie hyperfine imagemagick - img2pdf impala imv inetutils jujutsu just - jrnl keepassxc lazygit libtool librewolf links2 linuxHeaders - moc + mprocs mpv - ncmpcpp - neofetch networkmanagerapplet - nicotine-plus - nil nitch obsidian - swww microfetch nmap pamixer - pavucontrol + pwvucontrol pdfarranger pdfpc pfetch - pidgin playerctl - polkit + presenterm pulsemixer - python3 ripgrep rmpc + rusty-man signal-desktop smartmontools telegram-desktop - texliveFull - tldr thunderbird - tor-browser trash-cli typst util-linux v4l-utils - vesktop vlc - vscodium - weechat + wiki-tui wireguard-tools xournalpp - zapzap - zip - zoxide - kakoune - kakoune-lsp - television + zathura ; - inherit (self.packages.${pkgs.stdenv.system}) helix; }; } diff --git a/hosts/temperance/configuration.nix b/hosts/temperance/configuration.nix index cfc2982..d668190 100644 --- a/hosts/temperance/configuration.nix +++ b/hosts/temperance/configuration.nix @@ -3,46 +3,31 @@ lib, pkgs, ... -}: let - inherit - ( - pkgs.callPackage ./kernel/xanmod.nix { - inherit lib; - inherit - (pkgs) - stdenv - fetchFromGitHub - kernelPatches - buildLinux - variant - ; - } - ) - xanmod_blox - ; -in { +}: +{ # Time Zone time.timeZone = "Europe/Zurich"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; console.keyMap = "us"; - security.polkit.enable = true; # boot.kernelPackages = pkgs.linuxPackagesFor xanmod_blox; - boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; + boot.kernelPackages = pkgs.linuxPackages_latest; programs.nix-ld.enable = true; services = { fstrim.enable = lib.mkDefault true; udisks2.enable = true; + system76-scheduler = { + enable = true; + }; }; - virtualisation.docker.enable = true; - meta = { mainUser.gitSigningKey = ""; }; modules = { system = { + isGraphical = true; impermanence.enable = true; boot = { systemd-boot.enable = true; @@ -64,10 +49,11 @@ in { nvidia.enable = true; }; }; - desktops.hyprland.enable = true; + desktops.niri.enable = true; theming = { gtk.enable = true; + quickshell.enable = true; }; services = { @@ -79,8 +65,8 @@ in { enable = true; musicDirectory = "/home/${config.modules.other.system.username}/cloud/media/Music"; }; - uwsm.enable = true; - greetd.enable = true; + # uwsm.enable = true; + # greetd.enable = true; }; other = { system = { @@ -89,8 +75,8 @@ in { }; programs = { ssh.enable = true; - btop.enable = true; nh.enable = true; + thunar.enable = true; }; }; } diff --git a/hosts/temperance/filesystem/default.nix b/hosts/temperance/filesystem/default.nix index 7b7311f..4731289 100644 --- a/hosts/temperance/filesystem/default.nix +++ b/hosts/temperance/filesystem/default.nix @@ -1,6 +1,7 @@ { config = { - boot.initrd.luks.devices."cryptroot".device = "/dev/disk/by-uuid/96e8f3d6-8d2d-4e2d-abd9-3eb7f48fed02"; + boot.initrd.luks.devices."cryptroot".device = + "/dev/disk/by-uuid/96e8f3d6-8d2d-4e2d-abd9-3eb7f48fed02"; fileSystems = { "/boot" = { device = "/dev/disk/by-uuid/B3AC-9050"; @@ -10,29 +11,49 @@ "/" = { device = "none"; fsType = "tmpfs"; - options = ["defaults" "size=40%" "mode=755"]; + options = [ + "defaults" + "size=40%" + "mode=755" + ]; }; "/nix" = { device = "/dev/disk/by-uuid/f0569993-722e-4721-b0d9-8ac537a7a548"; fsType = "btrfs"; - options = ["subvol=nix" "compress=zstd" "noatime"]; + options = [ + "subvol=nix" + "compress=zstd" + "noatime" + ]; }; "/persist" = { device = "/dev/disk/by-uuid/f0569993-722e-4721-b0d9-8ac537a7a548"; neededForBoot = true; fsType = "btrfs"; - options = ["subvol=persist" "compress=zstd" "noatime"]; + options = [ + "subvol=persist" + "compress=zstd" + "noatime" + ]; }; "/home" = { device = "/dev/disk/by-uuid/f0569993-722e-4721-b0d9-8ac537a7a548"; fsType = "btrfs"; - options = ["subvol=home" "compress=zstd" "noatime"]; + options = [ + "subvol=home" + "compress=zstd" + "noatime" + ]; }; "/swap" = { device = "/dev/disk/by-uuid/f0569993-722e-4721-b0d9-8ac537a7a548"; fsType = "btrfs"; - options = ["subvol=swap" "compress=lzo" "noatime"]; + options = [ + "subvol=swap" + "compress=lzo" + "noatime" + ]; }; }; swapDevices = [ diff --git a/hosts/temperance/hardware-configuration.nix b/hosts/temperance/hardware-configuration.nix index e30e94e..8b5836c 100644 --- a/hosts/temperance/hardware-configuration.nix +++ b/hosts/temperance/hardware-configuration.nix @@ -3,13 +3,22 @@ lib, modulesPath, ... -}: { - imports = [(modulesPath + "/installer/scan/not-detected.nix")]; +}: +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; - boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "sd_mod"]; - boot.initrd.kernelModules = []; - boot.kernelModules = []; - boot.extraModulePackages = []; + boot = { + initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "nvme" + "usbhid" + "sd_mod" + ]; + initrd.kernelModules = [ ]; + kernelModules = [ ]; + extraModulePackages = [ ]; + }; # 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 @@ -18,7 +27,5 @@ networking.useDHCP = lib.mkDefault true; # networking.interfaces.enp4s0.useDHCP = lib.mkDefault true; - nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; - hardware.cpu.intel.updateMicrocode = - lib.mkDefault config.hardware.enableRedistributableFirmware; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; } diff --git a/hosts/temperance/hardware/default.nix b/hosts/temperance/hardware/default.nix index 715273e..c09935b 100644 --- a/hosts/temperance/hardware/default.nix +++ b/hosts/temperance/hardware/default.nix @@ -1 +1 @@ -_: {imports = [./monitors.nix];} +_: { imports = [ ./monitors.nix ]; } diff --git a/hosts/temperance/kernel/default.nix b/hosts/temperance/kernel/default.nix index 5146fec..ccd6622 100644 --- a/hosts/temperance/kernel/default.nix +++ b/hosts/temperance/kernel/default.nix @@ -3,8 +3,10 @@ lib, pkgs, ... -}: let +}: +let xanmod_custom = callPackage ./xanmod.nix; -in { +in +{ boot.kernelPackages = xanmod_custom; } diff --git a/hosts/temperance/kernel/unused.nix b/hosts/temperance/kernel/unused.nix index 8f4cc06..ce5a9ee 100644 --- a/hosts/temperance/kernel/unused.nix +++ b/hosts/temperance/kernel/unused.nix @@ -1,8 +1,10 @@ -{lib, ...}: let +{ lib, ... }: +let inherit (lib.kernel) no unset; inherit (lib.attrsets) mapAttrs; inherit (lib.modules) mkForce; -in { +in +{ boot.kernelPatches = [ { name = "disable-unused-features"; diff --git a/hosts/temperance/kernel/xanmod.nix b/hosts/temperance/kernel/xanmod.nix index d366252..f5dc2cf 100644 --- a/hosts/temperance/kernel/xanmod.nix +++ b/hosts/temperance/kernel/xanmod.nix @@ -4,7 +4,8 @@ buildLinux, kernelPatches, ... -}: let +}: +let pname = "linux-xanmod"; version = "6.11.5"; vendorSuffix = "xanmod1"; @@ -58,17 +59,17 @@ }; }) # 1:1 taken from raf's custom kernel, check out his config for this. - .overrideAttrs (oa: { - prePatch = - (oa.prePatch or "") - + '' + .overrideAttrs + (oa: { + prePatch = oa.prePatch or "" + '' # bragging rights echo "Replacing localversion with custom suffix" substituteInPlace localversion \ --replace-fail "xanmod1" "blox" ''; - }); -in { + }); +in +{ inherit xanmod_blox ; diff --git a/hosts/temperance/programs.nix b/hosts/temperance/programs.nix index 6089d35..139359f 100644 --- a/hosts/temperance/programs.nix +++ b/hosts/temperance/programs.nix @@ -1,24 +1,19 @@ -{pkgs, ...}: let -in { +{ pkgs, ... }: +{ environment.systemPackages = builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) alsa-utils anki asciinema beets - brave bubblewrap cachix calc calibre - cinny-desktop - comma + carapace digikam difftastic dnsutils - devenv - element-desktop evince gcc gh @@ -33,48 +28,40 @@ in { impala imv inetutils - joplin-desktop + inshellisense jujutsu - julia just keepassxc lazygit librewolf libtool logiops + mergiraf mpv nautilus - nextcloud-client - nheko nicotine-plus obsidian - swww + oculante pandoc pavucontrol pdfarranger picard - polkit pulsemixer - python3 pwvucontrol qbittorrent - r2modman radare2 ripgrep rmpc - ruby_3_2 signal-desktop - strawberry + starship telegram-desktop - texliveFull thunderbird + topiary tor-browser trash-cli - tutanota-desktop typst - vscodium - walker - wayneko + vesktop + vivid wireguard-tools xdg-utils xournalpp @@ -82,10 +69,13 @@ in { zathura zotero zoxide - ; - inherit - (pkgs.wineWowPackages) - waylandFull + curl + git + wget + unzip + zip + util-linux + zed-editor ; }; } diff --git a/hosts/tower/configuration.nix b/hosts/tower/configuration.nix index 7dfad78..d652aca 100644 --- a/hosts/tower/configuration.nix +++ b/hosts/tower/configuration.nix @@ -2,16 +2,15 @@ lib, pkgs, ... -}: { +}: +{ # Time Zone time.timeZone = "Europe/Vienna"; # Select internationalisation properties. i18n.defaultLocale = "en_US.UTF-8"; console.keyMap = "uk"; - security.polkit.enable = true; - # boot.kernelPackages = pkgs.linuxPackagesFor xanmod_blox; - # boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; + boot.kernelPackages = pkgs.linuxPackages_latest; programs.nix-ld.enable = true; users.users."cr".openssh.authorizedKeys.keys = [ "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILPiRe9OH/VtWFWyy5QbAVcN7CLxr4zUtRCwmxD6aeN6" @@ -29,8 +28,15 @@ locate.enable = true; }; system = { - boot.grub.enable = true; - services.forgejo.enable = true; + boot = { + grub.enable = true; + timeout = 30; + }; + services = { + forgejo.enable = true; + grafana.enable = true; + prometheus.enable = true; + }; programs = { editors = { helix.enable = true; diff --git a/hosts/tower/filesystem/default.nix b/hosts/tower/filesystem/default.nix index 331c4dd..be5ccd8 100644 --- a/hosts/tower/filesystem/default.nix +++ b/hosts/tower/filesystem/default.nix @@ -8,7 +8,7 @@ "/" = { device = "/dev/disk/by-uuid/3a781f2e-290a-4609-9035-a93374459def"; fsType = "ext4"; - options = ["noatime"]; + options = [ "noatime" ]; }; }; } diff --git a/hosts/tower/hardware-configuration.nix b/hosts/tower/hardware-configuration.nix index 2b2927f..67abc5e 100644 --- a/hosts/tower/hardware-configuration.nix +++ b/hosts/tower/hardware-configuration.nix @@ -2,17 +2,24 @@ lib, modulesPath, ... -}: { +}: +{ imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; - boot.initrd.availableKernelModules = ["xhci_pci" "virtio_scsi" "sr_mod"]; - boot.initrd.kernelModules = []; - boot.kernelModules = []; - boot.extraModulePackages = []; + boot = { + initrd.availableKernelModules = [ + "xhci_pci" + "virtio_scsi" + "sr_mod" + ]; + initrd.kernelModules = [ ]; + kernelModules = [ ]; + extraModulePackages = [ ]; + }; - swapDevices = []; + swapDevices = [ ]; # 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 diff --git a/hosts/tower/programs.nix b/hosts/tower/programs.nix index 505d7b8..74465fe 100644 --- a/hosts/tower/programs.nix +++ b/hosts/tower/programs.nix @@ -1,7 +1,7 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ environment.systemPackages = builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) ; }; } diff --git a/hosts/world/configuration.nix b/hosts/world/configuration.nix new file mode 100644 index 0000000..0d6ae9d --- /dev/null +++ b/hosts/world/configuration.nix @@ -0,0 +1,51 @@ +{ + lib, + pkgs, + ... +}: +{ + # Time Zone + time.timeZone = "Europe/Zurich"; + # Select internationalisation properties. + i18n.defaultLocale = "en_US.UTF-8"; + console.keyMap = "uk"; + programs.nix-ld.enable = false; + boot.kernelPackages = pkgs.linuxPackages_xanmod_latest; + services = { + fstrim.enable = lib.mkDefault true; + thermald.enable = true; + }; + + modules = { + desktops.hyprland.enable = true; + + system = { + boot.systemd-boot.enable = true; + impermanence.enable = false; + hardware = { + intel.enable = true; + }; + programs = { + editors = { + helix.enable = true; + }; + terminals = { + foot.enable = true; + }; + }; + }; + services = { + kanata.enable = true; + }; + other = { + system.username = "cr"; + }; + programs = { + ssh.enable = true; + btop.enable = true; + nh.enable = true; + thunar.enable = true; + }; + }; + system.stateVersion = "23.11"; +} diff --git a/hosts/world/default.nix b/hosts/world/default.nix new file mode 100644 index 0000000..0312dc8 --- /dev/null +++ b/hosts/world/default.nix @@ -0,0 +1,8 @@ +_: { + imports = [ + ./configuration.nix + ./programs.nix + ./hardware-configuration.nix + ./hardware + ]; +} diff --git a/hosts/world/filesystem/default.nix b/hosts/world/filesystem/default.nix new file mode 100644 index 0000000..f751038 --- /dev/null +++ b/hosts/world/filesystem/default.nix @@ -0,0 +1,45 @@ +{ + config = { + boot.initrd.luks.devices."cryptroot".device = + "/dev/disk/by-uuid/10318654-ed20-43f6-885d-35366a427581"; + fileSystems = { + "/boot" = { + device = "/dev/disk/by-uuid/5D7D-FC52"; + fsType = "vfat"; + }; + + "/" = { + device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; + fsType = "btrfs"; + options = [ + "compress=zstd" + "noatime" + ]; + }; + "/nix" = { + device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; + fsType = "btrfs"; + options = [ + "subvol=nix" + "compress=zstd" + "noatime" + ]; + }; + "/home" = { + device = "/dev/disk/by-uuid/e353013b-8ac7-40ed-80f2-ddbea21b8d5e"; + fsType = "btrfs"; + options = [ + "subvol=home" + "compress=zstd" + "noatime" + ]; + }; + }; + # swapDevices = [ + # { + # device = "/swap/swapfile"; + # size = (1024 * 16) + (1024 * 2); + # } + # ]; + }; +} diff --git a/hosts/world/hardware-configuration.nix b/hosts/world/hardware-configuration.nix new file mode 100644 index 0000000..ee5c934 --- /dev/null +++ b/hosts/world/hardware-configuration.nix @@ -0,0 +1,48 @@ +{ + config, + lib, + modulesPath, + ... +}: +{ + imports = [ + # (modulesPath + "/installer/cd-dvd/installation-cd-minimal.nix") + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + boot = { + initrd = { + availableKernelModules = [ + "xhci_pci" + "ahci" + "nvme" + "usb_storage" + "sd_mod" + "rtsx_pci_sdmmc" + ]; + kernelModules = [ ]; + }; + kernelModules = [ "kvm-intel" ]; + blacklistedKernelModules = [ + "nouveau" + "nvidia" + "nvidia_drm" + "nvidia_modeset" + ]; + + kernelParams = [ "mem_sleep_default=deep" ]; + extraModulePackages = [ ]; + extraModprobeConfig = '' + blacklist nouveau + options nouveau modeset=0 + ''; + }; + + # Earlier font setup + console.earlySetup = true; + + # Enable firmware updates via `fwupdmgr`. + services.fwupd.enable = lib.mkDefault true; + + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/hosts/world/hardware/default.nix b/hosts/world/hardware/default.nix new file mode 100644 index 0000000..c09935b --- /dev/null +++ b/hosts/world/hardware/default.nix @@ -0,0 +1 @@ +_: { imports = [ ./monitors.nix ]; } diff --git a/hosts/world/hardware/monitors.nix b/hosts/world/hardware/monitors.nix new file mode 100644 index 0000000..f29ff41 --- /dev/null +++ b/hosts/world/hardware/monitors.nix @@ -0,0 +1,16 @@ +_: { + modules.system.hardware.monitors = { + eDP-1 = { + resolution = { + x = 1920; + y = 1080; + }; + scale = 1; + refreshRate = 60; + position = { + x = 1920; + y = 0; + }; + }; + }; +} diff --git a/hosts/world/programs.nix b/hosts/world/programs.nix new file mode 100644 index 0000000..dd35220 --- /dev/null +++ b/hosts/world/programs.nix @@ -0,0 +1,41 @@ +{ + self, + pkgs, + ... +}: +{ + environment.systemPackages = builtins.attrValues { + inherit (pkgs) + calc + comma + difftastic + evince + eza + gcc + gh + grc + gparted + git + httpie + imagemagick + img2pdf + imv + inetutils + jujutsu + just + lazygit + libtool + librewolf + linuxHeaders + mpv + networkmanagerapplet + microfetch + nmap + pfetch + ripgrep + smartmontools + util-linux + wireguard-tools + ; + }; +} diff --git a/modules/home/dev/helix.hjem.nix b/modules/home/dev/helix.hjem.nix new file mode 100644 index 0000000..0cfd8b9 --- /dev/null +++ b/modules/home/dev/helix.hjem.nix @@ -0,0 +1,481 @@ +{ + lib, + pkgs, + sources, + ... +}: +let + inherit (lib.attrsets) mapAttrs' nameValuePair; + inherit (lib.meta) getExe; + + helix = pkgs.helix.overrideAttrs ( + finalAttrs: _: { + version = "25.07.2"; + src = pkgs.fetchzip { + url = "https://github.com/bloxx12/helix/releases/download/${finalAttrs.version}/helix-${finalAttrs.version}-source.tar.xz"; + hash = "sha256-ZNsQwFfPXe6oewajx1tl68W60kVo7q2SuvTgy/o1HKk="; + stripRoot = false; + }; + + doInstallCheck = false; + + cargoDeps = pkgs.rustPlatform.fetchCargoVendor { + inherit (helix) src; + hash = "sha256-3poZSvIrkx8lguxxDeNfngW6+4hH8TV/LHcZx5W5aXg="; + }; + } + ); + + toml = pkgs.formats.toml { }; + + languages = + let + inherit (lib.meta) getExe getExe'; + + nixfmt = pkgs.callPackage "${sources.nixfmt}/default.nix" { }; + + nil = pkgs.rustPlatform.buildRustPackage { + pname = "nil"; + version = "unstable"; + src = sources.nil; + cargoLock = { + lockFile = "${sources.nil}/Cargo.lock"; + allowBuiltinFetchGit = false; + }; + nativeBuildInputs = [ pkgs.nixVersions.latest ]; + + doInstallCheck = false; + meta.mainProgram = "nil"; + }; + + new-deadnix = pkgs.deadnix.overrideAttrs ( + _: _: { + version = "unstable-15-07-2025"; + src = pkgs.fetchFromGitHub { + owner = "astro"; + repo = "deadnix"; + rev = "d75457b95d7cfa82fcd60970939f76fccfce19e5"; + hash = "sha256-O/z2neAXL8JNkGosvxC+DyZnnJ8zYP9XHApxHVmlzfY="; + }; + + doInstallCheck = false; + + cargoDeps = pkgs.rustPlatform.fetchCargoVendor { + inherit (new-deadnix) src; + hash = "sha256-O8yhqyPflOvQXAA19k1XpbrHysgV5VNWLBX0l5Q5GkM="; + }; + meta.mainProgram = "nil"; + } + ); + in + { + language = + let + mark = lang: { + command = getExe pkgs.deno; + args = [ + "fmt" + "-" + "--ext" + lang + ]; + }; + in + [ + { + name = "bash"; + auto-format = true; + formatter = { + command = getExe pkgs.shfmt; + args = [ + "-i" + "2" + ]; + }; + } + { + name = "clojure"; + injection-regex = "(clojure|clj|edn|boot|yuck)"; + file-types = [ + "clj" + "cljs" + "cljc" + "clje" + "cljr" + "cljx" + "edn" + "boot" + "yuck" + ]; + } + { + name = "cmake"; + auto-format = true; + language-servers = [ "cmake-language-server" ]; + formatter = { + command = getExe pkgs.cmake-format; + args = [ "-" ]; + }; + } + { + name = "javascript"; + auto-format = true; + language-servers = [ + "dprint" + "typescript-language-server" + ]; + } + { + name = "json"; + formatter = mark "json"; + } + { + name = "markdown"; + auto-format = true; + formatter = mark "md"; + language-servers = [ "taplo" ]; + } + { + name = "nix"; + language-servers = [ + "nil" + "deadnix" + ]; + } + { + name = "qml"; + language-servers = [ "qmlls" ]; + } + { + name = "python"; + auto-format = true; + language-servers = [ + "basedpyright" + "ruff" + ]; + } + { + name = "typescript"; + auto-format = true; + language-servers = [ + "dprint" + "typescript-language-server" + ]; + } + { + name = "rust"; + } + { + name = "c"; + auto-format = true; + language-servers = [ "clangd" ]; + } + { + name = "zig"; + auto-format = true; + } + { + name = "c"; + } + ]; + + language-server = { + bash-language-server = { + command = getExe pkgs.bash-language-server; + args = [ "start" ]; + }; + + rust-analyzer = { + command = getExe pkgs.rust-analyzer; + config.rust-analyzer = { + checkOnSave.command = "clippy"; + procMacro.enable = true; + cargo = { + loadOutDirsFromCheck = true; + features = "all"; + }; + assist = { + preferSelf = true; + }; + check = { + command = "clippy"; + extraArgs = [ + "--" + "-W" + "clippy::pedantic" + "-W" + "clippy::nursery" + "-W" + "clippy::perf" + ]; + }; + lens = { + references = true; + methodReferences = true; + }; + completion.autoimport.enable = true; + experimental.procAttrMacros = true; + interpret.tests = true; + }; + }; + + clangd = { + command = "${pkgs.clang-tools}/bin/clangd"; + clangd.fallbackFlags = [ "-std=c++2b" ]; + }; + + cmake-language-server = { + command = getExe pkgs.cmake-language-server; + }; + + deno-lsp = { + command = getExe pkgs.deno; + args = [ "lsp" ]; + environment.NO_COLOR = "1"; + config.deno = { + enable = true; + lint = true; + unstable = true; + suggest = { + completeFunctionCalls = false; + imports = { + hosts."https://deno.land" = true; + }; + }; + inlayHints = { + enumMemberValues.enabled = true; + functionLikeReturnTypes.enabled = true; + parameterNames.enabled = "all"; + parameterTypes.enabled = true; + propertyDeclarationTypes.enabled = true; + variableTypes.enabled = true; + }; + }; + }; + dprint = { + command = getExe pkgs.dprint; + args = [ "lsp" ]; + }; + + nil = { + command = getExe nil; + config.nil = { + formatting.command = [ "${getExe nixfmt}" ]; + diagnostics = { + bindingEndHintMinLines = 10; + }; + nix.flake = { + autoArchive = true; + autoEvalInputs = true; + nixpkgsInputName = "nixpkgs"; + }; + }; + }; + deadnix = { + command = getExe new-deadnix; + }; + + typescript-language-server = { + command = getExe pkgs.typescript-language-server; + args = [ "--stdio" ]; + config = { + typescript-language-server.source = { + addMissingImports.ts = true; + fixAll.ts = true; + organizeImports.ts = true; + removeUnusedImports.ts = true; + sortImports.ts = true; + }; + }; + }; + ruff = { + command = getExe pkgs.ruff; + args = [ "server" ]; + }; + + qmlls.command = getExe' pkgs.kdePackages.qtdeclarative "qmlls"; + + basedpyright.command = "${pkgs.basedpyright}/bin/basedpyright-langserver"; + + vscode-css-language-server = { + command = "${pkgs.vscode-langservers-extracted}/bin/vscode-css-language-server"; + args = [ "--stdio" ]; + config = { + provideFormatter = true; + css.validate.enable = true; + scss.validate.enable = true; + }; + }; + zls = { + command = getExe pkgs.zls; + config = { + enable_build_on_save = true; + build_on_save_args = [ + "check" + "-fincremental" + "--watch" + ]; + enable_autofix = false; + warn_style = true; + highlight_global_var_declarations = true; + }; + }; + }; + }; + + themes = { + rose_pine_transparent = { + inherits = "rose_pine"; + "ui.background" = { }; + }; + rose_pine_dawn_transparent = { + inherits = "rose_pine_dawn"; + "ui.background" = { }; + }; + nightfox_transparent = { + inherits = "nightfox"; + "ui.background" = { }; + }; + nord_transparent = { + inherits = "nord"; + "ui.background" = { }; + }; + }; + + settings = { + theme = "gruvbox_dark_hard"; + editor = { + cursorline = true; + color-modes = true; + true-color = true; + indent-guides.render = true; + lsp = { + enable = true; + auto-signature-help = true; + display-inlay-hints = true; + display-messages = true; + display-progress-messages = true; + snippets = true; + }; + file-picker = { + hidden = false; + }; + line-number = "relative"; + completion-timeout = 5; + clipboard-provider = "wayland"; + + completion-trigger-len = 1; + completion-replace = true; + mouse = true; + bufferline = "multiple"; + popup-border = "none"; + soft-wrap.enable = true; + word-completion = { + enable = true; + trigger-length = 2; + }; + cursor-shape = { + insert = "bar"; + normal = "block"; + select = "underline"; + }; + statusline = { + left = [ + "spinner" + "diagnostics" + "file-name" + ]; + right = [ + "file-base-name" + "position" + ]; + diagnostics = [ + "warning" + "error" + ]; + workspace-diagnostics = [ + "warning" + "error" + ]; + }; + gutters.layout = [ + "diff" + "diagnostics" + "line-numbers" + ]; + inline-diagnostics = { + cursor-line = "hint"; + other-lines = "error"; + }; + }; + keys = { + normal = { + space = { + g = [ + ":new" + ":buffer-close!" + ":redraw" + ]; + i = ":toggle lsp.display-inlay-hints"; + }; + esc = [ + "collapse_selection" + "keep_primary_selection" + "normal_mode" + ]; + A-H = "goto_previous_buffer"; + A-L = "goto_next_buffer"; + A-w = ":buffer-close"; + A-f = ":format"; + A-r = ":reload"; + A-x = "extend_to_line_bounds"; + X = [ + "extend_line_up" + "extend_to_line_bounds" + ]; + ";" = "flip_selections"; + "A-;" = "collapse_selection"; + + # Kakoune-like config + H = "extend_char_left"; + J = "extend_line_down"; + K = "extend_line_up"; + L = "extend_char_right"; + }; + select = { + A-x = "extend_to_line_bounds"; + X = [ + "extend_line_up" + "extend_to_line_bounds" + ]; + g = { + e = "goto_file_end"; + }; + }; + }; + }; +in +{ + packages = builtins.attrValues { + inherit helix; + inherit (pkgs) + tinymist + taplo + kdlfmt + gopls + ; + }; + + files = { + ".config/helix/config.toml".source = toml.generate "helix-config.toml" settings; + ".config/helix/languages.toml".source = toml.generate "helix-languages.toml" languages; + + } + // mapAttrs' ( + name: value: + nameValuePair ".config/helix/themes/${name}.toml" { + source = toml.generate "helix-theme-${name}.toml" value; + } + ) themes; + +} diff --git a/modules/home/hjem.mod.nix b/modules/home/hjem.mod.nix new file mode 100644 index 0000000..43838e6 --- /dev/null +++ b/modules/home/hjem.mod.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + pkgs, + sources, + ... +}: +let + inherit (builtins) filter; + inherit (config.meta.mainUser) username; + inherit (lib.modules) mkForce; + inherit (lib.filesystem) listFilesRecursive; + inherit (lib.strings) hasSuffix; + +in +{ + + imports = [ (sources.hjem + "/modules/nixos") ]; + + config = { + hjem = { + clobberByDefault = true; + linker = pkgs.smfh; + users.${username} = { + enable = true; + user = username; + directory = config.users.users.${username}.home; + clobberFiles = mkForce true; + }; + extraModules = (listFilesRecursive ./.) |> filter (hasSuffix ".hjem.nix"); + specialArgs = { + inherit sources; + }; + }; + }; +} diff --git a/modules/home/nushell/completions.nu b/modules/home/nushell/completions.nu new file mode 100644 index 0000000..8b13789 --- /dev/null +++ b/modules/home/nushell/completions.nu @@ -0,0 +1 @@ + diff --git a/modules/home/nushell/config.nu b/modules/home/nushell/config.nu new file mode 100644 index 0000000..5bc1380 --- /dev/null +++ b/modules/home/nushell/config.nu @@ -0,0 +1,309 @@ +#! /usr/bin/env nu + +$env.config = { + bracketed_paste: true + buffer_editor: "hx" + datetime_format: {} + edit_mode: vi + error_style: fancy + float_precision: 2 + footer_mode: 25 + render_right_prompt_on_last_line: false + show_banner: false + use_ansi_coloring: true + use_kitty_protocol: true + + shell_integration: { + osc2: false + osc7: true + osc8: true + osc9_9: false + osc133: true + osc633: true + reset_application_mode: true + } +} + +$env.config.color_config = { + binary: '#b48ead' + block: '#81a1c1' + cell-path: '#e5e9f0' + closure: '#88c0d0' + custom: '#8fbcbb' + duration: '#ebcb8b' + float: '#bf616a' + glob: '#8fbcbb' + int: '#b48ead' + list: '#88c0d0' + nothing: '#bf616a' + range: '#ebcb8b' + record: '#88c0d0' + string: '#a3be8c' + + bool: {|| if $in { '#88c0d0' } else { '#ebcb8b' } } + + datetime: {|| (date now) - $in | + if $in < 1hr { + { fg: '#bf616a' attr: 'b' } + } else if $in < 6hr { + '#bf616a' + } else if $in < 1day { + '#ebcb8b' + } else if $in < 3day { + '#a3be8c' + } else if $in < 1wk { + { fg: '#a3be8c' attr: 'b' } + } else if $in < 6wk { + '#88c0d0' + } else if $in < 52wk { + '#81a1c1' + } else { 'dark_gray' } + } + + filesize: {|e| + if $e == 0b { + '#e5e9f0' + } else if $e < 1mb { + '#88c0d0' + } else {{ fg: '#81a1c1' }} + } + + shape_and: { fg: '#b48ead' attr: 'b' } + shape_binary: { fg: '#b48ead' attr: 'b' } + shape_block: { fg: '#81a1c1' attr: 'b' } + shape_bool: '#88c0d0' + shape_closure: { fg: '#88c0d0' attr: 'b' } + shape_custom: '#a3be8c' + shape_datetime: { fg: '#88c0d0' attr: 'b' } + shape_directory: '#88c0d0' + shape_external: '#88c0d0' + shape_external_resolved: '#88c0d0' + shape_externalarg: { fg: '#a3be8c' attr: 'b' } + shape_filepath: '#88c0d0' + shape_flag: { fg: '#81a1c1' attr: 'b' } + shape_float: { fg: '#bf616a' attr: 'b' } + shape_garbage: { fg: '#FFFFFF' bg: '#FF0000' attr: 'b' } + shape_glob_interpolation: { fg: '#88c0d0' attr: 'b' } + shape_globpattern: { fg: '#88c0d0' attr: 'b' } + shape_int: { fg: '#b48ead' attr: 'b' } + shape_internalcall: { fg: '#88c0d0' attr: 'b' } + shape_keyword: { fg: '#b48ead' attr: 'b' } + shape_list: { fg: '#88c0d0' attr: 'b' } + shape_literal: '#81a1c1' + shape_match_pattern: '#a3be8c' + shape_matching_brackets: { attr: 'u' } + shape_nothing: '#bf616a' + shape_operator: '#ebcb8b' + shape_or: { fg: '#b48ead' attr: 'b' } + shape_pipe: { fg: '#b48ead' attr: 'b' } + shape_range: { fg: '#ebcb8b' attr: 'b' } + shape_raw_string: { fg: '#8fbcbb' attr: 'b' } + shape_record: { fg: '#88c0d0' attr: 'b' } + shape_redirection: { fg: '#b48ead' attr: 'b' } + shape_signature: { fg: '#a3be8c' attr: 'b' } + shape_string: '#a3be8c' + shape_string_interpolation: { fg: '#88c0d0' attr: 'b' } + shape_table: { fg: '#81a1c1' attr: 'b' } + shape_vardecl: { fg: '#81a1c1' attr: 'u' } + shape_variable: '#b48ead' + + foreground: '#e5e9f0' + background: '#2e3440' + cursor: '#e5e9f0' + + empty: '#81a1c1' + header: { fg: '#a3be8c' attr: 'b' } + hints: '#4c566a' + leading_trailing_space_bg: { attr: 'n' } + row_index: { fg: '#a3be8c' attr: 'b' } + search_result: { fg: '#bf616a' bg: '#e5e9f0' } + separator: '#e5e9f0' +} + +$env.config.ls = { + clickable_links: true + use_ls_colors: true +} + +$env.config.rm.always_trash = true + +$env.config.table = { + header_on_separator: true + footer_inheritance: true + index_mode: always + mode: compact + missing_value_symbol: kek + padding: {left: 1 right: 1} + show_empty: false + trim: { + methodology: wrapping + truncating_suffix: "..." + wrapping_try_keep_words: true + } +} + +$env.config.explore = { + command_bar_text: {fg: "#C4C9C6"} + highlight: {fg: black bg: yellow} + status: { + error: {fg: white bg: red} + warn: {} + info: {} + } + status_bar_background: {fg: "#1D1F21" bg: "#C4C9C6"} + table: { + split_line: {fg: "#404040"} + selected_cell: {bg: light_blue} + selected_row: {} + selected_column: {} + } +} + +$env.config.history = { + file_format: sqlite + isolation: false + max_size: 100_000 + sync_on_enter: true +} + +$env.config.cursor_shape = { + vi_insert: line + vi_normal: block +} + +$env.config.hooks = { + command_not_found: {|| } + + pre_execution: [ + { + let prompt = commandline | str trim + + if ($prompt | is-empty) { + return + } + + print $"(ansi title)($prompt) — nu(char bel)" + } + ] + + pre_prompt: [ + {|| + if not ($env.PWD | path join .envrc | path exists) { + return + } + if (which direnv | is-empty) { + return + } + + direnv export json | from json | default {} | load-env + $env.PATH = $env.PATH | split row (char env_sep) + } + ] +} + +let menus = [ + { + name: completion_menu + only_buffer_difference: false + marker: $"(ansi yellow)╋ " + type: { + layout: ide + min_completion_width: 0 + max_completion_width: 150 + max_completion_height: 25 + padding: 0 + border: false + cursor_offset: 0 + description_mode: "prefer_right" + min_description_width: 0 + max_description_width: 50 + max_description_height: 10 + description_offset: 1 + correct_cursor_pos: true + } + style: { + text: white + selected_text: white_reverse + description_text: yellow + match_text: { attr: u } + selected_match_text: { attr: ur } + } + } + { + name: history_menu + only_buffer_difference: true + marker: $env.PROMPT_INDICATOR + type: { + layout: list + page_size: 10 + } + style: { + text: white + selected_text: white_reverse + } + } +] + +$env.config.menus = $env.config.menus +| where name not-in ($menus | get name) +| append $menus + +$env.config.keybindings ++= [ + { + name: copy_commandline + modifier: alt + keycode: char_c + mode: [vi_normal vi_insert] + event: { + send: executehostcommand + cmd: 'commandline | nu-highlight | $"```ansi\n($in)\n```" | wl-copy $in' + } + } +] + +let env_vars_file = '/tmp/nushell-env-vars' +if not ($env_vars_file | path exists) { + open /etc/profile + | lines + | select 11 + | str trim + | split column ' ' del path + | get path.0 + | open $in + | str trim + | lines + | parse 'export {name}="{value}"' + | transpose --header-row --as-record + | tee { load-env $in } + | to nuon + | save --force $env_vars_file +} else { + open $env_vars_file + | from nuon + | load-env $in +} + +def switch [] { + nh os switch --file ($env.NH_FLAKE | path join default.nix) (open /etc/hostname | str trim) +} + + +def --env y [...args] { + let tmp = (mktemp -t "yazi-cwd.XXXXXX") + yazi ...$args --cwd-file $tmp + let cwd = (open $tmp) + if $cwd != "" and $cwd != $env.PWD { + cd $cwd + } + rm -fp $tmp +} + +# fix sudo by prepending /run/wrappers/bin to the PATH. +$env.PATH = ($env.PATH | split row (char esep) | prepend '/run/wrappers/bin') +$env.PATH = ($env.PATH | split row (char esep) | prepend '/etc/profiles/per-user/cr/bin') + +carapace _carapace nushell +| save -f ($nu.user-autoload-dirs | path join carapace.nu) + +source ./prompt.nu +source ./zoxide.nu diff --git a/modules/home/nushell/nu.hjem.nix b/modules/home/nushell/nu.hjem.nix new file mode 100644 index 0000000..6ffa828 --- /dev/null +++ b/modules/home/nushell/nu.hjem.nix @@ -0,0 +1,22 @@ +{ + pkgs, + ... +}: +{ + + packages = with pkgs; [ + nushell + inshellisense + carapace + ]; + environment.sessionVariables = { + CARAPACE_BRIDGES = "inshellisense,carapace,clap,bash"; + CARAPACE_MATCH = 1; + }; + + files = { + ".config/nushell/config.nu".source = ./config.nu; + ".config/nushell/prompt.nu".source = ./prompt.nu; + ".config/nushell/zoxide.nu".source = ./zoxide.nu; + }; +} diff --git a/modules/home/nushell/prompt.nu b/modules/home/nushell/prompt.nu new file mode 100644 index 0000000..570ce4a --- /dev/null +++ b/modules/home/nushell/prompt.nu @@ -0,0 +1,73 @@ +use std null_device + +export-env { + load-env { + PROMPT_COMMAND: {|| + let exit_code = $env.LAST_EXIT_CODE + mut path_segment = $env.PWD | path basename + + let exit_code_segment = if ($exit_code == 0) { + "" + } else { + $"(ansi yellow)━┫(ansi red)($exit_code)(ansi yellow)┣━" + } + + [$"(ansi yellow)┏" $exit_code_segment "━ " $path_segment "\n"] | str join + } + TRANSIENT_PROMPT_COMMAND: {|| + let path_segment = $env.PWD | path basename + + let exit_code_segment = if ($env.LAST_EXIT_CODE == 0) { + "" + } else { + $"(ansi yellow)━┫(ansi red)($env.LAST_EXIT_CODE)(ansi yellow)┣━" + } + + [$"(ansi yellow)━" $exit_code_segment "━ " $path_segment] | str join + } + PROMPT_INDICATOR_VI_INSERT: $"(ansi yellow)┃ " + PROMPT_INDICATOR_VI_NORMAL: $"(ansi yellow)┋ " + PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " + TRANSIENT_PROMPT_INDICATOR_VI_INSERT: " " + TRANSIENT_PROMPT_INDICATOR_VI_NORMAL: " " + TRANSIENT_PROMPT_MULTILINE_INDICATOR: $"(ansi yellow)┃ " + + config: ( + $env.config? | default {} | merge { + render_right_prompt_on_last_line: true + } + ) + + PROMPT_COMMAND_RIGHT: {|| + let jj_status = try { + jj --quiet --color always --ignore-working-copy log --no-graph --revisions @ --template ' + separate( + " ", + if(empty, label("empty", "(empty)")), + coalesce( + surround( + "\"", + "\"", + if( + description.first_line().substr(0, 24).starts_with(description.first_line()), + description.first_line().substr(0, 24), + description.first_line().substr(0, 23) ++ "…" + ) + ), + label(if(empty, "empty"), description_placeholder) + ), + bookmarks.join(", "), + change_id.shortest(), + commit_id.shortest(), + if(conflict, label("conflict", "(conflict)")), + if(divergent, label("divergent prefix", "(divergent)")), + if(hidden, label("hidden prefix", "(hidden)")), + ) + ' err> $null_device + } catch { + "" + } + $jj_status + } + } +} diff --git a/modules/home/nushell/zoxide.nu b/modules/home/nushell/zoxide.nu new file mode 100644 index 0000000..a2bf5d7 --- /dev/null +++ b/modules/home/nushell/zoxide.nu @@ -0,0 +1,54 @@ +# Initialize hook to add new entries to the database. +export-env { + $env.config = ( + $env.config? + | default {} + | upsert hooks { default {} } + | upsert hooks.env_change { default {} } + | upsert hooks.env_change.PWD { default [] } + ) + let __zoxide_hooked = ( + $env.config.hooks.env_change.PWD | any { try { get __zoxide_hook } catch { false } } + ) + if not $__zoxide_hooked { + $env.config.hooks.env_change.PWD = ($env.config.hooks.env_change.PWD | append { + __zoxide_hook: true, + code: {|_, dir| zoxide add -- $dir} + }) + } +} + +def zoxide_completions [context: string] { + let parts = $context | split row " " | skip 1 + { + options: { + sort: false, + completion_algorithm: substring, + case_sensitive: false, + }, + completions: (^zoxide query --list --exclude $env.PWD -- ...$parts | lines | first 10) + } +} + +# Jump to a directory using only keywords. +def --env --wrapped __zoxide_z [...rest: string@zoxide_completions] { + let path = match $rest { + [] => {'~'}, + [ '-' ] => {'-'}, + [ $arg ] if ($arg | path expand | path type) == 'dir' => {$arg} + _ => { + zoxide query --exclude $env.PWD -- ...$rest | str trim -r -c "\n" + } + } + cd $path +} + +# Jump to a directory using interactive search. +def --env --wrapped __zoxide_zi [...rest:string] { + cd $'(zoxide query --interactive -- ...$rest | str trim -r -c "\n")' +} + +# ============================================================================= +alias z = __zoxide_z +alias zi = __zoxide_zi + diff --git a/modules/home/programs/btop.hjem.nix b/modules/home/programs/btop.hjem.nix new file mode 100644 index 0000000..a956a09 --- /dev/null +++ b/modules/home/programs/btop.hjem.nix @@ -0,0 +1,40 @@ +{ + lib, + pkgs, + ... +}: +let + inherit (builtins) attrValues; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.strings) concatStringsSep; + + btop-settings = { + truecolor = "True"; + vim_keys = "True"; + rounded_corners = "True"; + update_ms = "100"; + graph_symbol = "braille"; + cpu_single_graph = "True"; + clock_format = "%X"; + use_fstab = "True"; + io_mode = "True"; + net_sync = "True"; + net_iface = "enp4s0"; + log_level = "ERROR"; + color_theme = "gruvbox_dark"; + }; + + btop-no-desktop-entry = pkgs.btop.overrideAttrs (prev: { + postInstall = '' + ${prev.postInstall or ""} + rm -rf $out/share/applications/*.desktop + ''; + }); + +in +{ + packages = attrValues { inherit btop-no-desktop-entry; }; + files.".config/btop/btop.conf".text = + concatStringsSep "\n" <| mapAttrsToList (name: value: "${name} = ${toString value}") btop-settings; + +} diff --git a/modules/home/programs/ghostty.hjem.nix b/modules/home/programs/ghostty.hjem.nix new file mode 100644 index 0000000..c76b7c5 --- /dev/null +++ b/modules/home/programs/ghostty.hjem.nix @@ -0,0 +1,69 @@ +{ + lib, + osConfig, + pkgs, + ... +}: +let + inherit (lib.lists) elem; + inherit (lib.meta) getExe; + inherit (lib.attrsets) mapAttrsToList; + inherit (lib.strings) concatStringsSep; + + inherit (osConfig.meta.mainUser.defaultShell) name package; + + # Shell integration for ghostty only supports + # bash, fish and zsh for now. + shell-integration = + if + elem name [ + "bash" + "fish" + "zsh" + ] + then + name + else + "none"; + + ghostty-settings = { + font-size = 14; + font-family = "JetBrainsMonoNerdFont"; + + app-notifications = "no-clipboard-copy"; + background-opacity = 1.0; + bold-is-bright = "true"; + confirm-close-surface = "false"; + cursor-style-blink = "false"; + gtk-single-instance = "true"; + gtk-tabs-location = "bottom"; + gtk-wide-tabs = false; + mouse-hide-while-typing = "true"; + resize-overlay-duration = "0s"; + shell-integration-features = "cursor,sudo,no-title"; + term = "xterm-256color"; + theme = "GruvboxDarkHard"; + window-decoration = "none"; + window-padding-balance = true; + window-padding-x = 8; + window-padding-y = 8; + window-theme = "ghostty"; + cursor-style = "block"; + + # Whether to automatically copy selected text to the clipboard. true will prefer to copy to the selection clipboard, otherwise it will copy to the system clipboard. + # The value clipboard will always copy text to the selection clipboard as well as the system clipboard. + copy-on-select = "clipboard"; + inherit shell-integration; + + command = getExe package; + }; +in +{ + packages = builtins.attrValues { + inherit (pkgs) ghostty; + }; + + files.".config/ghostty/config".text = + concatStringsSep "\n" + <| mapAttrsToList (name: value: "${name} = ${toString value}") ghostty-settings; +} diff --git a/modules/options/system/monitors.nix b/modules/options/system/monitors.mod.nix similarity index 92% rename from modules/options/system/monitors.nix rename to modules/options/system/monitors.mod.nix index e65a481..b42d25d 100644 --- a/modules/options/system/monitors.nix +++ b/modules/options/system/monitors.mod.nix @@ -1,10 +1,18 @@ -{lib, ...}: let +{ lib, ... }: +let inherit (lib.options) mkOption; - inherit (lib.types) submodule int ints number attrsOf; -in { + inherit (lib.types) + submodule + int + ints + number + attrsOf + ; +in +{ options.modules.system.hardware.monitors = mkOption { description = "\n List of monitors to use\n "; - default = {}; + default = { }; type = attrsOf (submodule { options = { resolution = mkOption { diff --git a/modules/options/system/networking/default.nix b/modules/options/system/networking/default.nix deleted file mode 100644 index 68fa733..0000000 --- a/modules/options/system/networking/default.nix +++ /dev/null @@ -1,7 +0,0 @@ -{lib, ...}: let - inherit (lib.options) mkEnableOption; -in { - options.modules.system.networking = { - nftbles.enable = mkEnableOption "Nftables firewall"; - }; -} diff --git a/modules/options/system/module.nix b/modules/options/system/options.mod.nix similarity index 60% rename from modules/options/system/module.nix rename to modules/options/system/options.mod.nix index bce1197..a211afe 100644 --- a/modules/options/system/module.nix +++ b/modules/options/system/options.mod.nix @@ -2,49 +2,26 @@ config, lib, ... -}: let +}: +let inherit (builtins) elemAt; inherit (lib.options) mkOption mkEnableOption; - inherit (lib.types) enum listOf str nullOr bool package; -in { - imports = [ - # configuration options for nixos activation scripts - # ./activation.nix - - # boot/impermanence mounts - # ./boot.nix - # ./impermanence.nix - - # network and overall hardening - ./networking - # ./security.nix - # ./encryption.nix - - # filesystems - # ./fs.nix - - # package and program related options - # ./services - ./programs - - # monitor configuration - ./monitors.nix - ]; + inherit (lib.types) + enum + listOf + str + nullOr + bool + ; + inherit (lib.lists) elem; + inherit (config.modules.system) systemType; +in +{ options.modules.system = { - mainUser = mkOption { - type = enum config.modules.system.users; - default = elemAt config.modules.system.users 0; - description = '' - The username of the main user for your system. - - In case of a multiple systems, this will be the user with priority in ordered lists and enabled options. - ''; - }; - users = mkOption { type = listOf str; - default = ["charlie"]; + default = [ "cr" ]; description = "A list of users on the system."; }; @@ -57,10 +34,37 @@ in { ''; }; + systemType = mkOption { + type = nullOr (enum [ + "desktop" + "laptop" + "server" + ]); + default = null; + description = '' + The type of the current system. This is used to determine whether things like graphical + environments and power-saving programs should be installed or not. + ''; + }; + + isGraphical = mkOption { + type = bool; + default = elem systemType [ + "desktop" + "laptop" + ]; + description = '' + Whether the current system is a graphical system. + ''; + }; + yubikeySupport = { enable = mkEnableOption "yubikey support"; deviceType = mkOption { - type = nullOr (enum ["NFC5" "nano"]); + type = nullOr (enum [ + "NFC5" + "nano" + ]); default = null; description = "A list of device models to enable Yubikey support for"; }; @@ -72,6 +76,7 @@ in { impermanence = { enable = mkEnableOption "Enable Impermanence"; }; + video = { enable = mkEnableOption "video drivers and programs that require a graphical user interface"; nvidia = mkEnableOption "Nvidia graphics drivers"; @@ -89,18 +94,9 @@ in { enable = mkEnableOption "printing"; extraDrivers = mkOption { type = listOf str; - default = []; + default = [ ]; description = "A list of extra drivers to enable for printing"; }; - - "3d" = { - enable = mkEnableOption "3D printing suite"; - extraPrograms = mkOption { - type = listOf package; - default = []; - description = "A list of extra programs to enable for 3D printing"; - }; - }; }; }; } diff --git a/modules/options/system/programs/default.nix b/modules/options/system/programs.mod.nix similarity index 73% rename from modules/options/system/programs/default.nix rename to modules/options/system/programs.mod.nix index 403de42..04f6b85 100644 --- a/modules/options/system/programs/default.nix +++ b/modules/options/system/programs.mod.nix @@ -1,7 +1,9 @@ -{lib, ...}: let +{ lib, ... }: +let inherit (lib.types) str enum; inherit (lib.options) mkEnableOption mkOption; -in { +in +{ options.modules.system.programs = { editors = { helix.enable = mkEnableOption "Helix text editor"; @@ -27,23 +29,42 @@ in { }; default = { terminal = mkOption { - type = enum ["foot" "kitty"]; + type = enum [ + "foot" + "kitty" + ]; default = "foot"; }; fileManager = mkOption { - type = enum ["thunar" "dolphin" "nemo"]; + type = enum [ + "thunar" + "dolphin" + "nemo" + ]; default = "thunar"; }; browser = mkOption { - type = enum ["firefox" "librewolf" "chromium"]; + type = enum [ + "firefox" + "librewolf" + "chromium" + ]; default = "firefox"; }; editor = mkOption { - type = enum ["neovim" "helix" "emacs"]; + type = enum [ + "neovim" + "helix" + "emacs" + ]; default = "emacs"; }; launcher = mkOption { - type = enum ["anyrun" "rofi" "wofi"]; + type = enum [ + "anyrun" + "rofi" + "wofi" + ]; default = "anyrun"; }; }; diff --git a/modules/other/git.nix b/modules/other/git.mod.nix similarity index 69% rename from modules/other/git.nix rename to modules/other/git.mod.nix index c5b31c3..6e56d9f 100644 --- a/modules/other/git.nix +++ b/modules/other/git.mod.nix @@ -1,7 +1,8 @@ -{pkgs, ...}: let - key = - pkgs.writeText "signingkey" "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAWEDj/Yib6Mqs016jx7rtecWpytwfVl28eoHtPYCM9TVLq81VIHJSN37lbkc/JjiXCdIJy2Ta3A3CVV5k3Z37NbgAu23oKA2OcHQNaRTLtqWlcBf9fk9suOkP1A3NzAqzivFpBnZm3ytaXwU8LBJqxOtNqZcFVruO6fZxJtg2uE34mAw=="; -in { +{ pkgs, ... }: +let + key = pkgs.writeText "signingkey" "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAWEDj/Yib6Mqs016jx7rtecWpytwfVl28eoHtPYCM9TVLq81VIHJSN37lbkc/JjiXCdIJy2Ta3A3CVV5k3Z37NbgAu23oKA2OcHQNaRTLtqWlcBf9fk9suOkP1A3NzAqzivFpBnZm3ytaXwU8LBJqxOtNqZcFVruO6fZxJtg2uE34mAw=="; +in +{ programs.git = { enable = true; lfs.enable = true; diff --git a/modules/other/module.nix b/modules/other/module.nix deleted file mode 100644 index 6ddf05f..0000000 --- a/modules/other/module.nix +++ /dev/null @@ -1,8 +0,0 @@ -_: { - imports = [ - ./system.nix - ./xdg.nix - ./git.nix - ./users.nix - ]; -} diff --git a/modules/other/system.nix b/modules/other/system.mod.nix similarity index 89% rename from modules/other/system.nix rename to modules/other/system.mod.nix index d533cf5..dbec1ac 100644 --- a/modules/other/system.nix +++ b/modules/other/system.mod.nix @@ -1,7 +1,9 @@ -{lib, ...}: let +{ lib, ... }: +let inherit (lib.options) mkOption; inherit (lib.types) str; -in { +in +{ options.modules.other.system = { username = mkOption { description = "username for this system"; diff --git a/modules/other/users.nix b/modules/other/users.mod.nix similarity index 66% rename from modules/other/users.nix rename to modules/other/users.mod.nix index 1fa4711..091e76c 100644 --- a/modules/other/users.nix +++ b/modules/other/users.mod.nix @@ -2,19 +2,21 @@ config, lib, pkgs, - self, + sources, ... -}: let +}: +let inherit (builtins) elemAt; inherit (lib.options) mkOption; - inherit (lib.types) listOf str; - + inherit (lib.types) listOf str package; inherit (config.meta.mainUser) username; -in { +in +{ + imports = [ (sources.hjem + "/modules/nixos") ]; options.meta = { users = mkOption { type = listOf str; - default = ["cr"]; + default = [ "cr" ]; description = '' A list of users on a system. ''; @@ -27,17 +29,36 @@ in { The main user for each system. This is the first element of the list of users by default. ''; }; + gitSigningKey = mkOption { type = str; description = '' The main user's git signing key, used to automatically sing git commits with this key ''; default = '' - ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAWEDj/Yib6Mqs016jx7rtecWpytwfVl28eoHtPYCM9TVLq81VIHJSN37lbkc/JjiXCdIJy2Ta3A3CVV5k3Z37NbgAu23oKA2OcHQNaRTLtqWlcBf9fk9suOkP1A3NzAqzivFpBnZm3ytaXwU8LBJqxOtNqZcFVruO6fZxJtg2uE34mAw== ''; + ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAWEDj/Yib6Mqs016jx7rtecWpytwfVl28eoHtPYCM9TVLq81VIHJSN37lbkc/JjiXCdIJy2Ta3A3CVV5k3Z37NbgAu23oKA2OcHQNaRTLtqWlcBf9fk9suOkP1A3NzAqzivFpBnZm3ytaXwU8LBJqxOtNqZcFVruO6fZxJtg2uE34mAw== + ''; + }; + + # TODO: clean this up and move it somewhere else. + defaultShell = { + name = mkOption { + type = str; + default = "nushell"; + description = '' + The default shell of a user. This is not the main system shell, but the shell used in terminals. + ''; + }; + package = mkOption { + type = package; + default = pkgs.nushell; + }; }; }; }; config = { + # environment.shells = [ pkgs.nushell ]; + programs.zsh.enable = true; users = { mutableUsers = true; users = { @@ -52,10 +73,8 @@ in { "nix" "docker" ]; - shell = self.packages.${pkgs.stdenv.system}.fish; - # hashedPasswordFile = "/etc/passwords/cr"; + shell = pkgs.zsh; }; - # root.hashedPasswordFile = "/persist/passwords/root"; }; }; }; diff --git a/modules/other/xdg.mod.nix b/modules/other/xdg.mod.nix new file mode 100644 index 0000000..a08b632 --- /dev/null +++ b/modules/other/xdg.mod.nix @@ -0,0 +1,74 @@ +{ + config, + pkgs, + ... +}: +let + inherit (config.meta.mainUser) username; + + primary_browser = "Librewolf.desktop"; + mail_client = "thunderbird.desktop"; + file_manager = "nautilus.desktop"; + media_player = "mpv.desktop"; + image_viewer = "imv.desktop"; + text_editor = "helix.desktop"; + terminal = "foot.desktop"; + pdf_viewer = "zathura.desktop"; +in +{ + environment = { + systemPackages = [ pkgs.xdg-utils ]; + variables = { + TERMINAL = "${terminal}"; + XDG_CACHE_HOME = "/home/${username}/.config"; + }; + }; + + xdg = { + autostart.enable = true; + menus.enable = true; + icons.enable = true; + mime = { + enable = true; + defaultApplications = { + "text/html" = [ primary_browser ]; + "x-scheme-handler/http" = [ primary_browser ]; + "x-scheme-handler/https" = [ primary_browser ]; + "x-scheme-handler/about" = [ primary_browser ]; + "x-scheme-handler/unknown" = [ primary_browser ]; + "x-scheme-handler/mailto" = [ mail_client ]; + "message/rfc822" = [ mail_client ]; + "x-scheme-handler/mid" = [ mail_client ]; + "inode/directory" = [ file_manager ]; + "audio/mp3" = [ media_player ]; + "audio/ogg" = [ media_player ]; + "audio/mpeg" = [ media_player ]; + "audio/aac" = [ media_player ]; + "audio/opus" = [ media_player ]; + "audio/wav" = [ media_player ]; + "audio/webm" = [ media_player ]; + "audio/3gpp" = [ media_player ]; + "audio/3gpp2" = [ media_player ]; + "video/mp4" = [ media_player ]; + "video/x-msvideo" = [ media_player ]; + "video/mpeg" = [ media_player ]; + "video/ogg" = [ media_player ]; + "video/mp2t" = [ media_player ]; + "video/webm" = [ media_player ]; + "video/3gpp" = [ media_player ]; + "video/3gpp2" = [ media_player ]; + "image/png" = [ image_viewer ]; + "image/jpeg" = [ image_viewer ]; + "image/gif" = [ image_viewer ]; + "image/avif" = [ image_viewer ]; + "image/bmp" = [ image_viewer ]; + "image/vnd.microsoft.icon" = [ image_viewer ]; + "image/svg+xml" = [ image_viewer ]; + "image/tiff" = [ image_viewer ]; + "image/webp" = [ image_viewer ]; + "text/plain" = [ text_editor ]; + "application/pdf" = [ pdf_viewer ]; + }; + }; + }; +} diff --git a/modules/other/xdg.nix b/modules/other/xdg.nix deleted file mode 100644 index bbeeb21..0000000 --- a/modules/other/xdg.nix +++ /dev/null @@ -1,72 +0,0 @@ -{ - config, - pkgs, - ... -}: let - inherit (config.meta.mainUser) username; - - primary_browser = "Librewolf.desktop"; - mail_client = "thunderbird.desktop"; - file_manager = "nautilus.desktop"; - media_player = "mpv.desktop"; - image_viewer = "imv.desktop"; - text_editor = "helix.desktop"; - terminal = "foot.desktop"; - pdf_viewer = "sioyek.desktop"; -in { - environment = { - systemPackages = [pkgs.xdg-utils]; - sessionVariables = { - TERMINAL = "${terminal}"; - XDG_CACHE_HOME = "/home/${username}/.config"; - }; - }; - - xdg = { - autostart.enable = true; - menus.enable = true; - icons.enable = true; - mime = { - enable = true; - defaultApplications = { - "text/html" = [primary_browser]; - "x-scheme-handler/http" = [primary_browser]; - "x-scheme-handler/https" = [primary_browser]; - "x-scheme-handler/about" = [primary_browser]; - "x-scheme-handler/unknown" = [primary_browser]; - "x-scheme-handler/mailto" = [mail_client]; - "message/rfc822" = [mail_client]; - "x-scheme-handler/mid" = [mail_client]; - "inode/directory" = [file_manager]; - "audio/mp3" = [media_player]; - "audio/ogg" = [media_player]; - "audio/mpeg" = [media_player]; - "audio/aac" = [media_player]; - "audio/opus" = [media_player]; - "audio/wav" = [media_player]; - "audio/webm" = [media_player]; - "audio/3gpp" = [media_player]; - "audio/3gpp2" = [media_player]; - "video/mp4" = [media_player]; - "video/x-msvideo" = [media_player]; - "video/mpeg" = [media_player]; - "video/ogg" = [media_player]; - "video/mp2t" = [media_player]; - "video/webm" = [media_player]; - "video/3gpp" = [media_player]; - "video/3gpp2" = [media_player]; - "image/png" = [image_viewer]; - "image/jpeg" = [image_viewer]; - "image/gif" = [image_viewer]; - "image/avif" = [image_viewer]; - "image/bmp" = [image_viewer]; - "image/vnd.microsoft.icon" = [image_viewer]; - "image/svg+xml" = [image_viewer]; - "image/tiff" = [image_viewer]; - "image/webp" = [image_viewer]; - "text/plain" = [text_editor]; - "application/pdf" = [pdf_viewer]; - }; - }; - }; -} diff --git a/modules/packages/hardware.nix b/modules/packages/hardware.nix deleted file mode 100644 index 1a85c49..0000000 --- a/modules/packages/hardware.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let -in { -} diff --git a/modules/packages/module.nix b/modules/packages/module.nix deleted file mode 100644 index 23b52ec..0000000 --- a/modules/packages/module.nix +++ /dev/null @@ -1,22 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./hardware.nix - ./wayland.nix - # ./media.nix - ]; - # These are some standard packages I want to have installed on every system, regardless of type or use case. - environment.systemPackages = builtins.attrValues { - inherit - (pkgs) - calc # Calculator device - coreutils-full # All of the GNU coreutils - curl # I sometimes need to curl stuff - git # take a guess - inetutils # internet stuff I need/want on every system. - wget - unzip # zipping and unzipping stuff - zip - util-linux - ; - }; -} diff --git a/modules/packages/packages.mod.nix b/modules/packages/packages.mod.nix new file mode 100644 index 0000000..57494bd --- /dev/null +++ b/modules/packages/packages.mod.nix @@ -0,0 +1,109 @@ +{ + lib, + pkgs, + sources, + ... +}: +let + nixfmt = pkgs.callPackage "${sources.nixfmt}/default.nix" { }; + comma = pkgs.callPackage ( + _: + pkgs.rustPlatform.buildRustPackage { + pname = "comma"; + version = "unstable"; + src = sources.comma; + cargoLock = { + allowBuiltinFetchGit = true; + lockFile = "${sources.comma}/Cargo.lock"; + }; + nativeBuildInputs = [ pkgs.makeBinaryWrapper ]; + doInstallCheck = false; + + postInstall = '' + wrapProgram $out/bin/comma \ + --prefix PATH : ${ + lib.makeBinPath [ + pkgs.fzy + pkgs.nix-index-unwrapped + ] + } + ln -s $out/bin/comma $out/bin/, + ''; + } + ) { }; +in +{ + environment.systemPackages = + with pkgs; + [ + universal-android-debloater + emacs-pgtk + # better cd + zoxide + ouch + # pipe viewer + pv + # hex editor + bvi + #better ls + eza + atuin + # better cat + bat + # clipboard + # yazi + serpl + diff-so-fancy + tig + direnv + sesh + mprocs + curlie + entr + procs + sd + # mult + glow + # dua-cli + dust + iamb + kondo + # better grep + ripgrep + # IP stuff + dig + # simply the best fetch tool out there + microfetch + fzf + element + difftastic + hexyl + yazi + gnumake + asciinema + inetutils + tokei + starship + wget + cpufetch + watchman + # yt-dlp # borked check phase + tealdeer + hyperfine + imagemagick + ffmpeg-full + # catimg + timg + nmap + fd + jq + rsync + figlet + unzip + zip + ] + ++ [ + nixfmt + comma + ]; +} diff --git a/modules/packages/wayland.nix b/modules/packages/wayland.nix deleted file mode 100644 index eb0e2c3..0000000 --- a/modules/packages/wayland.nix +++ /dev/null @@ -1,15 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: { - # These are packages I only need in wayland environments, nowhere else. - environment.systemPackages = builtins.attrValues { - inherit - (pkgs) - wl-clipboard - grimblast - ; - }; -} diff --git a/modules/programs/cli/jj.mod.nix b/modules/programs/cli/jj.mod.nix new file mode 100644 index 0000000..80b06e5 --- /dev/null +++ b/modules/programs/cli/jj.mod.nix @@ -0,0 +1,139 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.meta) getExe; + + toml = pkgs.formats.toml { }; + jj-config = toml.generate "config.toml" { + user = { + name = "Bloxx12"; + email = "charlie@charlieroot.dev"; + }; + + ui = { + pager = [ + "${getExe pkgs.bat}" + "--plain" + ]; + default-command = "log"; + movement.edit = true; + + diff.tool = [ + "${getExe pkgs.difftastic}" + "--color" + "always" + "$left" + "$right" + ]; + }; + # FIXME: do this with agenix + # "--scope" = [ + # { + # "--when.repositories" = ["~/repos/projects/uni"]; + # user = { + # # TODO + # name = ""; + # email = ""; + # }; + # } + # { + # "--when.repositories" = ["~/repos/projects/uni/"]; + # user = { + # # TODO + # name = ""; + # email = ""; + # }; + # } + # ]; + git.push-new-bookmarks = true; + + signing = { + behaviour = "own"; + backend = "ssh"; + key = [ + "ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAAWEDj/Yib6Mqs016jx7rtecWpytwfVl28eoHtPYCM9TVLq81VIHJSN37lbkc/JjiXCdIJy2Ta3A3CVV5k3Z37NbgAu23oKA2OcHQNaRTLtqWlcBf9fk9suOkP1A3NzAqzivFpBnZm3ytaXwU8LBJqxOtNqZcFVruO6fZxJtg2uE34mAw==" + ]; + }; + + aliases = { + c = [ "commit" ]; + ci = [ + "commit" + "--interactive" + ]; + + e = [ "edit" ]; + + # "new bookmark" + nb = [ + "bookmark" + "create" + "-r @-" + ]; + + pull = [ + "git" + "fetch" + ]; + push = [ + "git" + "push" + "--allow-new" + ]; + + r = [ "rebase" ]; + s = [ "squash" ]; + si = [ + "squash" + "--interactive" + ]; + + tug = [ + "bookmark" + "move" + "--from" + "closest_bookmark(@-)" + "--to" + "@-" + ]; + }; + revset-aliases = { + "closest_bookmark(to)" = "heads(::to & bookmarks())"; + }; + + templates = { + draft_commit_description = '' + concat( + coalesce(description, "\n"), + surround( + "\nJJ: This commit contains the following changes:\n", "", + indent("JJ: ", diff.stat(72)), + ), + "\nJJ: ignore-rest\n", + diff.git(), + ) + ''; + }; + template-aliases = { + "format_short_id(id)" = "id.shortest()"; + }; + }; + + jj-wrapped = pkgs.symlinkJoin { + name = "jj-wrapped"; + paths = [ pkgs.jj ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/mako --add-flags "\ + --config ${jj-config} + + ''; + }; +in +{ + # environment.systemPackages = [jj-wrapped]; +} diff --git a/modules/programs/cli/module.nix b/modules/programs/cli/module.nix deleted file mode 100644 index a987192..0000000 --- a/modules/programs/cli/module.nix +++ /dev/null @@ -1,6 +0,0 @@ -_: { - imports = [ - ./nh.nix - # ./beets.nix - ]; -} diff --git a/modules/programs/cli/nh.nix b/modules/programs/cli/nh.mod.nix similarity index 64% rename from modules/programs/cli/nh.nix rename to modules/programs/cli/nh.mod.nix index 18033fa..a671006 100644 --- a/modules/programs/cli/nh.nix +++ b/modules/programs/cli/nh.mod.nix @@ -1,21 +1,30 @@ { config, lib, + pkgs, + sources, ... -}: let +}: +let cfg = config.modules.programs.nh; inherit (config.modules.other.system) username; inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; -in { + nh = (pkgs.callPackage "${sources.nh}/package.nix" { }).overrideAttrs (_: { + doInstallCheck = false; + }); +in +{ options.modules.programs.nh.enable = mkEnableOption "nh"; config = mkIf cfg.enable { programs.nh = { enable = true; + package = nh; + clean.enable = true; clean.extraArgs = "--keep-since 4d --keep 3"; - flake = "/home/${username}/repos/projects/nichts"; + flake = "/home/${username}/repos/projects/nichts/main"; }; }; } diff --git a/modules/programs/cli/zodide.mod.nix b/modules/programs/cli/zodide.mod.nix new file mode 100644 index 0000000..08675c8 --- /dev/null +++ b/modules/programs/cli/zodide.mod.nix @@ -0,0 +1,7 @@ +_: { + programs.zoxide = { + enable = true; + enableFishIntegration = true; + enableBashIntegration = true; + }; +} diff --git a/modules/programs/gui/bitwarden.mod.nix b/modules/programs/gui/bitwarden.mod.nix new file mode 100644 index 0000000..79726ad --- /dev/null +++ b/modules/programs/gui/bitwarden.mod.nix @@ -0,0 +1,35 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (config.modules.system) isGraphical; + inherit (lib.modules) mkIf; + + bitwarden-desktop-wrapped = pkgs.symlinkJoin { + name = "bitwarden-desktop-wrapped"; + paths = [ pkgs.bitwarden-desktop ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/bitwarden --set \ + BITWARDEN_SSH_AUTH_SOCK /run/user/1000/ssh-agent.sock + ''; + }; +in +{ + config = mkIf isGraphical { + environment = { + systemPackages = lib.attrValues { + inherit (pkgs) + bitwarden-cli + ; + inherit bitwarden-desktop-wrapped; + }; + # Set the ssh socket globally. This alows all applications and shells to use + # the ssh-agent. + variables."SSH_AUTH_SOCK" = "/run/user/1000/ssh-agent.sock"; + }; + }; +} diff --git a/modules/programs/gui/brave.mod.nix b/modules/programs/gui/brave.mod.nix new file mode 100644 index 0000000..ebf9db9 --- /dev/null +++ b/modules/programs/gui/brave.mod.nix @@ -0,0 +1,245 @@ +{ + lib, + pkgs, + ... +}: +let + inherit (lib.lists) map; + inherit (lib.strings) concatStringsSep; + + # https://peter.sh/experiments/chromium-command-line-switches/ + flags = concatStringsSep " " [ + "--no-first-run" + "--enable-gpu-rasterization" + "--force-dark-mode" + "--enable-smooth-scrolling" + "--enable-features=UseOzonePlatform" + "--ozone-platform=wayland" + "--user-agent='Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/134.0.0.0 Safari/537.3'" + # https://source.chromium.org/chromium/chromium/src/+/main:headless/app/headless_shell_switches.cc;drc=3556fbff47c18193f4a39d2496596e89b8307a15;l=47-55 + "--password-store=gnome-keyring" + ]; + brave-wrapped = pkgs.symlinkJoin { + name = "brave"; + paths = [ + pkgs.brave + ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/brave --append-flags "${flags}" + ''; + }; +in +{ + environment.systemPackages = [ + brave-wrapped + ]; + programs.chromium = { + enable = true; + + # This sets a bunch of flags to make Brave usable. + # This was made possible through several similar projects, + # which facilitated this process a lot: + # https://gist.github.com/yashgorana/869542b66d7188729716379abe7464e0 + # https://github.com/yashgorana/chrome-debloat + # https://chromeenterprise.google/intl/en_ca/policies + extraOpts = { + BraveRewardsDisabled = true; + BraveWalletDisabled = true; + + # Setting the policy to False prevents Google Chrome from showing + # product promotional content. + PromotionsEnabled = false; + TorDisabled = true; + BraveVPNDisabled = true; + BraveAIChatEnabled = false; + SyncDisabled = true; + + # Setting the policy to False stops Google Chrome from ever checking if + # it's the default and turns user controls off for this option. + DefaultBrowserSettingEnabled = false; + + # In background mode, a Google Chrome process is started on OS sign-in and keeps + # running when the last browser window is closed, allowing background apps and + # the browsing session to remain active. + BackgroundModeEnabled = false; + + # By default the browser will show media recommendations that are personalized to the user. + # Setting this policy to Disabled will result in these recommendations being hidden from the user. + MediaRecommendationsEnabled = false; + + # This policy controls the availability of the shopping list feature. + # If enabled, users will be presented with UI to track the price of + # the product displayed on the current page. The tracked product will + # be shown in the bookmarks side panel. If this policy is set to Enabled + # or not set, the shopping list feature will be available to users. + # If this policy is set to Disabled, the shopping list feature will be unavailable. + ShoppingListEnabled = false; + BraveSyncUrl = ""; + PrivacySandboxFingerprintingProtectionEnabled = true; + PrivacySandboxIpProtectionEnabled = true; + DefaultSearchProviderEnabled = true; + DefaultSearchProviderName = "Kagi"; + DefaultSearchProviderSearchURL = "https://kagi.com/search?q={searchTerms}"; + DefaultSearchProviderNewTabURL = "https://kagi.com"; + SearchSuggestEnabled = true; + DefaultSearchProviderSuggestURL = "https://kagi.com/api/autosuggest?q={searchTerms}"; + + # Prevents webpage elements that aren't from the domain + # that's in the browser's address bar from setting cookies. + BlockThirdPartyCookies = true; + DnsOverHttpsMode = "automatic"; + MetricsReportingEnabled = false; + SafeBrowsingExtendedReportingEnabled = false; + # Setting the policy to Enabled means URL-keyed anonymized data collection, + # which sends URLs of pages the user visits to Google to make searches and + # browsing better, is always active. + # Setting the policy to Disabled results in no URL-keyed anonymized data collection. + UrlKeyedAnonymizedDataCollectionEnabled = false; + + # Google Chrome in-product surveys collect user feedback for the browser. + # Survey responses are not associated with user accounts. When this policy + # is Enabled or not set, in-product surveys may be shown to users. + # When this policy is Disabled, in-product surveys are not shown to users. + FeedbackSurveysEnabled = false; + + PasswordManagerEnabled = false; + # Disable sharing user credentials with other users + PasswordSharingEnabled = false; + # Disable leak detection for entered credentials + PasswordLeakDetectionEnabled = false; + + AutofillAddressEnabled = false; + AutofillCreditCardEnabled = false; + ParcelTrackingEnabled = false; + + # Setting the policy to 2 denies sites tracking the users' physical locationing. + DefaultGeolocationSetting = 2; + DefaultNotificationsSetting = 2; + # Setting the policy to BlockLocalFonts (value 2) automatically denies the local fonts + # permission to sites by default. This will limit the ability of sites to see + # information about local fonts. + DefaultLocalFontsSetting = 2; + + # Setting the policy to 1 lets websites access and use sensors such as motion and light. + # Setting the policy to 2 denies access to sensors. + DefaultSensorsSetting = 2; + # Setting the policy to 3 lets websites ask for access to serial ports. + # Setting the policy to 2 denies access to serial ports. + DefaultSerialGuardSetting = 2; + # This policy allows to control the Related Website Sets feature enablement. + # This policy overrides the FirstPartySetsEnabled policy. + # When this policy is set to False, the Related Website Sets feature is disabled. + RelatedWebsiteSetsEnabled = false; + + # This policy controls the sign-in behavior of the browser. + # It allows you to specify if the user can sign in to Google Chrome with + # their account and use account related services like Google Chrome Sync. + BrowserSignin = 0; + + QuicAllowed = true; + + # Setting the policy to Enabled turns the internal PDF viewer off in Google Chrome, + # treats PDF files as a download, and lets users open PDFs with the default application. + AlwaysOpenPdfExternally = true; + + SpellcheckEnabled = false; + EnableDoNotTrack = true; + + # If this policy is set to Disabled, Google Chrome will not allow guest profiles to be started. + # Guest logins are Google Chrome profiles where all windows are in incognito mode. + BrowserGuestModeEnabled = false; + + # This policy controls which software stack is used to communicate with the DNS server: + # the Operating System DNS client, or Google Chrome's built-in DNS client. This policy + # does not affect which DNS servers are used: if, for example, the operating system is + # configured to use an enterprise DNS server, that same server would be used by the + # built-in DNS client. It also does not control if DNS-over-HTTPS is used; Google Chrome + # will always use the built-in resolver for DNS-over-HTTPS requests. + # If this policy is set to Disabled, the built-in DNS client will only be used when DNS-over-HTTPS is in use. + BuiltinDnsClientEnabled = false; + + # Control if Manifest v2 extensions can be used by browser. + ExtensionManifestV2Availability = 2; + + # Setting the policy to True means Google Chrome uses alternate error + # pages built into (such as "page not found"). Setting the policy to + # False means Google Chrome never uses alternate error pages. + AlternateErrorPagesEnabled = false; + + "3rdparty" = { + extensions = { + # Ublock Origin + cjpalhdlnbpafiamejdnhcphjbkeiagm = { + toOverwrite = { + filterLists = [ + # Default UBlock Origin filter lists + "user-filters" + "ublock-filters" + "ublock-badware" + "ublock-privacy" + "ublock-abuse" + "ublock-unbreak" + "easylist" + "easyprivacy" + "urlhaus-1" + "plowe-0" + + "https://raw.githubusercontent.com/yokoffing/filterlists/refs/heads/main/privacy_essentials.txt" + "https://raw.githubusercontent.com/hagezi/dns-blocklists/refs/heads/main/adblock/pro.plus.mini.txt" + "https://raw.githubusercontent.com/DandelionSprout/adfilt/refs/heads/master/LegitimateURLShortener.txt" + "https://raw.githubusercontent.com/yokoffing/filterlists/refs/heads/main/annoyance_list.txt" + "https://raw.githubusercontent.com/DandelionSprout/adfilt/refs/heads/master/BrowseWebsitesWithoutLoggingIn.txt" + ]; + }; + }; + }; + }; + }; + extensions = [ + # NoScript + "doojmbjmlfjjnbmnoijecmcbfeoakpjm" + # KeePassXC-Browser + # "oboonakemofpalcgghocfoadofidjkkk" + # Bitwarden Password Manager + "nngceckbapebfimnlniiiahkandclblb" + # Catppuccin Mocha + "bkkmolkhemgaeaeggcmfbghljjjoofoh" + # Dark Reader + "eimadpbcbfnmbkopoojfekhnkhdbieeh" + # UBlock Origin + "cjpalhdlnbpafiamejdnhcphjbkeiagm" + # I still don't care about cookies + "edibdbjcniadpccecjdfdjjppcpchdlm" + # Sponsorblock + "mnjggcdmjocbbbhaepdhchncahnbgone" + # Decentraleyes + "ldpochfccmkkmhdbclfhpagapcfdljkj" + # Humble new tab page + "mfgdmpfihlmdekaclngibpjhdebndhdj" + ]; + }; + + networking.extraHosts = + concatStringsSep "\n" + <| map (addr: "localhost ${addr}") [ + "rewards.brave.com" + "api.rewards.brave.com" + "grant.rewards.brave.com" + "variations.brave.com" + "laptop-updates.brave.com" + "static.brave.com" + "static1.brave.com" + "crlsets.brave.com" + "ads.brave.com" + "ads-admin.brave.com" + "ads-help.brave.com" + "referrals.brave.com" + "analytics.brave.com" + "search.anonymous.ads.brave.com" + "p3a.brave.com" + "variations.brave.com" + "star-randsrv.bsg.brave.com" + "usage-ping.brave.com" + ]; +} diff --git a/modules/programs/gui/dolphin.mod.nix b/modules/programs/gui/dolphin.mod.nix new file mode 100644 index 0000000..559f002 --- /dev/null +++ b/modules/programs/gui/dolphin.mod.nix @@ -0,0 +1,19 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (config.modules.system) isGraphical; +in +{ + config = mkIf isGraphical { + environment.systemPackages = with pkgs; [ + kdePackages.dolphin + kdePackages.kio-fuse # to mount remote filesystems via FUSE + kdePackages.kio-extras # extra protocols support (sftp, fish and more) + ]; + }; +} diff --git a/modules/programs/gui/foot.mod.nix b/modules/programs/gui/foot.mod.nix new file mode 100644 index 0000000..390c648 --- /dev/null +++ b/modules/programs/gui/foot.mod.nix @@ -0,0 +1,143 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + + inherit (config.meta.mainUser) username; + cfg = config.modules.system.programs.terminals.foot; + theme-colors = config.modules.style.colorScheme.colors; + + foot-config = pkgs.writeText "foot.ini" ( + lib.generators.toINI { } { + main = { + term = "xterm-256color"; + app-id = "foot"; + title = "foot"; + locked-title = "no"; + + font = "JetBrainsMono Nerd Font Mono:size=14"; + font-bold = "JetBrainsMono Nerd Font Mono:size=14:style=Bold"; + + line-height = 20; + letter-spacing = 0; + + horizontal-letter-offset = 0; + vertical-letter-offset = 0; + box-drawings-uses-font-glyphs = "no"; + dpi-aware = "no"; + + bold-text-in-bright = "no"; + word-delimiters = ",│`|:\"'()[]{}<>"; + selection-target = "primary"; + + initial-window-size-chars = "104x36"; + initial-window-mode = "windowed"; + pad = "8x8 center"; + resize-delay-ms = 100; + }; + + desktop-notifications.command = "${pkgs.libnotify}/bin/notify-send -a \${app-id} -i \${app-id} \${title} \${body}"; + + bell = { + urgent = "yes"; + notify = "yes"; + command = "${pkgs.libnotify}/bin/notify-send bell"; + command-focused = "no"; + }; + + scrollback = { + lines = 10000; + multiplier = 10.0; + indicator-position = "relative"; + indicator-format = "line"; + }; + + url = { + launch = "${pkgs.xdg-utils}/bin/xdg-open \${url}"; + label-letters = "sadfjklewcmpgh"; + osc8-underline = "always"; + }; + + tweak = { + font-monospace-warn = "no"; + sixel = "yes"; + }; + cursor = { + style = "beam"; + blink = "no"; + }; + + mouse = { + hide-when-typing = "yes"; # not really needed since we already enable this in Hyprland. + alternate-scroll-mode = "yes"; + }; + csd.preferred = "server"; + key-bindings = { + scrollback-up-half-page = "Control+k"; + scrollback-up-page = "Control+Shift+k"; + scrollback-down-half-page = "Control+j"; + scrollback-down-page = "Control+Shift+j"; + }; + mouse-bindings = { + selection-override-modifiers = "Shift"; + primary-paste = "BTN_MIDDLE"; + select-begin = "BTN_LEFT"; + select-begin-block = "Control+BTN_LEFT"; + select-extend = "BTN_RIGHT"; + select-extend-character-wise = "Control+BTN_RIGHT"; + select-word = "BTN_LEFT-2"; + select-word-whitespace = "Control+BTN_LEFT-2"; + }; + + colors = { + foreground = theme-colors.base05; # Text + background = theme-colors.base00; # Base + regular0 = theme-colors.base03; # Surface 1 + regular1 = theme-colors.base08; # red + regular2 = theme-colors.base0B; # green + regular3 = theme-colors.base0A; # yellow + regular4 = theme-colors.base0D; # blue + regular5 = "f5c2e7"; # pink + regular6 = "94e2d5"; # teal + regular7 = "bac2de"; # Subtext 1 + + bright0 = theme-colors.base04; # Surface 2 + bright1 = theme-colors.base08; # red + bright2 = theme-colors.base0B; # green + bright3 = theme-colors.base0A; # yellow + bright4 = "89b4fa"; # blue + bright5 = "f5c2e7"; # pink + bright6 = "94e2d5"; # teal + bright7 = "a6adc8"; # Subtext 0 + + selection-foreground = "cdd6f4"; + selection-background = "414356"; + + search-box-no-match = "11111b f38ba8"; + search-box-match = "cdd6f4 313244"; + + jump-labels = "11111b fab387"; + urls = "89b4fa"; + + alpha = 0.9; + }; + } + ); + foot-wrapped = pkgs.symlinkJoin { + name = "foot-wrapped"; + paths = [ pkgs.foot ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/foot --add-flags "--config=${foot-config} --working-directory=/home/${username}" + ''; + }; +in +{ + config = mkIf cfg.enable { + environment.systemPackages = [ foot-wrapped ]; + }; +} diff --git a/modules/programs/gui/foot.nix b/modules/programs/gui/foot.nix deleted file mode 100644 index 8677994..0000000 --- a/modules/programs/gui/foot.nix +++ /dev/null @@ -1,132 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib.modules) mkIf; - - inherit (config.meta.mainUser) username; - cfg = config.modules.system.programs.terminals.foot; - colours = config.modules.style.colorScheme.colors; - - foot-config = pkgs.writeText "foot.ini" (lib.generators.toINI {} { - main = { - term = "xterm-256color"; - app-id = "foot"; - title = "foot"; - locked-title = "no"; - - font = "valiosevka:size=14"; - font-bold = "valiosevka:size=14"; - # font = "Iosevka Nerd Font:size=14"; - # font-bold = "Iosevka Nerd Font:size=14"; - - line-height = 20; - letter-spacing = 0; - - horizontal-letter-offset = 0; - vertical-letter-offset = 0; - box-drawings-uses-font-glyphs = "no"; - dpi-aware = "no"; - - bold-text-in-bright = "no"; - word-delimiters = ",│`|:\"'()[]{}<>"; - selection-target = "primary"; - - initial-window-size-chars = "104x36"; - initial-window-mode = "windowed"; - pad = "8x8 center"; - resize-delay-ms = 100; - }; - - desktop-notifications.command = "${pkgs.libnotify}/bin/notify-send -a \${app-id} -i \${app-id} \${title} \${body}"; - - bell = { - urgent = "yes"; - notify = "yes"; - command = "${pkgs.libnotify}/bin/notify-send bell"; - command-focused = "no"; - }; - - scrollback = { - lines = 10000; - multiplier = 10.0; - indicator-position = "relative"; - indicator-format = "line"; - }; - - url = { - launch = "${pkgs.xdg-utils}/bin/xdg-open \${url}"; - label-letters = "sadfjklewcmpgh"; - osc8-underline = "always"; - }; - - tweak = { - font-monospace-warn = "no"; - sixel = "yes"; - }; - cursor = { - style = "beam"; - blink = "no"; - }; - - mouse = { - hide-when-typing = "yes"; # not really needed since we already enable this in Hyprland. - alternate-scroll-mode = "yes"; - }; - csd.preferred = "server"; - key-bindings = { - scrollback-up-half-page = "Control+k"; - scrollback-up-page = "Control+Shift+k"; - scrollback-down-half-page = "Control+j"; - scrollback-down-page = "Control+Shift+j"; - }; - mouse-bindings = { - selection-override-modifiers = "Shift"; - primary-paste = "BTN_MIDDLE"; - select-begin = "BTN_LEFT"; - select-begin-block = "Control+BTN_LEFT"; - select-extend = "BTN_RIGHT"; - select-extend-character-wise = "Control+BTN_RIGHT"; - select-word = "BTN_LEFT-2"; - select-word-whitespace = "Control+BTN_LEFT-2"; - }; - colors = { - background = colours.base00; # base color - foreground = colours.base05; # text color - - regular0 = colours.base03; # black - regular1 = colours.base08; # red - regular2 = colours.base0B; # green - regular3 = colours.base0A; # yellow - regular4 = colours.base0D; # blue - regular5 = colours.base0F; #magenta - regular6 = colours.base0C; #cyan - regular7 = colours.base06; #white - - bright0 = colours.base04; # Surface 2 - bright1 = colours.base08; # red - bright2 = colours.base0B; # green - bright3 = colours.base0A; # yellow - bright4 = colours.base0D; # blue - bright5 = colours.base0F; # pink - bright6 = colours.base0C; # teal - bright7 = colours.base07; # Subtext 0 - - alpha = 1.0; - }; - }); - foot-wrapped = pkgs.symlinkJoin { - name = "foot-wrapped"; - paths = [pkgs.foot]; - buildInputs = [pkgs.makeWrapper]; - postBuild = '' - wrapProgram $out/bin/foot --add-flags "--config=${foot-config} --working-directory=/home/${username}" - ''; - }; -in { - config = mkIf cfg.enable { - environment.systemPackages = [foot-wrapped]; - }; -} diff --git a/modules/programs/gui/fuzzel/module.nix b/modules/programs/gui/fuzzel/module.nix deleted file mode 100644 index 7bb939e..0000000 --- a/modules/programs/gui/fuzzel/module.nix +++ /dev/null @@ -1,11 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let -in { - environment.systemPackages = builtins.attrValues { - inherit (pkgs) fuzzel; - }; -} diff --git a/modules/programs/gui/minecraft.nix b/modules/programs/gui/minecraft.nix index 753faeb..fd5632a 100644 --- a/modules/programs/gui/minecraft.nix +++ b/modules/programs/gui/minecraft.nix @@ -3,18 +3,20 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.options) mkEnableOption; inherit (lib.modules) mkIf; cfg = config.modules.programs.minecraft; -in { +in +{ options.modules.programs.minecraft = { enable = mkEnableOption "minecraft"; wayland = mkEnableOption "wayland"; }; config = mkIf cfg.enable { - environment.systemPackages = [pkgs.prismlauncher]; + environment.systemPackages = [ pkgs.prismlauncher ]; }; } diff --git a/modules/programs/gui/module.nix b/modules/programs/gui/module.nix deleted file mode 100644 index 4a53a47..0000000 --- a/modules/programs/gui/module.nix +++ /dev/null @@ -1,9 +0,0 @@ -_: { - imports = [ - ./foot.nix - ./steam.nix - # ./schizofox.nix - ./minecraft.nix - ./miniflux.nix - ]; -} diff --git a/modules/programs/gui/spotify.mod.nix b/modules/programs/gui/spotify.mod.nix new file mode 100644 index 0000000..9f0eeeb --- /dev/null +++ b/modules/programs/gui/spotify.mod.nix @@ -0,0 +1,9 @@ +{ pkgs, ... }: +{ + environment.systemPackages = [ + pkgs.spotify + ] + ++ (with pkgs; [ + sptlrx + ]); +} diff --git a/modules/programs/gui/steam.nix b/modules/programs/gui/steam.mod.nix similarity index 70% rename from modules/programs/gui/steam.nix rename to modules/programs/gui/steam.mod.nix index 2b19e16..c9a8c72 100644 --- a/modules/programs/gui/steam.nix +++ b/modules/programs/gui/steam.mod.nix @@ -3,12 +3,14 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.system.programs.steam; -in { +in +{ options.modules.system.programs.steam.enable = mkEnableOption "Steam games platform"; config = mkIf cfg.enable { programs.steam = { @@ -19,16 +21,20 @@ in { SDL_VIDEODRIVER = "x11"; }; - extraLibraries = p: + extraLibraries = + p: builtins.attrValues { inherit (p) atk; }; }; gamescopeSession.enable = true; - extraCompatPackages = [pkgs.proton-ge-bin.steamcompattool]; + extraCompatPackages = [ pkgs.proton-ge-bin.steamcompattool ]; }; - # See + + services.udev.extraRules = '' + SUBSYSTEM=="input", ATTRS{idVendor}=="2dc8", ATTRS{idProduct}=="3106", MODE="0660", GROUP="input" + ''; # See # https://wiki.nixos.org/wiki/GameMode programs.gamemode.enable = true; }; diff --git a/modules/programs/gui/thunar.mod.nix b/modules/programs/gui/thunar.mod.nix new file mode 100644 index 0000000..30773f1 --- /dev/null +++ b/modules/programs/gui/thunar.mod.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + cfg = config.modules.programs.thunar; +in +{ + options.modules.programs.thunar.enable = mkEnableOption "Thunar file manager"; + config = mkIf cfg.enable { + programs.thunar = { + enable = true; + plugins = builtins.attrValues { + inherit (pkgs.xfce) + thunar-volman + thunar-vcs-plugin + thunar-archive-plugin + thunar-media-tags-plugin + ; + }; + }; + services.gvfs = { + enable = true; + package = pkgs.gvfs; + }; + + # Archive management + programs.file-roller = { + enable = true; + package = pkgs.file-roller; + }; + + # image thumbnails + services.tumbler.enable = true; + }; +} diff --git a/modules/programs/gui/thunar/module.nix b/modules/programs/gui/thunar/module.nix deleted file mode 100644 index 7a829d0..0000000 --- a/modules/programs/gui/thunar/module.nix +++ /dev/null @@ -1,23 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: { - programs.thunar = { - enable = true; - plugins = builtins.attrValues { - inherit - (pkgs.xfce) - thunar-volman - thunar-vcs-plugin - thunar-archive-plugin - thunar-media-tags-plugin - ; - }; - }; - services.gvfs = { - enable = true; - package = pkgs.gvfs; - }; -} diff --git a/modules/programs/other/direnv.nix b/modules/programs/other/direnv.mod.nix similarity index 75% rename from modules/programs/other/direnv.nix rename to modules/programs/other/direnv.mod.nix index 3698c77..1c5e612 100644 --- a/modules/programs/other/direnv.nix +++ b/modules/programs/other/direnv.mod.nix @@ -1,4 +1,5 @@ -{pkgs, ...}: { +{ pkgs, ... }: +{ config = { programs.direnv = { enable = true; @@ -10,8 +11,8 @@ # We want direnv to load in our nix dev shells loadInNixShell = true; - enableBashIntegration = true; - enableFishIntegration = true; + enableBashIntegration = false; + enableFishIntegration = false; }; }; } diff --git a/modules/programs/other/module.nix b/modules/programs/other/module.nix deleted file mode 100644 index 5be7857..0000000 --- a/modules/programs/other/module.nix +++ /dev/null @@ -1,3 +0,0 @@ -_: { - imports = [./direnv.nix ./nix-index.nix]; -} diff --git a/modules/programs/other/nix-index.nix b/modules/programs/other/nix-index.mod.nix similarity index 92% rename from modules/programs/other/nix-index.nix rename to modules/programs/other/nix-index.mod.nix index 43fb005..86c94b1 100644 --- a/modules/programs/other/nix-index.nix +++ b/modules/programs/other/nix-index.mod.nix @@ -1,4 +1,4 @@ -{pkgs, ...}: { +{ programs = { # We have to disable this and use nix-index instead. (Rust >>> Pearl) command-not-found = { diff --git a/modules/programs/tui/btop.nix b/modules/programs/tui/btop.nix deleted file mode 100644 index df1d29b..0000000 --- a/modules/programs/tui/btop.nix +++ /dev/null @@ -1,40 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib.options) mkEnableOption; - inherit (lib.modules) mkIf; - - cfg = config.modules.programs.btop; - - btop-settings = pkgs.writeTextDir "btop/btop.conf" '' - truecolor = True - vim_keys = True - rounded_corners = True - update_ms = 100 - graph_symbol = "braille" - cpu_single_graph = True - clock_format = "%X" - use_fstab = True - io_mode = True - net_sync = True - net_iface = "enp4s0" - log_level = "ERROR" - ''; - - btop-wrapped = pkgs.symlinkJoin { - name = "btop-wrapped"; - paths = [pkgs.btop]; - buildInputs = [pkgs.makeWrapper]; - postBuild = '' - wrapProgram $out/bin/btop --set XDG_CONFIG_HOME "${btop-settings}" - ''; - }; -in { - options.modules.programs.btop.enable = mkEnableOption "btop"; - config = mkIf cfg.enable { - environment.systemPackages = [btop-wrapped]; - }; -} diff --git a/modules/programs/tui/module.nix b/modules/programs/tui/module.nix deleted file mode 100644 index 5a5a318..0000000 --- a/modules/programs/tui/module.nix +++ /dev/null @@ -1,3 +0,0 @@ -_: { - imports = [./btop.nix]; -} diff --git a/modules/programs/tui/zellij/config.kdl b/modules/programs/tui/zellij/config.kdl new file mode 100644 index 0000000..b26ff6f --- /dev/null +++ b/modules/programs/tui/zellij/config.kdl @@ -0,0 +1,327 @@ +// taken from https://lobste.rs/s/ft797a/why_zellij#c_4g7k3x +// Make the default layout compact and non-disturbing +default_layout "compact" +// do not pane frames +pane_frames false +// do not show startup tips +show_startup_tips false +// Choose the mode that zellij uses when starting up. +// Default: normal +// +default_mode "locked" +default_shell "fish" +theme "catppuccin-frappe" +// Toggle enabling the mouse mode. On certain configurations, or terminals this +// could potentially interfere with copying text. +// Default: true +// +mouse_mode true +// If you'd like to override the default keybindings completely, be sure to change "keybinds" to "keybinds clear-defaults=true" +keybinds clear-defaults=true { + scroll { + bind "Esc" "Ctrl s" { + SwitchToMode "Locked" + } + bind "e" { + EditScrollback + SwitchToMode "Locked" + } + bind "/" { + SwitchToMode "EnterSearch" + SearchInput 0 + } + bind "Ctrl c" { + ScrollToBottom + SwitchToMode "Locked" + } + bind "j" "Down" { + ScrollDown + } + bind "k" "Up" { + ScrollUp + } + bind "Ctrl f" "PageDown" "Right" "l" { + PageScrollDown + } + bind "Ctrl b" "PageUp" "Left" "h" { + PageScrollUp + } + bind "d" { + HalfPageScrollDown + } + bind "u" { + HalfPageScrollUp + } + bind "g" { + ScrollToTop + } + bind "G" { + ScrollToBottom + } + } + search { + bind "Ctrl s" { + SwitchToMode "Locked" + } + bind "Esc" "Ctrl c" { + ScrollToBottom + SwitchToMode "Locked" + } + bind "j" "Down" { + ScrollDown + } + bind "k" "Up" { + ScrollUp + } + bind "Ctrl f" "PageDown" "Right" "l" { + PageScrollDown + } + bind "Ctrl b" "PageUp" "Left" "h" { + PageScrollUp + } + bind "d" { + HalfPageScrollDown + } + bind "u" { + HalfPageScrollUp + } + bind "n" { + Search "down" + } + bind "p" { + Search "up" + } + bind "c" { + SearchToggleOption "CaseSensitivity" + } + bind "w" { + SearchToggleOption "Wrap" + } + bind "o" { + SearchToggleOption "WholeWord" + } + } + entersearch { + bind "Ctrl c" "Esc" { + SwitchToMode "Scroll" + } + bind "Enter" { + SwitchToMode "Search" + } + } + renametab { + bind "Ctrl c" { + SwitchToMode "Locked" + } + bind "Esc" { + UndoRenameTab + SwitchToMode "Tmux" + } + } + renamepane { + bind "Ctrl c" { + SwitchToMode "Locked" + } + bind "Esc" { + UndoRenamePane + SwitchToMode "Tmux" + } + } + tmux { + bind "[" { + SwitchToMode "Scroll" + } + bind "Ctrl Space" { + Write 1 + SwitchToMode "Locked" + } + bind "z" { + ToggleFocusFullscreen + SwitchToMode "Locked" + } + // manipulate tabs + bind "c" { + NewTab + SwitchToMode "Locked" + } + bind "K" { + CloseTab + SwitchToMode "Locked" + } + bind "R" { + SwitchToMode "RenameTab" + } + // switch modes + bind "/" { + SwitchToMode "EnterSearch" + SearchInput 0 + } + // miscellaneous + bind "s" { + ToggleActiveSyncTab + SwitchToMode "Locked" + } + bind "m" { + ToggleMouseMode + SwitchToMode "Locked" + } + bind "y" { + Run "yazi" + SwitchToMode "Locked" + } + // create new pane + bind "Space" { + NewPane + SwitchToMode "Locked" + } + bind "-" "_" { + NewPane "Down" + SwitchToMode "Locked" + } + bind "|" "\\" { + NewPane "Right" + SwitchToMode "Locked" + } + bind "r" { + SwitchToMode "RenamePane" + } + // switch between tabs + bind "h" { + GoToPreviousTab + SwitchToMode "Locked" + } + bind "l" { + GoToNextTab + SwitchToMode "Locked" + } + bind "1" { + GoToTab 1 + SwitchToMode "Locked" + } + bind "2" { + GoToTab 2 + SwitchToMode "Locked" + } + bind "3" { + GoToTab 3 + SwitchToMode "Locked" + } + bind "4" { + GoToTab 4 + SwitchToMode "Locked" + } + bind "5" { + GoToTab 5 + SwitchToMode "Locked" + } + bind "6" { + GoToTab 6 + SwitchToMode "Locked" + } + bind "7" { + GoToTab 7 + SwitchToMode "Locked" + } + bind "8" { + GoToTab 8 + SwitchToMode "Locked" + } + bind "9" { + GoToTab 9 + SwitchToMode "Locked" + } + // switch between panes + bind "Left" { + MoveFocus "Left" + } + bind "Right" { + MoveFocus "Right" + } + bind "Down" { + MoveFocus "Down" + } + bind "Up" { + MoveFocus "Up" + } + bind "Tab" { + FocusNextPane + } + // move panes + bind "H" { + MovePane "Left" + } + bind "J" { + MovePane "Down" + } + bind "K" { + MovePane "Up" + } + bind "L" { + MovePane "Right" + } + // manipulate panes + bind "W" { + CloseFocus + SwitchToMode "Locked" + } + // exit etc + bind "Enter" "Esc" { + SwitchToMode "Locked" + } + bind "d" { + Detach + SwitchToMode "Locked" + } + bind "Q" { + Quit + } + // resizing + bind "Ctrl h" { + Resize "Increase Left" + } + bind "Ctrl j" { + Resize "Increase Down" + } + bind "Ctrl k" { + Resize "Increase Up" + } + bind "Ctrl l" { + Resize "Increase Right" + } + } + shared { + bind "Alt n" { + NewPane + } + bind "Alt Ctrl h" { + MoveFocus "Left" + } + bind "Alt Ctrl j" { + MoveFocus "Down" + } + bind "Alt Ctrl l" { + MoveFocus "Right" + } + bind "Alt Ctrl k" { + MoveFocus "Up" + } + bind "Alt [" { + PreviousSwapLayout + } + bind "Alt ]" { + NextSwapLayout + } + bind "Alt =" "Alt +" { + Resize "Increase" + } + bind "Alt -" "Alt _" { + Resize "Decrease" + } + } + shared_except "tmux" { + bind "Ctrl Space" { + SwitchToMode "Tmux" + } + } +} + diff --git a/modules/programs/tui/zellij/module.nix b/modules/programs/tui/zellij/module.nix deleted file mode 100644 index a0ccdc3..0000000 --- a/modules/programs/tui/zellij/module.nix +++ /dev/null @@ -1,12 +0,0 @@ -{pkgs, ...}: let - # I am patching zellij because of this issue: - # https://github.com/zellij-org/zellij/pull/2548 - patched-zellij = pkgs.zellij.overrideAttrs (old: { - patches = [./zellij-good-scrolling.patch]; - doCheck = false; - }); -in { - environment.systemPackages = builtins.attrValues { - # inherit patched-zellij; - }; -} diff --git a/modules/programs/tui/zellij/zellij-good-scrolling.patch b/modules/programs/tui/zellij/zellij-good-scrolling.patch deleted file mode 100644 index c7ba14d..0000000 --- a/modules/programs/tui/zellij/zellij-good-scrolling.patch +++ /dev/null @@ -1,22 +0,0 @@ ---- a/zellij-server/src/panes/grid.rs -+++ b/zellij-server/src/panes/grid.rs -@@ -271,7 +271,7 @@ fn subtract_isize_from_usize(u: usize, i: isize) -> usize { - macro_rules! dump_screen { - ($lines:expr) => {{ - let mut is_first = true; -- let mut buf = "".to_owned(); -+ let mut buf = String::with_capacity($lines.iter().map(|l| l.len()).sum()); - - for line in &$lines { - if line.is_canonical && !is_first { -@@ -280,8 +280,7 @@ macro_rules! dump_screen { - let s: String = (&line.columns).into_iter().map(|x| x.character).collect(); - // Replace the spaces at the end of the line. Sometimes, the lines are - // collected with spaces until the end of the panel. -- let re = Regex::new("([^ ])[ ]*$").unwrap(); -- buf.push_str(&(re.replace(&s, "${1}"))); -+ buf.push_str(&s.trim_end_matches(' ')); - is_first = false; - } - buf - diff --git a/modules/programs/tui/zellij/zellij.mod.nix b/modules/programs/tui/zellij/zellij.mod.nix new file mode 100644 index 0000000..ba3ef39 --- /dev/null +++ b/modules/programs/tui/zellij/zellij.mod.nix @@ -0,0 +1,17 @@ +{ pkgs, ... }: +let + zellij-wrapped = pkgs.symlinkJoin { + name = "zellij-wrapped"; + paths = [ pkgs.zellij ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/zellij --add-flags "\ + --config ${./config.kdl}" + ''; + }; +in +{ + environment.systemPackages = builtins.attrValues { + inherit zellij-wrapped; + }; +} diff --git a/modules/services/acme.mod.nix b/modules/services/acme.mod.nix new file mode 100644 index 0000000..07e8221 --- /dev/null +++ b/modules/services/acme.mod.nix @@ -0,0 +1,35 @@ +{ + config, + lib, + pkgs, + ... +}: +let + mkAcmeCert = domain: { + # An acme system user is created. This user belongs to the acme group + # and the home directory is /var/lib/acme. This user will try to make the directory + # .well-known/acme-challenge/ under the webroot directory. + webroot = "/var/lib/acme"; + + # email to send updates to, we prefix "acme" and the + # name of the domain the certificate is for to it. + email = "charlie@charlieroot.dev"; + group = "nginx"; + }; +in +{ + security.acme = { + acceptTerms = true; + defaults = { + email = "charlie@charlieroot.dev"; + # testing server, do not use in production, but DO use it for setting things up. + # it has much higher rate limits. + # server = "https://acme-staging-v02.api.letsencrypt.org/directory"; + }; + certs = { + # "copeberg.org" = mkAcmeCert "copeberg.org"; + # "info.copeberg.org" = mkAcmeCert "info.copeberg.org"; + # "mail.charlieroot.dev" = mkAcmeCert "mail.charlieroot.dev"; + }; + }; +} diff --git a/modules/services/firewall.nix b/modules/services/firewall.nix deleted file mode 100644 index 94d3b25..0000000 --- a/modules/services/firewall.nix +++ /dev/null @@ -1,3 +0,0 @@ -_: { - networking.nftables.enable = true; -} diff --git a/modules/services/forgejo/forgejo.mod.nix b/modules/services/forgejo/forgejo.mod.nix new file mode 100644 index 0000000..21b0592 --- /dev/null +++ b/modules/services/forgejo/forgejo.mod.nix @@ -0,0 +1,169 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (pkgs) fetchurl; + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + inherit (config.services.forgejo) customDir user group; + + cfg = config.modules.system.services.forgejo; + + port = 3000; + domain = "copeberg.org"; + img = ./img; + dataDir = "/srv/data/forgejo"; + dumpDir = "/srv/data/forgejo-dump"; +in +{ + options.modules.system.services.forgejo.enable = mkEnableOption "forgejo"; + + config = mkIf cfg.enable { + modules.system.services = { + database.postgresql.enable = true; + nginx.enable = true; + }; + + networking.firewall.allowedTCPPorts = [ + 443 + 80 + 3000 + ]; + + services.nginx = { + enable = true; + virtualHosts.${domain} = { + addSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString port}"; + }; + }; + }; + + # create the git user for forgejo + # NOTE: this is important and it will _not_ work otherwise. + users.users.git = { + home = dataDir; + useDefaultShell = true; + group = "git"; + isSystemUser = true; + }; + users.groups.git = { }; + + services.forgejo = { + enable = true; + package = pkgs.forgejo; + stateDir = dataDir; + + user = "git"; + group = "git"; + database = { + createDatabase = true; + name = "git"; + user = "git"; + type = "postgres"; + }; + + # Disable support for Git Large File Storage + lfs.enable = false; + + settings = { + server = { + DOMAIN = domain; + # You need to specify this to remove the port from URLs in the web UI. + ROOT_URL = "https://${domain}/"; + HTTP_PORT = port; + LANDING_PAGE = "home"; + }; + DEFAULT = { + APP_NAME = "Copeberg.org"; + APP_SLOGAN = "Code and seethe."; + }; + # disable registration by default. + service.DISABLE_REGISTRATION = true; + + # Add support for actions, based on act: https://github.com/nektos/act + actions = { + ENABLED = false; + DEFAULT_ACTIONS_URL = "github"; + }; + ui = { + SHOW_USER_EMAIL = false; + THEMES = "codeberg-dark"; + DEFAULT_THEME = "codeberg-dark"; + }; + + # The glory of the old default branch name + repository = { + DEFAULT_BRANCH = "master"; + }; + + "repository.signing" = { + SIGNING_KEY = "none"; + }; + }; + + dump = { + enable = false; + backupDir = dumpDir; + interval = "06:00"; + type = "tar.xz"; + }; + }; + + systemd.tmpfiles.rules = + let + # no crawlers, thank you. + robots = pkgs.writeText "robots-txt" '' + User-agent: * + Disallow: / + ''; + base-brand = fetchurl { + url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/src/branch/codeberg-11/web_src/css/themes/codeberg/base-brand.css"; + hash = "sha256-8gUmye/Z8H1Xe6U1CNAq907n3jt2TnPtzgpz6KhdiDU="; + }; + dark-variables = fetchurl { + url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/raw/branch/codeberg-11/web_src/css/themes/codeberg/dark-variables.css"; + hash = "sha256-nCSJUOU9/R1fldoKXTTZmP7vmRjYUk/OKkbgrJ/NrXQ="; + }; + theme-codeberg-dark = fetchurl { + url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/raw/branch/codeberg-11/web_src/css/themes/theme-codeberg-dark.css"; + hash = "sha256-KyXznH49koRGlzIDDqagN4PvFGD/zCX//wrctmtfgBs="; + }; + in + [ + "d '${customDir}/public' 0750 ${user} ${group} - -" + "d '${customDir}/public/assets' 0750 ${user} ${group} - -" + "d '${customDir}/public/assets/img' 0750 ${user} ${group} - -" + # Copeberg logo, thanks Raf <3 + "f '${customDir}/public/assets/img/logo.svg' - - - - ${img}/logo.svg" + "f '${customDir}/public/assets/img/logo.png' - - - - ${img}/logo.png" + "f '${customDir}/public/assets/img/apple-touch-icon' - - - - ${img}/logo.png" + "f '${customDir}/public/assets/img/favicon.svg' - - - - ${img}/logo.svg" + "f '${customDir}/public/assets/img/favicon.png' - - - - ${img}/logo.png" + + # Theming shenanigans + "d '${customDir}/public/assets' 0750 ${user} ${group} - -" + "d '${customDir}/public/assets/css' 0750 ${user} ${group} - -" + "d '${customDir}/public/assets/css/codeberg' 0750 ${user} ${group} - -" + + "f '${customDir}/public/assets/css/theme-codeberg-dark.css' - - - - ${theme-codeberg-dark}" + "f '${customDir}/public/assets/css/codeberg/base-brand.css' - - - - ${base-brand}" + "f '${customDir}/public/assets/css/codeberg/dark-variables.css' - - - - ${dark-variables}" + + # Templates + "d '${customDir}/templates' 0750 ${user} ${group} - -" + "d '${customDir}/templates/repo' 0750 ${user} ${group} - -" + # Home page + "f '${customDir}/templates/home.tmpl' - - - - ${./templates}/home.tmpl" + "f '${customDir}/templates/repo/header.tmpl' - - - - ${./templates/repo}/header.tmpl" + + # Fuck off scrapers + "f ${customDir}/public/robots.txt - - - - ${robots.outPath}" + ]; + }; +} diff --git a/modules/services/forgejo/module.nix b/modules/services/forgejo/module.nix deleted file mode 100644 index 079441c..0000000 --- a/modules/services/forgejo/module.nix +++ /dev/null @@ -1,172 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (pkgs) fetchurl; - inherit (lib.modules) mkIf; - inherit (config.services.forgejo) customDir user group; - - cfg = config.modules.system.services.forgejo; - - port = 3000; - domain = "copeberg.org"; - img = ./img; - acmeRoot = "/var/lib/acme/challenges-forgejo"; - dataDir = "/srv/data/forgejo"; -in { - options.modules.system.services.forgejo.enable = lib.mkEnableOption "forgejo"; - - config = mkIf cfg.enable { - modules.system.services = { - database.postgresql.enable = true; - nginx.enable = true; - }; - - networking.firewall.allowedTCPPorts = [ - 443 - 80 - 3000 - ]; - - services.nginx = { - enable = true; - virtualHosts.${domain} = { - addSSL = true; - enableACME = true; - locations."/" = { - proxyPass = "http://localhost:${toString port}"; - }; - }; - }; - - security.acme = let - email = "charlie@charlieroot.dev"; - in { - # testing server, do not use in production, but DO use it for setting things up. - # it has much higher rate limits. - # defaults.server = "https://acme-staging-v02.api.letsencrypt.org/directory"; - certs = { - ${domain} = { - webroot = acmeRoot; - inherit email; - group = "nginx"; - }; - }; - }; - - # create the git user for forgejo - # NOTE: this is important and it will _not_ work otherwise. - users.users.git = { - home = dataDir; - useDefaultShell = true; - group = "git"; - isSystemUser = true; - }; - users.groups.git = {}; - - services.forgejo = { - enable = true; - package = pkgs.forgejo; - stateDir = dataDir; - - user = "git"; - group = "git"; - database = { - createDatabase = true; - name = "git"; - user = "git"; - type = "postgres"; - }; - - # Disable support for Git Large File Storage - lfs.enable = false; - - settings = { - server = { - DOMAIN = domain; - # You need to specify this to remove the port from URLs in the web UI. - ROOT_URL = "https://${domain}/"; - HTTP_PORT = port; - LANDING_PAGE = "home"; - }; - DEFAULT = { - APP_NAME = "Copeberg.org"; - APP_SLOGAN = "Code and seethe."; - }; - # disable registration by default. - service.DISABLE_REGISTRATION = true; - - # Add support for actions, based on act: https://github.com/nektos/act - actions = { - ENABLED = false; - DEFAULT_ACTIONS_URL = "github"; - }; - ui = { - SHOW_USER_EMAIL = false; - THEMES = "codeberg-dark"; - DEFAULT_THEME = "codeberg-dark"; - }; - - # The glory of the old default branch name - repository = { - DEFAULT_BRANCH = "master"; - }; - - "repository.signing" = { - SIGNING_KEY = "none"; - }; - }; - }; - - systemd.tmpfiles.rules = let - # no crawlers, thank you. - robots = pkgs.writeText "robots-txt" '' - User-agent: * - Disallow: / - ''; - base-brand = fetchurl { - url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/raw/branch/codeberg-10/web_src/css/themes/codeberg/base-brand.css"; - hash = "sha256-QJ775HpINf8klO3d/8h+tEw0vk34p19dWUCWWuVwcho="; - }; - dark-variables = fetchurl { - url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/raw/branch/codeberg-10/web_src/css/themes/codeberg/dark-variables.css"; - hash = "sha256-nCSJUOU9/R1fldoKXTTZmP7vmRjYUk/OKkbgrJ/NrXQ="; - }; - theme-codeberg-dark = fetchurl { - url = "https://codeberg.org/Codeberg-Infrastructure/forgejo/raw/branch/codeberg-10/web_src/css/themes/theme-codeberg-dark.css"; - hash = "sha256-KyXznH49koRGlzIDDqagN4PvFGD/zCX//wrctmtfgBs="; - }; - in [ - "d '${customDir}/public' 0750 ${user} ${group} - -" - "d '${customDir}/public/assets' 0750 ${user} ${group} - -" - "d '${customDir}/public/assets/img' 0750 ${user} ${group} - -" - # Copeberg logo, thanks Raf <3 - "L+ '${customDir}/public/assets/img/logo.svg' - - - - ${img}/logo.svg" - "L+ '${customDir}/public/assets/img/logo.png' - - - - ${img}/logo.png" - "L+ '${customDir}/public/assets/img/apple-touch-icon' - - - - ${img}/logo.png" - "L+ '${customDir}/public/assets/img/favicon.svg' - - - - ${img}/logo.svg" - "L+ '${customDir}/public/assets/img/favicon.png' - - - - ${img}/logo.png" - - # Theming shenanigans - "d '${customDir}/public/assets' 0750 ${user} ${group} - -" - "d '${customDir}/public/assets/css' 0750 ${user} ${group} - -" - "d '${customDir}/public/assets/css/codeberg' 0750 ${user} ${group} - -" - - "L+ '${customDir}/public/assets/css/theme-codeberg-dark.css' - - - - ${theme-codeberg-dark}" - "L+ '${customDir}/public/assets/css/codeberg/base-brand.css' - - - - ${base-brand}" - "L+ '${customDir}/public/assets/css/codeberg/dark-variables.css' - - - - ${dark-variables}" - - # Templates - "d '${customDir}/templates' 0750 ${user} ${group} - -" - "d '${customDir}/templates/repo' 0750 ${user} ${group} - -" - # Home page - "L+ '${customDir}/templates/home.tmpl' - - - - ${./templates}/home.tmpl" - "L+ '${customDir}/templates/repo/header.tmpl' - - - - ${./templates/repo}/header.tmpl" - - # Fuck off scrapers - "L+ ${customDir}/public/robots.txt - - - - ${robots.outPath}" - ]; - }; -} diff --git a/modules/services/forgejo/templates/home.tmpl b/modules/services/forgejo/templates/home.tmpl index 03242f3..168bfbe 100644 --- a/modules/services/forgejo/templates/home.tmpl +++ b/modules/services/forgejo/templates/home.tmpl @@ -7,49 +7,10 @@

{{AppDisplayName}}

-

A very painful Git service

+

{{ctx.Locale.Tr "startpage.app_desc"}}

-
-
-

- -

Made with copious amounts of caffeeine

-

-

- TODO: Write some funny text here -

-
-
-

- -

I hate it here

-

-

- Bottom text -

-
-
-
-
-

- -

Is this the real life?

-

-

- Something something fuck poettering -

-
-
-

- -

Open source or something

-

-

- I forgor -

-
-
+ {{template "home_forgejo" .}} {{template "base/footer" .}} diff --git a/modules/services/forgejo/templates/home_forgejo.tmpl b/modules/services/forgejo/templates/home_forgejo.tmpl new file mode 100644 index 0000000..d5d18c7 --- /dev/null +++ b/modules/services/forgejo/templates/home_forgejo.tmpl @@ -0,0 +1,36 @@ +
+
+

+ {{svg "octicon-flame"}} {{ctx.Locale.Tr "startpage.install"}} +

+

+ {{ctx.Locale.Tr "startpage.install_desc" "https://forgejo.org/download/#installation-from-binary" "https://forgejo.org/download/#container-image" "https://forgejo.org/download"}} +

+
+
+

+ {{svg "octicon-device-desktop"}} {{ctx.Locale.Tr "startpage.platform"}} +

+

+ {{ctx.Locale.Tr "startpage.platform_desc"}} +

+
+
+
+
+

+ {{svg "octicon-rocket"}} {{ctx.Locale.Tr "startpage.lightweight"}} +

+

+ {{ctx.Locale.Tr "startpage.lightweight_desc"}} +

+
+
+

+ {{svg "octicon-code"}} {{ctx.Locale.Tr "startpage.license"}} +

+

+ {{ctx.Locale.Tr "startpage.license_desc" "https://forgejo.org/download" "https://codeberg.org/forgejo/forgejo"}} +

+
+
diff --git a/modules/services/grafana/grafana.mod.nix b/modules/services/grafana/grafana.mod.nix new file mode 100644 index 0000000..5652656 --- /dev/null +++ b/modules/services/grafana/grafana.mod.nix @@ -0,0 +1,103 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (builtins) fetchurl; + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.system.services.grafana; + domain = "info.copeberg.org"; + port = 4021; +in +{ + options.modules.system.services.grafana.enable = mkEnableOption "Grafana, a graphing service"; + + config = mkIf cfg.enable { + networking.firewall.allowedTCPPorts = [ config.services.grafana.settings.server.http_port ]; + + modules.system.services.database.postgresql.enable = true; + + services.grafana = { + enable = true; + package = pkgs.grafana; + + settings = { + server = { + http_addr = "127.0.0.1"; + http_port = port; + + root_url = "https://${domain}"; + inherit domain; + enforce_domain = true; + }; + database = { + type = "postgres"; + host = "/run/postgresql"; + name = "grafana"; + user = "grafana"; + ssl_mode = "disable"; + }; + + analytics = { + reporting_enabled = false; + check_for_updates = false; + }; + + users.allow_signup = false; + }; + provision = { + enable = true; + datasources.settings = { + datasources = [ + (mkIf config.modules.system.services.prometheus.enable { + name = "Prometheus"; + type = "prometheus"; + access = "proxy"; + url = "http://127.0.0.1:${toString config.services.prometheus.port}"; + isDefault = true; + }) + + (mkIf config.modules.system.services.database.postgresql.enable { + name = "PostgreSQL"; + type = "postgres"; + access = "proxy"; + url = "127.0.0.1:${toString config.services.prometheus.exporters.postgres.port}"; + }) + ]; + }; + dashboards.settings.providers = [ + { + # taken from https://grafana.com/grafana/dashboards/1860-node-exporter-full/ + name = "system-status"; + options.path = fetchurl { + url = "https://grafana.com/api/dashboards/1860/revisions/40/download"; + sha256 = "sha256-zTsS/UEX6W8+qK3l2GtvdDfmwS8eVnnyZxZ++LtRLBA="; + }; + } + { + # taken from https://grafana.com/grafana/dashboards/9628-postgresql-database/ + name = "PostgreSQL-status"; + options.path = fetchurl { + url = "https://grafana.com/api/dashboards/9628/revisions/8/download"; + sha256 = "sha256-UhusNAZbyt7fJV/DhFUK4FKOmnTpG0R15YO2r+nDnMc="; + }; + } + ]; + }; + }; + services.nginx = { + enable = true; + virtualHosts.${domain} = { + addSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString port}"; + }; + }; + }; + }; +} diff --git a/modules/services/greetd.nix b/modules/services/greetd.mod.nix similarity index 53% rename from modules/services/greetd.nix rename to modules/services/greetd.mod.nix index ffec7f4..b55b815 100644 --- a/modules/services/greetd.nix +++ b/modules/services/greetd.mod.nix @@ -3,13 +3,17 @@ lib, pkgs, ... -}: let - cfg = config.modules.services.greetd; - uwsmEnabled = config.modules.services.uwsm.enable; +}: +let + inherit (lib.meta) getExe getExe'; + inherit (lib.modules) mkIf; inherit (lib.options) mkOption mkEnableOption; inherit (lib.types) str listOf; - inherit (lib.modules) mkIf; -in { + + inherit (config.meta.mainUser) username; + cfg = config.modules.services.greetd; +in +{ options.modules.services.greetd = { enable = mkEnableOption "greetd"; greeter = mkOption { @@ -23,26 +27,30 @@ in { session = mkOption { description = "Which login session to start"; type = str; - default = - if uwsmEnabled - then "uwsm start Hyprland" - else "Hyprland"; + default = "niri"; }; }; config = mkIf cfg.enable { - services.greetd = { - enable = true; - package = pkgs.greetd; - settings.default_session = { - command = '' - ${pkgs.greetd.tuigreet}/bin/tuigreet \ - -c \"${cfg.session}\" \ - -r - -t --time-format "DD.MM.YYYY" - --asteriks''; + services.greetd = + let + session = { + command = '' + ${getExe pkgs.greetd.tuigreet} \ + -c \"${cfg.session}\" \ + -r + -t --time-format "DD.MM.YYYY" + --asteriks''; + user = "greeter"; + }; + in + { + enable = true; + vt = 7; + settings = { + default_session = session; + initial_session = session; + }; }; - vt = 7; - }; }; } diff --git a/modules/services/kanata/module.nix b/modules/services/kanata/kanata.mod.nix similarity index 54% rename from modules/services/kanata/module.nix rename to modules/services/kanata/kanata.mod.nix index b7164d5..d9a21a4 100644 --- a/modules/services/kanata/module.nix +++ b/modules/services/kanata/kanata.mod.nix @@ -2,24 +2,24 @@ config, lib, ... -}: let +}: +let inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.services.kanata; -in { +in +{ options.modules.services.kanata.enable = mkEnableOption "kanata"; config = mkIf cfg.enable { services.kanata = { enable = true; - - keyboards.daskeyboard = { - devices = ["/dev/input/by-id/usb-Metadot_-_Das_Keyboard_Das_Keyboard-event-kbd"]; - config = builtins.readFile (./. + "/main.kbd"); - }; - - keyboards.laptop = { - devices = ["/dev/input/by-path/platform-i8042-serio-0-event-kbd"]; + keyboards.main = { + devices = [ + "/dev/input/by-id/usb-Metadot_-_Das_Keyboard_Das_Keyboard-event-kbd" + "/dev/input/by-path/platform-i8042-serio-0-event-kbd" + "/dev/input/by-id/usb-Dell_Dell_USB_Keyboard-event-kbd" + ]; config = builtins.readFile (./. + "/main.kbd"); }; }; diff --git a/modules/services/locate.nix b/modules/services/locate.mod.nix similarity index 85% rename from modules/services/locate.nix rename to modules/services/locate.mod.nix index d945e6b..61bf0f4 100644 --- a/modules/services/locate.nix +++ b/modules/services/locate.mod.nix @@ -3,14 +3,16 @@ lib, pkgs, ... -}: let +}: +let cfg = config.modules.services.locate; inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; -in { +in +{ options.modules.services.locate.enable = mkEnableOption "Locate service"; config = mkIf cfg.enable { - environment.systemPackages = [pkgs.plocate]; + environment.systemPackages = [ pkgs.plocate ]; services.locate = { enable = true; interval = "hourly"; diff --git a/modules/services/mako.nix b/modules/services/mako.mod.nix similarity index 64% rename from modules/services/mako.nix rename to modules/services/mako.mod.nix index 4bbdc0e..2df18f9 100644 --- a/modules/services/mako.nix +++ b/modules/services/mako.mod.nix @@ -1,8 +1,9 @@ -{pkgs, ...}: let +{ pkgs, ... }: +let mako-wrapped = pkgs.symlinkJoin { name = "mako-wrapped"; - paths = [pkgs.mako]; - buildInputs = [pkgs.makeWrapper]; + paths = [ pkgs.mako ]; + nativeBuildInputs = [ pkgs.makeWrapper ]; postBuild = '' wrapProgram $out/bin/mako --add-flags "\ --font 'Lexend 11' \ @@ -12,6 +13,7 @@ --default-timeout 4000" ''; }; -in { - environment.systemPackages = [mako-wrapped]; +in +{ + environment.systemPackages = [ mako-wrapped ]; } diff --git a/modules/services/module.nix b/modules/services/module.nix deleted file mode 100644 index b874528..0000000 --- a/modules/services/module.nix +++ /dev/null @@ -1,11 +0,0 @@ -_: { - imports = [ - ./pipewire.nix - ./locate.nix - ./ssh.nix - ./greetd.nix - ./mako.nix - ./mpd.nix - ./firewall.nix - ]; -} diff --git a/modules/services/monitoring/loki/loki.mod.nix b/modules/services/monitoring/loki/loki.mod.nix new file mode 100644 index 0000000..4bdd589 --- /dev/null +++ b/modules/services/monitoring/loki/loki.mod.nix @@ -0,0 +1,27 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.system.services.loki; + port = 4026; + dataDir = "/srv/data/loki"; +in +{ + options.modules.system.services.loki.enable = mkEnableOption "Grafana, a graphing service"; + + config = mkIf cfg.enable { + services.loki = { + enable = true; + package = pkgs.loki; + + configuration = { + }; + }; + }; +} diff --git a/modules/services/mpd.nix b/modules/services/mpd.mod.nix similarity index 95% rename from modules/services/mpd.nix rename to modules/services/mpd.mod.nix index 195af90..edf67bf 100644 --- a/modules/services/mpd.nix +++ b/modules/services/mpd.mod.nix @@ -3,13 +3,15 @@ lib, pkgs, ... -}: let +}: +let cfg = config.modules.services.media.mpd; inherit (config.meta.mainUser) username; inherit (lib.modules) mkIf; inherit (lib.types) str; inherit (lib.options) mkOption mkEnableOption; -in { +in +{ options.modules.services = { media = { mpd = { @@ -24,7 +26,7 @@ in { }; config = mkIf cfg.enable { # command line interface to mpd - environment.systemPackages = [pkgs.mpc]; + environment.systemPackages = [ pkgs.mpc ]; systemd.services.mpd.environment = { # https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/609 diff --git a/modules/services/nginx/module.nix b/modules/services/nginx.mod.nix similarity index 94% rename from modules/services/nginx/module.nix rename to modules/services/nginx.mod.nix index 67e958a..e407478 100644 --- a/modules/services/nginx/module.nix +++ b/modules/services/nginx.mod.nix @@ -3,11 +3,13 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkIf mkDefault; inherit (lib.options) mkEnableOption; cfg = config.modules.system.services.nginx; -in { +in +{ options.modules.system.services.nginx.enable = mkEnableOption "nginx"; config = mkIf cfg.enable { security = { @@ -25,7 +27,6 @@ in { recommendedOptimisation = true; recommendedGzipSettings = true; recommendedProxySettings = true; - recommendedZstdSettings = true; # nginx defaults to a 1MB size limit for uploads, which # *definitely* isn't enough for Git LFS. diff --git a/modules/services/owncloud/module.nix b/modules/services/owncloud.mod.nix similarity index 51% rename from modules/services/owncloud/module.nix rename to modules/services/owncloud.mod.nix index 2d7974e..2be69c1 100644 --- a/modules/services/owncloud/module.nix +++ b/modules/services/owncloud.mod.nix @@ -3,12 +3,14 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.meta) getExe'; inherit (lib.modules) mkIf; cfg = config.modules.system.services.owncloud; -in { +in +{ options.modules.system.services.owncloud.enable = lib.mkEnableOption "owncloud"; config = { @@ -16,33 +18,16 @@ in { description = "Owncloud client service"; # makes the graphical session start this service when it starts - wantedBy = ["graphical-session.target"]; + wantedBy = [ "graphical-session.target" ]; # when graphical session restarts or gets stopped, this also gets restarted/stopped. - partOf = ["graphical-session.target"]; + partOf = [ "graphical-session.target" ]; # gets started only after graphical session - after = ["graphical-session.target"]; + after = [ "graphical-session.target" ]; serviceConfig = { ExecStart = "${getExe' pkgs.owncloud-client "owncloud"}"; Restart = "always"; RestartSec = 30; - - # User = "cr"; - # Group = "cr"; - - Keyringmode = "shared"; - DevicePolicy = "closed"; - PrivateDevices = true; - PrivateTmp = true; - ProtectClock = true; - ProtectControlGroups = true; - ProtectControlGroup = true; - ProtectKernelLogs = true; - ProtectKernelModules = true; - ProtectKernelTunables = true; - - ProtectSystem = "strict"; - SystemCallFilter = "~@clock @cpu-emulation @debug @obsolete @module @mount @raw-io @reboot @swap @privileged"; }; }; }; diff --git a/modules/services/pipewire.nix b/modules/services/pipewire.mod.nix similarity index 96% rename from modules/services/pipewire.nix rename to modules/services/pipewire.mod.nix index bb375c3..0f5e74f 100644 --- a/modules/services/pipewire.nix +++ b/modules/services/pipewire.mod.nix @@ -2,10 +2,12 @@ config, lib, ... -}: let +}: +let cfg = config.modules.system.sound; inherit (lib.modules) mkIf; -in { +in +{ config = mkIf cfg.enable { services.pulseaudio.enable = false; services.pipewire = { diff --git a/modules/services/postgresql/module.nix b/modules/services/postgresql.mod.nix similarity index 89% rename from modules/services/postgresql/module.nix rename to modules/services/postgresql.mod.nix index 84e95b5..363128d 100644 --- a/modules/services/postgresql/module.nix +++ b/modules/services/postgresql.mod.nix @@ -3,19 +3,21 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.system.services.database.postgresql; -in { +in +{ options.modules.system.services.database.postgresql.enable = mkEnableOption "postgresql"; config = mkIf cfg.enable { services.postgresql = { enable = true; package = pkgs.postgresql_17; - # NOTE: it is imperative to create this when starting postgresql! + # NOTE: it is imperative to create this manually when starting postgresql. dataDir = "/srv/data/postgresql/${config.services.postgresql.package.psqlSchema}"; # Whether PostgreSQL should listen on all network interfaces. @@ -27,6 +29,9 @@ in { ensureDatabases = [ "git" + "grafana" + "stalwart" + "plausible" ]; ensureUsers = [ @@ -44,6 +49,18 @@ in { name = "git"; ensureDBOwnership = true; } + { + name = "grafana"; + ensureDBOwnership = true; + } + { + name = "stalwart"; + ensureDBOwnership = true; + } + { + name = "plausible"; + ensureDBOwnership = true; + } ]; settings = { # taken from https://pgconfigurator.cybertec.at/ diff --git a/modules/services/printing.mod.nix b/modules/services/printing.mod.nix new file mode 100644 index 0000000..ea20bf8 --- /dev/null +++ b/modules/services/printing.mod.nix @@ -0,0 +1,58 @@ +{ + lib, + pkgs, + ... +}: +let + inherit (lib.options) mkEnableOption; +in +{ + options.modules.services.cups.enable = mkEnableOption "CUPS, the Common UNIX printing system"; + + config = { + services = { + # enable CUPS, the Common UNIX printing system. + printing = { + enable = true; + + # Move CUPSd's temporary directory. + # By default, it resides in /tmp. + tempDir = "/tmp/cups"; + + # Do not advertise shared printers. + browsing = true; + + # browsedConf = '' + # BrowseDNSSDSubTypes _cups,_print + # BrowseLocalProtocols all + # BrowseRemoteProtocols all + # CreateIPPPrinterQueues All + + # BrowseProtocols all + # ''; + + # Enable the CUPS webinterface, accessible at localhost:631. + webInterface = true; + + logLevel = "debug"; + + # Some local or network printers might need additional drivers. + # These can be added into here. + drivers = with pkgs; [ + gutenprint + cups-kyocera-ecosys-m552x-p502x + cups-filters + ]; + }; + + # Add and autodiscover printers on the network via the IPP everywhere[1] protocol. + # [1] https://www.pwg.org/ipp/everywhere.html + avahi = { + enable = true; + nssmdns4 = true; + nssmdns6 = true; + openFirewall = true; + }; + }; + }; +} diff --git a/modules/services/prometheus/prometheus.mod.nix b/modules/services/prometheus/prometheus.mod.nix new file mode 100644 index 0000000..e5933d2 --- /dev/null +++ b/modules/services/prometheus/prometheus.mod.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.system.services.prometheus; + port = 4022; +in +{ + options.modules.system.services.prometheus.enable = mkEnableOption "Grafana, a graphing service"; + + config = mkIf cfg.enable { + services.prometheus = { + enable = true; + package = pkgs.prometheus; + inherit port; + + exporters = { + node = { + enable = true; + port = 4023; + enabledCollectors = [ + "systemd" + "processes" + ]; + }; + + postgres = { + enable = true; + port = 4024; + user = "postgres"; + }; + nginx = { + enable = true; + port = 4025; + }; + }; + scrapeConfigs = [ + { + job_name = "prometheus"; + scrape_interval = "30s"; + static_configs = [ { targets = [ "localhost:${toString port}" ]; } ]; + } + { + job_name = "node"; + scrape_interval = "30s"; + static_configs = [ + { targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ]; } + ]; + } + { + job_name = "postgres"; + scrape_interval = "30s"; + static_configs = [ + { targets = [ "localhost:${toString config.services.prometheus.exporters.postgres.port}" ]; } + ]; + } + { + job_name = "nginx"; + scrape_interval = "30s"; + static_configs = [ + { targets = [ "localhost:${toString config.services.prometheus.exporters.nginx.port}" ]; } + ]; + } + ]; + }; + }; +} diff --git a/modules/services/searxng/module.nix b/modules/services/searxng/module.nix deleted file mode 100644 index bfc0e5d..0000000 --- a/modules/services/searxng/module.nix +++ /dev/null @@ -1,119 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib.options) mkEnableOption; - inherit (lib.modules) mkIf; - inherit (builtins) toString; - cfg = config.modules.services.searxng; - port = 4021; -in { - options.modules.services.searxng.enable = mkEnableOption "SearXNG, a private search engine"; - - config = mkIf cfg.enable { - networking.firewall.allowedTCPPorts = [port]; - - services = { - nginx.enable = true; - searx = { - enable = true; - package = pkgs.searxng; - environmentFile = "/srv/data/searxng/super_secret_file"; - settings = { - general = { - name = "Copesearch"; - privacypolicy_url = false; - debug = false; - enable_metrics = false; - }; - - search = { - safe_search = 1; - - formats = ["html" "json" "rss"]; - autocomplete = "google"; # "dbpedia", "duckduckgo", "google", "startpage", "swisscows", "qwant", "wikipedia" - leave blank to turn it off by default - default_lang = "en"; - }; - - ui = { - query_in_title = true; - theme_args.simple_style = "dark"; # auto, dark, light - results_on_new_tab = false; - }; - - server = { - inherit port; - limiter = false; - image_proxy = false; - - # taken from https://github.com/searx/searx/issues/715 - default_http_headers = { - X-Content-Type-Options = "nosniff"; - X-XSS-Protection = "1; mode=block"; - X-Download-Options = "noopen"; - X-Robots-Tag = "noindex, nofollow"; - Referrer-Policy = "no-referrer"; - }; - }; - - # shamelessly stolen from NotAShelf - engines = [ - { - name = "wikipedia"; - engine = "wikipedia"; - shortcut = "w"; - base_url = "https://wikipedia.org/"; - } - { - name = "duckduckgo"; - engine = "duckduckgo"; - shortcut = "ddg"; - } - { - name = "google"; - engine = "google"; - shortcut = "g"; - use_mobile_ui = false; - } - { - name = "archwiki"; - engine = "archlinux"; - shortcut = "aw"; - } - { - name = "github"; - engine = "github"; - categories = "it"; - shortcut = "gh"; - } - { - name = "nixpkgs"; - shortcut = "nx"; - engine = "elasticsearch"; - categories = "dev,nix"; - base_url = "https://nixos-search-5886075189.us-east-1.bonsaisearch.net:443"; - index = "latest-31-nixos-unstable"; - query_type = "match"; - } - ]; - }; - }; - nginx.virtualHosts."search.copeberg.org" = { - locations."/".proxyPass = "http://127.0.0.1:${toString port}"; - extraConfig = '' - access_log /dev/null; - error_log /dev/null; - proxy_connect_timeout 60s; - proxy_send_timeout 60s; - proxy_read_timeout 60s; - ''; - - quic = true; - forceSSL = true; - enableACME = true; - }; - }; - }; -} diff --git a/modules/services/spotifyd.mod.nix b/modules/services/spotifyd.mod.nix new file mode 100644 index 0000000..6ffecc9 --- /dev/null +++ b/modules/services/spotifyd.mod.nix @@ -0,0 +1,18 @@ +{ + config, + lib, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (config.modules.system) isGraphical; +in +{ + # TODO: setup + services.spotifyd = mkIf isGraphical { + enable = true; + settings = { + # backend = "pipe"; + }; + }; +} diff --git a/modules/services/ssh.nix b/modules/services/ssh.mod.nix similarity index 51% rename from modules/services/ssh.nix rename to modules/services/ssh.mod.nix index 248d54b..b8f5315 100644 --- a/modules/services/ssh.nix +++ b/modules/services/ssh.mod.nix @@ -1,16 +1,13 @@ -{lib, ...}: let +{ lib, ... }: +let inherit (lib.options) mkEnableOption; -in { +in +{ options.modules.programs.ssh.enable = mkEnableOption "ssh"; config = { - # set the ssh socket globally. This alows all applications and shells to use - # the ssh-agent. - environment.sessionVariables.SSH_AUTH_SOCK = "/run/user/1000/ssh-agent"; - programs.ssh.startAgent = true; - services.openssh = { enable = true; - ports = [22]; + ports = [ 22 ]; settings = { PasswordAuthentication = false; PermitRootLogin = "no"; diff --git a/modules/services/stalwart.mod.nix b/modules/services/stalwart.mod.nix new file mode 100644 index 0000000..93f8273 --- /dev/null +++ b/modules/services/stalwart.mod.nix @@ -0,0 +1,135 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + domain = "charlieroot.dev"; + + cfg = config.modules.system.services.stalwart; +in +{ + options.modules.system.services.stalwart.enable = mkEnableOption "stalwart"; + config = mkIf cfg.enable { + # create the stallwart user + users.users.stalwart = { + home = "/var/lib/stalwart-mail"; + useDefaultShell = true; + group = "stalwart"; + isSystemUser = true; + }; + users.groups.stalwart = { }; + + services.stalwart-mail = { + enable = true; + package = pkgs.stalwart-mail; + openFirewall = true; + settings = { + email = { + # All incoming messages via SMTP or LMTP are automatically encrypted before they are written to disk, + # provided the user has uploaded their S/MIME certificate or OpenPGP public key. + + encryption.enable = true; + }; + server = { + # The default server hostname is utilized in SMTP EHLO commands, + # as well as included in message headers and reports. + hostname = domain; + tls = { + # Specifies whether the TLS encryption is available for the listener. + enable = true; + + # Specifies whether the listener should use implicit or explicit TLS encryption. + # If set to false (the default), the listener will use explicit TLS encryption, + # which requires clients to initiate a STARTTLS command before upgrading the connection + # to an encrypted one. If set to true, the listener will use implicit TLS encryption, + # which requires the connection to be encrypted from the start. + implicit = true; + }; + + # Listeners are responsible for receiving incoming TCP connections. + listener = { + # Unencrypted SMTP connections are received on port 25 by default. + # This is the standard port for SMTP, and is used by mail servers to send email to each other. + smtp = { + protocol = "smtp"; + bind = [ "[::]:25" ]; + tls.implicit = true; + }; + # SMTP submissions with implicit TLS are received on port 465 by default. + # This is the standard port for SMTP submissions with native implicit TLS, + # and is used by mail clients to send email to mail servers. + + submissions = { + bind = [ "[::]:465" ]; + protocol = "smtp"; + tls.implicit = true; + }; + imaps = { + bind = [ "[::]:993" ]; + protocol = "imap"; + tls.implicit = true; + }; + management = { + bind = [ "127.0.0.1:8080" ]; + protocol = "http"; + tls.implicit = true; + }; + }; + lookup.default = { + hostname = "mail.${domain}"; + inherit domain; + }; + }; + # storage = { + # data = "postgresql"; + # blob = "postgresql"; + # fts = "postgresql"; + # lookup = "postgresql"; + # full-text = { + # default-language = "en"; + # }; + # }; + # store = { + # postgresql = { + # # Specifies the database type, set to "postgresql" for PostgreSQL. + # type = "postgresql"; + + # # The hostname or IP address of the PostgreSQL server. + # host = "localhost"; + + # # Port PostgreSQL runs on. Defaults to 5432. + # port = "5432"; + + # # Name of the database to connect to. + # # TODO: add this to PostgreSQL. + # database = "stalwart"; + + # # The username used for authentication with the PostgreSQL server. + # # TODO: add this to PostgreSQL. + # user = "stalwart"; + + # password = ""; + + # # Enable TLS + # tls.enable = true; + # }; + # }; + }; + }; + services.nginx = { + enable = true; + virtualHosts."mail.${domain}" = { + addSSL = true; + enableACME = true; + locations."/" = { + proxyPass = "http://localhost:${toString 8080}"; + }; + }; + }; + }; +} diff --git a/modules/services/usbguard/module.nix b/modules/services/usbguard.mod.nix similarity index 84% rename from modules/services/usbguard/module.nix rename to modules/services/usbguard.mod.nix index 9bdaa71..40e8353 100644 --- a/modules/services/usbguard/module.nix +++ b/modules/services/usbguard.mod.nix @@ -3,18 +3,23 @@ lib, pkgs, ... -}: let +}: +let inherit (config.meta.mainUser) username; inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.services.usbguard; -in { +in +{ options.modules.services.usbguard.enable = mkEnableOption "usbguard"; config = mkIf cfg.enable { - environment.systemPackages = [pkgs.usbguard]; + environment.systemPackages = [ pkgs.usbguard ]; services.usbguard = { enable = true; - IPCAllowedUsers = ["root" "${username}"]; + IPCAllowedUsers = [ + "root" + "${username}" + ]; presentDevicePolicy = "allow"; rules = '' allow with-interface equals { 08:*:* } diff --git a/modules/services/uwsm/module.nix b/modules/services/uwsm.mod.nix similarity index 96% rename from modules/services/uwsm/module.nix rename to modules/services/uwsm.mod.nix index 8a16d98..bc4bc7e 100644 --- a/modules/services/uwsm/module.nix +++ b/modules/services/uwsm.mod.nix @@ -3,11 +3,13 @@ lib, pkgs, ... -}: let +}: +let cfg = config.modules.services.uwsm; inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; -in { +in +{ options.modules.services.uwsm.enable = mkEnableOption "uwsm"; config = mkIf cfg.enable { programs.uwsm = { diff --git a/modules/services/wayneko/module.nix b/modules/services/wayneko.mod.nix similarity index 55% rename from modules/services/wayneko/module.nix rename to modules/services/wayneko.mod.nix index d3385e5..2eaf564 100644 --- a/modules/services/wayneko/module.nix +++ b/modules/services/wayneko.mod.nix @@ -1,50 +1,75 @@ { - config, lib, pkgs, ... -}: let +}: +let inherit (lib.meta) getExe; -in { + + custom-wayneko = pkgs.wayneko.overrideAttrs { + src = pkgs.fetchFromGitea { + domain = "copeberg.org"; + owner = "virt"; + repo = "wayneko"; + rev = "3ed4e4e1f847213e712fe22e0278ec62c4fa2cf2"; + hash = "sha256-NxNrcQkx82SQ5GRqcJbbgM/Qg3GY8Whu5m5wI3zQi18="; + }; + + hash = ""; + }; +in +{ systemd.user.services.wayneko = { description = "Wayneko, as a systemd service"; # makes the graphical session start this service when it starts - wantedBy = ["graphical-session.target"]; + wantedBy = [ "graphical-session.target" ]; # when graphical session restarts or gets stopped, this also gets restarted/stopped. - partOf = ["graphical-session.target"]; + partOf = [ "graphical-session.target" ]; # gets started only after graphical session - after = ["graphical-session.target"]; + after = [ "graphical-session.target" ]; serviceConfig = { - ExecStart = "${getExe pkgs.wayneko} --layer top --follow-pointer false"; + ExecStart = '' + ${getExe custom-wayneko}\ + --layer top\ + --type striped\ + --background-colour 0xb4befe\ + --outline-colour 0x1e1e2e + ''; Restart = "on-failure"; RestartSec = 1; TimeoutStopSec = 10; + CapabilityBoundingSet = [ "" ]; + DevicePolicy = "closed"; LockPersonality = true; MemoryDenyWriteExecute = true; NoNewPrivileges = true; - - PrivateTmp = true; PrivateDevices = true; - DevicePolicy = "closed"; PrivateNetwork = true; + PrivateTmp = true; + PrivateUsers = true; + ProcSubset = "pid"; + ProtectClock = true; ProtectControlGroups = true; ProtectControlGroup = true; + ProtectHome = "read-only"; + ProtectHostname = true; ProtectKernelLogs = true; ProtectKernelModules = true; ProtectKernelTunables = true; + ProtectProc = "invisible"; ProtectSystem = "strict"; - ProtectHome = "read-only"; - RestrictNamespaces = true; RestrictRealtime = true; RestrictRealTime = true; RestrictSUIDSGID = true; - SystemCallFilter = "~@clock @cpu-emulation @debug @obsolete @module @mount @raw-io @reboot @swap"; + SystemCallArchitectures = [ "native" ]; + + SystemCallFilter = "~@clock @cpu-emulation @debug @obsolete @module @mount @raw-io @reboot @swap @privileged"; }; }; } diff --git a/modules/style/colors.nix b/modules/style/colors.mod.nix similarity index 76% rename from modules/style/colors.nix rename to modules/style/colors.mod.nix index 07934ae..344788d 100644 --- a/modules/style/colors.nix +++ b/modules/style/colors.mod.nix @@ -9,10 +9,24 @@ config, lib, ... -}: let +}: +let inherit (lib.options) mkOption literalExpression; - inherit (lib.strings) toLower replaceStrings removePrefix hasPrefix isString; - inherit (lib.types) str nullOr enum mkOptionType attrsOf coercedTo; + inherit (lib.strings) + toLower + replaceStrings + removePrefix + hasPrefix + isString + ; + inherit (lib.types) + str + nullOr + enum + mkOptionType + attrsOf + coercedTo + ; cfg = config.modules.style; @@ -24,18 +38,26 @@ }; colorType = attrsOf (coercedTo str (removePrefix "#") hexColorType); - nameToSlug = name: toLower (replaceStrings [" "] ["-"] name); - getPaletteFromScheme = slug: - if builtins.pathExists ./palettes/${slug}.nix - then (import ./palettes/${slug}.nix).colorscheme.palette - else throw "The following colorscheme was imported but not found: ${slug}"; -in { + nameToSlug = name: toLower (replaceStrings [ " " ] [ "-" ] name); + getPaletteFromScheme = + slug: + if builtins.pathExists ./palettes/${slug}.nix then + (import ./palettes/${slug}.nix).colorscheme.palette + else + throw "The following colorscheme was imported but not found: ${slug}"; +in +{ options.modules.style = { colorScheme = { name = mkOption { - type = nullOr (enum ["Catppuccin Mocha" "Zenburn" "Black Metal Venom" "Gruvbox"]); + type = nullOr (enum [ + "Catppuccin Mocha" + "Zenburn" + "Black Metal Venom" + "Gruvbox" + ]); description = "The colorscheme that should be used globally to theme your system."; - default = "Gruvbox"; + default = "Catppuccin Mocha"; }; slug = mkOption { @@ -83,11 +105,11 @@ in { }; variant = mkOption { - type = enum ["dark" "light"]; - default = - if builtins.substring 0 1 cfg.colorScheme.colors.base00 < "5" - then "dark" - else "light"; + type = enum [ + "dark" + "light" + ]; + default = if builtins.substring 0 1 cfg.colorScheme.colors.base00 < "5" then "dark" else "light"; description = '' Whether the scheme is dark or light ''; diff --git a/modules/style/default.nix b/modules/style/default.nix deleted file mode 100644 index 8cb43d4..0000000 --- a/modules/style/default.nix +++ /dev/null @@ -1,8 +0,0 @@ -_: { - imports = [ - ./qt.nix - ./gtk.nix - ./module.nix - ./fonts.nix - ]; -} diff --git a/modules/style/fonts.nix b/modules/style/fonts.mod.nix similarity index 61% rename from modules/style/fonts.nix rename to modules/style/fonts.mod.nix index 18727cb..dcde8b2 100644 --- a/modules/style/fonts.nix +++ b/modules/style/fonts.mod.nix @@ -1,9 +1,11 @@ -{pkgs, ...}: let +{ pkgs, ... }: +let inherit (builtins) mapAttrs; - valiosevka = pkgs.iosevka.override { + + fancy-iosevka = pkgs.iosevka.override { privateBuildPlan = { - family = "valiosevka"; - spacing = "normal"; + family = "fancy-iosevka"; + spacing = "term"; serifs = "sans"; noCvSs = true; exportGlyphNames = false; @@ -16,10 +18,31 @@ f = "diagonal-tailed-crossbar-at-x-height"; }; }; + weights.Regular = { + shape = 400; + menu = 400; + css = 400; + }; + weights.Bold = { + shape = 700; + menu = 700; + css = 700; + }; + widths.Condensed = { + shape = 500; + menu = 3; + css = "condensed"; + }; + widths.normal = { + shape = 600; + menu = 5; + css = "normal"; + }; }; set = "Fancy"; }; -in { +in +{ # A (somewhat) sane list of fonts to be installed. fonts = { fontconfig = { @@ -37,25 +60,26 @@ in { # Set the defalt fonts. This was taken from raf, # many thanks. - defaultFonts = let - common = [ - "Iosevka Nerd Font" - "Roboto Mono Nerd Font" - "Fira Code Nerd Font" - "Symbols Nerd Font" - "Noto Color Emoji" - ]; - in + defaultFonts = + let + common = [ + "Iosevka Nerd Font" + "Roboto Mono Nerd Font" + "Fira Code Nerd Font" + "Symbols Nerd Font" + "Noto Color Emoji" + "JetbrainsMono Nerd Font" + ]; + in mapAttrs (_: fonts: fonts ++ common) { - serif = ["Noto Serif"]; - sansSerif = ["Lexend"]; - emoji = ["Noto Color Emoji"]; - monospace = ["Iosevka Nerd Font"]; + serif = [ "Noto Serif" ]; + sansSerif = [ "Lexend" ]; + emoji = [ "Noto Color Emoji" ]; + monospace = [ "Iosevka Nerd Font" ]; }; }; packages = builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) material-icons material-design-icons lexend @@ -66,14 +90,14 @@ in { corefonts font-awesome ; - inherit - (pkgs.nerd-fonts) + inherit (pkgs.nerd-fonts) iosevka jetbrains-mono comic-shanns-mono symbols-only ; - inherit valiosevka; + + # inherit fancy-iosevka; }; fontDir = { # Whether to create a directory with links to all fonts in diff --git a/modules/style/gtk-colors.nix b/modules/style/gtk-colors.nix new file mode 100644 index 0000000..eed6ff9 --- /dev/null +++ b/modules/style/gtk-colors.nix @@ -0,0 +1,93 @@ +# blatantly stolen from sioodmy, thanks :3 +{ colors }: +with colors; +'' + @define-color accent_color #${base0D}; + @define-color accent_bg_color #${base0D}; + @define-color accent_fg_color #${base00}; + @define-color destructive_color #${base08}; + @define-color destructive_bg_color #${base08}; + @define-color destructive_fg_color #${base00}; + @define-color success_color #${base0B}; + @define-color success_bg_color #${base0B}; + @define-color success_fg_color #${base00}; + @define-color warning_color #${base0E}; + @define-color warning_bg_color #${base0E}; + @define-color warning_fg_color #${base00}; + @define-color error_color #${base08}; + @define-color error_bg_color #${base08}; + @define-color error_fg_color #${base00}; + @define-color window_bg_color #${base00}; + @define-color window_fg_color #${base05}; + @define-color view_bg_color #${base00}; + @define-color view_fg_color #${base05}; + @define-color headerbar_bg_color #${base01}; + @define-color headerbar_fg_color #${base05}; + @define-color headerbar_border_color #${base01}; + @define-color headerbar_backdrop_color @window_bg_color; + @define-color headerbar_shade_color rgba(0, 0, 0, 0.07); + @define-color headerbar_darker_shade_color rgba(0, 0, 0, 0.07); + @define-color sidebar_bg_color #${base01}; + @define-color sidebar_fg_color #${base05}; + @define-color sidebar_backdrop_color @window_bg_color; + @define-color sidebar_shade_color rgba(0, 0, 0, 0.07); + @define-color secondary_sidebar_bg_color @sidebar_bg_color; + @define-color secondary_sidebar_fg_color @sidebar_fg_color; + @define-color secondary_sidebar_backdrop_color @sidebar_backdrop_color; + @define-color secondary_sidebar_shade_color @sidebar_shade_color; + @define-color card_bg_color #${base01}; + @define-color card_fg_color #${base05}; + @define-color card_shade_color rgba(0, 0, 0, 0.07); + @define-color dialog_bg_color #${base01}; + @define-color dialog_fg_color #${base05}; + @define-color popover_bg_color #${base01}; + @define-color popover_fg_color #${base05}; + @define-color popover_shade_color rgba(0, 0, 0, 0.07); + @define-color shade_color rgba(0, 0, 0, 0.07); + @define-color scrollbar_outline_color #${base02}; + @define-color blue_1 #${base0D}; + @define-color blue_2 #${base0D}; + @define-color blue_3 #${base0D}; + @define-color blue_4 #${base0D}; + @define-color blue_5 #${base0D}; + @define-color green_1 #${base0B}; + @define-color green_2 #${base0B}; + @define-color green_3 #${base0B}; + @define-color green_4 #${base0B}; + @define-color green_5 #${base0B}; + @define-color yellow_1 #${base0A}; + @define-color yellow_2 #${base0A}; + @define-color yellow_3 #${base0A}; + @define-color yellow_4 #${base0A}; + @define-color yellow_5 #${base0A}; + @define-color orange_1 #${base09}; + @define-color orange_2 #${base09}; + @define-color orange_3 #${base09}; + @define-color orange_4 #${base09}; + @define-color orange_5 #${base09}; + @define-color red_1 #${base08}; + @define-color red_2 #${base08}; + @define-color red_3 #${base08}; + @define-color red_4 #${base08}; + @define-color red_5 #${base08}; + @define-color purple_1 #${base0E}; + @define-color purple_2 #${base0E}; + @define-color purple_3 #${base0E}; + @define-color purple_4 #${base0E}; + @define-color purple_5 #${base0E}; + @define-color brown_1 #${base0F}; + @define-color brown_2 #${base0F}; + @define-color brown_3 #${base0F}; + @define-color brown_4 #${base0F}; + @define-color brown_5 #${base0F}; + @define-color light_1 #${base01}; + @define-color light_2 #${base01}; + @define-color light_3 #${base01}; + @define-color light_4 #${base01}; + @define-color light_5 #${base01}; + @define-color dark_1 #${base01}; + @define-color dark_2 #${base01}; + @define-color dark_3 #${base01}; + @define-color dark_4 #${base01}; + @define-color dark_5 #${base01}; +'' diff --git a/modules/style/gtk.mod.nix b/modules/style/gtk.mod.nix new file mode 100644 index 0000000..8be837b --- /dev/null +++ b/modules/style/gtk.mod.nix @@ -0,0 +1,117 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (builtins) toString isBool; + inherit (lib.generators) toINI; + inherit (lib.modules) mkIf; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.strings) escape; + inherit (lib.trivial) boolToString; + inherit (lib.types) str package; + + cfg = config.modules.theming.gtk; + + toGtk3Ini = toINI { + mkKeyValue = + key: value: + let + value' = if isBool value then boolToString value else toString value; + in + "${escape [ "=" ] key}=${value'}"; + }; + + gtkIni = { + gtk-application-prefer-dark-theme = 1; + gtk-font-name = "Lexend 11"; + gtk-icon-theme-name = "Papirus"; + gtk-xft-antialias = 1; + gtk-xft-hinting = 1; + gtk-xft-hintstyle = "hintslight"; + gtk-xft-rgba = "rgb"; + gtk-cursor-theme-name = "BreezeX-RosePine-Linux"; + gtk-theme-name = "Gruvbox-Dark"; + }; +in +{ + options.modules.theming.gtk = { + enable = mkEnableOption "Wether to enable GTK theming"; + theme = { + name = mkOption { + description = "The GTK theme name"; + default = "Gruvbox-Dark"; + type = str; + }; + package = mkOption { + description = "The GTK theme package"; + default = pkgs.gruvbox-gtk-theme; + type = package; + }; + }; + iconTheme = { + description = "The GTK icon theme"; + name = mkOption { + description = "The GTK icon theme name"; + default = "Papirus"; + type = str; + }; + package = mkOption { + description = "The GTK icon theme package"; + default = pkgs.papirus-icon-theme; + type = package; + }; + }; + }; + config = + let + cursorSize = 32; + in + mkIf cfg.enable { + programs.dconf.enable = true; + environment = { + systemPackages = builtins.attrValues { + inherit (pkgs) + rose-pine-cursor + gruvbox-gtk-theme + papirus-icon-theme + colloid-icon-theme + ; + }; + variables = { + GTK_THEME = cfg.theme.name; + XCURSOR_THEME = "BreezeX-RosePine-Linux"; + XCURSOR_SIZE = cursorSize; + }; + etc = + let + css = import ./gtk-colors.nix { inherit (config.modules.style.colorScheme) colors; }; + in + { + "xdg/gtk-4.0/settings.ini".text = toGtk3Ini { + Settings = gtkIni; + }; + "xdg/gtk-3.0/settings.ini".text = toGtk3Ini { + Settings = gtkIni; + }; + "xdg/gtk-4.0/gtk.css".text = css; + "xdg/gtk-3.0/gtk.css".text = css; + + "xdg/gtk-2.0/gtkrc".text = '' + gtk-cursor-theme-name = BreezeX-RosePine-Linux + gtk-cursor-theme-size = ${toString cursorSize} + gtk-theme-name = ${cfg.theme.name} + gtk-icon-theme-name = ${cfg.iconTheme.name} + gtk-font-name = Lexend 11 + ''; + + "xdg/Xresources".text = '' + Xcursor.size: ${toString cursorSize} + Xcursor.theme: BreezeX-RosePine-Linux + ''; + }; + }; + }; +} diff --git a/modules/style/gtk.nix b/modules/style/gtk.nix deleted file mode 100644 index 2e180bc..0000000 --- a/modules/style/gtk.nix +++ /dev/null @@ -1,65 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib.modules) mkIf; - inherit (lib.options) mkOption mkEnableOption; - inherit (lib.types) str package; - - cfg = config.modules.theming.gtk; -in { - options.modules.theming.gtk = { - enable = mkEnableOption "Wether to enable GTK theming"; - theme = { - name = mkOption { - description = "The GTK theme name"; - default = "Gruvbox-Dark-BL"; - type = str; - }; - package = mkOption { - description = "The GTK theme package"; - default = pkgs.gruvbox-gtk-theme; - type = package; - }; - }; - iconTheme = { - description = "The GTK icon theme"; - name = mkOption { - description = "The GTK icon theme name"; - default = "Papirus-Dark"; - type = str; - }; - package = mkOption { - description = "The GTK icon theme package"; - default = pkgs.papirus-icon-theme; - type = package; - }; - }; - }; - config = mkIf cfg.enable { - # NOTE: we need this or gtk breaks - programs.dconf.enable = true; - - environment = { - systemPackages = builtins.attrValues { - inherit - (pkgs) - gruvbox-gtk-theme - papirus-icon-theme - ; - }; - variables = let - cursorSize = 32; - in { - GTK_THEME = "Gruvbox-Dark"; - XCURSOR_THEME = "BreezeX-RosePine-Linux"; - XCURSOR_SIZE = cursorSize; - - HYPRCURSOR_THEME = "BreezeX-RosePine-Linux"; - HYPRCURSOR_SIZE = cursorSize; - }; - }; - }; -} diff --git a/modules/style/module.nix b/modules/style/module.nix deleted file mode 100644 index 71664a0..0000000 --- a/modules/style/module.nix +++ /dev/null @@ -1,8 +0,0 @@ -_: { - imports = [ - ./colors.nix - ./fonts.nix - ./gtk.nix - ./theming.nix - ]; -} diff --git a/modules/style/palettes/catppuccin-mocha.nix b/modules/style/palettes/catppuccin-mocha.nix index cca0510..6c2d23d 100644 --- a/modules/style/palettes/catppuccin-mocha.nix +++ b/modules/style/palettes/catppuccin-mocha.nix @@ -14,8 +14,8 @@ base07 = "#b4befe"; # lavender base08 = "#f38ba8"; # red base09 = "#fab387"; # peach - base0A = "#a6e3a1"; # yellow - base0B = "#94e2d5"; # green + base0A = "#f9e2af"; # yellow + base0B = "#a6e3a1"; # green base0C = "#a6e3a1"; # teal base0D = "#89b4fa"; # blue base0E = "#cba6f7"; # mauve diff --git a/modules/style/qt.nix b/modules/style/qt.mod.nix similarity index 87% rename from modules/style/qt.nix rename to modules/style/qt.mod.nix index 77413e4..76769ed 100644 --- a/modules/style/qt.nix +++ b/modules/style/qt.mod.nix @@ -3,13 +3,15 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption mkOption; inherit (lib.types) str package; cfg = config.modules.theming.qt; -in { +in +{ options.modules.theming.qt = { enable = mkEnableOption "qt theming"; name = mkOption { @@ -34,7 +36,10 @@ in { }; }; - config = - mkIf cfg.enable { + config = mkIf cfg.enable { + qt = { + enable = true; + platformTheme = "qt5ct"; }; + }; } diff --git a/modules/style/quickshell/module.nix b/modules/style/quickshell/module.nix deleted file mode 100644 index be5fc94..0000000 --- a/modules/style/quickshell/module.nix +++ /dev/null @@ -1,26 +0,0 @@ -{ - config, - lib, - inputs, - pkgs, - ... -}: let - # inherit (inputs) quickshell; - # inherit (lib.generators) toKeyValue; -in { - # environment.systemPackages = [ - # qt6.qtimageformats # amog - # qt6.qt5compat # shader fx - # (quickshell.packages.x86_64-linux.default.override { - # withJemalloc = true; - # withQtSvg = true; - # withX11 = true; - # withPipewire = true; - # withPam = true; - # withHyprland = true; - # }) - # pamtester # lockscreen - # grim - # imagemagick # screenshot - # ]; -} diff --git a/modules/style/quickshell/quickshell.mod.nix b/modules/style/quickshell/quickshell.mod.nix new file mode 100644 index 0000000..5ab2e37 --- /dev/null +++ b/modules/style/quickshell/quickshell.mod.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + pkgs, + sources, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.theming.quickshell; +in +{ + options.modules.theming.quickshell.enable = mkEnableOption "quickshell"; + + config = mkIf cfg.enable { + environment.systemPackages = with pkgs; [ + (pkgs.callPackage (sources.quickshell + "/default.nix") { }) + qt6.qtimageformats + qt6.qt5compat + qt6.qtmultimedia + qt6.qtdeclarative + qt6.qtsvg + qt6.qtwayland + qt6.qtbase + kdePackages.breeze + kdePackages.breeze-icons + ]; + + # taken from outfoxxed. + qt.enable = true; + }; +} diff --git a/modules/style/quickshell/shell/.qmlls.ini b/modules/style/quickshell/shell/.qmlls.ini new file mode 120000 index 0000000..a780449 --- /dev/null +++ b/modules/style/quickshell/shell/.qmlls.ini @@ -0,0 +1 @@ +/run/user/1000/quickshell/vfs/4f7a8066a49ba487f5b2754750896151/.qmlls.ini \ No newline at end of file diff --git a/modules/style/quickshell/shell/AudioPopup.qml b/modules/style/quickshell/shell/AudioPopup.qml new file mode 100644 index 0000000..383a9ef --- /dev/null +++ b/modules/style/quickshell/shell/AudioPopup.qml @@ -0,0 +1,105 @@ +pragma ComponentBehavior: Bound +pragma Singleton + +import QtQuick +import Quickshell +import QtQuick.Layouts +import Quickshell.Services.Pipewire +import Quickshell.Wayland + +import qs.config + +Singleton { + id: root + + property real volume: Pipewire.defaultAudioSink?.audio?.volume ?? 0 + property real popupOpacity: 0 + + PwObjectTracker { + objects: [Pipewire.defaultAudioSink] + } + + onVolumeChanged: { + root.popupOpacity = 1; + loader.activeAsync = true; + timer.restart(); + timer_opacity.restart(); + } + + LazyLoader { + id: loader + activeAsync: false + + PanelWindow { + id: popup + visible: true + implicitWidth: rect.implicitWidth + implicitHeight: 50 + color: "transparent" + mask: Region {} + exclusionMode: ExclusionMode.Ignore + WlrLayershell.layer: WlrLayer.Overlay + + anchors.bottom: true + margins.bottom: 100 + + Rectangle { + id: rect + Layout.fillWidth: true + anchors.fill: parent + color: Colors.surface0 + implicitWidth: 300 + implicitHeight: parent.implicitHeight + radius: 5 + opacity: root.popupOpacity + + Behavior on opacity { + NumberAnimation { + duration: 500 + easing.type: Easing.OutCubic + } + } + + Rectangle { + id: bar + color: Colors.blue + implicitWidth: rect.implicitWidth * root.volume - 20 + implicitHeight: 30 + topRightRadius: 5 + bottomRightRadius: 5 + + anchors { + left: parent.left + verticalCenter: parent.verticalCenter + } + + Behavior on implicitWidth { + NumberAnimation { + duration: 300 + easing.type: Easing.OutCubic + } + } + } + } + } + } + + Timer { + id: timer + interval: 2000 + running: false + onTriggered: loader.activeAsync = false + } + + Timer { + id: timer_opacity + interval: 1500 + running: false + onTriggered: { + root.popupOpacity = 0; + } + } + + function init() { + } +} diff --git a/modules/style/quickshell/shell/ClockWidget.qml b/modules/style/quickshell/shell/ClockWidget.qml new file mode 100644 index 0000000..6cf0ad7 --- /dev/null +++ b/modules/style/quickshell/shell/ClockWidget.qml @@ -0,0 +1,46 @@ +import QtQuick +import Quickshell + +Rectangle { + + + width: text.width + implicitHeight: text.height + // border.color: "black" + border.width: 2 + radius: 0 + color: "transparent" + + Behavior on implicitHeight { + NumberAnimation { + duration: 100 + easing.type: Easing.OutCubic + } + } + + Item { + width: parent.width + height: text.height + + anchors.centerIn: parent + + SystemClock { + id: clock + precision: SystemClock.Seconds + } + + Text { + id: text + anchors.centerIn: parent + property var date: Date() + + text: Qt.formatDateTime(clock.date, "hh mm") + + font.family: "ComicShannsMono Nerd Font Mono" + font.weight: Font.ExtraBold + font.pointSize: 12 + + color: "black" + } + } +} diff --git a/modules/style/quickshell/shell/Launcher.qml b/modules/style/quickshell/shell/Launcher.qml new file mode 100644 index 0000000..0cfebfb --- /dev/null +++ b/modules/style/quickshell/shell/Launcher.qml @@ -0,0 +1,310 @@ +pragma Singleton +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Widgets + +import qs.config + +Singleton { + id: launcher + property bool launcherOpen: false + + IpcHandler { + target: "launcher" + + function open(): void { + launcher.launcherOpen = true; + } + + function close(): void { + launcher.launcherOpen = false; + } + + function toggle(): void { + launcher.launcherOpen = !launcher.launcherOpen; + } + } + + LazyLoader { + id: loader + activeAsync: launcher.launcherOpen + + PanelWindow { + implicitWidth: 450 + implicitHeight: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10 + color: "transparent" + WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive + + Rectangle { + + height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10) + Behavior on height { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + width: 450 + color: Colors.base + radius: 5 + border.color: Colors.mantle + border.width: 2 + + ColumnLayout { + anchors.fill: parent + anchors.margins: 7 + anchors.bottomMargin: 0 + spacing: 0 + + Rectangle { + id: searchContainer + Layout.fillWidth: true + implicitHeight: searchbox.implicitHeight + 10 + color: Colors.base + radius: 3 + border.color: Colors.mantle + + RowLayout { + id: searchbox + anchors.fill: parent + anchors.margins: 5 + + TextInput { + id: search + Layout.fillWidth: true + color: Colors.text + font.pointSize: 13 + + focus: true + Keys.forwardTo: [list] + Keys.onEscapePressed: launcher.launcherOpen = false + + Keys.onPressed: event => { + if (event.modifiers & Qt.ControlModifier) { + if (event.key == Qt.Key_J) { + list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1; + event.accepted = true; + } else if (event.key == Qt.Key_K) { + list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1; + event.accepted = true; + } + } + } + + onAccepted: { + if (list.currentItem) { + list.currentItem.clicked(null); + } + } + + onTextChanged: { + list.currentIndex = 0; + } + } + } + } + + ListView { + id: list + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + cacheBuffer: 0 // works around QTBUG-131106 + //reuseItems: true + model: ScriptModel { + values: DesktopEntries.applications.values.map(object => { + const stxt = search.text.toLowerCase(); + const ntxt = object.name.toLowerCase(); + let si = 0; + let ni = 0; + + let matches = []; + let startMatch = -1; + + for (let si = 0; si != stxt.length; ++si) { + const sc = stxt[si]; + + while (true) { + // Drop any entries with letters that don't exist in order + if (ni == ntxt.length) + return null; + + const nc = ntxt[ni++]; + + if (nc == sc) { + if (startMatch == -1) + startMatch = ni; + break; + } else { + if (startMatch != -1) { + matches.push({ + index: startMatch, + length: ni - startMatch + }); + + startMatch = -1; + } + } + } + } + + if (startMatch != -1) { + matches.push({ + index: startMatch, + length: ni - startMatch + 1 + }); + } + + return { + object: object, + matches: matches + }; + }).filter(entry => entry !== null).sort((a, b) => { + let ai = 0; + let bi = 0; + let s = 0; + + while (ai != a.matches.length && bi != b.matches.length) { + const am = a.matches[ai]; + const bm = b.matches[bi]; + + s = bm.length - am.length; + if (s != 0) + return s; + + s = am.index - bm.index; + if (s != 0) + return s; + + ++ai; + ++bi; + } + + s = a.matches.length - b.matches.length; + if (s != 0) + return s; + + s = a.object.name.length - b.object.name.length; + if (s != 0) + return s; + + return a.object.name.localeCompare(b.object.name); + }).map(entry => entry.object) + + onValuesChanged: list.currentIndex = 0 + } + + topMargin: 7 + bottomMargin: list.count == 0 ? 0 : 7 + + add: Transition { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 100 + } + } + + displaced: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 1 + duration: 100 + } + } + + move: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 1 + duration: 100 + } + } + + remove: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 0 + duration: 100 + } + } + + highlight: Rectangle { + radius: 5 + color: "transparent" + border.color: Colors.lavender + border.width: 2 + } + keyNavigationEnabled: true + keyNavigationWraps: true + highlightMoveVelocity: -1 + highlightMoveDuration: 50 + preferredHighlightBegin: list.topMargin + preferredHighlightEnd: list.height - list.bottomMargin + highlightRangeMode: ListView.ApplyRange + snapMode: ListView.SnapToItem + + readonly property real delegateHeight: 44 + + delegate: MouseArea { + required property DesktopEntry modelData + + implicitHeight: list.delegateHeight + implicitWidth: ListView.view.width + + onClicked: { + modelData.execute(); + launcher.launcherOpen = false; + } + + RowLayout { + id: delegateLayout + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 5 + } + + IconImage { + Layout.alignment: Qt.AlignVCenter + asynchronous: true + implicitSize: 30 + source: Quickshell.iconPath(modelData.icon) + } + Text { + text: modelData.name + color: Colors.text + font.family: "JetBrainsMono Nerd Font Mono" + font.pointSize: 13 + Layout.alignment: Qt.AlignVCenter + } + } + } + } + } + } + } + } + function init() { + } +} diff --git a/modules/style/quickshell/shell/ReloadPopup.qml b/modules/style/quickshell/shell/ReloadPopup.qml new file mode 100644 index 0000000..513f814 --- /dev/null +++ b/modules/style/quickshell/shell/ReloadPopup.qml @@ -0,0 +1,127 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell + +Scope { + id: root + property bool failed + property string errorString + + // Connect to the Quickshell global to listen for the reload signals. + Connections { + target: Quickshell + + function onReloadCompleted() { + root.failed = false; + popupLoader.loading = true; + } + + function onReloadFailed(error: string) { + // Close any existing popup before making a new one. + popupLoader.active = false; + + root.failed = true; + root.errorString = error; + popupLoader.loading = true; + } + } + + // Keep the popup in a loader because it isn't needed most of the timeand will take up + // memory that could be used for something else. + LazyLoader { + id: popupLoader + + PanelWindow { + id: popup + + anchors { + top: true + right: true + } + + margins { + top: 25 + left: 25 + } + + width: rect.width + height: rect.height + + // color blending is a bit odd as detailed in the type reference. + color: "transparent" + + Rectangle { + id: rect + color: root.failed ? "#40802020" : "#40009020" + + implicitHeight: layout.implicitHeight + 50 + implicitWidth: layout.implicitWidth + 30 + + // Fills the whole area of the rectangle, making any clicks go to it, + // which dismiss the popup. + MouseArea { + id: mouseArea + anchors.fill: parent + onClicked: popupLoader.active = false + + // makes the mouse area track mouse hovering, so the hide animation + // can be paused when hovering. + hoverEnabled: true + } + + ColumnLayout { + id: layout + anchors { + top: parent.top + topMargin: 20 + horizontalCenter: parent.horizontalCenter + } + + Text { + text: root.failed ? "Reloaing failed." : "Reloading completed!" + color: "white" + } + + Text { + text: root.errorString + color: "white" + // When visible is false, it also takes up no space. + visible: root.errorString != "" + } + } + + // A progress bar on the bottom of the screen, showing how long until the + // popup is removed. + Rectangle { + id: bar + color: "#20ffffff" + anchors.bottom: parent.bottom + anchors.left: parent.left + height: 20 + + PropertyAnimation { + id: anim + target: bar + property: "width" + from: rect.width + to: 0 + duration: root.failed ? 10000 : 800 + onFinished: popupLoader.active = false + + // Pause the animation when the mouse is hovering over the popup, + // so it stays onscreen while reading. This updates reactively + // when the mouse moves on and off the popup. + paused: mouseArea.containsMouse + } + } + + // We could set `running: true` inside the animation, but the width of the + // rectangle might not be calculated yet, due to the layout. + // In the `Component.onCompleted` event handler, all of the component's + // properties and children have been initialized. + Component.onCompleted: anim.start() + } + } + } +} diff --git a/modules/style/quickshell/shell/SysTray.qml b/modules/style/quickshell/shell/SysTray.qml new file mode 100644 index 0000000..7445bcd --- /dev/null +++ b/modules/style/quickshell/shell/SysTray.qml @@ -0,0 +1,57 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import QtQuick.Layouts +import QtQuick.Effects +import QtQuick.Controls +import Quickshell +import Quickshell.Services.SystemTray + +Rectangle { + id: root + required property var bar + + width: parent.width + height: column.height + 10 + color: "#30c0ffff" + radius: 5 + border.color: "black" + border.width: 2 + + RowLayout { + id: column + spacing: 10 + + anchors.centerIn: parent + + Repeater { + model: SystemTray.items + + Item { + id: item + + required property SystemTrayItem modelData + + height: 35 + width: 35 + + Image { + source: item.modelData.icon + anchors.fill: parent + + MouseArea { + anchors.fill: parent + onClicked: function (mouse) { + if (mouse.button === Qt.LeftButton) { + item.modelData.activate(); + } + if (mouse.button === Qt.RightButton) { + if (item.modelData.hasMenu) {} + } + } + } + } + } + } + } +} diff --git a/modules/style/quickshell/shell/config/Colors.qml b/modules/style/quickshell/shell/config/Colors.qml new file mode 100644 index 0000000..8f77553 --- /dev/null +++ b/modules/style/quickshell/shell/config/Colors.qml @@ -0,0 +1,25 @@ +pragma Singleton + +import QtQuick +import Quickshell + +Singleton { + id: root + + readonly property color base: "#1e1e2e" + readonly property color mantle: "#181825" + readonly property color surface0: "#313244" + readonly property color surface1: "#45475a" + readonly property color surface2: "#585b70" + readonly property color text: "#cdd6f4" + readonly property color rosewater: "#f5e0dc" + readonly property color lavender: "#b4befe" + readonly property color red: "#f38ba8" + readonly property color peach: "#fab387" + readonly property color yellow: "#f9e2af" + readonly property color green: "#a6e3a1" + readonly property color teal: "#a6e3a1" + readonly property color blue: "#89b4fa" + readonly property color mauve: "#cba6f7" + readonly property color flamingo: "#f2cdcd" +} diff --git a/modules/style/quickshell/shell/config/Config.qml b/modules/style/quickshell/shell/config/Config.qml new file mode 100644 index 0000000..9e44e32 --- /dev/null +++ b/modules/style/quickshell/shell/config/Config.qml @@ -0,0 +1,32 @@ +pragma Singleton + +import Quickshell +import QtQuick + +Singleton { + id: root + + readonly property QtObject bar: QtObject { + readonly property int width: 50 + readonly property var colors: QtObject { + readonly property color bar: "#1e1e2e" + readonly property color barOutline: "#50ffffff" + readonly property color widget: "#25ceffff" + readonly property color widgetActive: "#80ceffff" + readonly property color widgetOutline: "#40ffffff" + readonly property color widgetOutlineSeparate: "#20ffffff" + readonly property color separator: "#60ffffff" + } + } + + readonly property QtObject border: QtObject { + readonly property int thickness: 0 + readonly property color color: "#1e1e2e" + readonly property int rounding: 0 + } + + readonly property QtObject volumeslider: QtObject { + readonly property int width: 50 + } + +} diff --git a/modules/style/quickshell/shell/modules/BackgroundImage.qml b/modules/style/quickshell/shell/modules/BackgroundImage.qml new file mode 100644 index 0000000..9cf0ded --- /dev/null +++ b/modules/style/quickshell/shell/modules/BackgroundImage.qml @@ -0,0 +1,55 @@ +import QtQuick +import Quickshell +import Quickshell.Wayland +import Qt.labs.folderlistmodel 2.9 + +PanelWindow { + id: root + + exclusionMode: ExclusionMode.Ignore + WlrLayershell.layer: WlrLayer.Background + WlrLayershell.namespace: "shell:background" + + property string basePath: "file:///home/cr/Documents/Backgrounds/" + property var absPath: folderModel.get(Math.floor(Math.random() * folderModel.count), "filePath") + property var finalPath: absPath + + // property bool _: log() + // function log() { + // console.log(absPath); + // console.log(folderModel.count); + // return true; + // } + FolderListModel { + id: folderModel + folder: root.basePath + nameFilters: ["*.png"] + showDirs: false + showFiles: true + } + + anchors { + top: true + bottom: true + left: true + right: true + } + + Item { + id: background + anchors.fill: parent + Image { + id: image + source: Qt.resolvedUrl(root.finalPath) + } + } + Timer { + id: timer + // 10 minutes + interval: 1000 * 60 * 10 + running: false + onTriggered: { + root.popupOpacity = 0; + } + } +} diff --git a/modules/style/quickshell/shell/modules/bar/Bar.qml b/modules/style/quickshell/shell/modules/bar/Bar.qml new file mode 100644 index 0000000..a7b28d0 --- /dev/null +++ b/modules/style/quickshell/shell/modules/bar/Bar.qml @@ -0,0 +1,50 @@ +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell + +import qs.config +import "components" + +Item { + id: root + + required property ShellScreen screen + + anchors { + top: parent.top + bottom: parent.bottom + left: parent.left + } + + implicitWidth: Config.bar.width + + Item { + id: child + + anchors { + top: parent.top + bottom: parent.bottom + horizontalCenter: parent.horizontalCenter + } + + implicitWidth: Math.max(clock.implicitWidth, workspaces.implicitWidth) + + ColumnLayout { + spacing: 2 + anchors { + top: parent.top + left: parent.left + right: parent.right + margins: 0 + } + Clock { + id: clock + } + Workspaces { + id: workspaces + screen: root.screen + } + } + } +} diff --git a/modules/style/quickshell/shell/modules/bar/components/Clock.qml b/modules/style/quickshell/shell/modules/bar/components/Clock.qml new file mode 100644 index 0000000..78d8c30 --- /dev/null +++ b/modules/style/quickshell/shell/modules/bar/components/Clock.qml @@ -0,0 +1,34 @@ +import QtQuick +import Quickshell + +import qs.config + +Rectangle { + id: root + + width: text.width + 5 + height: text.height + 5 + implicitWidth: width + border.color: Colors.rosewater + border.width: 0 + radius: 5 + color: "transparent" + + Text { + id: text + anchors.centerIn: parent + property var date: Date() + + text: Qt.formatDateTime(clock.date, "hh mm") + + font.family: "JetBrainsMono NF Mono" + font.pointSize: 15 + + color: Colors.text + } + + SystemClock { + id: clock + precision: SystemClock.Seconds + } +} diff --git a/modules/style/quickshell/shell/modules/bar/components/Workspaces.qml b/modules/style/quickshell/shell/modules/bar/components/Workspaces.qml new file mode 100644 index 0000000..404f13e --- /dev/null +++ b/modules/style/quickshell/shell/modules/bar/components/Workspaces.qml @@ -0,0 +1,108 @@ +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import QtQuick.Layouts + +import qs.services.niri +import qs.config + +Rectangle { + id: root + + required property ShellScreen screen + property var workspaces: Niri.workspaces + property var wsCount: Niri.workspaces.length + property var activeWorkspace: Niri.activeWorkspace + property var activeWorkspaceIndex: Niri.activeWorkspaceIndex + + property int wsItemHeight: 15 + + signal workspaceAdded(workspace: var) + function onWorkspaceAdded(workspace: var) { + root.workspaces.push(workspace); + } + + // property bool _: log() + // function log() { + // console.log(workspaces.values); + // return true; + // } + + // Works + height: 300 + + // Gives warning + // height: workspaces.length * root.wsItemHeight + implicitWidth: list.implicitWidth + color: "transparent" + border.color: Colors.rosewater + border.width: 0 + radius: 7 + + Layout.fillWidth: true + + ListView { + id: list + model: root.workspaces + implicitHeight: contentHeight + implicitWidth: contentItem.childrenRect.width + anchors.horizontalCenter: parent.horizontalCenter + + // anchors.fill: parent + + delegate: Item { + id: wsItem + // Name of the workspace + property string name: "VOID" + // ID of the workspace + required property string id + + required property string output + + property bool isActive: (id - 1 == root.activeWorkspaceIndex) + + property real animActive: isActive ? 1 : 0.65 + Behavior on animActive { + NumberAnimation { + duration: 150 + } + } + + // property bool isCorrectScreen: log() + // function log() { + // console.log("Screen name: " + root.screen.name); + // console.log(wsItem.output); + // console.log(wsItem.id); + + // let isCorrect = root.screen.name == wsItem.output; + // console.log("isCorrect: ", isCorrect); + // return root.screen.name == wsItem.output; + // } + + implicitHeight: root.wsItemHeight + implicitWidth: 50 + + anchors { + right: parent.right + left: parent.left + } + + Rectangle { + anchors.centerIn: parent + height: wsItem.height - 5 + width: parent.width * wsItem.animActive + radius: height / 2 + border.color: Colors.mantle + border.width: 0 + color: Colors.blue + } + } + } + + Component.onCompleted: { + Niri.workspaces.forEach(workspace => { + root.workspaceAdded(workspace); + }); + } +} diff --git a/modules/style/quickshell/shell/modules/drawers/Backgrounds.qml b/modules/style/quickshell/shell/modules/drawers/Backgrounds.qml new file mode 100644 index 0000000..7e50ae9 --- /dev/null +++ b/modules/style/quickshell/shell/modules/drawers/Backgrounds.qml @@ -0,0 +1,6 @@ +import QtQuick + + +Rectangle { + required property Item bar +} diff --git a/modules/style/quickshell/shell/modules/drawers/Border.qml b/modules/style/quickshell/shell/modules/drawers/Border.qml new file mode 100644 index 0000000..6fd6538 --- /dev/null +++ b/modules/style/quickshell/shell/modules/drawers/Border.qml @@ -0,0 +1,54 @@ +import QtQuick +import QtQuick.Effects + +import qs.config + +Item { + id: root + + required property Item bar + + anchors.fill: parent + + Rectangle { + id: rect + + // Parent has a mask applied that cuts out all except the border and the bar. + anchors.fill: parent + color: Config.border.color + visible: false + + + Behavior on color { + ColorAnimation { + duration: 150 + easing.type: Easing.BezierSpline + } + } + } + + Item { + id: mask + + anchors.fill: parent + layer.enabled: true + visible: false + + Rectangle { + anchors.fill: parent + anchors.margins: Config.border.thickness + anchors.leftMargin: root.bar.implicitWidth + radius: Config.border.rounding + } + } + + MultiEffect { + anchors.fill: parent + maskEnabled: true + maskInverted: true + maskSource: mask + source: rect + maskThresholdMin: 0.5 + maskSpreadAtMin: 1 + } +} diff --git a/modules/style/quickshell/shell/modules/drawers/Drawers.qml b/modules/style/quickshell/shell/modules/drawers/Drawers.qml new file mode 100644 index 0000000..466182c --- /dev/null +++ b/modules/style/quickshell/shell/modules/drawers/Drawers.qml @@ -0,0 +1,100 @@ +pragma ComponentBehavior: Bound + +import Quickshell +import Quickshell.Wayland +import QtQuick +import QtQuick.Effects + +import qs.modules.bar + +import qs.config +import qs.modules + +Variants { + model: Quickshell.screens + + Scope { + id: scope + required property ShellScreen modelData + + Exclusions { + screen: scope.modelData + bar: bar + } + + PanelWindow { + id: win + + screen: scope.modelData + color: "transparent" + + WlrLayershell.exclusionMode: ExclusionMode.Ignore + WlrLayershell.keyboardFocus: WlrKeyboardFocus.None + + // Clickthrough mask. + // Clickable areas of the window are determined by the provided region. + mask: Region { + // Start at the bottom left; right of the bar and on top of the border + x: bar.implicitWidth + y: Config.border.thickness + + // Width is the window width - the bar's width - the border thickness + width: win.width - bar.implicitWidth - Config.border.thickness + + // Height is window width - the border thickness x2 —top border and bottom border. + height: win.height - Config.border.thickness * 2 + + // Setting the intersection mode to Xor will invert the mask and make everything in the mask region not clickable and pass through clicks inside it through the window. + intersection: Intersection.Xor + // Region { + // item: volume + // intersection: Intersection.Subtract + // } + } + + anchors { + top: true + bottom: true + left: true + right: true + } + + Item { + id: background + + anchors.fill: parent + visible: false + + Border { + bar: bar + } + + Backgrounds { + bar: bar + } + } + + MultiEffect { + anchors.fill: source + source: background + shadowEnabled: true + blurMax: 15 + } + + Bar { + id: bar + screen: scope.modelData + } + } + BackgroundImage { + id: backgroundimage + screen: scope.modelData + } + BackgroundImage { + id: background_overview + screen: scope.modelData + + WlrLayershell.namespace: "shell:background-overview" + } + } +} diff --git a/modules/style/quickshell/shell/modules/drawers/Exclusions.qml b/modules/style/quickshell/shell/modules/drawers/Exclusions.qml new file mode 100644 index 0000000..d99092d --- /dev/null +++ b/modules/style/quickshell/shell/modules/drawers/Exclusions.qml @@ -0,0 +1,38 @@ + +pragma ComponentBehavior: Bound +import Quickshell +import QtQuick + +import "../../config" + +Scope { + id: root + required property ShellScreen screen + required property Item bar + + ExclusionZone { + anchors.left: true + exclusiveZone: root.bar.implicitWidth + } + + ExclusionZone { + anchors.top: true + } + + ExclusionZone { + anchors.right: true + } + + ExclusionZone { + anchors.bottom: true + } + + component ExclusionZone: PanelWindow { + screen: root.screen + color: "transparent" + exclusiveZone: Config.border.thickness + implicitHeight: Config.border.thickness + implicitWidth: Config.border.thickness + mask: Region {} + } +} diff --git a/modules/style/quickshell/shell/modules/launcher/Launcher.qml b/modules/style/quickshell/shell/modules/launcher/Launcher.qml new file mode 100644 index 0000000..8cf4f37 --- /dev/null +++ b/modules/style/quickshell/shell/modules/launcher/Launcher.qml @@ -0,0 +1,319 @@ +pragma Singleton +pragma ComponentBehavior: Bound +import QtQuick +import QtQuick.Layouts +import Quickshell +import Quickshell.Io +import Quickshell.Wayland +import Quickshell.Widgets + +Singleton { + id: launcher + property bool launcherOpen: false + + IpcHandler { + target: "launcher" + + function open(): void { + launcher.launcherOpen = true; + } + + function close(): void { + launcher.launcherOpen = false; + } + + function toggle(): void { + launcher.launcherOpen = !launcher.launcherOpen; + } + } + + LazyLoader { + id: loader + activeAsync: launcher.launcherOpen + + PanelWindow { + width: 450 + height: 7 + searchContainer.implicitHeight + list.topMargin * 2 + list.delegateHeight * 10 + color: "transparent" + + + anchors { + bottom: parent.bottom + } + + + WlrLayershell.keyboardFocus: WlrKeyboardFocus.Exclusive + WlrLayershell.namespace: "shell:launcher" + + Rectangle { + + height: 7 + searchContainer.implicitHeight + list.topMargin + list.bottomMargin + Math.min(list.contentHeight, list.delegateHeight * 10) + Behavior on height { + NumberAnimation { + duration: 200 + easing.type: Easing.OutCubic + } + } + width: 450 + color: "#30c0afaf" + radius: 5 + border.color: "black" + border.width: 2 + + ColumnLayout { + anchors.fill: parent + anchors.margins: 7 + anchors.bottomMargin: 0 + spacing: 0 + + Rectangle { + id: searchContainer + Layout.fillWidth: true + implicitHeight: searchbox.implicitHeight + 10 + color: "#30c0ffff" + radius: 3 + border.color: "#50ffffff" + + RowLayout { + id: searchbox + anchors.fill: parent + anchors.margins: 5 + + IconImage { + implicitSize: parent.height + source: "root:icons/magnifying-glass.svg" + } + + TextInput { + id: search + Layout.fillWidth: true + color: "black" + + focus: true + Keys.forwardTo: [list] + Keys.onEscapePressed: launcher.launcherOpen = false + + Keys.onPressed: event => { + if (event.modifiers & Qt.ControlModifier) { + if (event.key == Qt.Key_J) { + list.currentIndex = list.currentIndex == list.count - 1 ? 0 : list.currentIndex + 1; + event.accepted = true; + } else if (event.key == Qt.Key_K) { + list.currentIndex = list.currentIndex == 0 ? list.count - 1 : list.currentIndex - 1; + event.accepted = true; + } + } + } + + onAccepted: { + if (list.currentItem) { + list.currentItem.clicked(null); + } + } + + onTextChanged: { + list.currentIndex = 0; + } + } + } + } + + ListView { + id: list + Layout.fillWidth: true + Layout.fillHeight: true + clip: true + cacheBuffer: 0 // works around QTBUG-131106 + //reuseItems: true + model: ScriptModel { + values: DesktopEntries.applications.values.map(object => { + const stxt = search.text.toLowerCase(); + const ntxt = object.name.toLowerCase(); + let si = 0; + let ni = 0; + + let matches = []; + let startMatch = -1; + + for (let si = 0; si != stxt.length; ++si) { + const sc = stxt[si]; + + while (true) { + // Drop any entries with letters that don't exist in order + if (ni == ntxt.length) + return null; + + const nc = ntxt[ni++]; + + if (nc == sc) { + if (startMatch == -1) + startMatch = ni; + break; + } else { + if (startMatch != -1) { + matches.push({ + index: startMatch, + length: ni - startMatch + }); + + startMatch = -1; + } + } + } + } + + if (startMatch != -1) { + matches.push({ + index: startMatch, + length: ni - startMatch + 1 + }); + } + + return { + object: object, + matches: matches + }; + }).filter(entry => entry !== null).sort((a, b) => { + let ai = 0; + let bi = 0; + let s = 0; + + while (ai != a.matches.length && bi != b.matches.length) { + const am = a.matches[ai]; + const bm = b.matches[bi]; + + s = bm.length - am.length; + if (s != 0) + return s; + + s = am.index - bm.index; + if (s != 0) + return s; + + ++ai; + ++bi; + } + + s = a.matches.length - b.matches.length; + if (s != 0) + return s; + + s = a.object.name.length - b.object.name.length; + if (s != 0) + return s; + + return a.object.name.localeCompare(b.object.name); + }).map(entry => entry.object) + + onValuesChanged: list.currentIndex = 0 + } + + topMargin: 7 + bottomMargin: list.count == 0 ? 0 : 7 + + add: Transition { + NumberAnimation { + property: "opacity" + from: 0 + to: 1 + duration: 100 + } + } + + displaced: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 1 + duration: 100 + } + } + + move: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 1 + duration: 100 + } + } + + remove: Transition { + NumberAnimation { + property: "y" + duration: 200 + easing.type: Easing.OutCubic + } + NumberAnimation { + property: "opacity" + to: 0 + duration: 100 + } + } + + highlight: Rectangle { + radius: 5 + color: "#20e0ffff" + border.color: "#30ffffff" + border.width: 1 + } + keyNavigationEnabled: true + keyNavigationWraps: true + highlightMoveVelocity: -1 + highlightMoveDuration: 50 + preferredHighlightBegin: list.topMargin + preferredHighlightEnd: list.height - list.bottomMargin + highlightRangeMode: ListView.ApplyRange + snapMode: ListView.SnapToItem + + readonly property real delegateHeight: 44 + + delegate: MouseArea { + required property DesktopEntry modelData + + implicitHeight: list.delegateHeight + implicitWidth: ListView.view.width + + onClicked: { + modelData.execute(); + launcher.launcherOpen = false; + } + + RowLayout { + id: delegateLayout + anchors { + verticalCenter: parent.verticalCenter + left: parent.left + leftMargin: 5 + } + + IconImage { + Layout.alignment: Qt.AlignVCenter + asynchronous: true + implicitSize: 30 + source: Quickshell.iconPath(modelData.icon) + } + Text { + text: modelData.name + color: "black" + font.family: "ComicShannsMono Nerd Font Mono" + Layout.alignment: Qt.AlignVCenter + } + } + } + } + } + } + } + } + function init() { + } +} diff --git a/modules/style/quickshell/shell/modules/notifications/Notification.qml b/modules/style/quickshell/shell/modules/notifications/Notification.qml new file mode 100644 index 0000000..7c147e6 --- /dev/null +++ b/modules/style/quickshell/shell/modules/notifications/Notification.qml @@ -0,0 +1,60 @@ +import QtQuick +import QtQuick.Shapes + +import qs.config + +Shape { + id: root + anchors.top: parent.top + // anchors.right: parent.right + anchors.horizontalCenter: parent.horizontalCenter + + readonly property real rounding: Config.border.rounding + + implicitWidth: 1000 + implicitHeight: 300 + ShapePath { + fillColor: Config.catppuccin.base + strokeWidth: -1 + + PathArc { + relativeX: root.rounding + relativeY: root.rounding + radiusX: root.rounding + radiusY: root.rounding + } + PathLine { + relativeX: 0 + relativeY: 100 + } + PathLine { + relativeX: 300 + relativeY: 0 + } + PathLine { + relativeX: 0 + relativeY: -100 + } + PathArc { + relativeX: root.rounding + relativeY: -root.rounding + radiusX: root.rounding + radiusY: root.rounding + } + + Behavior on fillColor { + ColorAnimation { + duration: 500 + easing.type: Easing.BezierSpline + } + } + } + + Text { + anchors.centerIn: parent + text: "This is a test" + color: "white" + font.pointSize: 15 + font.bold: true + } +} diff --git a/modules/style/quickshell/shell/modules/volume/VolumeSlider.qml b/modules/style/quickshell/shell/modules/volume/VolumeSlider.qml new file mode 100644 index 0000000..e6004b4 --- /dev/null +++ b/modules/style/quickshell/shell/modules/volume/VolumeSlider.qml @@ -0,0 +1,82 @@ +pragma ComponentBehavior: Bound + +import Quickshell +import QtQuick +import QtQuick.Shapes +import qs.config + +Rectangle { + id: root + required property ShellScreen screen + readonly property real rounding: Config.border.rounding + color: "transparent" + + anchors { + right: parent.right + verticalCenter: parent.verticalCenter + } + + implicitWidth: Config.volumeslider.width + implicitHeight: screen.height / 3 + + Rectangle { + anchors.right: parent.right + color: "green" + implicitWidth: hover.hovered ? Config.volumeslider.width : Config.border.thickness + + implicitHeight: root.screen.height / 3 + + HoverHandler { + id: hover + acceptedDevices: PointerDevice.Mouse | PointerDevice.TouchPad + } + + Behavior on implicitWidth { + NumberAnimation { + duration: 400 + easing.type: Easing.OutCubic + } + } + } + + Shape { + implicitWidth: hover.hovered ? Config.volumeslider.width : Config.border.thickness + implicitHeight: root.screen.height / 3 + ShapePath { + fillColor: Config.catppuccin.base + strokeWidth: -1 + PathArc { + relativeX: -root.rounding + relativeY: root.rounding + radiusX: root.rounding + radiusY: root.rounding + direction: PathArc.Counterclockwise + } + PathLine { + relativeY: root.screen.height / 3 + relativeX: 0 + } + PathArc { + relativeX: root.rounding + // relativeX: 50 + relativeY: -root.rounding + radiusX: root.rounding + radiusY: root.rounding + // direction: PathArc.Counterclockwise + // useLargeArc: true + } + PathLine { + relativeX: 50 + relativeY: 0 + } + PathLine { + relativeY: -root.screen.height / 3 + relativeX: 0 + } + PathLine { + relativeX: -50 + relativeY: 0 + } + } + } +} diff --git a/modules/style/quickshell/shell/services/Hover.qml b/modules/style/quickshell/shell/services/Hover.qml new file mode 100644 index 0000000..9e76fd3 --- /dev/null +++ b/modules/style/quickshell/shell/services/Hover.qml @@ -0,0 +1,49 @@ +import Quickshell +import QtQuick +import qs.config + +MouseArea { + id: root + + anchors.fill: parent + hoverEnabled: true + + required property ShellScreen screen + // required property Panels panels + required property Item bar + + property bool showVolumeMenu: false + property bool isInRightPanel: false + + // function withinPanelHeight(panel: Item, x: real, y: real): bool { + // const panelY = Config.border.thickness + panel.y; + // return y >= panelY - Config.border.rounding && y <= panelY + panel.height + Config.border.rounding; + // } + + // function inLeftBorder(x: real, y: real): bool { + // return x <= Config.border.thickness; + // } + + function inRightPanel(x: real, y: real): bool { + // Cursor is in middle veritcal third of screen + // Cursor is in the right border + return y >= root.screen.height / 3 && y <= (root.screen.height / 3) * 2 && x >= root.screen.width - Config.border.thickness; + } + + // Update on mouse cursor movement + onPositionChanged: event => { + const x = event.x; + const y = event.y; + + root.isInRightPanel = inRightPanel(x, y); + + console.log("In right panel: " + root.isInRightPanel); + + console.log("x:" + x + " y: " + y); + } + onContainsMouseChanged: { + if (!containsMouse) { + root.isInRightPanel = false; + } + } +} diff --git a/modules/style/quickshell/shell/services/Notification.qml b/modules/style/quickshell/shell/services/Notification.qml new file mode 100644 index 0000000..bdf52de --- /dev/null +++ b/modules/style/quickshell/shell/services/Notification.qml @@ -0,0 +1,20 @@ +pragma Singleton +pragma ComponentBehavior: Bound + +import QtQuick +import Quickshell +import Quickshell.Io +import Quickshell.Services.Notifications + +/** + * Provides extra features not in Quickshell.Services.Notifications: + * - Persistent storage + * - Popup notifications, with timeout + * - Notification groups by app + */ +Singleton { + id: root + NotificationServer { + + } +} diff --git a/modules/style/quickshell/shell/services/niri/Niri.qml b/modules/style/quickshell/shell/services/niri/Niri.qml new file mode 100644 index 0000000..de16157 --- /dev/null +++ b/modules/style/quickshell/shell/services/niri/Niri.qml @@ -0,0 +1,94 @@ +// Kind thanks to https://github.com/MapoMagpie/nixos-flakes/blob/main/home/ui/quickshell/config/Data/Niri.qml +// This file was taken from there and further modified. + +pragma Singleton + +import QtQuick +import Quickshell +import Quickshell.Io + +Singleton { + id: root + // property var data + property var workspaces: [] + property var activeWorkspace: "VOID" + property var activeWorkspaceIndex: 0 + property var windows: [] + // property var activedWindowId: 0 + + Process { + id: proc + command: ["niri", "msg", "-j", "event-stream"] + + running: true + stdout: SplitParser { + onRead: data => { + var event = JSON.parse(data); + let workspaces = []; + if (event.WorkspacesChanged) { + root.workspaces = event.WorkspacesChanged.workspaces; + root.workspaces = root.workspaces.sort((a, b) => a.id - b.id); + root.activeWorkspaceIndex = root.workspaces.findIndex(w => w.is_focused); + if (root.activeWorkspaceIndex < 0) { + root.activeWorkspaceIndex = 0; + } + root.activeWorkspace = root.workspaces[root.activeWorkspaceIndex].name; + } + if (event.WindowsChanged) { + root.windows = [...event.WindowsChanged.windows].sort((a, b) => a.id - b.id); + } + if (event.WindowOpenedOrChanged) { + const window = event.WindowOpenedOrChanged.window; + const index = root.windows.findIndex(w => w.id === window.id); + // console.log("window opened or changed: ", index, ", win id: ", window.id); + if (index >= 0) { + // console.log("replace window, old: ", root.windows[index].id, ", new: ", window.id); + root.windows[index] = window; + } else { + // console.log("push window, new: ", window.id); + root.windows.push(window); + } + root.windows = [...root.windows.sort((a, b) => a.id - b.id)]; + } + if (event.WindowClosed) { + const index = root.windows.findIndex(w => w.id === event.WindowClosed.id); + // console.log("window closed: ", index, ", win id: ", event.WindowClosed.id); + if (index >= 0) { + root.windows.splice(index, 1); + } + root.windows = [...root.windows.sort((a, b) => a.id - b.id)]; + } + if (event.WorkspaceActivated) { + root.activeWorkspaceIndex = root.workspaces.findIndex(w => w.id === event.WorkspaceActivated.id); + if (root.activeWorkspaceIndex < 0) { + root.activeWorkspaceIndex = 0; + } + root.activeWorkspace = root.workspaces[root.activeWorkspaceIndex].name; + } + } + } + } + // component Workspace: QtObject { + // required property int id + // property int idx + // property string name: "VOID" + // required property string output + // property bool is_active + // property bool is_focused + // property int active_window_id + // } +} + +// { +// "workspaces": [ +// { +// "id": 5, +// "idx": 4, +// "name": "GAME", +// "output": "DP-3", +// "is_active": false, +// "is_focused": false, +// "active_window_id": null +// }, +// ] +// } diff --git a/modules/style/quickshell/shell/shell.qml b/modules/style/quickshell/shell/shell.qml index e69de29..0ff4469 100644 --- a/modules/style/quickshell/shell/shell.qml +++ b/modules/style/quickshell/shell/shell.qml @@ -0,0 +1,15 @@ +//@ pragma Env QS_NO_RELOAD_POPUP=1 + +import Quickshell +import QtQuick + +import qs.modules.drawers +import qs + +ShellRoot { + id: shellroot + + Component.onCompleted: [Launcher.init(), AudioPopup.init()] + + Drawers {} +} diff --git a/modules/style/theming.nix b/modules/style/theming.nix deleted file mode 100644 index d276442..0000000 --- a/modules/style/theming.nix +++ /dev/null @@ -1,70 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (builtins) toString isBool; - inherit (lib.generators) toINI; - inherit (lib.modules) mkMerge mkIf; - inherit (lib.options) mkEnableOption; - inherit (lib.strings) escape; - inherit (lib.trivial) boolToString; - - cfg = config.modules.theming; - - toGtk3Ini = toINI { - mkKeyValue = key: value: let - value' = - if isBool value - then boolToString value - else toString value; - in "${escape ["="] key}=${value'}"; - }; - - gtkIni = { - gtk-application-prefer-dark-theme = 1; - gtk-font-name = "Lexend 11"; - gtk-icon-theme-name = "Papirus-Dark"; - gtk-xft-antialias = 1; - gtk-xft-hinting = 1; - gtk-xft-hintstyle = "hintslight"; - gtk-xft-rgba = "rgb"; - gtk-cursor-theme-name = "BreezeX-RosePine-Linux"; - gtk-theme-name = "Gruvbox-Dark"; - }; -in { - options.modules.theming = { - qt.enable = mkEnableOption "qt theming"; - }; - config = mkMerge [ - (mkIf cfg.gtk.enable { - environment = { - systemPackages = builtins.attrValues { - inherit (pkgs) rose-pine-cursor; - }; - etc = { - "xdg/gtk-4.0/settings.ini".text = toGtk3Ini { - Settings = gtkIni; - }; - "xdg/gtk-3.0/settings.ini".text = toGtk3Ini { - Settings = gtkIni; - }; - - "xdg/gtk-2.0/gtkrc".text = '' - gtk-cursor-theme-name = BreezeX-RosePine-Linux - gtk-cursor-theme-size = 32 - gtk-theme-name = Gruvbox-Dark - gtk-icon-theme-name = Papirus-Dark - gtk-font-name = Lexend 11 - ''; - - "xdg/Xresources".text = '' - Xcursor.size: 32 - Xcursor.theme: BreezeX-RosePine-Linux - ''; - }; - }; - }) - ]; -} diff --git a/modules/style/wholefoods.jpg b/modules/style/wholefoods.jpg deleted file mode 100644 index 3d9c47f..0000000 Binary files a/modules/style/wholefoods.jpg and /dev/null differ diff --git a/modules/style/wholefoods.png b/modules/style/wholefoods.png new file mode 100644 index 0000000..865da3d Binary files /dev/null and b/modules/style/wholefoods.png differ diff --git a/modules/system/boot/boot.mod.nix b/modules/system/boot/boot.mod.nix new file mode 100644 index 0000000..5c05cb8 --- /dev/null +++ b/modules/system/boot/boot.mod.nix @@ -0,0 +1,97 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkForce mkDefault; + inherit (lib.options) mkOption mkEnableOption; + inherit (lib.types) int; + + cfg = config.modules.system.boot; +in +{ + options.modules.system.boot = { + grub.enable = mkEnableOption "Grub, a bloated boot loader"; + systemd-boot.enable = mkEnableOption "Poetteringboot"; + timeout = mkOption { + description = '' + Set the boot loader's timeout. This is 0 by default, but preferably longer on remote servers to make switching to previous generations easier. + ''; + type = int; + # I love spamming space + default = 0; + }; + }; + config = { + assertions = [ + { + assertion = cfg.systemd-boot.enable || cfg.grub.enable; + message = "No bootloader is enabled."; + } + { + assertion = + cfg.systemd-boot.enable -> !cfg.grub.enable && cfg.grub.enable -> !cfg.systemd-boot.enable; + message = "Please enable only ONE of systemd-boot or grub."; + } + ]; + boot = { + tmp.useTmpfs = true; + consoleLogLevel = 0; + + kernelParams = [ + "quiet" + "splash" + "rd.systemd.show_status=false" + "rd.udev.log_level=3" + "udev.log_priority=3" + "boot.shell_on_fail" + ]; + + initrd = { + verbose = false; + systemd.enable = true; + }; + loader = { + efi.canTouchEfiVariables = true; + timeout = mkDefault cfg.timeout; + systemd-boot = { + inherit (cfg.systemd-boot) enable; + # INFO: Leaving this enabled is a security vulneratibility, + # since we can just start /bin/sh from there and get root access. + # Since I have FDE, this isn't _as_ critical, but it would still be + # a bad idea to leave it enabled + editor = mkForce false; + consoleMode = "auto"; + configurationLimit = 5; + }; + grub = { + inherit (cfg.grub) enable; + efiSupport = true; + device = "nodev"; + configurationLimit = 5; + }; + }; + plymouth = { + enable = true; + themePackages = [ + (pkgs.adi1090x-plymouth-themes.override { + selected_themes = [ + "hud_3" + ]; + }) + ]; + theme = "hud_3"; + }; + }; + powerManagement = { + powerDownCommands = '' + ${pkgs.plymouth} --show-splash + ''; + resumeCommands = '' + ${pkgs.plymouth} --quit + ''; + }; + }; +} diff --git a/modules/system/boot/lanzaboote/module.nix b/modules/system/boot/lanzaboote.mod.nix similarity index 57% rename from modules/system/boot/lanzaboote/module.nix rename to modules/system/boot/lanzaboote.mod.nix index e7fd7a5..77fbf5f 100644 --- a/modules/system/boot/lanzaboote/module.nix +++ b/modules/system/boot/lanzaboote.mod.nix @@ -1,17 +1,25 @@ { config, - inputs, lib, pkgs, + sources, ... }: let inherit (lib.modules) mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.system.boot.lanzaboote; in { + options.modules.system.boot.lanzaboote.enable = mkEnableOption "Lanzaboote"; imports = [ - inputs.lanzaboote.nixosModules.lanzaboote + (import sources.flake-compat { + src = sources.lanzaboote; + copySourceTreeToStore = false; + useBuiltinsFetchTree = true; + }).outputs.nixosModules.lanzaboote ]; - config = mkIf false { + config = mkIf cfg.enable { boot = { lanzaboote = { enable = true; diff --git a/modules/system/boot/module.nix b/modules/system/boot/module.nix deleted file mode 100644 index 275fa5d..0000000 --- a/modules/system/boot/module.nix +++ /dev/null @@ -1,57 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let - inherit (lib.modules) mkForce; - inherit (lib.options) mkEnableOption; - - cfg = config.modules.system.boot; -in { - options.modules.system.boot = { - grub.enable = mkEnableOption "Grub, a bloated boot loader"; - systemd-boot.enable = mkEnableOption "Poetteringboot"; - }; - config = { - assertions = [ - { - assertion = cfg.systemd-boot.enable || cfg.grub.enable; - message = "No bootloader is enabled."; - } - { - assertion = cfg.systemd-boot.enable -> !cfg.grub.enable && cfg.grub.enable -> !cfg.systemd-boot.enable; - message = "Please enable only ONE of systemd-boot or grub."; - } - ]; - boot = { - tmp.useTmpfs = true; - initrd = { - verbose = true; - systemd.enable = true; - }; - loader = { - efi.canTouchEfiVariables = true; - # I love spamming space - timeout = 0; - systemd-boot = { - enable = cfg.systemd-boot.enable; - editor = mkForce false; - configurationLimit = 5; - }; - grub = { - enable = cfg.grub.enable; - efiSupport = true; - device = "nodev"; - configurationLimit = 5; - }; - }; - plymouth = { - enable = false; - # font = "${pkgs.jetbrains-mono}/share/fonts/truetype/JetBrainsMono-Regular.ttf"; - themePackages = [pkgs.plymouth-matrix-theme]; - theme = "matrix"; - }; - }; - }; -} diff --git a/modules/system/hardware/bluetooth.nix b/modules/system/hardware/bluetooth.mod.nix similarity index 78% rename from modules/system/hardware/bluetooth.nix rename to modules/system/hardware/bluetooth.mod.nix index b882011..ff68b93 100644 --- a/modules/system/hardware/bluetooth.nix +++ b/modules/system/hardware/bluetooth.mod.nix @@ -3,19 +3,20 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkIf; cfg = config.modules.system.hardware.bluetooth; -in { +in +{ config = mkIf cfg.enable { hardware.bluetooth = { enable = true; - powerOnBoot = mkIf cfg.powerOnBoot true; + inherit (cfg) powerOnBoot; }; environment.systemPackages = builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) bluetuith bluez blueman diff --git a/modules/system/hardware/cpu/amd.nix b/modules/system/hardware/cpu/amd.nix deleted file mode 100644 index e69de29..0000000 diff --git a/modules/system/hardware/cpu/module.nix b/modules/system/hardware/cpu/module.nix deleted file mode 100644 index 9b5284e..0000000 --- a/modules/system/hardware/cpu/module.nix +++ /dev/null @@ -1,3 +0,0 @@ -_: { - imports = [./intel.nix]; -} diff --git a/modules/system/hardware/graphics.mod.nix b/modules/system/hardware/graphics.mod.nix new file mode 100644 index 0000000..063e26e --- /dev/null +++ b/modules/system/hardware/graphics.mod.nix @@ -0,0 +1,70 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkDefault mkIf; + inherit (lib.options) mkEnableOption; + + cfg = config.modules.system.hardware; +in +{ + options.modules.system.hardware = { + nvidia = { + enable = mkEnableOption "Nvidia graphics drivers"; + }; + amd.enable = mkEnableOption "AMD graphics drivers"; + }; + config = { + hardware = { + graphics = { + enable = true; + extraPackages = [ pkgs.nvidia-vaapi-driver ]; + }; + + nvidia = mkIf cfg.nvidia.enable { + open = mkDefault true; + + # Whether to enable kernel modesetting when using the NVIDIA proprietary driver. + # Enabling this causes the proprietary NVIDIA driver to provide its own + # framebuffer device, which can cause Wayland compositors to work when + # they otherwise wouldn’t. . + modesetting.enable = true; + + # nvidia-settings is useless on NixOS. + nvidiaSettings = false; + + # fixes sleep on nvidia devices + powerManagement = { + enable = true; + finegrained = false; + }; + package = config.boot.kernelPackages.nvidiaPackages.beta; + }; + }; + services.xserver.videoDrivers = [ + "nvidia" + ]; + + environment.systemPackages = builtins.attrValues { + inherit (pkgs) + mesa + vulkan-tools + vulkan-loader + libva + libva-utils + ; + inherit (pkgs.nvtopPackages) nvidia; + }; + # Nouveau is a set of free and open-source drivers for NVIDIA GPUs + # that provide 2D/3D acceleration for all NVIDIA GPUs. + # Its use is in general not recommended due to its considerably worse + # performance compared to NVIDIA's kernel modules, as it does not + # support reclocking (changing the GPU clock frequency on-demand) + # for many NVIDIA GPUs. + # I therefore disable it to save myself from headaches. + boot.blacklistedKernelModules = mkIf cfg.nvidia.enable [ "nouveau" ]; + }; +} diff --git a/modules/system/hardware/graphics.nix b/modules/system/hardware/graphics.nix deleted file mode 100644 index 25e255e..0000000 --- a/modules/system/hardware/graphics.nix +++ /dev/null @@ -1,37 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (lib.modules) mkIf; - inherit (lib.options) mkEnableOption; - - cfg = config.modules.system.hardware; -in { - options.modules.system.hardware = { - nvidia = { - enable = mkEnableOption "Nvidia graphics drivers"; - }; - amd.enable = mkEnableOption "AMD graphics drivers"; - }; - config = { - hardware = { - graphics.enable = true; - nvidia = mkIf cfg.nvidia.enable { - # we want the open-source drivers - open = true; - - modesetting.enable = true; - nvidiaSettings = false; - - # fixes sleep on nvidia devices - powerManagement = { - enable = true; - finegrained = false; - }; - package = config.boot.kernelPackages.nvidiaPackages.beta; - }; - }; - services.xserver.videoDrivers = mkIf cfg.nvidia.enable ["nvidia"]; - }; -} diff --git a/modules/system/hardware/cpu/intel.nix b/modules/system/hardware/intel.mod.nix similarity index 92% rename from modules/system/hardware/cpu/intel.nix rename to modules/system/hardware/intel.mod.nix index ba82da7..863d9a3 100644 --- a/modules/system/hardware/cpu/intel.nix +++ b/modules/system/hardware/intel.mod.nix @@ -3,19 +3,20 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkDefault mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.system.hardware.intel; -in { +in +{ options.modules.system.hardware.intel.enable = mkEnableOption "Intel Hardware"; config = mkIf cfg.enable { hardware = { cpu.intel.updateMicrocode = mkDefault config.hardware.enableRedistributableFirmware; graphics.extraPackages = builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) intel-vaapi-driver intel-media-driver ; diff --git a/modules/system/hardware/irqbalance.mod.nix b/modules/system/hardware/irqbalance.mod.nix new file mode 100644 index 0000000..56f3198 --- /dev/null +++ b/modules/system/hardware/irqbalance.mod.nix @@ -0,0 +1,3 @@ +_: { + services.irqbalance.enable = true; +} diff --git a/modules/system/hardware/keyboard/default.nix b/modules/system/hardware/keyboard.mod.nix similarity index 100% rename from modules/system/hardware/keyboard/default.nix rename to modules/system/hardware/keyboard.mod.nix diff --git a/modules/system/hardware/module.nix b/modules/system/hardware/module.nix deleted file mode 100644 index 6efca34..0000000 --- a/modules/system/hardware/module.nix +++ /dev/null @@ -1,5 +0,0 @@ -_: { - imports = [./bluetooth.nix ./keyboard ./graphics.nix]; - - services.irqbalance.enable = true; -} diff --git a/modules/system/hardware/sound/pipewire/module.nix b/modules/system/hardware/pipewire.mod.nix similarity index 96% rename from modules/system/hardware/sound/pipewire/module.nix rename to modules/system/hardware/pipewire.mod.nix index a18d3de..9a61f76 100644 --- a/modules/system/hardware/sound/pipewire/module.nix +++ b/modules/system/hardware/pipewire.mod.nix @@ -2,11 +2,13 @@ config, lib, ... -}: let +}: +let inherit (lib.modules) mkIf; cfg = config.modules.system.sound; -in { +in +{ config = mkIf cfg.enable { services.pipewire = { enable = true; diff --git a/modules/system/hardware/power.mod.nix b/modules/system/hardware/power.mod.nix new file mode 100644 index 0000000..9d9c53d --- /dev/null +++ b/modules/system/hardware/power.mod.nix @@ -0,0 +1,243 @@ +{ + config, + sources, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkDefault; +in +{ + imports = [ + # (sources.watt + "/nix/module.nix") + ]; + config = { + environment.systemPackages = builtins.attrValues { + inherit (pkgs) + acpi + powertop + ; + }; + + boot = { + kernelModules = [ "acpi_call" ]; + extraModulePackages = with config.boot.kernelPackages; [ + acpi_call + cpupower + ]; + }; + + hardware.acpilight.enable = false; + + # services.watt = { + # enable = true; + # # sample config from https://github.com/NotAShelf/watt#sample-configuration + # settings = { + # rule = [ + # { + # cpu = { + # energy-performance-preference = "power"; + # frequency-mhz-maximum = 2000; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = { + # is-more-than = 85; + # value = "$cpu-temperature"; + # }; + # priority = 100; + # } + # { + # cpu = { + # energy-performance-preference = "power"; + # frequency-mhz-maximum = 800; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = { + # all = [ + # "?discharging" + # { + # is-less-than = 0.3; + # value = "%power-supply-charge"; + # } + # ]; + # }; + # power = {platform-profile = "low-power";}; + # priority = 90; + # } + # { + # cpu = { + # energy-performance-preference = "performance"; + # governor = "performance"; + # turbo = true; + # }; + # "if" = { + # all = [ + # { + # is-more-than = 0.8; + # value = "%cpu-usage"; + # } + # { + # is-less-than = 30; + # value = "$cpu-idle-seconds"; + # } + # { + # is-less-than = 75; + # value = "$cpu-temperature"; + # } + # ]; + # }; + # priority = 80; + # } + # { + # cpu = { + # energy-performance-bias = "balance_performance"; + # energy-performance-preference = "performance"; + # governor = "performance"; + # turbo = true; + # }; + # "if" = { + # all = [ + # {not = "?discharging";} + # { + # is-more-than = 0.1; + # value = "%cpu-usage"; + # } + # { + # is-less-than = 80; + # value = "$cpu-temperature"; + # } + # ]; + # }; + # priority = 70; + # } + # { + # cpu = { + # energy-performance-preference = "balance_performance"; + # governor = "schedutil"; + # }; + # "if" = { + # all = [ + # { + # is-more-than = 0.4; + # value = "%cpu-usage"; + # } + # { + # is-less-than = 0.8; + # value = "%cpu-usage"; + # } + # ]; + # }; + # priority = 60; + # } + # { + # cpu = { + # energy-performance-preference = "power"; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = { + # all = [ + # { + # is-less-than = 0.2; + # value = "%cpu-usage"; + # } + # { + # is-more-than = 60; + # value = "$cpu-idle-seconds"; + # } + # ]; + # }; + # priority = 50; + # } + # { + # cpu = { + # energy-performance-preference = "power"; + # frequency-mhz-maximum = 1600; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = { + # is-more-than = 300; + # value = "$cpu-idle-seconds"; + # }; + # priority = 40; + # } + # { + # cpu = { + # energy-performance-preference = "power"; + # frequency-mhz-maximum = 2000; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = { + # all = [ + # "?discharging" + # { + # is-less-than = 0.5; + # value = "%power-supply-charge"; + # } + # ]; + # }; + # power = {platform-profile = "low-power";}; + # priority = 30; + # } + # { + # cpu = { + # energy-performance-bias = "balance_power"; + # energy-performance-preference = "power"; + # frequency-mhz-maximum = 1800; + # frequency-mhz-minimum = 200; + # governor = "powersave"; + # turbo = false; + # }; + # "if" = "?discharging"; + # priority = 20; + # } + # { + # cpu = { + # energy-performance-preference = "balance_performance"; + # governor = "schedutil"; + # }; + # priority = 0; + # } + # ]; + # }; + # }; + services = { + upower = { + enable = true; + percentageLow = 15; + percentageCritical = 5; + }; + + acpid = { + enable = true; + logEvents = true; + }; + + auto-cpufreq = { + enable = false; + settings = { + charger = { + governor = "performance"; + energy_performance_preference = "performance"; + scaling_min_freq = mkDefault 1800000; + scaling_max_freq = mkDefault 3800000; + turbo = "auto"; + }; + + battery = { + governor = "powersave"; + energy_performance_preference = "power"; + scaling_min_freq = mkDefault 1200000; + scaling_max_freq = mkDefault 1800000; + turbo = "never"; + }; + }; + }; + }; + }; +} diff --git a/modules/system/hardware/ram/module.nix b/modules/system/hardware/ram.mod.nix similarity index 100% rename from modules/system/hardware/ram/module.nix rename to modules/system/hardware/ram.mod.nix diff --git a/modules/system/hardware/wifi.nix b/modules/system/hardware/wifi.nix deleted file mode 100644 index e69de29..0000000 diff --git a/modules/system/module.nix b/modules/system/module.nix deleted file mode 100644 index 8fc29c9..0000000 --- a/modules/system/module.nix +++ /dev/null @@ -1,14 +0,0 @@ -{config, ...}: let - machine-id = builtins.substring 0 23 (builtins.hashString "sha256" config.networking.hostName); -in { - system = { - # faster rebuilds - switch = { - enable = false; - enableNg = true; - }; - # our state version - stateVersion = "23.11"; - }; - environment.etc."machine-id".text = "${machine-id}\n"; -} diff --git a/modules/system/nix/documentation.nix b/modules/system/nix/documentation.mod.nix similarity index 78% rename from modules/system/nix/documentation.nix rename to modules/system/nix/documentation.mod.nix index b3afd60..41b5337 100644 --- a/modules/system/nix/documentation.nix +++ b/modules/system/nix/documentation.mod.nix @@ -3,13 +3,16 @@ documentation = { # whether to enable the `doc` output of packages # generally in ${pkg}/share/ as plaintext or html - # # can shave off a few megabytes + # can shave off a few megabytes doc.enable = false; # whether to install the `info` command and the `info` # output of packages info.enable = false; + # Whether to install documentation targeted at developers. + dev.enable = true; + man = { # Whether to install manual pages # this means packages that provide a `man` output will have said output @@ -22,7 +25,7 @@ generateCaches = false; # Whether to enable mandoc as the default man page viewer. - mandoc.enable = false; # my default manpage viewer is Neovim, so this isn't necessary + mandoc.enable = false; # my default manpage viewer is bat, so this isn't necessary }; }; } diff --git a/modules/system/nix/module.nix b/modules/system/nix/nix.mod.nix similarity index 66% rename from modules/system/nix/module.nix rename to modules/system/nix/nix.mod.nix index 1472607..5eb3fe2 100644 --- a/modules/system/nix/module.nix +++ b/modules/system/nix/nix.mod.nix @@ -1,57 +1,66 @@ # credits to raf { - config, - inputs, + sources, lib, pkgs, ... -}: let - inherit (lib.attrsets) mapAttrsToList; +}: +let inherit (lib.modules) mkForce; -in { - imports = [ - ./documentation.nix # nixos documentation - ./nixpkgs.nix # global nixpkgs configuration - ]; + lix = pkgs.callPackage "${sources.lix}/package.nix" { + stdenv = pkgs.clangStdenv; + }; +in +{ nix = { - package = pkgs.lix; + package = lix; + # Check that Nix can parse the generated nix.conf. + checkConfig = true; + + # Check the nix.conf, parsing for any kind of error. When disabled, checks only for unknown settings. + checkAllErrors = true; # fuck channels, no thanks channel.enable = mkForce false; # this is taken from sioodmy. # pin the registry to avoid downloading and evaling a new nixpkgs version every time - registry = - lib.mapAttrs (_: v: {flake = v;}) inputs - // {system.flake = inputs.self;}; + # registry = + # lib.mapAttrs (_: v: {flake = v.outPath;}) sources + # // {system.flake = sources.nichts;}; + registry.nixpkgs.to = { + type = "path"; + source = sources.nixpkgs; + }; - # This will additionally add your inputs to the system's legacy channels - # Making legacy nix commands consistent as well - nixPath = mapAttrsToList (key: _: "${key}=flake:${key}") config.nix.registry; + # Add inputs to the system's legacy channels + # to make legacy nix commands consistent as well + nixPath = [ "nixpkgs=/etc/nixos/nixpkgs" ]; - # Run the Nix daemon on lowest possible priority so that my system - # stays responsive during demanding tasks such as GC and builds. - # This is especially useful while auto-gc and auto-upgrade are enabled - # as they can be quite demanding on the CPU. + # Run the Nix daemon on lowest possible priority daemonCPUSchedPolicy = "idle"; daemonIOSchedClass = "idle"; daemonIOSchedPriority = 7; # Collect garbage + # NOTE: I use nh for this. gc = { automatic = false; dates = "20:00"; options = "--delete-older-than 7d"; - persistent = false; # don't try to catch up on missed GC runs + persistent = false; }; # Automatically optimize nix store by removing hard links optimise = { automatic = true; - dates = ["21:00"]; + dates = [ "21:00" ]; }; + # NOTE: + # Writes the settings to /etc/nix/nix.conf. + # See `man nix.conf` for more detailed descriptions of these settings. settings = { # Tell nix to use the xdg spec for base directories # while transitioning, any state must be carried over @@ -61,16 +70,31 @@ in { # Automatically optimise symlinks auto-optimise-store = true; - # Allow sudo users to mark the following values as trusted - allowed-users = ["root" "@wheel" "nix-builder"]; + # Users that are allowed to connect to the Nix daemon. + allowed-users = [ + "root" + "@wheel" + "nix-builder" + ]; - # Only allow sudo users to manage the nix store - trusted-users = ["root" "@wheel" "nix-builder"]; + # Users that are allowed to connect to the Nix daemon. + trusted-users = [ + "root" + "@wheel" + "nix-builder" + ]; # Let the system decide the number of max jobs # based on available system specs. Usually this is # the same as the number of cores your CPU has. - max-jobs = 2; + max-jobs = "auto"; + + # This option defines the maximum number of concurrent tasks during one build. + # It affects, e.g., -j option for make. The special value 0 means that the builder + # should use all available CPU cores in the system. Some builds may become + # non-deterministic with this option; use with care! + # Packages will only be affected if enableParallelBuilding is set for them. + cores = 0; # If set, Nix will perform builds in a sandboxed environment # that it will set up automatically for each build. @@ -99,6 +123,7 @@ in { "flakes" # flakes "nix-command" # experimental nix commands "cgroups" # allow nix to execute builds inside cgroups + "pipe-operator" ]; # Ensures that the result of Nix expressions is fully determined by @@ -132,21 +157,27 @@ in { keep-derivations = true; keep-outputs = true; - # Use binary cache, this is not Gentoo - # external builders can also pick up those substituters + # Use binary cache builders-use-substitutes = true; # Substituters to pull from. substituters = [ - "https://cache.nixos.org" # funny binary cache + "https://cache.nixos.org" ]; trusted-public-keys = [ "cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY=" ]; + # Determinate nix config + # =========================================== + # lazy-trees = true; + # =========================================== }; }; + environment.etc = { + "nixos/nixpkgs".source = builtins.storePath sources.nixpkgs; + }; systemd.services = { # WE DONT WANT TO BUILD STUFF ON TMPFS # ITS NOT A GOOD IDEA diff --git a/modules/system/nix/nixpkgs.mod.nix b/modules/system/nix/nixpkgs.mod.nix new file mode 100644 index 0000000..2955c48 --- /dev/null +++ b/modules/system/nix/nixpkgs.mod.nix @@ -0,0 +1,60 @@ +{ + lib, + sources, + pkgs, + ... +}: +let + inherit (lib.options) mkOption; + inherit (lib.types) str; +in +{ + imports = [ + # Going full schizo + "${sources.nixpkgs}/nixos/modules/misc/nixpkgs/read-only.nix" + ]; + + options.nixpkgs.system = mkOption { + type = str; + default = pkgs.system; + readOnly = true; + }; + + config.nixpkgs.pkgs = import sources.nixpkgs { + inherit (pkgs.stdenv) hostPlatform; + overlays = [ ]; + config = { + # Configuration reference: + # + # Disallow broken packages to be built. + allowBroken = false; + + allowUnsupportedSystem = true; + + # Warn when config contains an unrecognized attribute. + # This might be useful for getting a better configuration. + warnUndeclaredOptions = true; + + # Allow unfree packages + allowUnfree = true; + + # Permitted insecure packages in a system. + # Default to none, add more as necessary. + # Matrix also likes using deprecated libraries, which tend to go into this list. + # permittedInsecurePackages = []; + + # Whether to set enableParallelBuilding to true by default while + # building nixpkgs packages. Changing the default causes a mass rebuild. + enableParallelBuildingByDefault = false; + + # Whether to expose old attribute names for compatibility. + # This improves backwards compatibility, + # which I could not care less about in my configuration. + allowAliases = false; + + # List of derivation warnings to display while rebuilding. + # See: + showDerivationWarnings = [ ]; + }; + }; +} diff --git a/modules/system/nix/nixpkgs.nix b/modules/system/nix/nixpkgs.nix deleted file mode 100644 index f240b96..0000000 --- a/modules/system/nix/nixpkgs.nix +++ /dev/null @@ -1,35 +0,0 @@ -# taken from raf -{ - # Global nixpkgs configuration. This is ignored if nixpkgs.pkgs is set - # which is a case that should be avoided. Everything that is set to configure - # nixpkgs must go here. - nixpkgs = { - # Configuration reference: - # - config = { - # Disallow broken packages to be built. allowBroken = false; - allowUnsupportedSystem = true; - - # Allow unfree packages - allowUnfree = true; - - # Default to none, add more as necessary. This is usually where - # electron packages go when they reach EOL. - permittedInsecurePackages = ["olm-3.2.16"]; - - # Nixpkgs sets internal package aliases to ease migration from other - # distributions easier, or for convenience's sake. Even though the manual - # and the description for this option recommends this to be true, I prefer - # explicit naming conventions, i.e., no aliases. - allowAliases = false; - - # List of derivation warnings to display while rebuilding. - # See: - # NOTE: "maintainerless" can be added to emit warnings - # about packages without maintainers but it seems to me - # like there are more packages without maintainers than - # with maintainers, so it's disabled for the time being. - showDerivationWarnings = []; - }; - }; -} diff --git a/modules/system/os/impermanence/module.nix b/modules/system/os/impermanence.mod.nix similarity index 69% rename from modules/system/os/impermanence/module.nix rename to modules/system/os/impermanence.mod.nix index 8484f52..4125d44 100644 --- a/modules/system/os/impermanence/module.nix +++ b/modules/system/os/impermanence.mod.nix @@ -2,15 +2,18 @@ inputs, config, lib, + sources, ... -}: let +}: +let inherit (lib.modules) mkIf mkForce; inherit (builtins) map; cfg = config.modules.system.impermanence; -in { +in +{ imports = [ - inputs.impermanence.nixosModules.impermanence + (sources.impermanence + "/nixos.nix") ]; config = mkIf cfg.enable { users = { @@ -40,20 +43,36 @@ in { ]; users.cr = { - directories = - [ - "cloud" - "repos" - ] - ++ map ( - dir: ".config/${dir}" - ) ["nicotine" "Signal" "Nextcloud" "emacs" "doom"] - ++ map ( - dir: ".cache/${dir}" - ) ["tealdeer" "keepassxc" "nix" "starship" "nix-index" "mozilla" "zsh" "nvim"] - ++ map ( - dir: ".local/share/${dir}" - ) ["direnv" "Steam" "TelegramDesktop" "PrismLauncher" "nicotine" "zoxide" ".keepass"]; + directories = [ + "cloud" + "repos" + ] + ++ map (dir: ".config/${dir}") [ + "nicotine" + "Signal" + "Nextcloud" + "emacs" + "doom" + ] + ++ map (dir: ".cache/${dir}") [ + "tealdeer" + "keepassxc" + "nix" + "starship" + "nix-index" + "mozilla" + "zsh" + "nvim" + ] + ++ map (dir: ".local/share/${dir}") [ + "direnv" + "Steam" + "TelegramDesktop" + "PrismLauncher" + "nicotine" + "zoxide" + ".keepass" + ]; }; }; diff --git a/modules/system/os/networking/dns.mod.nix b/modules/system/os/networking/dns.mod.nix new file mode 100644 index 0000000..ee19661 --- /dev/null +++ b/modules/system/os/networking/dns.mod.nix @@ -0,0 +1,57 @@ +{ + config, + lib, + pkgs, + ... +}: +let + StateDirectory = "dnscrypt-proxy"; + inherit (lib.modules) mkForce; +in +{ + networking = { + networkmanager.dns = mkForce "none"; + nameservers = [ + "127.0.0.1" + "::1" + ]; + }; + + # See https://wiki.nixos.org/wiki/Encrypted_DNS + services.dnscrypt-proxy2 = { + enable = true; + # See https://github.com/DNSCrypt/dnscrypt-proxy/blob/master/dnscrypt-proxy/example-dnscrypt-proxy.toml + settings = { + sources.public-resolvers = { + urls = [ + "https://raw.githubusercontent.com/DNSCrypt/dnscrypt-resolvers/master/v3/public-resolvers.md" + "https://download.dnscrypt.info/resolvers-list/v3/public-resolvers.md" + ]; + minisign_key = "RWQf6LRCGA9i53mlYecO4IzT51TGPpvWucNSCh1CBM0QTaLn73Y7GFO3"; # See https://github.com/DNSCrypt/dnscrypt-resolvers/blob/master/v3/public-resolvers.md + cache_file = "/var/lib/${StateDirectory}/public-resolvers.md"; + }; + + # Use servers reachable over IPv6 -- Do not enable if you don't have IPv6 connectivity + ipv6_servers = true; + + # Server must support DNS security extensions (DNSSEC) + require_dnssec = true; + + # Server must not log user queries (declarative) + require_nolog = true; + + # Server must not enforce its own blocklist (for parental control, ads blocking...) + require_nofilter = true; + + ## Enable *experimental* support for HTTP/3 (DoH3, HTTP over QUIC) + ## Note that, like DNSCrypt but unlike other HTTP versions, this uses + ## UDP and (usually) port 443 instead of TCP. + http3 = false; + + ## Enable a DNS cache to reduce latency and outgoing traffic. + cache = true; + }; + }; + + systemd.services.dnscrypt-proxy2.serviceConfig.StateDirectory = StateDirectory; +} diff --git a/modules/system/os/networking/firewall.mod.nix b/modules/system/os/networking/firewall.mod.nix new file mode 100644 index 0000000..f016940 --- /dev/null +++ b/modules/system/os/networking/firewall.mod.nix @@ -0,0 +1,18 @@ +{ + config, + lib, + pkgs, + ... +}: +{ + networking = { + # use nftables over iptables + nftables.enable = true; + + firewall = { + enable = true; + allowPing = true; + logReversePathDrops = true; + }; + }; +} diff --git a/modules/system/os/networking/module.nix b/modules/system/os/networking/module.nix deleted file mode 100644 index fd4ca78..0000000 --- a/modules/system/os/networking/module.nix +++ /dev/null @@ -1,21 +0,0 @@ -{config, ...}: let - inherit (config.modules.other.system) username; -in { - imports = [ - ./networkmanager.nix - ]; - networking = { - enableIPv6 = true; - nameservers = [ - # quad9 DNS - "9.9.9.9" - "2620::fe::fe" - ]; - }; - services.resolved = { - enable = true; - # quad9 dns - fallbackDns = ["9.9.9.9" "2620::fe::fe"]; - }; - users.users.${username}.extraGroups = ["networkmanager"]; -} diff --git a/modules/system/os/networking/networking.mod.nix b/modules/system/os/networking/networking.mod.nix new file mode 100644 index 0000000..627919c --- /dev/null +++ b/modules/system/os/networking/networking.mod.nix @@ -0,0 +1,54 @@ +{ config, ... }: +let + inherit (config.modules.other.system) username; +in +{ + networking = { + enableIPv6 = true; + + wireless = { + # INFO: This disables wpa_supplicant, + # I use iwd instead. + enable = false; + + # use iwd over wpa_supplicant + iwd = { + enable = true; + settings = { + IPv6 = { + Enabled = true; + }; + Settings = { + AutoConnect = true; + }; + }; + }; + }; + + dhcpcd = { + # faster boot times + wait = "background"; + # do not edit resolv.conf + extraConfig = '' + nohook resolv.conf + ''; + }; + }; + + # service discovery on a local network via the mDNS/DNS-SD protocol suite + services.avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + }; + + users.users.${username}.extraGroups = [ "networkmanager" ]; + + # faster boot + systemd = { + network = { + enable = true; + wait-online.enable = false; + }; + }; +} diff --git a/modules/system/os/networking/networkmanager.nix b/modules/system/os/networking/networkmanager.mod.nix similarity index 69% rename from modules/system/os/networking/networkmanager.nix rename to modules/system/os/networking/networkmanager.mod.nix index d0c2228..187670c 100644 --- a/modules/system/os/networking/networkmanager.nix +++ b/modules/system/os/networking/networkmanager.mod.nix @@ -1,16 +1,12 @@ -{lib, ...}: let - inherit (lib.modules) mkForce; -in { +_: { networking.networkmanager = { enable = true; - # Removes about 2GB of stuff we do no need. - plugins = mkForce []; - dns = "systemd-resolved"; unmanaged = [ # DO NOT manage my docker containers, thank you. "interface-name:docker*" ]; + wifi = { # Generate a randomized value upon each connect macAddress = "random"; @@ -19,8 +15,11 @@ in { powersave = true; # Backend is either wpa_supplicant or iwd, - # we use iwd. + # I use iwd. backend = "iwd"; + + # Whether to enable MAC address randomization of a Wi-Fi device during scanning. + scanRandMacAddress = true; }; }; } diff --git a/modules/system/os/security/insults.patch b/modules/system/os/security/insults.patch new file mode 100644 index 0000000..db12548 --- /dev/null +++ b/modules/system/os/security/insults.patch @@ -0,0 +1,993 @@ +diff --git a/plugins/sudoers/ins_2001.h b/plugins/sudoers/ins_2001.h +index 19db27d842..d88bb95bf5 100644 +--- a/plugins/sudoers/ins_2001.h ++++ b/plugins/sudoers/ins_2001.h +@@ -1,35 +1,928 @@ +-/* +- * SPDX-License-Identifier: ISC +- * +- * Copyright (c) 1996, 1998, 1999 Todd C. Miller +- * +- * Permission to use, copy, modify, and distribute this software for any +- * purpose with or without fee is hereby granted, provided that the above +- * copyright notice and this permission notice appear in all copies. +- * +- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES +- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF +- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR +- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES +- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN +- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF +- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. +- */ +- +-#ifndef SUDOERS_INS_2001_H +-#define SUDOERS_INS_2001_H +- +- /* +- * HAL insults (paraphrased) from 2001. +- */ +- +- N_("Just what do you think you're doing Dave?"), +- N_("It can only be attributed to human error."), +- N_("That's something I cannot allow to happen."), +- N_("My mind is going. I can feel it."), +- N_("Sorry about this, I know it's a bit silly."), +- N_("Take a stress pill and think things over."), +- N_("This mission is too important for me to allow you to jeopardize it."), +- N_("I feel much better now."), ++ /* ++ * SPDX-License-Identifier: ISC ++ * ++ * Copyright (c) 1996, 1998, 1999 Todd C. Miller ++ * ++ * Permission to use, copy, modify, and distribute this software for any ++ * purpose with or without fee is hereby granted, provided that the above ++ * copyright notice and this permission notice appear in all copies. ++ * ++ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES ++ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF ++ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ++ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES ++ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ++ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF ++ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. ++ */ ++ ++ #ifndef SUDOERS_INS_2001_H ++ #define SUDOERS_INS_2001_H ++ ++ /* ++ * HAL insults (paraphrased) from 2001. ++ */ ++ ++ N_("Buttons are for idiots."), ++ N_("Why are you guys so fork paranoid? Do you want everyone to vote for the same political party, too?"), ++ N_("But software which OpenBSD uses and redistributes must be free to all (be they people or companies), for any purpose they wish to use it, including modification, use, peeing on, or even integration into baby mulching machines or atomic bombs to be dropped on Australia."), ++ N_("You did not create these mailing lists, so you can take your opinions about why these lists were created and shove them up your ass."), ++ N_("I am simply astounded at some of the things people keep repeating. I don't mean this applies to everyone, but is there a high quantity of attention deficit disorder in our user community? Or retards? Or is it just the same old trolling? OpenBSD does not incorporate non-free software."), ++ N_("Scaling isn't really our concern; I barely know what the word means. There is one group of people who we do know scales. Whiners. They scale really well."), ++ N_("I am very easy to get along with, but I don't have time to waste being nice to people who are being stupid."), ++ N_("Hardly surprising. Apple. They build crap and make you pay extra."), ++ N_("You are absolutely deluded, if not stupid, if you think that a worldwide collection of software engineers who can't write operating systems or applications without security holes, can then turn around and suddenly write virtualization layers without security holes."), ++ N_("In the modern world of search engines, this question lands at the same level as trolling."), ++ N_("You are very confused."), ++ N_("Have you considered trying to live 100% without our software?"), ++ N_("Your grief would seem more sincere if didn't look like a shopping list."), ++ N_("You are not listening."), ++ N_("You enabled things which are disabled for a good reason."), ++ N_("You are missing the point. Your bug report is huge, but we have no idea what went wrong."), ++ N_("It is pretty clear you are a troll."), ++ N_("No, please, don't explain."), ++ N_("You obviously have zero experience."), ++ N_("You clearly cannot read."), ++ N_("You better get back to class; your potty break is over."), ++ N_("Go read the source code some time."), ++ N_("Nope."), ++ N_("No."), ++ N_("Bullshit."), ++ N_("The rest of your new email is bullshit, too."), ++ N_("Noone deserves anything from us. People get good things, and they are happy. The developers in this project do the best they can writing innovative software, and will not accept preaching from pompous self-entitled American pricks like you."), ++ N_("I believe you deserve to stop running the software."), ++ N_("You are wrong."), ++ N_("Don't be ridiculous."), ++ N_("Yes, we should build a survey. And a wiki. It would be awesome. We'd get rich."), ++ N_("One word can change the meaning of a sentence. You failed at what you intended, and you also confused people."), ++ N_("You made a decision to keep running code that old, and thus you are on your own. You won't spend time figuring out which one of our changes over 2 years might fix the problem you are having, and we won't either."), ++ N_("Your hopes are misplaced."), ++ N_("I still think you are a loser."), ++ N_("If you have endured a real bug for a long time, and not filed a bug report to have it fixed.. and then feel it is your right to scold people who attempt to explain the bug, then quite frankly, then YOU TOTALLY SUCK."), ++ N_("You are astoundingly naive. We simply don't need the grief of entertaining users like you."), ++ N_("Basically what you submitted was not a bug report."), ++ N_("User is using a heavily tuned kernel and refuses to listen to advice about de-tuning all those things; as a result, noone can help him."), ++ N_("Holy cow, you are dense."), ++ N_("You don't know what you are talking about, and you don't seem to have the ability to wrap your mind around all the parts that are involved."), ++ N_("I am not reading your mails again."), ++ N_("Totally false."), ++ N_("You must not be reading the same code I am."), ++ N_("Your approach is wrong."), ++ N_("What you just said was utterly careless."), ++ N_("No. You misread the code."), ++ N_("All the many eyes are apparently attached to a lot of hands that type lots of words about many eyes, and never actually audit code."), ++ N_("I am so bloody dissapointed in the community that uses our stuff."), ++ N_("What a dismal world view."), ++ N_("That is a simplistic viewpoint held by your simplistic mind."), ++ N_("I hope that one day due process is denied you."), ++ N_("Such an American viewpoint."), ++ N_("It didn't work out for Don Quixote either."), ++ N_("You have it entirely backwards."), ++ N_("But you decided you are special, and don't want us to help us help you."), ++ N_("Oh good grief, grow up."), ++ N_("Things change. Learn to cope."), ++ N_("Bye bye."), ++ N_("Stop thinking of only yourself."), ++ N_("You don't listen well either."), ++ N_("The comedy just never ends."), ++ N_("Hahahahaha. That's a good one."), ++ N_("I have a hard time believing you."), ++ N_("You are using FreeBSD, aren't you."), ++ N_("These programs are all bad."), ++ N_("If you expected any of us to reply as if we are contractors or your employees, you came to the wrong place."), ++ N_("If you want the answers you are looking for, do the work yourself."), ++ N_("That is not our problem."), ++ N_("If you are not careful, why should we be?"), ++ N_("Enjoy your windmill tilting."), ++ N_("I should probably ask -- did you even read the panic? Is the wording too poor to understand (and thus result in peeking at the code) or is the problem above the keyboard?"), ++ N_("Oh, but linux people told you it was the best. I get it."), ++ N_("God god, do you live in some stupid fantasy world?"), ++ N_("You already have a prompt that asks you that question."), ++ N_("Since your PR contains absolutely zero information about your machine I am sending you back to kindergarden. Because you totally suck."), ++ N_("We'll be waiting for your fix then."), ++ N_("Come on. Read it carefully."), ++ N_("You have no right to speak."), ++ N_("It's a pity you don't go jump in a lake and drown yourself."), ++ N_("Thanks for telling me do so some reading, but a google of your name on these mailing lists will show a 10 year pattern of you not being able to self-help. Something to do with your parents, probably."), ++ N_("Hey look everyone, it's another uneducated user mouthing off on a noisy mailing list. He goes blah blah blah, loving the sound of his own noise."), ++ N_("I don't see any humility."), ++ N_("What a load of bullshit."), ++ N_("You are killing us with hyperbole. It is now hard to take anything you say seriously."), ++ N_("FULL STOP."), ++ N_("Why don't you figure that out."), ++ N_("Balony."), ++ N_("Anyways, who cares."), ++ N_("We couldn't care what you believe, unless you have diffs of your own to submit."), ++ N_("You're kidding."), ++ N_("You are making up rules as you go along. Why don't you go read the code?"), ++ N_("Oh cut the crap."), ++ N_("Frankly, I think you are a whiner."), ++ N_("In your dreams.."), ++ N_("No. You must be at least this tall to use OpenBSD; sorry -- you are a midget."), ++ N_("You've got it all wrong."), ++ N_("You'll experience anguish, and then if you try to ask for sympathy a lot of people will laugh at you."), ++ N_("I don't know for certain, but I believe you are just making things up as you go along, because you are nothing but a troll."), ++ N_("In summary -- the entire effort is a complete load of crap."), ++ N_("Oh come on, admit it, you are wrong."), ++ N_("That's a lot of words."), ++ N_("Sorry, but I have lost all appetite to help you."), ++ N_("Oh sorry, I forgot to think like an American for a second there."), ++ N_("If you have so many ideas you should go ahead and start your own project. Good luck building a successfull project based on 'ideas'."), ++ N_("I'm not even going to read to the end."), ++ N_("You are a prick."), ++ N_("Tell linus. You can google for his email address. "), ++ N_("Just pathetic. Hope you actually get a life sometime."), ++ N_("Wrong."), ++ N_("You missed the point."), ++ N_("Don't worry. Most of us see your name and at that moment delete the mail. This reply is an exception."), ++ N_("You realize that you are going to run into thousands of other problems as a result of that practice?"), ++ N_("What you suggest is absolute rubbish. It is just talk -- not action -- but furthermore you don't have a clue what you are talking about."), ++ N_("Really. How interesting."), ++ N_("Let's keep it simple. Why don't you just go away, and stop acting the fool?"), ++ N_("I am just plain fed up with the bullshit you cowards spew."), ++ N_("I don't believe you. You suggested it because you only thought of your own benefit, not of the amount of work others would have to do."), ++ N_("Have you thought this through, at all?"), ++ N_("Some days I want to just quit and say fuck it all."), ++ N_("All I ever wanted was a hobby. If this pathetic slob doesn't like our hobby, they should stop relying on it."), ++ N_("Let idiots suffer on their own."), ++ N_("The point is that you are a crybaby."), ++ N_("We really are not interested in the story of your life."), ++ N_("So you presume."), ++ N_("You probably rape children in your spare time, and here you are, yelling at us for violating your perceived entitlement."), ++ N_("Can you please leave?"), ++ N_("Now, again, please leave."), ++ N_("You know, you have an option available to you regarding this. You could come to the conclusion that you are not entitled and stop posting, and it will work out better in the long term. I did not read anything more you said."), ++ N_("Your attitude stinks. Good luck with life."), ++ N_("Pulease..."), ++ N_("I don't know who you are, but you do nothing. What do you do?"), ++ N_("I don't see your name on any the source code. So you shut up, loser. Just go away."), ++ N_("Perhaps we made mistakes. Perhaps they'll be changed. But you are just spouting bullshit."), ++ N_("I am not being sarcastic. I truly am sick of having my time wasted."), ++ N_("Yes you are wrong, and damn infuriating too."), ++ N_("You need to learn how to listen."), ++ N_("Read what it says."), ++ N_("You just like listening to yourself talk. Shut up."), ++ N_("I don't see the point."), ++ N_("Please don't."), ++ N_("The best part is that noone cares about that."), ++ N_("It is disgraceful to see what type of code being written these days."), ++ N_("You accept how we do it, and you will shut up, or less service will be provided in the future."), ++ N_("If you don't like it, run something else."), ++ N_("I don't care."), ++ N_("I don't give a shit."), ++ N_("I really don't give a shit what you admire or not. "), ++ N_("You are a whiny snively jerk, and every time you open your mouth I go work on something else."), ++ N_("Your sense of self-importance just makes other people not even want to try."), ++ N_("I could not give a rats ass what you say."), ++ N_("You just plain don't understand the problem."), ++ N_("Your attitude is not very nice."), ++ N_("You had me going for a moment."), ++ N_("Wow, your process stinks."), ++ N_("You need to read more carefully."), ++ N_("If you are just grandstanding, please stop."), ++ N_("Ah, we have another talker in the house."), ++ N_("Perhaps you should get a good delicing. "), ++ N_("You'll never be a developer, so who cares?"), ++ N_("Oh my god, the tears! Look at his tears!"), ++ N_("Just give it up and get lost."), ++ N_("Wow, you sure like to make presumptions."), ++ N_("Thing is, you won't get help here."), ++ N_("Your lack of any attempt to educate yourself is your problem."), ++ N_("No, no no no no."), ++ N_("No. You have it wrong. Go back to reading school."), ++ N_("Come on.. stop making assumptions."), ++ N_("We are not believers in buttons. Knobs are for knobs."), ++ N_("Oh yeah, that's a great idea!"), ++ N_("I'm making fun of you."), ++ N_("Whatever you did does not do what you think it does. In fact, I bet it is doing exactly the opposite of what you think it does."), ++ N_("Don't be fooled."), ++ N_("They are simplistic retards, not because they choose to be, but because their paychecks tell them to be so."), ++ N_("Great."), ++ N_("Oh, you're not going to do it? Oh you can't do it?"), ++ N_("No way."), ++ N_("Except you are wrong."), ++ N_("If some of you people keep insisting on having backwards compatibitity with the stone age, we'll have stone tools forever."), ++ N_("I don't know why our mailing lists are always full of people who don't even understand what they are talking about."), ++ N_("You guys just are not thinking."), ++ N_("You've got to be kidding me."), ++ N_("I won't look further since you have a history of not listening."), ++ N_("There is no point in testing a diff which is wrong."), ++ N_("Are you a troll?"), ++ N_("can you not read the prompt?"), ++ N_("No, I am advocating that you TAKE CARE OF YOUR OWN PROBLEMS YOURSELF."), ++ N_("Learn your tools. From hammers to saws to cars to operating systems, it is all the same."), ++ N_("That is balony."), ++ N_("PHP is not part of OpenBSD."), ++ N_("To me it sounds like you are used to paying a lot, and now you expect the same from us, who you don't pay at all. That is a rude approach."), ++ N_("Who's the child now?"), ++ N_("We try our best to make it the best. Do you try your best to help us? I doubt it. So we try the best we can without people like you helping us."), ++ N_("So learn to type correctly."), ++ N_("Shame on you."), ++ N_("This is an error in the manual page."), ++ N_("whatever."), ++ N_("I do not agree with your assessment."), ++ N_("Why hold people who you don't pay to a higher standard than the people who you do pay?"), ++ N_("Stop spreading lies."), ++ N_("Geez, you're not listening"), ++ N_("make of it what you will."), ++ N_("Unfortunate."), ++ N_("Be realistic."), ++ N_("Sorry, but you are wrong."), ++ N_("You are completely missing the point."), ++ N_("If that workaround was the right thing to do, it would be the default."), ++ N_("What happened is that you thought it was time to say something useless, which adds no value to the conversation."), ++ N_("You are just a whiny boy who pisses on people who spent 2 years writing the code."), ++ N_("In short, you are socially inept unappreciative asshole."), ++ N_("Come on guys. Don't have me OK this."), ++ N_("I see other projects falling into this problem all the time. It is awesome."), ++ N_("Ha ha. I watch other projects."), ++ N_("We won't commit it."), ++ N_("Perhaps."), ++ N_("I don't see any problem."), ++ N_("As developers we make decisions which we believe serve our users the best."), ++ N_("Wow, what's that got to do with anything?"), ++ N_("c++ is a pile of crap."), ++ N_("You have this very wrong."), ++ N_("Your code is completely wrong."), ++ N_("No way."), ++ N_("None of that matters here."), ++ N_("I am not directing you."), ++ N_("Wow. You sure do set the bar low."), ++ N_("The rest of what you are yapping about does not matter."), ++ N_("Do you think we care?"), ++ N_("God bless the people who employ you, they need the blessing."), ++ N_("That's the process."), ++ N_("Hey, stick a screw driver into your ear."), ++ N_("Does it help anything? No."), ++ N_("Ridiculous."), ++ N_("You know better."), ++ N_("Lacking a terse starting point, soon we have users who don't know where to start."), ++ N_("Beautiful."), ++ N_("the multiplicative effects are far too serious."), ++ N_("^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^"), ++ N_("If you believe strongly in this idea, you should take an entire operating system base and prove the case."), ++ N_("Good luck!"), ++ N_("Totally wrong there."), ++ N_("Uhm, that's a pretty weak argument."), ++ N_("Too bad. You can use other software."), ++ N_("I decided to make a guess as to the region you are from."), ++ N_("Your request is ridiculous."), ++ N_("The people who write code get to decide how they document it."), ++ N_("Don't like it? Then walk away."), ++ N_("The only person who did something useful, is the author of the software."), ++ N_("There is a user community, and a development community."), ++ N_("Listen to yourself, proud of the complex words you found in a dictionary."), ++ N_("It is really amazing that so many people prefer to remain blissfully unaware."), ++ N_("Sorry, but it's the truth."), ++ N_("So glad to have the expert speak."), ++ N_("It is clear you don't understand the code that was commited."), ++ N_("It is an obvious mechanism."), ++ N_("Good luck."), ++ N_("Autoinstall does not handle this type of problem either."), ++ N_("I really love how we keep getting advice."), ++ N_("That's a great idea."), ++ N_("That is not true."), ++ N_("Maybe."), ++ N_("It's so simple. Why didn't I think of it."), ++ N_("I am going to make a guess here."), ++ N_("Imagine you told us a lot about your life, and we gave you advice."), ++ N_("If you want it done, do it yourself."), ++ N_("I rather doubt it."), ++ N_("You've missed the point."), ++ N_("Wow, so many crazy suggstions."), ++ N_("I completely doubt that."), ++ N_("thanks for the lesson in logic."), ++ N_("No, the original answer here is the right one."), ++ N_("Please state your case very carefully and clearly."), ++ N_("Right now, you are not talking facts."), ++ N_("You are spreading misinformation."), ++ N_("Why???"), ++ N_("NO WAY!"), ++ N_("That feels like a disservice to the world."), ++ N_("This is total balony."), ++ N_("Bullshit."), ++ N_("Wow. What hostility."), ++ N_("There's research and there is the real world."), ++ N_("From time to time, mistakes sneak in."), ++ N_("It is theoretically possible to give a loaded gun to a baby; things will probably work out fine."), ++ N_("What is your solution?"), ++ N_("And what is your solution?"), ++ N_("I'm getting ready to declare you a kook"), ++ N_("In that situation, you would probably want to be left in piece."), ++ N_("If you start your own successfull project, you also can develop your own set of reasons for doing any of a variety of operational things at any point in time."), ++ N_("You seem to have a rather over-extented sense of entitlement"), ++ N_("Most people are not capable of writing good patches, so it would be unprofessional to ask such people to write patches."), ++ N_("You are speaking like a child."), ++ N_("You really need to write a single comprehensive bug report that has no inconsistancies."), ++ N_("THANK YOU FOR THE CLARITY."), ++ N_("Sigh."), ++ N_("So read what I said again."), ++ N_("Improvements come when people try to push forward along the curve."), ++ N_("People like you..."), ++ N_("Let's follow that thought."), ++ N_("Incorrect."), ++ N_("I don't see the point."), ++ N_("So that is the reason why my car stereo has two sets of volume control knobs..... with the second set located inside the engine compartment, so I have to stop at the side of the road, pop open the hood, and reach down along the hot engine to near where the oil filter is."), ++ N_("Take that for what it is."), ++ N_("Whatever you're doing, it is wrong."), ++ N_("Riiiiiiiiight. Suuuuuuuure. Keep believing that."), ++ N_("I would like to see some proof of that."), ++ N_("That's not going to happen."), ++ N_("Wow. No."), ++ N_("You are showing that you can't do any research at all, but want to throw ideas out."), ++ N_("Unlikely."), ++ N_("Well..."), ++ N_("That is a very dangerous direction."), ++ N_("I think this will cause further damage."), ++ N_("Are you saying OpenBSD does it wrong, or that all the operating systems do it wrong?"), ++ N_("Wow, really thick skull you got there."), ++ N_("Get real."), ++ N_("You can decide what you do with your time, but you cannot decide what other people do with theirs."), ++ N_("And then we move on?"), ++ N_("Are you kidding? Who does that help? Who?"), ++ N_("You have offered nothing."), ++ N_("You overstate your worth."), ++ N_("shrug"), ++ N_("In your dreams."), ++ N_("Amazing isn't it?"), ++ N_("Oh now I sense some angst."), ++ N_("See how bad things start to happen?"), ++ N_("But I think it is clear you aren't a programmer, and this is over your head."), ++ N_("Did they pay you to write all that text?"), ++ N_("there is bullshit coming out of your mouth."), ++ N_("You are the type of people who create these situations."), ++ N_("We rarely hear about success, because those people are just happy."), ++ N_("Totall irrelevant."), ++ N_("It is what it is. Work with it."), ++ N_("In the interests of full disclosure, do you work for the government or sell to the government?"), ++ N_("I heard."), ++ N_("you must know, i want no part in any politics."), ++ N_("i'm trying to stay out of politics."), ++ N_("there are fingers to point all the way around."), ++ N_("am i making all this up? perhaps i am, but you don't have to dream my dreams."), ++ N_("i was up at 9am, climbed a mountain, hiked 6 km through 4ft deep slush (the image you are supposed to get is of 12 million overturned slurpee cups, and of geting your groin wet in slurpee), nearly died eating beef vindaloo, wrote some code, talked on the phone, wrote mail, and now it's almost 4am and this is absolutely beyond ridiculous."), ++ N_("who said that?"), ++ N_("why are you asking me?"), ++ N_("Then I guess you are just stupid."), ++ N_("Since you don't supply diffs, you are a waste of skin."), ++ N_("Huh? You've understood incorrectly."), ++ N_("This approach is simplestic and wrong."), ++ N_("This is not a conversation about your IPv6 connection."), ++ N_("What problem are you trying to solve?"), ++ N_("Wow, what chatter."), ++ N_("I don't understand society is producing a generation of people incapable of self-help."), ++ N_("There are people who do that."), ++ N_("Shrug."), ++ N_("Chill dude."), ++ N_("It is crap."), ++ N_("Oh good god."), ++ N_("I don't know you, maybe I am misinterpreting you."), ++ N_("Wow, don't know where you got that from."), ++ N_("You persist in reading too much into things."), ++ N_("So this is a great way to lose focus."), ++ N_("You can figure out what I'm not saying on this line."), ++ N_("I think this is a trap."), ++ N_("That is an interesting claim."), ++ N_("ANSWER THE QUESTION."), ++ N_("I am not playing any games. Let's look at the facts."), ++ N_("I haven't even read this."), ++ N_("I don't care."), ++ N_("I quite dislike the direction this is going."), ++ N_("Nothing ever changes, noone ever learns, noone cares."), ++ N_("With your attitude, I beg you to please go run some other operating system."), ++ N_("Why haven't you left? Please leave."), ++ N_("Please leave immediately."), ++ N_("Get over it."), ++ N_("Please read the actual code."), ++ N_("Was that neccessary?"), ++ N_("Handholding can go only so far."), ++ N_("Please, not again."), ++ N_("It is in the FAQ."), ++ N_("Someone is totally full of shit."), ++ N_("You are quite a character."), ++ N_("I suspect money which goes into your bank account comes from an entity not quite on the same side as us."), ++ N_("You have an agenda."), ++ N_("So easy to be critical."), ++ N_("Great conversation..."), ++ N_("Who do you work for? Governments?"), ++ N_("Please people, ignore him."), ++ N_("I love this conversation."), ++ N_("Amazing."), ++ N_("Go a few cycles."), ++ N_("Why?"), ++ N_("No really, precisely why do you trust us?"), ++ N_("What a joke."), ++ N_("That is quite a fiction."), ++ N_("Never expect a group to perform a task which an individual won't."), ++ N_("We never said our code should be trusted."), ++ N_("Since I value my sanity, I saw that report, and I ignored it."), ++ N_("The complaint department is down the hall."), ++ N_("Such strong words."), ++ N_("It must be easy to sit in your chair and demand that others meet your expectations."), ++ N_("Didn't you read the manual page?"), ++ N_("I think you are on your own."), ++ N_("Nope."), ++ N_("Look there is a disconnect."), ++ N_("Fundamentally, OpenBSD is a research project."), ++ N_("Hilarious."), ++ N_("And now let's ask the question which matters."), ++ N_("Did you think of that?"), ++ N_("You aren't even trying. PLONK."), ++ N_("Oh just shut up."), ++ N_("You aren't going to do shit because you don't have any skills."), ++ N_("Thank you for adding the value of your words."), ++ N_("This is idle chatter hoping someone supplies some secret sauce that makes a disparate audience with different demands all happy."), ++ N_("Welcome to the real world."), ++ N_("Sorry."), ++ N_("Violates POSIX and C89, which violate best practice in this century."), ++ N_("Look, this is rather simple."), ++ N_("Oh really."), ++ N_("It ends badly."), ++ N_("I explained that."), ++ N_("Alas."), ++ N_("The NTP codebase is larger than the SSH codebase."), ++ N_("Guess you don't understand internet."), ++ N_("Can I ask what kind of plant are you?"), ++ N_("And who are you, and what you have you done to test and then prove your thesis?"), ++ N_("I am continually baffled by how often we have to explain this point, over and over and over again."), ++ N_("Do not submit a new bug report."), ++ N_("Let me be blunt. Your advice is bad."), ++ N_("If as a general rule we all want better code running on our systems, where do you fit in?"), ++ N_("Nope!"), ++ N_("Sigh."), ++ N_("Now you plainly don't sound like a developer type."), ++ N_("What is your solution?"), ++ N_("You've got access to all this source code."), ++ N_("If you can't study the world around you, you will remain ignorant."), ++ N_("Don't worry."), ++ N_("For contributions to the OpenBSD Project, I make the decision of how to spend it."), ++ N_("Is that an accusation?"), ++ N_("Look, you'll be fine."), ++ N_("Don't waste your money on a false ideal by someone who misunderstands modern hardware and the market forces."), ++ N_("I've think you've had your say."), ++ N_("You've had your say."), ++ N_("Do you get it? I doubt it."), ++ N_("How dreary."), ++ N_("Anyways, your timing is atrocious!"), ++ N_("Look, stop being a child."), ++ N_("Such hyperbole! Such drama!"), ++ N_("Reactive is not the same as proactive."), ++ N_("Please run something else. You'll be happier. Really."), ++ N_("The problem is you don't pay it backwards. You don't pay it forward. You don't pay at all. You just beg."), ++ N_("I'll ask in a general fashion: Are you stupid?"), ++ N_("You are out of touch."), ++ N_("OpenBSD is not generally known as an exposed democracy."), ++ N_("Are you going to do something -- beyond just being sarcastic?"), ++ N_("Highly unlikely."), ++ N_("Thanks for including all the information in the report."), ++ N_("Better question is: Why?"), ++ N_("Get back onto your meds."), ++ N_("What a waste of words."), ++ N_("Please people stop mailing me privately and asking."), ++ N_("Wait and see."), ++ N_("In general, you underestimate the effort involved."), ++ N_("Well, I don't think the world will fall over as a result."), ++ N_("NOT...."), ++ N_("I think this entire conversation is ridiculous, right from the start."), ++ N_("I do not agree with those assessments."), ++ N_("In that case, what's the fuss?"), ++ N_("Well...."), ++ N_("I disagree on all those points."), ++ N_("Completely wrong, and I have no no idea where you got that from!"), ++ N_("Read the man page again!"), ++ N_("You are scaring me."), ++ N_("I believe something is not being understood here."), ++ N_("I don't normally do this."), ++ N_("Well sorry."), ++ N_("I don't see any reason."), ++ N_("Oh something is broken?"), ++ N_("Please show your work."), ++ N_("Let's get serious and personal here for a second. In other aspects of life, do you behave the same?"), ++ N_("That is kind of crazy, isn't it."), ++ N_("That is an incorrect assessment."), ++ N_("That is only the beginning of it."), ++ N_("This is more than a meme. It is a plot."), ++ N_("Boggles the mind."), ++ N_("Please."), ++ N_("You know that is bullshit right?"), ++ N_("Please stop subscribing us to your motivations."), ++ N_("That is false."), ++ N_("You are speaking in riddles."), ++ N_("That's nice."), ++ N_("You are so full of BS!"), ++ N_("You are quite a persistant idiot."), ++ N_("You don't know jack shit about computers or electronics, that much is obvious."), ++ N_("Once again you show that you don't know shit."), ++ N_("You are on your own."), ++ N_("you have confused yourself."), ++ N_("Well there is this funny story about when I hacked into RMS's firmware-driven keyboard controller, and managed to grap his root password."), ++ N_("You've been smoking something really mind altering, and I think you should share it."), ++ N_("You've seen something on the shelf, and it has all sorts of pretty colurs, and you've bought it."), ++ N_("Feeling a lot of dejavu here."), ++ N_("People should be careful what they ask for"), ++ N_("Aww come on, you had us going until then."), ++ N_("I think I hear of someone doing this about every 10 years."), ++ N_("I made none of the claims you are composing."), ++ N_("That makes no sense."), ++ N_("Cannot."), ++ N_("Your process here is really strange."), ++ N_("How bizzare."), ++ N_("This conversation is going far too meta."), ++ N_("What's the goal."), ++ N_("You have a diff?"), ++ N_("What you are trying to do is insane, wrong, and entirely unsupported."), ++ N_("SERIOUSLY??"), ++ N_("If you turn the forums you frequent into your help desk, you are taking away their ability to focus on delivering you the software you use."), ++ N_("There are too few of us, we cannot take on every problem."), ++ N_("Everyone, please ignore these trolls who are cross-posting."), ++ N_("Essentially, you are on your own. :-)"), ++ N_("I am not so sure."), ++ N_("obviously."), ++ N_("I don't know, but I'll think about it later, because I am busy."), ++ N_("So the original idea wasn't yours. And now you think it can't work. And you are still talking about it. I see. Very interesting."), ++ N_("That statement is full of potential for misunderstanding, and cannot be left alone."), ++ N_("I was wrong."), ++ N_("Thanks."), ++ N_("Careful there :-)"), ++ N_("That is incorrect advice for the OpenBSD world."), ++ N_("Your mistake."), ++ N_("This bug report totally sucks."), ++ N_("my advice: walk away from this one."), ++ N_("Generally Unix has no way of doing this."), ++ N_("So what do you really mean here?"), ++ N_("Is a crash a performance impact?"), ++ N_("what is the goal?"), ++ N_("Your emails only contain opinions."), ++ N_("words words words words"), ++ N_("Are you done?"), ++ N_("Doesn't that send shivers down your spine?"), ++ N_("Your bug report is too incomplete. Can't help you."), ++ N_("No."), ++ N_("We'd rather jump off a cliff."), ++ N_("Good luck with that."), ++ N_("Looking forward to you providing code which solves the problem."), ++ N_("This feature is probably older than you."), ++ N_("it is behaving *exactly* as intended."), ++ N_("There are a few compromises."), ++ N_("I think I know a perfect candidate to take this further: You."), ++ N_("Seriously?"), ++ N_("The OpenBSD process is quite well understood. Use the best methods, doubt what you do, refractor."), ++ N_("Hey, it looks like you are just trying to be a dick."), ++ N_("Does your mother know?"), ++ N_("It's great that you have an opinion."), ++ N_("Run something else! We don't care!"), ++ N_("That's a load of bull."), ++ N_("Your opinions count for zero."), ++ N_("To achieve merit, you must do the homework you assigned yourself."), ++ N_("Get serious."), ++ N_("and I wanna build a rocket ship..."), ++ N_("No thanks."), ++ N_("The problem is obvious."), ++ N_("If you don't have the skill to do it, well that's too bad..."), ++ N_("You didn't do your homework, and it blew up in your face. Then you wrote a few paragraphs. Then I replied. That is the whole sad story."), ++ N_("I tried to read the rest of what you wrote. It makes no sense."), ++ N_("I find this discussion pretty uninteresting."), ++ N_("I wish more people would find real bugs to fix."), ++ N_(":-)"), ++ N_("I'm done."), ++ N_("I don't think you understand what is being done here."), ++ N_("Funny."), ++ N_("I don't see that."), ++ N_("I don't have an answer for you."), ++ N_("I don't see the purpose of that."), ++ N_("No."), ++ N_("Doctor it hurts when I stab myself in the eye."), ++ N_("I believe you are not trying to contribute anything valuable with your comment."), ++ N_("are you being trolled now?"), ++ N_("You are not tall enough to ride."), ++ N_("^^^^^^^"), ++ N_("People who submit reports which are missing information should feel terrible."), ++ N_("Absolutely no way, that makes no sense."), ++ N_("Kill it."), ++ N_("On that matter, I'd say tough."), ++ N_("It's not black magic."), ++ N_("Sigh."), ++ N_("Disagree strongly."), ++ N_("Don't hold me responsible for the shortcuts."), ++ N_("And noone cares what you like or dislike."), ++ N_("There will be little or no thought."), ++ N_("I am very sceptical."), ++ N_("A related issue is lots of people don't know anything about anything."), ++ N_("Look, your statement is false."), ++ N_("That is the result of a mis-configuration on your part."), ++ N_("That is not best practice."), ++ N_("This does not matter."), ++ N_("It is risk, all gigantic risk."), ++ N_("Sometimes people put a bad idea into an RFC."), ++ N_("Why -- to hurt people?"), ++ N_("Oh the situation is much worse than that."), ++ N_("I disagree."), ++ N_("The same model is not applicable to everything."), ++ N_("This is another offer which will be rejected."), ++ N_("No."), ++ N_("Tired of the suggestions."), ++ N_("The end."), ++ N_("Sorry, I see it the other way around."), ++ N_("This is how rumours start, I guess."), ++ N_("That is incorrect."), ++ N_("That is the worst possible advice ever."), ++ N_("I am really impressed by the analytical skills I observe here."), ++ N_("Maybe the fortress fell over because you didn't have enough Lego."), ++ N_("Why are you doing this?"), ++ N_("I still don't see the use case."), ++ N_("You haven't justified it."), ++ N_("No."), ++ N_("I have changed my mind."), ++ N_("Whoa."), ++ N_("I don't see how that helps anything."), ++ N_("What do you want us to do about it?"), ++ N_("I think you are done here."), ++ N_("Whoah."), ++ N_("because."), ++ N_("No, it is not."), ++ N_("Why?"), ++ N_("Please supply a good justification why that is good."), ++ N_("End of story."), ++ N_("Everyone tires of your well articulated agenda pushes."), ++ N_("Incorrect."), ++ N_("Not exactly."), ++ N_("We already suffer from low quality in many bug reports."), ++ N_("Our function in this ecosystem definately does not include dealing with other people's bullshit decisions..."), ++ N_("If you don't care, then don't talk about it."), ++ N_("Your voice does not count."), ++ N_("that is really not a useful bug report."), ++ N_("Yeah, you sure are the cool dude."), ++ N_("Things change."), ++ N_("Whoa."), ++ N_("No?"), ++ N_("Expectation management is a bitch."), ++ N_("There has been a lot of discussion about this."), ++ N_("Just stop it. We are not going to listen to you."), ++ N_("That is not right."), ++ N_("You are on your own."), ++ N_("That is not true."), ++ N_("That's nice."), ++ N_("not everything is perfect."), ++ N_("I don't like it."), ++ N_("We prefer creating a world that is simpler."), ++ N_("Are we finished here?"), ++ N_("that is intentional."), ++ N_("Why not delete it?"), ++ N_("Pick a position -- then defend it."), ++ N_("Switch to Linux, where violations are the norm."), ++ N_("Pick a damn position, and declare it."), ++ N_("If software sucks, say so."), ++ N_("Who didn't solve that problem? People like you."), ++ N_("Around here, you come off like a dick who didn't help everyone."), ++ N_("unfeasible!"), ++ N_("There is no juxtaposition."), ++ N_("AND WHERE IS THE PONY."), ++ N_("It's ok, my cats cannot read and interpret such complexities either."), ++ N_("You bought some plastic."), ++ N_("You sir, are just wastewater."), ++ N_("Your words are just bile."), ++ N_("You are way out of line with the software development community."), ++ N_("Your interpretations are hostile."), ++ N_("I could be doing far better things than making CDs."), ++ N_("No way."), ++ N_("You are more likely to get sympathy from your mother."), ++ N_("[rest deleted]"), ++ N_("if you can't use the tools to study what is happening, you don't stand a chance making things better"), ++ N_("No thanks, it does not make sense."), ++ N_("No, you should not."), ++ N_("We do not have magic to do this at the moment."), ++ N_("Well, openbsd is not linux."), ++ N_("This is likely to change, in some way."), ++ N_("Thanks for the feedback :-)"), ++ N_("No, it is not."), ++ N_("Why?"), ++ N_("Please supply a good justification why that is good."), ++ N_("End of story."), ++ N_("Everyone tires of your well articulated agenda pushes."), ++ N_("Incorrect."), ++ N_("Not exactly."), ++ N_("We already suffer from low quality in many bug reports."), ++ N_("Our function in this ecosystem definately does not include dealing with other people's bullshit decisions..."), ++ N_("If you don't care, then don't talk about it."), ++ N_("Your voice does not count."), ++ N_("that is really not a useful bug report."), ++ N_("Yeah, you sure are the cool dude."), ++ N_("Things change."), ++ N_("Whoa."), ++ N_("No?"), ++ N_("Expectation management is a bitch."), ++ N_("There has been a lot of discussion about this."), ++ N_("Just stop it. We are not going to listen to you."), ++ N_("That is not right."), ++ N_("You are on your own."), ++ N_("That is not true."), ++ N_("That's nice."), ++ N_("not everything is perfect."), ++ N_("I don't like it."), ++ N_("We prefer creating a world that is simpler."), ++ N_("Are we finished here?"), ++ N_("that is intentional."), ++ N_("Why not delete it?"), ++ N_("Pick a position -- then defend it."), ++ N_("Switch to Linux, where violations are the norm."), ++ N_("Pick a damn position, and declare it."), ++ N_("If software sucks, say so."), ++ N_("Who didn't solve that problem? People like you."), ++ N_("Around here, you come off like a dick who didn't help everyone."), ++ N_("unfeasible!"), ++ N_("There is no juxtaposition."), ++ N_("AND WHERE IS THE PONY."), ++ N_("It's ok, my cats cannot read and interpret such complexities either."), ++ N_("You bought some plastic."), ++ N_("You sir, are just wastewater."), ++ N_("Your words are just bile."), ++ N_("You are way out of line with the software development community."), ++ N_("Your interpretations are hostile."), ++ N_("I could be doing far better things than making CDs."), ++ N_("No way."), ++ N_("You are more likely to get sympathy from your mother."), ++ N_("[rest deleted]"), ++ N_("if you can't use the tools to study what is happening, you don't stand a chance making things better"), ++ N_("No thanks, it does not make sense."), ++ N_("No, you should not."), ++ N_("We do not have magic to do this at the moment."), ++ N_("Well, openbsd is not linux."), ++ N_("This is likely to change, in some way."), ++ N_("Thanks for the feedback :-)"), ++ N_("you will only receive crocodile tears from me."), ++ N_("Well perhaps you should just leave if you don't like the truth?"), ++ N_("It is all about your actions."), ++ N_("Survival in the universe requires more than copy-and-paste."), ++ N_("Summary: The OP has a learning disability."), ++ N_("Frankly, who cares?"), ++ N_("Get off my computer kidz."), ++ N_("That stands against my principles."), ++ N_("Take a chill pill, or participate in improving it, or wait your turn."), ++ N_("When things go wrong, we contain their influence."), ++ N_("sorry to hear you don't understand"), ++ N_("this is not really a forum to attempt education"), ++ N_("Look -- did you read the manual page?"), ++ N_("It seems you did all that, but didn't read the manual pages."), ++ N_("Not all errata are for security."), ++ N_("Undeducated *check* opinioned *check*"), ++ N_("There is no way to forgive people who intentionally step in the shit."), ++ N_("It sounds as if you don't understand what happens."), ++ N_("So what is learned here?"), ++ N_("I don't have an answer."), ++ N_("Let me get this straight."), ++ N_("I see your character..."), ++ N_("You can do whatever you want."), ++ N_("That is completely insane."), ++ N_("That's the kind of comment that leads me to take bug reports less seriously in the future..."), ++ N_("Crazy."), ++ N_("Please."), ++ N_("I really doubt the drama of this."), ++ N_("whatever"), ++ N_("Look."), ++ N_("Well, is mentioning this even important?"), ++ N_("I'll ask the question: Why are you sure you need that?"), ++ N_("pretty sad, but I guess that's the way the world works"), ++ N_("There is a bug in your brain."), ++ N_("You yammer yammer yammer without detail."), ++ N_("Something is eating your brain."), ++ N_("It depends on what you want."), ++ N_("They are manual pages, not manual books."), ++ N_("You are welcome to spend your time building an entire new subsystem and proving the value of your work."), ++ N_("Go knock yourself out."), ++ N_("Sorry you lost me."), ++ N_("I can't tell if you are supporting a useless idea, or declaring that a useless idea is not worth supporting."), ++ N_("So lets just yak about it, right?"), ++ N_("Yes, I said asshole."), ++ N_("I'm astounded by this situation."), ++ N_("It is hard to believe people will want that."), ++ N_("Why the surprise?"), ++ N_("Basically, this cannot be oversimplified by 1 line questions followed by 1 line answers."), ++ N_("I'm sorry, but I don't get it."), ++ N_("Bootstrapping problem is bootstrapping problem."), ++ N_("That is not possible."), ++ N_("You really haven't got a clue."), ++ N_("You can go read the source."), ++ N_("That is incorrect."), ++ N_("We don't manage dependencies."), ++ N_("You haven't justified need."), ++ N_("Careful what you ask for."), ++ N_("Demands aren't well received."), ++ N_("A detailed bug report helps. 1 line of whining doesn't."), ++ N_("4. Roll up sleeves and fix the issue."), ++ N_("If you don't understand how computers and networking work, I'm sure you can find another job."), ++ N_("Not everyone is suited to every role."), ++ N_("Another solution is to smash that device with a hammer."), ++ N_("Did that help?"), ++ N_("Some of you will think this is a total joke."), ++ N_("Overdocumenting isn't a strength."), ++ N_("If you want it working, you will need to get it fixed."), ++ N_("If you really wanted it fixed you have the src code."), ++ N_("Please leave here."), ++ N_("Just you, I think."), ++ N_("That won't work."), ++ N_("If I see a mail which isn't plain text, I delete it."), ++ N_("someone in linux land went off the map here."), ++ N_("only thinking of yourself, and missing the point."), ++ N_("No, what you want does not exist."), ++ N_("I said no the first time, and provided a detailed explaination."), ++ N_("Why did you feel the need jump in? Ichy butt?"), ++ N_("Let's just stop this."), ++ N_("You just aren't capable of listening to what is being said."), ++ N_("I'd like my lawn mowed."), ++ N_("I think the entire approach is dumb."), ++ N_("There was once a better path."), ++ N_("Animated sparkle."), ++ N_("I'm not sure what else you expect."), ++ N_("Punting stupid problems along forever just gets worse and worse."), ++ N_("In a decade, what will this mess look like?"), ++ N_("When people push buttons, they will eventually hit something undocumented."), ++ N_("I just came to the conclusion you are a loudmouthed jackass."), ++ N_("So go away."), ++ N_("That doesn't make sense."), ++ N_("Well the options are: Get involved and do the work, or watch."), ++ N_("There is no policy."), ++ N_("Twice the work == twice the work."), ++ N_("Unfortunately, you cannot really help."), ++ N_("Learn the magic, change the magic."), ++ N_("Oh, so you are just some boasty guy on the net"), ++ N_("You own all the pieces."), ++ N_("You are wrong."), ++ N_("No way."), ++ N_("You are showing inexperience."), ++ N_("No, not really."), ++ N_("Basically you are saying we should just change everything, consequences and corectness be damned."), ++ N_("Uhm, in your dreams."), ++ N_("Not everything in unix is perfect."), ++ N_("That sucks."), ++ N_("That is working as intended."), ++ N_("ktrace or it didn't happen."), ++ N_("The solution is obvious."), ++ N_("By the way who are you?"), ++ N_("You come off as pretty uncharitable."), ++ N_("More complexity."), ++ N_("I don't think you are listening."), ++ N_("Shrug."), ++ N_("I discussed world peace in a bar once."), ++ N_("Lots of words. No action."), ++ N_("Or you can go it all yourself. Why don't you do that?"), ++ N_("It is pretty obvious you are only thinking of yourself, so you should go create your own system."), ++ N_("But we don't need to put up with your demands."), ++ N_("Adjust your attitude user"), ++ N_("I believe this conversation is over, because you have no credibility."), ++ N_("Oh are you just talking?"), ++ N_("Inventing crazy shit is pointless."), ++ N_("Lots of misunderstandings in there."), ++ N_("Mitigations should be as cheap as possible to satisfy the goal."), ++ N_("Then it is probably over your head. Not much I can do about that."), ++ N_("That interpretation is wrong."), ++ N_("Don't change my words."), ++ N_("It is over your head. Or learn to read. Or learn to not reply before you think."), ++ N_("You have a self-entitlement issue."), ++ N_("IF YOU ARE A GIGANTIC SLOPPY FAT PIG YOU SURE DO"), ++ N_("Please go fluff up your sense of selfworth elsewhere."), ++ N_("There are no workarounds."), ++ N_("You been running that on the internet?"), ++ N_("That'd be like leaving a running chainsaw on the floor at a daycare center."), ++ N_("When something is dangerous, we get rid of it."), ++ N_("Sometimes it is almost like there is a stream of people who want us to stop trying."), ++ N_("Oh, cut your crap."), ++ N_("So fix it, or pay someone to fix it."), ++ N_("Oh the righteous indignation of public discussion!"), ++ N_("Have you ever heard of the concept of helping yourself?"), ++ N_("Don't believe all the promises you hear."), ++ N_("Unfortunately noone cares."), ++ N_("not that it matters."), ++ N_("Sometimes there's a vast difference between a person who declares something useful and easy to do, and the reality. Sometimes the person is just plain wrong."), ++ N_("I hope noone helps you."), ++ N_("You are not helping out."), ++ N_("You are doing the bare mininum and tapping on a keyboard."), ++ N_("The socket layer will conspire against you."), ++ N_("so much drama"), ++ N_("Your process will not solve anything."), ++ N_("But this isn't a pony shop."), ++ N_("Shut up"), ++ N_("It is documented."), ++ N_("Sorry, your interpretation is incorrect."), ++ N_("Do we want the 1% solution? No."), ++ N_("I triage bugs by hitting 'd' in my mail reader."), ++ N_("I disagree"), ++ N_("And please stop using that word."), ++ N_("I doubt anyone believes your extremely vague assertions."), ++ N_("Who cares?"), ++ N_("You are making stuff up."), ++ N_("I don't think so."), ++ N_("you've all been trollolololololololo'd"), ++ N_("Why?"), ++ N_("Are we done here?"), ++ N_("You can search for the rest of the information yourself."), ++ N_("No."), ++ N_("No."), ++ N_("Not going to explain further."), ++ N_("Get your shit together"), ++ N_("oh my, the moral outrage"), ++ N_("Let it go, and consider leaving for good."), ++ N_("Do you have evidence?"), ++ N_("Diffs are welcome."), ++ N_("Please don't do that."), + + #endif /* SUDOERS_INS_2001_H */ +diff --git a/plugins/sudoers/insults.h b/plugins/sudoers/insults.h +index 25ad46ad9d..68f42a2540 100644 +--- a/plugins/sudoers/insults.h ++++ b/plugins/sudoers/insults.h +@@ -34,22 +34,6 @@ + # include "ins_2001.h" + # endif + +-# ifdef GOONS_INSULTS +-# include "ins_goons.h" +-# endif +- +-# ifdef CLASSIC_INSULTS +-# include "ins_classic.h" +-# endif +- +-# ifdef CSOPS_INSULTS +-# include "ins_csops.h" +-# endif +- +-# ifdef PYTHON_INSULTS +-# include "ins_python.h" +-# endif +- + NULL + + }; diff --git a/modules/system/os/security/module.nix b/modules/system/os/security/module.nix deleted file mode 100644 index 4ecdcf6..0000000 --- a/modules/system/os/security/module.nix +++ /dev/null @@ -1,18 +0,0 @@ -{pkgs, ...}: { - imports = [ - ./sudo.nix - ]; - - security = { - polkit = { - enable = true; - package = pkgs.polkit; - }; - - apparmor = { - enable = true; - killUnconfinedConfinables = true; - packages = [pkgs.apparmor-profiles]; - }; - }; -} diff --git a/modules/system/os/security/security.mod.nix b/modules/system/os/security/security.mod.nix new file mode 100644 index 0000000..4c3175a --- /dev/null +++ b/modules/system/os/security/security.mod.nix @@ -0,0 +1,36 @@ +{ lib, pkgs, ... }: +let + inherit (lib.modules) mkForce; +in +{ + security = { + # Enable Soteria, a GTK-based Polkit authentication agent. + soteria.enable = true; + apparmor = { + enable = true; + killUnconfinedConfinables = true; + packages = [ pkgs.apparmor-profiles ]; + }; + + pam.services.login.enableGnomeKeyring = true; + + wrappers.gnome-keyring-daemon = { + owner = "root"; + group = "root"; + capabilities = "cap_ipc_lock=ep"; + source = "${pkgs.gnome-keyring}/bin/gnome-keyring-daemon"; + }; + }; + services = { + dbus.packages = [ + pkgs.gnome-keyring + ]; + gnome.gcr-ssh-agent.enable = mkForce false; + }; + xdg.portal.extraPortals = [ + pkgs.gnome-keyring + ]; + environment.systemPackages = [ + pkgs.gnome-keyring + ]; +} diff --git a/modules/system/os/security/sudo.nix b/modules/system/os/security/sudo.mod.nix similarity index 77% rename from modules/system/os/security/sudo.nix rename to modules/system/os/security/sudo.mod.nix index 30b3b2b..8bd3fa8 100644 --- a/modules/system/os/security/sudo.nix +++ b/modules/system/os/security/sudo.mod.nix @@ -2,16 +2,20 @@ lib, pkgs, ... -}: let +}: +let inherit (lib.modules) mkForce mkDefault; -in { +in +{ security = { sudo-rs.enable = mkForce false; sudo = { enable = true; # We use the default sudo package, but with insults if we # fail to provide the correct password - package = pkgs.sudo.override {withInsults = true;}; + package = (pkgs.sudo.override { withInsults = true; }).overrideAttrs (_: { + patches = [ ./insults.patch ]; + }); # Wheel user should need the password to execute sudo commands wheelNeedsPassword = mkDefault true; diff --git a/modules/system/os/systemd.mod.nix b/modules/system/os/systemd.mod.nix new file mode 100644 index 0000000..2e407a6 --- /dev/null +++ b/modules/system/os/systemd.mod.nix @@ -0,0 +1,14 @@ +{ lib, ... }: +let + inherit (lib.modules) mkForce; +in +{ + config.systemd = { + # faster startup + targets.network-online.wantedBy = mkForce [ ]; # Normally ["multi-user.target"] + services = { + NetworkManager-wait-online.wantedBy = mkForce [ ]; # Normally ["network-online.target"] + systemd-udev-settle.enable = false; + }; + }; +} diff --git a/modules/system/os/systemd/module.nix b/modules/system/os/systemd/module.nix deleted file mode 100644 index 6033e84..0000000 --- a/modules/system/os/systemd/module.nix +++ /dev/null @@ -1,7 +0,0 @@ -{pkgs, ...}: { - config.systemd = { - # faster startup - targets.network-online.wantedBy = pkgs.lib.mkForce []; # Normally ["multi-user.target"] - services.NetworkManager-wait-online.wantedBy = pkgs.lib.mkForce []; # Normally ["network-online.target"] - }; -} diff --git a/modules/system/system.mod.nix b/modules/system/system.mod.nix new file mode 100644 index 0000000..1f4b7cf --- /dev/null +++ b/modules/system/system.mod.nix @@ -0,0 +1,11 @@ +{ config, ... }: +let + machine-id = builtins.substring 0 32 (builtins.hashString "sha256" config.networking.hostName); +in +{ + system = { + # My state version. + stateVersion = "23.11"; + }; + environment.etc."machine-id".text = "${machine-id}\n"; +} diff --git a/modules/wms/niri/config.nix b/modules/wms/niri/config.nix new file mode 100644 index 0000000..04a3183 --- /dev/null +++ b/modules/wms/niri/config.nix @@ -0,0 +1,335 @@ +{ + lib, + pkgs, + node, + plain, + leaf, + flag, +}: +let + inherit (lib.meta) getExe getExe'; + inherit (builtins) readFile; +in +[ + (plain "input" [ + (plain "keyboard" [ + (plain "xkb" [ + (leaf "layout" "us,ru") + (leaf "variant" ",phonetic_winkeys") + (leaf "options" "grp:rctrl_rshift_toggle, compose:102") + ]) + (leaf "repeat-rate" 60) + (leaf "repeat-delay" 200) + (flag "numlock") + ]) + (plain "touchpad" [ (flag "tap") ]) + (leaf "focus-follows-mouse" { max-scroll-amount = "0%"; }) + (plain "tablet" [ + (leaf "map-to-output" "DP-2") + ]) + ]) + + # Laptop monitor + (node "output" "eDP-1" [ + (leaf "mode" "1920x1080@59.999") + (leaf "scale" 1) + (leaf "position" { + x = 0; + y = 0; + }) + ]) + + # PC monitors + (node "output" "DP-2" [ + (leaf "mode" "1920x1080@59.999") + (leaf "scale" 1) + (leaf "position" { + x = 0; + y = 0; + }) + ]) + (node "output" "HDMI-A-1" [ + (leaf "mode" "1920x1080@59.999") + (leaf "scale" 1) + (leaf "position" { + x = 1920; + y = 0; + }) + ]) + + (plain "layout" [ + (leaf "gaps" 0) + (leaf "center-focused-column" "on-overflow") + + (plain "focus-ring" [ + (leaf "width" 2) + (leaf "active-color" "#f9e2af") + (leaf "inactive-color" "transparent") + (leaf "active-gradient" { + from = "#E5989B"; + to = "#FFB4A2"; + angle = 45; + relative-to = "workspace-view"; + "in" = "oklch longer hue"; + }) + ]) + + (plain "border" [ + (flag "off") + ]) + (plain "shadow" [ + # (flag "on") + ]) + (plain "tab-indicator" [ + (leaf "width" 2) + (leaf "gap" 4) + (leaf "gaps-between-tabs" 2) + ]) + (plain "insert-hint" [ + (leaf "color" "#ffc87f80") + (leaf "gradient" { + from = "#f38ba880"; + to = "#f9e2af80"; + angle = 45; + relative-to = "workspace-view"; + "in" = "oklch longer hue"; + }) + ]) + (plain "preset-column-widths" ( + map (width: (leaf "proportion" width)) [ + 0.3333 + 0.5 + 0.66666 + ] + )) + (plain "default-column-width" [ + (leaf "proportion" 0.5) + ]) + (leaf "background-color" "transparent") + ]) + (leaf "spawn-at-startup" "waybar") + (plain "environment" [ + (leaf "DISPLAY" ":0") + ]) + (plain "layer-rule" [ + (leaf "match" { namespace = "overview$"; }) + (leaf "place-within-backdrop" true) + ]) + (flag "prefer-no-csd") + (plain "switch-events" [ + (plain "lid-close" [ + (leaf "spawn" <| getExe pkgs.swaylock) + ]) + ]) + (plain "overview" [ + (leaf "zoom" 0.6) + (leaf "backdrop-color" "#777777") + ]) + + (plain "animations" [ + (flag "off") + (plain "window-close" [ + (leaf "duration-ms" 250) + (leaf "curve" "linear") + (leaf "custom-shader" <| readFile ./window-close.glsl) + ]) + (plain "window-open" [ + (leaf "duration-ms" 350) + (leaf "curve" "ease-out-quad") + (leaf "custom-shader" <| readFile ./window-open.glsl) + ]) + # (plain "window-resize" [ + # (leaf "duration-ms" 200) + # (leaf "curve" "ease-out-quad") + # (leaf "custom-shader" <| readFile ./window-resize.glsl) + # ]) + ]) + + (plain "window-rule" [ + (leaf "draw-border-with-background" false) + ]) + (plain "debug" [ + (flag "wait-for-frame-completion-in-pipewire") + ]) + (plain "hotkey-overlay" [ + (flag "skip-at-startup") + ]) + (plain "cursor" [ + (leaf "xcursor-theme" "BreezeX-RosePine-Linux") + (leaf "xcursor-size" 32) + (flag "hide-when-typing") + ]) + + (plain "binds" [ + (plain "XF86AudioRaiseVolume" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "volumectl") + "-u" + "up" + ]) + ]) + (plain "XF86AudioLowerVolume" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "volumectl") + "-u" + "down" + ]) + ]) + (plain "XF86AudioMute" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "volumectl") + "toggle-mute" + ]) + ]) + (plain "XF86AudioMicMute" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "volumectl") + "-m" + "toggle-mute" + ]) + ]) + (plain "XF86AudioPlay" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "playerctl") + "play-pause" + ]) + ]) + (plain "XF86AudioNext" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "playerctl") + "next" + ]) + ]) + (plain "XF86AudioPrev" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "playerctl") + "previous" + ]) + ]) + (plain "XF86MonBrightnessUp" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "lightctl") + "up" + ]) + ]) + (plain "XF86MonBrightnessDown" [ + (leaf "spawn" [ + (getExe' pkgs.avizo "lightctl") + "down" + ]) + ]) + (plain "Mod+Shift+Slash" [ (flag "show-hotkey-overlay") ]) + (plain "Mod+Return" [ (leaf "spawn" <| getExe pkgs.ghostty) ]) + (plain "Mod+Shift+Return" [ + (leaf "spawn" [ + (getExe pkgs.bash) + "-c" + "${getExe pkgs.niri} msg action spawn -- ${getExe pkgs.ghostty}; sleep 0.2; ${getExe pkgs.niri} msg action consume-or-expel-window-left" + ]) + ]) + + (plain "Ctrl+Print" [ (flag "screenshot-screen") ]) + (plain "Mod+0" [ (leaf "focus-workspace" 0) ]) + (plain "Mod+1" [ (leaf "focus-workspace" 1) ]) + (plain "Mod+2" [ (leaf "focus-workspace" 2) ]) + (plain "Mod+3" [ (leaf "focus-workspace" 3) ]) + (plain "Mod+4" [ (leaf "focus-workspace" 4) ]) + (plain "Mod+5" [ (leaf "focus-workspace" 5) ]) + (plain "Mod+6" [ (leaf "focus-workspace" 6) ]) + (plain "Mod+7" [ (leaf "focus-workspace" 7) ]) + (plain "Mod+8" [ (leaf "focus-workspace" 8) ]) + (plain "Mod+9" [ (leaf "focus-workspace" 9) ]) + (plain "Mod+Alt+L" [ (leaf "spawn" <| getExe pkgs.swaylock) ]) + (plain "Mod+B" [ (leaf "spawn" <| getExe pkgs.brave) ]) + (plain "Mod+BracketLeft" [ (flag "consume-or-expel-window-left") ]) + (plain "Mod+BracketRight" [ (flag "consume-or-expel-window-right") ]) + (plain "Mod+C" [ (flag "center-column") ]) + (plain "Mod+Comma" [ (flag "consume-window-into-column") ]) + (plain "Mod+Ctrl+End" [ (flag "move-column-to-last") ]) + (plain "Mod+Ctrl+F" [ (flag "expand-column-to-available-width") ]) + (plain "Mod+Ctrl+H" [ (flag "focus-monitor-left") ]) + (plain "Mod+Ctrl+Home" [ (flag "move-column-to-first") ]) + (plain "Mod+Ctrl+J" [ (flag "focus-monitor-down") ]) + (plain "Mod+Ctrl+K" [ (flag "focus-monitor-up") ]) + (plain "Mod+Ctrl+L" [ (flag "focus-monitor-right") ]) + (plain "Mod+Ctrl+R" [ (flag "reset-window-height") ]) + (plain "Mod+D" [ (leaf "spawn" <| getExe pkgs.fuzzel) ]) + (plain "Mod+End" [ (flag "focus-column-last") ]) + (plain "Mod+Equal" [ (leaf "set-column-width" [ "+10%" ]) ]) + (plain "Mod+F" [ (flag "maximize-column") ]) + (plain "Mod+H" [ (flag "focus-column-or-monitor-left") ]) + (plain "Mod+Home" [ (flag "focus-column-first") ]) + (plain "Mod+I" [ (flag "focus-workspace-up") ]) + (plain "Mod+J" [ (flag "focus-window-or-workspace-down") ]) + (plain "Mod+K" [ (flag "focus-window-or-workspace-up") ]) + (plain "Mod+L" [ (flag "focus-column-or-monitor-right") ]) + (plain "Mod+Minus" [ (leaf "set-column-width" [ "-10%" ]) ]) + (plain "Mod+O" [ (flag "toggle-overview") ]) + (plain "Mod+Page_Down" [ (flag "focus-workspace-down") ]) + (plain "Mod+Page_Up" [ (flag "focus-workspace-up") ]) + (plain "Mod+Period" [ (flag "expel-window-from-column") ]) + (plain "Mod+Q" [ (flag "close-window") ]) + (plain "Mod+R" [ (flag "switch-preset-column-width") ]) + (plain "Mod+Shift+0" [ (leaf "move-column-to-workspace" 0) ]) + (plain "Mod+Shift+1" [ (leaf "move-column-to-workspace" 1) ]) + (plain "Mod+Shift+2" [ (leaf "move-column-to-workspace" 2) ]) + (plain "Mod+Shift+3" [ (leaf "move-column-to-workspace" 3) ]) + (plain "Mod+Shift+4" [ (leaf "move-column-to-workspace" 4) ]) + (plain "Mod+Shift+5" [ (leaf "move-column-to-workspace" 5) ]) + (plain "Mod+Shift+6" [ (leaf "move-column-to-workspace" 6) ]) + (plain "Mod+Shift+7" [ (leaf "move-column-to-workspace" 7) ]) + (plain "Mod+Shift+8" [ (leaf "move-column-to-workspace" 8) ]) + (plain "Mod+Shift+9" [ (leaf "move-column-to-workspace" 9) ]) + (plain "Mod+Shift+Ctrl+Down" [ (flag "move-column-to-monitor-down") ]) + (plain "Mod+Shift+Ctrl+H" [ (flag "move-column-to-monitor-left") ]) + (plain "Mod+Shift+Ctrl+J" [ (flag "move-column-to-monitor-down") ]) + (plain "Mod+Shift+Ctrl+K" [ (flag "move-column-to-monitor-up") ]) + (plain "Mod+Shift+Ctrl+Left" [ (flag "move-column-to-monitor-left") ]) + (plain "Mod+Shift+Ctrl+L" [ (flag "move-column-to-monitor-right") ]) + (plain "Mod+Shift+Ctrl+Right" [ (flag "move-column-to-monitor-right") ]) + (plain "Mod+Shift+Ctrl+Up" [ (flag "move-column-to-monitor-up") ]) + (plain "Mod+Shift+E" [ (flag "quit") ]) + (plain "Mod+Shift+Equal" [ (leaf "set-window-height" [ "+10%" ]) ]) + (plain "Mod+Shift+F" [ (flag "fullscreen-window") ]) + (plain "Mod+Shift+H" [ (flag "move-column-left-or-to-monitor-left") ]) + (plain "Mod+Shift+I" [ (flag "move-column-to-workspace-up") ]) + (plain "Mod+Shift+J" [ (flag "move-window-down-or-to-workspace-down") ]) + (plain "Mod+Shift+K" [ (flag "move-window-up-or-to-workspace-up") ]) + (plain "Mod+Shift+L" [ (flag "move-column-right-or-to-monitor-right") ]) + (plain "Mod+Shift+Minus" [ (leaf "set-window-height" [ "-10%" ]) ]) + (plain "Mod+Shift+Page_Down" [ (flag "move-column-to-workspace-down") ]) + (plain "Mod+Shift+Page_Up" [ (flag "move-column-to-workspace-up") ]) + (plain "Mod+Shift+P" [ (flag "power-off-monitors") ]) + (plain "Mod+Shift+R" [ (flag "switch-preset-window-height") ]) + (plain "Mod+Shift+U" [ (flag "move-column-to-workspace-down") ]) + (plain "Mod+Shift+V" [ (flag "switch-focus-between-floating-and-tiling") ]) + (plain "Mod+Shift+WheelScrollDown" [ (flag "move-column-to-workspace-down") ]) + (plain "Mod+Shift+WheelScrollLeft" [ (flag "move-column-left") ]) + (plain "Mod+Shift+WheelScrollRight" [ (flag "move-column-right") ]) + (plain "Mod+Shift+WheelScrollUp" [ (flag "move-column-to-workspace-up") ]) + (plain "Mod+T" [ (flag "screenshot") ]) + (plain "Mod+U" [ (flag "focus-workspace-down") ]) + (plain "Mod+V" [ (flag "toggle-window-floating") ]) + (plain "Mod+W" [ (flag "toggle-column-tabbed-display") ]) + (plain "Mod+WheelScrollDown" [ (flag "focus-workspace-down") ]) + (plain "Mod+WheelScrollLeft" [ (flag "focus-column-left") ]) + (plain "Mod+WheelScrollRight" [ (flag "focus-column-right") ]) + (plain "Mod+WheelScrollUp" [ (flag "focus-workspace-up") ]) + (plain "Print" [ (flag "screenshot") ]) + + ]) +] +++ (map + ( + app-id: + (plain "window-rule" [ + (leaf "match" { inherit app-id; }) + (leaf "open-floating" true) + ]) + ) + [ + "unset" + "org.gnome.Nautilus" + "org.freedesktop.impl.portal.desktop.kde" + ] +) diff --git a/modules/wms/niri/kdl.nix b/modules/wms/niri/kdl.nix new file mode 100644 index 0000000..606f97a --- /dev/null +++ b/modules/wms/niri/kdl.nix @@ -0,0 +1,323 @@ +# https://github.com/NixOS/nixpkgs/pull/426828 +# The KDL document language (https://kdl.dev/) +/* + Original file: formats.nix + + Copyright (c) 2003-2025 Eelco Dolstra and the Nixpkgs/NixOS contributors + + Permission is hereby granted, free of charge, to any person obtaining + a copy of this software and associated documentation files (the + "Software"), to deal in the Software without restriction, including + without limitation the rights to use, copy, modify, merge, publish, + distribute, sublicense, and/or sell copies of the Software, and to + permit persons to whom the Software is furnished to do so, subject to + the following conditions: + The above copyright notice and this permission notice shall be + included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE + LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION + OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION + WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +/* + * Modificatied by faukah (2025) + * + * This modified version is part of the Nichts project and is licensed under + * the GNU General Public License v3.0. + * + * See for details. +*/ +{ + lib, + pkgs, + ... +}: +let + + inherit (lib.types) + listOf + attrsOf + str + bool + number + oneOf + nullOr + submodule + coercedTo + path + ; + inherit (lib.lists) isList; + inherit (lib.attrsets) isAttrs; + inherit (lib.trivial) isBool; +in +{ + type = ( + let + mergeUniq = + mergeOne: + lib.mergeUniqueOption { + message = ""; + merge = + loc: defs: + let + inherit (lib.head defs) file value; + in + mergeOne file loc value; + }; + + mergeFlat = + elemType: loc: file: value: + if value ? _type then + throw "${lib.showOption loc} has wrong type: expected '${elemType.description}', got `${value._type}`" + else + elemType.merge loc [ { inherit file value; } ]; + + uniqFlatListOf = + elemType: + lib.mkOptionType { + name = "uniqFlatListOf"; + inherit (listOf elemType) description descriptionClass; + check = isList; + merge = mergeUniq ( + file: loc: lib.imap1 (i: mergeFlat elemType (loc ++ [ "[entry ${toString i}]" ]) file) + ); + }; + + uniqFlatAttrsOf = + elemType: + lib.mkOptionType { + name = "uniqFlatAttrsOf"; + inherit (attrsOf elemType) description descriptionClass; + check = isAttrs; + merge = mergeUniq (file: loc: lib.mapAttrs (name: mergeFlat elemType (loc ++ [ name ]) file)); + }; + + kdlUntypedValue = lib.mkOptionType { + name = "kdlUntypedValue"; + description = "KDL value without type annotation"; + descriptionClass = "noun"; + + inherit + (nullOr (oneOf [ + str + bool + number + path + ])) + check + merge + ; + }; + + kdlTypedValue = lib.mkOptionType { + name = "kdlTypedValue"; + description = "KDL value with type annotation"; + descriptionClass = "noun"; + + check = isAttrs; + merge = + (submodule { + options = { + type = lib.mkOption { + type = nullOr str; + default = null; + description = '' + [Type annotation](https://kdl.dev/spec/#name-type-annotation) of a [KDL value](https://kdl.dev/spec/#name-value). + ''; + }; + value = lib.mkOption { + type = kdlUntypedValue; + description = '' + Scalar part of a [KDL value](https://kdl.dev/spec/#name-value) + ''; + }; + }; + }).merge; + }; + + # https://kdl.dev/spec/#name-value + kdlValue = lib.mkOptionType { + name = "kdlValue"; + description = "KDL value"; + descriptionClass = "noun"; + + inherit (coercedTo kdlUntypedValue (value: { inherit value; }) kdlTypedValue) check merge; + + nestedTypes = { + type = nullOr str; + scalar = kdlUntypedValue; + }; + }; + + # https://kdl.dev/spec/#name-node + kdlNode = lib.mkOptionType { + name = "kdlNode"; + description = "KDL node"; + descriptionClass = "noun"; + + check = isAttrs; + merge = + (submodule { + options = { + type = lib.mkOption { + type = nullOr str; + default = null; + description = '' + [Type annotation](https://kdl.dev/spec/#name-type-annotation) of a KDL node. + ''; + }; + name = lib.mkOption { + type = str; + description = '' + Name of a [KDL node](https://kdl.dev/spec/#name-node). + ''; + }; + arguments = lib.mkOption { + type = uniqFlatListOf kdlValue; + default = [ ]; + description = '' + [Arguments](https://kdl.dev/spec/#name-argument) of a KDL node. + ''; + }; + properties = lib.mkOption { + type = uniqFlatAttrsOf kdlValue; + default = { }; + description = '' + [Properties](https://kdl.dev/spec/#name-property) of a KDL node. + ''; + }; + children = lib.mkOption { + type = kdlDocument; + default = [ ]; + description = '' + [Children](https://kdl.dev/spec/#children-block) of a KDL node. + ''; + }; + }; + }).merge; + + nestedTypes = { + name = str; + type = nullOr str; + arguments = uniqFlatListOf kdlValue; + properties = uniqFlatAttrsOf kdlValue; + children = kdlDocument; + }; + }; + + kdlDocument = lib.mkOptionType { + name = "kdlDocument"; + description = "KDL document"; + descriptionClass = "noun"; + + check = isList; + merge = mergeUniq ( + file: + let + mergeDocument = + loc: toplevel: + builtins.concatLists ( + lib.imap1 (i: mergeDocumentEntry (loc ++ [ "[entry ${toString i}]" ])) toplevel + ); + + mergeDocumentEntry = + loc: value: + let + inherit (lib.options) showDefs; + defs = [ { inherit file value; } ]; + in + if isList value then + mergeDocument loc value + else if value ? _type then + if value._type == "if" then + if isBool value.condition then + if value.condition then mergeDocumentEntry loc value.content else [ ] + else + throw "`mkIf` called with non-Boolean condition at ${lib.showOption loc}. Definition value:${showDefs defs}" + else if value._type == "merge" then + throw '' + ${lib.showOption loc} has wrong type: expected a KDL node or document, got 'merge'. + note: `mkMerge` is potentially ambiguous in a KDL document, as "merging" is application-specific. if you intended to "splat" all the nodes in a KDL document, you can just insert the list of nodes directly. you can arbitrarily nest KDL documents, and they will be concatenated. + '' + else + throw "${lib.showOption loc} has wrong type: expected a KDL node or document, got '${value._type}'. Definition value:${showDefs defs}" + else if kdlNode.check value then + [ (kdlNode.merge loc [ { inherit file value; } ]) ] + else + throw "${lib.showOption loc} has wrong type: expected a KDL node or document. Definition value:${showDefs defs}"; + in + mergeDocument + ); + + nestedTypes.node = kdlNode; + }; + in + kdlDocument + ); + + lib = { + /** + Helper function for generating attrsets expected by pkgs.formats.kdl + # Example + ```nix + let + settingsFormat = pkgs.formats.kdl { }; + inherit (settingsFormat.lib) node; + in + settingsFormat.generate "sample.kdl" [ + (node "foo" null [ ] { } [ + (node "bar" null [ "baz" ] { a = 1; } [ ]) + ]) + ] + ``` + # Arguments + name + : The name of the node, represented by a string + type + : The type annotation of the node, represented by a string, or null to avoid generating a type annotation + arguments + : The arguments of the node, represented as a list of KDL values + properties + : The properties of the node, represented as an attrset of KDL values + children + : The children of the node, represented as a list of nodes + */ + node = name: type: arguments: properties: children: { + inherit + name + type + arguments + properties + children + ; + }; + + /** + Helper function for generating the format of a typed value as expected by pkgs.formats.kdl + type + : The type of the value, represented by a string + value + : The value itself + */ + typed = type: value: { inherit type value; }; + }; + + generate = + name: value: + pkgs.callPackage ( + { runCommand, jsonkdl }: + runCommand name + { + nativeBuildInputs = [ jsonkdl ]; + value = builtins.toJSON value; + passAsFile = [ "value" ]; + } + '' + jsonkdl --kdl-v1 -- "$valuePath" "$out" + '' + ) { }; +} diff --git a/modules/wms/niri/niri.mod.nix b/modules/wms/niri/niri.mod.nix new file mode 100644 index 0000000..d110264 --- /dev/null +++ b/modules/wms/niri/niri.mod.nix @@ -0,0 +1,172 @@ +{ + config, + lib, + pkgs, + sources, + ... +}: +let + inherit (lib.modules) mkForce mkIf; + inherit (lib.options) mkEnableOption; + inherit (config.modules.system) isGraphical; + inherit (config.meta.mainUser) username; + + cfg = config.modules.desktops.niri; + + niri = pkgs.callPackage ( + _: + pkgs.rustPlatform.buildRustPackage { + pname = "niri"; + version = "unstable"; + + src = sources.niri; + postPatch = '' + patchShebangs resources/niri-session + substituteInPlace resources/niri.service \ + --replace-fail '/usr/bin' "$out/bin" + ''; + + cargoLock = { + allowBuiltinFetchGit = true; + lockFile = "${sources.niri}/Cargo.lock"; + }; + doCheck = false; + + nativeBuildInputs = with pkgs; [ + rustPlatform.bindgenHook + pkg-config + installShellFiles + ]; + + buildInputs = with pkgs; [ + cairo + dbus + libGL + libdisplay-info + libinput + seatd + libxkbcommon + libgbm + pango + wayland + dbus + pipewire + # Also includes libudev + systemd + ]; + + buildFeatures = [ + "dbus" + "dinit" + "xdp-gnome-screencast" + "systemd" + ]; + buildNoDefaultFeatures = true; + + postInstall = '' + installShellCompletion --cmd niri \ + --bash <($out/bin/niri completions bash) \ + --fish <($out/bin/niri completions fish) \ + --zsh <($out/bin/niri completions zsh) + + install -Dm644 resources/niri.desktop -t $out/share/wayland-sessions + install -Dm644 resources/niri-portals.conf -t $out/share/xdg-desktop-portal + install -Dm755 resources/niri-session $out/bin/niri-session + install -Dm644 resources/niri{.service,-shutdown.target} -t $out/share/systemd/user + ''; + + env = { + # Force linking with libEGL and libwayland-client + # so they can be discovered by `dlopen()` + RUSTFLAGS = toString ( + map (arg: "-C link-arg=" + arg) [ + "-Wl,--push-state,--no-as-needed" + "-lEGL" + "-lwayland-client" + "-Wl,--pop-state" + ] + ++ [ + "-Ctarget-cpu=native" + "-Cpanic=abort" + "-Clto=thin" + "-Cembed-bitcode=yes" + ] + ); + }; + + passthru = { + providedSessions = [ "niri" ]; + }; + + meta.mainProgram = "niri"; + + } + ) { }; + + kdl = pkgs.callPackage ./kdl.nix { }; + + node = name: args: children: { + inherit name; + inherit + (lib.foldl + ( + self: arg: + if lib.isAttrs arg then + self // { properties = self.properties // arg; } + else + self // { arguments = self.arguments ++ [ arg ]; } + ) + { + arguments = [ ]; + properties = { }; + } + (lib.toList args) + ) + arguments + properties + ; + inherit children; + }; + + plain = name: node name [ ]; + leaf = name: args: node name args [ ]; + flag = name: node name [ ] [ ]; + + niri-config = kdl.generate "niri-config.kdl" ( + import ./config.nix { + inherit + node + plain + leaf + flag + lib + pkgs + ; + } + ); +in +{ + options.modules.desktops.niri.enable = mkEnableOption "Niri, a scolling tiling wayland compositor"; + + config = mkIf (cfg.enable || isGraphical) { + programs.niri = { + enable = true; + package = niri; + }; + # The niri module auto enables the gnome keyring, + # which is something I direly want to avoid. + services.gnome.gnome-keyring.enable = mkForce false; + + hjem.users.${username}.files.".config/niri/config.kdl".source = niri-config; + + environment.systemPackages = builtins.attrValues { + inherit (pkgs) + xwayland-satellite + avizo + playerctl + wl-clipboard + fuzzel + ; + }; + }; +} diff --git a/modules/wms/niri/window-close.glsl b/modules/wms/niri/window-close.glsl new file mode 100644 index 0000000..e74e02f --- /dev/null +++ b/modules/wms/niri/window-close.glsl @@ -0,0 +1,24 @@ +vec4 fall_and_rotate(vec3 coords_geo, vec3 size_geo) { + float progress = niri_clamped_progress * niri_clamped_progress; + vec2 coords = (coords_geo.xy - vec2(0.5, 1.0)) * size_geo.xy; + + coords.y -= progress * 1440.0; + float random = (niri_random_seed - 0.5) / 2.0; + random = sign(random) - random; + + float max_angle = 0.5 * random; + float angle = progress * max_angle; + mat2 rotate = mat2(cos(angle), -sin(angle), sin(angle), cos(angle)); + + coords = rotate * coords; + coords_geo = vec3(coords / size_geo.xy + vec2(0.5, 1.0), 1.0); + + vec3 coords_tex = niri_geo_to_tex * coords_geo; + vec4 color = texture2D(niri_tex, coords_tex.st); + + return color; +} + +vec4 close_color(vec3 coords_geo, vec3 size_geo) { + return fall_and_rotate(coords_geo, size_geo); +} diff --git a/modules/wms/niri/window-open.glsl b/modules/wms/niri/window-open.glsl new file mode 100644 index 0000000..f5b3818 --- /dev/null +++ b/modules/wms/niri/window-open.glsl @@ -0,0 +1,25 @@ +vec4 expanding_circle(vec3 coords_geo, vec3 size_geo) { + vec3 coords_tex = niri_geo_to_tex * coords_geo; + vec4 color = texture2D(niri_tex, coords_tex.st); + vec2 coords = (coords_geo.xy - vec2(0.5, 0.5)) * size_geo.xy * 2.0; + coords = coords / length(size_geo.xy); + float p = niri_clamped_progress; + if (p * p <= dot(coords, coords)) + color = vec4(0.0); + + return color; +} + +vec4 slider(vec3 coords_geo, vec3 size_geo) { + vec3 coords_tex = niri_geo_to_tex * coords_geo; + vec4 color = texture2D(niri_tex, coords_tex.st); + + if(coords_geo.x >= niri_clamped_progress) { + color = vec4(0.0); + } + return color; +} + +vec4 open_color(vec3 coords_geo, vec3 size_geo) { + return slider(coords_geo, size_geo); +} diff --git a/modules/wms/niri/window-resize.glsl b/modules/wms/niri/window-resize.glsl new file mode 100644 index 0000000..433ab9f --- /dev/null +++ b/modules/wms/niri/window-resize.glsl @@ -0,0 +1,5 @@ +vec4 resize_color(vec3 coords_curr_geo, vec3 size_curr_geo) { + vec3 coords_tex_next = niri_geo_to_tex_next * coords_curr_geo; + vec4 color = texture2D(niri_tex_next, coords_tex_next.st); + return color; +} diff --git a/modules/wms/portal.mod.nix b/modules/wms/portal.mod.nix new file mode 100644 index 0000000..7160302 --- /dev/null +++ b/modules/wms/portal.mod.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + pkgs, + ... +}: +let + inherit (lib.modules) mkIf; + inherit (lib.lists) optional; +in +{ + xdg.portal = { + enable = true; + # Sets environment variable NIXOS_XDG_OPEN_USE_PORTAL to 1. + # This will make xdg-open use the portal to open programs, + # which resolves bugs involving programs opening inside FHS envs + # or with unexpected env vars set from wrappers. + # See #160923 for more info. + xdgOpenUsePortal = true; + extraPortals = [ + pkgs.xdg-desktop-portal-gtk + pkgs.kdePackages.xdg-desktop-portal-kde + pkgs.xdg-desktop-portal-gnome + ]; + config = { + niri = { + default = [ + "gnome" + "gtk" + "kde" + ]; + # Portal API reference: + # https://docs.flatpak.org/en/latest/portal-api-reference.html + # "org.freedesktop.impl.portal.Access" = ["kde"]; + # "org.freedesktop.impl.portal.Notification" = ["kde"]; + "org.freedesktop.impl.portal.FileChooser" = [ "kde" ]; + }; + }; + }; +} diff --git a/modules/wms/wayland/variables.nix b/modules/wms/variables.mod.nix similarity index 85% rename from modules/wms/wayland/variables.nix rename to modules/wms/variables.mod.nix index 3b2aec7..e7aabfc 100644 --- a/modules/wms/wayland/variables.nix +++ b/modules/wms/variables.mod.nix @@ -2,14 +2,16 @@ config, lib, ... -}: let +}: +let inherit (lib.modules) mkIf; inherit (lib.options) mkEnableOption; cfg = config.modules.wms.wayland; -in { +in +{ options.modules.wms.wayland.enable = mkEnableOption "wayland"; - config = mkIf cfg.enable { + config = mkIf true { environment.variables = { NIXOS_OZONE_WL = "1"; __GL_GSYNC_ALLOWED = "0"; @@ -29,8 +31,8 @@ in { NIXOS_XDG_OPEN_USE_PORTAL = "1"; - XDG_CURRENT_DESKTOP = "Hyprland"; - XDG_SESSION_DESKTOP = "Hyprland"; + XDG_CURRENT_DESKTOP = "niri"; + XDG_SESSION_DESKTOP = "niri"; XDG_SESSION_TYPE = "wayland"; ELECTRON_OZONE_PLATFORM_HINT = "auto"; diff --git a/modules/wms/wayland/hyprland/binds.nix b/modules/wms/wayland/hyprland/binds.nix deleted file mode 100644 index 3e923a1..0000000 --- a/modules/wms/wayland/hyprland/binds.nix +++ /dev/null @@ -1,117 +0,0 @@ -{ - lib, - pkgs, - ... -}: let - inherit (builtins) map genList toString; - inherit (lib.meta) getExe getExe'; -in { - programs.hyprland.settings = { - # Keybinds - bind = - # workspaces - # split-workspace is because of the split-workspace plugin - map ( - i: let - mod = a: b: a - (b * (a / b)); - key = toString (mod i 10); - workspace = toString i; - in "$mainMod, ${key}, split:workspace, ${workspace}" - ) (genList (i: i + 1) 10) - # split-movetoworkspacesilent - ++ map ( - i: let - mod = a: b: a - (b * (a / b)); - key = toString (mod i 10); - workspace = toString i; - in "$mainMod SHIFT, ${key}, split:movetoworkspacesilent, ${workspace}" - ) (genList (i: i + 1) 10) - ++ [ - "$mainMod, RETURN, exec, foot" - "$mainMod, Q, killactive" - "$mainMod, F, fullscreen, 0" - "$mainMod, D, exec, ${pkgs.procps}/bin/pkill fuzzel || ${getExe pkgs.fuzzel}" - "$mainMod, SPACE, togglefloating, active" - "$mainMod ALT, L, exec, ${getExe pkgs.swaylock}" - - # Screenshotting - "$mainMod, S, exec, ${pkgs.grimblast}/bin/grimblast copy area" # only copy - "$mainMod SHIFT, S, exec, ${pkgs.grimblast}/bin/grimblast save area - | ${pkgs.satty}/bin/satty -f -" # edit with satty - - # File manager - "$mainMod, E, exec, ${pkgs.xfce.thunar}/bin/thunar" - - # Toggle the three different special workspaces. - "$mainMod, N, togglespecialworkspace, nixos" - "$mainMod, X, togglespecialworkspace, keepassxc" - "$mainMod, V, togglespecialworkspace, audio" - - # Reload hyprland - "$mainMod, R, exec, ${getExe' pkgs.hyprland "hyprctl"} reload" - - # Restart waybar - "$mainMod CONTROL, B, exec, ${pkgs.procps}/bin/pkill waybar || ${getExe pkgs.waybar}" - ]; - - binde = [ - # window focus - "$mainMod, H, movefocus, l" - "$mainMod, J, movefocus, d" - "$mainMod, K, movefocus, u" - "$mainMod, L, movefocus, r" - - # Move Windows - "$mainMod SHIFT, H, movewindow, l" - "$mainMod SHIFT, J, movewindow, d" - "$mainMod SHIFT, K, movewindow, u" - "$mainMod SHIFT, L, movewindow, r" - ]; - - # Media controls - bindl = let - volumectl = getExe' pkgs.avizo "volumectl"; - playerctl = getExe pkgs.playerctl; - play-pause = "${playerctl} play-pause"; - stop = "${playerctl} stop"; - prev = "${playerctl} previous"; - next = "${playerctl} next"; - toggle-mute = "${volumectl} toggle-mute"; - toggle-mic-mute = "${volumectl} toggle-mute"; - in [ - ", XF86AudioMedia, exec, ${play-pause}" - ", XF86AudioPlay, exec, ${play-pause}" - ", XF86AudioStop, exec, ${stop}" - ", XF86AudioPrev, exec, ${prev}" - ", XF86AudioNext, exec, ${next}" - ", XF86AudioMute, exec, ${toggle-mute}" - ", XF86AudioMicMute, exec, ${toggle-mic-mute}" - ]; - - # locked + repeat - bindle = let - volumectl = getExe' pkgs.avizo "volumectl"; - lightctl = getExe' pkgs.avizo "lightctl"; - volume_up = "${volumectl} -u up"; - volume_down = "${volumectl} -u down"; - brightness_up = "${lightctl} up"; - brightness_down = "${lightctl} down"; - in [ - ", XF86AudioRaiseVolume, exec, ${volume_up}" - ", XF86AudioLowerVolume, exec, ${volume_down}" - ", XF86MonBrightnessUp, exec, ${brightness_up}" - ", XF86MonBrightnessDown, exec, ${brightness_down}" - ]; - - # Mouse settings - bindm = [ - "$mainMod, mouse:272, movewindow" - "$mainMod, mouse:273, resizewindow" - ]; - - # Some more movement-related settings - binds = { - pass_mouse_when_bound = false; - movefocus_cycles_fullscreen = false; - }; - }; -} diff --git a/modules/wms/wayland/hyprland/decorations.nix b/modules/wms/wayland/hyprland/decorations.nix deleted file mode 100644 index fd3a2c5..0000000 --- a/modules/wms/wayland/hyprland/decorations.nix +++ /dev/null @@ -1,60 +0,0 @@ -_: { - programs.hyprland.settings = { - #Decoration settings - decoration = { - rounding = 0; - blur = { - enabled = false; - size = 3; - passes = 2; - }; - }; - # Bezier curves for aninmations. - # Generate your own at https://www.cssportal.com/css-cubic-bezier-generator/ - bezier = [ - "dupa, 0.1, 0.9, 0.1, 1.05" - ]; - # Hyprland anomations, using the above bezier curves - animations = { - enabled = false; - # animation = [ - # "windows, 1, 4, dupa, popin" - # "windowsOut, 1, 4, dupa, slide" - # "border, 1, 15, default" - # "fade, 1, 10, default" - # "workspaces, 1, 5, dupa, slidevert" - # ]; - }; - - cursor = { - hide_on_key_press = true; - no_hardware_cursors = true; - }; - - misc = { - enable_swallow = true; - swallow_regex = "foot"; - focus_on_activate = true; - vrr = 1; - vfr = true; - animate_manual_resizes = false; - animate_mouse_windowdragging = false; - force_default_wallpaper = 0; - }; - - # Window rules for some programs. - windowrulev2 = [ - "float, class:^(Tor Browser)$" - "float, class:^(mpv)$" - "float, class:^(imv)$" - "float, title:^(Picture-in-Picture)$" - "float, title:^(.*)(Choose User Profile)(.*)$" - "float, title:^(blob:null/)(.*)$" - "float, class:^(xdg-desktop-portal-gtk)$" - "float, class:^(code), title: ^(Open*)" - "size 70% 70%, class:^(code), title: ^(Open*)" - "center, class: ^(code), title: ^(Open*)" - "float, class:^(org.keepassxc.KeePassXC)$" - ]; - }; -} diff --git a/modules/wms/wayland/hyprland/exec.nix b/modules/wms/wayland/hyprland/exec.nix deleted file mode 100644 index 6a2c5f5..0000000 --- a/modules/wms/wayland/hyprland/exec.nix +++ /dev/null @@ -1,27 +0,0 @@ -{ - config, - pkgs, - ... -}: let - # inherit (config.modules.style) cursor; - inherit (builtins) toString; -in { - programs.hyprland.settings = { - # Hyprland settings - # Programs which get executed at Hyprland start. - exec-once = [ - "hyprctl setcursor BreezeX-RosePine-Linux 32" - - "[workspace special:keepassxc; silent;tile] ${pkgs.keepassxc}/bin/keepassxc" - "[workspace special:audio; silent;tile] ${pkgs.pwvucontrol}/bin/pwvucontrol" - - "${pkgs.swww}/bin/swww-daemon" - - "${pkgs.avizo}/bin/avizo-service" - - "${pkgs.wlsunset}/bin/wlsunset -S 06:00 -s 20:00" - "${pkgs.lxqt.lxqt-policykit}/bin/lxqt-policykit-agent" - "hyprctl dispatch split-workspace 1" - ]; - }; -} diff --git a/modules/wms/wayland/hyprland/module.nix b/modules/wms/wayland/hyprland/module.nix deleted file mode 100644 index 2ecec85..0000000 --- a/modules/wms/wayland/hyprland/module.nix +++ /dev/null @@ -1,58 +0,0 @@ -{ - config, - inputs, - lib, - pkgs, - ... -}: let - inherit (lib.modules) mkIf; - inherit (lib.options) mkOption; - inherit (lib.types) bool; - - cfg = config.modules.desktops.hyprland; -in { - imports = [ - ./binds.nix - ./decorations.nix - ./exec.nix - ./settings.nix - ./workspaces.nix - inputs.hyprland.nixosModules.default - ]; - - options.modules.desktops.hyprland = { - enable = mkOption { - type = bool; - default = false; - description = '' - Whether to enable Hyprland wayland compositor. - ''; - }; - }; - - config = mkIf cfg.enable { - programs.hyprland = { - enable = true; - xwayland.enable = true; - package = pkgs.hyprland; - portalPackage = pkgs.xdg-desktop-portal-hyprland; - plugins = [ - pkgs.hyprlandPlugins.hyprsplit - ]; - withUWSM = true; - }; - # xdg Portal - xdg.portal = { - enable = true; - xdgOpenUsePortal = true; - extraPortals = [ - pkgs.xdg-desktop-portal-gtk - pkgs.xdg-desktop-portal-hyprland - ]; - config = { - common.default = ["*"]; - hyprland.default = ["gtk" "hyprland"]; - }; - }; - }; -} diff --git a/modules/wms/wayland/hyprland/settings.nix b/modules/wms/wayland/hyprland/settings.nix deleted file mode 100644 index bab7083..0000000 --- a/modules/wms/wayland/hyprland/settings.nix +++ /dev/null @@ -1,82 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (builtins) toString; - inherit (lib.attrsets) mapAttrsToList; - - inherit (config.modules.style.colorScheme) colors; - inherit (config.modules.system.hardware) monitors; -in { - config = { - programs.hyprland = { - settings = { - # Hyprland settings - "$mainMod" = "SUPER"; - - # Monitor config - # Thanks Poz for inspiration, using an attrSet is actually much smarter - # than using a normal list. - monitor = - mapAttrsToList ( - name: m: let - w = toString m.resolution.x; - h = toString m.resolution.y; - refreshRate = toString m.refreshRate; - x = toString m.position.x; - y = toString m.position.y; - scale = toString m.scale; - in "${name},${w}x${h}@${refreshRate},${x}x${y},${scale}" - ) - monitors; - - # Input settings - input = { - kb_layout = "us,ru"; - kb_variant = ",phonetic_winkeys"; - kb_options = "grp:rctrl_rshift_toggle, compose:102"; - - follow_mouse = true; - - repeat_rate = 60; - repeat_delay = 200; - - touchpad = { - disable_while_typing = true; - }; - }; - - general = { - layout = "dwindle"; - gaps_in = 0; - gaps_out = 0; - border_size = 2; - - "col.active_border" = "0xff${colors.base07}"; - no_border_on_floating = true; - }; - - ecosystem.no_update_news = true; - - plugin = { - hyprsplit = { - num_workspaces = 10; - persistent_workspaces = true; - }; - dynamic-cursors = { - enabled = true; - - mode = "rotate"; - rotate = { - length = 20; - offset = 0.0; - }; - threshhold = 2; - shake.enabled = false; - }; - }; - }; - }; - }; -} diff --git a/modules/wms/wayland/hyprland/workspaces.nix b/modules/wms/wayland/hyprland/workspaces.nix deleted file mode 100644 index f526436..0000000 --- a/modules/wms/wayland/hyprland/workspaces.nix +++ /dev/null @@ -1,46 +0,0 @@ -{ - config, - lib, - ... -}: let - inherit (builtins) map genList attrNames toString; - inherit (lib.lists) imap0 flatten; - inherit (lib.strings) optionalString; - - inherit (config.modules.system.hardware) monitors; -in { - programs.hyprland.settings = { - # INFO: This is a custom function to map all of my monitors to workspaces. - # Since I use split-monitor-workspaces, I map 10 workspaces to each monitor - # and set the first one to be the default one. - # To be able to use this for a varying amount of monitors we do some nasty trickery. - # This was inspired by jacekpoz, whose configuration is linked in this project's README.md. - workspace = - # We're creating several lists of workspace assignments, one for each monitor, - # and have to merge them into one big list. - (flatten - # We then use imap0 insted of map because imap0 starts indexing at zero as oppsed to one with map. - (imap0 (monitorIndex: monitorName: ( - map ( - i: let - # we define our own modulo operation for this, - # since only the first workspace on each monitor is the default workspace. - mod = a: b: a - (b * (a / b)); - workspace = toString i; - isDefault = (mod i 10) == 1; # 11, 21, 31, ... - in "${workspace}, monitor:${monitorName}${optionalString isDefault ", default:true"}" - ) - # we generate a list of 10 elements for each monitor. We have to add 1 each time since genList starts indexing at 0. - # also, we add the monitorIndex * 10 to get 10 workspaces for each individual monitor. - (genList (i: i + 1 + (10 * monitorIndex)) 10) - )) - # our attrSet of different monitors - (attrNames monitors))) - # These are my two special workspaces - ++ [ - "special:nixos, decorate:false" - "special:keepassxc, decorate:false" - "special:audio, decorate:false" - ]; - }; -} diff --git a/modules/wms/wayland/module.nix b/modules/wms/wayland/module.nix deleted file mode 100644 index 9a66420..0000000 --- a/modules/wms/wayland/module.nix +++ /dev/null @@ -1,5 +0,0 @@ -_: { - imports = [ - ./variables.nix - ]; -} diff --git a/modules/wms/wayland/sway/module.nix b/modules/wms/wayland/sway/module.nix deleted file mode 100644 index 1a85c49..0000000 --- a/modules/wms/wayland/sway/module.nix +++ /dev/null @@ -1,8 +0,0 @@ -{ - config, - lib, - pkgs, - ... -}: let -in { -} diff --git a/npins/default.nix b/npins/default.nix new file mode 100644 index 0000000..46c315b --- /dev/null +++ b/npins/default.nix @@ -0,0 +1,210 @@ +/* + This file is provided under the MIT licence: + + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +*/ +# Generated by npins. Do not modify; will be overwritten regularly +let + # Backwards-compatibly make something that previously didn't take any arguments take some + # The function must return an attrset, and will unfortunately be eagerly evaluated + # Same thing, but it catches eval errors on the default argument so that one may still call it with other arguments + mkFunctor = + fn: + let + e = (builtins.tryEval (fn { })); + in + (if e.success then e.value else { error = fn { }; }) // { __functor = _self: fn; }; + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295 + range = + first: last: if first > last then [ ] else builtins.genList (n: first + n) (last - first + 1); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257 + stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1)); + + # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269 + stringAsChars = f: s: concatStrings (map f (stringToCharacters s)); + concatMapStrings = f: list: concatStrings (map f list); + concatStrings = builtins.concatStringsSep ""; + + # If the environment variable NPINS_OVERRIDE_${name} is set, then use + # the path directly as opposed to the fetched source. + # (Taken from Niv for compatibility) + mayOverride = + name: path: + let + envVarName = "NPINS_OVERRIDE_${saneName}"; + saneName = stringAsChars (c: if (builtins.match "[a-zA-Z0-9]" c) == null then "_" else c) name; + ersatz = builtins.getEnv envVarName; + in + if ersatz == "" then + path + else + # this turns the string into an actual Nix path (for both absolute and + # relative paths) + builtins.trace "Overriding path of \"${name}\" with \"${ersatz}\" due to set \"${envVarName}\"" ( + if builtins.substring 0 1 ersatz == "/" then + /. + ersatz + else + /. + builtins.getEnv "PWD" + "/${ersatz}" + ); + + mkSource = + name: spec: + { + pkgs ? null, + }: + assert spec ? type; + let + # Unify across builtin and pkgs fetchers. + # `fetchGit` requires a wrapper because of slight API differences. + fetchers = + if pkgs == null then + { + inherit (builtins) fetchTarball fetchurl; + # For some fucking reason, fetchGit has a different signature than the other builtin fetchers … + fetchGit = args: (builtins.fetchGit args).outPath; + } + else + { + fetchTarball = pkgs.fetchzip; + inherit (pkgs) fetchurl; + fetchGit = + { + url, + submodules, + rev, + name, + narHash, + }: + pkgs.fetchgit { + inherit url rev name; + fetchSubmodules = submodules; + hash = narHash; + }; + }; + + # Dispatch to the correct code path based on the type + path = + if spec.type == "Git" then + mkGitSource fetchers spec + else if spec.type == "GitRelease" then + mkGitSource fetchers spec + else if spec.type == "PyPi" then + mkPyPiSource fetchers spec + else if spec.type == "Channel" then + mkChannelSource fetchers spec + else if spec.type == "Tarball" then + mkTarballSource fetchers spec + else + builtins.throw "Unknown source type ${spec.type}"; + in + spec // { outPath = mayOverride name path; }; + + mkGitSource = + { fetchTarball, fetchGit, ... }: + { + repository, + revision, + url ? null, + submodules, + hash, + branch ? null, + ... + }: + assert repository ? type; + # At the moment, either it is a plain git repository (which has an url), or it is a GitHub/GitLab repository + # In the latter case, there we will always be an url to the tarball + if url != null && !submodules then + fetchTarball { + inherit url; + sha256 = hash; + } + else + let + url = + if repository.type == "Git" then + repository.url + else if repository.type == "GitHub" then + "https://github.com/${repository.owner}/${repository.repo}.git" + else if repository.type == "GitLab" then + "${repository.server}/${repository.repo_path}.git" + else + throw "Unrecognized repository type ${repository.type}"; + urlToName = + url: rev: + let + matched = builtins.match "^.*/([^/]*)(\\.git)?$" url; + + short = builtins.substring 0 7 rev; + + appendShort = if (builtins.match "[a-f0-9]*" rev) != null then "-${short}" else ""; + in + "${if matched == null then "source" else builtins.head matched}${appendShort}"; + name = urlToName url revision; + in + fetchGit { + rev = revision; + narHash = hash; + + inherit name submodules url; + }; + + mkPyPiSource = + { fetchurl, ... }: + { url, hash, ... }: + fetchurl { + inherit url; + sha256 = hash; + }; + + mkChannelSource = + { fetchTarball, ... }: + { url, hash, ... }: + fetchTarball { + inherit url; + sha256 = hash; + }; + + mkTarballSource = + { fetchTarball, ... }: + { + url, + locked_url ? url, + hash, + ... + }: + fetchTarball { + url = locked_url; + sha256 = hash; + }; +in +mkFunctor ( + { + input ? ./sources.json, + }: + let + data = + if builtins.isPath input then + # while `readFile` will throw an error anyways if the path doesn't exist, + # we still need to check beforehand because *our* error can be caught but not the one from the builtin + # *piegames sighs* + if builtins.pathExists input then + builtins.fromJSON (builtins.readFile input) + else + throw "Input path ${toString input} does not exist" + else if builtins.isAttrs input then + input + else + throw "Unsupported input type ${builtins.typeOf input}, must be a path or an attrset"; + version = data.version; + in + if version == 6 then + builtins.mapAttrs (name: spec: mkFunctor (mkSource name spec)) data.pins + else + throw "Unsupported format version ${toString version} in sources.json. Try running `npins upgrade`" +) diff --git a/npins/sources.json b/npins/sources.json new file mode 100644 index 0000000..bad3715 --- /dev/null +++ b/npins/sources.json @@ -0,0 +1,227 @@ +{ + "pins": { + "comma": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "comma" + }, + "branch": "master", + "submodules": false, + "revision": "995b210e86c9d89cdabbdee622681389ce6c95ac", + "url": "https://github.com/nix-community/comma/archive/995b210e86c9d89cdabbdee622681389ce6c95ac.tar.gz", + "hash": "sha256-dNek1a8Yt3icWc8ZpVe1NGuG+eSoTDOmAAJbkYmMocU=" + }, + "flake-compat": { + "type": "Git", + "repository": { + "type": "Forgejo", + "server": "https://git.lix.systems/", + "owner": "lix-project", + "repo": "flake-compat" + }, + "branch": "main", + "submodules": false, + "revision": "549f2762aebeff29a2e5ece7a7dc0f955281a1d1", + "url": "https://git.lix.systems/lix-project/flake-compat/archive/549f2762aebeff29a2e5ece7a7dc0f955281a1d1.tar.gz", + "hash": "sha256-NKw96t+BgHIYzHUjkTK95FqYRVKB8DHpVhefWSz/kTw=" + }, + "hjem": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "feel-co", + "repo": "hjem" + }, + "branch": "main", + "submodules": false, + "revision": "3093a74542b30f8155954d585d0ae2401e3adbe5", + "url": "https://github.com/feel-co/hjem/archive/3093a74542b30f8155954d585d0ae2401e3adbe5.tar.gz", + "hash": "sha256-LzojKFWAAreWyH56aupj/MLwuPPnnyzplw/xdbavC9c=" + }, + "impermanence": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "impermanence" + }, + "branch": "master", + "submodules": false, + "revision": "4b3e914cdf97a5b536a889e939fb2fd2b043a170", + "url": "https://github.com/nix-community/impermanence/archive/4b3e914cdf97a5b536a889e939fb2fd2b043a170.tar.gz", + "hash": "sha256-LJggUHbpyeDvNagTUrdhe/pRVp4pnS6wVKALS782gRI=" + }, + "lanzaboote": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "lanzaboote" + }, + "branch": "master", + "submodules": false, + "revision": "785a5701b22259b85735301b1aad19c2bee15498", + "url": "https://github.com/nix-community/lanzaboote/archive/785a5701b22259b85735301b1aad19c2bee15498.tar.gz", + "hash": "sha256-pZQyCkqIFwGA77np+vqVQZgg2P0qPAI6x6kC3w6+PjE=" + }, + "lix": { + "type": "Git", + "repository": { + "type": "Forgejo", + "server": "https://git.lix.systems/", + "owner": "lix-project", + "repo": "lix" + }, + "branch": "main", + "submodules": false, + "revision": "321807a40e1fdd44d950ff01746c95cb6e2eced3", + "url": "https://git.lix.systems/lix-project/lix/archive/321807a40e1fdd44d950ff01746c95cb6e2eced3.tar.gz", + "hash": "sha256-2sDX5Nv/DGIzZH+3pIlAUpZfVlMGz7Hl/mqHUaic+p8=" + }, + "lix-module": { + "type": "Git", + "repository": { + "type": "Forgejo", + "server": "https://git.lix.systems/", + "owner": "lix-project", + "repo": "nixos-module" + }, + "branch": "main", + "submodules": false, + "revision": "4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f", + "url": "https://git.lix.systems/lix-project/nixos-module/archive/4d4c2b8f0a801c91ce5b717c77fe3a17efa1402f.tar.gz", + "hash": "sha256-gbpuESxl/An4GTh7QEbQRYJozVIxWkwVGbWK0/0GoRc=" + }, + "nh": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-community", + "repo": "nh" + }, + "branch": "master", + "submodules": false, + "revision": "ec34a659652d98c225e2a97d100830365d7551c3", + "url": "https://github.com/nix-community/nh/archive/ec34a659652d98c225e2a97d100830365d7551c3.tar.gz", + "hash": "sha256-+MuFPjyJl3JbNVs3Xq9dATJEbEOvwF4LMUNMmmzO7mU=" + }, + "nil": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "oxalica", + "repo": "nil" + }, + "branch": "main", + "submodules": false, + "revision": "cd7a6f6d5dc58484e62a8e85677e06e47cf2bd4d", + "url": "https://github.com/oxalica/nil/archive/cd7a6f6d5dc58484e62a8e85677e06e47cf2bd4d.tar.gz", + "hash": "sha256-fK4INnIJQNAA8cyjcDRZSPleA+N/STI6I0oBDMZ2r+E=" + }, + "niri": { + "type": "GitRelease", + "repository": { + "type": "GitHub", + "owner": "yalter", + "repo": "niri" + }, + "pre_releases": false, + "version_upper_bound": null, + "release_prefix": null, + "submodules": false, + "version": "v25.05.1", + "revision": "61e306c1c6b13ae99bf7f51532a6aa86cd50d690", + "url": "https://api.github.com/repos/yalter/niri/tarball/refs/tags/v25.05.1", + "hash": "sha256-z4viQZLgC2bIJ3VrzQnR+q2F3gAOEQpU1H5xHtX/2fs=" + }, + "nixfmt": { + "type": "GitRelease", + "repository": { + "type": "GitHub", + "owner": "nixos", + "repo": "nixfmt" + }, + "pre_releases": false, + "version_upper_bound": null, + "release_prefix": null, + "submodules": false, + "version": "v1.0.0", + "revision": "1f2589cb7198529c6c1eec9699eccd4d507d3600", + "url": "https://api.github.com/repos/nixos/nixfmt/tarball/refs/tags/v1.0.0", + "hash": "sha256-d8SYpFoCpi1GrqlKwxxq9qhyjDANeLgr8WWJNRK6wkc=" + }, + "nixpkgs": { + "type": "Channel", + "name": "nixpkgs-unstable", + "url": "https://releases.nixos.org/nixpkgs/nixpkgs-25.11pre836767.e44b8dc0882d/nixexprs.tar.xz", + "hash": "sha256-euf3HhNllLzdAjWqfM+sgM8WE8H8sl7O61LpjOxsQN8=" + }, + "npins": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "andir", + "repo": "npins" + }, + "branch": "master", + "submodules": false, + "revision": "afa9fe50cb0bff9ba7e9f7796892f71722b2180d", + "url": "https://github.com/andir/npins/archive/afa9fe50cb0bff9ba7e9f7796892f71722b2180d.tar.gz", + "hash": "sha256-D6dYAMk9eYpBriE07s8Q7M3WBT7uM9pz3RKIoNk+h7I=" + }, + "quickshell": { + "type": "Git", + "repository": { + "type": "Git", + "url": "https://git.outfoxxed.me/outfoxxed/quickshell" + }, + "branch": "master", + "submodules": false, + "revision": "a5431dd02dc23d9ef1680e67777fed00fe5f7cda", + "url": null, + "hash": "sha256-vqkSDvh7hWhPvNjMjEDV4KbSCv2jyl2Arh73ZXe274k=" + }, + "spicetify-nix": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "Gerg-L", + "repo": "spicetify-nix" + }, + "branch": "master", + "submodules": false, + "revision": "26c488b60360e15db372483d826cec89ac532980", + "url": "https://github.com/Gerg-L/spicetify-nix/archive/26c488b60360e15db372483d826cec89ac532980.tar.gz", + "hash": "sha256-Ow+qyFckroPS4SQFHcFZ8mKh3HIQ2pQdC6DRjiYF9EE=" + }, + "systems": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "nix-systems", + "repo": "default-linux" + }, + "branch": "main", + "submodules": false, + "revision": "31732fcf5e8fea42e59c2488ad31a0e651500f68", + "url": "https://github.com/nix-systems/default-linux/archive/31732fcf5e8fea42e59c2488ad31a0e651500f68.tar.gz", + "hash": "sha256-12tWmuL2zgBgZkdoB6qXZsgJEH9LR3oUgpaQq2RbI80=" + }, + "watt": { + "type": "Git", + "repository": { + "type": "GitHub", + "owner": "notashelf", + "repo": "watt" + }, + "branch": "main", + "submodules": false, + "revision": "154724c7b1bd49654ea55df719e1eb3219ec2000", + "url": "https://github.com/notashelf/watt/archive/154724c7b1bd49654ea55df719e1eb3219ec2000.tar.gz", + "hash": "sha256-hw3rL4rlIlYJMTeE7DlQ3lRhQDJURAhE+PC/NT4VAAQ=" + } + }, + "version": 6 +} diff --git a/packages/default.nix b/packages/default.nix index bd69889..bacd417 100644 --- a/packages/default.nix +++ b/packages/default.nix @@ -1,7 +1,16 @@ -pkgs: let - helix = pkgs.callPackage ./helix.nix {}; - kakoune = pkgs.callPackage ./kakoune.nix {}; - fish = pkgs.callPackage ./shell {}; -in { - inherit helix kakoune fish; +{ + inputs, + pkgs, + sources, +}: +let + inherit (pkgs) lib; + kakoune = pkgs.callPackage ./kakoune.nix { }; + fish = pkgs.callPackage ./fish { inherit lib; }; +in +{ + inherit + kakoune + fish + ; } diff --git a/packages/shell/aliases.nix b/packages/fish/aliases.nix similarity index 75% rename from packages/shell/aliases.nix rename to packages/fish/aliases.nix index de33835..e200f6c 100644 --- a/packages/shell/aliases.nix +++ b/packages/fish/aliases.nix @@ -1,8 +1,10 @@ -{pkgs, ...}: let +{ pkgs, ... }: +let inherit (pkgs.lib) getExe; -in { - ls = "${getExe pkgs.eza} --icons"; - la = "${getExe pkgs.eza} --icons -lha --git"; +in +{ + ls = "${getExe pkgs.eza} --icons=never"; + la = "${getExe pkgs.eza} --icons=never -lha --git"; g = "git"; n = "nix"; diff --git a/packages/shell/config.fish b/packages/fish/config.fish similarity index 100% rename from packages/shell/config.fish rename to packages/fish/config.fish diff --git a/packages/fish/default.nix b/packages/fish/default.nix new file mode 100644 index 0000000..8b09cfb --- /dev/null +++ b/packages/fish/default.nix @@ -0,0 +1,45 @@ +# This shell setup was originally inspired by sioodmy. +# Some further cool tricks, like using vendor_conf.d to avoid having +# to build fish myself, are taken from viperml's setup. +{ pkgs, ... }: +let + inherit (pkgs) lib; + inherit (lib.strings) concatStringsSep; + inherit (lib.attrsets) mapAttrsToList; + + toml = pkgs.formats.toml { }; + starship-config = import ./starship.nix; + aliases = import ./aliases.nix { inherit pkgs; }; + vendorConf = "share/fish/vendor_conf.d"; + + fishinit = import ./fishinit.nix { + inherit + pkgs + aliasesStr + vendorConf + ; + }; + + aliasesStr = mapAttrsToList (k: v: "alias ${k}=\"${v}\"") aliases |> concatStringsSep "\n"; + + packages = import ./packages.nix pkgs; +in +(pkgs.symlinkJoin { + name = "fish"; + paths = [ pkgs.fish ] ++ packages; + nativeBuildInputs = [ pkgs.makeWrapper ]; + postBuild = '' + wrapProgram $out/bin/fish \ + --set STARSHIP_CONFIG "${toml.generate "starship.toml" starship-config}" \ + --prefix XDG_DATA_DIRS : "${ + lib.makeSearchPathOutput "out" "share" [ + fishinit + ] + }" + ''; +}).overrideAttrs + (_: { + passthru = { + shellPath = "/bin/fish"; + }; + }) diff --git a/packages/fish/fishinit.nix b/packages/fish/fishinit.nix new file mode 100644 index 0000000..b818cce --- /dev/null +++ b/packages/fish/fishinit.nix @@ -0,0 +1,34 @@ +{ + pkgs, + aliasesStr, + vendorConf, +}: +pkgs.writeTextDir "${vendorConf}/blox_config.fish" + # fish + '' + # source ${pkgs.fishPlugins.sponge}/share/zsh-defer/zsh-defer.plugin.zsh + ${pkgs.atuin}/bin/atuin init fish | source + bind up _atuin_bind_up + + ${pkgs.zoxide}/bin/zoxide init fish | source + # abbr --erase cd &>/dev/null + # alias cd=__zoxide_z + + # abbr --erase ci &>/dev/null + # alias ci=__zoxide_zi + + + ${pkgs.starship}/bin/starship init fish | source + ${pkgs.direnv}/bin/direnv hook fish | source + ${pkgs.pay-respects}/bin/pay-respects fish --alias f --nocnf | source + + # I need to source /etc/profile using foreign-env, to get stuff set by nixos, e.g. environment.systemVariables. + # set -p fish_function_path ${pkgs.fishPlugins.foreign-env}/share/fish/vendor_functions.d + + # fenv source /etc/profile + + source ${./config.fish} + + + ${aliasesStr} + '' diff --git a/packages/shell/packages.nix b/packages/fish/packages.nix similarity index 86% rename from packages/shell/packages.nix rename to packages/fish/packages.nix index b5c7abf..3a3aacb 100644 --- a/packages/shell/packages.nix +++ b/packages/fish/packages.nix @@ -1,7 +1,6 @@ pkgs: builtins.attrValues { - inherit - (pkgs) + inherit (pkgs) # better cd zoxide # pipe viewer @@ -32,27 +31,24 @@ builtins.attrValues { kondo # better grep ripgrep - # better dig - dogdns + # IP stuff + dig # simply the best fetch tool out there microfetch fzf element - carapace difftastic hexyl - iputils + yazi gnumake - gping asciinema inetutils - scc + tokei starship - onefetch wget cpufetch watchman - yt-dlp + # yt-dlp # borked check phase tealdeer hyperfine imagemagick @@ -66,5 +62,6 @@ builtins.attrValues { figlet unzip zip + trash-cli ; } diff --git a/packages/fish/starship.nix b/packages/fish/starship.nix new file mode 100644 index 0000000..dec32be --- /dev/null +++ b/packages/fish/starship.nix @@ -0,0 +1,123 @@ +{ + add_newline = false; + aws.symbol = " "; + buf.symbol = " "; + bun.symbol = " "; + c.symbol = " "; + cmake.symbol = " "; + conda.symbol = " "; + cpp.symbol = " "; + crystal.symbol = " "; + dart.symbol = " "; + deno.symbol = " "; + directory.read_only = " 󰌾"; + docker_context.symbol = " "; + elixir.symbol = " "; + elm.symbol = " "; + fennel = { + symbol = " "; + }; + fossil_branch = { + symbol = " "; + }; + gcloud = { + symbol = " "; + }; + git_branch = { + symbol = " "; + }; + git_commit = { + tag_symbol = "  "; + }; + golang.symbol = " "; + gradle = { + symbol = " "; + }; + guix_shell = { + symbol = " "; + }; + haskell = { + symbol = " "; + }; + haxe = { + symbol = " "; + }; + hg_branch = { + symbol = " "; + }; + hostname = { + ssh_symbol = " "; + }; + java = { + symbol = " "; + }; + julia = { + symbol = " "; + }; + kotlin = { + symbol = " "; + }; + lua = { + symbol = " "; + }; + memory_usage = { + symbol = "󰍛 "; + }; + meson = { + symbol = "󰔷 "; + }; + nim = { + symbol = "󰆥 "; + }; + nix_shell = { + symbol = " "; + }; + nodejs = { + symbol = " "; + }; + ocaml = { + symbol = " "; + }; + os = { + symbols = { + Linux = " "; + NixOS = " "; + }; + }; + package = { + symbol = "󰏗 "; + }; + perl = { + symbol = " "; + }; + php = { + symbol = " "; + }; + pijul_channel = { + symbol = " "; + }; + pixi = { + symbol = "󰏗 "; + }; + python = { + symbol = " "; + }; + rlang = { + symbol = "󰟔 "; + }; + ruby = { + symbol = " "; + }; + rust = { + symbol = "󱘗 "; + }; + scala = { + symbol = " "; + }; + swift = { + symbol = " "; + }; + zig = { + symbol = " "; + }; +} diff --git a/packages/helix.nix b/packages/helix.nix deleted file mode 100644 index 763c8b0..0000000 --- a/packages/helix.nix +++ /dev/null @@ -1,315 +0,0 @@ -{ - symlinkJoin, - makeWrapper, - alejandra, - basedpyright, - bash-language-server, - black, - clang-tools, - clippy, - cmake-format, - cmake-language-server, - deno, - dprint, - formats, - gdb, - golangci-lint-langserver, - gopls, - helix, - lazygit, - lib, - lldb_19, - marksman, - nil, - pyright, - ruff, - rust-analyzer, - rustfmt, - shellcheck, - shfmt, - solargraph, - stdenv, - superhtml, - taplo, - tinymist, - typescript-language-server, - vscode-langservers-extracted, - ... -}: let - inherit (lib.meta) getExe; - - toml = formats.toml {}; - helix-config = { - theme = "gruvbox"; - editor = { - cursorline = false; - color-modes = true; - indent-guides.render = true; - lsp = { - enable = true; - auto-signature-help = true; - display-inlay-hints = true; - display-messages = true; - snippets = true; - }; - file-picker = { - hidden = true; - }; - line-number = "relative"; - true-color = true; - auto-format = true; - completion-timeout = 5; - mouse = true; - bufferline = "multiple"; - soft-wrap.enable = true; - cursor-shape = { - insert = "bar"; - normal = "block"; - select = "underline"; - }; - statusline = { - left = ["spinner" "version-control" "diagnostics" "file-name"]; - right = ["file-base-name" "file-type" "position" "file-encoding"]; - }; - gutters.layout = ["diff" "diagnostics" "line-numbers" "spacer"]; - inline-diagnostics = { - cursor-line = "hint"; - other-lines = "error"; - }; - }; - keys = { - normal = { - space.g = [":new" ":insert-output XDG_CONFIG_HOME=~/.config ${getExe lazygit}" ":buffer-close!" ":redraw"]; - esc = ["collapse_selection" "keep_primary_selection" "normal_mode"]; - A-H = "goto_previous_buffer"; - A-L = "goto_next_buffer"; - A-w = ":buffer-close"; - A-f = ":format"; - A-r = ":reload"; - A-x = "extend_to_line_bounds"; - X = ["extend_line_up" "extend_to_line_bounds"]; - }; - select = { - A-x = "extend_to_line_bounds"; - X = ["extend_line_up" "extend_to_line_bounds"]; - }; - }; - }; - helix-languages = { - language = let - mark = lang: { - command = getExe deno; - args = ["fmt" "-" "--ext" lang]; - }; - in [ - { - name = "bash"; - auto-format = true; - formatter = { - command = getExe shfmt; - args = ["-i" "2"]; - }; - } - { - name = "clojure"; - injection-regex = "(clojure|clj|edn|boot|yuck)"; - file-types = ["clj" "cljs" "cljc" "clje" "cljr" "cljx" "edn" "boot" "yuck"]; - } - { - name = "cmake"; - auto-format = true; - language-servers = ["cmake-language-server"]; - formatter = { - command = getExe cmake-format; - args = ["-"]; - }; - } - { - name = "javascript"; - auto-format = true; - language-servers = ["dprint" "typescript-language-server"]; - } - { - name = "json"; - formatter = mark "json"; - } - { - name = "markdown"; - auto-format = true; - formatter = mark "md"; - } - { - name = "qml"; - language-servers = ["qmlls"]; - } - { - name = "python"; - auto-format = true; - language-servers = [ - "basedpyright" - "ruff" - ]; - } - { - name = "typescript"; - auto-format = true; - language-servers = ["dprint" "typescript-language-server"]; - } - { - name = "rust"; - } - { - name = "c"; - auto-format = true; - language-servers = ["clangd"]; - } - { - name = "c"; - debugger = { - name = "gdb"; - command = getExe gdb; - transport = "stdio"; - templates = [ - { - name = "binary"; - request = "launch"; - completion = [ - { - name = "binary"; - completion = "filename"; - } - ]; - args = { - program = "{0}"; - runInTerminal = true; - }; - } - ]; - }; - } - ]; - - language-server = { - bash-language-server = { - command = getExe bash-language-server; - args = ["start"]; - }; - - rust-analyzer = { - config = { - check.command = "clippy"; - cargo.features = "all"; - }; - }; - - clangd = { - command = "${clang-tools}/bin/clangd"; - clangd.fallbackFlags = ["-std=c++2b"]; - }; - - cmake-language-server = { - command = getExe cmake-language-server; - }; - - deno-lsp = { - command = lib.getExe deno; - args = ["lsp"]; - environment.NO_COLOR = "1"; - config.deno = { - enable = true; - lint = true; - unstable = true; - suggest = { - completeFunctionCalls = false; - imports = {hosts."https://deno.land" = true;}; - }; - inlayHints = { - enumMemberValues.enabled = true; - functionLikeReturnTypes.enabled = true; - parameterNames.enabled = "all"; - parameterTypes.enabled = true; - propertyDeclarationTypes.enabled = true; - variableTypes.enabled = true; - }; - }; - }; - dprint = { - command = getExe dprint; - args = ["lsp"]; - }; - - nil = { - command = getExe nil; - # alejandro - config.nil.formatting.command = ["${getExe alejandra}" "-q"]; - }; - - typescript-language-server = { - command = lib.getExe typescript-language-server; - args = ["--stdio"]; - config = { - typescript-language-server.source = { - addMissingImports.ts = true; - fixAll.ts = true; - organizeImports.ts = true; - removeUnusedImports.ts = true; - sortImports.ts = true; - }; - }; - }; - ruff = { - command = lib.getExe ruff; - args = ["server"]; - }; - basedpyright.command = "${basedpyright}/bin/basedpyright-langserver"; - - vscode-css-language-server = { - command = "${vscode-langservers-extracted}/bin/vscode-css-language-server"; - args = ["--stdio"]; - config = { - provideFormatter = true; - css.validate.enable = true; - scss.validate.enable = true; - }; - }; - }; - }; - wrapped-helix = symlinkJoin { - name = "helix-wrapped"; - paths = [ - # Bash - bash-language-server - # C/C++ - clang-tools - clippy - golangci-lint-langserver - gopls - helix - lldb_19 - # Markdown - marksman - # Nix - nil - rust-analyzer - rustfmt - # Shell - shellcheck - superhtml - # toml - taplo - # typst - tinymist - # typst lsp - vscode-langservers-extracted - ]; - buildInputs = [makeWrapper]; - postBuild = '' - mkdir -p $out/config/helix - cp "${toml.generate "config.toml" helix-config}" $out/config/helix/config.toml - cp "${toml.generate "languages.toml" helix-languages}" $out/config/helix/languages.toml - wrapProgram $out/bin/hx --set \ - XDG_CONFIG_HOME $out/config - ''; - }; -in - wrapped-helix diff --git a/packages/kakoune.nix b/packages/kakoune.nix index aa51912..73fde0b 100644 --- a/packages/kakoune.nix +++ b/packages/kakoune.nix @@ -5,7 +5,8 @@ symlinkJoin, kakounePlugins, ... -}: let +}: +let custom-kakoune = stdenv.mkDerivation { name = "custom-kakoune"; src = fetchFromGitHub { @@ -15,7 +16,10 @@ hash = "sha256-+xqJrJr6nnmEpQaizQ3JMDEISCD8IMB84NJZiXJ74kY="; }; - makeFlags = ["debug=no" "PREFIX=${placeholder "out"}"]; + makeFlags = [ + "debug=no" + "PREFIX=${placeholder "out"}" + ]; enableParallellBuilding = true; @@ -32,13 +36,13 @@ ''; }; plugins = builtins.attrValues { - inherit (kakounePlugins); + inherit (kakounePlugins) ; }; kakoune-wrapped = symlinkJoin { name = "kakoune-wrapped"; - nativeBuildInputs = [makeWrapper]; - paths = [custom-kakoune] ++ plugins; + nativeBuildInputs = [ makeWrapper ]; + paths = [ custom-kakoune ] ++ plugins; postBuild = '' # create a directory for bins that kakoune needs @@ -62,4 +66,4 @@ ''; }; in - kakoune-wrapped +kakoune-wrapped diff --git a/packages/shell/default.nix b/packages/shell/default.nix deleted file mode 100644 index 94dbc91..0000000 --- a/packages/shell/default.nix +++ /dev/null @@ -1,37 +0,0 @@ -# This shell setup was inspired by sioodmy. Check out his setup! -{pkgs, ...}: let - toml = pkgs.formats.toml {}; - starship-config = import ./starship.nix; - aliases = import ./aliases.nix {inherit pkgs;}; - - fishinit = import ./fishinit.nix {inherit pkgs aliasesStr;}; - - aliasesStr = - pkgs.lib.concatStringsSep "\n" - (pkgs.lib.mapAttrsToList (k: v: "alias ${k}=\"${v}\"") aliases); - packages = import ./packages.nix pkgs; - - # this was taken from viperml, check out his config for this! - custom-fish = pkgs.fish.overrideAttrs (old: { - patches = [./fish-on-tmpfs.patch]; - doCheck = false; - postInstall = - old.postInstall - + '' - echo "source ${fishinit}" >> $out/etc/fish/config.fish - ''; - }); -in - (pkgs.symlinkJoin { - name = "fish"; - paths = [custom-fish] ++ packages; - buildInputs = [pkgs.makeWrapper]; - postBuild = '' - wrapProgram $out/bin/fish --set STARSHIP_CONFIG "${toml.generate "starship.toml" starship-config}" \ - ''; - }) - .overrideAttrs (_: { - passthru = { - shellPath = "/bin/fish"; - }; - }) diff --git a/packages/shell/fish-on-tmpfs.patch b/packages/shell/fish-on-tmpfs.patch deleted file mode 100644 index 1ff7c1b..0000000 --- a/packages/shell/fish-on-tmpfs.patch +++ /dev/null @@ -1,10 +0,0 @@ ---- a/src/path.rs -+++ b/src/path.rs -@@ -781,7 +781,7 @@ fn get_cache_directory() -> &'static BaseDirectory { - - fn get_config_directory() -> &'static BaseDirectory { - static DIR: Lazy = -- Lazy::new(|| make_base_directory(L!("XDG_CONFIG_HOME"), L!("/.config/fish"))); -+ Lazy::new(|| make_base_directory(L!("XDG_RUNTIME_DIR"), L!("/.config/fish"))); - &DIR - } diff --git a/packages/shell/fishinit.nix b/packages/shell/fishinit.nix deleted file mode 100644 index 69c7c6c..0000000 --- a/packages/shell/fishinit.nix +++ /dev/null @@ -1,19 +0,0 @@ -{ - pkgs, - aliasesStr, -}: -pkgs.writeText "config.fish" '' - - # source ${pkgs.fishPlugins.sponge}/share/zsh-defer/zsh-defer.plugin.zsh - ${pkgs.atuin}/bin/atuin init fish | source - ${pkgs.zoxide}/bin/zoxide init fish | source - ${pkgs.starship}/bin/starship init fish | source - ${pkgs.direnv}/bin/direnv hook fish | source - ${pkgs.pay-respects}/bin/pay-respects fish --alias f --nocnf | source - - - source ${./config.fish} - - - ${aliasesStr} -'' diff --git a/packages/shell/starship.nix b/packages/shell/starship.nix deleted file mode 100644 index a3175e7..0000000 --- a/packages/shell/starship.nix +++ /dev/null @@ -1,38 +0,0 @@ -{ - add_newline = false; - command_timeout = 2000; - format = "$hostname$username$directory$shell$nix_shell$jobs$character"; - scan_timeout = 1; - - character = { - error_symbol = "[λ](bold red)"; - success_symbol = "[λ](bold green)"; - }; - directory = { - format = "[](bold green) [$path]($style) "; - truncation_length = 2; - }; - - direnv = { - disabled = false; - }; - - git_status = { - disabled = true; - }; - - hostname = { - disabled = false; - format = "@[$hostname](bold blue) "; - ssh_only = true; - }; - - c.symbol = "[ ](black)"; - lua.symbol = "[ ](blue) "; - nix_shell.symbol = "[󱄅 ](blue) "; - nodejs.symbol = "[󰎙 ](yellow)"; - package.symbol = "📦 "; - python.symbol = "[ ](blue) "; - rust.symbol = "[ ](red) "; - username.format = "[$user]($style) in "; -} diff --git a/shell.nix b/shell.nix deleted file mode 100644 index c54b63d..0000000 --- a/shell.nix +++ /dev/null @@ -1,21 +0,0 @@ -{ - mkShellNoCC, - git, - writeShellApplication, -}: -mkShellNoCC { - name = "nichts"; - - DIRENV_LOG_FORMAT = ""; - - packages = [ - git # take a guess - - (writeShellApplication { - name = "update"; - text = '' - nix flake update && git commit flake.lock -m "flake: bump inputs" - ''; - }) - ]; -} diff --git a/templates/default.nix b/templates/default.nix new file mode 100644 index 0000000..0dea28b --- /dev/null +++ b/templates/default.nix @@ -0,0 +1,6 @@ +{ + rust = { + path = ./rust; + description = "Rust project template"; + }; +} diff --git a/templates/rust/.envrc b/templates/rust/.envrc new file mode 100644 index 0000000..3550a30 --- /dev/null +++ b/templates/rust/.envrc @@ -0,0 +1 @@ +use flake diff --git a/templates/rust/Cargo.toml b/templates/rust/Cargo.toml new file mode 100644 index 0000000..892d1eb --- /dev/null +++ b/templates/rust/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "sample-rust" +version = "0.0.1" +license = "GPL-3.0-only" +edition = "2024" diff --git a/templates/rust/default.nix b/templates/rust/default.nix new file mode 100644 index 0000000..3d6c889 --- /dev/null +++ b/templates/rust/default.nix @@ -0,0 +1,8 @@ +{ rustPlatform }: +rustPlatform.buildRustPackage { + pname = "some-rust-package"; + version = "0.0.1"; + + src = ./.; + cargoLock.lockFile = ./Cargo.lock; +} diff --git a/templates/rust/flake.nix b/templates/rust/flake.nix new file mode 100644 index 0000000..2bc9461 --- /dev/null +++ b/templates/rust/flake.nix @@ -0,0 +1,36 @@ +{ + description = "Rust project template"; + inputs = { + nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable"; + systems.url = "github:nix-systems/default-linux"; + }; + + outputs = + inputs: + let + inherit (inputs.nixpkgs) lib; + inherit (lib.attrsets) genAttrs mapAttrs; + + eachSystem = genAttrs (import inputs.systems); + pkgsFor = inputs.nixpkgs.legacyPackages; + in + { + packages = eachSystem (system: { + default = inputs.self.packages.${system}.ralc; + ralc = pkgsFor.${system}.callPackage ./nix/package.nix { }; + }); + + devShells = mapAttrs (_: pkgs: { + default = pkgs.mkShell { + packages = with pkgs; [ + cargo + rustc + rustfmt + bacon + rust-analyzer + rustPackages.clippy + ]; + }; + }) pkgsFor; + }; +} diff --git a/templates/rust/src/main.rs b/templates/rust/src/main.rs new file mode 100644 index 0000000..47ad8c6 --- /dev/null +++ b/templates/rust/src/main.rs @@ -0,0 +1,3 @@ +fn main() { + println!("Hello World!"); +} diff --git a/website/blog/01-BGP.txt b/website/blog/01-BGP.txt deleted file mode 100644 index 72b0dea..0000000 --- a/website/blog/01-BGP.txt +++ /dev/null @@ -1,66 +0,0 @@ - -TODO: -eBGP/iBGP session -Graphs - -/**********************************************/ -/* A no-bullshit guide to a bullshit protocol */ -/**********************************************/ - We can think of the Internet as a network of networks which are all connected in some way. We will refer to these networks as Autonomous Systems(AS) in this article. - -Now, how do we connect these AS's in a sane way? This is where BGP comes in. BGP, which stands for `Border Gateway Protocol`, enables different AS's to exchange information with each other, e.g. communicating with each other. - -There are three main challenges BGP has to solve: - - Scalability: The Internet is BIG. BGP needs to scale well to be feasible in a large scale. - - Privacy: Networks don't want to divulge internal topologies (topology = how a network is structured) - - Policy enforcement: The Networks themselves need to have control over where to send and recieve traffic. - -Other protocols, like Link-Sate routing, do not solve these challenges. - -BGP's key concept, which it revolves about, is called *path-vector routing*, where it adertises the entire AS-level path. -Now, what is an AS-level path? We'll get to that in a minute. - -Before that, why do we need even BGP? The problem is that sending data over the internet costs money. If we want to minimize the costs of sending data, we need to find routes which cost as little as possible. This is also why BGP is a "follow the money" protocol. Different ASes only connect with each other if they can save money that way. - -There are two policies we can use to define this routing: - - Selection: Which path to use (only relevant for outbound traffic) - - Export: Which path to advertise (only relevant for inbount traffic) - -TODO: add graphs here - -=============================================== - eBGP and iBGP -=============================================== - -BGP comes in two flavors: eBGP and iBGP. -The e/i stands for external/internal - -External BGP sessions connect border routers in different ASes. These are therefore use to learn routes to external destinatons - -TODO: add graph - -Internal BGP sessions connect the routers in the same AS. These are used to split up externally-learned routes internally. These are tehn announces exernally(to other ASes) again, using eBGP sessions. - -BGP itself is a pretty simple protocol composed of four basic messages: - - open: establish a BGP session (using TCP) - - notification: report unusual conditions - - update: inform neighbor of a new best route - - can be a change or a removal of a best route - - keepalive: inform neighbor that connection is alive - -update messages carry an IP prefix together with a set of attributes: -/*********************/ -/* IP prefix */ -/*********************/ -/* Attributes */ -/* */ -/* */ -/* */ -/* */ -/*********************/ - -There are four types of different attributes: - - NEXT-HOP - - AS-PATH - - LOCAL-PREF - - MED diff --git a/website/blog/posts/01.html b/website/blog/posts/01.html deleted file mode 100644 index c3d56ad..0000000 --- a/website/blog/posts/01.html +++ /dev/null @@ -1,91 +0,0 @@ - - - - - -
-
-
-
-
-        TODO:
-        eBGP/iBGP session
-        Graphs
-
-        /**********************************************/
-        /* A no-bullshit guide to a bullshit protocol */
-        /**********************************************/
-        We can think of the Internet as a network of networks which are all connected in some way. We will refer to
-        these networks as Autonomous Systems(AS) in this article.
-
-        Now, how do we connect these AS's in a sane way? This is where BGP comes in. BGP, which stands for `Border
-        Gateway Protocol`, enables different AS's to exchange information with each other, e.g. communicating with each
-        other.
-
-        There are three main challenges BGP has to solve:
-        - Scalability: The Internet is BIG. BGP needs to scale well to be feasible in a large scale.
-        - Privacy: Networks don't want to divulge internal topologies (topology = how a network is structured)
-        - Policy enforcement: The Networks themselves need to have control over where to send and recieve traffic.
-
-        Other protocols, like Link-Sate routing, do not solve these challenges.
-
-        BGP's key concept, which it revolves about, is called *path-vector routing*, where it adertises the entire
-        AS-level path.
-        Now, what is an AS-level path? We'll get to that in a minute.
-
-        Before that, why do we need even BGP? The problem is that sending data over the internet costs money. If we want
-        to minimize the costs of sending data, we need to find routes which cost as little as possible. This is also why
-        BGP is a "follow the money" protocol. Different ASes only connect with each other if they can save money that
-        way.
-
-        There are two policies we can use to define this routing:
-        - Selection: Which path to use (only relevant for outbound traffic)
-        - Export: Which path to advertise (only relevant for inbount traffic)
-
-        TODO: add graphs here
-
-        ===============================================
-        eBGP and iBGP
-        ===============================================
-
-        BGP comes in two flavors: eBGP and iBGP.
-        The e/i stands for external/internal
-
-        External BGP sessions connect border routers in different ASes. These are therefore use to learn routes to
-        external destinatons
-
-        TODO: add graph
-
-        Internal BGP sessions connect the routers in the same AS. These are used to split up externally-learned routes
-        internally. These are tehn announces exernally(to other ASes) again, using eBGP sessions.
-
-        BGP itself is a pretty simple protocol composed of four basic messages:
-        - open: establish a BGP session (using TCP)
-        - notification: report unusual conditions
-        - update: inform neighbor of a new best route
-        - can be a change or a removal of a best route
-        - keepalive: inform neighbor that connection is alive
-
-        update messages carry an IP prefix together with a set of attributes:
-        /*********************/
-        /* IP prefix */
-        /*********************/
-        /* Attributes */
-        /* */
-        /* */
-        /* */
-        /* */
-        /*********************/
-
-        There are four types of different attributes:
-        - NEXT-HOP
-        - AS-PATH
-        - LOCAL-PREF
-        - MED
-      
-
-
- - - - \ No newline at end of file diff --git a/website/blog/posts/02.html b/website/blog/posts/02.html deleted file mode 100644 index 499aefa..0000000 --- a/website/blog/posts/02.html +++ /dev/null @@ -1 +0,0 @@ -JJ is is a new version control system, made to be compatible with git and _much_ less painful than it. \ No newline at end of file diff --git a/website/index.html b/website/index.html deleted file mode 100644 index ff6e4f0..0000000 --- a/website/index.html +++ /dev/null @@ -1,22 +0,0 @@ - - - - - - -
-

My Website

-

- Welcome to my website. Here I share some heartfelt ramblings about different things.
-

-
- -
-

Brain farts

-

2025

- I love JJ -
-
- - - \ No newline at end of file diff --git a/website/style.css b/website/style.css deleted file mode 100644 index 13dc9b8..0000000 --- a/website/style.css +++ /dev/null @@ -1,58 +0,0 @@ -* { - margin: 0px; - padding: 0px; - line-height: 1.4; -} - -h1 { - text-align: center; -} - -body { - color: #FFFFFF; - background-color: #000000; - font-family: sans-serif; - font-size: 12; -} - -.content { - margin: auto; - padding: 5px; - max-width: 45em; - padding: 1em; - /* width: 100%; */ - border: 3px solid darkred; - overflow: auto; -} - -/* .around { */ -/* border: 1px solid grey; */ -/* margin: auto; */ -/* max-width: 685px; */ -/* padding: 1px; */ -/* width: 100%; */ -/* text-align: center; */ -/* } */ - -.post { - width: 76ch; - word-break: break-all; - font: mo; -} - -.years { - padding: 4px; - border-bottom: solid gray; -} - -pre { - text-align: left; - color: black; - padding: 20px; - padding-top: 5px; - margin: 0px; - font-size: 12px; - text-decoration: none; - overflow: hidden; - background-color: white; -} \ No newline at end of file diff --git a/website/template.html b/website/template.html deleted file mode 100644 index 5b618f9..0000000 --- a/website/template.html +++ /dev/null @@ -1,19 +0,0 @@ - - - - - -
-
- Year - : [ - - ] -
-
-
-
- - - - \ No newline at end of file