diff --git a/.gitignore b/.gitignore index a806510..2921c4f 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ result result-* +install.log diff --git a/LICENSE b/LICENSE index 0f1f46f..85bc546 100644 --- a/LICENSE +++ b/LICENSE @@ -1,9 +1,21 @@ MIT License -Copyright (c) 2024 myned +Copyright (c) 2023 Myned -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: +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 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. +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. diff --git a/README.md b/README.md index 5327140..9fd00b1 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,114 @@ -# nixos +# Install -NixOS Configuration \ No newline at end of file +## Remote (with NixOS Anywhere) + +1. Clone this repository + + ```sh + git clone https://github.com/Myned/nixos + ``` + +2. Enable [Flakes](https://wiki.nixos.org/wiki/Flakes) + +3. Boot from NixOS [minimal installer](https://nixos.org/download.html#nixos-iso) + +4. Create machine-specific modules in `machines/MACHINE/` + + a. If [Home Manager](https://github.com/nix-community/home-manager), home configuration in `home.nix` + + b. System configuration and hostname in `system.nix` + + ```nix + { networking.hostName = "MACHINE"; } + ``` + + c. [Disko](https://github.com/nix-community/disko) layout in `disko.nix` + + ```sh + # Verify /dev identifier on machine + lsblk + + # Verify EFI/BIOS firmware on machine + [ -d /sys/firmware/efi/efivars ] && echo "UEFI" || echo "BIOS" + ``` + + d. Generated hardware configuration in `hardware-configuration.nix` + + ```sh + nixos-generate-config --show-hardware-config --no-filesystems --root /mnt + ``` + + e. Import modules in `default.nix` + +5. Choose profile and add machine-specific modules to `flake.in.nix` + + ```nix + MACHINE = linux [ ./profiles/PROFILE ./machines/MACHINE ]; + ``` + +6. Generate `flake.nix` with [flakegen](https://github.com/jorsn/flakegen) + + ```sh + git add . + nix run .#genflake flake.nix + nix flake lock + ``` + +7. Copy host public SSH key to root on machine + + ```sh + # On machine + sudo passwd root + ``` + + ```sh + # On host + ssh-copy-id root@MACHINE + ``` + +8. Test and execute [NixOS Anywhere](https://github.com/nix-community/nixos-anywhere) + + ```sh + nixos-anywhere --vm-test -f .#MACHINE root@IP + nixos-anywhere -f .#MACHINE root@IP + ``` + +9. Shutdown, detach ISO, and reboot + +## Local (with script) + +1. Clone repository using personal access token + + ```sh + git clone https://TOKEN@github.com/Myned/nixos /tmp/nixos + ``` + +2. Go to repository directory + + ```sh + cd /tmp/nixos + ``` + +3. Check disk layout + + ```sh + lsblk + ``` + +4. Modify disko layout to match hardware + + ```sh + nano machine/MACHINE/disko.nix + ``` + +5. Execute install script + + ```sh + sudo nix --experimental-features 'nix-command flakes' run nixpkgs#fish -- install.fish + ``` + +6. Optionally shred personal access token + + ```sh + shred -zu github.token + ``` diff --git a/configuration.nix b/configuration.nix new file mode 100644 index 0000000..24e49dc --- /dev/null +++ b/configuration.nix @@ -0,0 +1,192 @@ +{ + config, + inputs, + lib, + ... +}: + +{ + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "common/nix/access-tokens.conf" = secret "common/nix/access-tokens.conf"; + }; + + ### NixOS + nixpkgs = + let + config = { + allowUnfree = true; + + allowInsecurePredicate = + pkg: + let + name = lib.getName pkg; + in + # HACK: Allow all insecure electron versions + name == "electron" + + # HACK: Some Matrix clients rely on libolm, which is deprecated + # https://github.com/NixOS/nixpkgs/pull/334638 + || name == "cinny" + || name == "cinny-unwrapped" + || name == "fluffychat-linux" + || name == "olm" + || name == "openssl"; # Cisco Packet Tracer + }; + in + { + inherit config; + + overlays = [ + ( + final: prev: + let + nixpkgs = + branch: + import inputs."nixpkgs-${branch}" { + inherit config; + system = prev.system; + }; + + stable = nixpkgs "stable"; + unstable = nixpkgs "unstable"; + staging-next = nixpkgs "staging-next"; + local = nixpkgs "local"; + in + { + # Overlay nixpkgs branches + #?? nixpkgs.BRANCH.PACKAGE + inherit stable unstable staging-next; + + # Hypr* + hypridle = inputs.hypridle.packages.${prev.system}.default; + hyprland = inputs.hyprland.packages.${prev.system}.default; + hyprlock = inputs.hyprlock.packages.${prev.system}.default; + + # TODO: Remove when merged into unstable + # https://github.com/NixOS/nixpkgs/pull/338836 + xdg-desktop-portal-hyprland = + inputs.xdg-desktop-portal-hyprland.packages.${prev.system}.xdg-desktop-portal-hyprland; + + hyprlandPlugins = { + hyprbars = inputs.hyprland-plugins.packages.${prev.system}.hyprbars; + }; + + # Development + ciscoPacketTracer8 = local.ciscoPacketTracer8; + } + ) + ]; + }; + + nix = { + #!! Override upstream nix + # TODO: Try lix v2.92.0 + # https://git.lix.systems/lix-project/lix + #// package = pkgs.lix; + + # BUG: Absolute paths are forbidden in pure mode + # https://github.com/NixOS/nix/issues/11030 + #// package = pkgs.nixVersions.latest; + + #// optimise.automatic = true; # Run storage optimizer periodically + + # https://nix.dev/manual/nix/latest/command-ref/conf-file.html + # https://nix.dev/manual/nix/2.18/command-ref/conf-file.html for Lix + settings = { + auto-optimise-store = true; # Run optimizer during build + fallback = true; # Build from source if cache timeout reached + log-lines = 1000; # Build failure log length + min-free = 1024 * 1024 * 1024; # Trigger garbage collection at 1 GB space remaining + warn-dirty = false; # Git tree is usually dirty + experimental-features = [ + "nix-command" + "flakes" + ]; + + # Binary caches + trusted-users = [ + "root" + "@wheel" + ]; + + trusted-substituters = [ + "https://anyrun.cachix.org" + "https://attic.kennel.juneis.dog/conduwuit" + "https://ezkea.cachix.org" + "https://hyprland.cachix.org" + "https://nix-community.cachix.org" + ]; + + trusted-public-keys = [ + "anyrun.cachix.org-1:pqBobmOjI7nKlsUMV25u9QHa9btJK65/C8vnO3p346s=" + "conduwuit:BbycGUgTISsltcmH0qNjFR9dbrQNYgdIAcmViSGoVTE=" + "ezkea.cachix.org-1:ioBmUbJTZIKsHmWWXPe1FSFbeVe+afhfgqgTSNd34eI=" + "hyprland.cachix.org-1:a7pgxzMz7+chwVL3/pzj6jIBMioiJM7ypFP8PwtkuGc=" + "nix-community.cachix.org-1:mB9FSh9qf2dCimDSUo8Zy7bkq5CX+/rkCWyvRCYg3Fs=" + ]; + }; + + #!! Handled by programs.nh.clean + # Garbage collection + # gc = { + # automatic = true; + # dates = "weekly"; + # options = "--delete-older-than 7d"; # Delete old generations + # }; + + # API access tokens to increase rate limits + # https://nix.dev/manual/nix/latest/command-ref/conf-file#conf-access-tokens + # https://github.com/NixOS/nix/issues/6536#issuecomment-1254858889 + # https://github.com/settings/tokens + extraOptions = "!include ${config.age.secrets."common/nix/access-tokens.conf".path}"; + }; + + system = { + nixos.label = ""; # Partially clean up boot entries + + #!! DO NOT MODIFY ### + stateVersion = "23.11"; + #!! ############# ### + }; + + ### Home Manager + # https://nix-community.github.io/home-manager/index.xhtml#sec-install-nixos-module + home-manager = { + backupFileExtension = "bak"; + useGlobalPkgs = true; + useUserPackages = true; + + extraSpecialArgs = { + inherit inputs; + }; + + users.${config.custom.username} = { + programs.home-manager.enable = true; + systemd.user.startServices = "sd-switch"; # Start/stop user services immediately + + # Inherit configuration.nix + nixpkgs.config = config.nixpkgs.config; + + nix.gc = { + automatic = config.nix.gc.automatic; + frequency = config.nix.gc.dates; + options = config.nix.gc.options; + }; + + home = { + username = config.custom.username; + homeDirectory = "/home/${config.custom.username}"; + + #!! DO NOT MODIFY ### + stateVersion = "23.11"; + #!! ############# ### + }; + }; + }; +} diff --git a/flake.in.nix b/flake.in.nix new file mode 100644 index 0000000..9267a3e --- /dev/null +++ b/flake.in.nix @@ -0,0 +1,193 @@ +# !! Generate flake.nix +# https://github.com/jorsn/flakegen +#?? rm flake.nix +#?? nix flake init -t github:jorsn/flakegen +#?? git add . +#?? nix run .#genflake flake.nix +# TODO: Remove flakegen hook when nix expressions are officially implemented +# https://github.com/NixOS/nix/issues/3966 + +{ + # https://wiki.nixos.org/wiki/Flakes + # https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-flake.html + inputs = + let + flake = url: { inherit url; }; + follows = input: { inputs.${input}.follows = input; }; + stable = input: { inputs.${input}.follows = "${input}-stable"; }; + unstable = input: { inputs.${input}.follows = "${input}-unstable"; }; + + source = url: { + inherit url; + flake = false; + }; + in + { + #?? branch = "git+https://REPO?ref=BRANCH" + #?? commit = "git+https://REPO?ref=BRANCH&rev=COMMIT" + #?? tag = "git+https://REPO?ref=refs/tags/TAG" + + ### Standalone + nixos-hardware = flake "github:NixOS/nixos-hardware"; + + ### Stable + nixpkgs-stable = flake "github:NixOS/nixpkgs/nixos-24.05"; + + # Common flakes + home-manager-stable = flake "github:nix-community/home-manager/release-24.05" // stable "nixpkgs"; + nix-index-database-stable = flake "github:nix-community/nix-index-database" // stable "nixpkgs"; + + # Desktop flakes + aagl-gtk-on-nix-stable = flake "github:ezKEa/aagl-gtk-on-nix/release-24.05" // stable "nixpkgs"; + + ### Unstable + nixpkgs-unstable = flake "github:NixOS/nixpkgs/nixos-unstable"; + + # Common flakes + agenix = flake "github:ryantm/agenix" // unstable "nixpkgs"; + arion = flake "github:hercules-ci/arion" // unstable "nixpkgs"; + compose2nix = flake "github:aksiksi/compose2nix" // unstable "nixpkgs"; + disko = flake "github:nix-community/disko" // unstable "nixpkgs"; + home-manager-unstable = flake "github:nix-community/home-manager" // unstable "nixpkgs"; + nix-index-database-unstable = flake "github:nix-community/nix-index-database" // unstable "nixpkgs"; + + # Console flakes + jovian-nixos = flake "github:Jovian-Experiments/Jovian-NixOS" // unstable "nixpkgs"; + + # Desktop flakes + aagl-gtk-on-nix-unstable = flake "github:ezKEa/aagl-gtk-on-nix" // unstable "nixpkgs"; + ags = flake "github:Aylur/ags" // unstable "nixpkgs"; + anyrun = flake "github:Kirottu/anyrun" // unstable "nixpkgs"; + bitwarden-menu = flake "github:firecat53/bitwarden-menu" // unstable "nixpkgs"; + fw-fanctrl = flake "github:TamtamHero/fw-fanctrl/packaging/nix" // unstable "nixpkgs"; + hypridle = flake "github:hyprwm/hypridle" // unstable "nixpkgs"; + hyprland = flake "git+https://github.com/hyprwm/Hyprland?submodules=1" // unstable "nixpkgs"; + # hyprland = + # flake "git+https://github.com/hyprwm/Hyprland?ref=refs/tags/v0.41.2&submodules=1" + # // unstable "nixpkgs"; + # hyprland = + # flake "git+https://github.com/UjinT34/Hyprland?ref=vrr-cursor-fix&submodules=1" + # // unstable "nixpkgs"; + hyprland-contrib = flake "github:hyprwm/contrib" // unstable "nixpkgs"; + hyprland-plugins = + flake "github:hyprwm/hyprland-plugins" // unstable "nixpkgs" // follows "hyprland"; + hyprlock = flake "github:hyprwm/hyprlock" // unstable "nixpkgs"; + hyprpaper = flake "github:hyprwm/hyprpaper" // unstable "nixpkgs"; + hyprpicker = flake "github:hyprwm/hyprpicker" // unstable "nixpkgs"; + nix-flatpak = flake "github:gmodena/nix-flatpak?ref=v0.4.1"; + nix-vscode-extensions = flake "github:nix-community/nix-vscode-extensions" // unstable "nixpkgs"; + nixd = flake "github:nix-community/nixd" // unstable "nixpkgs"; + xdg-desktop-portal-hyprland = + flake "github:hyprwm/xdg-desktop-portal-hyprland" + // unstable "nixpkgs"; + + # Server flakes + conduwuit = flake "github:Myned/conduwuit" // unstable "nixpkgs"; + + ### Staging + nixpkgs-staging-next = flake "github:NixOS/nixpkgs/staging-next"; + + ### Development + nixpkgs-local = flake "git+file:///home/myned/.dev/nixpkgs?ref=7849cd48822de4dc0515c787b20dc85de30acdca"; + #// hyprland = flake "git+file:///home/myned/.dev/Hyprland?submodules=1"; + + ### Source code + firefox-gnome-theme = source "github:rafaelmardojai/firefox-gnome-theme/v128"; + lifx-cli = source "github:Rawa/lifx-cli"; + steamtinkerlaunch = source "github:sonic2kk/steamtinkerlaunch"; + thunderbird-gnome-theme = source "github:rafaelmardojai/thunderbird-gnome-theme"; + virtio-win = source "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.262-2/virtio-win.iso"; + }; + + outputs = inputs: { + # TODO: Use forAllSystems + # https://nix.dev/manual/nix/2.18/command-ref/new-cli/nix3-fmt + formatter.x86_64-linux = inputs.nixpkgs-unstable.legacyPackages.x86_64-linux.nixfmt-rfc-style; + + nixosConfigurations = + let + # TODO: Use inline modules instead of specialArgs + # https://jade.fyi/blog/flakes-arent-real#nixos-modules + # Boilerplate systems with global imports + #!! There is no default nixpkgs, inputs.-BRANCH must exist + #?? branch = common "BRANCH" "ARCHITECTURE" [ MODULES ] + common = + branch: arch: modules: + inputs."nixpkgs-${branch}".lib.nixosSystem { + system = arch; + + specialArgs = { + inherit inputs; + }; + + # TODO: Clean up optional attributes with each new release + #!! Options will diverge between branches over time + #?? with lib; optionalAttrs (versionAtLeast version "VERSION") { ... }; + modules = modules ++ [ + ./options + ./configuration.nix + + #!! Avoid globally importing modules that are not guarded by .enable + # https://github.com/NixOS/nixpkgs/issues/137168 + ( + { config, inputs, ... }: + + { + imports = [ + inputs."aagl-gtk-on-nix-${branch}".nixosModules.default + inputs."home-manager-${branch}".nixosModules.home-manager + inputs."nix-index-database-${branch}".nixosModules.nix-index + inputs.agenix.nixosModules.default + inputs.arion.nixosModules.arion + inputs.disko.nixosModules.disko + inputs.fw-fanctrl.nixosModules.default + inputs.nix-flatpak.nixosModules.nix-flatpak + ]; + + home-manager.users.${config.custom.username}.imports = [ + inputs."nix-index-database-${branch}".hmModules.nix-index + ]; + } + ) + ]; + }; + + #?? system = branch "ARCHITECTURE" [ MODULES ] + stable = arch: modules: common "stable" "${arch}-linux" modules; + unstable = arch: modules: common "unstable" "${arch}-linux" modules; + in + { + ### Stable + myarm = stable "aarch64" [ + ./profiles/server + ./machines/myarm + ]; + + myne = stable "x86_64" [ + ./profiles/server + ./machines/myne + ]; + + mypi3 = stable "aarch64" [ + ./profiles/sbc + ./machines/mypi3 + ]; + + ### Unstable + myeck = unstable "x86_64" [ + ./profiles/console + ./machines/myeck + ]; + + mynix = unstable "x86_64" [ + ./profiles/desktop + ./machines/mynix + ]; + + myork = unstable "x86_64" [ + ./profiles/laptop + ./machines/myork + ]; + }; + }; +} diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..8be515a --- /dev/null +++ b/flake.lock @@ -0,0 +1,2611 @@ +{ + "nodes": { + "aagl-gtk-on-nix-stable": { + "inputs": { + "flake-compat": "flake-compat", + "nixpkgs": [ + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1725308061, + "narHash": "sha256-lTGO3P9Ir2ofgOqr0LxZ31IqXS9b3YbAGzVRjgw0Rjo=", + "owner": "ezKEa", + "repo": "aagl-gtk-on-nix", + "rev": "1645aa494fa5f409360bfeba99f6eaf807f83ed4", + "type": "github" + }, + "original": { + "owner": "ezKEa", + "ref": "release-24.05", + "repo": "aagl-gtk-on-nix", + "type": "github" + } + }, + "aagl-gtk-on-nix-unstable": { + "inputs": { + "flake-compat": "flake-compat_2", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725307913, + "narHash": "sha256-Slc+vPJFiarviylZsq3FgaWRPeeKHTrT6J0NpHvDfgg=", + "owner": "ezKEa", + "repo": "aagl-gtk-on-nix", + "rev": "f8e7957aa7d4651d5df7b50299cb9b6f4b51adfc", + "type": "github" + }, + "original": { + "owner": "ezKEa", + "repo": "aagl-gtk-on-nix", + "type": "github" + } + }, + "agenix": { + "inputs": { + "darwin": "darwin", + "home-manager": "home-manager", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems" + }, + "locked": { + "lastModified": 1723293904, + "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", + "owner": "ryantm", + "repo": "agenix", + "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", + "type": "github" + }, + "original": { + "owner": "ryantm", + "repo": "agenix", + "type": "github" + } + }, + "ags": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_2" + }, + "locked": { + "lastModified": 1721306136, + "narHash": "sha256-VKPsIGf3/a+RONBipx4lEE4LXG2sdMNkWQu22LNQItg=", + "owner": "Aylur", + "repo": "ags", + "rev": "344ea72cd3b8d4911f362fec34bce7d8fb37028c", + "type": "github" + }, + "original": { + "owner": "Aylur", + "repo": "ags", + "type": "github" + } + }, + "anyrun": { + "inputs": { + "flake-parts": "flake-parts", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_3" + }, + "locked": { + "lastModified": 1721135360, + "narHash": "sha256-ZhSA0e45UxiOAjEVqkym/aULh0Dt+KHJLNda7bjx9UI=", + "owner": "Kirottu", + "repo": "anyrun", + "rev": "c6101a31a80b51e32e96f6a77616b609770172e0", + "type": "github" + }, + "original": { + "owner": "Kirottu", + "repo": "anyrun", + "type": "github" + } + }, + "aquamarine": { + "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "hyprwayland-scanner": [ + "hyprland", + "hyprwayland-scanner" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1725199881, + "narHash": "sha256-jsmipf/u1GFZE5tBUkr56CHMN6VpUWCAjfLIhvQijU0=", + "owner": "hyprwm", + "repo": "aquamarine", + "rev": "f8a687dd29ff019657498f1bd14da2fbbf0e604b", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "aquamarine", + "type": "github" + } + }, + "arion": { + "inputs": { + "flake-parts": "flake-parts_2", + "haskell-flake": "haskell-flake", + "hercules-ci-effects": "hercules-ci-effects", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1722825873, + "narHash": "sha256-bFNXkD+s9NuidZePiJAjjFUnsMOwXb7hEZ4JEDdSALw=", + "owner": "hercules-ci", + "repo": "arion", + "rev": "90bc85532767c785245f5c1e29ebfecb941cf8c9", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "arion", + "type": "github" + } + }, + "attic": { + "inputs": { + "crane": "crane", + "flake-compat": "flake-compat_3", + "flake-utils": "flake-utils_2", + "nixpkgs": "nixpkgs", + "nixpkgs-stable": "nixpkgs-stable" + }, + "locked": { + "lastModified": 1724226964, + "narHash": "sha256-cltFh4su2vcFidxKp7LuEgX3ZGLfPy0DCdrQZ/QTe68=", + "owner": "zhaofengli", + "repo": "attic", + "rev": "6d9aeaef0a067d664cb11bb7704f7ec373d47fb2", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "main", + "repo": "attic", + "type": "github" + } + }, + "bitwarden-menu": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1711659384, + "narHash": "sha256-0hESRWYaH7KwBP4Agw2Nt2PT567A7/RsdipPIW4o2UY=", + "owner": "firecat53", + "repo": "bitwarden-menu", + "rev": "370920fab4c05fffafecd1990c49f01805130ae2", + "type": "github" + }, + "original": { + "owner": "firecat53", + "repo": "bitwarden-menu", + "type": "github" + } + }, + "cachix": { + "inputs": { + "devenv": "devenv", + "flake-compat": "flake-compat_5", + "git-hooks": "git-hooks", + "nixpkgs": "nixpkgs_3" + }, + "locked": { + "lastModified": 1724232775, + "narHash": "sha256-6u2DycIEgrgNYlLxyGqdFVmBNiKIitnQKJ1pbRP5oko=", + "owner": "cachix", + "repo": "cachix", + "rev": "03b6cb3f953097bff378fb8b9ea094bd091a4ec7", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "master", + "repo": "cachix", + "type": "github" + } + }, + "cachix_2": { + "inputs": { + "devenv": "devenv_2", + "flake-compat": [ + "conduwuit", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "conduwuit", + "cachix", + "devenv", + "nixpkgs" + ], + "pre-commit-hooks": [ + "conduwuit", + "cachix", + "devenv", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1712055811, + "narHash": "sha256-7FcfMm5A/f02yyzuavJe06zLa9hcMHsagE28ADcmQvk=", + "owner": "cachix", + "repo": "cachix", + "rev": "02e38da89851ec7fec3356a5c04bc8349cae0e30", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "cachix", + "type": "github" + } + }, + "complement": { + "flake": false, + "locked": { + "lastModified": 1722323564, + "narHash": "sha256-6w6/N8walz4Ayc9zu7iySqJRmGFukhkaICLn4dweAcA=", + "owner": "matrix-org", + "repo": "complement", + "rev": "6e4426a9e63233f9821a4d2382bfed145244183f", + "type": "github" + }, + "original": { + "owner": "matrix-org", + "ref": "main", + "repo": "complement", + "type": "github" + } + }, + "compose2nix": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ], + "onchg": "onchg" + }, + "locked": { + "lastModified": 1725129412, + "narHash": "sha256-gr9ln5YklrMXR0x5emR7ap4/ZKFgic/5QwT7UrMadRg=", + "owner": "aksiksi", + "repo": "compose2nix", + "rev": "971f843acd3c25ed32272257a9a648b7d10858c1", + "type": "github" + }, + "original": { + "owner": "aksiksi", + "repo": "compose2nix", + "type": "github" + } + }, + "conduwuit": { + "inputs": { + "attic": "attic", + "cachix": "cachix", + "complement": "complement", + "crane": "crane_2", + "fenix": "fenix", + "flake-compat": "flake-compat_6", + "flake-utils": "flake-utils_4", + "liburing": "liburing", + "nix-filter": "nix-filter", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "rocksdb": "rocksdb" + }, + "locked": { + "lastModified": 1725209064, + "narHash": "sha256-ut3IWEueNR/hT7NyGfuK5IYtppC6ArSoJdEfFuD/0vE=", + "owner": "Myned", + "repo": "conduwuit", + "rev": "8f7ade4c22533a3177bfd8f175e178573ba6c1d4", + "type": "github" + }, + "original": { + "owner": "Myned", + "repo": "conduwuit", + "type": "github" + } + }, + "crane": { + "inputs": { + "nixpkgs": [ + "conduwuit", + "attic", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722960479, + "narHash": "sha256-NhCkJJQhD5GUib8zN9JrmYGMwt4lCRp6ZVNzIiYCl0Y=", + "owner": "ipetkov", + "repo": "crane", + "rev": "4c6c77920b8d44cd6660c1621dea6b3fc4b4c4f4", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "repo": "crane", + "type": "github" + } + }, + "crane_2": { + "inputs": { + "nixpkgs": [ + "conduwuit", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724006180, + "narHash": "sha256-PVxPj0Ga2fMYMtcT9ARCthF+4U71YkOT7ZjgD/vf1Aw=", + "owner": "ipetkov", + "repo": "crane", + "rev": "7ce92819802bc583b7e82ebc08013a530f22209f", + "type": "github" + }, + "original": { + "owner": "ipetkov", + "ref": "master", + "repo": "crane", + "type": "github" + } + }, + "darwin": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1700795494, + "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=", + "owner": "lnl7", + "repo": "nix-darwin", + "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d", + "type": "github" + }, + "original": { + "owner": "lnl7", + "ref": "master", + "repo": "nix-darwin", + "type": "github" + } + }, + "devenv": { + "inputs": { + "cachix": "cachix_2", + "flake-compat": [ + "conduwuit", + "cachix", + "flake-compat" + ], + "nix": "nix_2", + "nixpkgs": [ + "conduwuit", + "cachix", + "nixpkgs" + ], + "pre-commit-hooks": [ + "conduwuit", + "cachix", + "git-hooks" + ] + }, + "locked": { + "lastModified": 1723156315, + "narHash": "sha256-0JrfahRMJ37Rf1i0iOOn+8Z4CLvbcGNwa2ChOAVrp/8=", + "owner": "cachix", + "repo": "devenv", + "rev": "ff5eb4f2accbcda963af67f1a1159e3f6c7f5f91", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "devenv", + "type": "github" + } + }, + "devenv_2": { + "inputs": { + "flake-compat": [ + "conduwuit", + "cachix", + "devenv", + "cachix", + "flake-compat" + ], + "nix": "nix", + "nixpkgs": "nixpkgs_2", + "poetry2nix": "poetry2nix", + "pre-commit-hooks": [ + "conduwuit", + "cachix", + "devenv", + "cachix", + "pre-commit-hooks" + ] + }, + "locked": { + "lastModified": 1708704632, + "narHash": "sha256-w+dOIW60FKMaHI1q5714CSibk99JfYxm0CzTinYWr+Q=", + "owner": "cachix", + "repo": "devenv", + "rev": "2ee4450b0f4b95a1b90f2eb5ffea98b90e48c196", + "type": "github" + }, + "original": { + "owner": "cachix", + "ref": "python-rewrite", + "repo": "devenv", + "type": "github" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725377834, + "narHash": "sha256-tqoAO8oT6zEUDXte98cvA1saU9+1dLJQe3pMKLXv8ps=", + "owner": "nix-community", + "repo": "disko", + "rev": "e55f9a8678adc02024a4877c2a403e3f6daf24fe", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "type": "github" + } + }, + "fenix": { + "inputs": { + "nixpkgs": [ + "conduwuit", + "nixpkgs" + ], + "rust-analyzer-src": "rust-analyzer-src" + }, + "locked": { + "lastModified": 1724221791, + "narHash": "sha256-mKX67QPnUybOopVph/LhOV1G/H4EvPxDIfSmbufrVdA=", + "owner": "nix-community", + "repo": "fenix", + "rev": "e88b38a5a3834e039d413a88f8150a75ef6453ef", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "main", + "repo": "fenix", + "type": "github" + } + }, + "firefox-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1721054065, + "narHash": "sha256-zB+Zd0V0ayKP/zg9n1MQ8J/Znwa49adylRftxuc694k=", + "owner": "rafaelmardojai", + "repo": "firefox-gnome-theme", + "rev": "c36cd1a35062ef0f7e37ff904e94e50d3c84373c", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "ref": "v128", + "repo": "firefox-gnome-theme", + "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": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_3": { + "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_4": { + "flake": false, + "locked": { + "lastModified": 1673956053, + "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", + "type": "github" + }, + "original": { + "owner": "edolstra", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_5": { + "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_6": { + "flake": false, + "locked": { + "lastModified": 1696426674, + "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=", + "owner": "edolstra", + "repo": "flake-compat", + "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33", + "type": "github" + }, + "original": { + "owner": "edolstra", + "ref": "master", + "repo": "flake-compat", + "type": "github" + } + }, + "flake-compat_7": { + "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_8": { + "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-parts": { + "inputs": { + "nixpkgs-lib": [ + "anyrun", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1717285511, + "narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_2": { + "inputs": { + "nixpkgs-lib": [ + "arion", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722555600, + "narHash": "sha256-XOQkdLafnb/p9ij77byFQjDf5m5QYl9b2REiVClC+x4=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "8471fe90ad337a8074e957b69ca4d0089218391d", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-parts_3": { + "inputs": { + "nixpkgs-lib": [ + "arion", + "hercules-ci-effects", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1712014858, + "narHash": "sha256-sB4SWl2lX95bExY2gMFG5HIzvva5AVMJd4Igm+GpZNw=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "9126214d0a59633752a136528f5f3b9aa8565b7d", + "type": "github" + }, + "original": { + "id": "flake-parts", + "type": "indirect" + } + }, + "flake-parts_4": { + "inputs": { + "nixpkgs-lib": "nixpkgs-lib" + }, + "locked": { + "lastModified": 1714606777, + "narHash": "sha256-bMkNmAXLj8iyTvxaaD/StcLSadbj1chPcJOjtuVnLmA=", + "owner": "hercules-ci", + "repo": "flake-parts", + "rev": "4d34ce6412bc450b1d4208c953dc97c7fc764f1a", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "flake-parts", + "type": "github" + } + }, + "flake-root": { + "locked": { + "lastModified": 1713493429, + "narHash": "sha256-ztz8JQkI08tjKnsTpfLqzWoKFQF4JGu2LRz8bkdnYUk=", + "owner": "srid", + "repo": "flake-root", + "rev": "bc748b93b86ee76e2032eecda33440ceb2532fcd", + "type": "github" + }, + "original": { + "owner": "srid", + "repo": "flake-root", + "type": "github" + } + }, + "flake-utils": { + "locked": { + "lastModified": 1652776076, + "narHash": "sha256-gzTw/v1vj4dOVbpBSJX4J0DwUR6LIyXo7/SuuTJp1kM=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "04c1b180862888302ddfb2e3ad9eaa63afc60cf8", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_2": { + "inputs": { + "systems": "systems_4" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_3": { + "inputs": { + "systems": "systems_5" + }, + "locked": { + "lastModified": 1689068808, + "narHash": "sha256-6ixXo3wt24N/melDWjq70UuHQLxGV8jZvooRanIHXw0=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "919d646de7be200f3bf08cb76ae1f09402b6f9b4", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_4": { + "inputs": { + "systems": "systems_6" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "flake-utils", + "type": "github" + } + }, + "flake-utils_5": { + "inputs": { + "systems": "systems_13" + }, + "locked": { + "lastModified": 1710146030, + "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + }, + "flakegen": { + "inputs": { + "systems": "systems_7" + }, + "locked": { + "lastModified": 1707120544, + "narHash": "sha256-pXwH9NLXjhjnaz1n7w5m36gVUZ1GVkvtltsLnvVPFJY=", + "owner": "jorsn", + "repo": "flakegen", + "rev": "8b11749b0724700273462a674dd16e5549fe2790", + "type": "github" + }, + "original": { + "owner": "jorsn", + "repo": "flakegen", + "type": "github" + } + }, + "fw-fanctrl": { + "inputs": { + "flake-compat": "flake-compat_7", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1724704488, + "narHash": "sha256-QmAanotjk81zsCwHI52XS4u9Cjv6KjNzTkYsAYFrubM=", + "owner": "TamtamHero", + "repo": "fw-fanctrl", + "rev": "db96c5962cff24f4c5977e30ca1c7626fb4171c7", + "type": "github" + }, + "original": { + "owner": "TamtamHero", + "ref": "packaging/nix", + "repo": "fw-fanctrl", + "type": "github" + } + }, + "git-hooks": { + "inputs": { + "flake-compat": [ + "conduwuit", + "cachix", + "flake-compat" + ], + "gitignore": "gitignore", + "nixpkgs": [ + "conduwuit", + "cachix", + "nixpkgs" + ], + "nixpkgs-stable": "nixpkgs-stable_2" + }, + "locked": { + "lastModified": 1723202784, + "narHash": "sha256-qbhjc/NEGaDbyy0ucycubq4N3//gDFFH3DOmp1D3u1Q=", + "owner": "cachix", + "repo": "git-hooks.nix", + "rev": "c7012d0c18567c889b948781bc74a501e92275d1", + "type": "github" + }, + "original": { + "owner": "cachix", + "repo": "git-hooks.nix", + "type": "github" + } + }, + "gitignore": { + "inputs": { + "nixpkgs": [ + "conduwuit", + "cachix", + "git-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" + } + }, + "haskell-flake": { + "locked": { + "lastModified": 1675296942, + "narHash": "sha256-u1X1sblozi5qYEcLp1hxcyo8FfDHnRUVX3dJ/tW19jY=", + "owner": "srid", + "repo": "haskell-flake", + "rev": "c2cafce9d57bfca41794dc3b99c593155006c71e", + "type": "github" + }, + "original": { + "owner": "srid", + "ref": "0.1.0", + "repo": "haskell-flake", + "type": "github" + } + }, + "hercules-ci-effects": { + "inputs": { + "flake-parts": "flake-parts_3", + "nixpkgs": [ + "arion", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1719226092, + "narHash": "sha256-YNkUMcCUCpnULp40g+svYsaH1RbSEj6s4WdZY/SHe38=", + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "rev": "11e4b8dc112e2f485d7c97e1cee77f9958f498f5", + "type": "github" + }, + "original": { + "owner": "hercules-ci", + "repo": "hercules-ci-effects", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "agenix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1703113217, + "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager-stable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1720042825, + "narHash": "sha256-A0vrUB6x82/jvf17qPCpxaM+ulJnD8YZwH9Ci0BsAzE=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "e1391fb22e18a36f57e6999c7a9f966dc80ac073", + "type": "github" + }, + "original": { + "owner": "nix-community", + "ref": "release-24.05", + "repo": "home-manager", + "type": "github" + } + }, + "home-manager-unstable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725180166, + "narHash": "sha256-fzssXuGR/mCeGbzM1ExaTqDz7QDGta3WA4jJsZyRruo=", + "owner": "nix-community", + "repo": "home-manager", + "rev": "471e3eb0a114265bcd62d11d58ba8d3421ee68eb", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "home-manager", + "type": "github" + } + }, + "hyprcursor": { + "inputs": { + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1722623071, + "narHash": "sha256-sLADpVgebpCBFXkA1FlCXtvEPu1tdEsTfqK1hfeHySE=", + "owner": "hyprwm", + "repo": "hyprcursor", + "rev": "912d56025f03d41b1ad29510c423757b4379eb1c", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprcursor", + "type": "github" + } + }, + "hypridle": { + "inputs": { + "hyprlang": "hyprlang", + "hyprutils": "hyprutils", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_8" + }, + "locked": { + "lastModified": 1725204025, + "narHash": "sha256-DdPf2Hm/ywtXqQutmxuzvMLgTzuV1nuzbrsahyhB8uU=", + "owner": "hyprwm", + "repo": "hypridle", + "rev": "22b058b47a57b609e00c5c8a90697f33c7fe1fd3", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hypridle", + "type": "github" + } + }, + "hyprland": { + "inputs": { + "aquamarine": "aquamarine", + "hyprcursor": "hyprcursor", + "hyprlang": "hyprlang_2", + "hyprutils": "hyprutils_2", + "hyprwayland-scanner": "hyprwayland-scanner", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_9", + "xdph": "xdph" + }, + "locked": { + "lastModified": 1725580992, + "narHash": "sha256-0g6lzfyIcRaHlDuiWTVy9ZGWtIhIpdqHUTTGtAVR+4Q=", + "ref": "refs/heads/main", + "rev": "b0fca6eaf00a2c5061f499c76ec8d60772b6a719", + "revCount": 5191, + "submodules": true, + "type": "git", + "url": "https://github.com/hyprwm/Hyprland" + }, + "original": { + "submodules": true, + "type": "git", + "url": "https://github.com/hyprwm/Hyprland" + } + }, + "hyprland-contrib": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725551787, + "narHash": "sha256-6LgsZHz8w3g4c9bRUwRAR+WIMwFGGf3P1VZQcKNRf2o=", + "owner": "hyprwm", + "repo": "contrib", + "rev": "1e531dc49ad36c88b45bf836081a7a2c8927e072", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "contrib", + "type": "github" + } + }, + "hyprland-plugins": { + "inputs": { + "hyprland": [ + "hyprland" + ], + "nixpkgs": [ + "hyprland-plugins", + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland-plugins", + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1723143591, + "narHash": "sha256-dPcWAeRJoG5CyWC32X3XX+Og0v/k1/S1N0T5dQWT32k=", + "owner": "hyprwm", + "repo": "hyprland-plugins", + "rev": "b73d7b901d8cb1172dd25c7b7159f0242c625a77", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-plugins", + "type": "github" + } + }, + "hyprland-protocols": { + "inputs": { + "nixpkgs": [ + "hyprland", + "xdph", + "nixpkgs" + ], + "systems": [ + "hyprland", + "xdph", + "systems" + ] + }, + "locked": { + "lastModified": 1721326555, + "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprland-protocols_2": { + "inputs": { + "nixpkgs": [ + "xdg-desktop-portal-hyprland", + "nixpkgs" + ], + "systems": [ + "xdg-desktop-portal-hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1721326555, + "narHash": "sha256-zCu4R0CSHEactW9JqYki26gy8h9f6rHmSwj4XJmlHgg=", + "owner": "hyprwm", + "repo": "hyprland-protocols", + "rev": "5a11232266bf1a1f5952d5b179c3f4b2facaaa84", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprland-protocols", + "type": "github" + } + }, + "hyprlang": { + "inputs": { + "hyprutils": [ + "hypridle", + "hyprutils" + ], + "nixpkgs": [ + "hypridle", + "nixpkgs" + ], + "systems": [ + "hypridle", + "systems" + ] + }, + "locked": { + "lastModified": 1721324361, + "narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_2": { + "inputs": { + "hyprutils": [ + "hyprland", + "hyprutils" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1725188252, + "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_3": { + "inputs": { + "hyprutils": [ + "hyprlock", + "hyprutils" + ], + "nixpkgs": [ + "hyprlock", + "nixpkgs" + ], + "systems": [ + "hyprlock", + "systems" + ] + }, + "locked": { + "lastModified": 1721324361, + "narHash": "sha256-BiJKO0IIdnSwHQBSrEJlKlFr753urkLE48wtt0UhNG4=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "adbefbf49664a6c2c8bf36b6487fd31e3eb68086", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_4": { + "inputs": { + "hyprutils": [ + "hyprpaper", + "hyprutils" + ], + "nixpkgs": [ + "hyprpaper", + "nixpkgs" + ], + "systems": [ + "hyprpaper", + "systems" + ] + }, + "locked": { + "lastModified": 1725188252, + "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlang_5": { + "inputs": { + "hyprutils": "hyprutils_6", + "nixpkgs": [ + "xdg-desktop-portal-hyprland", + "nixpkgs" + ], + "systems": "systems_14" + }, + "locked": { + "lastModified": 1725188252, + "narHash": "sha256-yBH8c4GDaEAtBrh+BqIlrx5vp6gG/Gu8fQQK63KAQgs=", + "owner": "hyprwm", + "repo": "hyprlang", + "rev": "c12ab785ce1982f82594aff03b3104c598186ddd", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlang", + "type": "github" + } + }, + "hyprlock": { + "inputs": { + "hyprlang": "hyprlang_3", + "hyprutils": "hyprutils_3", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_10" + }, + "locked": { + "lastModified": 1725535663, + "narHash": "sha256-hsvbU1utffVOFTRa3arPepv8en42VltR33L72vK3QVo=", + "owner": "hyprwm", + "repo": "hyprlock", + "rev": "153977aab35a72f3e142e32aed6b268b659d18e1", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprlock", + "type": "github" + } + }, + "hyprpaper": { + "inputs": { + "hyprlang": "hyprlang_4", + "hyprutils": "hyprutils_4", + "hyprwayland-scanner": "hyprwayland-scanner_2", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_11" + }, + "locked": { + "lastModified": 1725200438, + "narHash": "sha256-3Cqu8jz19YyWqhneac6QFfadlyxZ4s3saSLmmpYMOe4=", + "owner": "hyprwm", + "repo": "hyprpaper", + "rev": "1c18ad65032adb891b341292a1edf9e13adf4751", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprpaper", + "type": "github" + } + }, + "hyprpicker": { + "inputs": { + "hyprutils": "hyprutils_5", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_12" + }, + "locked": { + "lastModified": 1724326010, + "narHash": "sha256-84Zzoi6bWAnDKDxoqiv3DCIjQmP1Y8vynP6//Wtnpc4=", + "owner": "hyprwm", + "repo": "hyprpicker", + "rev": "38fe668e58014c75cf28f7cb5fc136aa710e7039", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprpicker", + "type": "github" + } + }, + "hyprutils": { + "inputs": { + "nixpkgs": [ + "hypridle", + "nixpkgs" + ], + "systems": [ + "hypridle", + "systems" + ] + }, + "locked": { + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "962582a090bc233c4de9d9897f46794280288989", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_2": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1724966483, + "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_3": { + "inputs": { + "nixpkgs": [ + "hyprlock", + "nixpkgs" + ], + "systems": [ + "hyprlock", + "systems" + ] + }, + "locked": { + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "962582a090bc233c4de9d9897f46794280288989", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_4": { + "inputs": { + "nixpkgs": [ + "hyprpaper", + "nixpkgs" + ], + "systems": [ + "hyprpaper", + "systems" + ] + }, + "locked": { + "lastModified": 1724966483, + "narHash": "sha256-WXDgKIbzjYKczxSZOsJplCS1i1yrTUpsDPuJV/xpYLo=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "8976e3f6a5357da953a09511d0c7f6a890fb6ec2", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_5": { + "inputs": { + "nixpkgs": [ + "hyprpicker", + "nixpkgs" + ], + "systems": [ + "hyprpicker", + "systems" + ] + }, + "locked": { + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "962582a090bc233c4de9d9897f46794280288989", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprutils_6": { + "inputs": { + "nixpkgs": [ + "xdg-desktop-portal-hyprland", + "hyprlang", + "nixpkgs" + ], + "systems": [ + "xdg-desktop-portal-hyprland", + "hyprlang", + "systems" + ] + }, + "locked": { + "lastModified": 1721324102, + "narHash": "sha256-WAZ0X6yJW1hFG6otkHBfyJDKRpNP5stsRqdEuHrFRpk=", + "owner": "hyprwm", + "repo": "hyprutils", + "rev": "962582a090bc233c4de9d9897f46794280288989", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprutils", + "type": "github" + } + }, + "hyprwayland-scanner": { + "inputs": { + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1721324119, + "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, + "hyprwayland-scanner_2": { + "inputs": { + "nixpkgs": [ + "hyprpaper", + "nixpkgs" + ], + "systems": [ + "hyprpaper", + "systems" + ] + }, + "locked": { + "lastModified": 1721324119, + "narHash": "sha256-SOOqIT27/X792+vsLSeFdrNTF+OSRp5qXv6Te+fb2Qg=", + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "rev": "a048a6cb015340bd82f97c1f40a4b595ca85cc30", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "hyprwayland-scanner", + "type": "github" + } + }, + "jovian-nixos": { + "inputs": { + "nix-github-actions": "nix-github-actions_2", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725559615, + "narHash": "sha256-q24lAKpBubomTHcNKLoVyvnNwVJJyBwcb/Gkhl0LLbs=", + "owner": "Jovian-Experiments", + "repo": "Jovian-NixOS", + "rev": "45e6dcff8489d75941468462c41fad0948a2c94b", + "type": "github" + }, + "original": { + "owner": "Jovian-Experiments", + "repo": "Jovian-NixOS", + "type": "github" + } + }, + "liburing": { + "flake": false, + "locked": { + "lastModified": 1724199144, + "narHash": "sha256-MVjnwO6EbKzzSrU51dSseLarZ1fRp+6SagAf/nE/XZU=", + "owner": "axboe", + "repo": "liburing", + "rev": "2d4e799017d64cd2f8304503eef9064931bb3fbd", + "type": "github" + }, + "original": { + "owner": "axboe", + "ref": "master", + "repo": "liburing", + "type": "github" + } + }, + "lifx-cli": { + "flake": false, + "locked": { + "lastModified": 1457381555, + "narHash": "sha256-ex2U35QesLRTga/7mQVH7vxr/uiQxWRhTVfH/OsE2xQ=", + "owner": "Rawa", + "repo": "lifx-cli", + "rev": "d29c12fa84ebb32692deead6952c49f034d0dff1", + "type": "github" + }, + "original": { + "owner": "Rawa", + "repo": "lifx-cli", + "type": "github" + } + }, + "nix": { + "inputs": { + "flake-compat": "flake-compat_4", + "nixpkgs": [ + "conduwuit", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nix-filter": { + "locked": { + "lastModified": 1710156097, + "narHash": "sha256-1Wvk8UP7PXdf8bCCaEoMnOT1qe5/Duqgj+rL8sRQsSM=", + "owner": "numtide", + "repo": "nix-filter", + "rev": "3342559a24e85fc164b295c3444e8a139924675b", + "type": "github" + }, + "original": { + "owner": "numtide", + "ref": "main", + "repo": "nix-filter", + "type": "github" + } + }, + "nix-flatpak": { + "locked": { + "lastModified": 1711997201, + "narHash": "sha256-J71xzQlVYsjagA4AsVwRazhBh2rZrPpKvxTgs6UzL7c=", + "owner": "gmodena", + "repo": "nix-flatpak", + "rev": "b76fa31346db7fc958a9898f3c594696ca71c4fd", + "type": "github" + }, + "original": { + "owner": "gmodena", + "ref": "v0.4.1", + "repo": "nix-flatpak", + "type": "github" + } + }, + "nix-github-actions": { + "inputs": { + "nixpkgs": [ + "conduwuit", + "cachix", + "devenv", + "cachix", + "devenv", + "poetry2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1688870561, + "narHash": "sha256-4UYkifnPEw1nAzqqPOTL2MvWtm3sNGw1UTYTalkTcGY=", + "owner": "nix-community", + "repo": "nix-github-actions", + "rev": "165b1650b753316aa7f1787f3005a8d2da0f5301", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-github-actions_2": { + "inputs": { + "nixpkgs": [ + "jovian-nixos", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1690328911, + "narHash": "sha256-fxtExYk+aGf2YbjeWQ8JY9/n9dwuEt+ma1eUFzF8Jeo=", + "owner": "zhaofengli", + "repo": "nix-github-actions", + "rev": "96df4a39c52f53cb7098b923224d8ce941b64747", + "type": "github" + }, + "original": { + "owner": "zhaofengli", + "ref": "matrix-name", + "repo": "nix-github-actions", + "type": "github" + } + }, + "nix-index-database-stable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-stable" + ] + }, + "locked": { + "lastModified": 1725161148, + "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "32058e9138248874773630c846563b1a78ee7a5b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "nix-index-database-unstable": { + "inputs": { + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725161148, + "narHash": "sha256-WfAHq3Ag3vLNFfWxKHjFBFdPI6JIideWFJod9mx1eoo=", + "owner": "nix-community", + "repo": "nix-index-database", + "rev": "32058e9138248874773630c846563b1a78ee7a5b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-index-database", + "type": "github" + } + }, + "nix-pre-commit": { + "inputs": { + "flake-utils": "flake-utils", + "nixpkgs": [ + "compose2nix", + "onchg", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1653259102, + "narHash": "sha256-XfCEu4zur/N2Dk4v8wFiQAgJ7bgNqPqwWp1vBXkeczM=", + "owner": "jmgilman", + "repo": "nix-pre-commit", + "rev": "6a99b2711c7eac9960939d8eb91e84322b22d50c", + "type": "github" + }, + "original": { + "owner": "jmgilman", + "repo": "nix-pre-commit", + "type": "github" + } + }, + "nix-vscode-extensions": { + "inputs": { + "flake-compat": "flake-compat_8", + "flake-utils": "flake-utils_5", + "nixpkgs": [ + "nixpkgs-unstable" + ] + }, + "locked": { + "lastModified": 1725500139, + "narHash": "sha256-drJz8wZ5RORqtPMnYOMZAQZ43SfrMxMnH5EmQMlVV3A=", + "owner": "nix-community", + "repo": "nix-vscode-extensions", + "rev": "33839dcc1d5a9243fb5c18ed72b0e200501b31ff", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nix-vscode-extensions", + "type": "github" + } + }, + "nix_2": { + "inputs": { + "flake-compat": [ + "conduwuit", + "cachix", + "devenv", + "flake-compat" + ], + "nixpkgs": [ + "conduwuit", + "cachix", + "devenv", + "nixpkgs" + ], + "nixpkgs-regression": "nixpkgs-regression_2" + }, + "locked": { + "lastModified": 1712911606, + "narHash": "sha256-BGvBhepCufsjcUkXnEEXhEVjwdJAwPglCC2+bInc794=", + "owner": "domenkozar", + "repo": "nix", + "rev": "b24a9318ea3f3600c1e24b4a00691ee912d4de12", + "type": "github" + }, + "original": { + "owner": "domenkozar", + "ref": "devenv-2.21", + "repo": "nix", + "type": "github" + } + }, + "nixd": { + "inputs": { + "flake-parts": "flake-parts_4", + "flake-root": "flake-root", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "treefmt-nix": "treefmt-nix" + }, + "locked": { + "lastModified": 1724296831, + "narHash": "sha256-+X9cc5fNEUtp6e+EZ2d9tjfPiXVcqkddEz1T/C9H5sc=", + "owner": "nix-community", + "repo": "nixd", + "rev": "f6ca74330b49c45f50cead6d0ac0469f8f830f88", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "nixd", + "type": "github" + } + }, + "nixos-hardware": { + "locked": { + "lastModified": 1725477728, + "narHash": "sha256-ahej1VRqKmWbG7gewty+GlrSBEeGY/J2Zy8Nt8+3fdg=", + "owner": "NixOS", + "repo": "nixos-hardware", + "rev": "880be1ab837e1e9fe0449dae41ac4d034694d4ce", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixos-hardware", + "type": "github" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1723827930, + "narHash": "sha256-EU+W5F6y2CVNxGrGIMpY7nSVYq72WRChYxF4zpjx0y4=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "d4a7a4d0e066278bfb0d77bd2a7adde1c0ec9e3d", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-lib": { + "locked": { + "dir": "lib", + "lastModified": 1714253743, + "narHash": "sha256-mdTQw2XlariysyScCv2tTE45QSU9v/ezLcHJ22f0Nxc=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "58a1abdbae3217ca6b702f03d3b35125d88a2994", + "type": "github" + }, + "original": { + "dir": "lib", + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-local": { + "locked": { + "lastModified": 1724600596, + "narHash": "sha256-wsL6/tpbD0e90bF3cCESaQ9K9EJNj1R71Ccfukt+yMg=", + "ref": "7849cd48822de4dc0515c787b20dc85de30acdca", + "rev": "7849cd48822de4dc0515c787b20dc85de30acdca", + "revCount": 671602, + "type": "git", + "url": "file:///home/myned/.dev/nixpkgs" + }, + "original": { + "ref": "7849cd48822de4dc0515c787b20dc85de30acdca", + "type": "git", + "url": "file:///home/myned/.dev/nixpkgs" + } + }, + "nixpkgs-regression": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-regression_2": { + "locked": { + "lastModified": 1643052045, + "narHash": "sha256-uGJ0VXIhWKGXxkeNnq4TvV3CIOkUJ3PAoLZ3HMzNVMw=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + }, + "original": { + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "215d4d0fd80ca5163643b03a33fde804a29cc1e2", + "type": "github" + } + }, + "nixpkgs-stable": { + "locked": { + "lastModified": 1720535198, + "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-23.11", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_2": { + "locked": { + "lastModified": 1720386169, + "narHash": "sha256-NGKVY4PjzwAa4upkGtAMz1npHGoRzWotlSnVlqI40mo=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "194846768975b7ad2c4988bdb82572c00222c0d7", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-stable_3": { + "locked": { + "lastModified": 1725407940, + "narHash": "sha256-tiN5Rlg/jiY0tyky+soJZoRzLKbPyIdlQ77xVgREDNM=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "6f6c45b5134a8ee2e465164811e451dcb5ad86e3", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-staging-next": { + "locked": { + "lastModified": 1725581600, + "narHash": "sha256-SAnRL9IF1FDJ1pKaNplkxLivOpkav413pAnwrFToQAU=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "25ef10109d198d1a6eac732c83cce8157c53ee98", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "staging-next", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1725432240, + "narHash": "sha256-+yj+xgsfZaErbfYM3T+QvEE2hU7UuE+Jf0fJCJ8uPS0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "ad416d066ca1222956472ab7d0555a6946746a80", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1692808169, + "narHash": "sha256-x9Opq06rIiwdwGeK2Ykj69dNc2IvUH1fY55Wm7atwrE=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "9201b5ff357e781bf014d0330d18555695df7ba8", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixpkgs-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1722813957, + "narHash": "sha256-IAoYyYnED7P8zrBFMnmp7ydaJfwTnwcnqxUElC1I26Y=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "cb9a96f23c491c081b38eab96d22fa958043c9fa", + "type": "github" + }, + "original": { + "owner": "NixOS", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "onchg": { + "inputs": { + "nix-pre-commit": "nix-pre-commit", + "nixpkgs": [ + "compose2nix", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1720368454, + "narHash": "sha256-NUSw3G2gsQX8/G64/pDBb1oitM+x13m7nFRvpiI4a+s=", + "owner": "aksiksi", + "repo": "onchg-rs", + "rev": "c42b693d10920874b3644ef1502e33318409d69c", + "type": "github" + }, + "original": { + "owner": "aksiksi", + "repo": "onchg-rs", + "type": "github" + } + }, + "poetry2nix": { + "inputs": { + "flake-utils": "flake-utils_3", + "nix-github-actions": "nix-github-actions", + "nixpkgs": [ + "conduwuit", + "cachix", + "devenv", + "cachix", + "devenv", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1692876271, + "narHash": "sha256-IXfZEkI0Mal5y1jr6IRWMqK8GW2/f28xJenZIPQqkY0=", + "owner": "nix-community", + "repo": "poetry2nix", + "rev": "d5006be9c2c2417dafb2e2e5034d83fabd207ee3", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "poetry2nix", + "type": "github" + } + }, + "rocksdb": { + "flake": false, + "locked": { + "lastModified": 1724285323, + "narHash": "sha256-k60kreKQ0v+bQ16yBd2SfLYpuNjMw2qoRmZL/S3k6CU=", + "owner": "girlbossceo", + "repo": "rocksdb", + "rev": "5a67ad7ce46328578ee5587fb0c23faa03d14e67", + "type": "github" + }, + "original": { + "owner": "girlbossceo", + "ref": "v9.5.2", + "repo": "rocksdb", + "type": "github" + } + }, + "root": { + "inputs": { + "aagl-gtk-on-nix-stable": "aagl-gtk-on-nix-stable", + "aagl-gtk-on-nix-unstable": "aagl-gtk-on-nix-unstable", + "agenix": "agenix", + "ags": "ags", + "anyrun": "anyrun", + "arion": "arion", + "bitwarden-menu": "bitwarden-menu", + "compose2nix": "compose2nix", + "conduwuit": "conduwuit", + "disko": "disko", + "firefox-gnome-theme": "firefox-gnome-theme", + "flakegen": "flakegen", + "fw-fanctrl": "fw-fanctrl", + "home-manager-stable": "home-manager-stable", + "home-manager-unstable": "home-manager-unstable", + "hypridle": "hypridle", + "hyprland": "hyprland", + "hyprland-contrib": "hyprland-contrib", + "hyprland-plugins": "hyprland-plugins", + "hyprlock": "hyprlock", + "hyprpaper": "hyprpaper", + "hyprpicker": "hyprpicker", + "jovian-nixos": "jovian-nixos", + "lifx-cli": "lifx-cli", + "nix-flatpak": "nix-flatpak", + "nix-index-database-stable": "nix-index-database-stable", + "nix-index-database-unstable": "nix-index-database-unstable", + "nix-vscode-extensions": "nix-vscode-extensions", + "nixd": "nixd", + "nixos-hardware": "nixos-hardware", + "nixpkgs-local": "nixpkgs-local", + "nixpkgs-stable": "nixpkgs-stable_3", + "nixpkgs-staging-next": "nixpkgs-staging-next", + "nixpkgs-unstable": "nixpkgs-unstable", + "steamtinkerlaunch": "steamtinkerlaunch", + "thunderbird-gnome-theme": "thunderbird-gnome-theme", + "virtio-win": "virtio-win", + "xdg-desktop-portal-hyprland": "xdg-desktop-portal-hyprland" + } + }, + "rust-analyzer-src": { + "flake": false, + "locked": { + "lastModified": 1724153119, + "narHash": "sha256-WxpvDJDttkINkXmUA/W5o11lwLPYhATAgu0QUAacZ2g=", + "owner": "rust-lang", + "repo": "rust-analyzer", + "rev": "3723e5910c14f0ffbd13de474b8a8fcc74db04ce", + "type": "github" + }, + "original": { + "owner": "rust-lang", + "ref": "nightly", + "repo": "rust-analyzer", + "type": "github" + } + }, + "steamtinkerlaunch": { + "flake": false, + "locked": { + "lastModified": 1725469657, + "narHash": "sha256-Z4tO5oymzp1KKN1ak10GsYLNI4hJh9MD3/l9vtLLCss=", + "owner": "sonic2kk", + "repo": "steamtinkerlaunch", + "rev": "c174a06f1b98d2aa523fe93e2afaed2713f46563", + "type": "github" + }, + "original": { + "owner": "sonic2kk", + "repo": "steamtinkerlaunch", + "type": "github" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_10": { + "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" + } + }, + "systems_11": { + "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" + } + }, + "systems_12": { + "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" + } + }, + "systems_13": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_14": { + "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" + } + }, + "systems_15": { + "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" + } + }, + "systems_2": { + "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" + } + }, + "systems_3": { + "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" + } + }, + "systems_4": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_5": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_6": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_7": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "systems_8": { + "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" + } + }, + "systems_9": { + "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" + } + }, + "thunderbird-gnome-theme": { + "flake": false, + "locked": { + "lastModified": 1721874544, + "narHash": "sha256-BHW9jlx92CsHY84FT0ce5Vxl0KFheLhNn2vndcIf7no=", + "owner": "rafaelmardojai", + "repo": "thunderbird-gnome-theme", + "rev": "628fcccb7788e3e0ad34f67114f563c87ac8c1dc", + "type": "github" + }, + "original": { + "owner": "rafaelmardojai", + "repo": "thunderbird-gnome-theme", + "type": "github" + } + }, + "treefmt-nix": { + "inputs": { + "nixpkgs": [ + "nixd", + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1722330636, + "narHash": "sha256-uru7JzOa33YlSRwf9sfXpJG+UAV+bnBEYMjrzKrQZFw=", + "owner": "numtide", + "repo": "treefmt-nix", + "rev": "768acdb06968e53aa1ee8de207fd955335c754b7", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "treefmt-nix", + "type": "github" + } + }, + "virtio-win": { + "flake": false, + "locked": { + "narHash": "sha256-KBayJBNwvXVO3RGJjXJJF0nQnruLCTv+x1G6sGJSOP4=", + "type": "file", + "url": "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.262-2/virtio-win.iso" + }, + "original": { + "type": "file", + "url": "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.262-2/virtio-win.iso" + } + }, + "xdg-desktop-portal-hyprland": { + "inputs": { + "hyprland-protocols": "hyprland-protocols_2", + "hyprlang": "hyprlang_5", + "nixpkgs": [ + "nixpkgs-unstable" + ], + "systems": "systems_15" + }, + "locked": { + "lastModified": 1725228143, + "narHash": "sha256-kbSiPA5oXiz1+1eVoRslMi5wylHD6SDT8dS9eZAxXAM=", + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "rev": "11e15b437e7efc39e452f36e15a183225d6bfa39", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "type": "github" + } + }, + "xdph": { + "inputs": { + "hyprland-protocols": "hyprland-protocols", + "hyprlang": [ + "hyprland", + "hyprlang" + ], + "nixpkgs": [ + "hyprland", + "nixpkgs" + ], + "systems": [ + "hyprland", + "systems" + ] + }, + "locked": { + "lastModified": 1725203932, + "narHash": "sha256-VLULC/OnI+6R9KEP2OIGk+uLJJsfRlaLouZ5gyFd2+Y=", + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "rev": "2425e8f541525fa7409d9f26a8ffaf92a3767251", + "type": "github" + }, + "original": { + "owner": "hyprwm", + "repo": "xdg-desktop-portal-hyprland", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..6ac4b07 --- /dev/null +++ b/flake.nix @@ -0,0 +1,138 @@ +# Do not modify! This file is generated. + +{ + inputs = { + aagl-gtk-on-nix-stable = { + inputs.nixpkgs.follows = "nixpkgs-stable"; + url = "github:ezKEa/aagl-gtk-on-nix/release-24.05"; + }; + aagl-gtk-on-nix-unstable = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:ezKEa/aagl-gtk-on-nix"; + }; + agenix = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:ryantm/agenix"; + }; + ags = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:Aylur/ags"; + }; + anyrun = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:Kirottu/anyrun"; + }; + arion = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hercules-ci/arion"; + }; + bitwarden-menu = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:firecat53/bitwarden-menu"; + }; + compose2nix = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:aksiksi/compose2nix"; + }; + conduwuit = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:Myned/conduwuit"; + }; + disko = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:nix-community/disko"; + }; + firefox-gnome-theme = { + flake = false; + url = "github:rafaelmardojai/firefox-gnome-theme/v128"; + }; + flakegen.url = "github:jorsn/flakegen"; + fw-fanctrl = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:TamtamHero/fw-fanctrl/packaging/nix"; + }; + home-manager-stable = { + inputs.nixpkgs.follows = "nixpkgs-stable"; + url = "github:nix-community/home-manager/release-24.05"; + }; + home-manager-unstable = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:nix-community/home-manager"; + }; + hypridle = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/hypridle"; + }; + hyprland = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "git+https://github.com/hyprwm/Hyprland?submodules=1"; + }; + hyprland-contrib = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/contrib"; + }; + hyprland-plugins = { + inputs.hyprland.follows = "hyprland"; + url = "github:hyprwm/hyprland-plugins"; + }; + hyprlock = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/hyprlock"; + }; + hyprpaper = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/hyprpaper"; + }; + hyprpicker = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/hyprpicker"; + }; + jovian-nixos = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:Jovian-Experiments/Jovian-NixOS"; + }; + lifx-cli = { + flake = false; + url = "github:Rawa/lifx-cli"; + }; + nix-flatpak.url = "github:gmodena/nix-flatpak?ref=v0.4.1"; + nix-index-database-stable = { + inputs.nixpkgs.follows = "nixpkgs-stable"; + url = "github:nix-community/nix-index-database"; + }; + nix-index-database-unstable = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:nix-community/nix-index-database"; + }; + nix-vscode-extensions = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:nix-community/nix-vscode-extensions"; + }; + nixd = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:nix-community/nixd"; + }; + nixos-hardware.url = "github:NixOS/nixos-hardware"; + nixpkgs-local.url = "git+file:///home/myned/.dev/nixpkgs?ref=7849cd48822de4dc0515c787b20dc85de30acdca"; + nixpkgs-stable.url = "github:NixOS/nixpkgs/nixos-24.05"; + nixpkgs-staging-next.url = "github:NixOS/nixpkgs/staging-next"; + nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; + steamtinkerlaunch = { + flake = false; + url = "github:sonic2kk/steamtinkerlaunch"; + }; + thunderbird-gnome-theme = { + flake = false; + url = "github:rafaelmardojai/thunderbird-gnome-theme"; + }; + virtio-win = { + flake = false; + url = "https://fedorapeople.org/groups/virt/virtio-win/direct-downloads/archive-virtio/virtio-win-0.1.262-2/virtio-win.iso"; + }; + xdg-desktop-portal-hyprland = { + inputs.nixpkgs.follows = "nixpkgs-unstable"; + url = "github:hyprwm/xdg-desktop-portal-hyprland"; + }; + }; + outputs = inputs: inputs.flakegen ./flake.in.nix inputs; +} \ No newline at end of file diff --git a/install.fish b/install.fish new file mode 100644 index 0000000..7d576ee --- /dev/null +++ b/install.fish @@ -0,0 +1,76 @@ +#!/usr/bin/env fish +# sudo nix --experimental-features 'nix-command flakes' run nixpkgs#fish -- install.fish + +# Wrap command execution in log output with error handling +function execute + if $argv &>>install.log + echo " done." + else + echo " error." + exit 1 + end +end + +# Alias nix to enable flakes +alias nix "nix --experimental-features 'nix-command flakes'" + +# Gather variables +set -l machine (read -P "Enter machine hostname: ") +set -l secret (read -P "Enter encryption secret: ") + +# Clear logfile +echo "Logging to install.log..." +rm install.log &>/dev/null + +# Create keyfile +echo -n "Creating secret.key..." +execute nix run nixpkgs#fish -- -c "echo -n $secret > /tmp/secret.key" + +# Format disks +echo -n "Formatting disks..." +execute nix run disko -- -m disko machines/$machine/disko.nix + +# Shred keyfile +echo -n "Shredding secret.key..." +execute shred -zu /tmp/secret.key + +# Generate hardware configuration +echo -n "Generating hardware-configuration.nix..." +execute nixos-generate-config --no-filesystems --root /mnt --dir . + +# Move hardware configuration +echo -n "Moving hardware-configuration.nix to machines/$machine/..." +execute mv hardware-configuration.nix machines/$machine/ + +# Stage files in git tree for flake to access +git add . + +# Update flake +echo -n "Updating flake.lock..." +execute nix flake update + +# Confirm installation of NixOS +while true + switch (read -P "Install NixOS? [Y/N] ") + case Y y + break + case N n + exit + end +end + +# Install NixOS +echo -n "Installing..." +execute nixos-install --no-root-password --flake .#$machine + +# Update git remote to remove personal access token +echo -n "Updating git remotes..." +git remote rm origin +execute git remote add git@github.com/Myned/nixos.git + +# Copy NixOS configuration to system +echo -n "Copying NixOS configuration to /mnt/etc/nixos/..." +execute cp -r . /mnt/etc/nixos/ + +# Finish +echo "Installation finished. Reboot when ready." diff --git a/machines/myarm/default.nix b/machines/myarm/default.nix new file mode 100644 index 0000000..df5732c --- /dev/null +++ b/machines/myarm/default.nix @@ -0,0 +1,15 @@ +{ + imports = [ + ./disko.nix + ./hardware-configuration.nix + ]; + + custom = { + hostname = "myarm"; + + settings.networking = { + static = true; + ipv6 = "2a01:4f8:c17:321c::1/64"; + }; + }; +} diff --git a/machines/myarm/disko.nix b/machines/myarm/disko.nix new file mode 100644 index 0000000..7a3734f --- /dev/null +++ b/machines/myarm/disko.nix @@ -0,0 +1,62 @@ +{ + disko.devices = { + disk = { + master = { + type = "disk"; + device = "/dev/sda"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "8G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/machines/myarm/hardware-configuration.nix b/machines/myarm/hardware-configuration.nix new file mode 100644 index 0000000..07d3157 --- /dev/null +++ b/machines/myarm/hardware-configuration.nix @@ -0,0 +1,32 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "virtio_scsi" + "sr_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.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 + # 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.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; +} diff --git a/machines/myeck/default.nix b/machines/myeck/default.nix new file mode 100644 index 0000000..c748dc2 --- /dev/null +++ b/machines/myeck/default.nix @@ -0,0 +1,23 @@ +{ + imports = [ + ./disko.nix + ./hardware-configuration.nix + ]; + + custom.hostname = "myeck"; + + fileSystems = { + "/mnt/external" = { + device = "/dev/disk/by-label/external"; + options = [ + "noatime" + "nofail" + "users" + "exec" + "x-gvfs-show" + ]; + }; + }; + + systemd.tmpfiles.rules = [ "z /mnt/external 0755 myned users" ]; +} diff --git a/machines/myeck/disko.nix b/machines/myeck/disko.nix new file mode 100644 index 0000000..3e33499 --- /dev/null +++ b/machines/myeck/disko.nix @@ -0,0 +1,62 @@ +{ + disko.devices = { + disk = { + master = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "16G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/machines/myeck/hardware-configuration.nix b/machines/myeck/hardware-configuration.nix new file mode 100644 index 0000000..c06227c --- /dev/null +++ b/machines/myeck/hardware-configuration.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ + "nvme" + "dwc3_pci" + "xhci_pci" + "usbhid" + "usb_storage" + "sd_mod" + "sdhci_pci" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.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 + # 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.enp4s0f3u1u1.useDHCP = lib.mkDefault true; + # networking.interfaces.enp4s0f3u1u2.useDHCP = lib.mkDefault true; + # networking.interfaces.wlo1.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/machines/myne/default.nix b/machines/myne/default.nix new file mode 100644 index 0000000..ed7ad21 --- /dev/null +++ b/machines/myne/default.nix @@ -0,0 +1,8 @@ +{ + imports = [ + ./disko.nix + ./hardware-configuration.nix + ]; + + custom.hostname = "myne"; +} diff --git a/machines/myne/disko.nix b/machines/myne/disko.nix new file mode 100644 index 0000000..596abc0 --- /dev/null +++ b/machines/myne/disko.nix @@ -0,0 +1,67 @@ +{ + disko.devices = { + disk = { + master = { + type = "disk"; + device = "/dev/sda"; + content = { + type = "gpt"; + partitions = { + BOOT = { + size = "1M"; + type = "EF02"; + }; + + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + root = { + size = "100%"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "8G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/machines/myne/hardware-configuration.nix b/machines/myne/hardware-configuration.nix new file mode 100644 index 0000000..949e33f --- /dev/null +++ b/machines/myne/hardware-configuration.nix @@ -0,0 +1,35 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/profiles/qemu-guest.nix") ]; + + boot.initrd.availableKernelModules = [ + "ahci" + "xhci_pci" + "virtio_pci" + "virtio_scsi" + "sd_mod" + "sr_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.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 + # 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.enp1s0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; +} diff --git a/machines/mynix/default.nix b/machines/mynix/default.nix new file mode 100644 index 0000000..1c3363e --- /dev/null +++ b/machines/mynix/default.nix @@ -0,0 +1,102 @@ +{ + imports = [ + ./disko.nix + ./hardware-configuration.nix + ]; + + custom = { + hostname = "mynix"; + width = 3440; + height = 1440; + }; + + boot.kernelParams = [ + # https://gitlab.freedesktop.org/drm/amd/-/issues/2516#note_2119750 + #// "gpu_sched.sched_policy=0" # Attempt to fix stutter + ]; + + # _._ _,-'""`-._ + # (,-.`._,'( |\`-/| + # `-.-' \ )-`( , o o) + # `- \`_`"'- + #// services.logind.powerKey = "ignore"; # Disable power button + + # Mount external drives on boot + fileSystems = { + "/mnt/gayme" = { + device = "/dev/disk/by-label/gayme"; + options = [ + "noatime" + "nofail" + "users" + "exec" + "x-gvfs-show" + ]; + }; + + "/mnt/gaymer" = { + device = "/dev/disk/by-label/gaymer"; + options = [ + "noatime" + "nofail" + "users" + "exec" + "x-gvfs-show" + ]; + }; + }; + + # Set mount directory permissions + #?? TYPE PATH MODE USER GROUP AGE ARGUMENT + systemd.tmpfiles.rules = [ + "z /mnt/gayme 0755 myned users" + "z /mnt/gaymer 0755 myned users" + ]; + + # Work around performance issues with AMD power scaling + # https://wiki.archlinux.org/title/AMDGPU#Screen_artifacts_and_frequency_problem + # https://wiki.archlinux.org/title/AMDGPU#Power_profiles + #!! cardX must match the correct gpu + #?? lspci + #?? ls -l /dev/dri/by-path/*-card + #?? grep '*' /sys/class/drm/card*/device/pp_power_profile_mode + services.udev.extraRules = '' + KERNEL=="renderD128", SUBSYSTEM=="drm", DRIVERS=="amdgpu", ATTR{device/power_dpm_force_performance_level}="manual", ATTR{device/pp_power_profile_mode}="5" + ''; + + # https://github.com/Zygo/bees + # Deduplicate entire filesystem + #?? Optimal for ~1TB total disk space + # https://github.com/Zygo/bees/blob/master/docs/config.md#hash-table-sizing + # services.beesd.filesystems.root = { + # spec = "/"; + # verbosity = "err"; + # extraOptions = [ "--loadavg-target" "5" ]; # Reduce threads on ~5% total processor load + # }; + + # Periodically upload current wallpaper to remote server + # systemd.user = { + # services."wallpaper" = { + # path = with pkgs; [ + # openssh + # rsync + # tailscale + # variety + # ]; + + # #!! Hostname dependent + # script = '' + # rsync --chown caddy:caddy "$(variety --current)" root@myarm:/srv/static/wallpaper.png + # ''; + # }; + + # timers."wallpaper" = { + # wantedBy = [ "timers.target" ]; + + # timerConfig = { + # OnBootSec = "1m"; + # OnUnitActiveSec = "1m"; + # }; + # }; + # }; +} diff --git a/machines/mynix/disko.nix b/machines/mynix/disko.nix new file mode 100644 index 0000000..0577352 --- /dev/null +++ b/machines/mynix/disko.nix @@ -0,0 +1,68 @@ +{ + disko.devices = { + disk = { + master = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + luks = { + size = "100%"; + content = { + type = "luks"; + name = "crypted"; + settings.allowDiscards = true; + passwordFile = "/tmp/secret.key"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "32G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/machines/mynix/hardware-configuration.nix b/machines/mynix/hardware-configuration.nix new file mode 100644 index 0000000..ab71533 --- /dev/null +++ b/machines/mynix/hardware-configuration.nix @@ -0,0 +1,39 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ + "xhci_pci" + "ahci" + "nvme" + "usbhid" + "uas" + "usb_storage" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-intel" ]; + boot.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 + # 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.enp0s31f6.useDHCP = lib.mkDefault true; + # networking.interfaces.enp5s0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlp0s20f3.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/machines/myork/default.nix b/machines/myork/default.nix new file mode 100644 index 0000000..a9c8d5a --- /dev/null +++ b/machines/myork/default.nix @@ -0,0 +1,81 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +let + brightnessctl = "${pkgs.brightnessctl}/bin/brightnessctl"; +in +{ + imports = [ + inputs.nixos-hardware.nixosModules.framework-13-7040-amd + + ./disko.nix + ./hardware-configuration.nix + ]; + + custom = { + hostname = "myork"; + width = 2256; + height = 1504; + scale = 1.5; + + services = { + fw-fanctrl.enable = true; + + auto-cpufreq.max = { + battery = 3; # GHz + charger = 3.5; # GHz + }; + }; + }; + + home-manager.users.${config.custom.username} = with lib; { + wayland.windowManager.hyprland.settings = { + exec-once = [ "${brightnessctl} set 0%" ]; + + master = { + mfact = mkForce 0.5; + orientation = mkForce "top"; + always_center_master = mkForce false; + }; + + device = [ + { + name = "pixa3854:00-093a:0274-touchpad"; + accel_profile = "adaptive"; + sensitivity = 0.3; + } + ]; + }; + }; + + services.keyd.keyboards.default.settings.main.rightcontrol = "layer(altgr)"; # No Ctrl_R + + # Enable hibernation with a swapfile on btrfs + # https://wiki.archlinux.org/title/Power_management/Suspend_and_hibernate#Hibernation_into_swap_file + #?? findmnt -no UUID -T /swap/swapfile + #?? sudo btrfs inspect-internal map-swapfile -r /swap/swapfile + boot = { + resumeDevice = "/dev/disk/by-uuid/f9416347-eff5-45d5-8dc3-93414c11ba6f"; + + kernelParams = [ + "resume_offset=533760" + + # Fix battery drain with suspend-then-hibernate + # https://wiki.archlinux.org/title/Framework_Laptop_13#Suspend-then-hibernate_on_AMD_version + "rtc_cmos.use_acpi_alarm=1" + + # Force disable display power savings + # https://wiki.archlinux.org/title/Framework_Laptop_13#(AMD)_Washed-out_colors_when_using_power-profiles-daemon_in_power-saver_or_balanced_mode + "amdgpu.abmlevel=0" + + # Disable AMD scaling driver + # https://wiki.archlinux.org/title/CPU_frequency_scaling#amd_pstate + #// "amd_pstate=disable" + ]; + }; +} diff --git a/machines/myork/disko.nix b/machines/myork/disko.nix new file mode 100644 index 0000000..0577352 --- /dev/null +++ b/machines/myork/disko.nix @@ -0,0 +1,68 @@ +{ + disko.devices = { + disk = { + master = { + type = "disk"; + device = "/dev/nvme0n1"; + content = { + type = "gpt"; + partitions = { + ESP = { + size = "512M"; + type = "EF00"; + content = { + type = "filesystem"; + format = "vfat"; + mountpoint = "/boot"; + }; + }; + + luks = { + size = "100%"; + content = { + type = "luks"; + name = "crypted"; + settings.allowDiscards = true; + passwordFile = "/tmp/secret.key"; + content = { + type = "btrfs"; + extraArgs = [ "-f" ]; + subvolumes = { + "/root" = { + mountpoint = "/"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/home" = { + mountpoint = "/home"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/nix" = { + mountpoint = "/nix"; + mountOptions = [ + "compress=zstd" + "noatime" + ]; + }; + + "/swap" = { + mountpoint = "/swap"; + swap.swapfile.size = "32G"; + }; + }; + }; + }; + }; + }; + }; + }; + }; + }; +} diff --git a/machines/myork/hardware-configuration.nix b/machines/myork/hardware-configuration.nix new file mode 100644 index 0000000..5a0fef2 --- /dev/null +++ b/machines/myork/hardware-configuration.nix @@ -0,0 +1,38 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ + "nvme" + "xhci_pci" + "thunderbolt" + "usbhid" + "uas" + "sd_mod" + ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ "kvm-amd" ]; + boot.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 + # 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.docker0.useDHCP = lib.mkDefault true; + # networking.interfaces.tailscale0.useDHCP = lib.mkDefault true; + # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/machines/mypi3/default.nix b/machines/mypi3/default.nix new file mode 100644 index 0000000..6eb21b0 --- /dev/null +++ b/machines/mypi3/default.nix @@ -0,0 +1,12 @@ +{ + imports = [ ./hardware-configuration.nix ]; + + custom.hostname = "mypi3"; + + swapDevices = [ + { + device = "/var/swapfile"; + size = 4 * 1024; # GiB * 1024 + } + ]; +} diff --git a/machines/mypi3/hardware-configuration.nix b/machines/mypi3/hardware-configuration.nix new file mode 100644 index 0000000..d42fd9b --- /dev/null +++ b/machines/mypi3/hardware-configuration.nix @@ -0,0 +1,36 @@ +# Do not modify this file! It was generated by ‘nixos-generate-config’ +# and may be overwritten by future invocations. Please make changes +# to /etc/nixos/configuration.nix instead. +{ + config, + lib, + pkgs, + modulesPath, + ... +}: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + boot.initrd.availableKernelModules = [ ]; + boot.initrd.kernelModules = [ ]; + boot.kernelModules = [ ]; + boot.extraModulePackages = [ ]; + + fileSystems."/" = { + device = "/dev/disk/by-uuid/44444444-4444-4444-8888-888888888888"; + fsType = "ext4"; + }; + + 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 + # 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.enu1u1u1.useDHCP = lib.mkDefault true; + # networking.interfaces.wlan0.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "aarch64-linux"; +} diff --git a/options/custom/default.nix b/options/custom/default.nix new file mode 100644 index 0000000..426b52e --- /dev/null +++ b/options/custom/default.nix @@ -0,0 +1,38 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom; +in +{ + options.custom = { + ### Profiles + default = mkOption { default = true; }; + full = mkOption { default = false; }; + minimal = mkOption { default = cfg.full; }; + profile = mkOption { }; + + ### Users + domain = mkOption { default = "bjork.tech"; }; + hostname = mkOption { }; + realname = mkOption { default = "Myned"; }; + username = mkOption { default = "myned"; }; + + ### Hardware + width = mkOption { default = 1920; }; + height = mkOption { default = 1080; }; + ultrawide = mkOption { default = cfg.width * 9 / 16 > cfg.height; }; # Wider than 16:9 + hidpi = mkOption { default = cfg.scale > 1; }; + scale = mkOption { default = 1; }; + + # TODO: Use option for border size + border = mkOption { default = 2; }; + + gap = mkOption { default = 10; }; + padding = mkOption { default = 56; }; # ?? journalctl --user -u waybar.service | grep height: + + ### Misc + wallpaper = mkOption { default = false; }; + }; +} diff --git a/options/custom/desktops/default.nix b/options/custom/desktops/default.nix new file mode 100644 index 0000000..d1db652 --- /dev/null +++ b/options/custom/desktops/default.nix @@ -0,0 +1,7 @@ +{ config, lib, ... }: + +with lib; + +{ + config.custom.desktops.hyprland.enable = config.custom.full; +} diff --git a/options/custom/desktops/gnome/default.nix b/options/custom/desktops/gnome/default.nix new file mode 100644 index 0000000..b68a920 --- /dev/null +++ b/options/custom/desktops/gnome/default.nix @@ -0,0 +1,35 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.desktops.gnome; +in +{ + options.custom.desktops.gnome = { + enable = mkOption { default = false; }; + gdm = mkOption { default = true; }; + }; + + config = mkIf cfg.enable { + # FIXME: xdg-desktop-portal-[gnome|gtk] not working through steam + services = { + xserver = { + enable = true; + desktopManager.gnome.enable = true; + displayManager.gdm.enable = cfg.gdm; + }; + + gnome.gnome-browser-connector.enable = true; # Install extensions from browser + }; + + # Remove default packages + # https://wiki.nixos.org/wiki/GNOME#Excluding_GNOME_Applications + environment.gnome.excludePackages = [ pkgs.gnome.gnome-shell-extensions ]; + }; +} diff --git a/options/custom/desktops/hyprland/binds.nix b/options/custom/desktops/hyprland/binds.nix new file mode 100644 index 0000000..ed4b7ad --- /dev/null +++ b/options/custom/desktops/hyprland/binds.nix @@ -0,0 +1,246 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + clipse = "${pkgs.clipse}/bin/clipse"; + codium = "${ + config.home-manager.users.${config.custom.username}.programs.vscode.package + }/bin/codium"; + firefox-esr = "${ + config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage + }/bin/firefox-esr"; + gnome-text-editor = "${pkgs.gnome-text-editor}/bin/gnome-text-editor"; + hyprctl = "${pkgs.hyprland}/bin/hyprctl"; + hyprlock = "${ + config.home-manager.users.${config.custom.username}.programs.hyprlock.package + }/bin/hyprlock"; + hyprpicker = "${pkgs.hyprpicker}/bin/hyprpicker"; + jq = "${pkgs.jq}/bin/jq"; + kill = "${pkgs.procps}/bin/kill"; + kitty = "${config.home-manager.users.${config.custom.username}.programs.kitty.package}/bin/kitty"; + libreoffice = "${config.custom.programs.libreoffice.package}/bin/libreoffice"; + loginctl = "${pkgs.systemd}/bin/loginctl"; + nautilus = "${pkgs.nautilus}/bin/nautilus"; + networkmanager_dmenu = "${pkgs.networkmanager_dmenu}/bin/networkmanager_dmenu"; + notify-send = "${pkgs.libnotify}/bin/notify-send"; + obsidian = "${pkgs.obsidian}/bin/obsidian"; + pkill = "${pkgs.procps}/bin/pkill"; + playerctl = "${pkgs.playerctl}/bin/playerctl"; + rofi-rbw = "${pkgs.rofi-rbw}/bin/rofi-rbw"; + sleep = "${pkgs.coreutils}/bin/sleep"; + swayosd-client = "${pkgs.swayosd}/bin/swayosd-client"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + virt-manager = "${config.programs.virt-manager.package}/bin/virt-manager"; + waydroid = "${pkgs.waydroid}/bin/waydroid"; + wofi = "${config.home-manager.users.${config.custom.username}.programs.wofi.package}/bin/wofi"; + + cfg = config.custom.desktops.hyprland.binds; +in +{ + options.custom.desktops.hyprland.binds.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + wayland.windowManager.hyprland.settings = { + # https://wiki.hyprland.org/Configuring/Binds + #?? bind = MODS, KEY, DISPATCHER, [PARAMS] + #?? wev + binds = { + allow_workspace_cycles = true; + disable_keybind_grabbing = true; + scroll_event_delay = 0; + }; + + # Lockscreen binds + bindl = [ + ### System + "CTRL, Delete, exec, ${hyprctl} reload" + "CTRL+ALT, Delete, exec, ${loginctl} terminate-session ''" + "SUPER, L, exec, ${hyprlock} --immediate & ${sleep} 1 && ${hyprctl} dispatch dpms off" + + ### Scripts + "SUPER, Delete, exec, inhibit" + ]; + + # Mouse binds + bindm = [ + "SUPER, mouse:272, movewindow" # LMB + "SUPER, mouse:273, resizewindow" # RMB + ]; + + # Repeat binds + binde = [ + # Media keys + # https://github.com/xkbcommon/libxkbcommon/blob/master/include/xkbcommon/xkbcommon-keysyms.h + ", XF86AudioMute, exec, ${swayosd-client} --output-volume mute-toggle" + ", XF86AudioLowerVolume, exec, ${swayosd-client} --output-volume lower" + ", XF86AudioRaiseVolume, exec, ${swayosd-client} --output-volume raise" + ", XF86AudioPlay, exec, ${playerctl} play-pause" + ", XF86AudioPrev, exec, ${playerctl} previous" + ", XF86AudioNext, exec, ${playerctl} next" + ", XF86MonBrightnessDown, exec, ${swayosd-client} --brightness lower" + ", XF86MonBrightnessUp, exec, ${swayosd-client} --brightness raise" + + # TODO: Unused media key + #// ", XF86AudioMedia, exec, null" + ]; + + # Release binds + bindr = [ + ### Applications + "SUPER, Super_L, exec, ${pkill} wofi || ${wofi} --show drun" + "SUPER+CTRL, Super_L, exec, ${pkill} wofi || calc" + "SUPER+SHIFT, Super_L, exec, ${pkill} wofi || ${wofi} --show run" + "SUPER+SHIFT+CTRL, Super_L, exec, ${pkill} wofi || ${networkmanager_dmenu}" + "SUPER+ALT, Super_L, exec, ${pkill} wofi || ${rofi-rbw}" + + ### Layouts + "SUPER+CTRL, Control_L, layoutmsg, swapwithmaster master" + "SUPER+SHIFT+CTRL, Control_L, layoutmsg, addmaster" + "SUPER+SHIFT+CTRL+ALT, Control_L, layoutmsg, removemaster" + + ### Workspaces + "SUPER+SHIFT, Shift_L, workspace, previous" + + # Special workspaces + "SUPER+ALT, Alt_L, togglespecialworkspace, wallpaper" + ]; + + # Regular binds + bind = [ + ### Scripts + ", Print, exec, screenshot" + "SHIFT, Print, exec, screenshot -d" + "SUPER, Print, exec, screenshot -e" + "SUPER+SHIFT, Print, exec, screenshot -ed" + "SUPER+SHIFT, Delete, exec, vrr" + "SUPER, Minus, exec, audio" + "SUPER, Equal, exec, audio Normalizer" + "SUPER+SHIFT, W, exec, vm -x ${if config.custom.hidpi then "/scale:140 +f" else ""}" + "SUPER+SHIFT+CTRL, W, exec, vm ${virt-manager} --connect qemu:///system --show-domain-console myndows" + "SUPER+SHIFT+CTRL, Q, exec, close" # Quit all windows + + # BUG: Freezes window when toggled + # https://github.com/hyprwm/Hyprland/issues/7609 + "CTRL, Space, exec, toggle dropdown special:dropdown ${kitty} --app-id dropdown --override font_size=12" + + "CTRL+SHIFT, Space, exec, toggle pip special:pip" + + # TODO: Toggle trackball hand + #// "SUPER, Delete, exec, left" + + ### Applications + "SUPER, B, exec, [tag +browser] ${firefox-esr}" + "SUPER, C, exec, ${codium}" + "SUPER, E, exec, ${gnome-text-editor}" + "SUPER, F, exec, ${nautilus}" + "SUPER, K, exec, ${obsidian}" + "SUPER, O, exec, ${libreoffice}" + "SUPER, P, exec, ${hyprpicker} --autocopy" + "SUPER+SHIFT, P, exec, ${hyprpicker} --autocopy --format rgb" + "SUPER+SHIFT, T, exec, ${kitty}" + "SUPER, V, exec, ${kitty} --app-id clipboard --override font_size=12 ${clipse}" + "SUPER+SHIFT, V, exec, ${clipse} -clear && ${notify-send} clipse 'Clipboard cleared' --urgency low" + + # Kill applications + "SUPER+SHIFT, A, exec, ${waydroid} session stop" + "SUPER+SHIFT, S, exec, ${pkill} steam" + "SUPER+SHIFT+CTRL, G, exec, ${pkill} gamescope" + + # LIFX + "SUPER+ALT, Escape, exec, lifx state --color red" + "SUPER+ALT, 1, exec, lifx state --kelvin 1500" + "SUPER+ALT, 2, exec, lifx state --kelvin 2500" + "SUPER+ALT, 3, exec, lifx state --kelvin 3000" + "SUPER+ALT, 4, exec, lifx state --kelvin 4000" + "SUPER+ALT, 5, exec, lifx state --kelvin 5000" + "CTRL+ALT, 1, exec, lifx state --brightness 0.01" + "CTRL+ALT, 2, exec, lifx state --brightness 0.25" + "CTRL+ALT, 3, exec, lifx state --brightness 0.50" + "CTRL+ALT, 4, exec, lifx state --brightness 0.75" + "CTRL+ALT, 5, exec, lifx state --brightness 1.00" + "CTRL+ALT, Space, exec, lifx toggle" + + ### Windows + "SUPER, Q, killactive" + "SUPER+SHIFT, Q, exec, ${kill} -9 $(${hyprctl} -j activewindow | ${jq} .pid)" + "SUPER, Escape, togglefloating" + "SUPER+SHIFT, Escape, centerwindow" + "SUPER, Return, fullscreen, 1" # Maximize + "SUPER+SHIFT, Return, fullscreen, 0" # Fullscreen + "SUPER, Tab, cyclenext, tiled" + + # FIXME: Handle hover focus and zorder + "SUPER+SHIFT, Tab, cyclenext, floating" + "SUPER+SHIFT, Tab, alterzorder, top" + + ### Groups + "SUPER, Backspace, changegroupactive, f" + "SUPER+SHIFT, Backspace, changegroupactive, b" + "SUPER+CTRL, Backspace, togglegroup" + "SUPER+SHIFT+CTRL, Backspace, lockactivegroup, toggle" + "SUPER, Up, movewindoworgroup, u" + "SUPER, Down, movewindoworgroup, d" + "SUPER, Left, movewindoworgroup, l" + "SUPER, Right, movewindoworgroup, r" + + ### Layouts + "SUPER, mouse:274, layoutmsg, swapwithmaster master" + "SUPER+SHIFT, mouse:274, layoutmsg, addmaster" + "SUPER+SHIFT+CTRL, mouse:274, layoutmsg, removemaster" + "SUPER, Bracketleft, layoutmsg, orientationprev" + "SUPER, Bracketright, layoutmsg, orientationnext" + "SUPER, Backslash, layoutmsg, orientationcenter" + "SUPER+SHIFT, Backslash, splitratio, exact 0.5" # Reset layout ratio + "SUPER+SHIFT, Bracketleft, splitratio, -0.1" + "SUPER+SHIFT, Bracketright, splitratio, +0.1" + + ### Workspaces + "SUPER, 1, workspace, 1" + "SUPER+SHIFT, 1, movetoworkspacesilent, 1" + "SUPER, 2, workspace, 2" + "SUPER+SHIFT, 2, movetoworkspacesilent, 2" + "SUPER, 3, workspace, 3" + "SUPER+SHIFT, 3, movetoworkspacesilent, 3" + "SUPER, 4, workspace, 4" + "SUPER+SHIFT, 4, movetoworkspacesilent, 4" + "SUPER, 5, workspace, 5" + "SUPER+SHIFT, 5, movetoworkspacesilent, 5" + "SUPER, 6, workspace, 6" + "SUPER+SHIFT, 6, movetoworkspacesilent, 6" + "SUPER, 7, workspace, 7" + "SUPER+SHIFT, 7, movetoworkspacesilent, 7" + "SUPER, 8, workspace, 8" + "SUPER+SHIFT, 8, movetoworkspacesilent, 8" + "SUPER, 9, workspace, 9" + "SUPER+SHIFT, 9, movetoworkspacesilent, 9" + "SUPER, 0, workspace, 10" + "SUPER+SHIFT, 0, movetoworkspacesilent, 10" + "SUPER, Z, workspace, -1" + "SUPER+SHIFT, Z, movetoworkspacesilent, -1" + "SUPER, X, workspace, +1" + "SUPER+SHIFT, X, movetoworkspacesilent, +1" + + # Named workspaces + "SUPER, G, workspace, name:game" + "SUPER+SHIFT, G, movetoworkspacesilent, name:game" + "SUPER+CTRL, G, workspace, name:gamescope" + + # Special workspaces + "SUPER, A, togglespecialworkspace, android" + "SUPER, M, togglespecialworkspace, music" + "SUPER, S, togglespecialworkspace, steam" + "SUPER, T, togglespecialworkspace, terminal" + "SUPER, W, togglespecialworkspace, vm" + "SUPER, Space, togglespecialworkspace, scratchpad" + "SUPER+SHIFT, Space, movetoworkspacesilent, special:scratchpad" + ]; + }; + }; +} diff --git a/options/custom/desktops/hyprland/default.nix b/options/custom/desktops/hyprland/default.nix new file mode 100644 index 0000000..c834b6f --- /dev/null +++ b/options/custom/desktops/hyprland/default.nix @@ -0,0 +1,32 @@ +{ + config, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.desktops.hyprland; +in +{ + options.custom.desktops.hyprland.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + custom.desktops.hyprland = mkIf config.custom.full { + binds.enable = true; + plugins.enable = true; + rules.enable = true; + settings.enable = true; + }; + + # https://github.com/hyprwm/Hyprland + programs.hyprland.enable = true; + + # https://wiki.hyprland.org + home-manager.users.${config.custom.username}.wayland.windowManager.hyprland = { + enable = true; + systemd.variables = [ "--all" ]; # Import some environment variables into session + }; + }; +} diff --git a/options/custom/desktops/hyprland/plugins.nix b/options/custom/desktops/hyprland/plugins.nix new file mode 100644 index 0000000..f27d97d --- /dev/null +++ b/options/custom/desktops/hyprland/plugins.nix @@ -0,0 +1,63 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + hyprctl = "${pkgs.hyprland}/bin/hyprctl"; + + cfg = config.custom.desktops.hyprland.plugins; +in +{ + options.custom.desktops.hyprland.plugins.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + wayland.windowManager.hyprland = { + # https://github.com/hyprwm/hyprland-plugins/tree/main/hyprbars + # https://wiki.hyprland.org/Plugins/Using-Plugins + plugins = with pkgs.hyprlandPlugins; [ hyprbars ]; + + settings = { + #!! Static rules + windowrulev2 = [ + "plugin:hyprbars:bar_color rgb(073642), focus:0" + "plugin:hyprbars:title_color rgb(586e75), focus:0" + + "plugin:hyprbars:nobar, floating:0" + "plugin:hyprbars:nobar, class:^clipboard$" + "plugin:hyprbars:nobar, class:^discord$, title:^Discord Updater$" + "plugin:hyprbars:nobar, class:^dropdown$" + "plugin:hyprbars:nobar, class:^steam_app_.+$" + "plugin:hyprbars:nobar, title:^Picture.in.[Pp]icture$" + ]; + + # Plugin settings + plugin = { + hyprbars = { + bar_button_padding = 10; + bar_color = "rgb(002b36)"; + bar_height = 30; + bar_padding = 10; + bar_precedence_over_border = true; # Render borders around hyprbars + bar_text_align = "left"; + bar_text_font = "monospace"; + bar_text_size = 11; + #// bar_title_enabled = false; + "col.text" = "rgb(93a1a1)"; + + #?? hyprbars-button = COLOR, SIZE, ICON, EXEC + hyprbars-button = [ + "rgb(dc322f), 16,, ${hyprctl} dispatch killactive" # Close + "rgb(d33682), 16,, ${hyprctl} dispatch fullscreen 1" # Maximize + "rgb(6c71c4), 16,, minimize" # Minimize + ]; + }; + }; + }; + }; + }; +} diff --git a/options/custom/desktops/hyprland/rules.nix b/options/custom/desktops/hyprland/rules.nix new file mode 100644 index 0000000..e04b912 --- /dev/null +++ b/options/custom/desktops/hyprland/rules.nix @@ -0,0 +1,263 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + gamescope = "${config.programs.gamescope.package}/bin/gamescope"; + loupe = "${pkgs.loupe}/bin/loupe"; + steam = "${config.programs.steam.package}/bin/steam"; + virt-manager = "${pkgs.virt-manager}/bin/virt-manager"; + waydroid = "${pkgs.waydroid}/bin/waydroid"; + kitty = "${config.home-manager.users.${config.custom.username}.programs.kitty.package}/bin/kitty"; + youtube-music = "${pkgs.youtube-music}/bin/youtube-music"; + + cfg = config.custom.desktops.hyprland.rules; +in +{ + options.custom.desktops.hyprland.rules.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + wayland.windowManager.hyprland.settings = { + # https://wiki.hyprland.org/Configuring/Workspace-Rules + #?? workspace = WORKSPACE, RULES + workspace = [ + "name:gamescope, on-created-empty:MANGOHUD=0 ${gamescope} --fullscreen --steam ${steam}" + + "special:android, on-created-empty:${waydroid} app launch com.YoStarEN.Arknights" + "special:music, on-created-empty:${youtube-music}" + "special:steam, on-created-empty:${steam}" + "special:terminal, on-created-empty:${kitty}" + "special:wallpaper, on-created-empty:[tile] ${loupe} /tmp/wallpaper.png" + ]; + + # https://wiki.hyprland.org/Configuring/Window-Rules + #?? windowrulev2 = RULE, WINDOW + windowrulev2 = + with config.custom; + let + # Return hypr-formatted string, converting booleans into 0/1 + format = + field: expr: + "${field}:${ + toString ( + if expr == true then + 1 + else if expr == false then + 0 + else + expr + ) + }"; + + # Generate hypr-formatted window rules + #?? merge + merge = + field: expr: rules: + map ( + rule: + if builtins.isAttrs field then + "${rule}, ${lib.concatStringsSep ", " (lib.mapAttrsToList (f: e: format f e) field)}" + else + "${rule}, ${format field expr}" + ) rules; + + class = expr: rules: merge "class" "^${expr}$" rules; + floating = expr: rules: merge "floating" expr rules; + fullscreen = expr: rules: merge "fullscreen" expr rules; + pinned = expr: rules: merge "pinned" expr rules; + tag = expr: rules: merge "tag" expr rules; + title = expr: rules: merge "title" "^${expr}$" rules; + + fields = fields: rules: merge fields null rules; + + ### Hardware-dependent rules + # Convert truncated float to string + tr = num: toString (builtins.floor num); + + # Bottom center + clipboard = rec { + x = tr (width / scale / 2 - (toInt w) / 2); + y = tr (height / scale - (toInt h) - gap - border - padding); + w = "600"; + h = tr (height / scale * 0.5 * scale); + }; + + # Bottom center + dropdown = rec { + x = tr (width / scale / 2 - (toInt w) / 2); + y = tr (height / scale - (toInt h) - gap - border - padding); + w = tr (width / scale * (if ultrawide then 0.5 else 1) - gap - gap / 2 + 1); + h = tr (height / scale * 0.2 * scale); + }; + + # Top right + pip = rec { + x = tr (width / scale - (toInt w) - gap - border); + y = tr (gap + border); + w = tr (width / scale * 0.25 - gap - gap + 1); + h = tr ((toInt w) * 9 / 16); # 16:9 aspect ratio + }; + in + flatten [ + ### Defaults + (class ".*" [ + "center" + "float" + "suppressevent maximize" + "syncfullscreen" + ]) + (floating true [ "bordercolor rgb(073642)" ]) + (fullscreen true [ "idleinhibit focus" ]) + (pinned true [ "bordercolor rgb(073642) rgb(073642)" ]) + + # TODO: Convert to nix variables instead of tags + ### Tags + (tag "android" [ + "tile" + "workspace special:android" + ]) + (tag "browser" [ + "group new lock" + "tile" + ]) + (tag "clipboard" [ + "move ${clipboard.x} ${clipboard.y}" + "pin" + "size ${clipboard.w} ${clipboard.h}" + "stayfocused" + ]) + (tag "dropdown" [ + "move ${dropdown.x} ${dropdown.y}" + "pin" + "size ${dropdown.w} ${dropdown.h}" + ]) + (tag "editor" [ + "group invade" + "tile" + ]) + (tag "files" [ + "size 1000 625" + ]) + (tag "game" [ + "group barred" + "idleinhibit always" + "noborder" + "noshadow" + "renderunfocused" + "workspace name:game" + ]) + (tag "music" [ + "tile" + "workspace special:music" + ]) + (tag "pip" [ + "keepaspectratio" + "move ${pip.x} ${pip.y}" + "pin" + "size ${pip.w} ${pip.h}" + ]) + (tag "social" [ + "group" + "tile" + ]) + (tag "steam" [ "workspace special:steam" ]) + (tag "terminal" [ "tile" ]) + (tag "vm" [ "workspace special:vm" ]) + (tag "wine" [ + "noborder" + "noshadow" + ]) + + ### Applications + (class ".*\\.(exe|x86_64)" [ "tag +wine" ]) # Wine + (class "(sdl-|wl|x)freerdp" [ + "nomaxsize" + "tag +vm" + "tile" + ]) + (class "cinny" [ "tag +social" ]) + (class "clipboard" [ "tag +clipboard" ]) + (class "codium-url-handler" [ "tag +editor" ]) # VSCode + (class "discord" [ "tag +social" ]) + (class "dropdown" [ "tag +dropdown" ]) + (class "Element" [ "tag +social" ]) + (class "foot" [ "tag +terminal" ]) + (class "kitty" [ "tag +terminal" ]) + (class "libreoffice.+" [ "tile" ]) + (class "moe\\.launcher\\.the-honkers-railway-launcher" [ + "size 1280 730" + "tag +game" + ]) + (class "obsidian" [ + "group barred" + "tag +editor" + ]) + (class "org\\.gnome\\.Nautilus" [ "tag +files" ]) + (class "org\\.telegram\\.desktop" [ "tag +social" ]) + (class "org\\.wezfurlong\\.wezterm" [ "tag +terminal" ]) + (class "SDL Application" [ "tag +steam" ]) # Steam + (class "Spotify" [ "tag +music" ]) + (class "steam_app_1473350" [ "workspace 0" ]) # (the) Gnorp Apologue + (class "steam" [ "tag +steam" ]) + (class "steam_app_.+" [ "tag +game" ]) # Proton + (class "Tap Wizard 2.x86_64" [ "workspace 0" ]) + (class "virt-manager" [ "tag +vm" ]) + (class "waydroid.*" [ "tag +android" ]) + (class "YouTube Music" [ "tag +music" ]) + + (title "Picture.in.[Pp]icture" [ "tag +pip" ]) + (title "Spotify Premium" [ "tag +music" ]) + + ### Overrides + #!! Expressions are not wrapped in ^$ + (fields + { + class = "^lutris$"; + title = "^Lutris$"; + } + [ + "center" + "size 1000 500" + ] + ) + (fields { + tag = "steam"; + title = "^notificationtoasts$"; + } [ "workspace unset" ]) + (fields { + tag = "steam"; + title = "^Steam$"; + } [ "tile" ]) + + (fields + { + class = "^com\\.github\\.wwmm\\.easyeffects$"; + title = "^Easy Effects$"; + } + [ + "size 50% 50%" + ] + ) + (fields + { + class = "^discord$"; + title = "^Discord Updater$"; + } + [ + "float" + "nofocus" + ] + ) + (fields { + class = "^virt-manager$"; + title = "^.+on QEMU/KVM$"; + } [ "tile" ]) + ]; + }; + }; +} diff --git a/options/custom/desktops/hyprland/settings.nix b/options/custom/desktops/hyprland/settings.nix new file mode 100644 index 0000000..85dd43a --- /dev/null +++ b/options/custom/desktops/hyprland/settings.nix @@ -0,0 +1,257 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + clipse = "${pkgs.clipse}/bin/clipse"; + firefox-esr = "${ + config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage + }/bin/firefox-esr"; + pkill = "${pkgs.procps}/bin/pkill"; + rm = "${pkgs.coreutils}/bin/rm"; + sleep = "${pkgs.coreutils}/bin/sleep"; + sway-audio-idle-inhibit = "${pkgs.sway-audio-idle-inhibit}/bin/sway-audio-idle-inhibit"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + waybar = "${ + config.home-manager.users.${config.custom.username}.programs.waybar.package + }/bin/waybar"; + + cfg = config.custom.desktops.hyprland.settings; +in +{ + options.custom.desktops.hyprland.settings.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + wayland.windowManager.hyprland.settings = { + # https://wiki.hyprland.org/Configuring/Variables/#debug + debug = { + #// disable_logs = false; + enable_stdout_logs = true; # systemd-cat + + #!! May result in resolution oddities + disable_scale_checks = true; + }; + + # https://wiki.hyprland.org/Configuring/Monitors + #?? monitor = NAME, RESOLUTION, POSITION, SCALE + monitor = [ + ", highrr, auto, ${toString config.custom.scale}" + + # HACK: Ensure the fallback output has a sane resolution + # https://github.com/hyprwm/Hyprland/issues/7276#issuecomment-2323346668 + "FALLBACK, ${toString config.custom.width}x${toString config.custom.height}@60, auto, ${toString config.custom.scale}" + ]; + + # https://wiki.hyprland.org/Configuring/Keywords/#setting-the-environment + #?? envd = VARIABLE, VALUE + # HACK: Mapped home-manager variables to envd in lieu of upstream fix + # https://github.com/nix-community/home-manager/issues/2659 + envd = + with builtins; + attrValues ( + mapAttrs ( + name: value: "${name}, ${toString value}" + ) config.home-manager.users.${config.custom.username}.home.sessionVariables + ) + ++ [ + "EDITOR, gnome-text-editor" + ]; + + # https://wiki.hyprland.org/Configuring/Keywords/#executing + #// exec = [ ]; + + # https://wiki.hyprland.org/Configuring/Keywords/#executing + exec-once = [ + "${rm} ~/.config/qalculate/qalc.dmenu.history" # Clear calc history + "${clipse} -clear" # Clear clipboard history + "${clipse} -listen" # Monitor clipboard + sway-audio-idle-inhibit # Inhibit idle while audio is playing + + # TODO: Remove when systemd service fixed + # https://github.com/Alexays/Waybar/issues/2882 + "${sleep} 2 && ${systemctl} --user restart waybar" + + "[tag +browser] ${firefox-esr}" + ] ++ optionals config.custom.wallpaper [ "wallpaper" ]; + + # https://wiki.hyprland.org/Configuring/Variables/#xwayland + xwayland = { + force_zero_scaling = true; + }; + + # https://wiki.hyprland.org/Configuring/Master-Layout + # Optimized for ultrawide use by default + master = { + allow_small_split = true; + always_center_master = true; + mfact = 0.5; + orientation = "center"; + }; + + # https://wiki.hyprland.org/Configuring/Variables/#general + general = { + "col.active_border" = "rgb(93a1a1)"; + "col.inactive_border" = "rgba(93a1a140)"; + "col.nogroup_border_active" = "rgb(dc322f)"; + "col.nogroup_border" = "rgba(dc322f40)"; + #// allow_tearing = true; + border_size = config.custom.border; + gaps_in = config.custom.gap / 2; + gaps_out = config.custom.gap; + layout = "master"; + #// no_border_on_floating = true; + resize_on_border = true; + }; + + # https://wiki.hyprland.org/Configuring/Animations + #?? animation = NAME, ONOFF, SPEED, CURVE, [STYLE] + animation = [ + "global, 1, 5, default" + "windows, 1, 5, default, slide" + "layers, 1, 5, default, slide" + "specialWorkspace, 1, 5, default, fade" + ]; + + # https://wiki.hyprland.org/Configuring/Variables/#decoration + decoration = { + "col.shadow_inactive" = "rgba(0000001a)"; + "col.shadow" = "rgba(00000040)"; + blur.enabled = false; + dim_special = 0.5; + rounding = 12; + shadow_range = 50; + shadow_render_power = 4; # Distance falloff + }; + + # https://wiki.hyprland.org/Configuring/Variables/#group + group = { + "col.border_active" = "rgb(6c71c4)"; + "col.border_inactive" = "rgba(6c71c440)"; + "col.border_locked_active" = "rgb(d33682)"; + "col.border_locked_inactive" = "rgba(d3368240)"; + insert_after_current = false; + + # https://wiki.hyprland.org/Configuring/Variables/#groupbar + groupbar = { + "col.active" = "rgb(6c71c4)"; + "col.inactive" = "rgba(6c71c440)"; + "col.locked_active" = "rgb(d33682)"; + "col.locked_inactive" = "rgba(d3368240)"; + font_size = if config.custom.hidpi then 16 else 10; + height = 5; + render_titles = false; + text_color = "rgb(93a1a1)"; + }; + }; + + # https://wiki.hyprland.org/Configuring/Variables/#misc + misc = { + #// animate_manual_resizes = true; + #// animate_mouse_windowdragging = true; + background_color = "rgb(073642)"; + disable_hyprland_logo = true; + disable_splash_rendering = true; + focus_on_activate = true; + font_family = "monospace"; + force_default_wallpaper = 0; + key_press_enables_dpms = true; + middle_click_paste = false; + + # BUG: Possibly still causes hard freezes + vrr = 2; # VRR in fullscreen + }; + + # https://wiki.hyprland.org/Configuring/Variables/#input + input = { + accel_profile = "flat"; + float_switch_override_focus = 0; # Disable float to tile hover focus + follow_mouse = 1; # Hover focus + mouse_refocus = false; + repeat_delay = 400; + repeat_rate = 40; + sensitivity = 0.5; + #// scroll_factor = 0.75; + + touchpad = { + clickfinger_behavior = true; # Multi-finger clicks + natural_scroll = true; + scroll_factor = 0.4; + }; + }; + + # https://wiki.hyprland.org/Configuring/Variables/#cursor + cursor = { + hotspot_padding = 10; + min_refresh_rate = 60; # !! Hardware dependent + no_break_fs_vrr = true; + #// no_hardware_cursors = true; + no_warps = true; + zoom_rigid = true; + }; + + # https://wiki.hyprland.org/Configuring/Variables/#gestures + gestures = { + workspace_swipe = true; + workspace_swipe_cancel_ratio = 0.2; + workspace_swipe_distance = 1000; + workspace_swipe_forever = true; + workspace_swipe_min_speed_to_force = 10; + }; + + # https://wiki.hyprland.org/Configuring/Keywords/#per-device-input-configs + #?? device = { name = NAME ... } + # TODO: Combine same devices + # FIXME: Hotplugging may result in different id + device = [ + { + name = "kensington-orbit-wireless-tb-mouse"; + accel_profile = "adaptive"; + sensitivity = -0.6; + left_handed = true; + middle_button_emulation = true; + natural_scroll = true; + } + + { + name = "orbit-bt5.0-mouse"; + accel_profile = "adaptive"; + sensitivity = -0.6; + left_handed = true; + middle_button_emulation = true; + natural_scroll = true; + } + + { + name = "logitech-m570"; + accel_profile = "adaptive"; + sensitivity = -0.9; + } + + { + name = "nordic-2.4g-wireless-receiver-mouse"; + sensitivity = -0.6; + } + + { + name = "protoarc-em11-nl-mouse"; + sensitivity = -0.6; + } + + { + name = "razer-razer-viper-ultimate-dongle"; + sensitivity = 0; + } + + { + name = "wireless-controller-touchpad"; + enabled = false; + } + ]; + }; + }; +} diff --git a/options/custom/desktops/kde/default.nix b/options/custom/desktops/kde/default.nix new file mode 100644 index 0000000..c001859 --- /dev/null +++ b/options/custom/desktops/kde/default.nix @@ -0,0 +1,12 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.desktops.kde; +in +{ + options.custom.desktops.kde.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { services.desktopManager.plasma6.enable = true; }; +} diff --git a/options/custom/files/agenix.nix b/options/custom/files/agenix.nix new file mode 100644 index 0000000..e23188a --- /dev/null +++ b/options/custom/files/agenix.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.files.agenix; +in +{ + # https://wiki.nixos.org/wiki/Agenix + # https://github.com/ryantm/agenix + options.custom.files.agenix.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.identityPaths = [ "/etc/ssh/id_ed25519" ]; # !! Must be set without sshd + }; +} diff --git a/options/custom/files/default.nix b/options/custom/files/default.nix new file mode 100644 index 0000000..b740578 --- /dev/null +++ b/options/custom/files/default.nix @@ -0,0 +1,12 @@ +{ config, lib, ... }: + +with lib; + +{ + config.custom.files = mkIf config.custom.default { + agenix.enable = true; + dev.enable = true; + mnt.enable = true; + nixos.enable = true; + }; +} diff --git a/options/custom/files/dev.nix b/options/custom/files/dev.nix new file mode 100644 index 0000000..1cc8a72 --- /dev/null +++ b/options/custom/files/dev.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.files.dev; +in +{ + options.custom.files.dev.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # .keep empty file needed to create empty directory + # https://github.com/nix-community/home-manager/issues/2104 + home.file.".dev/.keep".text = ""; # Development folder + }; +} diff --git a/options/custom/files/mnt.nix b/options/custom/files/mnt.nix new file mode 100644 index 0000000..aeb5aa8 --- /dev/null +++ b/options/custom/files/mnt.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.files.mnt; +in +{ + options.custom.files.mnt.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Set /mnt permissions + systemd.tmpfiles.rules = [ "z /mnt 0755 root root" ]; + }; +} diff --git a/options/custom/files/nixos.nix b/options/custom/files/nixos.nix new file mode 100644 index 0000000..c5040d1 --- /dev/null +++ b/options/custom/files/nixos.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.files.nixos; +in +{ + options.custom.files.nixos.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://www.freedesktop.org/software/systemd/man/latest/tmpfiles.d.html + # Create NixOS configuration directory and set permissions + systemd.tmpfiles.rules = [ + "d /etc/nixos 0755 myned root" + "Z /etc/nixos - myned root" # Recursively set owner + ]; + }; +} diff --git a/options/custom/programs/adb.nix b/options/custom/programs/adb.nix new file mode 100644 index 0000000..1d7140c --- /dev/null +++ b/options/custom/programs/adb.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.adb; +in +{ + options.custom.programs.adb.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Android + # https://developer.android.com/tools/adb + programs.adb.enable = true; + users.users.${config.custom.username}.extraGroups = [ "adbusers" ]; + }; +} diff --git a/options/custom/programs/ags/config.js b/options/custom/programs/ags/config.js new file mode 100644 index 0000000..b9fcfad --- /dev/null +++ b/options/custom/programs/ags/config.js @@ -0,0 +1,178 @@ +const battery = await Service.import('battery') +const audio = await Service.import('audio') +const hyprland = await Service.import('hyprland') +const mpris = await Service.import('mpris') +const notifications = await Service.import('notifications') +const systemtray = await Service.import('systemtray') + +/// WORKSPACES /// + +const Workspaces = () => Widget.EventBox({ + onScrollDown: () => hyprland.messageAsync(`dispatch workspace -1`), + onScrollUp: () => hyprland.messageAsync(`dispatch workspace +1`), + + child: Widget.Box({ + spacing: 8, + + //?? Increase length if workspaces > 10 + children: Array.from({ length: 10 }, (_, i) => i + 1).map(i => Widget.Button({ + onClicked: () => hyprland.messageAsync(`dispatch workspace ${i}`), + + attribute: i, + label: `${i}`, + })), + + // Initial button visibility + setup: self => self.hook(hyprland, () => self.children.forEach(btn => { + btn.visible = hyprland.workspaces.some(ws => ws.id === btn.attribute) + })), + }), +}) + +/// CLOCK /// + +const Clock = () => Widget.Label({ + class_name: 'clock', + + setup: self => self.poll(1000, self => + Utils.execAsync(['date', '+%a %b %d %I:%M %p']) + .then(date => self.label = date)), +}) + +/// NOTIFICATIONS /// + +const Notification = () => Widget.Box({ + class_name: 'notification', + visible: notifications.bind('popups').transform(p => p.length > 0), + children: [ + Widget.Icon({ + icon: 'preferences-system-notifications-symbolic', + }), + Widget.Label({ + label: notifications.bind('popups').transform(p => p[0]?.summary || ''), + }), + ], +}) + +/// PLAYER /// + +const Media = () => Widget.Button({ + class_name: 'media', + on_primary_click: () => mpris.getPlayer('')?.playPause(), + on_scroll_up: () => mpris.getPlayer('')?.next(), + on_scroll_down: () => mpris.getPlayer('')?.previous(), + child: Widget.Label('-').hook(mpris, self => { + if (mpris.players[0]) { + const { track_artists, track_title } = mpris.players[0] + self.label = `${track_artists.join(', ')} - ${track_title}` + } else { + self.label = 'Nothing is playing' + } + }, 'player-changed'), +}) + +/// VOLUME /// +console.log(audio.speaker) +const Volume = () => Widget.Button({ + on_clicked: () => audio.speaker.is_muted = !audio.speaker.is_muted, + + child: Widget.Icon().hook(audio.speaker, self => { + const icon = [ + [101, 'overamplified'], + [67, 'high'], + [34, 'medium'], + [0, 'low'], + ].find(([threshold]) => threshold <= audio.speaker.volume * 100)?.[1] + + self.icon = `audio-volume-${icon}-symbolic` + self.tooltip_text = `Volume ${Math.floor(audio.speaker.volume * 100)}%` + }), +}) + +/// BATTERY /// + +const Battery = () => Widget.Box({ + spacing: 4, + class_name: battery.bind('charging').transform(c => c ? 'charging' : ''), + visible: battery.bind('available'), + + children: [ + // Battery icon + Widget.Icon({ + icon: battery.bind('percent').transform(p => `battery-level-${Math.floor(p / 10) * 10}-symbolic`), + }), + + // Battery discharge wattage + Widget.Label({ + label: battery.bind('energy-rate').transform(e => `${Math.round(e)}W`), + }), + ], +}) + +/// TRAY /// + +const SysTray = () => Widget.Box({ + children: systemtray.bind('items').transform(items => { + return items.map(item => Widget.Button({ + child: Widget.Icon({ binds: [['icon', item, 'icon']] }), + on_primary_click: (_, event) => item.activate(event), + on_secondary_click: (_, event) => item.openMenu(event), + binds: [['tooltip-markup', item, 'tooltip-markup']], + })) + }), +}) + +/// LAYOUT /// + +const Left = () => Widget.Box({ + spacing: 8, + children: [ + Workspaces(), + ], +}) + +const Center = () => Widget.Box({ + spacing: 8, + children: [ + Clock(), + Notification(), + ], +}) + +const Right = () => Widget.Box({ + hpack: 'end', + spacing: 8, + children: [ + Media(), + SysTray(), + Volume(), + Battery(), + ], +}) + +const Bar = (monitor = 0) => Widget.Window({ + monitor, + name: `bar${monitor}`, + class_name: 'bar', + anchor: ['top', 'left', 'right'], + exclusivity: 'exclusive', + + child: Widget.EventBox({ + on_scroll_up: () => audio['speaker'].volume = audio['speaker'].volume + 1, + on_scroll_down: () => audio['speaker'].volume = audio['speaker'].volume + 1, + + child: Widget.CenterBox({ + spacing: 8, + start_widget: Left(), + center_widget: Center(), + end_widget: Right(), + }), + }) +}) + +/// EXPORTS /// + +export default { + style: './style.css', + windows: [Bar()], +} diff --git a/options/custom/programs/ags/default.nix b/options/custom/programs/ags/default.nix new file mode 100644 index 0000000..2ee45ff --- /dev/null +++ b/options/custom/programs/ags/default.nix @@ -0,0 +1,26 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.programs.ags; +in +{ + options.custom.programs.ags.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + imports = [ inputs.ags.homeManagerModules.default ]; + + # https://aylur.github.io/ags-docs + # https://github.com/Aylur/ags + programs.ags = { + enable = true; + configDir = ./.; + }; + }; +} diff --git a/options/custom/programs/ags/style.css b/options/custom/programs/ags/style.css new file mode 100644 index 0000000..e267fe0 --- /dev/null +++ b/options/custom/programs/ags/style.css @@ -0,0 +1,7 @@ +/*** AGS +***/ + +.bar { + font: 18px monospace; + color: #eee8d5; +} diff --git a/options/custom/programs/alacritty.nix b/options/custom/programs/alacritty.nix new file mode 100644 index 0000000..31653d1 --- /dev/null +++ b/options/custom/programs/alacritty.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.alacritty; +in +{ + options.custom.programs.alacritty.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/alacritty/alacritty + programs.alacritty = { + enable = true; + + # https://alacritty.org/config-alacritty.html + settings = { + font = { + #// builtin_box_drawing = false; + size = 14; + }; + + window = { + dynamic_padding = true; + resize_increments = true; + }; + }; + }; + }; +} diff --git a/options/custom/programs/anime-game-launcher.nix b/options/custom/programs/anime-game-launcher.nix new file mode 100644 index 0000000..ceece99 --- /dev/null +++ b/options/custom/programs/anime-game-launcher.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.anime-game-launcher; +in +{ + options.custom.programs.anime-game-launcher.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/an-anime-team + # https://github.com/ezKEa/aagl-gtk-on-nix + #?? If error on first setup, clone components + #?? git clone https://github.com/an-anime-team/components.git + programs.honkers-railway-launcher.enable = true; + }; +} diff --git a/options/custom/programs/anyrun.nix b/options/custom/programs/anyrun.nix new file mode 100644 index 0000000..da9c873 --- /dev/null +++ b/options/custom/programs/anyrun.nix @@ -0,0 +1,67 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.anyrun; +in +{ + options.custom.programs.anyrun.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + imports = [ inputs.anyrun.home-managerModules.default ]; + + # https://github.com/Kirottu/anyrun + programs.anyrun = { + enable = true; + + # https://github.com/Kirottu/anyrun/blob/master/nix/hm-module.nix + config = { + plugins = with inputs.anyrun.packages.${pkgs.system}; [ + applications + dictionary + #// kidex # File search + #// randr # Hyprland only\{ + + rink # Calculator + shell + #// stdin # Entries from input, aka dmenu + symbols + translate + websearch + ]; + + closeOnClick = true; # Close when clicking outside the runner + hidePluginInfo = true; # Disable plugin sections + y.fraction = 0.3; # Relative position from the top + }; + + # https://github.com/Kirottu/anyrun/blob/master/anyrun/res/style.css + extraCss = '' + *:not(separator) { + margin: 2px; + border-radius: 20px; + } + + *:focus { outline: none; } + + #window { + font: 16px monospace; + background: none; + } + + #entry { + margin: 8px; + padding: 4px 12px; + font-size: 24px; + } + ''; + }; + }; +} diff --git a/options/custom/programs/appimage.nix b/options/custom/programs/appimage.nix new file mode 100644 index 0000000..3a69ff6 --- /dev/null +++ b/options/custom/programs/appimage.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.appimage; +in +{ + options.custom.programs.appimage.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Appimage + programs.appimage = { + enable = true; + binfmt = true; + }; + }; +} diff --git a/options/custom/programs/bitwarden-menu.nix b/options/custom/programs/bitwarden-menu.nix new file mode 100644 index 0000000..9264bc7 --- /dev/null +++ b/options/custom/programs/bitwarden-menu.nix @@ -0,0 +1,31 @@ +{ config, lib, ... }: + +with lib; + +let + wofi = "${config.home-manager.users.${config.custom.username}.programs.wofi.package}/bin/wofi"; + + cfg = config.custom.programs.bitwarden-menu; +in +{ + options.custom.programs.bitwarden-menu.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/firecat53/bitwarden-menu + #!! Options not available, files written directly + # https://github.com/firecat53/bitwarden-menu/blob/main/docs/configure.md + home.file.".config/bwm/config.ini".text = '' + [dmenu] + dmenu_command = ${wofi} --dmenu + + [dmenu_passphrase] + obscure = True + + # FIXME: Login options taking effect + [vault] + server = https://vault.bitwarden.com + twofactor = 0 + session_timeout_min = 720 + ''; + }; +} diff --git a/options/custom/programs/chromium.nix b/options/custom/programs/chromium.nix new file mode 100644 index 0000000..eae2bd6 --- /dev/null +++ b/options/custom/programs/chromium.nix @@ -0,0 +1,35 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.chromium; +in +{ + options.custom.programs.chromium.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Chromium + # https://www.chromium.org/chromium-projects + programs.chromium = { + enable = true; + + commandLineArgs = [ + "--enable-features=OverlayScrollbar,ChromeRefresh2023,TabGroupsSave,TouchpadOverscrollHistoryNavigation" + ]; + + extensions = [ + #"ajopnjidmegmdimjlfnijceegpefgped" # BetterTTV + #"nngceckbapebfimnlniiiahkandclblb" # Bitwarden + #"enamippconapkdmgfgjchkhakpfinmaj" # DeArrow + #"fnaicdffflnofjppbagibeoednhnbjhg" # floccus + #"bnomihfieiccainjcjblhegjgglakjdd" # Improve YouTube + #"mnjggcdmjocbbbhaepdhchncahnbgone" # SponsorBlock + #"clngdbkpkpeebahjckkjfobafhncgmne" # Stylus + #"kfidecgcdjjfpeckbblhmfkhmlgecoff" # Svelte DevTools + #"nplimhmoanghlebhdiboeellhgmgommi" # Tab Groups Extension + "ddkjiahejlhfcafbddmgiahcphecmpfh" # uBlock Origin Lite + ]; + }; + }; +} diff --git a/options/custom/programs/clipse.nix b/options/custom/programs/clipse.nix new file mode 100644 index 0000000..6aa6019 --- /dev/null +++ b/options/custom/programs/clipse.nix @@ -0,0 +1,38 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.clipse; +in +{ + options.custom.programs.clipse.enable = mkOption { default = false; }; + + config = { + # https://github.com/savedra1/clipse + environment.systemPackages = with pkgs; [ + clipse + wl-clipboard + xclip + ]; + + home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/savedra1/clipse?tab=readme-ov-file#configuration + home.file.".config/clipse/config.json".text = '' + { + "historyFile": "clipboard_history.json", + "maxHistory": 100, + "allowDuplicates": false, + "themeFile": "custom_theme.json", + "tempDir": "tmp_files", + "logFile": "clipse.log" + } + ''; + }; + }; +} diff --git a/options/custom/programs/dconf.nix b/options/custom/programs/dconf.nix new file mode 100644 index 0000000..636d236 --- /dev/null +++ b/options/custom/programs/dconf.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.dconf; +in +{ + options.custom.programs.dconf.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://gitlab.gnome.org/GNOME/dconf + programs.dconf.enable = true; + }; +} diff --git a/options/custom/programs/default.nix b/options/custom/programs/default.nix new file mode 100644 index 0000000..adfde8f --- /dev/null +++ b/options/custom/programs/default.nix @@ -0,0 +1,78 @@ +{ config, lib, ... }: + +with lib; + +{ + config.custom.programs = mkMerge [ + (mkIf config.custom.default { + direnv.enable = true; + fastfetch.enable = true; + fish.enable = true; + git.enable = true; + htop.enable = true; + man.enable = true; + mosh.enable = true; + nano.enable = true; + nh.enable = true; + nix-index.enable = true; + nushell.enable = true; + ssh.enable = true; + tmux.enable = true; + }) + + (mkIf config.custom.minimal { + #// alacritty.enable = true; + appimage.enable = true; + chromium.enable = true; + dconf.enable = true; + firefox.enable = true; + #// foot.enable = true; + #// gnome-terminal.enable = true; + kdeconnect.enable = true; + kitty.enable = true; + nautilus.enable = true; + nvtop.enable = true; + #// wezterm.enable = true; + }) + + (mkIf config.custom.full { + adb.enable = true; + ags.enable = true; + #// anyrun.enable = true; + #// bitwarden-menu.enable = true; + clipse.enable = true; + discord.enable = true; + element-desktop.enable = true; + #// fuzzel.enable = true; + gamemode.enable = true; + gamescope.enable = true; + #// gnome-shell.enable = true; + gpg.enable = true; + hyprlock.enable = true; + libreoffice.enable = true; + #// librewolf.enable = true; + localsend.enable = true; + logseq.enable = true; + mangohud.enable = true; + networkmanager-dmenu.enable = true; + #// nheko.enable = true; + nix-ld.enable = true; + obs-studio.enable = true; + #// onedrive.enable = true; + path-of-building.enable = true; + rbw.enable = true; + rofi-rbw.enable = true; + rofi.enable = true; + seahorse.enable = true; + slurp.enable = true; + steam.enable = true; + #// swaylock.enable = true; + #// thunderbird.enable = true; + tio.enable = true; + vscode.enable = true; + waybar.enable = true; + wofi.enable = true; + #// wpaperd.enable = true; + }) + ]; +} diff --git a/options/custom/programs/direnv.nix b/options/custom/programs/direnv.nix new file mode 100644 index 0000000..4b48137 --- /dev/null +++ b/options/custom/programs/direnv.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.direnv; +in +{ + options.custom.programs.direnv.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/direnv/direnv + programs.direnv = { + enable = true; + loadInNixShell = false; # nix develop + silent = true; + }; + }; +} diff --git a/options/custom/programs/discord.nix b/options/custom/programs/discord.nix new file mode 100644 index 0000000..850fd9d --- /dev/null +++ b/options/custom/programs/discord.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.discord; +in +{ + options.custom.programs.discord.enable = mkOption { default = false; }; + + config.home-manager.users.myned = mkIf cfg.enable { + home.file.".config/BetterDiscord".source = + config.home-manager.users.${config.custom.username}.lib.file.mkOutOfStoreSymlink + "/home/${config.custom.username}/SYNC/common/config/discord/BetterDiscord"; + }; +} diff --git a/options/custom/programs/element-desktop.nix b/options/custom/programs/element-desktop.nix new file mode 100644 index 0000000..0f7c0a2 --- /dev/null +++ b/options/custom/programs/element-desktop.nix @@ -0,0 +1,45 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.element-desktop; +in +{ + options.custom.programs.element-desktop.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # Element Desktop custom themes + # https://github.com/aaronraimist/element-themes + home.file.".config/Element/config.json".text = '' + { + "show_labs_settings": true, + "setting_defaults": { + "custom_themes": [ + { + "name": "Solarized", + "is_dark": true, + "colors": { + "accent-color": "#b58900", + "primary-color": "#268bd2", + "reaction-row-button-selected-bg-color": "#268bd2", + "roomlist-background-color": "#073642", + "roomlist-highlights-color": "#002b36", + "roomlist-text-color": "#93a1a1", + "roomlist-text-secondary-color": "#586e75", + "secondary-content": "#93a1a1", + "sidebar-color": "#002b36", + "tertiary-content": "#586e75", + "timeline-background-color": "#073642", + "timeline-highlights-color": "#002b36", + "timeline-text-color": "#fdf6e3", + "timeline-text-secondary-color": "#93a1a1", + "warning-color": "#dc322f" + } + } + ] + } + } + ''; + }; +} diff --git a/options/custom/programs/fastfetch.nix b/options/custom/programs/fastfetch.nix new file mode 100644 index 0000000..e813748 --- /dev/null +++ b/options/custom/programs/fastfetch.nix @@ -0,0 +1,58 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + fastfetch = "${pkgs.fastfetch}/bin/fastfetch"; + + cfg = config.custom.programs.fastfetch; +in +{ + options.custom.programs.fastfetch = { + enable = mkOption { default = false; }; + greet = mkOption { default = false; }; + }; + + config = mkIf cfg.enable { + # https://github.com/fastfetch-cli/fastfetch + environment.systemPackages = [ pkgs.fastfetch ]; + + # System info greeting + programs.fish.interactiveShellInit = mkIf cfg.greet '' + # If not root, print greeting + if test (id -u) -ne 0 + function fish_greeting + ${fastfetch} + end + end + ''; + + # https://github.com/fastfetch-cli/fastfetch + #!! Option not available, files written directly + home-manager.users.${config.custom.username}.home.file.".config/fastfetch/config.jsonc".text = '' + { + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "source": "none", + }, + "modules": [ + "publicip", + "datetime", + "uptime", + "processes", + "cpuusage", + "memory", + "swap", + "disk", + "diskio", + "netio", + ] + } + ''; + }; +} diff --git a/options/custom/programs/firefox.nix b/options/custom/programs/firefox.nix new file mode 100644 index 0000000..a81862f --- /dev/null +++ b/options/custom/programs/firefox.nix @@ -0,0 +1,590 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.firefox; +in +{ + options.custom.programs.firefox.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # TODO: Switch to librewolf when supported by module + # https://github.com/nix-community/home-manager/pull/5128 + #!! Creates package derivation + #?? config.home-manager.users.${config.custom.username}.programs.firefox.finalPackage + # https://www.mozilla.org/en-US/firefox/developer + programs.firefox = { + enable = true; + package = pkgs.firefox-esr-128; + + # nativeMessagingHosts = with pkgs; [ + # firefoxpwa + # gnome-browser-connector + # ]; + + #!! Prefer policy over profile + #?? about:profiles + profiles.default = { + # Import CSS theme with solarized overrides + # https://github.com/rafaelmardojai/firefox-gnome-theme/blob/master/theme/colors/dark.css + userChrome = '' + @import "firefox-gnome-theme/userChrome.css"; + + :root { + --gnome-accent: #6c71c4; + --gnome-window-background: #002b36; + --gnome-window-color: #93a1a1; + --gnome-view-background: #073642; + --gnome-sidebar-background: #002b36; + --gnome-secondary-sidebar-background: #002b36; + --gnome-menu-background: #073642; + --gnome-headerbar-background: #002b36; + --gnome-toolbar-icon-fill: #93a1a1; + --gnome-tabbar-tab-hover-background: #073642; + --gnome-tabbar-tab-active-background: #073642; + --gnome-tabbar-tab-active-hover-background: #073642; + } + + :root:-moz-window-inactive { + --gnome-inactive-entry-color: #586e75; + --gnome-tabbar-tab-hover-background: #073642; + --gnome-tabbar-tab-active-background: #073642; + } + + /* Center bookmarks */ + #PlacesToolbarItems { + justify-content: center; + } + + /* Disable bookmark folder icons */ + .bookmark-item[container] > .toolbarbutton-icon { + display: none; + } + ''; + + userContent = ''@import "firefox-gnome-theme/userContent.css";''; + + settings = { + # https://github.com/rafaelmardojai/firefox-gnome-theme?tab=readme-ov-file#features + "gnomeTheme.bookmarksToolbarUnderTabs" = true; + "gnomeTheme.systemIcons" = true; + + "font.default.x-unicode" = "sans-serif"; + "font.default.x-western" = "sans-serif"; + "font.name-list.emoji" = "emoji"; # System emoji + "font.name.monospace.x-unicode" = "monospace"; + "font.name.monospace.x-western" = "monospace"; + "font.name.sans-serif.x-unicode" = "sans-serif"; + "font.name.sans-serif.x-western" = "sans-serif"; + "font.name.serif.x-unicode" = "sans-serif"; + "font.name.serif.x-western" = "sans-serif"; + "full-screen-api.ignore-widgets" = false; # Fake fullscreen + "full-screen-api.warning.delay" = -1; + "full-screen-api.warning.timeout" = 0; + "middlemouse.paste" = false; + "privacy.donottrackheader.enabled" = true; + "privacy.fingerprintingProtection" = false; + "privacy.globalprivacycontrol.enabled" = true; + "svg.context-properties.content.enabled" = true; # Dark theme icons + }; + }; + + # https://mozilla.github.io/policy-templates + policies = { + CaptivePortal = false; + DisableFirefoxStudies = true; + DisableFormHistory = true; + DisableMasterPasswordCreation = true; + DisablePocket = true; + DisableSetDesktopBackground = true; + DisableTelemetry = true; + + DNSOverHTTPS = { + Enabled = false; + Locked = true; + }; + + DontCheckDefaultBrowser = true; + + # https://mozilla.github.io/policy-templates/#extensionsettings + #?? https://addons.mozilla.org/en-US/firefox + #?? about:support#addons + ExtensionSettings = + let + extension = id: { + install_url = "https://addons.mozilla.org/firefox/downloads/latest/${id}/latest.xpi"; + installation_mode = "normal_installed"; + }; + in + mkMerge [ + (mkIf config.custom.minimal { + "uBlock0@raymondhill.net" = extension "ublock-origin"; # uBlock Origin + }) + + (mkIf config.custom.full { + #// "firefox@betterttv.net" = extension "betterttv"; # BetterTTV + "{446900e4-71c2-419f-a6a7-df9c091e268b}" = extension "bitwarden-password-manager"; # Bitwarden + #// "FirefoxColor@mozilla.com" = extension "firefox-color"; # Firefox Color + #// "chrome-gnome-shell@gnome.org" = extension "gnome-shell-integration"; # GNOME Shell Integration + #// "{248e6a49-f636-4c81-9899-a456eb6291a8}" = extension "ground-news-bias-checker"; # Ground News Bias Checker + "{3c6bf0cc-3ae2-42fb-9993-0d33104fdcaf}" = extension "youtube-addon"; # ImprovedTube + "7esoorv3@alefvanoon.anonaddy.me" = extension "libredirect"; # LibRedirect + #// "firefoxpwa@filips.si" = extension "pwas-for-firefox"; # Progressive Web Apps for Firefox + "select-after-closing-current@qw.linux-2g64.local" = extension "select-after-closing-current"; # Select After Closing Current + "simple-tab-groups@drive4ik" = extension "simple-tab-groups"; # Simple Tab Groups + "sponsorBlocker@ajay.app" = extension "sponsorblock"; # SponsorBlock + "{7a7a4a92-a2a0-41d1-9fd7-1e92480d612d}" = extension "styl-us"; # Stylus + #// "{a0370179-acc3-452f-9530-246b6adb2768}" = extension "svelte-devtools"; # Svelte Devtools + "uBlock0@raymondhill.net" = extension "ublock-origin"; # uBlock Origin + "{a6c4a591-f1b2-4f03-b3ff-767e5bedf4e7}" = extension "user-agent-string-switcher"; # User-Agent Switcher and Manager + #// "{c49b13b1-5dee-4345-925e-0c793377e3fa}" = extension "youtube-enhancer-vc"; # YouTube Enhancer + }) + ]; + + FirefoxHome = { + Highlights = false; + Pocket = false; + Search = false; + Snippets = false; + SponsoredPocket = false; + SponsoredTopSites = false; + TopSites = false; + Locked = true; + }; + + FirefoxSuggest = { + ImproveSuggest = false; + SponsoredSuggestions = false; + WebSuggestions = false; + Locked = true; + }; + + HardwareAcceleration = true; + + Homepage = { + StartPage = "previous-session"; + Locked = true; + }; + + NetworkPrediction = false; + NoDefaultBookmarks = true; + OfferToSaveLogins = false; + OverrideFirstRunPage = ""; + PasswordManagerEnabled = false; + + Permissions = { + Autoplay.Default = "block-audio-video"; + Location.BlockNewRequests = true; + }; + + PictureInPicture = { + Enabled = true; + Locked = true; + }; + + PopupBlocking.Default = true; + + #!! Only certain preferences are supported via policies + # https://mozilla.github.io/policy-templates/#preferences + #?? about:config + Preferences = + let + locked = value: { + Value = value; + Status = "locked"; + }; + in + { + "accessibility.browsewithcaret" = locked false; + "accessibility.typeaheadfind" = locked false; + "browser.aboutConfig.showWarning" = locked false; + "browser.contentblocking.category" = locked "standard"; + "browser.crashReports.unsubmittedCheck.autoSubmit2" = locked false; + "browser.ctrlTab.sortByRecentlyUsed" = locked false; + "browser.download.always_ask_before_handling_new_types" = locked false; + "browser.download.useDownloadDir" = locked true; + "browser.link.open_newwindow" = locked 3; # New tab + "browser.link.open_newwindow.restriction" = locked 0; # Popups in new tab + "browser.newtabpage.enabled" = locked true; + "browser.preferences.defaultPerformanceSettings.enabled" = locked true; + "browser.quitShortcut.disabled" = locked true; + "browser.search.widget.inNavBar" = locked false; + "browser.startup.homepage" = locked "about:home"; + "browser.startup.page" = locked 3; # Previous session + "browser.tabs.closeTabByDblclick" = locked true; + "browser.tabs.closeWindowWithLastTab" = locked false; + "browser.tabs.insertAfterCurrent" = locked false; + "browser.tabs.insertRelatedAfterCurrent" = locked false; + "browser.tabs.loadInBackground" = locked true; + "browser.tabs.warnOnClose" = locked false; + "browser.tabs.warnOnCloseOtherTabs" = locked false; + "browser.theme.dark-private-windows" = locked false; + "browser.toolbars.bookmarks.showOtherBookmarks" = locked false; + "browser.uidensity" = locked 0; + "browser.warnOnQuitShortcut" = locked true; + "dom.security.https_only_mode" = locked true; + "extensions.formautofill.addresses.enabled" = locked false; + "extensions.formautofill.creditCards.enabled" = locked false; + "general.autoScroll" = locked false; + "general.smoothScroll" = locked true; + "layers.acceleration.force-enabled" = locked true; + "layout.css.always_underline_links" = locked false; + "layout.css.backdrop-filter.enabled" = locked true; + "layout.spellcheckDefault" = locked 0; # Disabled + "media.eme.enabled" = locked true; # DRM + "media.hardwaremediakeys.enabled" = locked true; + "media.hardware-video-decoding.enabled" = locked false; # !! Disable video acceleration + #// "media.rdd-process.enabled" = locked false; # RDD sandbox #!! Insecure + "toolkit.legacyUserProfileCustomizations.stylesheets" = locked true; + "ui.key.menuAccessKey" = locked 0; # Disable menu key + "widget.gtk.overlay-scrollbars.enabled" = locked true; + "widget.gtk.rounded-bottom-corners.enabled" = locked true; + }; + + SearchBar = "unified"; + + # https://mozilla.github.io/policy-templates/#searchengines-this-policy-is-only-available-on-the-esr + SearchEngines = { + Default = "SearXNG"; + + Add = [ + { + Name = "Amazon"; + Alias = "a"; + IconURL = "https://www.amazon.com/favicon.ico"; + URLTemplate = "https://www.amazon.com/s?k={searchTerms}"; + } + + { + Name = "ArchWiki"; + Alias = "aw"; + IconURL = "https://wiki.archlinux.org/favicon.ico"; + URLTemplate = "https://wiki.archlinux.org/index.php?search={searchTerms}"; + } + + { + Name = "Brave"; + Alias = "b"; + IconURL = "https://cdn.search.brave.com/serp/v2/_app/immutable/assets/favicon.c09fe1a1.ico"; + URLTemplate = "https://search.brave.com/search?q={searchTerms}"; + } + + { + Name = "Docker Hub"; + Alias = "dh"; + IconURL = "https://hub.docker.com/favicon.ico"; + URLTemplate = "https://hub.docker.com/search?q={searchTerms}"; + } + + { + Name = "Duck"; + Alias = "d"; + IconURL = "https://duckduckgo.com/favicon.ico"; + URLTemplate = "https://duckduckgo.com/?q={searchTerms}"; + SuggestURLTemplate = "https://duckduckgo.com/ac/?type=list&q={searchTerms}"; + } + + { + Name = "e621"; + Alias = "e"; + IconURL = "https://e621.net/favicon.ico"; + URLTemplate = "https://e621.net/posts?tags={searchTerms}"; + } + + { + Name = "Element Issues"; + Alias = "ei"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/element-hq/element-web/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "Flathub"; + Alias = "fh"; + IconURL = "https://flathub.org/favicon.png"; + URLTemplate = "https://flathub.org/apps/search?q={searchTerms}"; + } + + { + Name = "GitHub"; + Alias = "gh"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/search?q={searchTerms}"; + } + + { + Name = "Google"; + Alias = "g"; + IconURL = "https://www.google.com/favicon.ico"; + URLTemplate = "https://www.google.com/search?q={searchTerms}"; + } + + { + Name = "Home Manager Options"; + Alias = "ho"; + IconURL = "https://home-manager-options.extranix.com/images/favicon.png"; + URLTemplate = "https://home-manager-options.extranix.com/?query={searchTerms}&release=master"; + } + + { + Name = "Home Manager Issues"; + Alias = "hi"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/nix-community/home-manager/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "Hyprland Issues"; + Alias = "hyi"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/hyprwm/Hyprland/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "Lix Issues"; + Alias = "li"; + IconURL = "https://git.lix.systems/assets/img/favicon.png"; + URLTemplate = "https://git.lix.systems/lix-project/lix/issues?state=open&q={searchTerms}"; + } + + { + Name = "i3 Issues"; + Alias = "ii"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/i3/i3/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "Lutris"; + Alias = "l"; + IconURL = "https://lutris.net/favicon.ico"; + URLTemplate = "https://lutris.net/games?q={searchTerms}"; + } + + { + Name = "Mozilla Web Docs"; + Alias = "mdn"; + IconURL = "https://developer.mozilla.org/favicon-48x48.cbbd161b.png"; + URLTemplate = "https://developer.mozilla.org/en-US/search?q={searchTerms}"; + } + + { + Name = "MyNixOS Options"; + Alias = "mno"; + IconURL = "https://mynixos.com/favicon.ico"; + URLTemplate = "https://mynixos.com/search?q=option+{searchTerms}"; + } + + { + Name = "Nix Dev"; + Alias = "nd"; + IconURL = "https://nix.dev/manual/nix/latest/favicon.png"; + URLTemplate = "https://nix.dev/manual/nix/latest?search={searchTerms}"; + } + + { + Name = "Nix Hub"; + Alias = "nh"; + IconURL = "https://www.nixhub.io/favicon.ico"; + URLTemplate = "https://www.nixhub.io/search?q={searchTerms}"; + } + + { + Name = "Nix PR"; + Alias = "npr"; + URLTemplate = "https://nixpk.gs/pr-tracker.html?pr={searchTerms}"; + } + + { + Name = "NixOS Flakes"; + Alias = "nf"; + IconURL = "https://nixos.org/favicon.png"; + URLTemplate = "https://search.nixos.org/flakes?channel=unstable&query={searchTerms}"; + } + + { + Name = "NixOS Nixpkgs Issues"; + Alias = "ni"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/NixOS/nixpkgs/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "NixOS Options"; + Alias = "no"; + IconURL = "https://nixos.org/favicon.png"; + URLTemplate = "https://search.nixos.org/options?channel=unstable&query={searchTerms}"; + } + + { + Name = "NixOS Packages"; + Alias = "np"; + IconURL = "https://nixos.org/favicon.png"; + URLTemplate = "https://search.nixos.org/packages?channel=unstable&query={searchTerms}"; + } + + { + Name = "NixOS Wiki"; + Alias = "nw"; + IconURL = "https://wiki.nixos.org/favicon.ico"; + URLTemplate = "https://wiki.nixos.org/w/index.php?search={searchTerms}"; + } + + { + Name = "Noogle Dev"; + Alias = "nod"; + IconURL = "https://noogle.dev/favicon.png"; + URLTemplate = "https://noogle.dev/q?term={searchTerms}"; + } + + { + Name = "PCGamingWiki"; + Alias = "pc"; + IconURL = "https://static.pcgamingwiki.com/favicons/pcgamingwiki.png"; + URLTemplate = "https://www.pcgamingwiki.com/w/index.php?search={searchTerms}"; + } + + { + Name = "Piped"; + Alias = "p"; + IconURL = "https://piped.bjork.tech/favicon.ico"; + URLTemplate = "https://piped.bjork.tech/results?search_query={searchTerms}"; + } + + { + Name = "ProtonDB"; + Alias = "pdb"; + IconURL = "https://www.protondb.com/sites/protondb/images/favicon.ico"; + URLTemplate = "https://www.protondb.com/search?q={searchTerms}"; + } + + { + Name = "PyPI"; + Alias = "pip"; + IconURL = "https://pypi.org/static/images/favicon.35549fe8.ico"; + URLTemplate = "https://pypi.org/search/?q={searchTerms}"; + } + + { + Name = "Reddit"; + Alias = "r"; + IconURL = "https://www.redditstatic.com/desktop2x/img/favicon/favicon-96x96.png"; + URLTemplate = "https://search.bjork.tech/search?q=site%3Areddit.com+{searchTerms}"; + } + + { + Name = "SearXNG"; + Alias = "s"; + IconURL = "https://search.bjork.tech/static/themes/simple/img/favicon.png"; + URLTemplate = "https://search.bjork.tech/search?q={searchTerms}"; + } + + { + Name = "Sway Issues"; + Alias = "si"; + IconURL = "https://github.com/favicon.ico"; + URLTemplate = "https://github.com/swaywm/sway/issues?q=is%3Aissue+is%3Aopen+{searchTerms}"; + } + + { + Name = "Wikipedia"; + Alias = "w"; + IconURL = "https://en.wikipedia.org/static/favicon/wikipedia.ico"; + URLTemplate = "https://en.wikipedia.org/w/index.php?search={searchTerms}"; + } + + { + Name = "Wolfram Alpha"; + Alias = "wa"; + IconURL = "https://www.wolframalpha.com/_next/static/images/favicon_1zbE9hjk.ico"; + URLTemplate = "https://www.wolframalpha.com/input?i={searchTerms}"; + } + + { + Name = "YouTube"; + Alias = "y"; + IconURL = "https://www.youtube.com/s/desktop/f8c8418d/img/favicon.ico"; + URLTemplate = "https://www.youtube.com/results?search_query={searchTerms}"; + } + ]; + + Remove = [ + "Amazon.com" + "Bing" + "DuckDuckGo" + "eBay" + "Google" + "Wikipedia (en)" + ]; + }; + + SearchSuggestEnabled = true; + ShowHomeButton = true; + + UserMessaging = { + ExtensionRecommendations = false; + FeatureRecommendations = false; + MoreFromMozilla = false; + SkipOnboarding = false; + UrlbarInterventions = false; + WhatsNew = false; + Locked = true; + }; + }; + }; + + home.file = { + # TODO: Consider other themes + # https://github.com/soulhotel/FF-ULTIMA + + # CSS theme to import into profile + # https://github.com/rafaelmardojai/firefox-gnome-theme + ".mozilla/firefox/default/chrome/firefox-gnome-theme".source = inputs.firefox-gnome-theme; + + # Imperative symlinks intended to be synced + "Downloads/stg".source = mkIf config.custom.full ( + config.home-manager.users.${config.custom.username}.lib.file.mkOutOfStoreSymlink + "/home/myned/SYNC/common/config/extensions/Simple Tab Groups" + ); + + # Work around icon dissociation due to missing --name flag in actions + # https://github.com/micheleg/dash-to-dock/issues/1968 + #!! Keep updated with upstream desktop file + #?? cat /etc/profiles/per-user/myned/share/applications/firefox-esr.desktop + # ".local/share/applications/firefox-esr.desktop".text = '' + # [Desktop Entry] + # Actions=new-private-window;new-window;profile-manager-window + # Categories=Network;WebBrowser + # Exec=firefox --name firefox %U + # GenericName=Web Browser + # Icon=firefox + # MimeType=text/html;text/xml;application/xhtml+xml;application/vnd.mozilla.xul+xml;x-scheme-handler/http;x-scheme-handler/https + # Name=Firefox ESR + # StartupNotify=true + # StartupWMClass=firefox + # Terminal=false + # Type=Application + # Version=1.4 + + # [Desktop Action new-private-window] + # Exec=firefox --name firefox --private-window %U + # Name=New Private Window + + # [Desktop Action new-window] + # Exec=firefox --name firefox --new-window %U + # Name=New Window + + # [Desktop Action profile-manager-window] + # Exec=firefox --name firefox --ProfileManager + # Name=Profile Manager + # ''; + }; + }; +} diff --git a/options/custom/programs/fish.nix b/options/custom/programs/fish.nix new file mode 100644 index 0000000..578480f --- /dev/null +++ b/options/custom/programs/fish.nix @@ -0,0 +1,161 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.fish; +in +{ + options.custom.programs.fish.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Fish + # https://github.com/fish-shell/fish-shell + programs.fish = { + enable = true; + + shellAbbrs = { + c = "clear"; + e = "exit"; + m = "mosh"; + s = "ssh"; + i = "tailscale ip --4"; + + "/h" = "cd ~"; + "/hd" = "cd ~/.dev"; + "/e" = "cd /etc"; + "/en" = "cd /etc/nixos"; + "/n" = "cd /nix"; + "/nv" = "cd /nix/var"; + "/nvn" = "cd /nix/var/nix"; + "/nvnp" = "cd /nix/var/nix/profiles"; + "/nvnps" = "cd /nix/var/nix/profiles/system"; + "/r" = "cd /run"; + "/rc" = "cd /run/current-system"; + + f = "flakegen"; + r = "rebuild"; + rb = "rebuild boot"; + rbp = "rebuild boot && poweroff"; + rbr = "rebuild boot && reboot"; + rs = "rebuild switch"; + rt = "rebuild test"; + t = "target"; + u = "upgrade"; + ub = "upgrade boot"; + ubp = "upgrade boot && poweroff"; + ubr = "upgrade boot && reboot"; + + nd = "nvd diff /run/current-system /nix/var/nix/profiles/system"; + no = "nh os"; + nb = "flakegen && nh os boot"; + nbr = "flakegen && nh os boot && reboot"; + nbp = "flakegen && nh os boot && poweroff"; + ns = "flakegen && nh os switch"; + nt = "flakegen && nh os test"; + + jc = "journalctl"; + sc = "systemctl"; + + d = "docker"; + dc = "docker compose"; + dcd = "docker compose down"; + dce = "docker compose exec"; + dcl = "docker compose logs"; + dcp = "docker compose pull"; + dcu = "docker compose up"; + dcuf = "docker compose up --force-recreate"; + ds = "docker system"; + + g = "git"; + gb = "git bisect"; + gbb = "git bisect bad"; + gbg = "git bisect good"; + gc = "git clone"; + gs = "git status"; + + ta = "tmux attach"; + td = "tmux detach"; + tk = "tmux kill-session"; + tl = "tmux list-sessions"; + + k = "kitten"; + ks = "kitten ssh"; + }; + + interactiveShellInit = '' + # Default is brblack (bright0) + set -g fish_color_autosuggestion brgreen + + function exit -d 'Always exit successfully when interactive' + builtin exit 0 + end + + # TODO: Pass flags properly + # TODO: Convert to bash + function run -d 'Run packages via nixpkg flakes' + for i in (seq (count $argv)) + if ! string match -r '^-' -- $argv[$i] + set argv[$i] (string replace -r ^ nixpkgs# $argv[$i]) + end + end + nix run $argv + end + + function shell -d 'Open packages in new shell via nixpkg flakes' + for i in (seq (count $argv)) + if ! string match -r '^-' -- $argv[$i] + set argv[$i] (string replace -r ^ nixpkgs# $argv[$i]) + end + end + nix shell $argv + end + + function activate -d 'Activate Python venv' + source .venv/bin/activate.fish + end + + function arknights -d 'Launch Arknights' + waydroid app launch com.YoStarEN.Arknights + end + ''; + + promptInit = '' + # Disable greeting + set -g fish_greeting + + # Prompt + function fish_prompt --description 'Write out the prompt' + set -l last_status $status + set -l normal (set_color normal) + set -l status_color (set_color brgreen) + set -l cwd_color (set_color $fish_color_cwd) + set -l vcs_color (set_color brpurple) + set -l prompt_status "" + + # Since we display the prompt on a new line allow the directory names to be longer. + set -q fish_prompt_pwd_dir_length + or set -lx fish_prompt_pwd_dir_length 0 + + # Color the prompt differently when we're root + set -l suffix '❯' + if functions -q fish_is_root_user; and fish_is_root_user + if set -q fish_color_cwd_root + set cwd_color (set_color $fish_color_cwd_root) + end + set suffix '#' + end + + # Color the prompt in red on error + if test $last_status -ne 0 + set status_color (set_color $fish_color_error) + set prompt_status $status_color "[" $last_status "]" $normal + end + + echo -s (prompt_login) ' ' $cwd_color (prompt_pwd) $vcs_color (fish_vcs_prompt) $normal ' ' $prompt_status + echo -n -s $status_color $suffix ' ' $normal + end + ''; + }; + }; +} diff --git a/options/custom/programs/foot.nix b/options/custom/programs/foot.nix new file mode 100644 index 0000000..ac5ceb5 --- /dev/null +++ b/options/custom/programs/foot.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.foot; +in +{ + options.custom.programs.foot.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://codeberg.org/dnkl/foot + programs.foot = { + enable = true; + + # https://codeberg.org/dnkl/foot/src/branch/master/foot.ini + settings = { + main.font = "monospace:size=12"; + scrollback.lines = 10000; # Default 1000 + + # Solarized Dark + # https://codeberg.org/dnkl/foot/src/branch/master/themes/solarized-dark + # https://fishshell.com/docs/current/cmds/set_color.html + colors = { + background = "002b36"; + foreground = "839496"; + regular0 = "073642"; + regular1 = "dc322f"; + regular2 = "859900"; + regular3 = "b58900"; + regular4 = "268bd2"; + regular5 = "d33682"; + regular6 = "2aa198"; + regular7 = "eee8d5"; + bright0 = "002b36"; + bright1 = "cb4b16"; + bright2 = "586e75"; + bright3 = "657b83"; + bright4 = "839496"; + bright5 = "6c71c4"; + bright6 = "93a1a1"; + bright7 = "fdf6e3"; + }; + }; + }; + }; +} diff --git a/options/custom/programs/fuzzel.nix b/options/custom/programs/fuzzel.nix new file mode 100644 index 0000000..ec94bb0 --- /dev/null +++ b/options/custom/programs/fuzzel.nix @@ -0,0 +1,42 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.fuzzel; +in +{ + options.custom.programs.fuzzel.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://codeberg.org/dnkl/fuzzel + programs.fuzzel = { + enable = true; + + settings = { + main = { + font = "${config.gtk.font.name}:size=12"; + icon-theme = config.gtk.iconTheme.name; + horizontal-pad = 20; + inner-pad = 12; + lines = 5; + line-height = 25; + vertical-pad = 12; + layer = "overlay"; + }; + + colors = { + background = "073642ff"; + selection = "002b36ff"; + selection-text = "eee8d5ff"; + text = "93a1a1ff"; + }; + + border = { + radius = 20; + width = 2; + }; + }; + }; + }; +} diff --git a/options/custom/programs/gamemode.nix b/options/custom/programs/gamemode.nix new file mode 100644 index 0000000..b5c5342 --- /dev/null +++ b/options/custom/programs/gamemode.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.gamemode; +in +{ + options.custom.programs.gamemode.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/FeralInteractive/gamemode + programs.gamemode.enable = true; + }; +} diff --git a/options/custom/programs/gamescope.nix b/options/custom/programs/gamescope.nix new file mode 100644 index 0000000..c49bc86 --- /dev/null +++ b/options/custom/programs/gamescope.nix @@ -0,0 +1,28 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.gamescope; +in +{ + options.custom.programs.gamescope.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/ValveSoftware/gamescope + #!! Issues may arise depending on environment + # https://github.com/NixOS/nixpkgs/issues/162562#issuecomment-1523177264 + programs.gamescope = { + enable = true; + capSysNice = true; # Allow renice + + #!! Align default window size with Steam Deck resolution + # args = [ + # "--rt" + # "--output-width 1280" + # "--output-height 800" + # "--nested-refresh 60" + # ]; + }; + }; +} diff --git a/options/custom/programs/git.nix b/options/custom/programs/git.nix new file mode 100644 index 0000000..9a4f859 --- /dev/null +++ b/options/custom/programs/git.nix @@ -0,0 +1,38 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.git; +in +{ + options.custom.programs.git.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.archlinux.org/title/Git + # https://git-scm.com + programs.git = { + enable = true; + userName = "Myned"; + userEmail = "dev@bjork.tech"; + + # BUG: GitHub Desktop tries to enable if this is not in gitconfig + lfs.enable = true; # Enable Large File Storage + + signing = { + signByDefault = true; + key = "C7224454F7881A34"; + }; + + extraConfig = { + init.defaultBranch = "master"; + push.autoSetupRemote = true; + pull.ff = "only"; + url."git@github.com:".insteadOf = [ + "gh:" + "github:" + ]; + }; + }; + }; +} diff --git a/options/custom/programs/gnome-shell.nix b/options/custom/programs/gnome-shell.nix new file mode 100644 index 0000000..a87472f --- /dev/null +++ b/options/custom/programs/gnome-shell.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.gnome-shell; +in +{ + options.custom.programs.gnome-shell.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # BUG: programs.gnome-shell.theme option forces installation of gnome-shell-extensions + programs.gnome-shell = { + enable = true; + + extensions = + with pkgs.gnomeExtensions; + optionals config.custom.default [ + { package = appindicator; } # https://github.com/ubuntu/gnome-shell-extension-appindicator + + ] + ++ optionals config.custom.minimal [ + { package = caffeine; } # https://github.com/eonpatapon/gnome-shell-extension-caffeine + { package = dash-to-dock; } # https://github.com/micheleg/dash-to-dock + #// { package = dash2dock-lite; } # https://github.com/icedman/dash2dock-lite + { package = gsconnect; } # https://github.com/GSConnect/gnome-shell-extension-gsconnect + { package = just-perfection; } # https://gitlab.gnome.org/jrahmatzadeh/just-perfection + #// { package = user-themes; } # https://gitlab.gnome.org/GNOME/gnome-shell-extensions + + ] + ++ optionals config.custom.full [ + #// { package = auto-move-windows; } # https://gitlab.gnome.org/GNOME/gnome-shell-extensions + { package = clipboard-indicator; } # https://github.com/Tudmotu/gnome-shell-extension-clipboard-indicator + { package = ddterm; } # https://github.com/ddterm/gnome-shell-extension-ddterm + #// { package = hide-top-bar; } # https://gitlab.gnome.org/tuxor1337/hidetopbar + { package = media-controls; } # https://github.com/sakithb/media-controls + #// { package = smart-auto-move; } # https://github.com/khimaros/smart-auto-move + { package = tailscale-qs; } # https://github.com/joaophi/tailscale-gnome-qs + { package = tiling-assistant; } # https://github.com/Leleat/Tiling-Assistant + ]; + }; + + #!! Installed to user directory until packaged into nixpkgs + # https://github.com/flexagoon/rounded-window-corners + # TODO: Use extension store version when published + # https://extensions.gnome.org/review/55303 + home.file.".local/share/gnome-shell/extensions/rounded-window-corners@fxgn".source = + mkIf config.custom.full pkgs.fetchzip + { + stripRoot = false; + url = "https://extensions.gnome.org/review/download/55303.shell-extension.zip"; + sha256 = "sha256-cg4/Y0irl5X2D2P/ncYJM0fRbeAgRSfBXmdRoVBY7jo="; + }; + }; +} diff --git a/options/custom/programs/gnome-terminal.nix b/options/custom/programs/gnome-terminal.nix new file mode 100644 index 0000000..54493f3 --- /dev/null +++ b/options/custom/programs/gnome-terminal.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.gnome-terminal; +in +{ + options.custom.programs.gnome-terminal.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://gitlab.gnome.org/GNOME/gnome-terminal + programs.gnome-terminal = { + enable = true; + + profile."8856406f-96d1-4284-8428-2329d2458b55" = { + default = true; + visibleName = "Master"; # Profile name + scrollOnOutput = false; + showScrollbar = false; + + colors = { + foregroundColor = "rgb(131,148,150)"; + backgroundColor = "rgb(0,43,54)"; + palette = [ + "rgb(7,54,66)" + "rgb(220,50,47)" + "rgb(133,153,0)" + "rgb(181,137,0)" + "rgb(38,139,210)" + "rgb(211,54,130)" + "rgb(42,161,152)" + "rgb(238,232,213)" + "rgb(0,43,54)" + "rgb(203,75,22)" + "rgb(88,110,117)" + "rgb(101,123,131)" + "rgb(131,148,150)" + "rgb(108,113,196)" + "rgb(147,161,161)" + "rgb(253,246,227)" + ]; + }; + }; + }; + }; +} diff --git a/options/custom/programs/gpg.nix b/options/custom/programs/gpg.nix new file mode 100644 index 0000000..ec39a33 --- /dev/null +++ b/options/custom/programs/gpg.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.gpg; +in +{ + options.custom.programs.gpg.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.archlinux.org/title/GnuPG + # https://gnupg.org + programs.gpg = { + enable = true; + settings.keyserver = "hkp://keyserver.ubuntu.com"; + }; + }; +} diff --git a/options/custom/programs/htop.nix b/options/custom/programs/htop.nix new file mode 100644 index 0000000..9d99340 --- /dev/null +++ b/options/custom/programs/htop.nix @@ -0,0 +1,99 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.htop; +in +{ + options.custom.programs.htop.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/htop-dev/htop + programs.htop = { + enable = true; + + # https://nix-community.github.io/home-manager/options.xhtml#opt-programs.htop.settings + #!! Not up-to-date, some config is imperative + settings = + { + account_guest_in_cpu_meter = 1; + all_branches_collapsed = 0; + color_scheme = 0; + cpu_count_from_one = 1; + degree_fahrenheit = 0; + delay = 30; + detailed_cpu_time = 0; + enable_mouse = 1; + find_comm_in_cmdline = 0; + header_layout = "two_50_50"; + header_margin = 1; + hide_function_bar = 0; + hide_kernel_threads = 1; + hide_running_in_container = 0; + hide_userland_threads = 1; + highlight_base_name = 1; + highlight_changes = 1; + highlight_changes_delay_secs = 3; + highlight_deleted_exe = 1; + highlight_megabytes = 1; + highlight_threads = 1; + screen_tabs = 1; + shadow_distribution_path_prefix = 0; + shadow_other_users = 0; + show_cpu_frequency = 0; + show_cpu_temperature = 0; + show_cpu_usage = 0; + show_merged_command = 0; + show_program_path = 0; + show_thread_names = 0; + sort_direction = -1; + sort_key = 46; + strip_exe_from_cmdline = 0; + tree_sort_direction = 1; + tree_sort_key = 0; + tree_view = 0; + tree_view_always_by_pid = 0; + update_process_names = 1; + + #!! Variable max of 120 + fields = with config.home-manager.users.${config.custom.username}.lib.htop.fields; [ + PID + USER + PROCESSOR + PERCENT_CPU + PERCENT_MEM + IO_READ_RATE + IO_WRITE_RATE + 125 # CWD + COMM + ]; + } + // ( + with config.home-manager.users.${config.custom.username}.lib.htop; + leftMeters [ + (bar "LeftCPUs4") + (text "Blank") + (bar "CPU") + (bar "MemorySwap") + (text "System") + (text "DateTime") + ] + ) + // ( + with config.home-manager.users.${config.custom.username}.lib.htop; + rightMeters [ + (bar "RightCPUs4") + (text "Blank") + (bar "NetworkIO") + (bar "DiskIO") + (text "Hostname") + (text "Uptime") + ] + ); + }; + + # https://github.com/nix-community/home-manager/issues/4947 + xdg.configFile."htop/htoprc".force = true; # Force overwrite config file + }; +} diff --git a/options/custom/programs/hyprlock.nix b/options/custom/programs/hyprlock.nix new file mode 100644 index 0000000..8021a3c --- /dev/null +++ b/options/custom/programs/hyprlock.nix @@ -0,0 +1,65 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.hyprlock; +in +{ + options.custom.programs.hyprlock.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + programs.hyprlock.enable = true; # Grant PAM access + + # https://wiki.hyprland.org/Hypr-Ecosystem/hyprlock + # https://github.com/hyprwm/hyprlock + home-manager.users.${config.custom.username}.programs.hyprlock = { + enable = true; + + settings = { + general = { + grace = 5 * 60; # Seconds + hide_cursor = true; + immediate_render = true; + }; + + background = { + blur_passes = 5; + color = "rgb(073642)"; + path = "/tmp/wallpaper.png"; + }; + + input-field = { + capslock_color = "rgb(cb4b16)"; + check_color = "rgb(859900)"; + fade_timeout = 0; + fail_color = "rgb(dc322f)"; + fail_text = ""; + font_color = "rgb(fdf6e3)"; + inner_color = "rgb(002b36)"; + outer_color = "rgb(fdf6e3)"; + outline_thickness = 0; + placeholder_text = ""; + position = "0, 0"; + shadow_passes = 1; + shadow_size = 2; + size = "300, 50"; + }; + + label = { + color = "rgb(fdf6e3)"; + font_family = "monospace"; + font_size = 48; + halign = "center"; + position = "0, 200"; + text_align = "center"; + valign = "center"; + + # 12:00 AM + # Sunday, January 01 + text = "cmd[update:1000] echo \"$(date +'%I:%M %p
%A, %B %d')
\""; + }; + }; + }; + }; +} diff --git a/options/custom/programs/kdeconnect.nix b/options/custom/programs/kdeconnect.nix new file mode 100644 index 0000000..f5be0fd --- /dev/null +++ b/options/custom/programs/kdeconnect.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.kdeconnect; +in +{ + options.custom.programs.kdeconnect.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/KDE/kdeconnect-kde + programs.kdeconnect.enable = true; + }; +} diff --git a/options/custom/programs/kitty.nix b/options/custom/programs/kitty.nix new file mode 100644 index 0000000..fabd891 --- /dev/null +++ b/options/custom/programs/kitty.nix @@ -0,0 +1,70 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.kitty; +in +{ + options.custom.programs.kitty.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://sw.kovidgoyal.net/kitty/ + # https://github.com/kovidgoyal/kitty + programs.kitty = { + enable = true; + + font = { + name = "monospace"; + size = 14; + }; + + # https://sw.kovidgoyal.net/kitty/conf/ + #?? man kitty + settings = { + active_tab_font_style = "bold"; + inactive_tab_font_style = "normal"; + confirm_os_window_close = 0; + cursor_blink_interval = 0; + scrollback_lines = -1; + strip_trailing_spaces = "smart"; + tab_bar_style = "powerline"; + touch_scroll_multiplier = 3; + url_style = "straight"; + wayland_enable_ime = "no"; + window_padding_width = "0 5 5 5"; # top right bottom left + + # Solarized Dark colors + # https://ethanschoonover.com/solarized/ + #?? kitten themes + cursor = "none"; # Invert colors + background = "#002b36"; + foreground = "#839496"; + active_tab_background = "#93a1a1"; + active_tab_foreground = "#002b36"; + inactive_tab_background = "#586e75"; + inactive_tab_foreground = "#002b36"; + selection_background = "#073642"; # Affects scrollbar color + selection_foreground = "none"; + url_color = "#586e75"; + + color0 = "#073642"; + color1 = "#dc322f"; + color2 = "#859900"; + color3 = "#b58900"; + color4 = "#268bd2"; + color5 = "#d33682"; + color6 = "#2aa198"; + color7 = "#eee8d5"; + color8 = "#002b36"; + color9 = "#cb4b16"; + color10 = "#586e75"; + color11 = "#657b83"; + color12 = "#839496"; + color13 = "#6c71c4"; + color14 = "#93a1a1"; + color15 = "#fdf6e3"; + }; + }; + }; +} diff --git a/options/custom/programs/libreoffice.nix b/options/custom/programs/libreoffice.nix new file mode 100644 index 0000000..c5a1a3b --- /dev/null +++ b/options/custom/programs/libreoffice.nix @@ -0,0 +1,28 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.libreoffice; +in +{ + options.custom.programs.libreoffice = { + enable = mkOption { default = false; }; + package = mkOption { default = pkgs.libreoffice-fresh; }; + }; + + config = mkIf cfg.enable { + # https://www.libreoffice.org + environment.systemPackages = [ cfg.package ]; + + #!! Options not available, files synced + home-manager.users.${config.custom.username}.home.file.".config/libreoffice/4/user".source = + config.home-manager.users.${config.custom.username}.lib.file.mkOutOfStoreSymlink + "/home/${config.custom.username}/SYNC/linux/config/libreoffice/user"; + }; +} diff --git a/options/custom/programs/librewolf.nix b/options/custom/programs/librewolf.nix new file mode 100644 index 0000000..23eb1dc --- /dev/null +++ b/options/custom/programs/librewolf.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.librewolf; +in +{ + options.custom.programs.librewolf.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://codeberg.org/librewolf + # TODO: Revisit when extensions can be managed declaratively + # https://github.com/nix-community/home-manager/issues/2803 + programs.librewolf.enable = true; + }; +} diff --git a/options/custom/programs/localsend.nix b/options/custom/programs/localsend.nix new file mode 100644 index 0000000..bd601c8 --- /dev/null +++ b/options/custom/programs/localsend.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.localsend; +in +{ + options.custom.programs.localsend.enable = mkOption { default = false; }; + + config = + if (versionAtLeast version "24.11") then + (mkIf cfg.enable { + # https://github.com/localsend/localsend + programs.localsend = { + enable = true; + openFirewall = true; + }; + }) + else + { }; +} diff --git a/options/custom/programs/logseq.nix b/options/custom/programs/logseq.nix new file mode 100644 index 0000000..cb0facf --- /dev/null +++ b/options/custom/programs/logseq.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.logseq; +in +{ + options.custom.programs.logseq.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + #!! Synced imperative configuration + home.file.".logseq/".source = + config.home-manager.users.${config.custom.username}.lib.file.mkOutOfStoreSymlink + "/home/${config.custom.username}/SYNC/common/config/logseq/"; + }; +} diff --git a/options/custom/programs/man.nix b/options/custom/programs/man.nix new file mode 100644 index 0000000..d4dbe40 --- /dev/null +++ b/options/custom/programs/man.nix @@ -0,0 +1,24 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.man; +in +{ + options.custom.programs.man.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Enable as much offline docs as possible + # https://wiki.nixos.org/wiki/Man_pages + documentation = { + dev.enable = true; # Library manpages + + man = { + generateCaches = true; # Index manpages for search + man-db.enable = false; # !! Hangs on building man-cache + mandoc.enable = true; + }; + }; + }; +} diff --git a/options/custom/programs/mangohud.nix b/options/custom/programs/mangohud.nix new file mode 100644 index 0000000..2ec1a55 --- /dev/null +++ b/options/custom/programs/mangohud.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.mangohud; +in +{ + options.custom.programs.mangohud.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/flightlessmango/MangoHud + programs.mangohud = { + enable = true; + enableSessionWide = true; + + settings = { + core_load = true; + frame_timing = true; + gpu_stats = true; + no_display = true; # Hide by default + ram = true; + vram = true; + background_alpha = 0; + font_size = 24; + fps_limit = "100,75,60"; # !! Monitor dependent + background_color = "002b36"; + cpu_color = "268bd2"; + device_battery = "gamepad,mouse"; + engine_color = "dc322f"; + font_file = "${pkgs.nerdfonts}/share/fonts/truetype/NerdFonts/IosevkaNerdFont-Bold.ttf"; + fps_limit_method = "early"; # Smoother frametimes compared to late + frametime_color = "859900"; + gpu_color = "2aa198"; + position = "top-center"; + ram_color = "d33682"; + text_color = "ffffff"; + toggle_fps_limit = "Control_L+period"; + toggle_hud = "Control_L+slash"; + vram_color = "6c71c4"; + }; + }; + }; +} diff --git a/options/custom/programs/mosh.nix b/options/custom/programs/mosh.nix new file mode 100644 index 0000000..8b74c77 --- /dev/null +++ b/options/custom/programs/mosh.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.mosh; +in +{ + options.custom.programs.mosh.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Mosh + # https://github.com/mobile-shell/mosh + programs.mosh.enable = true; # !! Opens UDP ports 60000-61000 + environment.shellAliases.mosh = "mosh --predict-overwrite"; + }; +} diff --git a/options/custom/programs/nano.nix b/options/custom/programs/nano.nix new file mode 100644 index 0000000..d278d97 --- /dev/null +++ b/options/custom/programs/nano.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nano; +in +{ + options.custom.programs.nano.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.archlinux.org/title/Nano + # https://www.nano-editor.org + programs.nano = { + enable = true; + + # https://www.nano-editor.org/dist/latest/nanorc.5.html + #?? man nanorc + nanorc = '' + set autoindent + set magic + set minibar + set tabsize 2 + set tabstospaces + set trimblanks + ''; + }; + }; +} diff --git a/options/custom/programs/nautilus.nix b/options/custom/programs/nautilus.nix new file mode 100644 index 0000000..5b82f63 --- /dev/null +++ b/options/custom/programs/nautilus.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.nautilus; +in +{ + options.custom.programs.nautilus.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + services.gvfs.enable = true; # Trash dependency + + # Fix nautilus extension environment + # https://github.com/NixOS/nixpkgs/pull/240780 + #?? echo $NAUTILUS_4_EXTENSION_DIR + services.gnome = { + core-utilities.enable = true; # Required to set environment variables + sushi.enable = true; # Quick preview with spacebar + }; + + environment.systemPackages = with pkgs; [ + nautilus + nautilus-open-in-blackbox + nautilus-python + ]; + }; +} diff --git a/options/custom/programs/networkmanager-dmenu.nix b/options/custom/programs/networkmanager-dmenu.nix new file mode 100644 index 0000000..b11d99c --- /dev/null +++ b/options/custom/programs/networkmanager-dmenu.nix @@ -0,0 +1,28 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.networkmanager-dmenu; +in +{ + options.custom.programs.networkmanager-dmenu.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/firecat53/networkmanager-dmenu + # https://github.com/firecat53/networkmanager-dmenu/blob/main/config.ini.example + #!! Option not available, files written directly + # FIXME: active_chars does not take effect + home.file.".config/networkmanager-dmenu/config.ini".text = + let + wofi = "${config.home-manager.users.${config.custom.username}.programs.wofi.package}/bin/wofi"; + in + '' + [dmenu] + dmenu_command = ${wofi} --dmenu --lines 11 + active_chars = > + wifi_icons = 󰤯󰤟󰤢󰤥󰤨 + format = {icon} {name} + ''; + }; +} diff --git a/options/custom/programs/nh.nix b/options/custom/programs/nh.nix new file mode 100644 index 0000000..14cd0b2 --- /dev/null +++ b/options/custom/programs/nh.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nh; +in +{ + options.custom.programs.nh.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/viperML/nh + programs.nh = { + enable = true; + flake = "/etc/nixos"; + + clean = { + enable = true; + extraArgs = "--keep-since ${if config.custom.minimal then "7" else "30"}d"; + }; + }; + }; +} diff --git a/options/custom/programs/nheko.nix b/options/custom/programs/nheko.nix new file mode 100644 index 0000000..6da0c19 --- /dev/null +++ b/options/custom/programs/nheko.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nheko; +in +{ + options.custom.programs.nheko.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/Nheko-Reborn/nheko + programs.nheko.enable = true; + }; +} diff --git a/options/custom/programs/nix-index.nix b/options/custom/programs/nix-index.nix new file mode 100644 index 0000000..90bc9f1 --- /dev/null +++ b/options/custom/programs/nix-index.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nix-index; +in +{ + options.custom.programs.nix-index.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/nix-community/nix-index + # https://github.com/nix-community/nix-index-database + #?? nix-index + #?? nix-locate -p + programs = { + nix-index.enable = true; + command-not-found.enable = false; + }; + + home-manager.users.${config.custom.username}.programs.nix-index.enable = true; + }; +} diff --git a/options/custom/programs/nix-ld.nix b/options/custom/programs/nix-ld.nix new file mode 100644 index 0000000..02066d9 --- /dev/null +++ b/options/custom/programs/nix-ld.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nix-ld; +in +{ + options.custom.programs.nix-ld.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/nix-community/nix-ld + programs.nix-ld.enable = true; + }; +} diff --git a/options/custom/programs/nushell.nix b/options/custom/programs/nushell.nix new file mode 100644 index 0000000..f16b2ba --- /dev/null +++ b/options/custom/programs/nushell.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nushell; +in +{ + options.custom.programs.nushell.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # TODO: Create config + # https://github.com/nushell/nushell + programs.nushell = { + enable = true; + }; + }; +} diff --git a/options/custom/programs/nvtop.nix b/options/custom/programs/nvtop.nix new file mode 100644 index 0000000..57923ae --- /dev/null +++ b/options/custom/programs/nvtop.nix @@ -0,0 +1,50 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.nvtop; +in +{ + options.custom.programs.nvtop.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/Syllo/nvtop + #!! Options not available, config written directly + #?? Imperative config generated by F12 + home.file.".config/nvtop/interface.ini".text = '' + [GeneralOption] + UseColor = true + UpdateInterval = 3000 + ShowInfoMessages = false + + [HeaderOption] + UseFahrenheit = false + EncodeHideTimer = 3.000000e+01 + + [ChartOption] + ReverseChart = false + + [ProcessListOption] + HideNvtopProcess = true + SortOrder = descending + SortBy = gpuRate + DisplayField = pId + DisplayField = gpuId + DisplayField = type + DisplayField = gpuRate + DisplayField = encRate + DisplayField = decRate + DisplayField = memory + DisplayField = cpuUsage + DisplayField = cpuMem + DisplayField = cmdline + + [Device] + Pdev = 0000:c1:00.0 + Monitor = true + ShownInfo = gpuRate + ShownInfo = gpuMemRate + ''; + }; +} diff --git a/options/custom/programs/obs-studio.nix b/options/custom/programs/obs-studio.nix new file mode 100644 index 0000000..2ad3a39 --- /dev/null +++ b/options/custom/programs/obs-studio.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.obs-studio; +in +{ + options.custom.programs.obs-studio.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/obsproject/obs-studio + programs.obs-studio.enable = true; + }; +} diff --git a/options/custom/programs/onedrive.nix b/options/custom/programs/onedrive.nix new file mode 100644 index 0000000..fcb0110 --- /dev/null +++ b/options/custom/programs/onedrive.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.onedrive; +in +{ + options.custom.programs.onedrive.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/abraunegg/onedrive + #!! Login is imperative + #?? onedrive + #?? systemctl --user enable --now onedrive@onedrive.service + + #!! Option not available, files written directly + home.file = { + # https://github.com/abraunegg/onedrive/blob/master/docs/USAGE.md#configuration + ".config/onedrive/config".text = '' + sync_dir = "~/SYNC/edu/hawkeye" + ''; + + # https://github.com/abraunegg/onedrive/blob/master/docs/USAGE.md#performing-a-selective-sync-via-sync_list-file + ".config/onedrive/sync_list".text = '' + !/Apps/ + !/Attachments/ + /* + ''; + }; + }; +} diff --git a/options/custom/programs/path-of-building.nix b/options/custom/programs/path-of-building.nix new file mode 100644 index 0000000..c43e1e3 --- /dev/null +++ b/options/custom/programs/path-of-building.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.path-of-building; +in +{ + options.custom.programs.path-of-building.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + xdg.desktopEntries.path-of-building = { + name = "Path of Building"; + exec = "${pkgs.path-of-building}/bin/pobfrontend"; + }; + }; +} diff --git a/options/custom/programs/rbw.nix b/options/custom/programs/rbw.nix new file mode 100644 index 0000000..c3bcf98 --- /dev/null +++ b/options/custom/programs/rbw.nix @@ -0,0 +1,31 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.rbw; +in +{ + options.custom.programs.rbw.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/doy/rbw + #!! Register with API secrets before using + #?? rbw register + #?? rbw login + programs.rbw = { + enable = true; + + # https://github.com/doy/rbw?tab=readme-ov-file#configuration + settings = { + email = "myned@bjork.tech"; + pinentry = pkgs.pinentry-gnome3; + }; + }; + }; +} diff --git a/options/custom/programs/rofi-rbw.nix b/options/custom/programs/rofi-rbw.nix new file mode 100644 index 0000000..f213faa --- /dev/null +++ b/options/custom/programs/rofi-rbw.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.rofi-rbw; +in +{ + options.custom.programs.rofi-rbw.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/fdw/rofi-rbw + #!! Options not available, files written directly + # https://github.com/fdw/rofi-rbw?tab=readme-ov-file#configuration + # TODO: Enable input emulation when merged (uinput.enable?) + # https://github.com/NixOS/nixpkgs/pull/303745 + home.file.".config/rofi-rbw.rc".text = '' + action=copy + ''; + }; +} diff --git a/options/custom/programs/rofi.nix b/options/custom/programs/rofi.nix new file mode 100644 index 0000000..47c3c19 --- /dev/null +++ b/options/custom/programs/rofi.nix @@ -0,0 +1,186 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.rofi; +in +{ + options.custom.programs.rofi.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + #!! Creates package derivation + #?? config.home-manager.users.${config.custom.username}.programs.rofi.finalPackage + # https://github.com/lbonn/rofi + programs.rofi = { + enable = true; + package = pkgs.rofi-wayland; # Wayland fork + + # TODO: Look into rofi plugins + plugins = with pkgs; [ + rofi-rbw # Bitwarden + rofimoji # Character picker + + # TODO: Remove when rofi v1.7.6 released + # Build against rofi-wayland due to ABI incompatibility with upstream + # https://github.com/lbonn/rofi/issues/96 + # https://github.com/NixOS/nixpkgs/issues/298539 + (rofi-calc.override { rofi-unwrapped = rofi-wayland-unwrapped; }) # Calculator + (rofi-top.override { rofi-unwrapped = rofi-wayland-unwrapped; }) # System monitor + ]; + + #?? rofi-theme-selector + theme = "custom"; + font = "monospace 16"; + + # https://github.com/davatorium/rofi/blob/next/CONFIG.md + extraConfig = { + modi = "drun,run,calc"; + matching = "prefix"; # Match beginning of words + drun-display-format = "{name}"; # Display only names + drun-match-fields = "name"; # Disable matching of invisible desktop attributes + }; + }; + + # https://github.com/davatorium/rofi/blob/next/doc/rofi-theme.5.markdown + # https://github.com/davatorium/rofi/blob/next/themes/paper-float.rasi + # TODO: Clean up theme + home.file.".config/rofi/custom.rasi".text = '' + * { + background: #073642ff; + alternate: #002b36ff; + text: #eee8d5ff; + accent: #d33682ff; + + spacing: 2; + text-color: @text; + background-color: #00000000; + border-color: @accent; + anchor: north; + location: center; + } + window { + transparency: "real"; + background-color: #00000000; + border: 0; + padding: 0% 0% 1em 0%; + x-offset: 0; + y-offset: -10%; + } + mainbox { + padding: 0px; + border: 0; + spacing: 1%; + } + message { + border: 2px; + padding: 1em; + background-color: @background; + text-color: @text; + } + textbox normal { + text-color: @text; + padding: 0; + border: 0; + } + listview { + fixed-height: 1; + border: 2px; + padding: 1em; + reverse: false; + + columns: 1; + background-color: @background; + } + element { + border: 0; + padding: 2px; + highlight: bold ; + } + element-text { + background-color: inherit; + text-color: inherit; + } + element normal.normal { + text-color: @text; + background-color: @background; + } + element normal.urgent { + text-color: @text; + background-color: @background; + } + element normal.active { + text-color: @text; + background-color: @background; + } + element selected.normal { + text-color: @text; + background-color: @accent; + } + element selected.urgent { + text-color: @text; + background-color: @accent; + } + element selected.active { + text-color: @text; + background-color: @accent; + } + element alternate.normal { + text-color: @text; + background-color: @alternate; + } + element alternate.urgent { + text-color: @text; + background-color: @alternate; + } + element alternate.active { + text-color: @text; + background-color: @alternate; + } + scrollbar { + border: 0; + padding: 0; + } + inputbar { + spacing: 0; + border: 2px; + padding: 0.5em 1em; + background-color: @background; + index: 0; + } + inputbar normal { + foreground-color: @text; + background-color: @background; + } + mode-switcher { + border: 2px; + padding: 0.5em 1em; + background-color: @background; + index: 10; + } + button selected { + text-color: @accent; + } + inputbar { + children: [ prompt,textbox-prompt-colon,entry,case-indicator ]; + } + textbox-prompt-colon { + expand: false; + str: ":"; + margin: 0px 0.3em 0em 0em ; + text-color: @text; + } + error-message { + border: 2px; + padding: 1em; + background-color: @background; + text-color: @text; + } + ''; + }; +} diff --git a/options/custom/programs/seahorse.nix b/options/custom/programs/seahorse.nix new file mode 100644 index 0000000..4432208 --- /dev/null +++ b/options/custom/programs/seahorse.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.seahorse; +in +{ + options.custom.programs.seahorse.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + programs.seahorse.enable = true; + services.gnome.gnome-keyring.enable = true; + }; +} diff --git a/options/custom/programs/slurp.nix b/options/custom/programs/slurp.nix new file mode 100644 index 0000000..1685759 --- /dev/null +++ b/options/custom/programs/slurp.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.slurp; +in +{ + options.custom.programs.slurp.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/emersion/slurp + # https://github.com/emersion/slurp/blob/master/slurp.1.scd + home.sessionVariables.SLURP_ARGS = lib.concatStringsSep " " [ + "-B 00000000" + "-b 00000000" + "-c d33682" + #// "-s d3368240" + "-w 2" + ]; + }; +} diff --git a/options/custom/programs/ssh.nix b/options/custom/programs/ssh.nix new file mode 100644 index 0000000..0d36c44 --- /dev/null +++ b/options/custom/programs/ssh.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.ssh; +in +{ + options.custom.programs.ssh.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Disable prompt for new hosts + # MitM warning is still active + programs.ssh.extraConfig = '' + StrictHostKeyChecking no + ''; + }; +} diff --git a/options/custom/programs/steam.nix b/options/custom/programs/steam.nix new file mode 100644 index 0000000..981704b --- /dev/null +++ b/options/custom/programs/steam.nix @@ -0,0 +1,36 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.steam; +in +{ + # https://wiki.nixos.org/wiki/Steam + # https://store.steampowered.com + options.custom.programs.steam = { + enable = mkOption { default = false; }; + extest = mkOption { default = false; }; + }; + + config = mkIf cfg.enable { + programs.steam = { + enable = true; + extest.enable = cfg.extest; # Work around invisible cursor on Wayland + extraCompatPackages = [ pkgs.proton-ge-bin ]; + + gamescopeSession = { + enable = true; + # args = [ + # "--backend sdl" + # "--fullscreen" + # ]; + }; + } // optionalAttrs (versionAtLeast version "24.11") { protontricks.enable = true; }; + }; +} diff --git a/options/custom/programs/swaylock.nix b/options/custom/programs/swaylock.nix new file mode 100644 index 0000000..18f5531 --- /dev/null +++ b/options/custom/programs/swaylock.nix @@ -0,0 +1,73 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.swaylock; +in +{ + options.custom.programs.swaylock.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Allow swaylock to unlock the session + # https://wiki.nixos.org/wiki/Sway#Swaylock_cannot_be_unlocked_with_the_correct_password + security.pam.services.swaylock = { }; + + # https://github.com/swaywm/swaylock + home-manager.users.${config.custom.username}.programs.swaylock = { + enable = true; + + # https://github.com/jirutka/swaylock-effects + package = pkgs.swaylock-effects; + + # https://github.com/swaywm/swaylock/blob/master/swaylock.1.scd + #?? man swaylock + settings = { + daemonize = true; + disable-caps-lock-text = true; + line-uses-inside = true; + indicator-caps-lock = true; + indicator-idle-visible = true; + indicator-radius = 150; + font-size = 48 * config.custom.scale; + font = "monospace"; + image = mkIf config.custom.wallpaper "/tmp/altered.png"; + bs-hl-color = "93a1a1"; + color = "073642"; + inside-caps-lock-color = "002b36"; + inside-clear-color = "002b36"; + inside-color = "002b36"; + inside-ver-color = "002b36"; + inside-wrong-color = "002b36"; + key-hl-color = "6c71c4"; + ring-caps-lock-color = "cb4b16"; + ring-clear-color = "fdf6e3"; + ring-color = "002b36"; + ring-ver-color = "268bd2"; + ring-wrong-color = "dc322f"; + separator-color = "002b36"; + text-caps-lock-color = "cb4b16"; + text-clear-color = "002b36"; + text-color = "93a1a1"; + text-ver-color = "002b36"; + text-wrong-color = "002b36"; + + ### swaylock-effects + # https://github.com/jirutka/swaylock-effects?tab=readme-ov-file#new-features + clock = true; + #// indicator = true; + effect-blur = mkIf config.custom.wallpaper "50x2"; + #// fade-in = 1; # Seconds + + # https://strftime.org/ + datestr = "%a %b %d"; + timestr = "%I:%M %p"; + }; + }; + }; +} diff --git a/options/custom/programs/thunderbird.nix b/options/custom/programs/thunderbird.nix new file mode 100644 index 0000000..00cc1af --- /dev/null +++ b/options/custom/programs/thunderbird.nix @@ -0,0 +1,87 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.thunderbird; +in +{ + options.custom.programs.thunderbird.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Thunderbird + # https://www.thunderbird.net + programs.thunderbird = { + enable = true; + package = pkgs.thunderbird-115; + + profiles.default = { + isDefault = true; + userContent = ''@import "thunderbird-gnome-theme/theme/colors/dark.css";''; + + userChrome = '' + @import "thunderbird-gnome-theme/theme/gnome-theme.css"; + + :root { + --gnome-accent: #6c71c4; + --gnome-window-background: #002b36; + --gnome-window-color: #93a1a1; + --gnome-view-background: #073642; + --gnome-sidebar-background: #002b36; + --gnome-secondary-sidebar-background: #002b36; + --gnome-menu-background: #073642; + --gnome-headerbar-background: #002b36; + --gnome-toolbar-icon-fill: #93a1a1; + --gnome-tabbar-tab-hover-background: #073642; + --gnome-tabbar-tab-active-background: #073642; + --gnome-tabbar-tab-active-hover-background: #073642; + + --layout-background-3: #073642 !important; + } + + :root:-moz-window-inactive { + --gnome-inactive-entry-color: #586e75; + --gnome-tabbar-tab-hover-background: #073642; + --gnome-tabbar-tab-active-background: #073642; + } + ''; + + settings = { + # https://github.com/rafaelmardojai/thunderbird-gnome-theme?tab=readme-ov-file#required-thunderbird-preferences + "svg.context-properties.content.enabled" = true; + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + + "app.donation.eoy.version.viewed" = 5; # Disable donation banner + "browser.display.document_color_use" = 2; # Override colors + "browser.display.use_system_colors" = true; + "mail.pane_config.dynamic" = 1; # Wide view + "mailnews.message_display.disable_remote_image" = false; + + # Telemetry + "datareporting.healthreport.uploadEnabled" = false; + "dom.security.unexpected_system_load_telemetry_enabled" = false; + "network.trr.confirmation_telemetry_enabled" = false; + "toolkit.telemetry.archive.enabled" = false; + "toolkit.telemetry.bhrPing.enabled" = false; + "toolkit.telemetry.firstShutdownPing.enabled" = false; + "toolkit.telemetry.newProfilePing.enabled" = false; + "toolkit.telemetry.server" = "localhost"; + "toolkit.telemetry.unified" = false; + "toolkit.telemetry.updatePing.enabled" = false; + }; + }; + }; + + accounts.email.accounts.${config.custom.username}.thunderbird.enable = true; + + # https://github.com/rafaelmardojai/thunderbird-gnome-theme + home.file.".thunderbird/default/chrome/thunderbird-gnome-theme".source = + inputs.thunderbird-gnome-theme; + }; +} diff --git a/options/custom/programs/tio.nix b/options/custom/programs/tio.nix new file mode 100644 index 0000000..179e928 --- /dev/null +++ b/options/custom/programs/tio.nix @@ -0,0 +1,22 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.tio; +in +{ + options.custom.programs.tio.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Allow serial device access + # https://github.com/tio/tio?tab=readme-ov-file#46-known-issues + users.users.${config.custom.username}.extraGroups = [ "dialout" ]; + + # https://github.com/tio/tio + #!! Options not available, files written directly + home-manager.users.${config.custom.username}.home.file.".config/tio/config".text = '' + baudrate = 9600 + ''; + }; +} diff --git a/options/custom/programs/tmux.nix b/options/custom/programs/tmux.nix new file mode 100644 index 0000000..eb60f05 --- /dev/null +++ b/options/custom/programs/tmux.nix @@ -0,0 +1,20 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.tmux; +in +{ + options.custom.programs.tmux.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Tmux + # https://github.com/tmux/tmux + programs.tmux = { + enable = true; + shortcut = "t"; + terminal = "tmux-256color"; + }; + }; +} diff --git a/options/custom/programs/vscode.nix b/options/custom/programs/vscode.nix new file mode 100644 index 0000000..a64e6c6 --- /dev/null +++ b/options/custom/programs/vscode.nix @@ -0,0 +1,115 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.programs.vscode; +in +{ + options.custom.programs.vscode.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/VSCodium + # https://github.com/VSCodium/vscodium + #!! Configuration is imperative + programs.vscode = { + enable = true; + mutableExtensionsDir = false; + package = pkgs.vscodium; + + # https://github.com/nix-community/nix-vscode-extensions + #?? nixos-rebuild repl > inputs.nix-vscode-extensions.extensions.${pkgs.system}.* + extensions = with inputs.nix-vscode-extensions.extensions.${pkgs.system}.vscode-marketplace; [ + # Some extensions go missing from open-vsx, so use official marketplace + # https://github.com/nix-community/nix-vscode-extensions?tab=readme-ov-file#note + aaron-bond.better-comments + antfu.iconify + antfu.unocss + bedsteler20.gnome-magic + bilelmoussaoui.flatpak-vscode + bmalehorn.vscode-fish + bmewburn.vscode-intelephense-client + bodil.blueprint-gtk + bradlc.vscode-tailwindcss + cormoran.disable-default-keybinding + csstools.postcss + dbaeumer.vscode-eslint + #// eamodio.gitlens + esbenp.prettier-vscode + foxundermoon.shell-format + ginfuru.ginfuru-better-solarized-dark-theme + gruntfuggly.todo-tree + jnoortheen.nix-ide + koihik.vscode-lua-format + mhutchie.git-graph + mkhl.direnv + ms-python.black-formatter + ms-python.debugpy + ms-python.isort + ms-python.python + natizyskunk.sftp + pkief.material-icon-theme + pkief.material-product-icons + sirmspencer.vscode-autohide + sketchbuch.vsc-workspace-sidebar + svelte.svelte-vscode + timonwong.shellcheck + vincaslt.highlight-matching-tag + ]; + }; + + home = { + # Extension dependencies + packages = with pkgs; [ + blueprint-compiler # blueprint-gtk + nixd # nix-ide + nixfmt-rfc-style # nix-ide + shfmt # shell-format + ]; + + # https://github.com/nix-community/nixd/blob/main/nixd/docs/features.md + sessionVariables.NIXD_FLAGS = "--inlay-hints=false"; # Disable package versions in the editor + + file = with config.home-manager.users.${config.custom.username}.lib.file; { + # Imperative symlinks intended to be synced + ".config/VSCodium/User/settings.json".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/dev/config/vscode/settings.json"; + ".config/VSCodium/User/keybindings.json".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/dev/config/vscode/keybindings.json"; + ".config/VSCodium/User/snippets/".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/dev/config/vscode/snippets/"; + ".config/VSCodium/User/profiles/".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/dev/config/vscode/profiles/"; + + # Work around wrong wmclass + # https://github.com/microsoft/vscode/issues/129953 + # https://github.com/VSCodium/vscodium/issues/1414 + #!! Keep updated with upstream desktop file + #?? cat /etc/profiles/per-user/USER/share/applications/codium.desktop + # ".local/share/applications/codium.desktop".text = '' + # [Desktop Entry] + # Actions=new-empty-window + # Categories=Utility;TextEditor;Development;IDE + # Comment=Code Editing. Redefined. + # Exec=codium %F + # GenericName=Text Editor + # Icon=vscodium + # Keywords=vscode + # MimeType=text/plain;inode/directory + # Name=VSCodium + # StartupNotify=true + # StartupWMClass=codium-url-handler + # Type=Application + # Version=1.4 + + # [Desktop Action new-empty-window] + # Exec=codium --new-window %F + # Icon=vscodium + # Name=New Empty Window + # ''; + }; + }; + }; +} diff --git a/options/custom/programs/waybar/default.nix b/options/custom/programs/waybar/default.nix new file mode 100644 index 0000000..888582a --- /dev/null +++ b/options/custom/programs/waybar/default.nix @@ -0,0 +1,383 @@ +{ + config, + lib, + pkgs, + ... +}: +with lib; let + bash = "${pkgs.bash}/bin/bash"; + blueberry = "${pkgs.blueberry}/bin/blueberry"; + bluetoothctl = "${pkgs.bluez}/bin/bluetoothctl"; + easyeffects = "${pkgs.easyeffects}/bin/easyeffects"; + echo = "${pkgs.coreutils}/bin/echo"; + hyprctl = "${ + config.home-manager.users.${config.custom.username}.wayland.windowManager.hyprland.finalPackage + }/bin/hyprctl"; + jq = "${pkgs.jq}/bin/jq"; + loginctl = "${pkgs.systemd}/bin/loginctl"; + nm-connection-editor = "${pkgs.networkmanagerapplet}/bin/nm-connection-editor"; + pgrep = "${pkgs.procps}/bin/pgrep"; + ping = "${pkgs.iputils}/bin/ping"; + pkill = "${pkgs.procps}/bin/pkill"; + playerctl = "${pkgs.playerctl}/bin/playerctl"; + rfkill = "${pkgs.util-linux}/bin/rfkill"; + sleep = "${pkgs.coreutils}/bin/sleep"; + swaync-client = "${ + config.home-manager.users.${config.custom.username}.services.swaync.package + }/bin/swaync-client"; + swayosd-client = "${pkgs.swayosd}/bin/swayosd-client"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + systemd-inhibit = "${pkgs.systemd}/bin/systemd-inhibit"; + tailscale = "${pkgs.tailscale}/bin/tailscale"; + wttrbar = "${pkgs.wttrbar}/bin/wttrbar"; + + cfg = config.custom.programs.waybar; +in { + options.custom.programs.waybar.enable = mkOption {default = false;}; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/Alexays/Waybar + # https://www.nerdfonts.com/cheat-sheet + programs.waybar = { + enable = true; + style = ./style.css; # ?? waybar --log-level debug + systemd.enable = true; # Start on login + + ### SETTINGS ### + # https://github.com/Alexays/Waybar/wiki/Configuration + #?? pkill -SIGUSR2 -x waybar + settings = let + ## INHERIT ## + #!! Module defaults are not accurate to documentation + # TODO: Submit pull request to fix in addition to inconsistent hyphen vs underscore + # https://github.com/Alexays/Waybar/wiki/Module:-Cava + cava-config = { + cava_config = null; # Default: null? + framerate = 30; # Default: 30? + autosens = 1; # Default: 1 + # sensitivity = 0; # Default: 100? + bars = 16; # Default: 2 + lower_cutoff_freq = 50; # Default: 50? + higher_cutoff_freq = 10000; # Default: 10000? + sleep_timer = 5; # Default: 0 + hide_on_silence = true; # Default: false + method = "pipewire"; # Default: pulse + source = "auto"; # Default: auto? + sample_rate = 44100; # Default: 44100? + sample_bits = 16; # Default: 16? + stereo = false; # Default: true + reverse = false; # Default: false + bar_delimiter = 32; # ASCII code for space, default: 59 or ; + monstercat = true; # Default: false? + waves = true; # Default: false? + noise_reduction = 0.2; # Default: 0.77? + input_delay = 1; # Default: 4 + format-icons = [ + "▁" + "▂" + "▃" + "▄" + "▅" + "▆" + "▇" + "█" + ]; # !! Required + on-click = easyeffects; + on-scroll-up = "${swayosd-client} --output-volume raise"; + on-scroll-down = "${swayosd-client} --output-volume lower"; + rotate = 180; + }; + in { + status = { + ## GLOBAL ## + layer = "top"; + position = "bottom"; + + ## POSITION ## + modules-left = [ + "custom/power" + "custom/inhibitor" + "custom/vpn" + "custom/vm" + "hyprland/workspaces" + ]; + modules-center = [ + "clock" + "custom/weather" + ]; + modules-right = [ + "mpris" + "tray" + "wireplumber" + "bluetooth" + "network" + "battery" + ]; + + ## MODULES ## + # https://github.com/Alexays/Waybar/wiki/Module:-Custom + "custom/power" = { + format = ""; + on-click = "${systemctl} poweroff"; + on-click-right = "${systemctl} reboot"; + on-click-middle = "${loginctl} terminate-session ''"; + }; + + "custom/inhibitor" = { + interval = 5; + exec = "~/.config/waybar/scripts/inhibitor.sh"; + on-click = "~/.local/bin/inhibit"; + }; + + "custom/vm" = { + interval = 5; + exec = "~/.config/waybar/scripts/vm.sh"; + on-click = "~/.local/bin/vm -x ${ + if config.custom.hidpi + then "/scale:140" + else "" + }"; + }; + + "custom/vpn" = { + interval = 5; + exec = "~/.config/waybar/scripts/vpn.sh"; + on-click = "~/.local/bin/vpn mypi3"; + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-Idle-Inhibitor + # FIXME: Not currently usable + # https://github.com/Alexays/Waybar/issues/690 + idle_inhibitor = { + format = "{icon}"; + format-icons = { + activated = "󰅶"; + deactivated = "󰾪"; + }; + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-Hyprland + "hyprland/workspaces" = { + show-special = true; + format = "{icon}"; + format-icons = { + android = ""; + dropdown = "󰞷"; + game = "󰊴"; + music = "󰝚"; + pip = "󰹙"; + scratchpad = "󰎚"; + steam = "󰓓"; + terminal = ""; + vm = "󰢹"; + wallpaper = "󰏩"; + }; + }; + + cava = cava-config; + + # https://github.com/Alexays/Waybar/wiki/Module:-Clock + clock = { + # https://fmt.dev/latest/syntax.html#chrono-specs + format = "{:%a %b %d %I:%M %p}"; # Mon Jan 01 12:00 AM + tooltip-format = "{calendar}"; + calendar.format = { + months = "{}"; + weeks = "{}"; + weekdays = "{}"; + days = "{}"; + today = "{}"; + }; + + # FIXME: Click release event sends to incorrect layer without sleeping + # https://github.com/hyprwm/Hyprland/issues/1348 + on-click = "${swaync-client} --toggle-panel"; + # on-click-right = easyeffects; + on-scroll-up = "${swayosd-client} --output-volume raise"; + on-scroll-down = "${swayosd-client} --output-volume lower"; + }; + + # https://github.com/bjesus/wttrbar + "custom/weather" = { + format = "{}°"; + interval = 60 * 60; + return-type = "json"; + + exec = lib.strings.concatStringsSep " " [ + "${wttrbar}" + "--ampm" + "--fahrenheit" + "--hide-conditions" + "--main-indicator temp_F" + ]; + }; + + "cava#reverse" = + cava-config + // { + reverse = true; + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-MPRIS + mpris = { + format = "{player_icon} {dynamic}"; + format-paused = "{status_icon} {dynamic}"; + dynamic-len = 50; + dynamic-order = [ + "title" + "artist" + ]; + dynamic-separator = " 󰧟 "; + player-icons.default = "󰎈"; + status-icons.paused = ""; + on-click-middle = ""; # TODO: Close music player + on-scroll-up = "${swayosd-client} --output-volume raise"; + on-scroll-down = "${swayosd-client} --output-volume lower"; + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-WirePlumber + wireplumber = { + format = "{icon} {volume}%"; + format-muted = "󰸈"; + format-icons = [ + "󰕿" + "󰖀" + "󰕾" + ]; + on-click = easyeffects; + on-click-right = "${swayosd-client} --output-volume mute-toggle"; + on-scroll-up = "${swayosd-client} --output-volume raise"; + on-scroll-down = "${swayosd-client} --output-volume lower"; + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-Bluetooth + bluetooth = { + format-disabled = "󰂲"; + format-off = "󰂲"; + format-on = "󰂯"; + format-connected = "󰂱"; + on-click = blueberry; + on-click-right = "${bluetoothctl} disconnect"; + on-click-middle = "${rfkill} toggle bluetooth"; # Toggle bluetooth on/off + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-Network + network = { + format = "{icon}"; + format-icons = { + disabled = ""; + disconnected = ""; + ethernet = "󰈀"; + linked = ""; + wifi = [ + "󰤯" + "󰤟" + "󰤢" + "󰤥" + "󰤨" + ]; + }; + + on-click = nm-connection-editor; + on-click-right = "~/.local/bin/network"; # Toggle networking on/off + }; + + # https://github.com/Alexays/Waybar/wiki/Module:-Battery + "battery" = { + format = "{icon} {power:.0f}W"; + format-icons = [ + "󰂃" + "󰁺" + "󰁻" + "󰁼" + "󰁽" + "󰁾" + "󰁿" + "󰂀" + "󰂁" + "󰂂" + "󰁹" + ]; + interval = 5; + states = { + critical = 15; + warning = 30; + }; + + on-click = "~/.local/bin/power"; # Toggle power-saver mode + }; + }; + }; + }; + + # TODO: Convert to writeShellApplication + ### SCRIPTS ### + #?? text + #?? tooltip + #?? class + home.file = { + # Return inhibit idle status + ".config/waybar/scripts/inhibitor.sh" = { + executable = true; + text = '' + #! /usr/bin/env ${bash} + + if ${pgrep} systemd-inhibit &> /dev/null; then + ${echo} 󰅶 + ${echo} Enabled + ${echo} enabled + else + ${echo} 󰾪 + ${echo} Disabled + ${echo} disabled + fi + ''; + }; + + # Return tailscale status + ".config/waybar/scripts/vm.sh" = { + executable = true; + text = '' + #! /usr/bin/env ${bash} + + case "$(virsh --connect qemu:///system domstate myndows)" in + 'running') + ${echo}  + ${echo} Online + ${echo} online;; + 'paused') + ${echo}  + ${echo} Paused + ${echo} paused;; + 'shut off') + ${echo}  + ${echo} Offline + ${echo} offline;; + *) + ${echo}  + ${echo} Unknown + ${echo} unknown;; + esac + ''; + }; + + # Return tailscale status + ".config/waybar/scripts/vpn.sh" = { + executable = true; + text = '' + #! /usr/bin/env ${bash} + + if [[ $(${tailscale} status --json | ${jq} .ExitNodeStatus.Online) == 'true' ]]; then + ${echo} 󰖂 + ${echo} Connected + ${echo} connected + else + ${echo} 󰖂 + ${echo} Disconnected + ${echo} disconnected + fi + ''; + }; + }; + }; +} diff --git a/options/custom/programs/waybar/style.css b/options/custom/programs/waybar/style.css new file mode 100644 index 0000000..d97d74a --- /dev/null +++ b/options/custom/programs/waybar/style.css @@ -0,0 +1,116 @@ +/*** Waybar +https://github.com/Alexays/Waybar/wiki/Styling +https://github.com/Alexays/Waybar/blob/master/resources/style.css +https://gitlab.gnome.org/GNOME/gtk/-/blob/gtk-3-24/gtk/theme/Adwaita/_colors-public.scss + +//?? +GTK_DEBUG=interactive waybar +#custom-module { } +***/ + +* { + border-radius: 50px; + color: #93a1a1; + font: 18px 'Iosevka NFP SemiBold'; + margin: 0; + padding: 0; +} + +button:hover, +label:hover { + background: #073642; +} + +tooltip { + opacity: 0; + /* background: #002b36; */ +} + +.active { + background: rgba(88, 110, 117, 0.25); +} + +.horizontal > box { + background: #002b36; + border: 2px #073642 solid; + margin: 0 10px 10px; + padding: 4px; +} + +.module { + padding: 4px 12px; +} + +#waybar { + background: transparent; +} + +#battery.critical { + color: #dc322f; +} + +#battery.warning { + color: #b58900; +} + +#battery.charging { + color: #859900; +} + +#bluetooth.connected { + color: #268bd2; +} + +#bluetooth.disabled { + color: #dc322f; +} + +#custom-inhibitor.enabled { + color: #cb4b16; +} + +#custom-vm.online { + color: #268bd2; +} + +#custom-vm.paused { + color: #b58900; +} + +#custom-vm.unknown { + color: #dc322f; +} + +#custom-vpn.connected { + color: #d33682; +} + +#network.disabled { + color: #dc322f; +} + +#network.disconnected { + color: #b58900; +} + +#tray .active { + background: none; +} + +#wireplumber.muted { + color: #dc322f; +} + +#workspaces { + background: #073642; + padding: 0; +} + +#workspaces > button { + margin: 0 1px; + padding: 4px 8px; +} + +#workspaces > button:hover { + background: rgba(88, 110, 117, 0.25); +} diff --git a/options/custom/programs/wezterm/config.lua b/options/custom/programs/wezterm/config.lua new file mode 100644 index 0000000..f266c5f --- /dev/null +++ b/options/custom/programs/wezterm/config.lua @@ -0,0 +1,79 @@ +config.bold_brightens_ansi_colors = "No" +config.check_for_updates = false +config.color_scheme = "solarized" +config.enable_scroll_bar = true + +-- # BUG: Wayland is currently a WIP +-- https://github.com/wez/wezterm/issues/5793 +config.enable_wayland = false + +-- # BUG: Font weight does not render properly with WebGpu +-- https://github.com/wez/wezterm/issues/3032 +-- # BUG: fontconfig is broken in unstable +-- https://github.com/NixOS/nixpkgs/pull/338815 +-- config.font = wezterm.font('monospace') +config.font = wezterm.font('Iosevka NFP SemiBold') + +config.force_reverse_video_cursor = true -- Invert colors + +-- # BUG: OpenGL/Software rendering is broken +-- https://github.com/wez/wezterm/issues/5990 +config.front_end = 'WebGpu' -- Vulkan support + +config.hide_tab_bar_if_only_one_tab = true +config.scrollback_lines = 10000 +config.tab_bar_at_bottom = true +config.use_fancy_tab_bar = false +config.use_resize_increments = true +config.warn_about_missing_glyphs = false + +config.window_padding = { + left = '1cell', + right = '1cell', + top = '0.25cell', + bottom = '0.25cell' +} + +-- https://wezfurlong.org/wezterm/config/mouse.html +config.mouse_bindings = { + { + -- Disable primary selection + event = {Up = {streak = 1, button = 'Left'}}, + mods = 'SHIFT', + action = act.CompleteSelectionOrOpenLinkAtMouseCursor("Clipboard") + }, { + event = {Up = {streak = 1, button = 'Left'}}, + mods = 'NONE', + action = act.CompleteSelectionOrOpenLinkAtMouseCursor("Clipboard") + }, { + event = {Up = {streak = 1, button = 'Left'}}, + mods = 'ALT', + action = act.CompleteSelectionOrOpenLinkAtMouseCursor("Clipboard") + }, { + event = {Up = {streak = 2, button = 'Left'}}, + mods = 'NONE', + action = act.CompleteSelection("Clipboard") + }, { + event = {Up = {streak = 3, button = 'Left'}}, + mods = 'NONE', + action = act.CompleteSelection("Clipboard") + }, { + event = {Up = {streak = 1, button = 'Left'}}, + mods = 'ALT|SHIFT', + action = act.CompleteSelection("Clipboard") + }, { + event = {Down = {streak = 1, button = 'Middle'}}, + mods = 'NONE', + action = act.CompleteSelectionOrOpenLinkAtMouseCursor("Clipboard") + }, { + -- Lower scroll speed + -- https://github.com/wez/wezterm/issues/3142 + event = {Down = {streak = 1, button = {WheelUp = 1}}}, + mods = 'NONE', + action = act.ScrollByLine(-5) + }, { + event = {Down = {streak = 1, button = {WheelDown = 1}}}, + mods = 'NONE', + action = act.ScrollByLine(5) + } +} diff --git a/options/custom/programs/wezterm/default.nix b/options/custom/programs/wezterm/default.nix new file mode 100644 index 0000000..e28e513 --- /dev/null +++ b/options/custom/programs/wezterm/default.nix @@ -0,0 +1,65 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.wezterm; +in +{ + options.custom.programs.wezterm.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/wez/wezterm + programs.wezterm = { + enable = true; + + # https://wezfurlong.org/wezterm/config/files.html + extraConfig = '' + -- Provided by module + -- local wezterm = require 'wezterm' + + local act = wezterm.action + local config = wezterm.config_builder() + + -- # TODO: Remove when using Wayland + config.font_size = ${toString (14 * config.custom.scale)} + + ${builtins.readFile ./config.lua} + + return config + ''; + + # https://wezfurlong.org/wezterm/config/appearance.html#defining-a-color-scheme-in-a-separate-file + colorSchemes.solarized = { + background = "#002b36"; + foreground = "#839496"; + selection_bg = "#839496"; + selection_fg = "#073642"; + cursor_border = "#839496"; + scrollbar_thumb = "#073642"; + + ansi = [ + "073642" + "dc322f" + "859900" + "b58900" + "268bd2" + "d33682" + "2aa198" + "eee8d5" + ]; + + brights = [ + "002b36" + "cb4b16" + "586e75" + "657b83" + "839496" + "6c71c4" + "93a1a1" + "fdf6e3" + ]; + }; + }; + }; +} diff --git a/options/custom/programs/wofi.nix b/options/custom/programs/wofi.nix new file mode 100644 index 0000000..2d10e4e --- /dev/null +++ b/options/custom/programs/wofi.nix @@ -0,0 +1,58 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.wofi; +in +{ + options.custom.programs.wofi.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://hg.sr.ht/~scoopta/wofi + programs.wofi = { + enable = true; + + #?? man 5 wofi + settings = { + allow_images = true; + + # TODO: Fix line height + # BUG: Not dynamic + # https://todo.sr.ht/~scoopta/wofi/93 + # dynamic_lines = true; + + hide_scroll = true; + insensitive = true; + no_actions = true; + lines = 6; + matching = "multi-contains"; + + # BUG: Prompt only displayed without textbox focus + # https://todo.sr.ht/~scoopta/wofi/169 + prompt = ""; + + # Fix flickering on open + # https://todo.sr.ht/~scoopta/wofi/183 + width = 1000; + # height = 500; + }; + + # https://cloudninja.pw/docs/wofi.html + style = '' + * { + padding: 2px; + border-radius: 20px; + } + + window { + border: 2px #073642 solid; + } + + #entry:selected { + outline: none; + } + ''; + }; + }; +} diff --git a/options/custom/programs/wpaperd.nix b/options/custom/programs/wpaperd.nix new file mode 100644 index 0000000..33a302b --- /dev/null +++ b/options/custom/programs/wpaperd.nix @@ -0,0 +1,21 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.programs.wpaperd; +in +{ + options.custom.programs.wpaperd.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/danyspin97/wpaperd + programs.wpaperd = { + enable = true; + + settings.default = { + path = "/tmp/altered.png"; + }; + }; + }; +} diff --git a/options/custom/scripts/audio.sh b/options/custom/scripts/audio.sh new file mode 100644 index 0000000..7599c89 --- /dev/null +++ b/options/custom/scripts/audio.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env bash + +if [[ -v 1 ]]; then + easyeffects --load-preset "$1" && + easyeffects --bypass 2 + notify-send '> audio' "$1" --urgency low +else + easyeffects --load-preset Flat && + easyeffects --bypass 1 + notify-send '> audio' 'Bypass' --urgency low +fi diff --git a/options/custom/scripts/bcrypt.py b/options/custom/scripts/bcrypt.py new file mode 100644 index 0000000..1ede061 --- /dev/null +++ b/options/custom/scripts/bcrypt.py @@ -0,0 +1,7 @@ +#! /usr/bin/env python + +# Generate bcrypt hash + +import bcrypt + +print(bcrypt.hashpw(input("Password: ").encode(), bcrypt.gensalt()).decode()) diff --git a/options/custom/scripts/bwm.sh b/options/custom/scripts/bwm.sh new file mode 100644 index 0000000..0d3a2c4 --- /dev/null +++ b/options/custom/scripts/bwm.sh @@ -0,0 +1,50 @@ +#! /usr/bin/env bash + +# Bitwarden dmenu +# TODO: Clear clipboard after timer + +SESSIONFILE="$XDG_RUNTIME_DIR/bwm" + +# Use current session if exists +if test -f "$SESSIONFILE"; then + BW_SESSION="$(cat "$SESSIONFILE")" && export BW_SESSION +fi + +# Unlock vault if needed +if ! bw unlock --check; then + # Prompt for obfuscated password + password="$(wofi --dmenu --password --lines 3 <<< 'Vault locked. Enter master password.')" + + # Save session to /tmp + BW_SESSION="$(bw unlock "$password" --raw)" && export BW_SESSION + touch "$SESSIONFILE" + chmod u=rw,g=,o= "$SESSIONFILE" + echo "$BW_SESSION" > "$SESSIONFILE" +fi + +# Prompt for search term +search="$(wofi --dmenu --lines 3 <<< 'Enter item to search.')" + +# Gather and parse results +items="$(bw list items --search "$search")" +usernames="$(jq -r '.[].login.username' <<< "$items")" +passwords="$(jq -r '.[].login.password' <<< "$items")" + +# Prompt to select username +username="$(wofi --dmenu <<< "$usernames")" + +# Find matching password line number +count=1 + +while IFS= read -r username; do + if [[ "$username" == "$username" ]]; then + break + else + ((count++)) + fi +done <<< "$usernames" + +# Copy line to clipboard +tail --lines "+$count" <<< "$passwords" | head -1 | tee >(xclip -rmlastnl -selection clipboard &> /dev/null) >(wl-copy --trim-newline &> /dev/null) + +notify-send '> bwm' 'Copied' --urgency low diff --git a/options/custom/scripts/calc.sh b/options/custom/scripts/calc.sh new file mode 100644 index 0000000..ca8f67c --- /dev/null +++ b/options/custom/scripts/calc.sh @@ -0,0 +1,25 @@ +#! /usr/bin/env bash + +# Dmenu qalculator +# TODO: Use --pre-display-cmd? + +HISTORYFILE="$HOME/.config/qalculate/qalc.dmenu.history" + +# If history file contains text +if test -s "$HISTORYFILE"; then + # Gather unique reversed history + prompt="$(tac "$HISTORYFILE" | nl | sort --unique --key 2 | sort | cut --fields 2)" + lines=6 +else + # Default prompt + prompt='Enter calculation.' + lines=3 +fi + +# Prompt for calculation +input="$(wofi --dmenu --lines "$lines" <<< "$prompt")" + +# Copy qalc result to history file and clipboard +result="$(qalc --terse "$input" | tee --append "$HISTORYFILE" >(xclip -rmlastnl -selection clipboard &> /dev/null) >(wl-copy --trim-newline &> /dev/null))" + +notify-send '> calc' "$result" --urgency low diff --git a/options/custom/scripts/clipboard.sh b/options/custom/scripts/clipboard.sh new file mode 100644 index 0000000..2279f48 --- /dev/null +++ b/options/custom/scripts/clipboard.sh @@ -0,0 +1,14 @@ +#! /usr/bin/env bash + +# Toggle clipboard menu + +# Kill menu if running +if ! pkill wofi; then + # Prompt clipboard for selection + selection="$(cliphist list | wofi --dmenu)" + + # Decode and copy to clipboard + cliphist decode <<< "$selection" | tee >(xclip -rmlastnl -selection clipboard &> /dev/null) >(wl-copy --trim-newline &> /dev/null) + + notify-send '> clipboard' 'Copied' --urgency low +fi diff --git a/options/custom/scripts/close.sh b/options/custom/scripts/close.sh new file mode 100644 index 0000000..e99a92e --- /dev/null +++ b/options/custom/scripts/close.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env bash + +# Close all windows + +# Gather windows with classes +# If they don't have classes, ¯\_(ツ)_/¯ +clients="$(hyprctl clients -j | jq -j '.[] | if .class != "" then "\(.pid) " else empty end')" + +notify-send '> close' 'Killing open windows...' --urgency low + +kill "$clients" diff --git a/options/custom/scripts/default.nix b/options/custom/scripts/default.nix new file mode 100644 index 0000000..52e1745 --- /dev/null +++ b/options/custom/scripts/default.nix @@ -0,0 +1,183 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + # Use packages from local derivation + git = config.home-manager.users.${config.custom.username}.programs.git.package; + hyprland = + config.home-manager.users.${config.custom.username}.wayland.windowManager.hyprland.finalPackage; + wofi = config.home-manager.users.${config.custom.username}.programs.wofi.package; +in +{ + config.home-manager.users.${config.custom.username}.home.file = + let + # Place script.ext in the same directory as this file + #?? pkg = (SHELL "NAME" [ DEPENDENCIES ]) + # https://nixos.org/manual/nixpkgs/unstable/#trivial-builder-writeShellApplication + bash = name: dependencies: { + ".local/bin/${name}".source = + pkgs.writeShellApplication { + inherit name; + runtimeInputs = dependencies; + text = builtins.readFile ./${name}.sh; + } + + "/bin/${name}"; + }; + + # https://wiki.nixos.org/wiki/Nix-writers#Python3 + # Always latest python version in nixpkgs, use writers.makePythonWriter to pin version + # https://github.com/NixOS/nixpkgs/blob/master/pkgs/build-support/writers/scripts.nix#L605 + python = name: dependencies: { + ".local/bin/${name}".source = + pkgs.writers.writePython3Bin name { libraries = dependencies; } + # Disable linting + # https://flake8.pycqa.org/en/3.1.1/user/ignoring-errors.html#ignoring-entire-files + ("# flake8: noqa\n" + builtins.readFile ./${name}.py) + + "/bin/${name}"; + }; + in + mkIf config.custom.full ( + with pkgs; + mkMerge ( + [ + # Bash files with extension .sh + (bash "audio" [ + easyeffects + libnotify + ]) + (bash "bwm" [ + bitwarden-cli + coreutils + jq + libnotify + wl-clipboard + wofi + xclip + ]) + (bash "calc" [ + coreutils + libnotify + libqalculate + wl-clipboard + wofi + xclip + ]) + (bash "clipboard" [ + cliphist + libnotify + procps + wl-clipboard + wofi + xclip + ]) + (bash "close" [ + coreutils + hyprland + jq + libnotify + ]) + (bash "fingerprints" [ + fprintd + libnotify + ]) + (bash "flakegen" [ + git + libnotify + nix + ]) + (bash "inhibit" [ + coreutils + libnotify + systemd + ]) + (bash "left" [ + hyprland + jq + libnotify + ]) + (bash "minimize" [ + hyprland + jq + libnotify + ]) + (bash "network" [ + libnotify + networkmanager + ]) + (bash "power" [ + libnotify + power-profiles-daemon + ]) + (bash "rebuild" [ + libnotify + nixos-rebuild + ]) + (bash "repl" [ + libnotify + nixos-rebuild + ]) + (bash "screenshot" [ + coreutils + grimblast + imagemagick + libnotify + swappy + ]) + (bash "target" [ + libnotify + nixos-rebuild + ]) + (bash "toggle" [ + gnugrep + hyprland + jq + libnotify + ]) + (bash "upgrade" [ + libnotify + nix + nixos-rebuild + ]) + (bash "vm" [ + coreutils + freerdp3 + iputils + libnotify + libvirt + remmina + ]) + (bash "vpn" [ + gnused + jq + libnotify + tailscale + ]) + (bash "vrr" [ + hyprland + jq + libnotify + ]) + (bash "wallpaper" [ + coreutils + fd + imagemagick + libnotify + rsync + swww + tailscale + ]) + + ] + ++ (with pkgs.python3Packages; [ + # Python files with extension .py + (python "bcrypt" [ bcrypt ]) + ]) + ) + ); +} diff --git a/options/custom/scripts/fingerprints.sh b/options/custom/scripts/fingerprints.sh new file mode 100644 index 0000000..8c4ebf7 --- /dev/null +++ b/options/custom/scripts/fingerprints.sh @@ -0,0 +1,8 @@ +#! /usr/bin/env bash + +# Enroll fingerprints + +for finger in {left,right}-{thumb,{index,middle}-finger}; do + fprintd-enroll -f "$finger" + sleep 2 +done diff --git a/options/custom/scripts/flakegen.sh b/options/custom/scripts/flakegen.sh new file mode 100644 index 0000000..b11058e --- /dev/null +++ b/options/custom/scripts/flakegen.sh @@ -0,0 +1,16 @@ +#! /usr/bin/env bash + +# Generate flake.nix via flakegen +# https://github.com/jorsn/flakegen + +cd /etc/nixos || exit 1 + +if [[ "${1-}" == '-r' ]]; then + # Nuke and reinitialize + rm flake.nix + nix flake init --template github:jorsn/flakegen +else + # Generate and track all files + nix run .#genflake flake.nix + git add . +fi diff --git a/options/custom/scripts/inhibit.sh b/options/custom/scripts/inhibit.sh new file mode 100644 index 0000000..79f419e --- /dev/null +++ b/options/custom/scripts/inhibit.sh @@ -0,0 +1,10 @@ +#! /usr/bin/env bash + +# Toggle inhibit idle + +if pkill systemd-inhibit; then + notify-send '> inhibit' 'Stopped inhibiting' --urgency low +else + notify-send '> inhibit' 'Inhibiting...' --urgency low + systemd-inhibit --what idle:handle-lid-switch --who User --why 'User requested' sleep 1d +fi diff --git a/options/custom/scripts/left.sh b/options/custom/scripts/left.sh new file mode 100644 index 0000000..82ac60e --- /dev/null +++ b/options/custom/scripts/left.sh @@ -0,0 +1,15 @@ +#! /usr/bin/env bash + +# Toggle left-handed mouse +# TODO: Make device-specific when commit released +# https://github.com/hyprwm/hyprlang/commit/95471ec86f37acb8281062e54e2be99b24b50cd0 + +left=$(("$(hyprctl getoption input:left_handed -j | jq '.int')" - 1)) + +hyprctl keyword input:left_handed ${left#-} + +if [[ "$(hyprctl getoption input:left_handed -j | jq '.int')" == 1 ]]; then + notify-send '> left' 'Left-handed' --urgency low +else + notify-send '> left' 'Right-handed' --urgency low +fi diff --git a/options/custom/scripts/minimize.sh b/options/custom/scripts/minimize.sh new file mode 100644 index 0000000..ced910a --- /dev/null +++ b/options/custom/scripts/minimize.sh @@ -0,0 +1,12 @@ +#! /usr/bin/env bash + +# Minimize/unminimize active window + +# Get active workspace +workspace="$(hyprctl activewindow -j | jq -r .workspace.name)" + +if [[ "$workspace" == "special:scratchpad" ]]; then + hyprctl dispatch movetoworkspacesilent +0 +else + hyprctl dispatch movetoworkspacesilent special:scratchpad +fi diff --git a/options/custom/scripts/network.sh b/options/custom/scripts/network.sh new file mode 100644 index 0000000..c967514 --- /dev/null +++ b/options/custom/scripts/network.sh @@ -0,0 +1,9 @@ +#! /usr/bin/env bash + +# Toggle networking on/off + +if [[ "$(nmcli networking connectivity)" == 'none' ]]; then + nmcli networking on +else + nmcli networking off +fi diff --git a/options/custom/scripts/power.sh b/options/custom/scripts/power.sh new file mode 100644 index 0000000..1676e91 --- /dev/null +++ b/options/custom/scripts/power.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env bash + +# Toggle power-saver mode + +if [[ "$(powerprofilesctl get)" == 'power-saver' ]]; then + powerprofilesctl set balanced + notify-send '> power' 'Balanced' --urgency low +else + powerprofilesctl set power-saver + notify-send '> power' 'Power Saver' --urgency low +fi diff --git a/options/custom/scripts/rebuild.sh b/options/custom/scripts/rebuild.sh new file mode 100644 index 0000000..cbb1b28 --- /dev/null +++ b/options/custom/scripts/rebuild.sh @@ -0,0 +1,10 @@ +#! /usr/bin/env bash + +# Rebuild local flake configuration + +cd /etc/nixos || exit 1 + +nix run .#genflake flake.nix && + sleep 0.1 && + git add . && + sudo nixos-rebuild --show-trace "$@" diff --git a/options/custom/scripts/repl.sh b/options/custom/scripts/repl.sh new file mode 100644 index 0000000..aff0f49 --- /dev/null +++ b/options/custom/scripts/repl.sh @@ -0,0 +1,10 @@ +#! /usr/bin/env bash + +# Nix repl with loaded configuration + +cd /etc/nixos || exit 1 + +nix run .#genflake flake.nix && + sleep 0.1 && + git add . && + nixos-rebuild repl "$@" diff --git a/options/custom/scripts/screenshot.sh b/options/custom/scripts/screenshot.sh new file mode 100644 index 0000000..3a8d4bc --- /dev/null +++ b/options/custom/scripts/screenshot.sh @@ -0,0 +1,23 @@ +#! /usr/bin/env bash + +# Screenshot region or display with rounded corners + +r=20 # Radius + +function round() { + magick - \ + \( +clone -alpha extract -draw "fill black polygon 0,0 0,$r $r,0 fill white circle $r,$r $r,0" \ + \( +clone -flip \) -compose Multiply -composite \ + \( +clone -flop \) -compose Multiply -composite \) \ + -alpha off -compose CopyOpacity -composite - +} + +# TODO: Use proper flags +# TODO: Add clipboard support +if [[ "${1-}" == '-e' ]]; then + grimblast --freeze save area - | round | swappy --file - +elif [[ "${1-}" == '-d' ]]; then + grimblast --freeze save output - | round > "$XDG_SCREENSHOTS_DIR/$(date +'%F %H.%M.%S').png" +else + grimblast --freeze save area - | round > "$XDG_SCREENSHOTS_DIR/$(date +'%F %H.%M.%S').png" +fi diff --git a/options/custom/scripts/target.sh b/options/custom/scripts/target.sh new file mode 100644 index 0000000..0bc5285 --- /dev/null +++ b/options/custom/scripts/target.sh @@ -0,0 +1,10 @@ +#! /usr/bin/env bash + +# Rebuild and send closures to remote machine + +cd /etc/nixos || exit 1 + +nix run .#genflake flake.nix && + sleep 0.1 && + git add . && + nixos-rebuild --flake .#"$1" --target-host root@"$1" "$2" --show-trace "${@:3}" diff --git a/options/custom/scripts/toggle.sh b/options/custom/scripts/toggle.sh new file mode 100644 index 0000000..c68ebab --- /dev/null +++ b/options/custom/scripts/toggle.sh @@ -0,0 +1,27 @@ +#! /usr/bin/env bash + +# Toggle tagged window, launch if needed +#?? toggle TAG WORKSPACE [COMMAND] +# TODO: Use proper flags +# TODO: Support floating groups + +if (("$#" >= 3)); then + # Launch if tag does not exist yet + if ! hyprctl -j clients | jq -r '.[].tags[]' | grep "$1"; then + hyprctl dispatch exec -- "${@:3}" + exit + fi +fi + +# Dispatchers do not currently support matching by tag, so select address +window="address:$(hyprctl -j clients | jq -r "first(.[] | select(.tags[] | startswith(\"$1\")).address)")" + +workspace="$(hyprctl -j clients | jq -r "first(.[] | select(.tags[] | startswith(\"$1\")).workspace.name)")" + +if [[ "$workspace" == "$2" ]]; then + hyprctl dispatch pin "$window" # Pin + (("$#" >= 3)) && hyprctl dispatch focuswindow "$window" # Focus if third argument +else + hyprctl dispatch pin "$window" # Unpin + hyprctl dispatch movetoworkspacesilent "$2,$window" +fi diff --git a/options/custom/scripts/upgrade.sh b/options/custom/scripts/upgrade.sh new file mode 100644 index 0000000..b95ca5f --- /dev/null +++ b/options/custom/scripts/upgrade.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env bash + +# Update flake.lock and rebuild + +cd /etc/nixos || exit 1 + +nix run .#genflake flake.nix && + sleep 0.1 && + git add . && + sudo nix flake update && + sudo nixos-rebuild --show-trace "$@" diff --git a/options/custom/scripts/vm.sh b/options/custom/scripts/vm.sh new file mode 100644 index 0000000..49b81c8 --- /dev/null +++ b/options/custom/scripts/vm.sh @@ -0,0 +1,59 @@ +#! /usr/bin/env bash + +# Start/resume VM if needed and launch viewer +#?? man xfreerdp + +function virsh() { command virsh --connect qemu:///system "$@"; } + +state="$(virsh domstate myndows)" + +if [[ "$state" == 'paused' ]]; then + virsh resume myndows + notify-send '> vm' 'Resumed' --urgency low +elif [[ "$state" == 'shut off' ]]; then + virsh start myndows + notify-send '> vm' 'Starting...' --urgency low + + # Wait for guest to become available + #!! Requires ICMP firewall access on guest + while ! ping -c 1 myndows; do + sleep 1 + done +else + notify-send '> vm' 'Online' --urgency low +fi + +flags=( + '/cert:ignore' + '/v:myndows' + '/u:Myned' + '/p:' + '/kbd:remap:015b=0154' # VK_LWIN=<00> #?? xfreerdp /list:kbd-scancode + '/dynamic-resolution' + '/sound' + '+auto-reconnect' + '+clipboard' + '+menu-anims' + '-grab-keyboard' + '-grab-mouse' +) + +if [[ "${1-}" == '-s' ]]; then + SDL_VIDEODRIVER=wayland sdl-freerdp "${flags[@]}" "${@:2}" + virsh suspend myndows + notify-send '> vm' 'Paused' --urgency low +elif [[ "${1-}" == '-w' ]]; then + wlfreerdp "${flags[@]}" "${@:2}" + virsh suspend myndows + notify-send '> vm' 'Paused' --urgency low +elif [[ "${1-}" == '-x' ]]; then + xfreerdp "${flags[@]}" "${@:2}" + virsh suspend myndows + notify-send '> vm' 'Paused' --urgency low +elif [[ "${1-}" == '-e' ]]; then + "$@" + virsh suspend myndows + notify-send '> vm' 'Paused' --urgency low +else + "$@" +fi diff --git a/options/custom/scripts/vpn.sh b/options/custom/scripts/vpn.sh new file mode 100644 index 0000000..b2831cc --- /dev/null +++ b/options/custom/scripts/vpn.sh @@ -0,0 +1,16 @@ +#! /usr/bin/env bash + +# Toggle tailscale exit node + +if [[ "$(tailscale status --json | jq .ExitNodeStatus.Online)" == 'true' ]]; then + tailscale set --exit-node= + notify-send '> vpn' 'Disconnected' --urgency low +elif [[ "${1-}" == '-s' ]]; then + # TODO: Remove regex workaround when tailscale v1.70.0 is in nixpkgs + suggested="$(tailscale exit-node suggest | sed --regexp-extended --quiet 's/Suggested exit node: (.+)\./\1/p')" + tailscale set --exit-node="$suggested" --exit-node-allow-lan-access + notify-send '> vpn' "Connected to $suggested" --urgency low +else + tailscale set --exit-node="$1" --exit-node-allow-lan-access + notify-send '> vpn' "Connected to $1" --urgency low +fi diff --git a/options/custom/scripts/vrr.sh b/options/custom/scripts/vrr.sh new file mode 100644 index 0000000..8de4f09 --- /dev/null +++ b/options/custom/scripts/vrr.sh @@ -0,0 +1,11 @@ +#! /usr/bin/env bash + +# Toggle vrr + +if [[ "$(hyprctl -j getoption misc:vrr | jq .int)" != 0 ]]; then + hyprctl keyword misc:vrr 0 + notify-send '> vrr' 'Disabled' --urgency low +else + hyprctl keyword misc:vrr 2 + notify-send '> vrr' 'Enabled' --urgency low +fi diff --git a/options/custom/scripts/wallpaper.sh b/options/custom/scripts/wallpaper.sh new file mode 100644 index 0000000..8ada740 --- /dev/null +++ b/options/custom/scripts/wallpaper.sh @@ -0,0 +1,33 @@ +#! /usr/bin/env bash + +# Wallpaper switcher +#?? wallpaper DIRECTORY + +INTERVAL=15 # Minutes/seconds between switches +WALLPAPER=/tmp/wallpaper.png # Path to copy original +ALTERED=/tmp/altered.png # Path to create altered image +STATIC=/srv/static/wallpaper.png # Path to static image on server + +# Launch wallpaper daemon in background +swww-daemon & + +# Delay before initial switch +sleep "$INTERVAL"s + +while true; do + # Select random image from argument directory + cp "$(fd . -t file -e png -e jpg -e jpeg "${1:-$HOME/SYNC/owo/unsorted}" | shuf -n 1)" "$WALLPAPER" + + # Apply image alterations + #// magick "$WALLPAPER" -brightness-contrast -50x-50 -blur x50 "$ALTERED" + magick "$WALLPAPER" -brightness-contrast -50x-50 "$ALTERED" + + # Display altered wallpaper + swww img "$ALTERED" + + # Send unaltered image to server in background + #!! Hostname dependent + rsync --chown caddy:caddy "$WALLPAPER" root@myarm:"$STATIC" || notify-send --urgency critical '> wallpaper' 'Upload failed' & + + sleep "$INTERVAL"m +done diff --git a/options/custom/services/agenix.nix b/options/custom/services/agenix.nix new file mode 100644 index 0000000..3bdc956 --- /dev/null +++ b/options/custom/services/agenix.nix @@ -0,0 +1,47 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cat = "${pkgs.coreutils}/bin/cat"; + sed = "${pkgs.gnused}/bin/sed"; + + cfg = config.custom.services.agenix; +in +{ + options.custom.services.agenix.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + xdg.configFile."hypr/hyprland.conf".force = true; + + # Replace placeholders with secrets after agenix user service starts + systemd.user.services.secrets = { + Unit = { + Description = "Replace agenix secrets in-place"; + After = "agenix.service"; + }; + + Service = { + ExecStart = pkgs.writeShellScript "secrets" '' + file="${config.custom.homeDirectory}/.config/hypr/hyprland.conf" + + ${sed} -i "s|@BW_CLIENTID@|$(${cat} ${ + config.age.secrets."desktop/bitwarden/client_id".path + })|" "$file" + ${sed} -i "s|@BW_CLIENTSECRET@|$(${cat} ${ + config.age.secrets."desktop/bitwarden/client_secret".path + })|" "$file" + ''; + }; + + Install = { + WantedBy = [ "default.target" ]; + }; + }; + }; +} diff --git a/options/custom/services/auto-cpufreq.nix b/options/custom/services/auto-cpufreq.nix new file mode 100644 index 0000000..b564a37 --- /dev/null +++ b/options/custom/services/auto-cpufreq.nix @@ -0,0 +1,47 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.auto-cpufreq; +in +{ + options.custom.services.auto-cpufreq = { + enable = mkOption { default = false; }; + + max = { + battery = mkOption { default = null; }; # GHz + charger = mkOption { default = null; }; # GHz + }; + }; + + config = mkIf cfg.enable { + # https://github.com/AdnanHodzic/auto-cpufreq + #?? auto-cpufreq --stats + #?? cpu-power freqency-info + #?? grep '' /sys/devices/system/cpu/cpu0/cpufreq/* + services = { + auto-cpufreq = { + enable = true; + + # https://github.com/AdnanHodzic/auto-cpufreq/blob/master/auto-cpufreq.conf-example + settings = { + battery = { + energy_performance_preference = "balance_power"; + governor = "powersave"; + scaling_max_freq = mkIf (isFloat cfg.max.battery) (builtins.floor (cfg.max.battery * 1000 * 1000)); # KHz + #// turbo = "never"; # Only works with acpi-cpufreq + }; + + charger = { + energy_performance_preference = "balance_performance"; + governor = "powersave"; + scaling_max_freq = mkIf (isFloat cfg.max.charger) (builtins.floor (cfg.max.charger * 1000 * 1000)); # KHz + }; + }; + }; + + power-profiles-daemon.enable = false; # Conflicts with auto-cpufreq + }; + }; +} diff --git a/options/custom/services/avizo.nix b/options/custom/services/avizo.nix new file mode 100644 index 0000000..b3a5a32 --- /dev/null +++ b/options/custom/services/avizo.nix @@ -0,0 +1,28 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.avizo; +in +{ + options.custom.services.avizo.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/misterdanb/avizo + services.avizo = { + enable = true; + + # https://github.com/misterdanb/avizo/blob/master/config.ini + settings = { + default = { + time = 1; + height = 150; + border-radius = 12; + background = "#93a1a1"; + border-color = "#002b36"; + }; + }; + }; + }; +} diff --git a/options/custom/services/blueman-applet.nix b/options/custom/services/blueman-applet.nix new file mode 100644 index 0000000..3375c28 --- /dev/null +++ b/options/custom/services/blueman-applet.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.blueman-applet; +in +{ + options.custom.services.blueman-applet.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/blueman-project/blueman + services.blueman-applet.enable = true; + }; +} diff --git a/options/custom/services/blueman.nix b/options/custom/services/blueman.nix new file mode 100644 index 0000000..a7ae5a3 --- /dev/null +++ b/options/custom/services/blueman.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.blueman; +in +{ + options.custom.services.blueman.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/blueman-project/blueman + services.blueman.enable = true; + }; +} diff --git a/options/custom/services/borgmatic.nix b/options/custom/services/borgmatic.nix new file mode 100644 index 0000000..2762627 --- /dev/null +++ b/options/custom/services/borgmatic.nix @@ -0,0 +1,79 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cat = "${pkgs.coreutils}/bin/cat"; + + cfg = config.custom.services.borgmatic; +in +{ + # https://wiki.nixos.org/wiki/Borg_backup + # https://github.com/borgmatic-collective/borgmatic + #!! Imperative initialization + #?? sudo borgmatic init -e repokey-blake2 + #?? sudo borgmatic key export + #?? sudo borgmatic -v 1 create --progress --stats + options.custom.services.borgmatic = { + enable = mkOption { default = false; }; + repositories = mkOption { default = [ ]; }; + sources = mkOption { default = [ ]; }; + }; + + config = mkIf cfg.enable { + services.borgmatic = { + enable = true; + + # https://torsion.org/borgmatic/docs/reference/configuration/ + settings = { + keep_daily = 7; + keep_weekly = 4; + keep_monthly = 1; + keep_yearly = 1; + retries = 10; + retry_wait = 60; # Additive seconds per retry + compression = "auto,zstd"; # Use heuristics to decide whether to compress with zstd + ssh_command = "ssh -i /etc/ssh/id_ed25519"; # !! Imperative key generation + encryption_passcommand = "${cat} ${ + config.age.secrets."${config.custom.profile}/borgmatic/borgbase.${config.custom.hostname}".path + }"; + repositories = cfg.repositories; + source_directories = cfg.sources; + + # TODO: Add more databases + #?? sudo borgmatic restore --archive latest + # postgresql_databases = [ + # { + # name = "nextcloud"; + # username = "nextcloud"; + # pg_dump_command = "docker exec -i nextcloud-db pg_dump"; + # pg_restore_command = "docker exec -i nextcloud-db pg_restore"; + # psql_command = "docker exec -i nextcloud-db psql"; + # } + + # { + # name = "piped"; + # username = "piped"; + # pg_dump_command = "docker exec -i postgres pg_dump"; + # pg_restore_command = "docker exec -i postgres pg_restore"; + # psql_command = "docker exec -i postgres psql"; + # } + # ]; + }; + }; + + age.secrets = + let + secret = filename: { file = "${inputs.self}/secrets/${filename}"; }; + in + { + "${config.custom.profile}/borgmatic/borgbase.${config.custom.hostname}" = secret "${config.custom.profile}/borgmatic/borgbase.${config.custom.hostname}"; + }; + }; +} diff --git a/options/custom/services/caddy.nix b/options/custom/services/caddy.nix new file mode 100644 index 0000000..84afe90 --- /dev/null +++ b/options/custom/services/caddy.nix @@ -0,0 +1,77 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.services.caddy; +in +{ + options.custom.services.caddy.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + owner = "caddy"; + group = "caddy"; + }; + in + { + "${config.custom.profile}/caddy/Caddyfile" = secret "${config.custom.profile}/caddy/Caddyfile"; + }; + + # https://caddyserver.com/ + # https://github.com/caddyserver/caddy + services = { + caddy = { + enable = true; + + # TODO: Convert services to Tailscale subdomains when supported or use plugin when supported by nix + # https://github.com/tailscale/tailscale/issues/7081 + # https://github.com/tailscale/caddy-tailscale + # https://github.com/NixOS/nixpkgs/pull/317881 + configFile = config.age.secrets."${config.custom.profile}/caddy/Caddyfile".path; + }; + }; + + # Serve static files + systemd.tmpfiles.rules = [ + "d /srv/static - caddy caddy" + "Z /srv/static - caddy caddy" + ]; + + # https://wiki.nixos.org/wiki/Firewall + # https://github.com/coturn/coturn/blob/master/docker/coturn/README.md + # https://element-hq.github.io/synapse/latest/turn-howto.html + networking.firewall = { + enable = true; + + allowedTCPPorts = [ + 80 # HTTP + 443 # HTTPS + 1935 # RTMP + 3478 # TURN + 5349 # TURN + ]; + + allowedUDPPorts = [ + 3478 # TURN + 5349 # TURN + ]; + + allowedUDPPortRanges = [ + { + # TURN + from = 49152; + to = 65535; + } + ]; + }; + }; +} diff --git a/options/custom/services/clipcat.nix b/options/custom/services/clipcat.nix new file mode 100644 index 0000000..4d0cadd --- /dev/null +++ b/options/custom/services/clipcat.nix @@ -0,0 +1,42 @@ +{ config, lib, ... }: + +with lib; + +let + wofi = "${config.home-manager.users.${config.custom.username}.programs.wofi.package}/bin/wofi"; + + cfg = config.custom.services.clipcat; +in +{ + options.custom.services.clipcat.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # BUG: Random high CPU usage + # https://github.com/xrelkd/clipcat/issues/347 + # https://github.com/xrelkd/clipcat + services.clipcat.enable = true; + + # https://github.com/xrelkd/clipcat?tab=readme-ov-file#configuration + home-manager.users.${config.custom.username}.home.file = { + ".config/clipcat/clipcatd.toml".text = '' + daemonize = false + max_history = 100 + + [watcher] + enable_clipboard = true + enable_primary = false + + [grpc] + enable_http = false + ''; + + ".config/clipcat/clipcat-menu.toml".text = '' + finder = "custom_finder" + + [custom_finder] + program = "${wofi}" + args = ["--dmenu"] + ''; + }; + }; +} diff --git a/options/custom/services/cliphist.nix b/options/custom/services/cliphist.nix new file mode 100644 index 0000000..2510e34 --- /dev/null +++ b/options/custom/services/cliphist.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.cliphist; +in +{ + options.custom.services.cliphist.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/sentriz/cliphist + services.cliphist.enable = true; + }; +} diff --git a/options/custom/services/create_ap.nix b/options/custom/services/create_ap.nix new file mode 100644 index 0000000..1688770 --- /dev/null +++ b/options/custom/services/create_ap.nix @@ -0,0 +1,80 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + bash = "${pkgs.bash}/bin/bash"; + cat = "${pkgs.coreutils}/bin/cat"; + sleep = "${pkgs.coreutils}/bin/sleep"; + + create_ap = "${ + config.home-manager.users.${config.custom.username}.services.create_ap.package + }/bin/create_ap"; + + cfg = config.custom.services.create_ap; +in +{ + options.custom.services.create_ap = { + enable = mkOption { default = false; }; + internet = mkOption { default = "eth0"; }; + wifi = mkOption { default = "wlan0"; }; + }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { file = "${inputs.self}/secrets/${filename}"; }; + in + { + "${config.custom.profile}/create_ap/passphrase" = secret "${config.custom.profile}/create_ap/passphrase"; + "${config.custom.profile}/create_ap/ssid" = secret "${config.custom.profile}/create_ap/ssid"; + }; + + # https://github.com/lakinduakash/linux-wifi-hotspot + services.create_ap = { + enable = true; + + #!! Declare defaults, enable with interfaces and secrets in machine config + # https://github.com/lakinduakash/linux-wifi-hotspot/blob/master/src/scripts/create_ap.conf + settings = { + COUNTRY = "US"; + FREQ_BAND = 5; + IEEE80211AC = 1; + IEEE80211AX = 1; + IEEE80211N = 1; + NO_HAVEGED = 1; # Obsolete since kernel v5.6 + NO_VIRT = 1; + }; + }; + + # Override service command with decrypted passphrase + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/networking/create_ap.nix + systemd.services.create_ap.serviceConfig = { + ExecStartPre = "${sleep} 15s"; # Some cards like Intel force regulatory domain discovery + + ExecStart = + let + configFile = pkgs.writeText "create_ap.conf" ( + generators.toKeyValue { } config.services.create_ap.settings + ); + in + mkForce ( + concatStringsSep " " [ + "${bash} -c" + "'${create_ap}" + "--config ${configFile}" + "${cfg.wifi}" + "${cfg.internet}" + "$(${cat} ${config.age.secrets."${config.custom.profile}/create_ap/ssid".path})" + "$(${cat} ${config.age.secrets."${config.custom.profile}/create_ap/passphrase".path})'" + ] + ); + }; + }; +} diff --git a/options/custom/services/dbus.nix b/options/custom/services/dbus.nix new file mode 100644 index 0000000..d431246 --- /dev/null +++ b/options/custom/services/dbus.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.dbus; +in +{ + options.custom.services.dbus.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/bus1/dbus-broker + # TODO: Scour journal for dbus errors + environment.systemPackages = with pkgs; [ dbus ]; + services.dbus.implementation = "broker"; # Newer message bus + }; +} diff --git a/options/custom/services/default.nix b/options/custom/services/default.nix new file mode 100644 index 0000000..90de35d --- /dev/null +++ b/options/custom/services/default.nix @@ -0,0 +1,50 @@ +{ config, lib, ... }: + +with lib; + +{ + config.custom.services = mkMerge [ + (mkIf config.custom.default { + #// agenix.enable = true; + tailscale.enable = true; + }) + + (mkIf config.custom.minimal { + dbus.enable = true; + flatpak.enable = true; + fwupd.enable = true; + geoclue2.enable = true; + kdeconnect.enable = true; + keyd.enable = true; + libinput.enable = true; + logind.enable = true; + pipewire.enable = true; + playerctld.enable = true; + ratbagd.enable = true; + syncthing.enable = true; + udev.enable = true; + upower.enable = true; + }) + + (mkIf config.custom.full { + #// avizo.enable = true; + #// blueman-applet.enable = true; + #// clipcat.enable = true; + #// cliphist.enable = true; + easyeffects.enable = true; + gammastep.enable = true; + gnome-keyring.enable = true; + gpg-agent.enable = true; + greetd.enable = true; + hypridle.enable = true; + #// hyprpaper.enable = true; + #// mako.enable = true; + #// network-manager-applet.enable = true; + samba.enable = true; + #// swayidle.enable = true; + swaync.enable = true; + swayosd.enable = true; + #// xembed-sni-proxy.enable = true; + }) + ]; +} diff --git a/options/custom/services/easyeffects.nix b/options/custom/services/easyeffects.nix new file mode 100644 index 0000000..4864551 --- /dev/null +++ b/options/custom/services/easyeffects.nix @@ -0,0 +1,23 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.easyeffects; +in +{ + options.custom.services.easyeffects.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/wwmm/easyeffects + # systemctl --user start easyeffects.service + services.easyeffects.enable = true; + + ### PRESETS ### + # https://github.com/Digitalone1/EasyEffects-Presets + home.file = with config.home-manager.users.${config.custom.username}.lib.file; { + ".config/easyeffects/input".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/linux/config/easyeffects/input"; + ".config/easyeffects/output".source = mkOutOfStoreSymlink "/home/${config.custom.username}/SYNC/linux/config/easyeffects/output"; + }; + }; +} diff --git a/options/custom/services/flatpak.nix b/options/custom/services/flatpak.nix new file mode 100644 index 0000000..9e1e47c --- /dev/null +++ b/options/custom/services/flatpak.nix @@ -0,0 +1,40 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.flatpak; +in +{ + options.custom.services.flatpak.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Flatpak + # https://github.com/gmodena/nix-flatpak + services.flatpak = { + enable = true; + uninstallUnmanaged = true; # Immutable flatpaks + update.auto.enable = true; # Auto update flatpaks weekly + + #!! Installation occurs in background as a oneshot service + #?? flatpak search NAME + packages = [ + "app.drey.Biblioteca" + "com.github.tchx84.Flatseal" + ]; + }; + + # Theme packages must be installed system-wide for flatpaks + environment.systemPackages = with pkgs; [ + adw-gtk3 + google-cursor + papirus-icon-theme + ]; + }; +} diff --git a/options/custom/services/fprintd.nix b/options/custom/services/fprintd.nix new file mode 100644 index 0000000..ef694c8 --- /dev/null +++ b/options/custom/services/fprintd.nix @@ -0,0 +1,18 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.fprintd; +in +{ + options.custom.services.fprintd.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.archlinux.org/title/Fprint + # https://www.freedesktop.org/wiki/Software/fprint + #!! Configuration is imperative + #?? fprintd-enroll -f FINGER + services.fprintd.enable = true; + }; +} diff --git a/options/custom/services/fw-fanctrl.nix b/options/custom/services/fw-fanctrl.nix new file mode 100644 index 0000000..a70b7b0 --- /dev/null +++ b/options/custom/services/fw-fanctrl.nix @@ -0,0 +1,40 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.fw-fanctrl; +in +{ + options.custom.services.fw-fanctrl.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/TamtamHero/fw-fanctrl/tree/packaging/nix + programs.fw-fanctrl = { + enable = true; + + # https://github.com/TamtamHero/fw-fanctrl/blob/packaging/nix/config.json + #?? fw-fanctrl --reload + config = { + defaultStrategy = "custom"; + + strategies.custom = { + fanSpeedUpdateFrequency = 3; # Seconds + movingAverageInterval = 30; # Seconds + speedCurve = + let + curve = temp: speed: { inherit temp speed; }; + in + [ + (curve 0 0) + (curve 40 20) + (curve 50 30) + (curve 60 40) + (curve 70 50) + #!! Max fan speed of 50% + ]; + }; + }; + }; + }; +} diff --git a/options/custom/services/fwupd.nix b/options/custom/services/fwupd.nix new file mode 100644 index 0000000..13d4a59 --- /dev/null +++ b/options/custom/services/fwupd.nix @@ -0,0 +1,19 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.fwupd; +in +{ + options.custom.services.fwupd.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Fwupd + # https://github.com/fwupd/fwupd + services.fwupd = { + enable = true; + extraRemotes = [ "lvfs-testing" ]; + }; + }; +} diff --git a/options/custom/services/gammastep.nix b/options/custom/services/gammastep.nix new file mode 100644 index 0000000..4f4f53e --- /dev/null +++ b/options/custom/services/gammastep.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.gammastep; +in +{ + options.custom.services.gammastep.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://gitlab.com/chinstrap/gammastep + services.gammastep = { + enable = true; + enableVerboseLogging = true; + provider = "geoclue2"; # geoclue2 service must be enabled + + temperature = { + day = 5000; + night = 4000; + }; + + # TODO: Add keybinds + settings.general = { + brightness-day = 1; + brightness-night = 0.5; + }; + }; + }; +} diff --git a/options/custom/services/geoclue2.nix b/options/custom/services/geoclue2.nix new file mode 100644 index 0000000..262ba4b --- /dev/null +++ b/options/custom/services/geoclue2.nix @@ -0,0 +1,56 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.services.geoclue2; +in +{ + options.custom.services.geoclue2.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + owner = "geoclue"; + group = "geoclue"; + }; + in + { + "desktop/geoclue2/geolocation" = secret "desktop/geoclue2/geolocation"; + }; + + # https://gitlab.freedesktop.org/geoclue/geoclue + # FIXME: geoclue2 relies on MLS, which is retired + # https://github.com/NixOS/nixpkgs/issues/321121 + # TODO: Use static source option when merged into unstable + # https://github.com/NixOS/nixpkgs/pull/329654 + services.geoclue2 = { + enable = true; + + # Overriden by static source + enable3G = false; + enableCDMA = false; + enableModemGPS = false; + enableNmea = false; + enableWifi = false; + }; + + # Manually use static source from coordinates + # https://github.com/NixOS/nixpkgs/issues/311595#issuecomment-2247989491 + environment.etc = { + "geolocation".source = config.age.secrets."desktop/geoclue2/geolocation".path; + + "geoclue/conf.d/00-config.conf".text = '' + [static-source] + enable=true + ''; + }; + }; +} diff --git a/options/custom/services/gnome-keyring.nix b/options/custom/services/gnome-keyring.nix new file mode 100644 index 0000000..84c104d --- /dev/null +++ b/options/custom/services/gnome-keyring.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.gnome-keyring; +in +{ + options.custom.services.gnome-keyring.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.archlinux.org/title/GNOME/Keyring + # https://gitlab.gnome.org/GNOME/gnome-keyring + services.gnome-keyring.enable = true; + }; +} diff --git a/options/custom/services/gpg-agent.nix b/options/custom/services/gpg-agent.nix new file mode 100644 index 0000000..f558022 --- /dev/null +++ b/options/custom/services/gpg-agent.nix @@ -0,0 +1,23 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.gpg-agent; +in +{ + options.custom.services.gpg-agent.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.archlinux.org/title/GnuPG#gpg-agent + services.gpg-agent = { + enable = true; + pinentryPackage = pkgs.pinentry-gnome3; # Default: curses + }; + }; +} diff --git a/options/custom/services/greetd.nix b/options/custom/services/greetd.nix new file mode 100644 index 0000000..691252c --- /dev/null +++ b/options/custom/services/greetd.nix @@ -0,0 +1,55 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + Hyprland = "${config.programs.hyprland.package}/bin/Hyprland"; + systemd-cat = "${pkgs.systemd}/bin/systemd-cat"; + tuigreet = "${pkgs.greetd.tuigreet}/bin/tuigreet"; + + cfg = config.custom.services.greetd; +in +{ + options.custom.services.greetd.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://sr.ht/~kennylevinsen/greetd + # https://github.com/apognu/tuigreet + services.greetd = { + enable = true; + + settings.default_session = { + command = lib.concatStringsSep " " [ + "${tuigreet}" + "--session-wrapper '${systemd-cat} --identifier hyprland'" # ?? journalctl --identifier hyprland + "--cmd ${Hyprland}" + "--remember" + "--time" + "--asterisks" + "--window-padding 1" + "--greeting owo" + ]; + }; + }; + + # Attempt to prevent bootlogs from polluting the tty + # https://github.com/apognu/tuigreet/issues/68 + systemd.services.greetd.serviceConfig = { + Type = "idle"; + StandardInput = "tty"; + StandardOutput = "tty"; + StandardError = "journal"; + TTYReset = true; + TTYVHangup = true; + TTYVTDisallocate = true; + }; + + # FIXME: Does not unlock at login + security.pam.services.greetd.enableGnomeKeyring = true; # Allow PAM unlocking + }; +} diff --git a/options/custom/services/hypridle.nix b/options/custom/services/hypridle.nix new file mode 100644 index 0000000..437708b --- /dev/null +++ b/options/custom/services/hypridle.nix @@ -0,0 +1,60 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + grep = "${pkgs.gnugrep}/bin/grep"; + hyprctl = "${ + config.home-manager.users.${config.custom.username}.wayland.windowManager.hyprland.finalPackage + }/bin/hyprctl"; + hyprlock = "${ + config.home-manager.users.${config.custom.username}.programs.hyprlock.package + }/bin/hyprlock"; + loginctl = "${pkgs.systemd}/bin/loginctl"; + pgrep = "${pkgs.coreutils}/bin/pgrep"; + pw-cli = "${pkgs.pipewire}/bin/pw-cli"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + + cfg = config.custom.services.hypridle; +in +{ + options.custom.services.hypridle.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/hyprwm/hypridle + # https://wiki.hyprland.org/Hypr-Ecosystem/hypridle + services.hypridle = { + enable = true; + + settings = { + general = { + before_sleep_cmd = "${pgrep} hyprlock || ${hyprlock} --immediate"; + lock_cmd = "${pgrep} hyprlock || ${hyprlock}"; + }; + + listener = [ + { + timeout = 15 * 60; # Seconds + on-timeout = "${loginctl} lock-session"; + } + + { + timeout = 20 * 60; # Seconds + on-timeout = "${hyprctl} dispatch dpms off"; + } + + { + # FIXME: Add resume offset to mynix + timeout = 60 * 60; # Seconds + on-timeout = "${pw-cli} info all | ${grep} running || ${systemctl} suspend-then-hibernate"; # Suspend if no audio + } + ]; + }; + }; + }; +} diff --git a/options/custom/services/hyprpaper.nix b/options/custom/services/hyprpaper.nix new file mode 100644 index 0000000..57aaada --- /dev/null +++ b/options/custom/services/hyprpaper.nix @@ -0,0 +1,27 @@ +{ + config, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.services.hyprpaper; +in +{ + options.custom.services.hyprpaper.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://wiki.hyprland.org/Hypr-Ecosystem/hyprpaper + # https://github.com/hyprwm/hyprpaper + services.hyprpaper = { + enable = true; + + settings = { + preload = [ "/tmp/altered.png" ]; + wallpaper = [ ", /tmp/altered.png" ]; + }; + }; + }; +} diff --git a/options/custom/services/kdeconnect.nix b/options/custom/services/kdeconnect.nix new file mode 100644 index 0000000..da879bf --- /dev/null +++ b/options/custom/services/kdeconnect.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.kdeconnect; +in +{ + options.custom.services.kdeconnect.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/KDE/kdeconnect-kde + services.kdeconnect.enable = true; + }; +} diff --git a/options/custom/services/keyd.nix b/options/custom/services/keyd.nix new file mode 100644 index 0000000..f24562e --- /dev/null +++ b/options/custom/services/keyd.nix @@ -0,0 +1,128 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.keyd; +in +{ + options.custom.services.keyd.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/rvaiya/keyd + #?? keyd list-keys + #!! Enabling xkeyboard-config layouts will underlap with keyd binds + services.keyd = { + enable = true; + + #!! Binds use qwerty without layouts + #?? keyd monitor + keyboards.default.settings = { + #// global.disable_modifier_guard = 1; # Disable extraneous Control injection + + control.esc = "toggle(qwerty)"; # Control+Esc toggles qwerty + shift.shift = "capslock"; # Both Shifts toggle Capslock + + # Emulate function keys + function = { + space = "playpause"; + rightalt = "previoussong"; + rightcontrol = "nextsong"; + backspace = "mute"; + minus = "volumedown"; + equal = "volumeup"; + + ";" = "pageup"; + "." = "pagedown"; + "'" = "home"; + "/" = "end"; + "\\" = "sysrq"; # Printscreen + }; + + qwerty = { + capslock = "capslock"; + backspace = "backspace"; + + "w" = "w"; + "," = ","; + "s" = "s"; + "a" = "a"; + "c" = "c"; + "g" = "g"; + "q" = "q"; + "e" = "e"; + "]" = "]"; + "d" = "d"; + "/" = "/"; + ";" = ";"; + "'" = "'"; + "r" = "r"; + "f" = "f"; + "t" = "t"; + "u" = "u"; + "." = "."; + "j" = "j"; + "k" = "k"; + "p" = "p"; + "o" = "o"; + "z" = "z"; + "h" = "h"; + "i" = "i"; + "[" = "["; + "v" = "v"; + "l" = "l"; + "m" = "m"; + "n" = "n"; + "x" = "x"; + "b" = "b"; + "y" = "y"; + }; + + main = { + capslock = "backspace"; + backspace = "delete"; + + compose = "layer(function)"; + leftmeta = "layer(alt)"; + leftalt = "layer(meta)"; + rightalt = "layer(meta)"; + + # Colemak default + "w" = "w"; + "," = ","; + "s" = "r"; + "a" = "a"; + "c" = "c"; + "g" = "d"; + "q" = "q"; + "e" = "f"; + "]" = "]"; + "d" = "s"; + "/" = "/"; + ";" = "o"; + "'" = "'"; + "r" = "p"; + "f" = "t"; + "t" = "g"; + "u" = "l"; + "." = "."; + "j" = "n"; + "k" = "e"; + "p" = ";"; + "o" = "y"; + "z" = "z"; + "h" = "h"; + "i" = "u"; + "[" = "["; + "v" = "v"; + "l" = "i"; + "m" = "m"; + "n" = "k"; + "x" = "x"; + "b" = "b"; + "y" = "j"; + }; + }; + }; + }; +} diff --git a/options/custom/services/libinput.nix b/options/custom/services/libinput.nix new file mode 100644 index 0000000..3af4e9b --- /dev/null +++ b/options/custom/services/libinput.nix @@ -0,0 +1,26 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.libinput; +in +{ + options.custom.services.libinput.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://gitlab.freedesktop.org/libinput/libinput + services = { + libinput.enable = true; + + # https://wiki.archlinux.org/title/Libinput#Via_Udev_Rule + # https://wiki.archlinux.org/title/Libinput#Disable_device + #?? libinput list-devices + #?? udevadm info --attribute-walk /dev/input/DEVICE + # udev.extraRules = '' + # # Disable controller touchpad + # ACTION=="add|change", ATTRS{name}=="Wireless Controller Touchpad", ENV{LIBINPUT_IGNORE_DEVICE}="1" + # ''; + }; + }; +} diff --git a/options/custom/services/logind.nix b/options/custom/services/logind.nix new file mode 100644 index 0000000..6ad618c --- /dev/null +++ b/options/custom/services/logind.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.logind; +in +{ + options.custom.services.logind.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + services.logind = { + lidSwitch = "suspend-then-hibernate"; # Laptop lid switch + }; + }; +} diff --git a/options/custom/services/mako.nix b/options/custom/services/mako.nix new file mode 100644 index 0000000..16d9d22 --- /dev/null +++ b/options/custom/services/mako.nix @@ -0,0 +1,30 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.mako; +in +{ + options.custom.services.mako.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/emersion/mako + # FIXME: Cairo subpixel rendering; WL_OUTPUT_SUBPIXEL_NONE? + # https://github.com/emersion/mako/issues/258 + services.mako = { + enable = true; + borderRadius = 12; + borderSize = 2; + defaultTimeout = 5 * 1000; # 5 seconds + width = 750; + anchor = "top-center"; + backgroundColor = "#073642"; + borderColor = "#002b36"; + font = "sans-serif 12"; + layer = "overlay"; + margin = "20"; + padding = "10"; + }; + }; +} diff --git a/options/custom/services/matrix-conduit.nix b/options/custom/services/matrix-conduit.nix new file mode 100644 index 0000000..add2a53 --- /dev/null +++ b/options/custom/services/matrix-conduit.nix @@ -0,0 +1,66 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.matrix-conduit; +in +{ + options.custom.services.matrix-conduit.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + owner = "300"; + group = "300"; + }; + in + { + "${config.custom.profile}/matrix-conduit/conduwuit.toml" = secret "${config.custom.profile}/matrix-conduit/conduwuit.toml"; + }; + + # https://wiki.nixos.org/wiki/Matrix + # https://conduwuit.puppyirl.gay/deploying/nixos.html + # https://github.com/girlbossceo/conduwuit + services.matrix-conduit = { + enable = true; + package = inputs.conduwuit.packages.${pkgs.system}.default-debug; # !! Debug build + }; + + # Bind conduwuit service to media mount + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/matrix/conduit.nix#L113 + systemd.services.conduit = + let + mount = "mnt-remote-conduwuit.mount"; + in + { + after = [ mount ]; + bindsTo = [ mount ]; + + # Override with static uid for media mount + serviceConfig.User = lib.mkForce "300"; # 400-499 is reserved for system users + + # Override module's attempt to use conduit default config + # https://github.com/girlbossceo/conduwuit/blob/main/conduwuit-example.toml + environment = lib.mkForce { + CONDUWUIT_CONFIG = config.age.secrets."${config.custom.profile}/matrix-conduit/conduwuit.toml".path; + }; + }; + + # Create bind mount to remote media in lieu of conduwuit.toml setting + # https://nixos.wiki/wiki/Filesystems#Bind_mounts + fileSystems."/var/lib/matrix-conduit/media" = { + device = "/mnt/remote/conduwuit/media"; + fsType = "none"; + options = [ "bind" ]; + }; + }; +} diff --git a/options/custom/services/modufur.nix b/options/custom/services/modufur.nix new file mode 100644 index 0000000..d6e8344 --- /dev/null +++ b/options/custom/services/modufur.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + poetry = "${pkgs.poetry}/bin/poetry"; + + cfg = config.custom.services.modufur; +in +{ + options.custom.services.modufur.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + #!! Imperative source control + #?? git clone https://github.com/Myned/modufur + systemd.user.services.modufur = { + description = [ "Modufur" ]; + requires = [ "default.target" ]; + after = [ "default.target" ]; + wantedBy = [ "default.target" ]; + + serviceConfig = { + WorkingDirectory = [ "/home/myned/.git/modufur" ]; + ExecStart = [ "${poetry}/bin/poetry run python -OO run.py >&2" ]; + }; + }; + }; +} diff --git a/options/custom/services/netdata.nix b/options/custom/services/netdata.nix new file mode 100644 index 0000000..55edffa --- /dev/null +++ b/options/custom/services/netdata.nix @@ -0,0 +1,71 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.services.netdata; +in +{ + options.custom.services.netdata = { + enable = mkOption { default = false; }; + parent = mkOption { default = false; }; + child = mkOption { default = false; }; + }; + + config = + let + role = + if cfg.parent then + "parent" + else if cfg.child then + "child" + else + ""; + in + mkIf cfg.enable { + # https://github.com/netdata/netdata + # https://wiki.nixos.org/wiki/Netdata + services.netdata = { + enable = true; + + # Override package to include v2 dashboard + # https://learn.netdata.cloud/docs/developer-and-contributor-corner/redistributed-software + package = mkIf cfg.parent pkgs.netdata.override { withCloudUi = true; }; # !! NCUL1 non-free license + + # Minimize overhead for children + # https://learn.netdata.cloud/docs/netdata-agent/configuration/daemon-configuration + # https://learn.netdata.cloud/docs/netdata-agent/configuration/how-to-optimize-the-netdata-agent-s-performance + config = { + global."memory mode" = mkIf cfg.child "ram"; + health.enabled = mkIf cfg.child "no"; + ml.enabled = mkIf cfg.child "no"; + + web = { + mode = mkIf cfg.child "none"; + "enable gzip compression" = "no"; + }; + }; + + configDir."stream.conf" = mkIf ( + role != "" + ) config.age.secrets."${config.custom.profile}/netdata/${role}.conf".path; + }; + + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + owner = "netdata"; + group = "netdata"; + }; + in + mkIf (role != "") { + "${config.custom.profile}/netdata/${role}.conf" = secret "${config.custom.profile}/netdata/${role}.conf"; + }; + }; +} diff --git a/options/custom/services/network-manager-applet.nix b/options/custom/services/network-manager-applet.nix new file mode 100644 index 0000000..4850b4d --- /dev/null +++ b/options/custom/services/network-manager-applet.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.network-manager-applet; +in +{ + options.custom.services.network-manager-applet.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://gitlab.gnome.org/GNOME/network-manager-applet + services.network-manager-applet.enable = true; + }; +} diff --git a/options/custom/services/onedrive.nix b/options/custom/services/onedrive.nix new file mode 100644 index 0000000..6e4e303 --- /dev/null +++ b/options/custom/services/onedrive.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.onedrive; +in +{ + options.custom.services.onedrive.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/abraunegg/onedrive + services.onedrive.enable = true; + }; +} diff --git a/options/custom/services/piped.nix b/options/custom/services/piped.nix new file mode 100644 index 0000000..b96fa30 --- /dev/null +++ b/options/custom/services/piped.nix @@ -0,0 +1,51 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + curl = "${pkgs.curl}/bin/curl"; + docker = "${pkgs.docker}/bin/docker"; + parallel = "${pkgs.parallel}/bin/parallel"; + + cfg = config.custom.services.piped; +in +{ + options.custom.services.piped.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Systemd/timers + + # Manually fetch channels in background + # TODO: Remove when fixed upstream + # https://github.com/TeamPiped/Piped/issues/1130 + systemd = { + services."fetch-channels" = { + script = '' + ${docker} compose --file /docker/piped/docker-compose.yml exec postgres \ + psql \ + --username piped \ + --dbname piped \ + --tuples-only \ + --no-align \ + --quiet \ + --command 'SELECT DISTINCT(channel) FROM users_subscribed' | \ + ${parallel} ${curl} --silent --output /dev/null 'https://pipedapi.bjork.tech/channel/{}' + ''; + }; + + timers."fetch-channels" = { + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnBootSec = "1h"; + OnUnitActiveSec = "1h"; + }; + }; + }; + }; +} diff --git a/options/custom/services/pipewire.nix b/options/custom/services/pipewire.nix new file mode 100644 index 0000000..e427b98 --- /dev/null +++ b/options/custom/services/pipewire.nix @@ -0,0 +1,39 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.pipewire; +in +{ + options.custom.services.pipewire.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/PipeWire + # https://gitlab.freedesktop.org/pipewire/pipewire + #!! Realtime priority may cause desync + #// security.rtkit.enable = true; + hardware.pulseaudio.enable = false; + + services.pipewire = { + enable = true; + alsa.enable = true; + alsa.support32Bit = true; + pulse.enable = true; + + # Avoid resampling if possible + # https://wiki.archlinux.org/title/PipeWire#Changing_the_allowed_sample_rate(s) + extraConfig.pipewire = { + "10-sample-rate"."context.properties"."default.clock.allowed-rates" = [ + 32000 + 44100 + 48000 + 88200 + 96000 + 176400 + 192000 + ]; + }; + }; + }; +} diff --git a/options/custom/services/playerctld.nix b/options/custom/services/playerctld.nix new file mode 100644 index 0000000..c34dda7 --- /dev/null +++ b/options/custom/services/playerctld.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.playerctld; +in +{ + options.custom.services.playerctld.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/altdesktop/playerctl + services.playerctld.enable = true; + }; +} diff --git a/options/custom/services/power-profiles-daemon.nix b/options/custom/services/power-profiles-daemon.nix new file mode 100644 index 0000000..ddf898a --- /dev/null +++ b/options/custom/services/power-profiles-daemon.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.power-profiles-daemon; +in +{ + options.custom.services.power-profiles-daemon.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://gitlab.freedesktop.org/upower/power-profiles-daemon + #!! Usage is imperative + #?? powerprofilesctl set + services.power-profiles-daemon.enable = true; + }; +} diff --git a/options/custom/services/ratbagd.nix b/options/custom/services/ratbagd.nix new file mode 100644 index 0000000..709701d --- /dev/null +++ b/options/custom/services/ratbagd.nix @@ -0,0 +1,22 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.ratbagd; +in +{ + options.custom.services.ratbagd.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://github.com/libratbag/libratbag + # https://github.com/libratbag/piper + services.ratbagd.enable = true; + environment.systemPackages = with pkgs; [ piper ]; + }; +} diff --git a/options/custom/services/samba.nix b/options/custom/services/samba.nix new file mode 100644 index 0000000..33dcb32 --- /dev/null +++ b/options/custom/services/samba.nix @@ -0,0 +1,42 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.samba; +in +{ + options.custom.services.samba.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Samba + # https://gitlab.com/samba-team/samba + #!! User configuration is imperative + #?? sudo smbpasswd -a $USER + services.samba = { + enable = true; + openFirewall = true; + + shares = { + Public.path = "/home/${config.custom.username}/Public"; + SYNC.path = "/home/${config.custom.username}/SYNC"; + }; + + extraConfig = '' + logging = systemd + + hosts allow = 127.0.0.1 myndows 192.168.111. + + browseable = yes + writeable = yes + force user = ${config.custom.username} + map to guest = bad password + inherit owner = unix only + inherit permissions = yes + follow symlinks = yes + wide links = yes + allow insecure wide links = yes + ''; + }; + }; +} diff --git a/options/custom/services/swayidle.nix b/options/custom/services/swayidle.nix new file mode 100644 index 0000000..b6a87b2 --- /dev/null +++ b/options/custom/services/swayidle.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + chayang = "${pkgs.chayang}/bin/chayang"; + hyprctl = "${ + config.home-manager.users.${config.custom.username}.wayland.windowManager.hyprland.package + }/bin/hyprctl"; + loginctl = "${pkgs.systemd}/bin/loginctl"; + pgrep = "${pkgs.procps}/bin/pgrep"; + swaylock = "${ + config.home-manager.users.${config.custom.username}.programs.swaylock.package + }/bin/swaylock"; + systemctl = "${pkgs.systemd}/bin/systemctl"; + + cfg = config.custom.services.swayidle; +in +{ + options.custom.services.swayidle.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/swaywm/swayidle + # https://wiki.archlinux.org/title/Sway#Idle + services.swayidle = { + enable = true; + + events = [ + { + command = "${pgrep} swaylock || ${swaylock}"; + event = "before-sleep"; + } + + { + command = "${pgrep} swaylock || ${swaylock}"; + event = "lock"; + } + ]; + + # https://github.com/swaywm/swayidle/blob/master/swayidle.1.scd + #?? man swayidle + timeouts = [ + # Lock session + { + # FIXME: Grace period likely broken by Hyprland (flicker) + #// command = "${pgrep} swaylock || ${swaylock} --grace 300"; # 5 minute grace period + command = "${pgrep} swaylock || ${swaylock}"; + timeout = 15 * 60; # Minutes * 60 + } + + # Fade out display + { + # TODO: Use chayang when supported by Hyprland + # https://github.com/hyprwm/Hyprland/issues/6624 + #// command = "${chayang} -d 15 && ${hyprctl} dispatch dpms off"; + command = "${hyprctl} dispatch dpms off"; + timeout = 20 * 60; # Minutes * 60 + # Resume handled by Hyprland + } + + # TODO: Possibly migrate to systemd-lock-handler for suspend + # https://github.com/NixOS/nixpkgs/pull/259196 + # Suspend system + { + command = "${systemctl} suspend-then-hibernate"; + timeout = 60 * 60; # Minutes * 60 + } + ]; + }; + }; +} diff --git a/options/custom/services/swaync/default.nix b/options/custom/services/swaync/default.nix new file mode 100644 index 0000000..2a67fa3 --- /dev/null +++ b/options/custom/services/swaync/default.nix @@ -0,0 +1,41 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.swaync; +in +{ + options.custom.services.swaync.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/ErikReider/SwayNotificationCenter + services.swaync = { + enable = true; + style = ./style.css; + + # https://github.com/ErikReider/SwayNotificationCenter/blob/main/src/configSchema.json + settings = { + control-center-width = 750 / config.custom.scale; + control-center-height = config.custom.height / 2; + fit-to-screen = false; + hide-on-clear = true; + notification-2fa-action = false; + #// notification-inline-replies = true; + positionX = "center"; + positionY = "top"; + timeout-low = 5; + timeout = 5; # normal + timeout-critical = 0; + + widgets = [ + "notifications" + "backlight" + "inhibitors" + "dnd" + "title" + ]; + }; + }; + }; +} diff --git a/options/custom/services/swaync/style.css b/options/custom/services/swaync/style.css new file mode 100644 index 0000000..a8c6f24 --- /dev/null +++ b/options/custom/services/swaync/style.css @@ -0,0 +1,53 @@ +/*** SwayNotificationCenter +https://docs.gtk.org/gtk3/css-overview.html +https://docs.gtk.org/gtk3/css-properties.html +https://github.com/ErikReider/SwayNotificationCenter/blob/main/data/style/style.scss +***/ + +@define-color cc-bg #002b36; + +@define-color noti-border-color #073642; +@define-color noti-bg #002b36; +@define-color noti-bg-opaque #002b36; +@define-color noti-bg-darker #002b36; +@define-color noti-bg-hover #073642; +@define-color noti-bg-hover-opaque #073642; +@define-color noti-bg-focus #002b36; + +@define-color text-color #93a1a1; +@define-color text-color-disabled #586e75; + +.notification.low { + border: 2px solid #6c71c4; +} + +.notification.normal { + border: 2px solid #d33682; +} + +.notification.critical { + border: 2px solid #dc322f; +} + +.notification-content { + padding: 16px; +} + +.text-box .summary, +.text-box .time { + font-size: 18px; +} + +.text-box .body { + font-size: 16px; +} + +.control-center { + border: 2px solid #073642; + margin: 10px; /* Gap size */ + padding: 16px; +} + +.control-center .notification { + box-shadow: none; +} diff --git a/options/custom/services/swayosd.nix b/options/custom/services/swayosd.nix new file mode 100644 index 0000000..e3408ee --- /dev/null +++ b/options/custom/services/swayosd.nix @@ -0,0 +1,20 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.swayosd; +in +{ + options.custom.services.swayosd.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://github.com/ErikReider/SwayOSD + services.swayosd.enable = true; + + ### THEME ### + # https://github.com/ErikReider/SwayOSD/blob/main/data/style/style.scss + #!! Options not yet available, files written directly + home.file.".config/swayosd/style.css".text = ''''; + }; +} diff --git a/options/custom/services/syncthing.nix b/options/custom/services/syncthing.nix new file mode 100644 index 0000000..bab6c4f --- /dev/null +++ b/options/custom/services/syncthing.nix @@ -0,0 +1,161 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.syncthing; +in +{ + # https://github.com/syncthing/syncthing + # https://wiki.nixos.org/wiki/Syncthing + # https://docs.syncthing.net/users/config.html + options.custom.services.syncthing = { + enable = mkOption { default = false; }; + configDir = mkOption { default = "${cfg.dataDir}/.config/syncthing"; }; + dataDir = mkOption { default = "/home/${cfg.user}"; }; + devices = mkOption { + default = [ + "myarm" + "mynix" + "myork" + ]; + }; + ignorePerms = mkOption { default = false; }; + mount = mkOption { default = null; }; + order = mkOption { default = "alphabetic"; }; + type = mkOption { default = "sendreceive"; }; + user = mkOption { default = config.custom.username; }; + group = mkOption { default = "users"; }; + + versioning = mkOption { + default = { + params.cleanoutDays = "7"; + type = "trashcan"; + }; + }; + + # Per folder attributes override config + folders = mkOption { + default = + let + #?? "FOLDER" = folder "ID" [ "DEVICES" ] + folder = id: devices: { inherit id devices; }; + in + { + "SYNC/.backup" = folder "oxdvq-dfzjk" [ ]; + "SYNC/.ignore" = folder "qpvfw-j127s" [ + "myeck" + "myxel" + ]; + "SYNC/android" = folder "y3omj-gpjch" [ "myxel" ]; + "SYNC/common" = folder "fcsij-g7cnw" [ "myxel" ]; + "SYNC/dev" = folder "fsmar-4wsd3" [ "myxel" ]; + "SYNC/edu" = folder "4nyqw-jfkq2" [ "myxel" ]; + "SYNC/game" = folder "xvdpp-mxlki" [ + "myeck" + "zendows" + ]; + "SYNC/linux" = folder "ieikk-bnm7u" [ "myxel" ]; + "SYNC/mac" = folder "yjmt6-z7u4m" [ ]; + "SYNC/owo" = folder "ervqc-ebnzz" [ "myxel" ]; + "SYNC/windows" = folder "2hmna-vfap9" [ ]; + "ZEL/android" = + folder "gn2l3-2hxtu" [ + "zendows" + "zexel" + ] + // { + type = "receiveonly"; + }; + "ZEL/music" = folder "nytcx-uwqs7" [ "zendows" ] // { + type = "receiveonly"; + }; + }; + }; + }; + + config = mkIf cfg.enable { + services.syncthing = { + enable = true; + configDir = cfg.configDir; + dataDir = cfg.dataDir; + extraFlags = [ "-no-default-folder" ]; # Disable automatic creation of Sync folder + guiAddress = "0.0.0.0:8384"; # Open to all interfaces + openDefaultPorts = true; # Open transfer/discovery ports + user = cfg.user; + group = cfg.group; + + # https://docs.syncthing.net/rest/config.html + # Undocumented endpoints can be manually extended onto /rest/config/* + #?? "END/POINT" = null + #!! Untrusted devices/folders are not exposed via options + # https://github.com/NixOS/nixpkgs/issues/121286 + #!! GUI configured imperatively + settings = { + options.urAccepted = -1; # Decline usage statistics + + # BUG: Defaults are not applied via API + # https://github.com/syncthing/syncthing/issues/6748 + # https://github.com/NixOS/nixpkgs/issues/268282 + "defaults/ignores".lines = [ + # Linux + "(?d).~*" + "(?d).directory" + "(?d)*.kate-swp" + + # macOS + "(?d).DS_Store" + "(?d).Spotlight-V100" + "(?d).Trashes" + "(?d)__MACOSX" + + # Windows + "(?d)~*" + "(?d)*.laccdb" + + # Development + "(?d).venv" + "(?d).data" + "(?d)*.lock" + "(?d)*.meldcmp" + "(?d)node_modules" + ]; + + # Devices can be declared globally without issue + # Syncthing seems to ignore entries that match the machine's id + devices = { + myarm = { + introducer = true; + id = "XM3ZAIB-337KY6I-T2IFUF6-U6NE7M2-OHKKX4F-CGQDTYE-DBKSIUD-E6RUBQJ"; + }; + + mynix.id = "UFLECA5-QQUKD5J-FQB55TE-YKKHD37-VT5ASXU-4EGUZNV-KW7Z434-FBI7CQ2"; + myork.id = "UTVTIWY-6YCR2XG-UPCUFDX-O6AVZQP-XJM7ZA6-CPAL6LP-YS4LFUA-XMTO6QG"; + myxel.id = "JXIWWYX-7YPOZKV-HPPCPZW-25P34XV-Z7RB7NY-46QN26M-YNP3S4I-UQEISAH"; + myeck.id = "NLGUPGG-XFGRDSE-43MQEXO-TLEW2XD-DMOL6RM-RPQ4IFQ-GENDXPF-PM7NQAO"; + zendows.id = "4JS6YSF-OBZFPYW-B3OUF4G-R6DVOZ4-KFAVGFY-NT4J223-E44HK3D-GPYAFQP"; + zexel.id = "VYG4QAC-SY7ET5F-CHIPQUN-TP6P7WN-LQCT3HO-UBS73JG-ZGOKCLG-SHWZOAN"; + }; + + # Simplify boilerplate folders + folders = concatMapAttrs (name: folder: { + "~/${name}" = { + ignorePerms = cfg.ignorePerms; + label = name; + order = cfg.order; + type = cfg.type; + versioning = cfg.versioning; + } // folder // { devices = cfg.devices ++ folder.devices or [ ]; }; + }) cfg.folders; + }; + }; + + #!! Syncthing needs to start after mounting or there is a risk of file deletion + # https://github.com/NixOS/nixpkgs/blob/nixos-unstable/nixos/modules/services/networking/syncthing.nix#L646 + #?? systemctl status + systemd.services.syncthing = mkIf (isString cfg.mount) { + after = [ cfg.mount ]; + bindsTo = [ cfg.mount ]; # Start/stop service on mount/unmount + }; + }; +} diff --git a/options/custom/services/tailscale.nix b/options/custom/services/tailscale.nix new file mode 100644 index 0000000..1e04ce4 --- /dev/null +++ b/options/custom/services/tailscale.nix @@ -0,0 +1,74 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cat = "${pkgs.coreutils}/bin/cat"; + tailscale = "${config.services.tailscale.package}/bin/tailscale"; + + cfg = config.custom.services.tailscale; +in +{ + # TODO: Enact recommendations + # https://tailscale.com/kb/1320/performance-best-practices + # https://github.com/tailscale/tailscale + #!! Configuration is imperative + #?? sudo tailscale up --ssh --advertise-exit-node --accept-routes --operator=$USER --reset --qr + options.custom.services.tailscale = { + enable = mkOption { default = false; }; + cert = mkOption { default = false; }; + }; + + # TODO: Use caddy plugin for provisioning when supported by NixOS + # https://github.com/NixOS/nixpkgs/pull/317881 + # https://github.com/tailscale/caddy-tailscale + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "common/tailscale/tailnet" = secret "common/tailscale/tailnet"; + }; + + services.tailscale = { + enable = true; + #// permitCertUid = mkIf cfg.cert "caddy"; # Allow caddy to fetch TLS certificates + useRoutingFeatures = "both"; # Enable server/client exit nodes + }; + + # Provision Tailscale certificates in the background per machine + systemd = + let + hostname = config.custom.hostname; + in + mkIf cfg.cert { + #!! Needs to be run on the machine + # tailscale cert always writes to /var/lib/tailscale/certs/ regardless of flags + services."tailscale-cert-${hostname}".script = concatStringsSep " " [ + "${tailscale} cert" + "--cert-file -" + "--key-file -" + "${hostname}.\"$(${cat} ${config.age.secrets."common/tailscale/tailnet".path})\"" + "> /dev/null" + ]; + + timers."tailscale-cert-${hostname}" = { + wantedBy = [ "timers.target" ]; + + timerConfig = { + OnCalendar = "daily"; + Persistent = true; # Retry if previous timer missed + }; + }; + }; + }; +} diff --git a/options/custom/services/udev.nix b/options/custom/services/udev.nix new file mode 100644 index 0000000..0435d4d --- /dev/null +++ b/options/custom/services/udev.nix @@ -0,0 +1,30 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.services.udev; +in +{ + options.custom.services.udev.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.archlinux.org/title/Udev + # Allow video group to change display brightness + # https://raw.githubusercontent.com/ErikReider/SwayOSD/main/data/udev/99-swayosd.rules + services.udev.extraRules = + let + chgrp = "${pkgs.coreutils}/bin/chgrp"; + chmod = "${pkgs.coreutils}/bin/chmod"; + in + '' + ACTION=="add", SUBSYSTEM=="backlight", RUN+="${chgrp} video /sys/class/backlight/%k/brightness" + ACTION=="add", SUBSYSTEM=="backlight", RUN+="${chmod} g+w /sys/class/backlight/%k/brightness" + ''; + }; +} diff --git a/options/custom/services/upower.nix b/options/custom/services/upower.nix new file mode 100644 index 0000000..d0962e9 --- /dev/null +++ b/options/custom/services/upower.nix @@ -0,0 +1,15 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.upower; +in +{ + options.custom.services.upower.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://gitlab.freedesktop.org/upower/upower + services.upower.enable = true; + }; +} diff --git a/options/custom/services/xembed-sni-proxy.nix b/options/custom/services/xembed-sni-proxy.nix new file mode 100644 index 0000000..0c04899 --- /dev/null +++ b/options/custom/services/xembed-sni-proxy.nix @@ -0,0 +1,14 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.services.xembed-sni-proxy; +in +{ + options.custom.services.xembed-sni-proxy.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + services.xembed-sni-proxy.enable = true; # Support XEmbed tray icons + }; +} diff --git a/options/custom/settings/accounts.nix b/options/custom/settings/accounts.nix new file mode 100644 index 0000000..56ea581 --- /dev/null +++ b/options/custom/settings/accounts.nix @@ -0,0 +1,31 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.accounts; +in +{ + options.custom.settings.accounts.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + accounts = { + email.accounts.${config.custom.username} = { + primary = true; + address = "${config.custom.username}@${config.custom.domain}"; + realName = config.custom.realname; + userName = "${config.custom.username}@${config.custom.domain}"; + + imap = { + host = "imap.fastmail.com"; + port = 993; + }; + + smtp = { + host = "smtp.fastmail.com"; + port = 465; + }; + }; + }; + }; +} diff --git a/options/custom/settings/boot.nix b/options/custom/settings/boot.nix new file mode 100644 index 0000000..8ccf2a6 --- /dev/null +++ b/options/custom/settings/boot.nix @@ -0,0 +1,89 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + sed = "${pkgs.gnused}/bin/sed"; + + cfg = config.custom.settings.boot; +in +{ + options.custom.settings.boot = { + enable = mkOption { default = false; }; + console-mode = mkOption { default = "max"; }; + grub = mkOption { default = false; }; + kernel = mkOption { + default = if config.custom.full then pkgs.linuxPackages_zen else pkgs.linuxPackages; + }; + systemd-boot = mkOption { default = config.custom.minimal; }; + timeout = mkOption { default = if config.custom.minimal then 2 else 10; }; + u-boot = mkOption { default = false; }; + }; + + config = mkIf cfg.enable { + boot = { + # https://wiki.nixos.org/wiki/Linux_kernel + kernelPackages = cfg.kernel; + + kernel.sysctl = mkIf config.custom.default { + # https://wiki.archlinux.org/title/Sysctl#Virtual_memory + "vm.dirty_bytes" = 256 * 1024 * 1024; # 256MB + "vm.dirty_background_bytes" = 128 * 1024 * 1024; # 128MB + "vm.vfs_cache_pressure" = 50; # Default: 100 + + # https://wiki.archlinux.org/title/Swap#Swappiness + "vm.swappiness" = 1; # Default: 60 + + # https://redis.io/docs/latest/develop/get-started/faq/#background-saving-fails-with-a-fork-error-on-linux + "vm.overcommit_memory" = 1; + }; + + loader = { + timeout = cfg.timeout; + + systemd-boot = mkIf cfg.systemd-boot { + enable = true; + configurationLimit = 15; + consoleMode = cfg.console-mode; + editor = false; # Disable cmdline + + # HACK: consoleMode does not accept undocumented device modes (e.g. 3 4 5) + extraInstallCommands = mkIf (isInt cfg.console-mode && cfg.console-mode > 2) '' + ${sed} -i 's|console-mode.*|console-mode ${toString cfg.console-mode}|' /boot/loader/loader.conf + ''; + }; + + generic-extlinux-compatible.enable = cfg.u-boot; + grub.enable = cfg.grub; + }; + }; + + console = mkIf config.custom.minimal { + # Modified Solarized Dark + # https://github.com/coderonline/base16-vtrgb/blob/master/consolecolors/base16-solarized-dark.hex + colors = [ + "073642" + "002b36" # Background + "859900" # Success + "657b83" + "839496" + "b58900" + "eee8d5" + "93a1a1" # Primary + "dc322f" + "cb4b16" + "d33682" # Tertiary + "586e75" + "6c71c4" # Accent + "268bd2" + "2aa198" + "fdf6e3" # Secondary + ]; + }; + }; +} diff --git a/options/custom/settings/containers/actualbudget.nix b/options/custom/settings/containers/actualbudget.nix new file mode 100644 index 0000000..fa0c26d --- /dev/null +++ b/options/custom/settings/containers/actualbudget.nix @@ -0,0 +1,34 @@ +{ + config, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.actualbudget; +in +{ + options.custom.settings.containers.actualbudget.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + #?? arion-actualbudget pull + environment.shellAliases.arion-actualbudget = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.actualbudget.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.actualbudget = { + serviceName = "actualbudget"; + + settings.services = { + actualbudget.service = { + container_name = "actualbudget"; + image = "actualbudget/actual-server:24.9.0"; + ports = [ "5006:5006" ]; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/actualbudget/data:/data" ]; + # TODO: Set up trusted proxies + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/coturn.nix b/options/custom/settings/containers/coturn.nix new file mode 100644 index 0000000..a4bbc3a --- /dev/null +++ b/options/custom/settings/containers/coturn.nix @@ -0,0 +1,57 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.coturn; +in +{ + options.custom.settings.containers.coturn.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/coturn/coturn.conf" = secret "${config.custom.profile}/coturn/coturn.conf"; + }; + + #?? arion-coturn pull + environment.shellAliases.arion-coturn = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.coturn.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.coturn = { + serviceName = "coturn"; + + settings.services = { + # https://conduwuit.puppyirl.gay/turn.html + coturn.service = { + container_name = "coturn"; + image = "coturn/coturn:4.6"; + network_mode = "host"; + restart = "unless-stopped"; + + volumes = [ + "${config.custom.settings.containers.directory}/coturn/coturn.conf:/etc/coturn/turnserver.conf" + ]; + }; + }; + }; + + # TODO: Use nobody:nogroup instead when docker allows changing mount ownership + # HACK: Copy with global read-only permissions in container directory which is assumed to be locked down + # https://github.com/moby/moby/issues/2259 + systemd.tmpfiles.rules = [ + "C ${config.custom.settings.containers.directory}/coturn/coturn.conf 0444 - - - ${ + config.age.secrets."${config.custom.profile}/coturn/coturn.conf".path + }" + ]; + }; +} diff --git a/options/custom/settings/containers/default.nix b/options/custom/settings/containers/default.nix new file mode 100644 index 0000000..c13a3ba --- /dev/null +++ b/options/custom/settings/containers/default.nix @@ -0,0 +1,84 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers; +in +{ + options.custom.settings.containers = { + enable = mkOption { default = false; }; + boot = mkOption { default = false; }; + directory = mkOption { default = "/containers"; }; + docker = mkOption { default = true; }; + }; + + config = mkIf cfg.enable { + virtualisation = { + # https://github.com/hercules-ci/arion + # https://docs.hercules-ci.com/arion/options + # https://docs.hercules-ci.com/arion/deployment#_nixos_module + arion.backend = if cfg.docker then "docker" else "podman-socket"; + + # https://wiki.nixos.org/wiki/NixOS_Containers + oci-containers.backend = if cfg.docker then "docker" else "podman"; + + # https://github.com/containers/common/blob/main/docs/containers.conf.5.md + containers = { + enable = true; + containersConf.settings.engine.compose_warning_logs = !cfg.docker; + }; + + # https://www.docker.com + # https://wiki.nixos.org/wiki/Docker + docker = mkIf cfg.docker { + enable = true; + enableOnBoot = cfg.boot; # Socket activation + storageDriver = "overlay2"; + }; + + # https://github.com/containers/podman + # https://wiki.nixos.org/wiki/Podman + podman = mkIf (!cfg.docker) { + enable = true; + dockerCompat = true; # Drop-in for docker command + dockerSocket.enable = true; # Docker API + defaultNetwork.settings.dns_enabled = true; # Compose container shortnames + + autoPrune = { + enable = true; + flags = [ + "--all" + "--volumes" + ]; + }; + }; + }; + + environment.systemPackages = + with pkgs; + [ + # https://github.com/hercules-ci/arion/issues/210 + #?? arion-CONTAINER + arion + + # https://github.com/aksiksi/compose2nix + # Convert docker-compose.yml to NixOS oci-containers + #?? compose2nix + #// inputs.compose2nix.packages.${system}.default + ] + ++ optionals (!cfg.docker) [ + podman-compose + podman-tui + ]; + + systemd.tmpfiles.rules = [ "d /containers 0700 root root" ]; # Custom directory for containers + users.users.${config.custom.username}.extraGroups = [ (if cfg.docker then "docker" else "podman") ]; + }; +} diff --git a/options/custom/settings/containers/forgejo.nix b/options/custom/settings/containers/forgejo.nix new file mode 100644 index 0000000..f6194a3 --- /dev/null +++ b/options/custom/settings/containers/forgejo.nix @@ -0,0 +1,65 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.forgejo; +in +{ + options.custom.settings.containers.forgejo.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/forgejo/.env" = secret "${config.custom.profile}/forgejo/.env"; + "${config.custom.profile}/forgejo/db.env" = secret "${config.custom.profile}/forgejo/db.env"; + }; + + #?? arion-forgejo pull + environment.shellAliases.arion-forgejo = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.forgejo.settings.out.dockerComposeYaml}"; + + networking.firewall.allowedTCPPorts = [ 22 ]; # SSH + + virtualisation.arion.projects.forgejo = { + serviceName = "forgejo"; + + settings.services = { + # https://codeberg.org/forgejo/forgejo + # https://forgejo.org/docs/latest/admin/ + #?? docker exec -it forgejo bash + #?? sudo -u git forgejo admin user create --username USERNAME --random-password --email EMAIL --admin + forgejo.service = { + container_name = "forgejo"; + depends_on = [ "db" ]; + env_file = [ config.age.secrets."${config.custom.profile}/forgejo/.env".path ]; + image = "codeberg.org/forgejo/forgejo:8"; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/forgejo/data:/data" ]; + + ports = [ + "127.0.0.1:3333:3000" + "22:2222" + ]; + }; + + db.service = { + container_name = "forgejo-db"; + env_file = [ config.age.secrets."${config.custom.profile}/forgejo/db.env".path ]; + image = "postgres:15"; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/forgejo/db:/var/lib/postgresql/data" ]; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/foundryvtt.nix b/options/custom/settings/containers/foundryvtt.nix new file mode 100644 index 0000000..7f56152 --- /dev/null +++ b/options/custom/settings/containers/foundryvtt.nix @@ -0,0 +1,45 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.foundryvtt; +in +{ + options.custom.settings.containers.foundryvtt.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/foundryvtt/.env" = secret "${config.custom.profile}/foundryvtt/.env"; + }; + + #?? arion-foundryvtt pull + environment.shellAliases.arion-foundryvtt = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.foundryvtt.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.foundryvtt = { + serviceName = "foundryvtt"; + + settings.services = { + foundryvtt.service = { + container_name = "foundryvtt"; + env_file = [ config.age.secrets."${config.custom.profile}/foundryvtt/.env".path ]; + image = "felddy/foundryvtt:12"; + ports = [ "127.0.0.1:30000:30000" ]; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/foundryvtt/data:/data" ]; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/homeassistant.nix b/options/custom/settings/containers/homeassistant.nix new file mode 100644 index 0000000..4f9b449 --- /dev/null +++ b/options/custom/settings/containers/homeassistant.nix @@ -0,0 +1,33 @@ +{ + config, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.homeassistant; +in +{ + options.custom.settings.containers.homeassistant.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + #?? arion-homeassistant pull + environment.shellAliases.arion-homeassistant = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.homeassistant.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.homeassistant = { + serviceName = "homeassistant"; + + settings.services = { + homeassistant.service = { + container_name = "homeassistant"; + image = "homeassistant/home-assistant:2024.9.1"; + ports = [ "8123:8123" ]; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/homeassistant/config:/config" ]; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/mastodon.nix b/options/custom/settings/containers/mastodon.nix new file mode 100644 index 0000000..5324d92 --- /dev/null +++ b/options/custom/settings/containers/mastodon.nix @@ -0,0 +1,68 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.mastodon; +in +{ + options.custom.settings.containers.mastodon.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/mastodon/.env" = secret "${config.custom.profile}/mastodon/.env"; + "${config.custom.profile}/mastodon/db.env" = secret "${config.custom.profile}/mastodon/db.env"; + }; + + #?? arion-mastodon pull + environment.shellAliases.arion-mastodon = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.mastodon.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.mastodon = { + serviceName = "mastodon"; + + settings.services = { + # https://github.com/linuxserver/docker-mastodon + # https://github.com/mastodon/mastodon/blob/main/docker-compose.yml + mastodon.service = { + container_name = "mastodon"; + env_file = [ config.age.secrets."${config.custom.profile}/mastodon/.env".path ]; + image = "lscr.io/linuxserver/mastodon:4.2.12"; + ports = [ "3000:443" ]; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/mastodon/config:/config" ]; + + depends_on = [ + "cache" + "db" + ]; + }; + + cache.service = { + container_name = "mastodon-cache"; + image = "redis:latest"; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/mastodon/cache:/data" ]; + }; + + db.service = { + container_name = "mastodon-db"; + env_file = [ config.age.secrets."${config.custom.profile}/mastodon/db.env".path ]; + image = "postgres:15"; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/mastodon/db:/var/lib/postgresql/data" ]; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/nextcloud.nix b/options/custom/settings/containers/nextcloud.nix new file mode 100644 index 0000000..b688021 --- /dev/null +++ b/options/custom/settings/containers/nextcloud.nix @@ -0,0 +1,88 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.nextcloud; +in +{ + options.custom.settings.containers.nextcloud.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/nextcloud/.env" = secret "${config.custom.profile}/nextcloud/.env"; + "${config.custom.profile}/nextcloud/db.env" = secret "${config.custom.profile}/nextcloud/db.env"; + }; + + #?? arion-nextcloud pull + environment.shellAliases.arion-nextcloud = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.nextcloud.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.nextcloud = { + serviceName = "nextcloud"; + + settings.services = { + # https://github.com/nextcloud/docker + nextcloud.service = { + container_name = "nextcloud"; + env_file = [ config.age.secrets."${config.custom.profile}/nextcloud/.env".path ]; + image = "nextcloud:29-apache"; + ports = [ "127.0.0.1:8181:80" ]; + restart = "unless-stopped"; + + volumes = [ + "${config.custom.settings.containers.directory}/nextcloud/app:/var/www/html" + "${config.custom.settings.containers.directory}/nextcloud/data:/var/www/html/data" + ]; + + depends_on = [ + "db" + "cache" + ]; + }; + + cron.service = { + container_name = "nextcloud-cron"; + entrypoint = "/cron.sh"; + image = "nextcloud:29-apache"; + restart = "unless-stopped"; + volumes = + config.virtualisation.arion.projects.nextcloud.settings.services.nextcloud.service.volumes; # volumes_from + + depends_on = [ + "db" + "cache" + ]; + }; + + cache.service = { + container_name = "nextcloud-cache"; + image = "redis:latest"; + restart = "unless-stopped"; + volumes = [ "${config.custom.settings.containers.directory}/nextcloud/cache:/data" ]; + }; + + db.service = { + container_name = "nextcloud-db"; + env_file = [ config.age.secrets."${config.custom.profile}/nextcloud/db.env".path ]; + image = "postgres:15"; + restart = "unless-stopped"; + + volumes = [ + "${config.custom.settings.containers.directory}/nextcloud/db:/var/lib/postgresql/data" + ]; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/redlib.nix b/options/custom/settings/containers/redlib.nix new file mode 100644 index 0000000..e1d61e0 --- /dev/null +++ b/options/custom/settings/containers/redlib.nix @@ -0,0 +1,40 @@ +{ + config, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.redlib; +in +{ + options.custom.settings.containers.redlib.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + #?? arion-redlib pull + environment.shellAliases.arion-redlib = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.redlib.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.redlib = { + serviceName = "redlib"; + + settings.services = { + redlib.service = { + container_name = "redlib"; + image = "quay.io/redlib/redlib:latest"; + ports = [ "127.0.0.1:8888:8080" ]; + restart = "unless-stopped"; + + environment = { + REDLIB_DEFAULT_HIDE_HLS_NOTIFICATION = "on"; + REDLIB_DEFAULT_SHOW_NSFW = "on"; + REDLIB_DEFAULT_THEME = "dracula"; + REDLIB_DEFAULT_USE_HLS = "on"; + REDLIB_DEFAULT_WIDE = "off"; + }; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/searxng/default.nix b/options/custom/settings/containers/searxng/default.nix new file mode 100644 index 0000000..fa4e9d3 --- /dev/null +++ b/options/custom/settings/containers/searxng/default.nix @@ -0,0 +1,60 @@ +{ + config, + inputs, + lib, + ... +}: + +with lib; + +let + cfg = config.custom.settings.containers.searxng; +in +{ + options.custom.settings.containers.searxng.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/searxng/.env" = secret "${config.custom.profile}/searxng/.env"; + }; + + #?? arion-searxng pull + environment.shellAliases.arion-searxng = "sudo arion --prebuilt-file ${config.virtualisation.arion.projects.searxng.settings.out.dockerComposeYaml}"; + + virtualisation.arion.projects.searxng = { + serviceName = "searxng"; + + settings.services = { + # https://github.com/searxng/searxng + # https://github.com/searxng/searxng-docker + searxng.service = { + container_name = "searxng"; + depends_on = [ "cache" ]; + env_file = [ config.age.secrets."${config.custom.profile}/searxng/.env".path ]; + image = "searxng/searxng:latest"; + ports = [ "127.0.0.1:8000:8080" ]; + restart = "unless-stopped"; + + volumes = [ + "${./limiter.toml}:/etc/searxng/limiter.toml" + "${./settings.yml}:/etc/searxng/settings.yml" + ]; + }; + + # https://github.com/valkey-io/valkey + cache.service = { + command = "valkey-server --save 60 1 --loglevel warning"; + container_name = "searxng-cache"; + image = "valkey/valkey:7-alpine"; + restart = "unless-stopped"; + }; + }; + }; + }; +} diff --git a/options/custom/settings/containers/searxng/limiter.toml b/options/custom/settings/containers/searxng/limiter.toml new file mode 100644 index 0000000..ff72105 --- /dev/null +++ b/options/custom/settings/containers/searxng/limiter.toml @@ -0,0 +1,7 @@ +# https://docs.searxng.org/admin/searx.limiter.html +[real_ip] +x_for = 1 # Client behind a reverse proxy + +[botdetection.ip_limit] +filter_link_local = true # Limit local addresses +link_token = true # Suspicious if client does not request token diff --git a/options/custom/settings/containers/searxng/settings.yml b/options/custom/settings/containers/searxng/settings.yml new file mode 100644 index 0000000..8608e25 --- /dev/null +++ b/options/custom/settings/containers/searxng/settings.yml @@ -0,0 +1,200 @@ +# https://docs.searxng.org/admin/settings +search: + autocomplete: duckduckgo + autocomplete_min: 3 + +server: + method: GET + +ui: + static_use_hash: true + infinite_scroll: true + default_locale: en + +# https://github.com/searxng/searxng/blob/master/searx/preferences.py +preferences: + lock: + #// - categories + - language + - locale + - autocomplete + - image_proxy + - method + - safesearch + - theme + - results_on_new_tab + - doi_resolver + - simple_style + - center_alignment + - advanced_search + - query_in_title + - infinite_scroll + - search_on_category_select + +# https://docs.searxng.org/admin/plugins.html +enabled_plugins: + # General + - Basic Calculator + - Hostnames plugin + - Open Access DOI rewrite + - Unit converter plugin + + # Privacy + - Tracker URL remover + + # Special + - Hash plugin + - Self Information + - Tor check plugin + +hostnames: + replace: + '(.*\.)?reddit\.com$': 'reddit.bjork.tech' + '(.*\.)?redd\.it$': 'reddit.bjork.tech' + +# https://docs.searxng.org/admin/settings/settings_categories_as_tabs.html#settings-categories-as-tabs +categories_as_tabs: + general: + images: + videos: + news: + #// map: + music: + it: + science: + #// files: + social media: + +# https://docs.searxng.org/admin/settings/settings_engine.html +engines: + # General + - name: brave + disabled: false + - name: currency + disabled: false + #// - name: duckduckgo + #// disabled: false + - name: google + disabled: false + - name: qwant + disabled: false + - name: wikipedia + disabled: false + + # Images + - name: duckduckgo images + disabled: false + - name: qwant images + disabled: false + + # Videos + - name: youtube + disabled: false + + # News + - name: brave.news + disabled: false + - name: duckduckgo news + disabled: false + - name: qwant news + disabled: false + + # Music + - name: bandcamp + disabled: false + - name: genius + disabled: false + - name: soundcloud + disabled: false + - name: youtube + disabled: false + + # IT + - name: arch linux wiki + disabled: false + - name: caddy.community + disabled: false + - name: codeberg + disabled: false + - name: docker hub + disabled: false + - name: github + disabled: false + - name: gitlab + disabled: false + - name: mdn + disabled: false + - name: pypi + disabled: false + - name: sourcehut + disabled: false + - name: stackoverflow + disabled: false + - name: superuser + disabled: false + + # Science + - name: arxiv + disabled: false + - name: google scholar + disabled: false + - name: pubmed + disabled: false + + # Social Media + - name: lemmy communities + disabled: false + - name: lemmy posts + disabled: false + +# https://docs.searxng.org/user/configured_engines.html +use_default_settings: + engines: + keep_only: + # General + - brave + - currency + #// - duckduckgo + - google + - qwant + - wikipedia + + # Images + - duckduckgo images + - qwant images + + # Videos + - youtube + + # News + - brave.news + - duckduckgo news + - qwant news + + # Music + - bandcamp + - genius + - soundcloud + - youtube + + # IT + - arch linux wiki + - caddy.community + - codeberg + - docker hub + - github + - gitlab + - mdn + - pypi + - sourcehut + - stackoverflow + - superuser + + # Science + - arxiv + - google scholar + - pubmed + + # Social Media + - lemmy communities + - lemmy posts diff --git a/options/custom/settings/dconf/apps.nix b/options/custom/settings/dconf/apps.nix new file mode 100644 index 0000000..e4212de --- /dev/null +++ b/options/custom/settings/dconf/apps.nix @@ -0,0 +1,181 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.dconf.apps; +in +{ + options.custom.settings.dconf.apps.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + # https://nix-community.github.io/home-manager/index.xhtml#sec-option-types + # https://docs.gtk.org/glib/struct.Variant.html + # https://docs.gtk.org/glib/gvariant-format-strings.html + #?? dconf watch / + dconf.settings = with config.home-manager.users.${config.custom.username}.lib.gvariant; { + # BlackBox + "com/raggesilver/BlackBox" = { + command-as-login-shell = mkBoolean false; + context-aware-header-bar = mkBoolean true; + cursor-blink-mode = mkUint32 0; + cursor-shape = mkUint32 0; + delay-before-showing-floating-controls = mkUint32 100; + easy-copy-paste = mkBoolean false; + fill-tabs = mkBoolean true; + floating-controls = mkBoolean true; + floating-controls-hover-area = mkUint32 10; + font = mkString "monospace 14"; + headerbar-drag-area = mkBoolean false; + notify-process-completion = mkBoolean false; + opacity = mkUint32 100; + pretty = mkBoolean false; + remember-window-size = mkBoolean false; + scrollback-mode = mkInt32 1; + scrollbar-mode = mkUint32 1; + show-headerbar = mkBoolean false; + show-menu-button = mkBoolean false; + show-scrollbars = mkBoolean true; + style-preference = mkUint32 0; + terminal-bell = mkBoolean true; + terminal-cell-height = mkDouble 1.0; + terminal-cell-width = mkDouble 1.0; + theme-bold-is-bright = mkBoolean false; + theme-dark = mkString "Solarized Dark"; + theme-light = mkString "Solarized Light"; + use-custom-command = mkBoolean false; + use-overlay-scrolling = mkBoolean true; + working-directory-mode = mkUint32 1; + + #?? (uuuu) + terminal-padding = mkTuple [ + (mkUint32 4) + (mkUint32 4) + (mkUint32 4) + (mkUint32 4) + ]; + }; + + # Dconf Editor + "ca/desrt/dconf-editor" = { + show-warning = mkBoolean false; + }; + + # EasyEffects + "com/github/wwmm/easyeffects/spectrum" = { + show = false; + }; + + # GNOME + "org/gnome/desktop/interface" = { + cursor-blink = mkBoolean false; + gtk-enable-primary-paste = mkBoolean false; + color-scheme = mkString "prefer-dark"; + monospace-font-name = mkString "monospace 14"; + }; + + # GNOME Files + "org/gtk/gtk4/settings/file-chooser" = { + show-hidden = mkBoolean true; + }; + + "org/gnome/nautilus/preferences" = { + show-create-link = mkBoolean true; + show-delete-permanently = mkBoolean true; + click-policy = mkString "single"; + default-folder-viewer = mkString "list-view"; + }; + + "org/gnome/nautilus/list-view" = { + #?? [as] + default-column-order = mkArray type.string [ + "name" + "type" + "size" + "owner" + "group" + "permissions" + "where" + "date_modified" + "date_modified_with_time" + "date_accessed" + "date_created" + "recency" + "detailed_type" + ]; + + #?? [as] + default-visible-columns = mkArray type.string [ + "name" + "type" + "size" + "date_modified" + ]; + }; + + # GNOME Terminal + "org/gnome/terminal/legacy/profiles:/:8856406f-96d1-4284-8428-2329d2458b55" = { + scrollback-unlimited = mkBoolean true; + }; + + # GNOME Text Editor + "org/gnome/TextEditor" = { + highlight-current-line = mkBoolean true; + restore-session = mkBoolean false; + show-line-numbers = mkBoolean true; + show-map = mkBoolean true; + tab-width = mkUint32 2; + indent-style = mkString "space"; + style-scheme = mkString "solarized-dark"; + style-variant = mkString "dark"; + + # Not exposed in UI + # https://gitlab.gnome.org/GNOME/gnome-text-editor/-/commit/416a65af17f6b759721ef4606f7b7805fe7af67a + #?? [as] + draw-spaces = mkArray type.string [ + "space" + "tab" + "nbsp" + "trailing" + ]; + }; + + # Virtual Machine Manager + "org/virt-manager/virt-manager" = { + xmleditor-enabled = mkBoolean true; + }; + + "org/virt-manager/virt-manager/confirm" = { + forcepoweroff = mkBoolean false; + }; + + "org/virt-manager/virt-manager/connections" = { + #?? [as] + autoconnect = mkArray type.string [ "qemu:///system" ]; + uris = mkArray type.string [ "qemu:///system" ]; + }; + + "org/virt-manager/virt-manager/console" = { + auto-redirect = mkBoolean false; + resize-guest = mkInt32 1; + scaling = mkInt32 2; + }; + + "org/virt-manager/virt-manager/new-vm" = { + cpu-default = mkString "host-passthrough"; + firmware = mkString "uefi"; + graphics-type = mkString "spice"; + storage-format = mkString "qcow2"; + }; + + "org/virt-manager/virt-manager/stats" = { + enable-cpu-poll = mkBoolean false; + update-interval = mkInt32 5; + }; + + "org/virt-manager/virt-manager/vmlist-fields" = { + cpu-usage = mkBoolean false; + }; + }; + }; +} diff --git a/options/custom/settings/dconf/default.nix b/options/custom/settings/dconf/default.nix new file mode 100644 index 0000000..9836c19 --- /dev/null +++ b/options/custom/settings/dconf/default.nix @@ -0,0 +1,16 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.dconf; +in +{ + options.custom.settings.dconf.default = mkOption { default = false; }; + + config.custom.settings.dconf = mkIf cfg.default { + apps.enable = true; + gnome.enable = true; + gnome-shell.enable = true; + }; +} diff --git a/options/custom/settings/dconf/gnome-shell.nix b/options/custom/settings/dconf/gnome-shell.nix new file mode 100644 index 0000000..4de8432 --- /dev/null +++ b/options/custom/settings/dconf/gnome-shell.nix @@ -0,0 +1,279 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.dconf.gnome-shell; +in +{ + options.custom.settings.dconf.gnome-shell.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + dconf.settings = with config.home-manager.users.${config.custom.username}.lib.gvariant; { + # Extensions + "org/gnome/shell" = { + disable-extension-version-validation = mkBoolean false; + + #!! Concatenated with home-manager extensions + #?? [as] + enabled-extensions = mkArray type.string [ "rounded-window-corners@fxgn" ]; + }; + + # Auto Move Windows + "org/gnome/shell/extensions/auto-move-windows" = { + application-list = mkArray type.string [ + "codium.desktop:1" + "discord.desktop:1" + "firefox-esr.desktop:1" + "obsidian.desktop:1" + "org.telegram.desktop.desktop:1" + "signal-desktop.desktop:1" + "steam.desktop:2" + "youtube-music.desktop:1" + ]; + }; + + # Caffeine + "org/gnome/shell/extensions/caffeine" = { + show-notifications = mkBoolean false; + duration-timer = mkInt32 4; + + #?? [as] + toggle-shortcut = mkArray type.string [ "Delete" ]; + }; + + # Clipboard Indicator + "org/gnome/shell/extensions/clipboard-indicator" = { + clear-on-boot = mkBoolean true; + move-item-first = mkBoolean true; + strip-text = mkBoolean true; + display-mode = mkInt32 3; + preview-size = mkInt32 100; + + #?? [as] + clear-history = mkArray type.string [ ]; + next-entry = mkArray type.string [ ]; + prev-entry = mkArray type.string [ ]; + private-mode-binding = mkArray type.string [ ]; + toggle-menu = mkArray type.string [ "v" ]; + }; + + # Dash to Dock + "org/gnome/shell/extensions/dash-to-dock" = { + animate-show-apps = mkBoolean true; + application-counter-overrides-notifications = mkBoolean true; + apply-custom-theme = mkBoolean false; + autohide-in-fullscreen = mkBoolean false; + custom-theme-shrink = mkBoolean false; + dance-urgent-applications = mkBoolean true; + disable-overview-on-startup = mkBoolean true; + dock-fixed = mkBoolean false; + hide-tooltip = mkBoolean false; + hot-keys = mkBoolean false; + intellihide = mkBoolean true; + isolate-monitors = mkBoolean true; + multi-monitor = mkBoolean true; + require-pressure-to-show = mkBoolean false; + running-indicator-dominant-color = mkBoolean true; + scroll-to-focused-application = mkBoolean true; + show-apps-always-in-the-edge = mkBoolean true; + show-apps-at-top = mkBoolean true; + show-dock-urgent-notify = mkBoolean false; + show-favorites = mkBoolean true; + show-icons-emblems = mkBoolean true; + show-icons-notifications-counter = mkBoolean true; + show-mounts = mkBoolean false; + show-running = mkBoolean true; + show-show-apps-button = mkBoolean true; + show-trash = mkBoolean true; + show-windows-preview = mkBoolean false; + workspace-agnostic-urgent-windows = mkBoolean true; + dash-max-icon-size = mkInt32 36; + animation-time = mkDouble 0.2; + hide-delay = mkDouble 0.2; + show-delay = mkDouble 1.3877787807814457e-17; + click-action = mkString "focus-minimize-or-appspread"; + dock-position = mkString "BOTTOM"; + intellihide-mode = mkString "ALL_WINDOWS"; + middle-click-action = mkString "quit"; + running-indicator-style = mkString "DOTS"; + scroll-action = mkString "switch-workspace"; + transparency-mode = mkString "DEFAULT"; + }; + + # Dash2Dock Lite + "org/gnome/shell/extensions/dash2dock-lite" = { + apps-icon-front = mkBoolean true; + autohide-dash = mkBoolean true; + icon-shadow = mkBoolean false; + open-app-animation = mkBoolean true; + trash-icon = mkBoolean true; + multi-monitor-preference = mkInt32 1; + running-indicator-size = mkInt32 2; + running-indicator-style = mkInt32 1; + border-radius = mkDouble 8.0; + animation-bounce = mkDouble 0.1; + animation-magnify = mkDouble 1.0e-2; + animation-rise = mkDouble 0.0; + animation-spread = mkDouble 0.5; + autohide-speed = mkDouble 0.0; + dock-padding = mkDouble 1.0; + edge-distance = mkDouble 0.5; + icon-size = mkDouble 0.1; + icon-spacing = mkDouble 0.2; + pressure-sense-sensitivity = mkDouble 0.0; + scroll-sensitivity = mkDouble 0.0; + + #?? (dddd) + background-color = mkTuple [ + (mkDouble 0.0) + (mkDouble 0.16862741112709045) + (mkDouble 0.21176470816135406) + (mkDouble 1.0) + ]; + + notification-badge-color = mkTuple [ + (mkDouble 0.8274509906768799) + (mkDouble 0.21176470816135406) + (mkDouble 0.5098039507865906) + (mkDouble 1.0) + ]; + + running-indicator-color = mkTuple [ + (mkDouble 0.8274509906768799) + (mkDouble 0.21176470816135406) + (mkDouble 0.5098039507865906) + (mkDouble 1.0) + ]; + }; + + # ddterm + "com/github/amezin/ddterm" = { + notebook-border = mkBoolean false; + override-window-animation = mkBoolean false; + preserve-working-directory = mkBoolean false; + scrollback-unlimited = mkBoolean true; + tab-show-shortcuts = mkBoolean false; + tab-switcher-popup = mkBoolean false; + transparent-background = mkBoolean false; + window-resizable = mkBoolean false; + use-theme-colors = mkBoolean false; + window-size = mkDouble 0.2; + background-color = mkString "rgb(0,43,54)"; + foreground-color = mkString "rgb(131,148,150)"; + panel-icon-type = mkString "none"; + tab-policy = mkString "automatic"; + tab-position = mkString "top"; + window-position = mkString "bottom"; + + #?? [as] + ddterm-toggle-hotkey = mkArray type.string [ "space" ]; + shortcut-move-tab-next = mkArray type.string [ "" ]; + shortcut-move-tab-prev = mkArray type.string [ "" ]; + shortcut-next-tab = mkArray type.string [ "" ]; + shortcut-prev-tab = mkArray type.string [ "" ]; + shortcut-toggle-maximize = mkArray type.string [ "" ]; + shortcut-win-new-tab = mkArray type.string [ "t" ]; + shortcut-window-size-dec = mkArray type.string [ "" ]; + shortcut-window-size-inc = mkArray type.string [ "" ]; + + palette = mkArray type.string [ + "rgb(7,54,66)" + "rgb(220,50,47)" + "rgb(133,153,0)" + "rgb(181,137,0)" + "rgb(38,139,210)" + "rgb(211,54,130)" + "rgb(42,161,152)" + "rgb(238,232,213)" + "rgb(0,43,54)" + "rgb(203,75,22)" + "rgb(88,110,117)" + "rgb(101,123,131)" + "rgb(131,148,150)" + "rgb(108,113,196)" + "rgb(147,161,161)" + "rgb(253,246,227)" + ]; + }; + + # Hide Top Bar + "org/gnome/shell/extensions/hidetopbar" = { + animation-time-overview = mkDouble 0.2; + pressure-threshold = mkDouble 0.0; + enable-active-window = mkBoolean false; + mouse-sensitive = mkBoolean true; + mouse-sensitive-fullscreen-window = mkBoolean false; + }; + + # Just Perfection + "org/gnome/shell/extensions/just-perfection" = { + background-menu = mkBoolean false; + search = mkBoolean false; + switcher-popup-delay = mkBoolean false; + window-demands-attention-focus = mkBoolean true; + world-clock = mkBoolean false; + startup-status = mkInt32 0; + }; + + # Media Controls + "org/gnome/shell/extensions/mediacontrols" = { + colored-player-icon = mkBoolean true; + hide-media-notification = mkBoolean true; + scroll-labels = mkBoolean true; + show-control-icons = mkBoolean false; + show-label = mkBoolean true; + show-player-icon = mkBoolean true; + label-width = mkUint32 0; + extension-position = mkString "Right"; + mouse-action-left = mkString "PLAY_PAUSE"; + mouse-action-middle = mkString "QUIT_PLAYER"; + }; + + # Rounded Window Corners Reborn + "org/gnome/shell/extensions/rounded-window-corners" = { + skip-libadwaita-app = mkBoolean true; + skip-libhandy-app = mkBoolean true; + }; + + # Tiling Assistant + "org/gnome/shell/extensions/tiling-assistant" = { + adapt-edge-tiling-to-favorite-layout = mkBoolean true; + enable-advanced-experimental-features = mkBoolean true; + enable-raise-tile-group = mkBoolean false; + enable-tiling-popup = mkBoolean false; + maximize-with-gap = mkBoolean true; + active-window-hint = mkInt32 0; + default-move-mode = mkInt32 1; + dynamic-keybinding-behavior = mkInt32 4; + ignore-ta-mod = mkInt32 0; + move-adaptive-tiling-mod = mkInt32 0; + move-favorite-layout-mod = mkInt32 1; + screen-bottom-gap = mkInt32 20; + screen-left-gap = mkInt32 20; + screen-right-gap = mkInt32 20; + screen-top-gap = mkInt32 20; + window-gap = mkInt32 20; + active-window-hint-color = mkString "rgb(211,54,130)"; + + #?? [as] + center-window = mkArray type.string [ ]; + favorite-layouts = mkArray type.string [ "0" ]; + restore-window = mkArray type.string [ "BackSpace" ]; + tile-edit-mode = mkArray type.string [ ]; + tile-maximize = mkArray type.string [ "Return" ]; + tile-maximize-vertically = mkArray type.string [ ]; + tile-maximize-horizontally = mkArray type.string [ ]; + tile-bottom-half = mkArray type.string [ "r" ]; + tile-bottomleft-quarter = mkArray type.string [ ]; + tile-bottomright-quarter = mkArray type.string [ ]; + tile-left-half = mkArray type.string [ "a" ]; + tile-right-half = mkArray type.string [ "s" ]; + tile-top-half = mkArray type.string [ "w" ]; + tile-topleft-quarter = mkArray type.string [ ]; + tile-topright-quarter = mkArray type.string [ ]; + toggle-always-on-top = mkArray type.string [ ]; + }; + }; + }; +} diff --git a/options/custom/settings/dconf/gnome.nix b/options/custom/settings/dconf/gnome.nix new file mode 100644 index 0000000..e75a622 --- /dev/null +++ b/options/custom/settings/dconf/gnome.nix @@ -0,0 +1,324 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.dconf.gnome; +in +{ + options.custom.settings.dconf.gnome.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + dconf.settings = with config.home-manager.users.${config.custom.username}.lib.gvariant; { + "org/gnome/desktop/datetime" = { + automatic-timezone = mkBoolean true; + }; + + "org/gnome/desktop/interface" = { + clock-show-date = mkBoolean true; + clock-show-seconds = mkBoolean false; + clock-show-weekday = mkBoolean true; + enable-hot-corners = mkBoolean false; + gtk-enable-primary-paste = mkBoolean false; + clock-format = mkString "12h"; + }; + + "org/gnome/desktop/notifications" = { + show-in-lock-screen = mkBoolean false; + }; + + "org/gnome/desktop/peripherals/mouse" = { + speed = mkDouble 0.3; + accel-profile = mkString "flat"; + }; + + "org/gnome/desktop/peripherals/trackball" = { + middle-click-emulation = mkBoolean true; + accel-profile = mkString "adaptive"; + }; + + "org/gnome/desktop/privacy" = { + remember-recent-files = mkBoolean true; + remove-old-temp-files = mkBoolean true; + remove-old-trash-files = mkBoolean true; + old-files-age = mkUint32 7; + recent-files-max-age = mkInt32 7; + }; + + "org/gnome/desktop/screensaver" = { + lock-enabled = mkBoolean true; + lock-delay = mkUint32 (60 * 5); # 5 minutes + }; + + "org/gnome/desktop/session" = { + idle-delay = mkUint32 (60 * 15); # 15 minutes + }; + + "org/gnome/desktop/sound" = { + event-sounds = mkBoolean false; + }; + + "org/gnome/desktop/wm/keybindings" = { + #?? [as] + activate-window-menu = mkArray type.string [ ]; + begin-move = mkArray type.string [ ]; + begin-resize = mkArray type.string [ ]; + close = mkArray type.string [ "q" ]; + cycle-group = mkArray type.string [ ]; + cycle-group-backward = mkArray type.string [ ]; + cycle-panels = mkArray type.string [ ]; + cycle-panels-backward = mkArray type.string [ ]; + cycle-windows = mkArray type.string [ ]; + cycle-windows-backward = mkArray type.string [ ]; + maximize = mkArray type.string [ ]; + minimize = mkArray type.string [ ]; + move-to-monitor-down = mkArray type.string [ ]; + move-to-monitor-left = mkArray type.string [ ]; + move-to-monitor-right = mkArray type.string [ ]; + move-to-monitor-up = mkArray type.string [ ]; + move-to-workspace-1 = mkArray type.string [ ]; + move-to-workspace-last = mkArray type.string [ ]; + move-to-workspace-left = mkArray type.string [ "z" ]; + move-to-workspace-right = mkArray type.string [ "x" ]; + panel-run-dialog = mkArray type.string [ ]; + switch-group = mkArray type.string [ ]; + switch-group-backward = mkArray type.string [ ]; + switch-input-source = mkArray type.string [ ]; + switch-input-source-backward = mkArray type.string [ ]; + switch-panels = mkArray type.string [ ]; + switch-panels-backward = mkArray type.string [ ]; + switch-to-workspace-1 = mkArray type.string [ ]; + switch-to-workspace-last = mkArray type.string [ ]; + switch-to-workspace-left = mkArray type.string [ "z" ]; + switch-to-workspace-right = mkArray type.string [ "x" ]; + toggle-maximized = mkArray type.string [ ]; + unmaximize = mkArray type.string [ ]; + }; + + "org/gnome/desktop/wm/preferences" = { + auto-raise = mkBoolean false; + resize-with-right-button = mkBoolean true; + num-workspaces = mkInt32 3; + action-double-click-titlebar = mkString "toggle-maximize"; + action-middle-click-titlebar = mkString "minimize"; + action-right-click-titlebar = mkString "menu"; + button-layout = mkString "appmenu:close"; + focus-mode = mkString "sloppy"; + mouse-button-modifier = mkString ""; + }; + + "org/gnome/gnome-session" = { + logout-prompt = mkBoolean false; + }; + + "org/gnome/mutter" = { + attach-modal-dialogs = mkBoolean true; + center-new-windows = mkBoolean true; + dynamic-workspaces = mkBoolean false; + edge-tiling = mkBoolean false; + workspaces-only-on-primary = mkBoolean true; + + #?? [as] + experimental-features = mkArray type.string [ "variable-refresh-rate" ]; + }; + + "org/gnome/mutter/wayland/keybindings" = { + #?? [as] + restore-shortcuts = mkArray type.string [ ]; + }; + + "org/gnome/settings-daemon/plugins/color" = { + night-light-enabled = mkBoolean true; + night-light-schedule-automatic = mkBoolean true; + night-light-temperature = mkUint32 4000; + }; + + "org/gnome/settings-daemon/plugins/media-keys" = { + #?? [as] + help = mkArray type.string [ ]; + logout = mkArray type.string [ ]; + magnifier = mkArray type.string [ ]; + magnifier-zoom-in = mkArray type.string [ ]; + magnifier-zoom-out = mkArray type.string [ ]; + screenreader = mkArray type.string [ ]; + }; + + "org/gnome/settings-daemon/plugins/power" = { + sleep-inactive-ac-timeout = mkInt32 (60 * 60); # 1 hour + power-button-action = mkString "nothing"; + sleep-inactive-ac-type = mkString "suspend"; + }; + + "org/gnome/shell" = { + favorite-apps = mkArray type.string [ + "org.gnome.Nautilus.desktop" + "firefox-esr.desktop" + "signal-desktop.desktop" + "org.telegram.desktop.desktop" + "discord.desktop" + "youtube-music.desktop" + "steam.desktop" + "codium.desktop" + "obsidian.desktop" + ]; + }; + + "org/gnome/shell/app-switcher" = { + current-workspace-modules = mkBoolean false; + }; + + "org/gnome/shell/keybindings" = { + #?? [as] + focus-active-notification = mkArray type.string [ ]; + screenshot = mkArray type.string [ ]; + screenshot-window = mkArray type.string [ ]; + show-screen-recording-ui = mkArray type.string [ ]; + toggle-application-view = mkArray type.string [ ]; + toggle-quick-settings = mkArray type.string [ ]; + toggle-message-tray = mkArray type.string [ ]; + }; + + "org/gnome/system/location" = { + enabled = mkBoolean true; + }; + + "org/gnome/tweaks" = { + show-extensions-notice = mkBoolean false; + }; + + "org/gtk/settings/file-chooser" = { + clock-format = mkString "12h"; + }; + + # Custom keybinds + #!! custom# must be incremental and updated in custom-keybindings schema + # TODO: Convert to range function + # https://discourse.nixos.org/t/nixos-options-to-configure-gnome-keyboard-shortcuts/7275/7 + "org/gnome/settings-daemon/plugins/media-keys" = { + custom-keybindings = mkArray type.string [ + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom4/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom5/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom6/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom7/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom8/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom9/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom10/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom11/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom12/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom13/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom14/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom15/" + "/org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom16/" + ]; + }; + + # Variety + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom0" = { + name = mkString "Variety Current"; + command = mkString ''bash -c "loupe $(variety --current)"''; + binding = mkString "backslash"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom1" = { + name = mkString "Variety Next"; + command = mkString "variety --next"; + binding = mkString "bracketright"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom2" = { + name = mkString "Variety Previous"; + command = mkString "variety --previous"; + binding = mkString "bracketleft"; + }; + + # LIFX + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom3" = { + name = mkString "LIFX Toggle"; + command = mkString "lifx toggle"; + binding = mkString "space"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom4" = { + name = mkString "LIFX Brightness 1%"; + command = mkString "lifx state --brightness 0.01"; + binding = mkString "1"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom5" = { + name = mkString "LIFX Brightness 25%"; + command = mkString "lifx state --brightness 0.25"; + binding = mkString "2"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom6" = { + name = mkString "LIFX Brightness 50%"; + command = mkString "lifx state --brightness 0.5"; + binding = mkString "3"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom7" = { + name = mkString "LIFX Brightness 75%"; + command = mkString "lifx state --brightness 0.75"; + binding = mkString "4"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom8" = { + name = mkString "LIFX Brightness 100%"; + command = mkString "lifx state --brightness 1"; + binding = mkString "5"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom9" = { + name = mkString "LIFX Color Red"; + command = mkString "lifx state --color red"; + binding = mkString "Escape"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom10" = { + name = mkString "LIFX Temperature 1500K"; + command = mkString "lifx state --kelvin 1500"; + binding = mkString "1"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom11" = { + name = mkString "LIFX Temperature 2500K"; + command = mkString "lifx state --kelvin 2500"; + binding = mkString "2"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom12" = { + name = mkString "LIFX Temperature 3000K"; + command = mkString "lifx state --kelvin 3000"; + binding = mkString "3"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom13" = { + name = mkString "LIFX Temperature 4000K"; + command = mkString "lifx state --kelvin 4000"; + binding = mkString "4"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom14" = { + name = mkString "LIFX Temperature 5000K"; + command = mkString "lifx state --kelvin 5000"; + binding = mkString "5"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom15" = { + name = mkString "Audio Flat"; + command = mkString "audio Flat"; + binding = mkString "minus"; + }; + + "org/gnome/settings-daemon/plugins/media-keys/custom-keybindings/custom16" = { + name = mkString "Audio Normalizer"; + command = mkString "audio Normalizer"; + binding = mkString "equal"; + }; + }; + }; +} diff --git a/options/custom/settings/default.nix b/options/custom/settings/default.nix new file mode 100644 index 0000000..8495aea --- /dev/null +++ b/options/custom/settings/default.nix @@ -0,0 +1,32 @@ +{ config, lib, ... }: + +with lib; + +{ + config.custom.settings = mkMerge [ + (mkIf config.custom.default { + boot.enable = true; + environment.enable = true; + hardware.enable = true; + networking.enable = true; + packages.enable = true; + security.enable = true; + users.enable = true; + }) + + (mkIf config.custom.minimal { + dconf.default = true; + fonts.enable = true; + gtk.enable = true; + qt.enable = true; + xdg.enable = true; + }) + + (mkIf config.custom.full { + accounts.enable = true; + containers.enable = true; + vm.enable = true; + waydroid.enable = true; + }) + ]; +} diff --git a/options/custom/settings/environment.nix b/options/custom/settings/environment.nix new file mode 100644 index 0000000..8eb02e7 --- /dev/null +++ b/options/custom/settings/environment.nix @@ -0,0 +1,69 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.environment; +in +{ + options.custom.settings.environment = { + enable = mkOption { default = false; }; + builder = mkOption { default = config.custom.full; }; + timezone = mkOption { default = "America/Chicago"; }; + wayland = mkOption { default = config.custom.minimal; }; + }; + + config = mkIf cfg.enable { + time.timeZone = cfg.timezone; + + # https://wiki.nixos.org/wiki/Cross_Compiling + boot.binfmt.emulatedSystems = mkIf cfg.builder [ "aarch64-linux" ]; # Emulate architecture + #// nixpkgs.buildPlatform = "x86_64-linux"; # Binary caches often not available + + environment = { + localBinInPath = true; + + # HACK: Nix does not currently handle locale properly, so force default + # https://github.com/NixOS/nixpkgs/issues/183960 et al. + #// i18n.defaultLocale = "C.UTF-8"; + + sessionVariables = { + GDK_SCALE = toString config.custom.scale; # Steam HiDPI + + # https://wiki.nixos.org/wiki/Wayland#Electron_and_Chromium + NIXOS_OZONE_WL = mkIf cfg.wayland "1"; + }; + + shellAliases = { + backup = "sudo borgmatic -v 1 create --progress --stats"; + extract = "sudo borgmatic -v 1 extract --progress"; + restore = "sudo borgmatic -v 1 restore"; + list = "sudo borgmatic -v 1 list"; + init = "sudo borgmatic init -e repokey-blake2"; + key = "sudo borgmatic key export"; + + reboot = "sudo systemctl reboot"; + restart = "sudo systemctl reboot"; + poweroff = "sudo systemctl poweroff"; + shutdown = "sudo systemctl poweroff"; + + rsync = "rsync --info=progress2"; + + # https://github.com/aksiksi/compose2nix?tab=readme-ov-file#usage + # https://github.com/aksiksi/compose2nix?tab=readme-ov-file#agenix + compose2nix = concatStringsSep " " [ + "compose2nix" + "--inputs compose.yaml" + "--output compose.nix" + "--root_path /containers" + "--auto_format" + "--check_systemd_mounts" + "--env_files_only" + "--ignore_missing_env_files" + "--include_env_files" + #?? --env_files /run/agenix/containers/*/.env + ]; + }; + }; + }; +} diff --git a/options/custom/settings/fonts.nix b/options/custom/settings/fonts.nix new file mode 100644 index 0000000..7d98954 --- /dev/null +++ b/options/custom/settings/fonts.nix @@ -0,0 +1,54 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.fonts; +in +{ + options.custom.settings.fonts.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/Fonts + fonts = { + enableDefaultPackages = true; # Fallback fonts + + packages = with pkgs; [ + # Monospace + (nerdfonts.override { fonts = [ "Iosevka" ]; }) + + # Sans Serif + (google-fonts.override { + fonts = [ + # Text + "Jost" + "Lexend" + "Outfit" + + # Condensed + "Oswald" + + # Pixel + "Silkscreen" + ]; + }) + ]; + + #?? fc-list --brief | grep family: | sort + fontconfig.defaultFonts = { + emoji = [ "Noto Color Emoji" ]; + monospace = [ "Iosevka NFP SemiBold" ]; + sansSerif = [ "Outfit" ]; + serif = [ "Liberation Serif" ]; + }; + }; + + home-manager.users.${config.custom.username}.fonts.fontconfig.defaultFonts = + config.fonts.fontconfig.defaultFonts; + }; +} diff --git a/options/custom/settings/gtk/default.nix b/options/custom/settings/gtk/default.nix new file mode 100644 index 0000000..b1382ab --- /dev/null +++ b/options/custom/settings/gtk/default.nix @@ -0,0 +1,49 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.gtk; +in +{ + options.custom.settings.gtk.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + home.pointerCursor = { + gtk.enable = true; # Propagate attributes to gtk.cursorTheme + size = 24; + name = "GoogleDot-Black"; + package = pkgs.google-cursor; + }; + + gtk = { + enable = true; + gtk3.extraCss = builtins.readFile ./style.css; + + gtk4 = { + extraConfig.gtk-hint-font-metrics = 1; # Fix blurry fonts + extraCss = builtins.readFile ./style.css; + }; + + font = { + name = "sans-serif"; + size = 12; + }; + + iconTheme = { + name = "Papirus-Dark"; + package = pkgs.papirus-icon-theme; + }; + + theme = { + name = "adw-gtk3-dark"; + #// package = pkgs.adw-gtk3; + }; + }; + }; +} diff --git a/options/custom/settings/gtk/style.css b/options/custom/settings/gtk/style.css new file mode 100644 index 0000000..86994ea --- /dev/null +++ b/options/custom/settings/gtk/style.css @@ -0,0 +1,37 @@ +/*** Solarized Dark +https://github.com/lassekongo83/adw-colors/blob/main/themes/solarized-dark/gtk.css +https://gnome.pages.gitlab.gnome.org/libadwaita/doc/1.2/named-colors.html +***/ + +@define-color accent_bg_color #1f444d; +@define-color accent_color #586e75; +@define-color accent_fg_color #eee8d5; +@define-color card_bg_color #123a44; +@define-color card_fg_color #fdf6e3; +@define-color destructive_bg_color #d33682; +@define-color destructive_color #d33682; +@define-color destructive_fg_color #eee8d5; +@define-color dialog_bg_color @popover_bg_color; +@define-color dialog_fg_color @popover_fg_color; +@define-color error_bg_color #dc322f; +@define-color error_color #dc322f; +@define-color error_fg_color #eee8d5; +@define-color headerbar_backdrop_color #002b36; +@define-color headerbar_bg_color #07313b; +@define-color headerbar_fg_color #eee8d5; +@define-color popover_bg_color #123a44; +@define-color popover_fg_color #eee8d5; +@define-color sidebar_backdrop_color @window_bg_color; +@define-color sidebar_bg_color @window_bg_color; +@define-color sidebar_border_color @window_bg_color; +@define-color sidebar_fg_color @window_fg_color; +@define-color success_bg_color #859900; +@define-color success_color #859900; +@define-color success_fg_color #eee8d5; +@define-color view_bg_color #073642; +@define-color view_fg_color #eee8d5; +@define-color warning_bg_color #cb4b16; +@define-color warning_color #cb4b16; +@define-color warning_fg_color #eee8d5; +@define-color window_bg_color #002b36; +@define-color window_fg_color #eee8d5; diff --git a/options/custom/settings/hardware.nix b/options/custom/settings/hardware.nix new file mode 100644 index 0000000..1f1a363 --- /dev/null +++ b/options/custom/settings/hardware.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.hardware; +in +{ + options.custom.settings.hardware.enable = mkOption { default = false; }; + + config.hardware = mkIf cfg.enable { + enableAllFirmware = config.custom.default; # Non-free firmware + + # https://wiki.nixos.org/wiki/Bluetooth + bluetooth.enable = config.custom.minimal; + }; +} diff --git a/options/custom/settings/mounts.nix b/options/custom/settings/mounts.nix new file mode 100644 index 0000000..88c766d --- /dev/null +++ b/options/custom/settings/mounts.nix @@ -0,0 +1,85 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.mounts; +in +{ + options.custom.settings.mounts.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Enforce permissions for mountpoint directory + systemd.tmpfiles.rules = [ "d /mnt/remote 0755 root root" ]; + + #!! FUSE does not support remount, sometimes causing activation errors on switch + # https://github.com/libfuse/libfuse/issues/717 + #?? sudo umount /mnt/remote && sudo mount /mnt/remote + # https://wiki.nixos.org/wiki/SSHFS + # https://man.archlinux.org/man/sshfs.1 + fileSystems = + let + #?? "/mnt/PATH" = remote "PATH" UID GID "UMASK" + remote = path: uid: gid: umask: { + # https://robot.hetzner.com/storage + device = "u415778@u415778.your-storagebox.de:/home/${path}"; + fsType = "sshfs"; + + options = [ + "noatime" # Do not modify access time + "reconnect" # Gracefully handle network issues + "default_permissions" # Check local permissions + "allow_other" # Grant other users access + "umask=${umask}" # Set permissions mask + "uid=${toString uid}" # Set user id + "gid=${toString gid}" # Set group id + "idmap=user" # Map local users to remote + "transform_symlinks" # Convert absolute symlinks to relative + "compression=no" # Save CPU cycles at the cost of transfer speed + "port=23" + "IdentityFile=/etc/ssh/id_ed25519" # !! SSH key configured imperatively + "ServerAliveInterval=15" # Prevent application hangs on reconnect + ]; + }; + in + { + # Use umask to set sshfs permissions + #!! Up to 10 simultaneous connections with Hetzner + #?? docker compose exec CONTAINER cat /etc/passwd + "/mnt/remote/conduwuit" = remote "conduwuit" 300 300 "0077"; # conduit:conduit @ 0700 + #// "/mnt/remote/nextcloud" = remote "nextcloud" 33 33 "0007"; # www-data:www-data @ 0700 + "/mnt/remote/syncthing" = remote "syncthing" 237 237 "0077"; # syncthing:syncthing @ 0700 + }; + + # https://wiki.nixos.org/wiki/Rclone + # https://docs.hetzner.com/robot/storage-box/access/access-ssh-rsync-borg/#rclone + #!! SSH keys configured imperatively + #!! rclone attempts to write to immutable config; need to manually merge changes + # https://github.com/rclone/rclone/issues/3655 + # TODO: Attempt to use rclone after daemon is fixed + # https://github.com/rclone/rclone/issues/5664 + # environment.etc."rclone.conf".text = '' + # [remote] + # type = sftp + # host = u415778.your-storagebox.de + # user = u415778 + # port = 23 + # key_file = /etc/ssh/id_ed25519 + # shell_type = unix + # ''; + + # fileSystems."/mnt/remote" = { + # device = "remote:/home"; + # fsType = "rclone"; + + # options = [ + # "nodev" + # "nofail" + # "reconnect" + # "args2env" # Pass secrets as environment variables + # "default_permissions" + # "config=/etc/rclone.conf" + # ]; + # }; + }; +} diff --git a/options/custom/settings/networking.nix b/options/custom/settings/networking.nix new file mode 100644 index 0000000..6dbd253 --- /dev/null +++ b/options/custom/settings/networking.nix @@ -0,0 +1,110 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.networking; +in +{ + options.custom.settings.networking = { + enable = mkOption { default = false; }; + dns = mkOption { default = config.custom.default; }; + ipv4 = mkOption { default = null; }; + ipv6 = mkOption { default = null; }; + networkd = mkOption { default = !cfg.networkmanager; }; + networkmanager = mkOption { default = config.custom.minimal; }; + static = mkOption { default = false; }; # Falls back to DHCP/RA + wifi = mkOption { default = config.custom.minimal; }; + + interface = mkOption { + default = [ + "en*" + "eth*" + ]; + }; + }; + + config = mkIf cfg.enable { + #!! Imperative networking + #?? nmtui or nmcli + # https://wiki.nixos.org/wiki/Networking + networking = { + hostName = config.custom.hostname; + useNetworkd = cfg.networkd; + wireless.iwd.enable = cfg.wifi; + + networkmanager = mkIf cfg.networkmanager { + enable = true; + wifi.backend = mkIf cfg.wifi "iwd"; + }; + }; + + users.users.${config.custom.username}.extraGroups = mkIf cfg.networkmanager [ "networkmanager" ]; + + # Declarative networking + #?? networkctl + # https://wiki.nixos.org/wiki/Systemd/networkd + systemd.network = mkIf (!cfg.networkmanager) { + enable = true; + + networks."10-static" = mkIf cfg.static { + linkConfig.RequiredForOnline = "routable"; + matchConfig.Name = cfg.interface; + + networkConfig = { + DHCP = mkIf (isNull cfg.ipv4) "ipv4"; + IPv6AcceptRA = isNull cfg.ipv6; + }; + + address = + optionals (!isNull cfg.ipv4) [ + cfg.ipv4 + ] + ++ optionals (!isNull cfg.ipv6) [ + cfg.ipv6 + ]; + }; + }; + + # DNS resolver + # https://wiki.nixos.org/wiki/Systemd-resolved + services.resolved = mkIf cfg.dns { + enable = true; + dnsovertls = "opportunistic"; # Fallback only + #// llmnr = "false"; + #// domains = [ "~." ]; # All interfaces + #// extraConfig = "MulticastDNS=false"; # mDNS + + # https://controld.com/free-dns + #?? host verify.controld.com + fallbackDns = mkIf cfg.dns [ + "76.76.2.22#p0.freedns.controld.com" + "76.76.10.22#p0.freedns.controld.com" + "2606:1a40::22#p0.freedns.controld.com" + "2606:1a40:1::22#p0.freedns.controld.com" + ]; + }; + + #!! Override nsswitch.conf resolution order + #!! nss-resolve blocks some modules after [!UNAVAIL=return] + # https://wiki.archlinux.org/title/Systemd-resolved#systemd-resolved_not_searching_the_local_domain + # https://github.com/NixOS/nixpkgs/issues/132646 + # Default: mymachines resolve [!UNAVAIL=return] files myhostname libvirt_guest libvirt dns + # TODO: Remove elements from final list instead of forcing + system.nssDatabases.hosts = mkIf config.custom.full (mkForce [ + "files" + "myhostname" + "mymachines" + "libvirt_guest" + "libvirt" + "resolve" + "dns" + ]); + + # Wireless regulatory domain + # https://github.com/NixOS/nixpkgs/issues/25378 + boot.extraModprobeConfig = mkIf cfg.wifi '' + options cfg80211 ieee80211_regdom="US" + ''; + }; +} diff --git a/options/custom/settings/packages.nix b/options/custom/settings/packages.nix new file mode 100644 index 0000000..b85fe55 --- /dev/null +++ b/options/custom/settings/packages.nix @@ -0,0 +1,183 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.packages; +in +{ + options.custom.settings.packages = { + enable = mkOption { default = false; }; + extra = mkOption { default = [ ]; }; + }; + + config = mkIf cfg.enable ( + with pkgs; + { + environment.systemPackages = + cfg.extra + ++ [ + # CLI applications + config.boot.kernelPackages.cpupower # Install for current kernel + + fd + fzf + jq + lm_sensors # sensors + nixfmt-rfc-style # nixfmt + nix-output-monitor # nom + nix-tree + nmap + nvd + progress + rclone + stress + trashy + waypipe + wl-clipboard # wl-copy/wl-paste + xclip + + # Dependencies + man-pages + man-pages-posix + ] + ++ optionals config.custom.minimal [ + # GUI applications + kdiskmark # Must be system package for polkit + + # CLI applications + # https://github.com/sonic2kk/steamtinkerlaunch + # TODO: Remove when v14 released on nixpkgs + # https://github.com/sonic2kk/steamtinkerlaunch/issues/992 + # Build from latest commit + (steamtinkerlaunch.overrideAttrs { src = inputs.steamtinkerlaunch; }) + + # Dependencies + p7zip # steamtinkerlaunch (Special K) + ] + ++ optionals config.custom.full [ + # GUI applications + amberol + baobab + bitwarden + blackbox-terminal + cinny-desktop + d-spy + dconf-editor + discord + easyeffects + element-desktop + evince + flare-signal + fluffychat + #// fractal + gcolor3 + gitg + github-desktop + gnome-boxes + gnome-calculator + gnome-calendar + gnome-connections + gnome-console + gnome-disk-utility + gnome-resources + gnome-software + gnome-system-monitor + gnome-text-editor + gnome-tweaks + gnome-usage + gradience + gtkcord4 + gtkterm + heroic + icon-library + impression + logseq + loupe + lutris + nheko + obsidian + path-of-building + pika-backup + protonup-qt + protonvpn-gui + pwvucontrol + remmina + snapshot + spotify + syncthingtray + telegram-desktop + variety + ventoy + virt-viewer + wildcard + wowup-cf + #// xivlauncher + youtube-music + + #!! Must be downloaded manually due to licensing + (ciscoPacketTracer8.overrideAttrs { + src = /home/myned/SYNC/linux/config/cisco/CiscoPacketTracer822_amd64_signed.deb; + }) + + # CLI applications + inputs.agenix.packages.${system}.default + + betterdiscordctl + bitwarden-cli + brightnessctl + devbox + er-patcher # Elden Ring fixes + firefoxpwa + glxinfo # glxgears + hwloc # lstopo + freerdp3 + grimblast + imagemagick + libinput + libnotify # notify-send + linux-wifi-hotspot # create_ap + nixos-anywhere + nvtopPackages.full # nvtop + playerctl + satty + tio + usbutils # lsusb + vrrtest + winetricks + xdg-utils # xdg-open + ydotool # TODO: Remove when using service + + # Dependencies + wineWowPackages.unstableFull # WoW64, not World of Warcraft + + # TODO: Use home.gtk.theme.package when fixed upstream + # https://github.com/nix-community/home-manager/issues/5133 + adw-gtk3 + + # Python packages + # https://wiki.nixos.org/wiki/Python#Package_unavailable_in_Nixpkgs + # https://wiki.nixos.org/wiki/Packaging/Python + (python311.withPackages ( + ps: with ps; [ + # lifx-cli + # https://github.com/Rawa/lifx-cli + (buildPythonPackage { + pname = "lifx-cli"; + version = "master"; + src = inputs.lifx-cli; + doCheck = false; + propagatedBuildInputs = with python311Packages; [ requests ]; + }) + ] + )) + ]; + } + ); +} diff --git a/options/custom/settings/qt.nix b/options/custom/settings/qt.nix new file mode 100644 index 0000000..2a292b7 --- /dev/null +++ b/options/custom/settings/qt.nix @@ -0,0 +1,17 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.qt; +in +{ + options.custom.settings.qt.enable = mkOption { default = false; }; + + config.home-manager.users.${config.custom.username} = mkIf cfg.enable { + qt = { + enable = true; + platformTheme.name = "gtk3"; + }; + }; +} diff --git a/options/custom/settings/security.nix b/options/custom/settings/security.nix new file mode 100644 index 0000000..986ecb1 --- /dev/null +++ b/options/custom/settings/security.nix @@ -0,0 +1,29 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.security; +in +{ + options.custom.settings.security.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # Bypass password prompts + security = { + sudo.wheelNeedsPassword = false; + + # https://wiki.nixos.org/wiki/Sway#Using_Home_Manager + polkit = { + enable = true; + + # https://wiki.archlinux.org/title/Polkit#Bypass_password_prompt + extraConfig = '' + polkit.addRule(function(action, subject) { + if (subject.isInGroup("wheel")) { return polkit.Result.YES; } + }); + ''; + }; + }; + }; +} diff --git a/options/custom/settings/users.nix b/options/custom/settings/users.nix new file mode 100644 index 0000000..cde3423 --- /dev/null +++ b/options/custom/settings/users.nix @@ -0,0 +1,67 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.users; +in +{ + options.custom.settings.users = { + enable = mkOption { default = false; }; + shell = mkOption { default = pkgs.fish; }; + + ${config.custom.username} = { + groups = mkOption { + default = + if config.custom.full then + [ + "input" + "video" + ] + else + [ ]; + }; + linger = mkOption { default = false; }; + packages = mkOption { default = [ ]; }; + }; + }; + + config = mkIf cfg.enable { + age.secrets = + let + secret = filename: { + file = "${inputs.self}/secrets/${filename}"; + }; + in + { + "${config.custom.profile}/users/${config.custom.username}.pass" = secret "${config.custom.profile}/users/${config.custom.username}.pass"; + "${config.custom.profile}/users/root.pass" = secret "${config.custom.profile}/users/root.pass"; + }; + + users = { + defaultUserShell = cfg.shell; + mutableUsers = false; # !! Immutable users + + users = { + #!! secrets/PROFILE/users/USERNAME.pass hashedPasswordFile is required + + root.hashedPasswordFile = config.age.secrets."${config.custom.profile}/users/root.pass".path; + + ${config.custom.username} = { + isNormalUser = true; + extraGroups = [ "wheel" ] ++ cfg.${config.custom.username}.groups; + hashedPasswordFile = + config.age.secrets."${config.custom.profile}/users/${config.custom.username}.pass".path; + linger = cfg.${config.custom.username}.linger; + packages = cfg.${config.custom.username}.packages; + }; + }; + }; + }; +} diff --git a/options/custom/settings/vm.nix b/options/custom/settings/vm.nix new file mode 100644 index 0000000..3b149f9 --- /dev/null +++ b/options/custom/settings/vm.nix @@ -0,0 +1,102 @@ +{ + config, + inputs, + lib, + pkgs, + ... +}: + +with lib; + +let + cfg = config.custom.settings.vm; +in +{ + options.custom.settings.vm = { + enable = mkOption { default = false; }; + libvirt = mkOption { default = true; }; + virtualbox = mkOption { default = false; }; + }; + + config = mkIf cfg.enable { + # https://github.com/virt-manager/virt-manager + programs.virt-manager.enable = cfg.libvirt; + + users.users.${config.custom.username}.extraGroups = + lib.optionals cfg.libvirt [ "libvirtd" ] + ++ lib.optionals cfg.virtualbox [ "vboxusers" ]; + + virtualisation = { + # https://wiki.nixos.org/wiki/Libvirt + # https://libvirt.org + libvirtd = mkIf cfg.libvirt { + enable = true; + onBoot = "ignore"; + onShutdown = "shutdown"; + + qemu = { + swtpm.enable = true; # TPM emulation + + # Build OVMF with Windows 11 support + ovmf.packages = [ + (pkgs.OVMF.override { + secureBoot = true; + tpmSupport = true; + }).fd + ]; + }; + + # Guest hostname resolution + # https://libvirt.org/nss.html + #!! Requires DHCP, preferably without lease expiry + # https://libvirt.org/formatnetwork.html#addressing + #?? sudo virsh net-dhcp-leases NETWORK + #?? + #?? + #?? + nss = { + enable = true; + enableGuest = true; + }; + + # Attempt to synchronize time with host on resume + # https://libvirt.org/manpages/libvirt-guests.html + #!! Windows Time service must be started on Windows guest + #?? sudo virsh domtime DOMAIN --sync + extraConfig = '' + SYNC_TIME=1 + ''; + }; + + # https://wiki.nixos.org/wiki/VirtualBox + # https://www.virtualbox.org + virtualbox.host = mkIf cfg.virtualbox { + enable = true; + enableExtensionPack = true; + }; + }; + + systemd = mkIf cfg.libvirt { + # Fix resume messages polluting tty + services.libvirt-guests.serviceConfig.StandardOutput = "journal"; + + tmpfiles.rules = + let + firmware = pkgs.runCommandLocal "qemu-firmware" { } '' + mkdir $out + cp ${pkgs.qemu}/share/qemu/firmware/*.json $out + substituteInPlace $out/*.json --replace ${pkgs.qemu} /run/current-system/sw + ''; + in + [ + # HACK: Fix libvirt not automatically locating firmware + # https://github.com/NixOS/nixpkgs/issues/115996#issuecomment-2224296279 + # https://libvirt.org/formatdomain.html#bios-bootloader + "L+ /var/lib/qemu/firmware - - - - ${firmware}" + + # HACK: Manually link image to default directory + "L+ /var/lib/libvirt/images/virtio-win.iso - - - - ${inputs.virtio-win}" + ]; + }; + }; +} diff --git a/options/custom/settings/waydroid.nix b/options/custom/settings/waydroid.nix new file mode 100644 index 0000000..1dacbdd --- /dev/null +++ b/options/custom/settings/waydroid.nix @@ -0,0 +1,66 @@ +{ config, lib, ... }: + +with lib; + +let + cfg = config.custom.settings.waydroid; +in +{ + options.custom.settings.waydroid.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.nixos.org/wiki/WayDroid + # https://wiki.archlinux.org/title/Waydroid + #!! Configuration is imperative + #* Optionally update image + #?? sudo waydroid upgrade + + # Install image + #?? sudo waydroid init + + # Helper script + # https://github.com/casualsnek/waydroid_script + #?? git clone https://github.com/casualsnek/waydroid_script.git + #?? cd waydroid_script + #?? python -m venv .venv + #?? source .venv/bin/activate.fish + #?? pip install -r requirements.txt + #?? sudo python main.py install microg + #?? sudo python main.py install libndk + #?? sudo python main.py hack hidestatusbar + + # Start session + #?? waydroid session start & + + # Enable windowed applications + #?? waydroid prop set persist.waydroid.multi_windows true + + # Set window size + #?? waydroid prop set persist.waydroid.width WIDTH + #?? waydroid prop set persist.waydroid.height HEIGHT + #?? sudo waydroid shell + #?? wm size reset + + # Waydroid must run on the same GPU as the compositor + # https://wiki.archlinux.org/title/Waydroid#Graphical_Corruption_on_multi-gpu_systems + # https://github.com/Quackdoc/waydroid-scripts/blob/main/waydroid-choose-gpu.sh + #!! Rerun after each waydroid_script invocation + #?? sudo sed -i 's|/dev/dri/card0|/dev/dri/card1|' /var/lib/waydroid/lxc/waydroid/config_nodes + #?? sudo sed -i 's|/dev/dri/renderD128|/dev/dri/renderD129|' /var/lib/waydroid/lxc/waydroid/config_nodes + + # Some games like Arknights do not use the proper storage mechanism and need insecure permissions + # https://github.com/casualsnek/waydroid_script?tab=readme-ov-file#granting-full-permission-for-apps-data-hack + #?? sudo waydroid shell + #?? chmod 777 -R /sdcard/Android + #?? chmod 777 -R /data/media/0/Android + #?? chmod 777 -R /sdcard/Android/data + #?? chmod 777 -R /data/media/0/Android/obb + #?? chmod 777 -R /mnt/*/*/*/*/Android/data + #?? chmod 777 -R /mnt/*/*/*/*/Android/obb + + # Disable unnecessary desktop files + #?? sed -i 's|(\[Desktop Entry\])|$1\nNoDisplay=true|' ~/.local/share/applications/waydroid.*.desktop + + virtualisation.waydroid.enable = true; + }; +} diff --git a/options/custom/settings/xdg.nix b/options/custom/settings/xdg.nix new file mode 100644 index 0000000..9973f36 --- /dev/null +++ b/options/custom/settings/xdg.nix @@ -0,0 +1,76 @@ +{ + config, + lib, + pkgs, + ... +}: + +with lib; + +let + evince = "org.gnome.Evince.desktop"; + firefox-esr = + config.home-manager.users.${config.custom.username}.programs.firefox.package.desktopItem.name; + gnome-text-editor = "org.gnome.TextEditor.desktop"; + loupe = "org.gnome.Loupe.desktop"; + nautilus = "org.gnome.Nautilus.desktop"; + + cfg = config.custom.settings.xdg; +in +{ + options.custom.settings.xdg.enable = mkOption { default = false; }; + + config = mkIf cfg.enable { + # https://wiki.archlinux.org/title/XDG_Desktop_Portal + xdg.portal = { + enable = true; + extraPortals = [ pkgs.xdg-desktop-portal-gtk ]; + config.common.default = [ + "hyprland" + "gtk" + ]; # Prefer hyprland over gtk portal + + # Use portal for xdg-open + # https://github.com/NixOS/nixpkgs/issues/160923 + xdgOpenUsePortal = true; + }; + + home-manager.users.${config.custom.username}.xdg = { + configFile."mimeapps.list".force = true; + + mimeApps = { + enable = true; + + # https://www.iana.org/assignments/media-types/media-types.xhtml + #?? xdg-mime query + defaultApplications = { + "application/json" = gnome-text-editor; + "application/pdf" = evince; + "application/xhtml+xml" = gnome-text-editor; + "application/xhtml_xml" = gnome-text-editor; + "application/xml" = gnome-text-editor; + "image/jpeg" = loupe; + "image/png" = loupe; + "inode/directory" = nautilus; + "text/html" = gnome-text-editor; + "text/plain" = gnome-text-editor; + "x-scheme-handler/http" = firefox-esr; + "x-scheme-handler/https" = firefox-esr; + }; + }; + + userDirs = { + enable = true; + createDirectories = true; + desktop = null; + templates = "/home/${config.custom.username}/SYNC/linux/config/templates"; + + extraConfig = { + XDG_SCREENSHOTS_DIR = "${ + config.home-manager.users.${config.custom.username}.xdg.userDirs.pictures + }/Screenshots"; + }; + }; + }; + }; +} diff --git a/options/default.nix b/options/default.nix new file mode 100644 index 0000000..d9f2081 --- /dev/null +++ b/options/default.nix @@ -0,0 +1,8 @@ +{ lib, ... }: + +with lib; + +{ + # Import all *.nix options from custom directory + imports = filter (f: strings.hasSuffix ".nix" f) (filesystem.listFilesRecursive ./custom); +} diff --git a/profiles/console/default.nix b/profiles/console/default.nix new file mode 100644 index 0000000..b97656c --- /dev/null +++ b/profiles/console/default.nix @@ -0,0 +1,82 @@ +{ + config, + inputs, + lib, + options, + pkgs, + ... +}: + +{ + imports = [ inputs.jovian-nixos.nixosModules.default ]; + + custom = { + minimal = true; + profile = "console"; + + desktops.gnome = { + enable = true; + gdm = false; + }; + + programs = { + gnome-shell.enable = true; + + steam = { + enable = true; + extest = true; + }; + }; + + services.syncthing = { + enable = true; + folders = lib.getAttrs [ + "SYNC/.ignore" + "SYNC/game" + ] options.custom.syncthing.folders.default; + }; + + settings = { + boot = { + console-mode = 5; # Proper orientation + kernel = pkgs.linuxPackages_jovian; + }; + + packages.extra = with pkgs; [ + # GUI applications + bitwarden + gnome-tweaks + heroic + lutris + xivlauncher + + # CLI applications + er-patcher # Elden Ring fixes + winetricks + + # Dependencies + wineWowPackages.stable + ]; + }; + }; + + # https://github.com/Jovian-Experiments/Jovian-NixOS + # https://jovian-experiments.github.io/Jovian-NixOS/options.html + jovian = { + steam = { + enable = true; + autoStart = true; + desktopSession = "gnome"; + user = config.custom.username; + environment = config.programs.steam.package.steamargs.extraEnv; # Inherit desktop environment + }; + + devices.steamdeck = { + enable = true; + enableGyroDsuService = true; + autoUpdate = true; + }; + + decky-loader.enable = true; + }; +} diff --git a/profiles/desktop/default.nix b/profiles/desktop/default.nix new file mode 100644 index 0000000..5633b88 --- /dev/null +++ b/profiles/desktop/default.nix @@ -0,0 +1,8 @@ +{ + custom = { + full = true; + profile = "desktop"; + wallpaper = true; + services.power-profiles-daemon.enable = true; + }; +} diff --git a/profiles/laptop/default.nix b/profiles/laptop/default.nix new file mode 100644 index 0000000..f98627f --- /dev/null +++ b/profiles/laptop/default.nix @@ -0,0 +1,7 @@ +{ + custom = { + full = true; + profile = "desktop"; # Inherit desktop + services.auto-cpufreq.enable = true; + }; +} diff --git a/profiles/sbc/default.nix b/profiles/sbc/default.nix new file mode 100644 index 0000000..40c1b9f --- /dev/null +++ b/profiles/sbc/default.nix @@ -0,0 +1,38 @@ +{ + custom = { + profile = "sbc"; + programs.fastfetch.greet = true; + + services = { + tailscale.cert = true; + + borgmatic = { + enable = true; + sources = [ "/containers" ]; + + repositories = [ + { + path = "ssh://h1m9k594@h1m9k594.repo.borgbase.com/./repo"; + label = "mypi3"; + } + ]; + }; + + # netdata = { + # enable = true; + # child = true; + # }; + }; + + settings = { + boot.u-boot = true; + networking.wifi = true; + + containers = { + enable = true; + boot = true; + homeassistant.enable = true; + }; + }; + }; +} diff --git a/profiles/server/default.nix b/profiles/server/default.nix new file mode 100644 index 0000000..98a8539 --- /dev/null +++ b/profiles/server/default.nix @@ -0,0 +1,65 @@ +{ + custom = { + profile = "server"; + programs.fastfetch.greet = true; + + services = { + caddy.enable = true; + matrix-conduit.enable = true; + #// modufur.enable = true; + tailscale.cert = true; + + borgmatic = { + enable = true; + sources = [ + "/containers" + "/home" + "/mnt/remote" + "/srv" + ]; + + repositories = [ + { + path = "ssh://n882bnik@n882bnik.repo.borgbase.com/./repo"; + label = "myarm"; + } + ]; + }; + + # netdata = { + # enable = true; + # parent = true; + # }; + + syncthing = { + enable = true; + configDir = "/var/lib/syncthing"; + dataDir = "/mnt/remote/syncthing"; + ignorePerms = true; # Mount permissions are forced + mount = "mnt-remote-syncthing.mount"; + type = "receiveonly"; + user = "syncthing"; + group = "syncthing"; + }; + }; + + settings = { + boot.systemd-boot = true; + mounts.enable = true; + users.myned.linger = true; + + containers = { + enable = true; + boot = true; + actualbudget.enable = true; + coturn.enable = true; + forgejo.enable = true; + foundryvtt.enable = true; + mastodon.enable = true; + nextcloud.enable = true; + redlib.enable = true; + searxng.enable = true; + }; + }; + }; +} diff --git a/secrets/common/netdata/child.conf b/secrets/common/netdata/child.conf new file mode 100644 index 0000000..fe84f08 Binary files /dev/null and b/secrets/common/netdata/child.conf differ diff --git a/secrets/common/netdata/parent.conf b/secrets/common/netdata/parent.conf new file mode 100644 index 0000000..394db5f --- /dev/null +++ b/secrets/common/netdata/parent.conf @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q alvDFT49CWk/danem23tYRmbnN7t6SCB4d+fnLB6FlA +3GFz8Y4RVmLyizebYGJki+BURhXp93N0TPDZZKoNflE +-> ssh-ed25519 sfxzoQ w53sUKwwwY6C+IQYt+7sqRlInfQnIPdlNgVKHNc4J0Q +HKaAIGKrfFFW7VTOJTHjjksDr/YrPvNvz3a8yhMNZlA +-> ssh-ed25519 fEyKPw GaLlogx1QqNoDlPMwxFuuhXK0H1ds9vzcTusMJZTFgo +FvpoPiIiTEjSV8gaTFHDWPt2jxcXoBJ7dpiT5v/glR8 +--- M3C3ZLyb9N2g2QsmS6TiRN3K1HykG/WnXHDh5OKz2Io +< xܧXpa@ٹe'K?0oQ,6E0.V(d&٬SN:P \ No newline at end of file diff --git a/secrets/common/nix/access-tokens.conf b/secrets/common/nix/access-tokens.conf new file mode 100644 index 0000000..4dddf35 --- /dev/null +++ b/secrets/common/nix/access-tokens.conf @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q H3a8HOUPVjUnV/SYiFMYGG2B8hHAaout1CIvetDX8lw +Mhwhq904g/NRHWfKGHhoSdNyd6cGuPUF32WXfW5okGU +-> ssh-ed25519 sfxzoQ chiWfsT/QBe6EObgxmi5+1rT3J/lwb1M6RoWU5tYhw8 +c5fnKSukEouTweInUn88A1r/IZPq6cwmJP6Rh0q21m0 +-> ssh-ed25519 g5GcDQ p1R40R4GR22bH1Au2Mfpgm4cTzyQGbdUjyez1OIokyc +Fwg30iqHQHjUJKUypvT/XQCvxhQcuLuipxipQ2GreE0 +-> ssh-ed25519 T/dATA +MrQwD7TcIknaIPe//UEye1o8oq+qzafDlcrFHhE2D8 +5AY1tgPtXpZtbPIJVLDLoDNZF3a+GWNI/jOqmfzjRMg +-> ssh-ed25519 kMNckw 40orelJLLtoefyeQI6h2+fw3w5SzN+1OJq23hPtDtm4 +CbrcNUfKO3wE47HnMYoYpU3+07EJp1CNHsT1xfgGCio +-> ssh-ed25519 fEyKPw EAhLUDz0Pta0IS+kdCEpQDOQe3QqjZHVe8OgNY6m5Gc +ConoI/TvpljjGfqyMVUXAPRdqopKMrYVvCBZ/vBj7IQ +--- pMBz03BnzAMiIn/lb6ykDi2cA1/itzNlZ1djIA2WIkw +`j;A֥b:?GJVo56FG 7К'ҲׯIrs:ʤ~I|PzòO6$6r"Xr歹BvZV慹\|¥Q=Ĵ*Rj,1h_?] \ No newline at end of file diff --git a/secrets/common/tailscale/tailnet b/secrets/common/tailscale/tailnet new file mode 100644 index 0000000..8a0edf0 --- /dev/null +++ b/secrets/common/tailscale/tailnet @@ -0,0 +1,15 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q /4sDlnaVNaYnc3LV5TIgo5u2/F9KbEfngbe7iJ+jGUo +ssJV/ZNwZ1UbJ9fGGVVleLcIT+on9AzXHQpeg5wC+5Y +-> ssh-ed25519 sfxzoQ YoDLrRkC7pb+Jb96IHrpQ3XR5Sy0oaZCGS0W2S4jyDE +wcQxPTBdLskPrvm09bufZ5FliHxPkRY2pyDOuumbPLI +-> ssh-ed25519 g5GcDQ cuUvdB6BkCdkXcnHX0lQknjZdf+qp0wyAUZXBTjfGFo +ic1sXQzh8o1uTCTQcwBQmRhNv31WVNRWXKnkulXTzYA +-> ssh-ed25519 T/dATA FJgWILxeNeZuJiusMX4fxb85xMomBoUNoIf221F2Cwc +aYlNag9hGSII2BNiouvP/OAjsRKi8adK/9TzFJp+g6A +-> ssh-ed25519 kMNckw xLqGh1JelGrMU/LXSKmmjCBF7LqdDJulCov5XkWsRXw +oJbHkuQbk1zLgxPv46K9CQ5Q6xC+LLQ3KeMxPMo8kpA +-> ssh-ed25519 fEyKPw FC1Bu3C67IAfhbETW3RHoX7+SPhdlITrXvSrPf68nC0 +AX6iSjbBQBhKbPencWZ6hXGO1bp1ht3tHgRqNyKwnIo +--- 0TrUyAsgQv4n/YMNJobJrrAniwzSpricWpiRJu8uals +f%m(Kszvd&+I]@図Sc1N-)L \ No newline at end of file diff --git a/secrets/console/users/myned.pass b/secrets/console/users/myned.pass new file mode 100644 index 0000000..8eac1ad Binary files /dev/null and b/secrets/console/users/myned.pass differ diff --git a/secrets/console/users/root.pass b/secrets/console/users/root.pass new file mode 100644 index 0000000..df9f887 --- /dev/null +++ b/secrets/console/users/root.pass @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q Z76+n4Urt2r9dgVEW/+tOr63Q5cuUxxPB5BfGNUNZzw +LsmsgNGg4nAP7Ec1z8x3tWA+bX7hY6t+/2KakpS+0Js +-> ssh-ed25519 sfxzoQ WYWpwiEvGX2qL9obml/n7y0oRK7KOFyYChDRgLKdFTI +QEhy8cdhunnfocaejYvOkEQxmdns5DtwT0aQDcZW4fs +-> ssh-ed25519 BIBw2w 8ermevGUS80hi9cSCYs4cNFkt2YBMR7t6PQYtq+FlU4 +kUls3mwPFYreGbqUf3x0fgSGcdKCKEHTXEJaXEM962s +--- 4g4q2sYMSS3v/le/SpZw2sAfC2xf8NiRyBMlDdA5i4o +6ܢ)D2Ҿ(J8Ϥ"4Q:: t IRbŽ/8'Lˊ0cSG^EϷ6 'Dp3qQH^" Jsl \ No newline at end of file diff --git a/secrets/desktop/bitwarden/client_id b/secrets/desktop/bitwarden/client_id new file mode 100644 index 0000000..a347226 --- /dev/null +++ b/secrets/desktop/bitwarden/client_id @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q pYzdxtMJo4CLF/xV8fXcniJuRbF7TW3sPnCuaZuB1EA +/mYH4ADP8X0SXR/nRoeXdHj9AhiL2v9Bsie5ftJqchY +-> ssh-ed25519 sfxzoQ WbMMKBLZMJJvXtUpkxh1R/ek+S456xB7mpJJiRkpgTE +i+87Wz3A+ffLd8NotB76zVx6fOnFGV/uFXYjBKYM1Hk +-> ssh-ed25519 g5GcDQ ojjZQzp7uDlkCAbd2vi/yoSIJbQ4eYuQRhJ8Gs3bXWc +Qj4XlxVFzIN09/yY1xpTJ6AzX6KbXgTQ80sg9C0WJpA +-> ssh-ed25519 T/dATA rweLuSiybslpM4ReYGX9rCxvS5HZuytgP/YZV0USeEo +OyUQ4oS+BY5+hvCNLXqkW+3BcepFwywvfiuvv4+ayy4 +--- sHcdt9tjK8lD93EHGZjamODeCTsyw/wR2LnkKO848NM +trِO64E/2q^#ȼr^|<|hEzi]z']RECᅡl \ No newline at end of file diff --git a/secrets/desktop/bitwarden/client_secret b/secrets/desktop/bitwarden/client_secret new file mode 100644 index 0000000..7b34706 Binary files /dev/null and b/secrets/desktop/bitwarden/client_secret differ diff --git a/secrets/desktop/geoclue2/geolocation b/secrets/desktop/geoclue2/geolocation new file mode 100644 index 0000000..0e8c1db Binary files /dev/null and b/secrets/desktop/geoclue2/geolocation differ diff --git a/secrets/desktop/users/myned.pass b/secrets/desktop/users/myned.pass new file mode 100644 index 0000000..534199b --- /dev/null +++ b/secrets/desktop/users/myned.pass @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q 2KMED/T9uh1747hJMKbMPEhGutXIzfHukyVr7ZUIKVg +d6U1EYfQ1o5yUMvrbugP2OF4P+ooJmGOijy8lELerpU +-> ssh-ed25519 sfxzoQ W2f5dueZcBnps8yrIU+ar/dw/sfdu83gKQ2tXC2X3l0 +eP/qi4pH+ku9PZmYPhmtW+KB/XERrmhmuKp23loL6Ec +-> ssh-ed25519 g5GcDQ vz6arJiGKz2aySfqh9qnlf/be9KyqX94N+8xmTW8Vmg +MrbK9cBVCpLMw6FTURhPbAkLXE6mlOmWy7otAhqXzMs +-> ssh-ed25519 T/dATA bFf2rA8kdqlk7LZlzkcpHtnge7p1bFo/ncjnMuMVyQA +/J+Ww+Lku1PPd39Fiwv/L4FvQYb9C8LhWbnKGzKzvHc +--- Pa+Ygdw45hzONjwPFuKR3k1+wgAYcul0rHZSf/RQzTE +iu]ЬB*Tנ([C.0<:Pq3. bPi+m#6@G?ܧ\}ri s"";^% 08\rB9 \ No newline at end of file diff --git a/secrets/desktop/users/root.pass b/secrets/desktop/users/root.pass new file mode 100644 index 0000000..eb2a4e5 --- /dev/null +++ b/secrets/desktop/users/root.pass @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q GxWfsq2HMi5oIKRBIu8NPYytqbcL+FjxKXP0UO438Hs +4vfio6miHDp85UTkxZUvLhDvmolE+1M1+9COcK8AAMc +-> ssh-ed25519 sfxzoQ XByuEiFm6qRWud4CnfWQ7GGKAWtSQsbQIDrSAs9azho +m5+9PjUDj20qYLzuS3HkZ7q599/ZmA2vs+S8gQJ+T6o +-> ssh-ed25519 g5GcDQ jDFLRDoGDV1eWpFAKH2kdagMUQ9W54Xwn68CiZYUIis +BqMKncw2nuSuFNoW3EBpd+jF5cx3TSx0dPqDrOx6Rlg +-> ssh-ed25519 T/dATA qaToANDpsieGYblpsNIi0JliXgv2LPYxN6475C0qXUo +Vx25u9YmKsc8HeLISEIRoXibXkfGngFviEYE/BSV5QM +--- fBtBeJV++bgitcIgjSnWNXUv+Vx7oWAcPujh3I7NzrA +3&~50 ()c_/3d)nk- Mi K:@xJD[C\i`彟!Nhi;O ~C? \ No newline at end of file diff --git a/secrets/sbc/borgmatic/borgbase.mypi3 b/secrets/sbc/borgmatic/borgbase.mypi3 new file mode 100644 index 0000000..8e952c1 --- /dev/null +++ b/secrets/sbc/borgmatic/borgbase.mypi3 @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q 2AKWNb5ceKyvqK70mjV/hzn9pKhESZzwaCX2tWL4bhk +cIzLn/AwY92sYM5ChW+QK6lgdjcVhXkxvjvIjTU9f+E +-> ssh-ed25519 sfxzoQ rMC1RSGjilhefYehMdwUpkVQ0I1iDaykuQMvwCYy6TE +6hsmsh26nRmKsPu62A0ATcYClFbnEz+LA8D+zHsX2c8 +-> ssh-ed25519 kMNckw ZWH5tahiKMt99VwNR2ZozcR5ZTZREIJ6YBikdcFInkE +mOa+AfE1ygEyD7pleC9aysVw7Wvb8IcxFgOPEFdvJIo +--- 7ONqzuJi6NCoFCSdUcqqtWqpDFbWryRWJgyWSd8v5zE +l6!{TNK4̆ɂ[.C2chBhy,_a 9O \ No newline at end of file diff --git a/secrets/sbc/create_ap/passphrase b/secrets/sbc/create_ap/passphrase new file mode 100644 index 0000000..23f261f --- /dev/null +++ b/secrets/sbc/create_ap/passphrase @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q FUgF+GfjBtSpWnC4n/rvTW6hxOzWVe7iUT5zDatwAGA +U1SWT30hU+16420YRpGWGMBVq2f56WpXhIJWsXBtN+g +-> ssh-ed25519 sfxzoQ hnEKgSSSKC2EGKpF+5WxgBQyJsahw/VuSBR5skvojFU +H0bCt8sW3EjlquZIbBOqguln0jxnEgOoMp5RU4teRC0 +-> ssh-ed25519 kMNckw njfI/03C06eIWKGxhweNMu/P4aoqPu7VFcn6Ag1ZQCc +oFdZM4mh/ARwP85MfX9FPFsjnPTsFGU8CEE8j5BR7fY +--- cgcfMDS5lC8SvxD2usG2fc/O6m1d8vHGszdg3hxwFE4 +DDb#<I|9;OLЧ"h \ No newline at end of file diff --git a/secrets/sbc/create_ap/ssid b/secrets/sbc/create_ap/ssid new file mode 100644 index 0000000..fe92251 --- /dev/null +++ b/secrets/sbc/create_ap/ssid @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q R1kE7yUfljQyJH2J7T9/OXGYYWlR2GTB/ARV9IE4Xhs +s3kWciXh7Jwa6WWQR44u1AkAEPcgJ7nLL+VKg5tCb6s +-> ssh-ed25519 sfxzoQ N1tDW8B826EGcH5mx6PloKmqjtjdakNQJaREteMdqiI +J65VjfEDRGkLF5Sf3+mI9Cdpt1k/8eBjs7RFPOu8m+Y +-> ssh-ed25519 kMNckw AHcgZYq1Hoj7Z6Z7dAlqNw/Pa/pSn/UJD+i4+r/rq20 +16tfjdP61kx6IIUEqxCCA3QC1OXELhjFi8VIzXzESLg +--- JXZ+dKyJPjQvh2T6bIJvLCWLEREB9hMxzs6G0N+FTJs +ի'MKm Rd'XFtNPt)7ISgc \ No newline at end of file diff --git a/secrets/sbc/users/myned.pass b/secrets/sbc/users/myned.pass new file mode 100644 index 0000000..cfe3511 --- /dev/null +++ b/secrets/sbc/users/myned.pass @@ -0,0 +1,11 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q VaDrk4HrXv5i0OPhy1v3Z1ZyIkknQURdrdUYP0Wtyhw +8oljnQXAVa0PLV97GpP4RGZkmirfea/sY6IU1lqPrY4 +-> ssh-ed25519 sfxzoQ o4FqYuF/zFv8AY5aN7WaUdr9EQ66O+9qjHXKL19tODo +VJ03FUduU95fGU3qTn2Y+ItirnvT2DxbZi/OciZQQag +-> ssh-ed25519 kMNckw PkP0RXKavqwBow7bU1A/XO5+qi+lhpmrkb0I2RG65Gw +R98c6uRFc5ohtvjqanVYyNwWg0qpELBAXu6yDwOo++I +--- ABkSZt0vEoCsRhOz8EcgUBdHwmkSuMvbq/IP4joPa3E +͍vUaΣP~vo`^ +}:#Bq[wzk!n9/G"!@Eag=mb +2F~F ssh-ed25519 8E6j8Q qILYrLuRPQ1RDkIOhmbAF5dIDT6NIj1kKNRUWBgHAzQ +5ceasJ4ACX6cySoj8SR4NGLdJTd5retCDLWFhDMYmZo +-> ssh-ed25519 sfxzoQ UFU3nfgg0xvp5u+swk/amlD7ZrAlQGYv/odjAziBnnU +Gei1OIAZvevpuOHfpgbL4fiwOZdHt9XqrJ5jbfeY79k +-> ssh-ed25519 fEyKPw LcNnPjU4WNBH2zq8sj/l93vkriGEnuwHQ5vedB//mhM +lgLDnE5aP4aH9ie6XuwTInJ6U+9rg1P15KfnT/NfzQ8 +--- bV80JjRWmfeHOBAJg1i3x9duyJNLwyxtFHzd6yiUGIY + %0m d- ="7:,N.bmDR.dT,ј \ No newline at end of file diff --git a/secrets/server/caddy/Caddyfile b/secrets/server/caddy/Caddyfile new file mode 100644 index 0000000..5692b8d Binary files /dev/null and b/secrets/server/caddy/Caddyfile differ diff --git a/secrets/server/coturn/coturn.conf b/secrets/server/coturn/coturn.conf new file mode 100644 index 0000000..cdf2635 --- /dev/null +++ b/secrets/server/coturn/coturn.conf @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q 2ekeG1mwVd+ofzoPhE82yyzOa9GxBa7IyxlyD/NbvRM +BiShp1BAq+8U544Pb4BRiKa3yyRtnJm82I4HrVrx3WI +-> ssh-ed25519 sfxzoQ dXcp4pybRg7SZUqubpgHQcrw7g4Q9nhZCc6aVR+xP20 +FZ0jNVqhtelAOwBdPhJH1XSM+SqyuLkCoMzNpRyZLzE +-> ssh-ed25519 fEyKPw QE2pjyXLZbW8HR3OhF8oB+uCWZ66DguGS+RsD7DOcAA +dgmY4gHz8Y8oWkK9Y7fBPJRrLbbAyZ5fZf//hIczqCA +--- 04Z/evyHZwcH0VpuTUX49uMFvOVXaJP/kNZBoOMKQPY +)۟ pmeOlpO %\ZDӋtX>p)]AW1_jHbw|iXܲ!'9>#26C_3eJ`X% }~-,`˞JSQ~Of¹،GUqU?X|BCv?g+m~eKEGٙIH*3xCuL&"w{ \ No newline at end of file diff --git a/secrets/server/forgejo/.env b/secrets/server/forgejo/.env new file mode 100644 index 0000000..5b96ccc Binary files /dev/null and b/secrets/server/forgejo/.env differ diff --git a/secrets/server/forgejo/db.env b/secrets/server/forgejo/db.env new file mode 100644 index 0000000..19f20b5 Binary files /dev/null and b/secrets/server/forgejo/db.env differ diff --git a/secrets/server/foundryvtt/.env b/secrets/server/foundryvtt/.env new file mode 100644 index 0000000..6d49062 Binary files /dev/null and b/secrets/server/foundryvtt/.env differ diff --git a/secrets/server/mastodon/.env b/secrets/server/mastodon/.env new file mode 100644 index 0000000..e1bb31d Binary files /dev/null and b/secrets/server/mastodon/.env differ diff --git a/secrets/server/mastodon/db.env b/secrets/server/mastodon/db.env new file mode 100644 index 0000000..21c5efd --- /dev/null +++ b/secrets/server/mastodon/db.env @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q WAGn8daIQLEJw9Mt/bJfTnIwjUBRmng74austLhnYy4 +nFAOsI9zvlDQi6MTsMvlaCZh+accDCehrol4jkz9yAY +-> ssh-ed25519 sfxzoQ EcHcN24Uc3Xe4v5uHrqydGyPKWJ3BW+ZBoSk6jcgTnk +ZFAkpf1+gP+1LElX+FrMpVe/X+gz2ddDmMLvpnmdoS4 +-> ssh-ed25519 fEyKPw o4GfQwf4rmmPSqDoFVQ2x8tUlnGQHN3H9CRpOedt/ho +YfenVPOA8RKuAld9JQy8Pnqg1wLTeymkL5AmMHzsNPo +--- sAlRSf0bIR2QaxW1RSch0IfTlMrjdHbCHSDEZ8t/MzI +[SA tma<K0e^j0%ן8{]YRSD"aLΉt#04!Cokt勞 \ No newline at end of file diff --git a/secrets/server/matrix-conduit/conduwuit.toml b/secrets/server/matrix-conduit/conduwuit.toml new file mode 100644 index 0000000..2be3aba Binary files /dev/null and b/secrets/server/matrix-conduit/conduwuit.toml differ diff --git a/secrets/server/nextcloud/.env b/secrets/server/nextcloud/.env new file mode 100644 index 0000000..fd5b634 Binary files /dev/null and b/secrets/server/nextcloud/.env differ diff --git a/secrets/server/nextcloud/db.env b/secrets/server/nextcloud/db.env new file mode 100644 index 0000000..40fb612 --- /dev/null +++ b/secrets/server/nextcloud/db.env @@ -0,0 +1,10 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q 97om/IOWXk6tl01kGopGrdnjCt//TCnTUjj99OG6diA +6PEnfDrMvZ3xeK2jHm3lB9mEzc50y7qz9fv69oBxAfk +-> ssh-ed25519 sfxzoQ nDfHXnV8tZTnx1aRqRswSiayUhd2QZIwoRMuMwwqRy0 +NtHuLusQOg7gkjEtblKfuivkpvBJJffiXu7eltyVX84 +-> ssh-ed25519 fEyKPw bWaCxW+ZWY48w5I5m3zfM2dmZiQGRhXcLw9I1BqfqBY +mc1WeCoe4x/DwMCb0fXoj8d1F0IinR/lvuXkPAx0ycc +--- zKmS5drfHXuFo7OpC8xnJFiiU8bmzUP8v1Q6tC6K5fI +0+m+C+tx?&hME +G;mRQj妐$EM dsa6oO^ZR'tw(Vu=ʨ^/0 \ No newline at end of file diff --git a/secrets/server/searxng/.env b/secrets/server/searxng/.env new file mode 100644 index 0000000..b34a45d Binary files /dev/null and b/secrets/server/searxng/.env differ diff --git a/secrets/server/users/myned.pass b/secrets/server/users/myned.pass new file mode 100644 index 0000000..6197a9c Binary files /dev/null and b/secrets/server/users/myned.pass differ diff --git a/secrets/server/users/root.pass b/secrets/server/users/root.pass new file mode 100644 index 0000000..4680181 --- /dev/null +++ b/secrets/server/users/root.pass @@ -0,0 +1,9 @@ +age-encryption.org/v1 +-> ssh-ed25519 8E6j8Q 821leYAo6b+qO4Fd3ykS7O0nIpETJEnQzOk85SjAnlo +Y893N1pN0MQhvGvS3V2vpEwrpdbKsHqjPrUJM8LEfc4 +-> ssh-ed25519 sfxzoQ Cf/yYSkBdnuR7V48xNUlA2UG4vsy1xfHNNXAO/YTDT8 ++VjbK3f7jDtNM3970vw7nRA8s5sG99R5HFsnvGEI6EY +-> ssh-ed25519 fEyKPw rHtfRIbFh8WYa3jEBIVbU44pQQp70Z/I8ahZwGa7jjo +ltbDAUjzChNkkjY0AuMifNdpsDkX5rT+qEOSv1xpTBo +--- zixaHgL7I4tRr97guQll80nKaKr7HCZ7BSpnNihbCJ8 +eH 42/Mھ^^89"Hy$0 Vd^SP?g:BLU)'@sL⼗oj^Xi \ No newline at end of file