diff --git a/.gitignore b/.gitignore index 697775e..145ae83 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1 @@ -Server/secrets.nix +nixos/common/secrets.nix diff --git a/README.md b/README.md index 260f480..bd2be21 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,7 @@ -### My Nix "dotfiles", organized in the worst way you will ever see. +### My Nix files, now organized in a flake. + +TODO: Documentation Made with love ❤️ -![image](./Extras/Screenshots/SecondUnix.png) +![image](./preview.png) diff --git a/flake.lock b/flake.lock new file mode 100644 index 0000000..8166207 --- /dev/null +++ b/flake.lock @@ -0,0 +1,323 @@ +{ + "nodes": { + "blobs": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, + "blobs_2": { + "flake": false, + "locked": { + "lastModified": 1604995301, + "narHash": "sha256-wcLzgLec6SGJA8fx1OEN1yV/Py5b+U5iyYpksUY/yLw=", + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "rev": "2cccdf1ca48316f2cfd1c9a0017e8de5a7156265", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "blobs", + "type": "gitlab" + } + }, + "disko": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "locked": { + "lastModified": 1724349583, + "narHash": "sha256-zgB1Cfk46irIsto8666yLdKjqKdBrjR48Dd3lhQ0CnQ=", + "owner": "nix-community", + "repo": "disko", + "rev": "435737144be0259559ca3b43f7d72252b1fdcc1b", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "disko", + "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" + } + }, + "hardware": { + "locked": { + "lastModified": 1724067415, + "narHash": "sha256-WJBAEFXAtA41RMpK8mvw0cQ62CJkNMBtzcEeNIJV7b0=", + "owner": "nixos", + "repo": "nixos-hardware", + "rev": "b09c46430ffcf18d575acf5c339b38ac4e1db5d2", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "master", + "repo": "nixos-hardware", + "type": "github" + } + }, + "home-manager": { + "inputs": { + "nixpkgs": [ + "nixpkgs" + ] + }, + "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" + } + }, + "mail": { + "inputs": { + "blobs": "blobs", + "flake-compat": "flake-compat", + "nixpkgs": "nixpkgs", + "nixpkgs-24_05": "nixpkgs-24_05" + }, + "locked": { + "lastModified": 1722877200, + "narHash": "sha256-qgKDNJXs+od+1UbRy62uk7dYal3h98I4WojfIqMoGcg=", + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "rev": "af7d3bf5daeba3fc28089b015c0dd43f06b176f2", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "type": "gitlab" + } + }, + "nixos-mailserver": { + "inputs": { + "blobs": "blobs_2", + "flake-compat": "flake-compat_2", + "nixpkgs": "nixpkgs_2", + "nixpkgs-24_05": "nixpkgs-24_05_2", + "utils": "utils" + }, + "locked": { + "lastModified": 1718084203, + "narHash": "sha256-Cx1xoVfSMv1XDLgKg08CUd1EoTYWB45VmB9XIQzhmzI=", + "owner": "simple-nixos-mailserver", + "repo": "nixos-mailserver", + "rev": "29916981e7b3b5782dc5085ad18490113f8ff63b", + "type": "gitlab" + }, + "original": { + "owner": "simple-nixos-mailserver", + "ref": "nixos-24.05", + "repo": "nixos-mailserver", + "type": "gitlab" + } + }, + "nixpkgs": { + "locked": { + "lastModified": 1717602782, + "narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs-24_05": { + "locked": { + "lastModified": 1717144377, + "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "805a384895c696f802a9bf5bf4720f37385df547", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-24.05", + "type": "indirect" + } + }, + "nixpkgs-24_05_2": { + "locked": { + "lastModified": 1717144377, + "narHash": "sha256-F/TKWETwB5RaR8owkPPi+SPJh83AQsm6KrQAlJ8v/uA=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "805a384895c696f802a9bf5bf4720f37385df547", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-24.05", + "type": "indirect" + } + }, + "nixpkgs-unstable": { + "locked": { + "lastModified": 1724224976, + "narHash": "sha256-Z/ELQhrSd7bMzTO8r7NZgi9g5emh+aRKoCdaAv5fiO0=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "c374d94f1536013ca8e92341b540eba4c22f9c62", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-unstable", + "repo": "nixpkgs", + "type": "github" + } + }, + "nixpkgs_2": { + "locked": { + "lastModified": 1717602782, + "narHash": "sha256-pL9jeus5QpX5R+9rsp3hhZ+uplVHscNJh8n8VpqscM0=", + "owner": "NixOS", + "repo": "nixpkgs", + "rev": "e8057b67ebf307f01bdcc8fba94d94f75039d1f6", + "type": "github" + }, + "original": { + "id": "nixpkgs", + "ref": "nixos-unstable", + "type": "indirect" + } + }, + "nixpkgs_3": { + "locked": { + "lastModified": 1724242322, + "narHash": "sha256-HMpK7hNjhEk4z5SFg5UtxEio9OWFocHdaQzCfW1pE7w=", + "owner": "nixos", + "repo": "nixpkgs", + "rev": "224042e9a3039291f22f4f2ded12af95a616cca0", + "type": "github" + }, + "original": { + "owner": "nixos", + "ref": "nixos-24.05", + "repo": "nixpkgs", + "type": "github" + } + }, + "nur": { + "locked": { + "lastModified": 1724395746, + "narHash": "sha256-kutXBf+8Rd9KxLMe/W/lN8RlqItCrQIyqyXH37mMsZc=", + "owner": "nix-community", + "repo": "NUR", + "rev": "f77e6626a93ab9670675bd495187a4aba8587dae", + "type": "github" + }, + "original": { + "owner": "nix-community", + "repo": "NUR", + "type": "github" + } + }, + "root": { + "inputs": { + "disko": "disko", + "hardware": "hardware", + "home-manager": "home-manager", + "mail": "mail", + "nixos-mailserver": "nixos-mailserver", + "nixpkgs": "nixpkgs_3", + "nixpkgs-unstable": "nixpkgs-unstable", + "nur": "nur" + } + }, + "systems": { + "locked": { + "lastModified": 1681028828, + "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=", + "owner": "nix-systems", + "repo": "default", + "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e", + "type": "github" + }, + "original": { + "owner": "nix-systems", + "repo": "default", + "type": "github" + } + }, + "utils": { + "inputs": { + "systems": "systems" + }, + "locked": { + "lastModified": 1709126324, + "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", + "owner": "numtide", + "repo": "flake-utils", + "rev": "d465f4819400de7c8d874d50b982301f28a84605", + "type": "github" + }, + "original": { + "owner": "numtide", + "repo": "flake-utils", + "type": "github" + } + } + }, + "root": "root", + "version": 7 +} diff --git a/flake.nix b/flake.nix new file mode 100644 index 0000000..902f856 --- /dev/null +++ b/flake.nix @@ -0,0 +1,88 @@ +{ + description = "Jimbo's Nix Flake"; + + inputs = { + # Nixpkgs + nixpkgs.url = "github:nixos/nixpkgs/nixos-24.05"; + nixpkgs-unstable.url = "github:nixos/nixpkgs/nixos-unstable"; + nur.url = "github:nix-community/NUR"; + mail.url = "gitlab:simple-nixos-mailserver/nixos-mailserver"; + nixos-mailserver.url = "gitlab:simple-nixos-mailserver/nixos-mailserver/nixos-24.05"; + + # NixOS utils + hardware.url = "github:nixos/nixos-hardware/master"; + disko = { + url = "github:nix-community/disko"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + + # Home manager + home-manager = { + url = "github:nix-community/home-manager/release-24.05"; + inputs.nixpkgs.follows = "nixpkgs"; + }; + }; + + outputs = { + self, + nixpkgs, + home-manager, + nur, + nixos-mailserver, + ... + } @inputs: let + inherit (self) outputs; + forAllSystems = nixpkgs.lib.genAttrs [ + "aarch64-linux" + "x86_64-linux" + ]; + in rec { + # Your custom packages + # Accessible through 'nix build', 'nix shell', etc + packages = forAllSystems (system: import ./pkgs nixpkgs.legacyPackages.${system}); + + # Formatter for your nix files, available through 'nix fmt' + # Other options beside 'alejandra' include 'nixpkgs-fmt' + formatter = forAllSystems (system: nixpkgs.legacyPackages.${system}.alejandra); + + # Your custom packages and modifications, exported as overlays + overlays = import ./overlays {inherit inputs;}; + + # NixOS configuration entrypoint, use 'nixos-rebuild --flake .#your-hostname' + nixosConfigurations = { + JimNixDesktop = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs outputs;}; + modules = [ + ./nixos/desktop.nix + ]; + }; + JimNixServer = nixpkgs.lib.nixosSystem { + specialArgs = {inherit inputs outputs;}; + modules = [ + ./nixos/server.nix + nixos-mailserver.nixosModule + ]; + }; + }; + + # Standalone home-manager configuration entrypoint + # Available through 'home-manager --flake .#your-username@your-hostname' + homeConfigurations = { + "jimbo@JimNixDesktop" = home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + extraSpecialArgs = {inherit inputs outputs;}; + modules = [ + ./home-manager/jimbo_desktop.nix + nur.nixosModules.nur + ]; + }; + "jimbo@JimNixServer" = home-manager.lib.homeManagerConfiguration { + pkgs = nixpkgs.legacyPackages.x86_64-linux; + extraSpecialArgs = {inherit inputs outputs;}; + modules = [ + ./home-manager/jimbo_server.nix + ]; + }; + }; + }; +} diff --git a/home-manager/assets/user-icon.png b/home-manager/assets/user-icon.png new file mode 100644 index 0000000..9cc6fd4 Binary files /dev/null and b/home-manager/assets/user-icon.png differ diff --git a/home-manager/assets/wallpapers/1.png b/home-manager/assets/wallpapers/1.png new file mode 100644 index 0000000..dfa5537 Binary files /dev/null and b/home-manager/assets/wallpapers/1.png differ diff --git a/home-manager/assets/wallpapers/2.png b/home-manager/assets/wallpapers/2.png new file mode 100644 index 0000000..70a632a Binary files /dev/null and b/home-manager/assets/wallpapers/2.png differ diff --git a/home-manager/assets/wallpapers/3.png b/home-manager/assets/wallpapers/3.png new file mode 100644 index 0000000..0d3e6c7 Binary files /dev/null and b/home-manager/assets/wallpapers/3.png differ diff --git a/home-manager/assets/wallpapers/lock.png b/home-manager/assets/wallpapers/lock.png new file mode 100644 index 0000000..0d97584 Binary files /dev/null and b/home-manager/assets/wallpapers/lock.png differ diff --git a/home-manager/common/auth.nix b/home-manager/common/auth.nix new file mode 100644 index 0000000..2c4b758 --- /dev/null +++ b/home-manager/common/auth.nix @@ -0,0 +1,3 @@ +{ + method = "doas"; +} diff --git a/home-manager/common/border.nix b/home-manager/common/border.nix new file mode 100644 index 0000000..790234c --- /dev/null +++ b/home-manager/common/border.nix @@ -0,0 +1,5 @@ +rec { + # Define miscellaneous window manager properties + weightInt = 3; + weight = toString weightInt; +} diff --git a/home-manager/common/displays.nix b/home-manager/common/displays.nix new file mode 100644 index 0000000..698c51f --- /dev/null +++ b/home-manager/common/displays.nix @@ -0,0 +1,7 @@ +{ + # Define the primary monitor + d1 = ''DP-3''; + d2 = ''DP-1''; + d3 = ''DP-2''; + dTouch = ''eDP-1''; +} diff --git a/home-manager/common/fonts.nix b/home-manager/common/fonts.nix new file mode 100644 index 0000000..d326efb --- /dev/null +++ b/home-manager/common/fonts.nix @@ -0,0 +1,5 @@ +{ + # Set the default fonts + main = ''Ubuntu''; + nerd = ''UbuntuMono Nerd Font''; +} diff --git a/home-manager/common/nixcfg.nix b/home-manager/common/nixcfg.nix new file mode 100644 index 0000000..88370a9 --- /dev/null +++ b/home-manager/common/nixcfg.nix @@ -0,0 +1,3 @@ +{ + open = "ranger /etc/nixos"; +} diff --git a/home-manager/guiapps/easyeffects.nix b/home-manager/guiapps/easyeffects.nix new file mode 100644 index 0000000..bffaa3e --- /dev/null +++ b/home-manager/guiapps/easyeffects.nix @@ -0,0 +1,309 @@ +{pkgs, ...}: { + home = { + packages = with pkgs; [ + easyeffects + ]; + file = let + # An Easyeffects equalizer profile that sounds good to me + easyEffectsProfile = '' + { + "output": { + "blocklist": [], + "crystalizer#0": { + "band0": { + "bypass": false, + "intensity": 0.0, + "mute": false + }, + "band1": { + "bypass": false, + "intensity": -1.0, + "mute": false + }, + "band2": { + "bypass": false, + "intensity": -2.0, + "mute": false + }, + "band3": { + "bypass": false, + "intensity": -3.0, + "mute": false + }, + "band4": { + "bypass": false, + "intensity": -4.0, + "mute": false + }, + "band5": { + "bypass": false, + "intensity": -5.0, + "mute": false + }, + "band6": { + "bypass": false, + "intensity": -6.0, + "mute": false + }, + "band7": { + "bypass": false, + "intensity": -7.0, + "mute": false + }, + "band8": { + "bypass": false, + "intensity": -8.0, + "mute": false + }, + "band9": { + "bypass": false, + "intensity": -9.0, + "mute": false + }, + "band10": { + "bypass": false, + "intensity": -10.0, + "mute": false + }, + "band11": { + "bypass": false, + "intensity": -11.0, + "mute": false + }, + "band12": { + "bypass": false, + "intensity": -12.0, + "mute": false + }, + "bypass": false, + "input-gain": 0.0, + "output-gain": 0.0 + }, + "equalizer#0": { + "balance": 0.0, + "bypass": false, + "input-gain": 0.0, + "left": { + "band0": { + "frequency": 32.0, + "gain": 1.1, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band1": { + "frequency": 64.0, + "gain": 1.16, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band2": { + "frequency": 125.0, + "gain": 3.33, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band3": { + "frequency": 250.0, + "gain": 1.53, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band4": { + "frequency": 500.0, + "gain": -1.83, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band5": { + "frequency": 1000.0, + "gain": -0.58, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band6": { + "frequency": 2000.0, + "gain": 1.42, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band7": { + "frequency": 4000.0, + "gain": 4.73, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band8": { + "frequency": 16000.0, + "gain": 7.62, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band9": { + "frequency": 156.38, + "gain": 2.84, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + } + }, + "mode": "IIR", + "num-bands": 10, + "output-gain": 0.0, + "pitch-left": 0.0, + "pitch-right": 0.0, + "right": { + "band0": { + "frequency": 32.0, + "gain": 1.1, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band1": { + "frequency": 64.0, + "gain": 1.16, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band2": { + "frequency": 125.0, + "gain": 3.33, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band3": { + "frequency": 250.0, + "gain": 1.53, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band4": { + "frequency": 500.0, + "gain": -1.83, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band5": { + "frequency": 1000.0, + "gain": -0.58, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band6": { + "frequency": 2000.0, + "gain": 1.42, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band7": { + "frequency": 4000.0, + "gain": 4.73, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band8": { + "frequency": 16000.0, + "gain": 7.62, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + }, + "band9": { + "frequency": 156.38, + "gain": 2.84, + "mode": "RLC (BT)", + "mute": false, + "q": 4.36, + "slope": "x1", + "solo": false, + "type": "Bell" + } + }, + "split-channels": false + }, + "plugins_order": [ + "equalizer#0", + "crystalizer#0" + ] + } + } + ''; + in { + # Easyeffects profile + ".config/easyeffects/output/JimHeadphones.json".text = easyEffectsProfile; + }; + }; +} diff --git a/home-manager/guiapps/foot.nix b/home-manager/guiapps/foot.nix new file mode 100644 index 0000000..3de379c --- /dev/null +++ b/home-manager/guiapps/foot.nix @@ -0,0 +1,43 @@ +{ + # Enable a terminal emulator + programs.foot = { + enable = true; + server.enable = false; + settings = { + main = let + fonts = import ../common/fonts.nix; + in { + term = "xterm-256color"; + font = "${fonts.nerd}:size=14.7"; + }; + cursor = { + style = "beam"; + }; + colors = let + colors = import ../style/colors.nix; + in { + alpha = "0.65"; + background = "${colors.dark}"; + regular0 = "3f3f3f"; + regular1 = "cc0000"; + regular2 = "4e9a06"; + regular3 = "c4a000"; + regular4 = "94bff3"; + regular5 = "85678f"; + regular6 = "06989a"; + regular7 = "dcdccc"; + bright0 = "545454"; + bright1 = "fc5454"; + bright2 = "8ae234"; + bright3 = "fce94f"; + bright4 = "94bff3"; + bright5 = "b294bb"; + bright6 = "93e0e3"; + bright7 = "ffffff"; + }; + key-bindings = { + search-start = "Control+f"; + }; + }; + }; +} diff --git a/home-manager/guiapps/librewolf.nix b/home-manager/guiapps/librewolf.nix new file mode 100644 index 0000000..b96fa8f --- /dev/null +++ b/home-manager/guiapps/librewolf.nix @@ -0,0 +1,426 @@ +{pkgs, config, ...}: let + # Import variables + colors = import ../style/colors.nix; + fonts = import ../common/fonts.nix; + + # FireFox colors + themeJim = '' + :root { + --tab-active-bg-color: #${colors.prime}; + --tab-hover-bg-color: #${colors.accent}; + --tab-inactive-bg-color: #${colors.dark}; + --tab-active-fg-fallback-color: #FFFFFF; + --tab-inactive-fg-fallback-color: #${colors.text}; + --urlbar-focused-bg-color: #${colors.dark}; + --urlbar-not-focused-bg-color: #${colors.dark}; + --toolbar-bgcolor: #${colors.dark} !important; + ''; + themeAlt = '' + :root { + --tab-active-bg-color: #${colors.dark}; + --tab-hover-bg-color: #${colors.accent}; + --tab-inactive-bg-color: #${colors.prime}; + --tab-active-fg-fallback-color: #${colors.text}; + --tab-inactive-fg-fallback-color: #FFFFFF; + --urlbar-focused-bg-color: #${colors.prime}; + --urlbar-not-focused-bg-color: #${colors.prime}; + --toolbar-bgcolor: #${colors.prime} !important; + ''; + quteFoxCSS = '' + --tab-font: '${fonts.main}'; + --urlbar-font: '${fonts.main}'; + + /* try increasing if you encounter problems */ + --urlbar-height-setting: 24px; + --tab-min-height: 20px !important; + + /* I don't recommend you touch this */ + --arrowpanel-menuitem-padding: 2px !important; + --arrowpanel-border-radius: 0px !important; + --arrowpanel-menuitem-border-radius: 0px !important; + --toolbarbutton-border-radius: 0px !important; + --toolbarbutton-inner-padding: 0px 2px !important; + --toolbar-field-focus-background-color: var(--urlbar-focused-bg-color) !important; + --toolbar-field-background-color: var(--urlbar-not-focused-bg-color) !important; + --toolbar-field-focus-border-color: transparent !important; + } + + /* --- General debloat ------------------------------ */ + + /* bottom left page loading status or url preview */ + #statuspanel { display: none !important; } + + /* remove radius from right-click popup */ + menupopup, panel { --panel-border-radius: 0px !important; } + menu, menuitem, menucaption { border-radius: 0px !important; } + + /* no large buttons in right-click menu */ + menupopup > #context-navigation { display: none !important; } + menupopup > #context-sep-navigation { display: none !important; } + + /* --- Debloat navbar ------------------------------- */ + + #back-button { display: none; } + #forward-button { display: none; } + #reload-button { display: none; } + #stop-button { display: none; } + #home-button { display: none; } + #library-button { display: none; } + #fxa-toolbar-menu-button { display: none; } + /* empty space before and after the url bar */ + #customizableui-special-spring1, #customizableui-special-spring2 { display: none; } + + /* --- Style navbar -------------------------------- */ + + /* remove padding between toolbar buttons */ + toolbar .toolbarbutton-1 { padding: 0 0 !important; } + + #urlbar-container { + --urlbar-container-height: var(--urlbar-height-setting) !important; + margin-left: 0 !important; + margin-right: 0 !important; + padding-top: 0 !important; + padding-bottom: 0 !important; + font-family: var(--urlbar-font, 'monospace'); + font-size: 14px; + } + + #urlbar { + --urlbar-height: var(--urlbar-height-setting) !important; + --urlbar-toolbar-height: var(--urlbar-height-setting) !important; + min-height: var(--urlbar-height-setting) !important; + border-color: var(--lwt-toolbar-field-border-color, hsla(240,5%,5%,.25)) !important; + } + + #urlbar-input { + margin-left: 0.8em !important; + margin-right: 0.4em !important; + } + + #navigator-toolbox { + border: none !important; + } + + /* keep pop-up menus from overlapping with navbar */ + #widget-overflow { margin: 0 !important; } + #appmenu-popup { margin: 0 !important; } + #customizationui-widget-panel { margin: 0 !important; } + #unified-extensions-panel { margin: 0 !important; } + + /* --- Unified extensions button -------------------- */ + + /* make extension icons smaller */ + #unified-extensions-view { + --uei-icon-size: 18px; + } + + /* hide bloat */ + .unified-extensions-item-message-deck, + #unified-extensions-view > .panel-header, + #unified-extensions-view > toolbarseparator, + #unified-extensions-manage-extensions { + display: none !important; + } + + /* add 3px padding on the top and the bottom of the box */ + .panel-subview-body { + padding: 3px 0px !important; + } + + #unified-extensions-view .unified-extensions-item-menu-button { + margin-inline-end: 0 !important; + } + + #unified-extensions-view .toolbarbutton-icon { + padding: 0 !important; + } + + .unified-extensions-item-contents { + line-height: 1 !important; + white-space: nowrap !important; + } + + /* --- Debloat URL bar ------------------------------- */ + + #identity-box { display: none; } + #pageActionButton { display: none; } + #pocket-button { display: none; } + #urlbar-zoom-button { display: none; } + #tracking-protection-icon-container { display: none !important; } + #reader-mode-button{ display: none !important; } + #star-button { display: none; } + #star-button-box:hover { background: inherit !important; } + + /* Go to arrow button at the end of the urlbar when searching */ + #urlbar-go-button { display: none; } + + /* remove container indicator from urlbar */ + #userContext-label, #userContext-indicator { display: none !important;} + + /* --- Style tab toolbar ---------------------------- */ + + #titlebar { + --proton-tab-block-margin: 0px !important; + --tab-block-margin: 0px !important; + } + + #TabsToolbar, .tabbrowser-tab { + max-height: var(--tab-min-height) !important; + font-size: 14px !important; + outline: none !important; + } + + /* Change color of normal tabs */ + tab:not([selected="true"]) { + background-color: var(--tab-inactive-bg-color) !important; + color: var(--identity-icon-color, var(--tab-inactive-fg-fallback-color)) !important; + } + + tab { + font-family: var(--tab-font, monospace); + border: none !important; + } + + /* safari style tab width */ + .tabbrowser-tab[fadein] { + max-width: 100vw !important; + border: none + } + + /* Hide close button on tabs */ + #tabbrowser-tabs .tabbrowser-tab .tab-close-button { display: none !important; } + + .tabbrowser-tab { + /* remove border between tabs */ + padding-inline: 0px !important; + /* reduce fade effect of tab text */ + --tab-label-mask-size: 1em !important; + /* fix pinned tab behaviour on overflow */ + overflow-clip-margin: 0px !important; + } + + /* Tab: selected colors */ + #tabbrowser-tabs .tabbrowser-tab[selected] .tab-content { + background: var(--tab-active-bg-color) !important; + color: var(--identity-icon-color, var(--tab-active-fg-fallback-color)) !important; + } + + /* Tab: hovered colors */ + #tabbrowser-tabs .tabbrowser-tab:hover:not([selected]) .tab-content { + background: var(--tab-hover-bg-color) !important; + } + + /* hide window controls */ + .titlebar-buttonbox-container { display: none; } + + /* remove titlebar spacers */ + .titlebar-spacer { display: none !important; } + + /* disable tab shadow */ + #tabbrowser-tabs:not([noshadowfortests]) .tab-background:is([selected], [multiselected]) { + box-shadow: none !important; + } + + /* remove dark space between pinned tab and first non-pinned tab */ + #tabbrowser-tabs[haspinnedtabs]:not([positionpinnedtabs]) > + #tabbrowser-arrowscrollbox > + .tabbrowser-tab:nth-child(1 of :not([pinned], [hidden])) { + margin-inline-start: 0px !important; + } + + /* remove dropdown menu button which displays all tabs on overflow */ + #alltabs-button { display: none !important } + + /* fix displaying of pinned tabs on overflow */ + #tabbrowser-tabs:not([secondarytext-unsupported]) .tab-label-container { + height: var(--tab-min-height) !important; + } + + /* remove overflow scroll buttons */ + #scrollbutton-up, #scrollbutton-down { display: none !important; } + + /* remove new tab button */ + #tabs-newtab-button { + display: none !important; + } + + /* --- Autohide Navbar ------------------------------ */ + + /* hide navbar unless focused */ + #nav-bar { + min-height: 0 !important; + max-height: 0 !important; + height: 0 !important; + --moz-transform: scaleY(0) !important; + transform: scaleY(0) !important; + } + + /* show on focus */ + #nav-bar:focus-within { + --moz-transform: scale(1) !important; + transform: scale(1) !important; + max-height: var(--urlbar-height-setting) !important; + height: var(--urlbar-height-setting) !important; + min-height: var(--urlbar-height-setting) !important; + } + + #navigator-toolbox:focus-within > .browser-toolbar { + transform: translateY(0); + opacity: 1; + } + + /* --- Hide tab bar on single tab ------------------- */ + + #tabbrowser-tabs .tabbrowser-tab:only-of-type, + #tabbrowser-tabs .tabbrowser-tab:only-of-type + #tabbrowser-arrowscrollbox-periphery{ + display:none !important; + } + #tabbrowser-tabs, #tabbrowser-arrowscrollbox {min-height:0!important;} + #alltabs-button {display:none !important;} + + /* --- Prevent tab folding -------------------------- */ + + .tabbrowser-tab { + min-width: initial !important; + } + .tab-content { + overflow: hidden !important; + } + ''; +in { + # Enable Librewolf and extensions + programs.firefox = let + commonExtensions = with config.nur.repos.rycee.firefox-addons; [ + ublock-origin + bitwarden + darkreader + sponsorblock + return-youtube-dislikes + no-pdf-download + ]; + commonSearch = { + force = true; + default = "Google"; + engines = { + "Google" = { + urls = [ + { + template = "https://www.google.com/search"; + params = [ + { + name = "q"; + value = "{searchTerms}"; + } + ]; + } + ]; + definedAliases = ["@g"]; + }; + "NixPKGs" = { + urls = [ + { + template = "https://search.nixos.org/packages"; + params = [ + { + name = "type"; + value = "packages"; + } + { + name = "query"; + value = "{searchTerms}"; + } + ]; + } + ]; + icon = "${pkgs.nixos-icons}/share/icons/hicolor/scalable/apps/nix-snowflake.svg"; + definedAliases = ["@pkgs"]; + }; + }; + }; + commonSettings = { + "font.name.serif.x-western" = "${fonts.main}"; + "font.name.sans-serif.x-western" = "${fonts.main}"; + "font.name.monospace.x-western" = "${fonts.nerd}"; + "general.autoScroll" = true; + "browser.compactmode.show" = true; + "browser.uidensity" = 1; + "browser.startup.page" = 3; + "extensions.pocket.enabled" = false; + "toolkit.legacyUserProfileCustomizations.stylesheets" = true; + "privacy.userContext.newTabContainerOnLeftClick.enabled" = true; + "privacy.clearOnShutdown.history" = false; + "privacy.clearOnShutdown.cookies" = false; + "browser.toolbars.bookmarks.visibility" = "never"; + "media.hardware-video-decoding.force-enabled" = true; + "svg.context-properties.content.enabled" = true; + "toolkit.tabbox.switchByScrolling" = true; + "device.sensors.motion.enabled" = false; + "extensions.autoDisableScopes" = 0; + "gnomeTheme.hideSingleTab" = true; + "browser.contentblocking.category" = "strict"; + "urlclassifier.trackingSkipURLs" = "*.reddit.com, *.twitter.com, *.twimg.com, *.tiktok.com"; + "urlclassifier.features.socialtracking.skipURLs" = "*.instagram.com, *.twitter.com, *.twimg.com"; + "network.cookie.sameSite.noneRequiresSecure" = true; + "browser.helperApps.deleteTempFileOnExit" = true; + "privacy.globalprivacycontrol.enabled" = true; + "privacy.globalprivacycontrol.functionality.enabled" = true; + #"webgl.disabled" = false; + }; + in { + enable = true; + package = pkgs.librewolf; + profiles = { + Jimbo = { + id = 0; + extensions = commonExtensions; + search = commonSearch; + settings = commonSettings; + userChrome = '' + ${themeJim} + ${quteFoxCSS} + ''; + }; + Alt = { + id = 1; + extensions = commonExtensions; + search = commonSearch; + settings = commonSettings; + userChrome = '' + ${themeAlt} + ${quteFoxCSS} + ''; + }; + Misc = { + id = 2; + extensions = commonExtensions; + search = commonSearch; + settings = commonSettings; + containersForce = true; + containers = { + Google = { + color = "green"; + icon = "fingerprint"; + id = 200; + }; + Seneca = { + color = "red"; + icon = "briefcase"; + id = 201; + }; + }; + }; + }; + }; + + # Fixes + home.file = { + # Symlinks to Librewolf + ".librewolf".source = config.lib.file.mkOutOfStoreSymlink "/home/jimbo/.mozilla/firefox"; + + # Gnome theme + ".mozilla/firefox/Misc/chrome".source = "${fetchTarball { + url = "https://github.com/rafaelmardojai/firefox-gnome-theme/archive/refs/tags/v129.zip"; + sha256 = "14x0vp66i8b14q6c9n75sa88fcwy9jd9lik8sjnab2rnwlskvq9h"; + }}"; + }; +} diff --git a/home-manager/guiapps/mangohud.nix b/home-manager/guiapps/mangohud.nix new file mode 100644 index 0000000..f7160d7 --- /dev/null +++ b/home-manager/guiapps/mangohud.nix @@ -0,0 +1,32 @@ +{pkgs, ...}: { + home = { + packages = with pkgs; [ + mangohud + ]; + file = let + # Mangohud config file + mangoConf = '' + table_columns=2 + frametime=0 + legacy_layout=0 + font_scale=0.80 + background_alpha=0.25 + + # Set the loads and such + exec=echo $(echo $XDG_CURRENT_DESKTOP | sed 's/./\U&/') on $(cat /etc/os-release | grep PRETTY_NAME | cut -d '"' -f 2) + fps + fps_color_change + ram + vram + cpu_stats + cpu_load_change + gpu_stats + gpu_load_change + frame_timing + ''; + in { + # Mangohud config + ".config/MangoHud/MangoHud.conf".text = mangoConf; + }; + }; +} diff --git a/home-manager/guiapps/mpv.nix b/home-manager/guiapps/mpv.nix new file mode 100644 index 0000000..0fec58b --- /dev/null +++ b/home-manager/guiapps/mpv.nix @@ -0,0 +1,11 @@ +{ + # MPV settings + programs.mpv = { + enable = true; + config = { + volume = 55; + loop-playlist = "inf"; + osc = "no"; + }; + }; +} diff --git a/home-manager/guiapps/obs.nix b/home-manager/guiapps/obs.nix new file mode 100644 index 0000000..f8da5fe --- /dev/null +++ b/home-manager/guiapps/obs.nix @@ -0,0 +1,14 @@ +{pkgs, ...}: { + # OBS with plugins + programs.obs-studio = { + enable = true; + plugins = with pkgs.obs-studio-plugins; [ + obs-pipewire-audio-capture + obs-webkitgtk + obs-multi-rtmp + obs-vkcapture + obs-tuna + looking-glass-obs + ]; + }; +} diff --git a/home-manager/guiapps/pcmanfm-qt.nix b/home-manager/guiapps/pcmanfm-qt.nix new file mode 100644 index 0000000..e8e4838 --- /dev/null +++ b/home-manager/guiapps/pcmanfm-qt.nix @@ -0,0 +1,61 @@ +{pkgs, ...}: { + # Swappy config file + home = { + packages = with pkgs; [ + pcmanfm-qt + ]; + file = let + # File manager config + pcmanConf = '' + [Behavior] + BookmarkOpenMethod=current_tab + ConfirmDelete=true + RecentFilesNumber=0 + + [Desktop] + HideItems=false + SortColumn=name + SortFolderFirst=true + SortHiddenLast=false + SortOrder=ascending + + [FolderView] + Mode=icon + ScrollPerPixel=true + ShadowHidden=true + ShowFilter=false + ShowFullNames=true + ShowHidden=true + SortCaseSensitive=false + SortColumn=mtime + SortFolderFirst=true + SortHiddenLast=false + SortOrder=descending + + [Places] + HiddenPlaces=menu://applications/, network:///, computer:///, /home/jimbo/Desktop + + [System] + Archiver=file-roller + Terminal=foot + + [Thumbnail] + MaxExternalThumbnailFileSize=-1 + MaxThumbnailFileSize=4096 + ShowThumbnails=true + ThumbnailLocalFilesOnly=true + + [Window] + AlwaysShowTabs=false + PathBarButtons=true + ShowMenuBar=true + ShowTabClose=true + SwitchToNewTab=true + TabPaths=@Invalid() + ''; + in { + # PCManFM config + ".config/pcmanfm-qt/default/settings.conf".text = pcmanConf; + }; + }; +} diff --git a/home-manager/guiapps/rofi.nix b/home-manager/guiapps/rofi.nix new file mode 100644 index 0000000..fd0f60e --- /dev/null +++ b/home-manager/guiapps/rofi.nix @@ -0,0 +1,191 @@ +{pkgs, config, ...}: { + # Enable Rofi + programs.rofi = { + enable = true; + package = pkgs.rofi-wayland; + terminal = "foot"; + font = let + fonts = import ../common/fonts.nix; + in "${fonts.main} 14"; + theme = let + inherit (config.lib.formats.rasi) mkLiteral; + border = import ../common/border.nix; + colors = import ../style/colors.nix; + in { + "*" = { + lightbg = mkLiteral "#EEE8D5"; + lightfg = mkLiteral "#586875"; + blue = mkLiteral "#268BD2"; + red = mkLiteral "#DC322F"; + background-color = mkLiteral "#00000000"; + separatorcolor = mkLiteral "#00000000"; + normal-foreground = mkLiteral "#${colors.text}"; + normal-background = mkLiteral "#${colors.dark}1A"; + urgent-foreground = mkLiteral "#${colors.urgent}"; + active-foreground = mkLiteral "#${colors.split}"; + selected-active-foreground = mkLiteral "#${colors.prime}"; + background = mkLiteral "#${colors.dark}B3"; + bordercolor = mkLiteral "#${colors.prime}"; + selected-normal-foreground = mkLiteral "#FFFFFF"; + selected-normal-background = mkLiteral "#${colors.prime}80"; + border-color = mkLiteral "#${colors.prime}"; + urgent-background = mkLiteral "#${colors.accent}26"; + active-background = mkLiteral "#${colors.accent}26"; + selected-active-background = mkLiteral "#${colors.split}54"; + }; + "#window" = { + background-color = mkLiteral "@background"; + width = 500; + border = mkLiteral "${border.weight}"; + padding = 5; + }; + "#message" = { + border = mkLiteral "1px dash 0px 0px"; + border-color = mkLiteral "@separatorcolor"; + padding = 1; + }; + "#textbox" = { + text-color = mkLiteral "@normal-foreground"; + }; + "#listview" = { + fixed-height = 0; + border-color = mkLiteral "@separatorcolor"; + scrollbar = mkLiteral "false"; + columns = 2; + }; + "#element" = { + border = 0; + padding = 1; + }; + "#element-text" = { + background-color = mkLiteral "inherit"; + text-color = mkLiteral "inherit"; + }; + "#element.normal.normal" = { + text-color = mkLiteral "@normal-foreground"; + }; + "#element.normal.urgent" = { + text-color = mkLiteral "@urgent-foreground"; + }; + "#element.normal.active" = { + background-color = mkLiteral "@active-background"; + text-color = mkLiteral "@active-foreground"; + }; + "#element.selected.normal" = { + background-color = mkLiteral "@selected-normal-background"; + text-color = mkLiteral "@selected-normal-foreground"; + }; + "#element.selected.urgent" = { + background-color = mkLiteral "@urgent-background"; + text-color = mkLiteral "@urgent-foreground"; + }; + "#element.selected.active" = { + background-color = mkLiteral "@selected-active-background"; + text-color = mkLiteral "@selected-active-foreground"; + }; + "#element.alternate.normal" = { + text-color = mkLiteral "@normal-foreground"; + }; + "#element.alternate.urgent" = { + text-color = mkLiteral "@urgent-foreground"; + }; + "#element.alternate.active" = { + background-color = mkLiteral "@active-background"; + text-color = mkLiteral "@active-foreground"; + }; + "#mode-switcher" = { + border = mkLiteral "2px dash 0px 0px"; + border-color = mkLiteral "@separatorcolor"; + }; + "#button.selected" = { + background-color = mkLiteral "@selected-normal-background"; + text-color = mkLiteral "@selected-normal-foreground"; + }; + "#case-indicator" = { + spacing = mkLiteral "0"; + text-color = mkLiteral "@normal-foreground"; + }; + "#entry" = { + spacing = 0; + text-color = mkLiteral "@normal-foreground"; + }; + "#prompt" = { + spacing = 0; + text-color = mkLiteral "@normal-foreground"; + }; + "#inputbar" = { + spacing = 0; + text-color = mkLiteral "@normal-foreground"; + padding = 1; + children = map mkLiteral ["prompt" "textbox-prompt-colon" "entry"]; + }; + "#textbox-prompt-colon" = { + expand = false; + str = ":"; + margin = mkLiteral "0px 0.3em 0em 0em"; + text-color = mkLiteral "@normal-foreground"; + }; + }; + }; + home.packages = let + # All my rofi scripts in one file + rofiScripts = let + displays = import ../common/displays.nix; + in pkgs.writeScriptBin "rofiscripts" '' + # Scratchpad function + handle_scratchpads() { + SCRATCHPADS=$(echo -e "Gotop\nMusic\nSound\nEasyEffects" | rofi -dmenu -i -p "Scratchpads") + case $SCRATCHPADS in + Gotop) foot -a gotop -T Gotop gotop;; + Music) foot -a music -T Music ncmpcpp;; + Sound) foot -a sound -T Sound pulsemixer;; + EasyEffects) easyeffects;; + esac + } + + # Lock menu + handle_power() { + POWER=$(echo -e "Shutdown\nReboot\nSleep\nLock\nKill" | rofi -dmenu -i -p "Power") + case $POWER in + Shutdown) poweroff;; + Reboot) reboot;; + Sleep) swaylock --sleep &;; + Lock) swaylock &;; + Kill) pkill -9 sway;; + esac + } + + # Resolutions + handle_resolutions() { + RET=$(echo -e "Default\nWide\nGPU2" | rofi -dmenu -i -p "Resolutions") + case $RET in + Default) swaymsg reload ;; + Wide) swaymsg " + output ${displays.d1} enable pos 1680 0 mode 1680x1050@59.954Hz + output ${displays.d2} enable pos 0 0 mode 1680x1050@59.954Hz + output ${displays.d3} enable pos 3360 0 transform 0 + ";; + GPU2) swaymsg " + output ${displays.d2} enable pos 1680 0 mode 1920x1080@60Hz + output ${displays.d3} enable pos 0 0 transform 0 + ";; + esac + } + + # Check for command-line arguments + if [ "$1" == "--scratchpads" ]; then + handle_scratchpads + elif [ "$1" == "--power" ]; then + handle_power + elif [ "$1" == "--resolutions" ]; then + handle_resolutions + else + echo "Please use a valid argument." + fi + ''; + in with pkgs; [ + rofiScripts + rofi-bluetooth + bemoji + ]; +} diff --git a/home-manager/guiapps/swappy.nix b/home-manager/guiapps/swappy.nix new file mode 100644 index 0000000..917bc40 --- /dev/null +++ b/home-manager/guiapps/swappy.nix @@ -0,0 +1,19 @@ +{pkgs, ...}: { + # Swappy config file + home = { + packages = with pkgs; [ + swappy + ]; + file = let + # Swappy config, for screenshot editing + swappyConfig = '' + [Default] + early_exit=true + save_dir=$HOME/Pictures/Screenshots + ''; + in { + # Swappy's config + ".config/swappy/config".text = swappyConfig; + }; + }; +} diff --git a/home-manager/home.nix b/home-manager/home.nix new file mode 100644 index 0000000..a05935b --- /dev/null +++ b/home-manager/home.nix @@ -0,0 +1,49 @@ +# This is your home-manager configuration file +# Use this to configure your home environment (it replaces ~/.config/nixpkgs/home.nix) +{pkgs, inputs, outputs, ...}: { + imports = [ + # Terminal apps + ./tuiapps/git.nix + ./tuiapps/zsh.nix + ./tuiapps/fastfetch.nix + ./tuiapps/neovim.nix + ./tuiapps/ranger.nix + ./tuiapps/tmux.nix + + # Services + ./services/reloadunits.nix + ]; + + nixpkgs = { + # You can add overlays here + overlays = [ + # Add overlays your own flake exports (from overlays and pkgs dir): + outputs.overlays.additions + outputs.overlays.modifications + outputs.overlays.unstable-packages + ]; + # Configure your nixpkgs instance + config = { + # Disable if you don't want unfree packages + allowUnfree = true; + # Workaround for https://github.com/nix-community/home-manager/issues/2942 + allowUnfreePredicate = _: true; + }; + }; + + # Common programs I'll need everywhere + home.packages = with pkgs; [ + home-manager + gotop + tcptrack + p7zip + vimv + dua + pciutils + usbutils + protonvpn-cli_2 + ]; + + # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion + home.stateVersion = "24.05"; +} diff --git a/home-manager/jimbo_desktop.nix b/home-manager/jimbo_desktop.nix new file mode 100644 index 0000000..b246304 --- /dev/null +++ b/home-manager/jimbo_desktop.nix @@ -0,0 +1,60 @@ +{config, ...}: { + imports = [ + # Common modules + ./home.nix + ./users/jimbo.nix + + # GUI Apps + ./misc/guifiles.nix + ./sway/sway.nix + ./guiapps/foot.nix + ./guiapps/librewolf.nix + ./guiapps/mangohud.nix + ./guiapps/mpv.nix + ./guiapps/obs.nix + ./guiapps/pcmanfm-qt.nix + ./guiapps/rofi.nix + ./guiapps/swappy.nix + ./guiapps/easyeffects.nix + ./tuiapps/ncmpcpp.nix + + # Misc Apps + ./misc/useful.nix + ./misc/avtools.nix + ./misc/filemanager.nix + ./misc/production.nix + #./misc/remotedesktop.nix + #./misc/emulators.nix + ./misc/school.nix + + # Theming + ./style/gtk.nix + ./style/qt.nix + + # Services + ./services/gnome-keyring.nix + ./services/mako.nix + ./services/udiskie.nix + ]; + + # Rebuild this entire system + programs.zsh = { + oh-my-zsh.theme = "agnoster"; # risto for VM, half-life for Server + shellAliases = let + auth = import ./common/auth.nix; + in { + nixdate = '' + ${auth.method} nixos-rebuild switch --flake /etc/nixos/.#JimNixDesktop; + home-manager switch --flake /etc/nixos/.#jimbo@JimNixDesktop; + notify-send "NixOS switch finished." + ''; + }; + }; + + # Symlinks + home.file = { + "VMs" = { + source = config.lib.file.mkOutOfStoreSymlink "/etc/libvirt/VMs"; + }; + }; +} diff --git a/home-manager/jimbo_server.nix b/home-manager/jimbo_server.nix new file mode 100644 index 0000000..720bc4f --- /dev/null +++ b/home-manager/jimbo_server.nix @@ -0,0 +1,20 @@ +{config, ...}: { + imports = [ + # Common modules + ./home.nix + ./users/jimbo.nix + ]; + + # Rebuild this entire system + programs.zsh = { + oh-my-zsh.theme = "half-life"; + shellAliases = let + auth = import ./common/auth.nix; + in { + nixdate = '' + ${auth.method} nixos-rebuild switch --flake /etc/nixos/.#JimNixServer; + home-manager switch --flake /etc/nixos/.#jimbo@JimNixServer; + ''; + }; + }; +} diff --git a/home-manager/misc/avtools.nix b/home-manager/misc/avtools.nix new file mode 100644 index 0000000..baffc4b --- /dev/null +++ b/home-manager/misc/avtools.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + yt-dlp + spotdl + playerctl + ffmpeg + pulsemixer + ]; +} diff --git a/home-manager/misc/emulators.nix b/home-manager/misc/emulators.nix new file mode 100644 index 0000000..931f46d --- /dev/null +++ b/home-manager/misc/emulators.nix @@ -0,0 +1,10 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + dolphin-emu + cemu + ryujinx + duckstation + pcsx2 + unstable.lime3ds + ]; +} diff --git a/home-manager/misc/filemanager.nix b/home-manager/misc/filemanager.nix new file mode 100644 index 0000000..f6b18f9 --- /dev/null +++ b/home-manager/misc/filemanager.nix @@ -0,0 +1,7 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + gnome.file-roller + imagemagick + poppler_utils + ]; +} diff --git a/home-manager/misc/guifiles.nix b/home-manager/misc/guifiles.nix new file mode 100644 index 0000000..dc85cc1 --- /dev/null +++ b/home-manager/misc/guifiles.nix @@ -0,0 +1,15 @@ +{pkgs, ...}: { + # Files that only make sense with a GUI + home.file = { + ".face" = { + source = ../assets/user-icon.png; + }; + ".wallpapers" = { + source = ../assets/wallpapers; + recursive = true; + }; + ".icons/default" = { + source = "${pkgs.simp1e-cursors}/share/icons/Simp1e-Dark"; + }; + }; +} diff --git a/home-manager/misc/production.nix b/home-manager/misc/production.nix new file mode 100644 index 0000000..add7334 --- /dev/null +++ b/home-manager/misc/production.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + krita + inkscape + audacity + blender + sunvox + ]; +} diff --git a/home-manager/misc/remotedesktop.nix b/home-manager/misc/remotedesktop.nix new file mode 100644 index 0000000..4d18c48 --- /dev/null +++ b/home-manager/misc/remotedesktop.nix @@ -0,0 +1,6 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + moonlight-qt + rustdesk-flutter + ]; +} diff --git a/home-manager/misc/school.nix b/home-manager/misc/school.nix new file mode 100644 index 0000000..9b4630f --- /dev/null +++ b/home-manager/misc/school.nix @@ -0,0 +1,9 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + remmina + freerdp + globalprotect-openconnect + python3 + zoom-us + ]; +} diff --git a/home-manager/misc/useful.nix b/home-manager/misc/useful.nix new file mode 100644 index 0000000..cc9b824 --- /dev/null +++ b/home-manager/misc/useful.nix @@ -0,0 +1,13 @@ +{pkgs, ...}: { + home.packages = with pkgs; [ + imv + qbittorrent + libreoffice-fresh + vesktop + element-desktop + ffmpegthumbnailer + thunderbird + protonvpn-cli_2 + bc + ]; +} diff --git a/home-manager/services/gnome-keyring.nix b/home-manager/services/gnome-keyring.nix new file mode 100644 index 0000000..9b45e0d --- /dev/null +++ b/home-manager/services/gnome-keyring.nix @@ -0,0 +1,13 @@ +{pkgs, ...}: { + services.gnome-keyring = { + enable = true; + components = [ + "ssh" + ]; + }; + + home.packages = with pkgs; [ + gnome.gnome-keyring + gnome.libgnome-keyring + ]; +} diff --git a/home-manager/services/mako.nix b/home-manager/services/mako.nix new file mode 100644 index 0000000..c27324b --- /dev/null +++ b/home-manager/services/mako.nix @@ -0,0 +1,48 @@ +{pkgs, ...}: { + # Notification daemon + services.mako = let + colors = import ../style/colors.nix; + border = import ../common/border.nix; + displays = import ../common/displays.nix; + fonts = import ../common/fonts.nix; + in { + enable = true; + borderColor = "#${colors.accent}"; + backgroundColor = "#${colors.dark}CC"; + output = "${displays.d1}"; + sort = "+time"; + layer = "overlay"; + padding = "8"; + margin = "0"; + borderSize = border.weightInt; + maxIconSize = 40; + defaultTimeout = 6000; + font = "${fonts.main} 12"; + anchor = "bottom-right"; + extraConfig = "on-button-right=dismiss-all\nouter-margin=10\n[mode=do-not-disturb]\ninvisible=1"; + }; + + # Script to toggle notifications using mako + home.packages = let + makoToggle = pkgs.writeScriptBin "makotoggle" '' + # Run makoctl mode and store the output in a variable + mode_output=$(makoctl mode) + + # Extract the second line after "default" + mode_line=$(echo "$mode_output" | sed -n '/default/{n;p}') + + if [[ "$mode_line" == "do-not-disturb" ]]; then + # Notifications are disabled, so we enable them + makoctl mode -r do-not-disturb + notify-send --expire-time=1500 'Notifications Enabled' + else + # Notifications are enabled, so we disable them + notify-send --expire-time=1500 'Notifications Disabled' + sleep 2 + makoctl mode -a do-not-disturb + fi + ''; + in with pkgs; [ + makoToggle + ]; +} diff --git a/home-manager/services/reloadunits.nix b/home-manager/services/reloadunits.nix new file mode 100644 index 0000000..2cd1837 --- /dev/null +++ b/home-manager/services/reloadunits.nix @@ -0,0 +1,7 @@ +{ + # Nicely reload system units when changing configs + systemd.user = { + enable = true; + startServices = "sd-switch"; + }; +} diff --git a/home-manager/services/udiskie.nix b/home-manager/services/udiskie.nix new file mode 100644 index 0000000..6dc7210 --- /dev/null +++ b/home-manager/services/udiskie.nix @@ -0,0 +1,4 @@ +{ + # Automount with udisk2 + services.udiskie.enable = true; +} diff --git a/home-manager/style/colors.nix b/home-manager/style/colors.nix new file mode 100644 index 0000000..84bd09b --- /dev/null +++ b/home-manager/style/colors.nix @@ -0,0 +1,12 @@ +{ + # Global color palette + prime = ''3823C4''; #3823C4 + accent = ''1B1F59''; #1B1F59 + split = ''555B9E''; #555B9E + actSplit = ''5980B7''; #5980B7 + dark = ''101419''; #101419 + mid = ''171C23''; #171C23 + light = ''272b33''; #272B33 + urgent = ''C43823''; #C43823 + text = ''C7D3E3''; #C7D3E3 +} diff --git a/home-manager/style/gtk.nix b/home-manager/style/gtk.nix new file mode 100644 index 0000000..1eba478 --- /dev/null +++ b/home-manager/style/gtk.nix @@ -0,0 +1,70 @@ +{pkgs, ...}: { + # Define GTK theme settings + gtk = { + enable = true; + font = let + fonts = import ../common/fonts.nix; + in { + name = "${fonts.main}"; + size = 11; + }; + theme = { + name = "Colloid-Dark"; + package = pkgs.colloid-gtk-theme.override { + themeVariants = ["default"]; + colorVariants = ["dark"]; + sizeVariants = ["standard"]; + tweaks = ["black" "rimless" "normal"]; + }; + }; + iconTheme = { + package = pkgs.papirus-icon-theme.override {color = "indigo";}; + name = "Papirus-Dark"; + }; + cursorTheme = { + package = pkgs.simp1e-cursors; + name = "Simp1e-Dark"; + }; + + # GTK app bookmarks + gtk3 = { + bookmarks = [ + # Local + "file:///home/jimbo/Downloads" + "file:///home/jimbo/Documents" + "file:///home/jimbo/Videos" + "file:///home/jimbo/Pictures/Screenshots" + + # Remote + "file:///home/jimbo/JimboNFS/Downloads" + "file:///home/jimbo/JimboNFS/Documents" + "file:///home/jimbo/JimboNFS/Music" + "file:///home/jimbo/JimboNFS/Photos" + "file:///home/jimbo/JimboNFS/Videos" + "file:///home/jimbo/JimboNFS/Projects" + + # Links and mounts + "file:///home/jimbo/VMs" + + # More important stuff + "file:///home/jimbo/JimboNFS/School" + ]; + + # Disable shadows + extraCss = '' + * { outline-width: 0px; } + decoration { box-shadow: none; } + ''; + }; + + # Stop gtk4 from being rounded + gtk4.extraCss = '' + window { + border-top-left-radius:0; + border-top-right-radius:0; + border-bottom-left-radius:0; + border-bottom-right-radius:0; + } + ''; + }; +} diff --git a/home-manager/style/qt.nix b/home-manager/style/qt.nix new file mode 100644 index 0000000..1368714 --- /dev/null +++ b/home-manager/style/qt.nix @@ -0,0 +1,8 @@ +{pkgs, ...}: { + # Theme QT apps + qt = { + enable = true; + style.name = "gtk2"; + platformTheme.name = "gtk2"; + }; +} diff --git a/home-manager/sway/autostart.nix b/home-manager/sway/autostart.nix new file mode 100644 index 0000000..08ab834 --- /dev/null +++ b/home-manager/sway/autostart.nix @@ -0,0 +1,35 @@ +{config, pkgs, ...}: { + # Enable Sway and write some scripts + wayland.windowManager.sway = { + config = { + # Use Waybar rather than Sway's + bars = [{command = "waybar";}]; + + startup = [ + # Lock the screen on start, to allow an autostarted session + {command = "swaylock";} + + # Scratchpads + {command = "foot -a gotop -T Gotop gotop";} + {command = "foot -a music -T Music ncmpcpp";} + {command = "foot -a sound -T Sound pulsemixer";} + {command = "easyeffects";} + + # Daemons and tray apps + {command = "wl-paste -t text --watch clipman store -P";} + {command = "wl-copy";} + {command = "mako";} + {command = "${pkgs.rot8}/bin/rot8";} + + # Polkit agent + {command = "${pkgs.mate.mate-polkit}/libexec/polkit-mate-authentication-agent-1";} + + # Foreground apps + {command = "librewolf -P Misc --name=MiscBrowser";} + {command = "vesktop --ozone-platform-hint=auto";} + {command = "element-desktop";} + {command = "thunderbird";} + ]; + }; + }; +} diff --git a/home-manager/sway/hardware.nix b/home-manager/sway/hardware.nix new file mode 100644 index 0000000..c86b1a3 --- /dev/null +++ b/home-manager/sway/hardware.nix @@ -0,0 +1,62 @@ +{config, pkgs, ...}: { + # Enable Sway and write some scripts + wayland.windowManager.sway = { + config = let + displays = import ../common/displays.nix; + in { + # Define hardware + output = { + ${displays.d1} = { + pos = "1920 405"; + mode = "1920x1080@143.980Hz"; + max_render_time = "3"; + bg = "~/.wallpapers/1.png fill"; + scale = "1"; + adaptive_sync = "on"; + }; + ${displays.d2} = { + pos = "0 405"; + mode = "1920x1080@60Hz"; + max_render_time = "3"; + bg = "~/.wallpapers/2.png fill"; + }; + ${displays.d3} = { + pos = "3840 0"; + mode = "1680x1050@59.883Hz"; + transform = "270"; + max_render_time = "3"; + bg = "~/.wallpapers/3.png fill"; + }; + ${displays.dTouch} = { + #scale = "1.4"; + }; + "*" = { + bg = "~/.wallpapers/1.png fill"; + }; + }; + + # Mouse sensitivity, disable acceleration, allow touch while typing + input = { + "9610:4103:SINOWEALTH_Game_Mouse" = { + pointer_accel = "-0.9"; + }; + "9639:64097:Compx_2.4G_Receiver_Mouse" = { + pointer_accel = "-0.82"; + }; + "1452:627:bcm5974" = { + scroll_factor = "0.3"; + }; + "*" = { + accel_profile = "flat"; + dwt = "disabled"; + natural_scroll = "disabled"; + }; + + # Map touchscreen to output + "1386:806:Wacom_ISDv5_326_Finger" = { + map_to_output = "${displays.dTouch}"; + }; + }; + }; + }; +} diff --git a/home-manager/sway/hotkeys.nix b/home-manager/sway/hotkeys.nix new file mode 100644 index 0000000..f6dd96d --- /dev/null +++ b/home-manager/sway/hotkeys.nix @@ -0,0 +1,276 @@ +{config, pkgs, ...}: { + wayland.windowManager.sway = { + config = let + border = import ../common/border.nix; + colors = import ../style/colors.nix; + displays = import ../common/displays.nix; + nixcfg = import ../common/nixcfg.nix; + ws = import ./workspaces.nix; + + # Set default modifier and variables + primeMod = "Mod4"; + secMod = "Mod1"; + resizeAmount = ''55''; + sendNotif = ''notify-send --expire-time=1500''; + in { + # Hotkeys + modifier = "${primeMod}"; + keybindings = let + # Define scripts specific to Sway + pinWindow = pkgs.writeScript "pin-window" '' + # Get the current border style of the focused window + current_style=$(swaymsg -t get_tree | jq -r '.. | select(.focused?).border') + + # Toggle between "normal" (default) and "pixel ${border.weight}" border styles + if [ "$current_style" == "none" ]; then + swaymsg "sticky disable, border pixel ${border.weight}" + else + swaymsg "sticky enable, border none" + fi + ''; + + # Kill a window or probe it for info + swayTools = pkgs.writeScript "swaytools" '' + # List the app name and whether or not it uses wayland + swayprop() { + selected_window=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' | slurp -r -c ${colors.prime} -B 00000066 -b 00000000) + if [ -n "$selected_window" ]; then + app_id=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .app_id') + system=$(sed 's/xdg_shell/Wayland/g; s/xwayland/Xorg/g' < <(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .shell')) + notify-send "$(echo -e "Window's app_id: $app_id\nWindow System: $system")" + fi + } + + # Kill a selected window + swaykill() { + selected_window=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | "\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)"' | slurp -r -c ${colors.prime} -B 00000066 -b 00000000) + if [ -n "$selected_window" ]; then + pid=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | select("\(.rect.x),\(.rect.y) \(.rect.width)x\(.rect.height)" == "'"$selected_window"'") | .pid') + kill -9 "$pid" + fi + } + + # Handle which tool we use + if [ "$1" == "--prop" ]; then + swayprop + elif [ "$1" == "--kill" ]; then + swaykill + fi + ''; + in { + ## Launcher keys + + # LibreWolf profiles + "${primeMod}+F1" = ''exec librewolf -P Jimbo --name=JimBrowser | ${sendNotif} "Main Browser"''; + "${primeMod}+F2" = ''exec librewolf -P Alt --name=AltBrowser | ${sendNotif} "Alternate Browser"''; + "${primeMod}+F3" = ''exec librewolf -P Misc --name=MiscBrowser | ${sendNotif} "Miscellaneous Browser"''; + + # Discord + "${primeMod}+F4" = ''exec vesktop --ozone-platform-hint=auto | ${sendNotif} "Discord"''; + + # Games + "${primeMod}+F5" = ''exec steam | ${sendNotif} "Steam"''; + "${primeMod}+F6" = ''exec heroic | ${sendNotif} "Heroic Games"''; + + # Looking glass for VMs + "${primeMod}+F7" = ''exec looking-glass-client input:rawMouse=yes | ${sendNotif} "Looking Glass"''; + + # Virtual Machines + "${primeMod}+F10" = ''exec virt-manager | ${sendNotif} "Virtual Machines"''; + + # BeMenu scripts + "${primeMod}+F11" = ''exec rofiscripts --scratchpads | ${sendNotif} "Scratchpads"''; + "${primeMod}+${secMod}+Ctrl+r" = ''exec rofiscripts --resolutions''; + + # Open NixOS configuration files + "${primeMod}+F12" = ''exec foot ${nixcfg.open} | ${sendNotif} "Nix Config"''; + + # Terminal, rofi, clipmenu, media script, power menu, show/hide waybar + "${primeMod}+Return" = ''exec foot''; + "${primeMod}+s" = ''exec rofi -show run -p Command''; + "${primeMod}+c" = ''exec clipman pick -t rofi''; + "${primeMod}+x" = ''exec rofiscripts --power''; + "${primeMod}+b" = ''exec pkill -USR1 waybar''; + "${primeMod}+Escape" = ''exec ${swayTools} --kill''; + + # PCManFM, Emoji Picker, Rofi Launcher, Bluetooth, Ranger + "${primeMod}+Shift+t" = ''exec pcmanfm-qt''; + "${primeMod}+Shift+e" = ''exec BEMOJI_PICKER_CMD="rofi -dmenu -i -p Emoji" bemoji -n -P 0''; + "${primeMod}+Shift+s" = ''exec rofi -show drun -modi drun -drun-display-format {name} -show-icons -disable-history''; + "${primeMod}+Shift+b" = ''exec rofi-bluetooth''; + "${primeMod}+Shift+Return" = ''exec foot ranger''; + + # Swaytools prop, colorpicker, obs-cmd + "${primeMod}+Ctrl+x" = ''exec ${swayTools} --prop''; + "${primeMod}+Ctrl+c" = ''exec ${pkgs.hyprpicker}/bin/hyprpicker -an && ${sendNotif} "Color copied to clipboard"''; + "${primeMod}+Ctrl+Prior" = ''exec ${pkgs.obs-cmd}/bin/obs-cmd scene switch "Main"''; + "${primeMod}+Ctrl+Next" = ''exec ${pkgs.obs-cmd}/bin/obs-cmd scene switch "Guest"''; + + ## Media keys + + # Volume control + "XF86AudioRaiseVolume" = ''exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%+''; + "XF86AudioLowerVolume" = ''exec wpctl set-volume @DEFAULT_AUDIO_SINK@ 5%-''; + + # MPV volume control + "${secMod}+XF86AudioRaiseVolume" = ''exec mpc volume +3''; + "${secMod}+XF86AudioLowerVolume" = ''exec mpc volume -3''; + + # Mute, Stop + "XF86AudioMute" = ''exec wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle''; + "XF86AudioStop" = ''exec mpc stop''; + + # Play MPD, Firefox, or MPV + "XF86AudioPlay" = ''exec mpc toggle''; + "${secMod}+XF86AudioPlay" = ''exec playerctl --player=librewolf play-pause''; + "Ctrl+XF86AudioPlay" = ''exec playerctl --player=mpv play-pause''; + + # Next/Previous + "XF86AudioNext" = ''exec mpc next''; + "XF86AudioPrev" = ''exec mpc prev''; + + # Seek + "${secMod}+Shift+XF86AudioNext" = ''exec mpc seek +5''; + "${secMod}+Shift+XF86AudioPrev" = ''exec mpc seek -5''; + + ## Notification keys + + # Toggle mako + "${primeMod}+n" = ''exec makotoggle''; + "${primeMod}+Shift+n" = ''exec makoctl restore''; + "${primeMod}+Ctrl+n" = ''exec makoctl dismiss -a''; + + ## Miscellaneous keys + + # Screenshots + "Print" = ''exec swayshot --swappy''; + "${primeMod}+Shift+f" = ''exec swayshot --swappy''; + "Shift+Print" = ''exec swayshot --current''; + "Ctrl+Print" = ''exec swayshot --all''; + + # Server SSH + "${primeMod}+Ctrl+Return" = ''exec foot ssh server -p 2222''; + + # Display Brightness and Keyboard Brightness + "XF86MonBrightnessUp" = ''exec light -A 5''; + "XF86MonBrightnessDown" = ''exec light -U 5''; + "Shift+XF86MonBrightnessUp" = ''exec light -A 1''; + "Shift+XF86MonBrightnessDown" = ''exec light -U 1''; + "XF86KbdBrightnessUp" = ''exec light -s sysfs/leds/smc::kbd_backlight -A 5''; + "XF86KbdBrightnessDown" = ''exec light -s sysfs/leds/smc::kbd_backlight -U 5''; + + ## Window manager keys + "${primeMod}+q" = ''kill''; + "${primeMod}+Shift+r" = ''reload''; + + # Switch to workspaces + "${primeMod}+grave" = ''workspace ${ws.w0}''; + "${primeMod}+1" = ''workspace ${ws.w1}''; + "${primeMod}+2" = ''workspace ${ws.w2}''; + "${primeMod}+3" = ''workspace ${ws.w3}''; + "${primeMod}+4" = ''workspace ${ws.w4}''; + "${primeMod}+5" = ''workspace ${ws.w5}''; + "${primeMod}+6" = ''workspace ${ws.w6}''; + "${primeMod}+7" = ''workspace ${ws.w7}''; + "${primeMod}+8" = ''workspace ${ws.w8}''; + "${primeMod}+9" = ''workspace ${ws.w9}''; + + # Switch to alternate workspaces + "${secMod}+F1" = ''workspace ${ws.w1a}''; + "${secMod}+F2" = ''workspace ${ws.w2a}''; + "${secMod}+F3" = ''workspace ${ws.w3a}''; + "${secMod}+F4" = ''workspace ${ws.w4a}''; + "${secMod}+F5" = ''workspace ${ws.w5a}''; + "${secMod}+F6" = ''workspace ${ws.w6a}''; + "${secMod}+F7" = ''workspace ${ws.w7a}''; + "${secMod}+F8" = ''workspace ${ws.w8a}''; + "${secMod}+F9" = ''workspace ${ws.w9a}''; + + # Move window to and focus new workspace + "${primeMod}+Shift+grave" = ''move container to workspace ${ws.w0}; workspace ${ws.w0}''; + "${primeMod}+Shift+1" = ''move container to workspace ${ws.w1}; workspace ${ws.w1}''; + "${primeMod}+Shift+2" = ''move container to workspace ${ws.w2}; workspace ${ws.w2}''; + "${primeMod}+Shift+3" = ''move container to workspace ${ws.w3}; workspace ${ws.w3}''; + "${primeMod}+Shift+4" = ''move container to workspace ${ws.w4}; workspace ${ws.w4}''; + "${primeMod}+Shift+5" = ''move container to workspace ${ws.w5}; workspace ${ws.w5}''; + "${primeMod}+Shift+6" = ''move container to workspace ${ws.w6}; workspace ${ws.w6}''; + "${primeMod}+Shift+7" = ''move container to workspace ${ws.w7}; workspace ${ws.w7}''; + "${primeMod}+Shift+8" = ''move container to workspace ${ws.w8}; workspace ${ws.w8}''; + "${primeMod}+Shift+9" = ''move container to workspace ${ws.w9}; workspace ${ws.w9}''; + + # Move window to and focus new alternate workspace + "${secMod}+Shift+F1" = ''move container to workspace ${ws.w1a}; workspace ${ws.w1a}''; + "${secMod}+Shift+F2" = ''move container to workspace ${ws.w2a}; workspace ${ws.w2a}''; + "${secMod}+Shift+F3" = ''move container to workspace ${ws.w3a}; workspace ${ws.w3a}''; + "${secMod}+Shift+F4" = ''move container to workspace ${ws.w4a}; workspace ${ws.w4a}''; + "${secMod}+Shift+F5" = ''move container to workspace ${ws.w5a}; workspace ${ws.w5a}''; + "${secMod}+Shift+F6" = ''move container to workspace ${ws.w6a}; workspace ${ws.w6a}''; + "${secMod}+Shift+F7" = ''move container to workspace ${ws.w7a}; workspace ${ws.w7a}''; + "${secMod}+Shift+F8" = ''move container to workspace ${ws.w8a}; workspace ${ws.w8a}''; + "${secMod}+Shift+F9" = ''move container to workspace ${ws.w9a}; workspace ${ws.w9a}''; + + # Change focus across windows + "${primeMod}+Up" = ''focus up''; + "${primeMod}+Down" = ''focus down''; + "${primeMod}+Left" = ''focus left''; + "${primeMod}+Right" = ''focus right''; + + # Switch focus across outputs + "${primeMod}+j" = ''focus output ${displays.d2}''; + "${primeMod}+k" = ''focus output ${displays.d1}''; + "${primeMod}+l" = ''focus output ${displays.d3}''; + + # Move focused window + "${primeMod}+Shift+Up" = ''move up ${resizeAmount} px''; + "${primeMod}+Shift+Down" = ''move down ${resizeAmount} px''; + "${primeMod}+Shift+Left" = ''move left ${resizeAmount} px''; + "${primeMod}+Shift+Right" = ''move right ${resizeAmount} px''; + + # Move window across outputs + "${primeMod}+Shift+j" = ''move output ${displays.d2}; focus output ${displays.d2}''; + "${primeMod}+Shift+k" = ''move output ${displays.d1}; focus output ${displays.d1}''; + "${primeMod}+Shift+l" = ''move output ${displays.d3}; focus output ${displays.d3}''; + + # Change focus between floating/tiled, toggle floating + "${primeMod}+space" = ''focus mode_toggle''; + "${primeMod}+Shift+space" = ''floating toggle''; + + # Allow a window to be visible on all workspaces, toggle border + "${primeMod}+0" = ''exec ${pinWindow}''; + + # Toggle fullscreen + "${primeMod}+f" = ''fullscreen toggle''; + "${primeMod}+${secMod}+Ctrl+f" = ''fullscreen toggle global''; + + # Change container layout + "${primeMod}+w" = ''layout toggle split''; + "${primeMod}+e" = ''layout toggle tabbed stacking''; + + # Change split direction + "${primeMod}+h" = ''split h''; + "${primeMod}+v" = ''split v''; + + # Focus parent / child + "${primeMod}+a" = ''focus parent''; + "${primeMod}+d" = ''focus child''; + + # Resize windows + "${primeMod}+${secMod}+Up" = ''resize grow height ${resizeAmount} px or 5 ppt''; + "${primeMod}+${secMod}+Down" = ''resize shrink height ${resizeAmount} px or 5 ppt''; + "${primeMod}+${secMod}+Left" = ''resize shrink width ${resizeAmount} px or 5 ppt''; + "${primeMod}+${secMod}+Right" = ''resize grow width ${resizeAmount} px or 5 ppt''; + + # Adjust gap size + "${primeMod}+Shift+equal" = ''gaps inner current set 5''; + "${primeMod}+equal" = ''gaps inner current plus 5''; + "${primeMod}+minus" = ''gaps inner current minus 5''; + + # Scratchpads + "Ctrl+Shift+Escape" = ''[app_id="gotop"] scratchpad show, move position center, resize set 1216 888''; + "${primeMod}+Shift+m" = ''[app_id="music"] scratchpad show, move position center, resize set 1006 657''; + "${primeMod}+Shift+v" = ''[app_id="sound"] scratchpad show, move position center, resize set 1000 800''; + "${primeMod}+Shift+Backslash" = ''[app_id="com.github.wwmm.easyeffects"] scratchpad show, move position center, resize set 1000 800''; + }; + }; + }; +} diff --git a/home-manager/sway/rules.nix b/home-manager/sway/rules.nix new file mode 100644 index 0000000..638dbd7 --- /dev/null +++ b/home-manager/sway/rules.nix @@ -0,0 +1,112 @@ +{config, pkgs, ...}: { + # Enable Sway and write some scripts + wayland.windowManager.sway = { + config = let + border = import ../common/border.nix; + displays = import ../common/displays.nix; + ws = import ./workspaces.nix; + in { + # Assign workspaces to outputs + workspaceOutputAssign = let + workspaces1 = ["${ws.w0}" "${ws.w1}" "${ws.w2}" "${ws.w3}" "${ws.w1a}" "${ws.w2a}" "${ws.w3a}"]; + workspaces2 = ["${ws.w4}" "${ws.w5}" "${ws.w6}" "${ws.w4a}" "${ws.w5a}" "${ws.w6a}"]; + workspaces3 = ["${ws.w7}" "${ws.w8}" "${ws.w9}" "${ws.w7a}" "${ws.w8a}" "${ws.w9a}"]; + assign = output: workspaces: + map (workspace: { + inherit workspace; + inherit output; + }) + workspaces; + in + (assign "${displays.d1}" workspaces1) ++ (assign "${displays.d2}" workspaces2) ++ (assign "${displays.d3}" workspaces3); + + # Rules + window = { + border = border.weightInt; + titlebar = false; + commands = [ + # Scratchpads + { + criteria = {con_mark = "scratchpad";}; + command = ''floating enable, sticky enable, move scratchpad, mark borderless''; + } + { + criteria = {app_id = "gotop";}; + command = ''mark scratchpad''; + } + { + criteria = {app_id = "music";}; + command = ''mark scratchpad''; + } + { + criteria = {app_id = "sound";}; + command = ''mark scratchpad''; + } + { + criteria = {app_id = "com.github.wwmm.easyeffects";}; + command = ''mark scratchpad, opacity 0.9''; + } + + # Create a "Scratchpad" for apps I don't want to be seen when launched + { + criteria = {con_mark = "hiddenaway";}; + command = ''move scratchpad''; + } + + # Give apps that don't have them borders + { + criteria = {con_mark = "borderless";}; + command = ''border pixel ${border.weight}''; + } + { + criteria = {app_id = "com.github.wwmm.easyeffects";}; + command = ''mark borderless''; + } + { + criteria = {class = "steam";}; + command = ''mark borderless''; + } + { + criteria = {app_id = "swappy";}; + command = ''mark borderless''; + } + { + criteria = {app_id = "virt-manager";}; + command = ''mark borderless''; + } + { + criteria = {window_role = "pop-up";}; + command = ''mark borderless''; + } + + # Floating or fullscreen rules + { + criteria = {app_id = "float";}; + command = ''floating enable''; + } + { + criteria = {title = "^GlobalShot";}; + command = ''floating enable, fullscreen enable global''; + } + ]; + }; + assigns = { + # Browsers + "${ws.w1}" = [{app_id = "JimBrowser";}]; + "${ws.w1a}" = [{app_id = "AltBrowser";}]; + + # Communication + "${ws.w3a}" = [{class = "zoom";}]; + "${ws.w7}" = [{app_id = "MiscBrowser";} {app_id = "vesktop";}]; + "${ws.w8}" = [{class = "Element";}]; + "${ws.w9}" = [{app_id = "thunderbird";}]; + + # Else + "${ws.w2}" = [{class = "SDL Application";} {class = "heroic";}]; + "${ws.w2a}" = [{app_id = "looking-glass-client";}]; + "${ws.w4a}" = [{app_id = "com.obsproject.Studio";}]; + }; + focus.newWindow = "focus"; + }; + }; +} diff --git a/home-manager/sway/sway.nix b/home-manager/sway/sway.nix new file mode 100644 index 0000000..73ec5af --- /dev/null +++ b/home-manager/sway/sway.nix @@ -0,0 +1,42 @@ +{config, pkgs, ...}: { + # Import modules + imports = [ + #"./swayfx.nix" + ./hardware.nix + ./theme.nix + ./hotkeys.nix + ./rules.nix + ./autostart.nix + ./swaylock.nix + ./waybar.nix + ./swayshot.nix + ]; + + # Enable Sway and write some scripts + wayland.windowManager.sway = { + enable = true; + #package = pkgs.unstable.swayfx; + wrapperFeatures.gtk = true; + checkConfig = false; + extraConfig = let + border = import ../common/border.nix; + ws = import ./workspaces.nix; + in '' + # Options I can't find in Nix yet + default_floating_border pixel ${border.weight} + hide_edge_borders --i3 smart + titlebar_padding 10 1 + primary_selection disabled + + # Include extra window icons + include ${pkgs.fetchurl { + url = "https://raw.githubusercontent.com/iguanajuice/sway-font-awesome/6b7a9d08974eea1b9cddb8d444e1c89d6837083a/icons"; + sha256 = "09ki5qw1h91kd33k3fwzq7cb6ck8sq4haswgizrsy387sfr2a75x"; + }} + + # Switch to workspace 1 + workspace ${ws.w7} + workspace ${ws.w1} + ''; + }; +} diff --git a/home-manager/sway/swayfx.nix b/home-manager/sway/swayfx.nix new file mode 100644 index 0000000..5390490 --- /dev/null +++ b/home-manager/sway/swayfx.nix @@ -0,0 +1,14 @@ +{config, pkgs, ...}: { + # Enable Sway and write some scripts + wayland.windowManager.sway = { + package = pkgs.unstable.sway; + extraConfig = '' + # SwayFX specific options + blur enable + blur_passes 3 + blur_radius 5 + layer_effects 'rofi' blur enable + layer_effects 'notifications' blur enable; blur_ignore_transparent enable + ''; + }; +} diff --git a/home-manager/sway/swaylock.nix b/home-manager/sway/swaylock.nix new file mode 100644 index 0000000..4cf2bf3 --- /dev/null +++ b/home-manager/sway/swaylock.nix @@ -0,0 +1,61 @@ +{config, pkgs, ...}: let + swayLock = let + colors = import ../style/colors.nix; + fonts = import ../common/fonts.nix; + in pkgs.writeScriptBin "swaylock" '' + # Set the lock script + lockscript() { + BLANK='#00000000' + CLEAR='#FFFFFF22' + DEFAULT='#${colors.prime}FF' + TEXT='#FFFFFFFF' + WRONG='#${colors.split}FF' + VERIFYING='#${colors.accent}FF' + + ${pkgs.swaylock-effects}/bin/swaylock -f -e \ + --key-hl-color=$VERIFYING \ + --bs-hl-color=$WRONG \ + \ + --ring-clear-color=$CLEAR \ + --ring-ver-color=$VERIFYING \ + --ring-wrong-color=$WRONG \ + --ring-color=$DEFAULT \ + --ring-clear-color=$VERIFYING \ + \ + --inside-color=$CLEAR \ + --inside-ver-color=$CLEAR \ + --inside-wrong-color=$CLEAR \ + --inside-clear-color=$CLEAR \ + \ + --text-color=$TEXT \ + --text-clear-color=$TEXT \ + --text-ver-color=$TEXT \ + --text-caps-lock-color=$TEXT \ + --text-wrong-color=$TEXT \ + \ + --indicator \ + --indicator-radius=80 \ + --image=~/.wallpapers/lock.png \ + --clock \ + --font=${fonts.main} \ + --font-size=30 \ + --timestr="%I:%M%p" \ + --datestr="%a %b %d %Y" + } + + # Handle whether to lock or sleep + if [ "$1" == "--sleep" ]; then + lockscript & + exec ${pkgs.swayidle}/bin/swayidle -w \ + timeout 1 'swaymsg "output * dpms off"' \ + resume 'swaymsg "output * dpms on"; pkill -9 swayidle' + else + lockscript + fi + ''; +in { + # Enable Sway and write some scripts + home.packages = with pkgs; [ + swayLock + ]; +} diff --git a/home-manager/sway/swayshot.nix b/home-manager/sway/swayshot.nix new file mode 100644 index 0000000..c292a42 --- /dev/null +++ b/home-manager/sway/swayshot.nix @@ -0,0 +1,87 @@ +{pkgs, ...}: { + home.packages = let + # Use grim and slurp to take screenshots in multiple ways + swayShot = let + border = import ../common/border.nix; + colors = import ../style/colors.nix; + in pkgs.writeScriptBin "swayshot" '' + # Swappy + handle_swappy() { + # Create an imv window to act as a static screen + grim -t jpeg - | imv -w "GlobalShot" - & imv_pid=$! + + # Capture the screenshot of the selected area and save to a temporary file + selected_area=$(swaymsg -t get_tree | jq -r '.. | select(.pid? and .visible?) | .rect | "\(.x),\(.y) \(.width)x\(.height)"'\ + | XCURSOR_SIZE=40 slurp -w ${border.weight} -c ${colors.prime} -B 00000066 -b 00000099) + temp_file=$(mktemp -u).png + grim -g "$selected_area" "$temp_file" + + # Kill the imv window + kill $imv_pid + + # Copy the screenshot to the clipboard + swappy -f - < "$temp_file" + + # Clean up the temporary file + rm "$temp_file" + } + + # Current + handle_current() { + # Take a screenshot and save it to the temporary file + temp_file=$(mktemp -u).png + grim -o $(swaymsg -t get_outputs | jq -r '.[] | select(.focused) | .name') "$temp_file" + + # Check if the screenshot was successfully taken + if [ $? -eq 0 ]; then + # Copy the screenshot to the clipboard + wl-copy < "$temp_file" + + # Show a notification with the screenshot + notify-send -i "$temp_file" "Current screen copied." + + # Remove the temporary file + rm "$temp_file" + else + # If the screenshot capture failed, show an error notification + notify-send "Error: Unable to capture screenshot." + fi + } + + # All screens + handle_all() { + # Take a screenshot and save it to the temporary file + temp_file=$(mktemp -u).png + grim -t jpeg "$temp_file" + + # Check if the screenshot was successfully taken + if [ $? -eq 0 ]; then + # Copy the screenshot to the clipboard + wl-copy < "$temp_file" + + # Show a notification with the screenshot + notify-send -i "$temp_file" "All screen copied." + + # Remove the temporary file + rm "$temp_file" + else + # If the screenshot capture failed, show an error notification + notify-send "Error: Unable to capture screenshot." + fi + } + + # Check for command-line arguments + if [ "$1" == "--swappy" ]; then + handle_swappy + elif [ "$1" == "--current" ]; then + handle_current + elif [ "$1" == "--all" ]; then + handle_all + else + echo "Please use the arguments swappy, current, or all." + fi + ''; + in with pkgs; [ + swayShot + ]; +} diff --git a/home-manager/sway/theme.nix b/home-manager/sway/theme.nix new file mode 100644 index 0000000..3f4bbee --- /dev/null +++ b/home-manager/sway/theme.nix @@ -0,0 +1,53 @@ +{config, pkgs, ...}: { + # Enable Sway and write some scripts + wayland.windowManager.sway = { + enable = true; + #package = pkgs.unstable.sway; + wrapperFeatures.gtk = true; + checkConfig = false; + config = let + colors = import ../style/colors.nix; + fonts = import ../common/fonts.nix; + in { + # Theming settings + colors = { + focused = { + border = "#${colors.prime}"; + background = "#${colors.prime}"; + text = "#FFFFFF"; + indicator = "#${colors.actSplit}"; + childBorder = "#${colors.prime}"; + }; + focusedInactive = { + border = "#${colors.accent}"; + background = "#${colors.accent}"; + text = "#${colors.text}"; + indicator = "#${colors.split}"; + childBorder = "#${colors.accent}"; + }; + unfocused = { + border = "#${colors.dark}"; + background = "#${colors.dark}"; + text = "#${colors.text}"; + indicator = "#${colors.split}"; + childBorder = "#${colors.split}"; + }; + urgent = { + border = "#${colors.urgent}"; + background = "#${colors.urgent}"; + text = "#${colors.text}"; + indicator = "#${colors.urgent}"; + childBorder = "#${colors.urgent}"; + }; + }; + fonts = { + names = ["${fonts.main}"]; + size = 10.5; + }; + gaps = { + inner = 5; + smartGaps = true; + }; + }; + }; +} diff --git a/home-manager/sway/waybar.nix b/home-manager/sway/waybar.nix new file mode 100644 index 0000000..e60f4c4 --- /dev/null +++ b/home-manager/sway/waybar.nix @@ -0,0 +1,484 @@ +{pkgs, ...}: { + programs.waybar = let + colors = import ../style/colors.nix; + displays = import ../common/displays.nix; + fonts = import ../common/fonts.nix; + + swayWorkspacesModule = { + format = "{name}"; + enable-bar-scroll = true; + warp-on-scroll = false; + disable-scroll-wraparound = true; + }; + + swayWindowsModule = { + icon = true; + icon-size = 15; + all-outputs = true; + tooltip = false; + rewrite = { + "(.*) — LibreWolf" = " $1"; + "LibreWolf" = " Firefox"; + "(.*) - LibreWolf — Firefox" = "󰗃 $1"; + }; + }; + + pulseModule = { + format = "{icon} {volume}%"; + format-bluetooth = "{icon} {volume}%"; + format-muted = " muted"; + format-icons = { + headphone = "󰋋 "; + headset = "󰋋 "; + default = [" " " "]; + }; + on-click = "wpctl set-mute @DEFAULT_AUDIO_SINK@ toggle"; + on-click-middle = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 100%"; + on-click-right = "wpctl set-volume @DEFAULT_AUDIO_SINK@ 60%"; + ignored-sinks = ["Easy Effects Sink" "USB FS AUDIO Analog Stereo"]; + }; + + # CPU, Ram and Vram + cpuModule = { + format = " {usage}%"; + interval = 3; + }; + ramModule = { + format = " {used}G"; + tooltip = false; + }; + vramModule = { + exec = pkgs.writeScript "vramScript" '' + # Don't run the script if running on integrated graphics + if lspci -k | grep "Kernel driver in use: nvidia" &> /dev/null || lspci -k | grep "Kernel driver in use: amdgpu" &> /dev/null; then + + # Run the nvidia-smi command and capture the VRAM usage and GPU utilization output + if lspci -k | grep "Kernel driver in use: nvidia" &> /dev/null; then + vram_usage_mb=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits) + temperature=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits) + + # Check the drm memory if an AMD GPU is present + elif lspci -k | grep "Kernel driver in use: amdgpu" &> /dev/null; then + vram_usage_mb=$(echo "$(cat /sys/class/drm/card0/device/mem_info_vram_used || cat /sys/class/drm/card1/device/mem_info_vram_used) / 1024 / 1024" | bc) + temperature=$(sensors | grep 'edge' | awk '{print $2}' | sed 's/[^0-9.-]//g') + fi + + # Check if VRAM usage is under 1GB + if [ $vram_usage_mb -lt 1024 ]; then + vram_usage_display="$(echo $vram_usage_mb)M" + else + # Convert MB to GiB + vram_usage_gib=$(bc <<< "scale=2; $vram_usage_mb / 1024") + vram_usage_display="$(echo $vram_usage_gib)G" + fi + + # Print the VRAM usage in MB or GiB, and include GPU utilization and temperature + echo "{\"text\":\"󰢮 $(echo $vram_usage_display)\",\"tooltip\":\"$(echo $temperature)°C\"}" + else + : + fi + ''; + format = "{}"; + return-type = "json"; + interval = 3; + }; + + # Clocks + longClockModule = { + exec = pkgs.writeScript "longClock" '' + # Long clock format, with a numeric date and military time tooltip + time=$(date +'%a %b %d %l:%M:%S%p' | tr -s ' ') + date=$(date "+%Y-%m-%d") + echo "{\"text\":\" $time\",\"tooltip\":\"$date\"}" + ''; + on-click = ''wl-copy $(date "+%Y-%m-%d-%H%M%S"); notify-send "Date copied."''; + format = "{}"; + return-type = "json"; + interval = 1; + tooltip = true; + }; + shortClockModule = { + exec = "echo ' '$(date +'%l:%M%p' | sed 's/^ //')"; + on-click = ''wl-copy $(date "+%Y-%m-%d-%H%M%S"); notify-send "Date copied."''; + interval = 60; + tooltip = false; + }; + + # Tray, gamemode, bluetooth, and network tray modules + trayModule = { + spacing = 5; + }; + networkModule = { + format-ethernet = "󰈀"; + format-wifi = ""; + format-disconnected = "󰖪"; + format-linked = ""; + tooltip-format-ethernet = "{ipaddr}\n{ifname} "; + tooltip-format-wifi = "{ipaddr}\n{essid} ({signalStrength}%)"; + tooltip-format-disconnected = "Disconnected"; + }; + bluetoothModule = { + format = ""; + format-disabled = ""; + format-no-controller = ""; + tooltip-format-on = "No devices connected."; + tooltip-format-connected = "{num_connections} connected\n{device_enumerate}"; + tooltip-format-enumerate-connected = "{device_alias}"; + tooltip-format-enumerate-connected-battery = "{device_alias} {device_battery_percentage}%"; + on-click = "rofi-bluetooth"; + }; + scratchpadModule = { + format = " {count}"; + show-empty = false; + tooltip = true; + tooltip-format = "{title}"; + }; + gamemodeModule = { + format = "{glyph}"; + glyph = "󰖺"; + hide-not-running = true; + use-icon = true; + icon-spacing = 3; + icon-size = 19; + tooltip = true; + tooltip-format = "Gamemode On"; + }; + + # Special per-bar modules + mediaModule = { + exec-if = "mpc status | grep -q '^\\[playing\\] \\|^\\[paused\\]'"; + exec = pkgs.writeScript "mpvMetadata" '' + get_metadata() { + mpc --format "%file%" | head -n 1 | sed -E 's/\.(mp3|mp4|m4a|mov|flac|opus|oga)$//; s/&/&/g' + } + + truncate_string() { + local str="$1" + local max_length=30 + if [ $(expr length "$str") -gt $max_length ]; then + str=$(expr substr "$str" 1 $max_length)... + fi + echo "$str" + } + + if mpc status 2>/dev/null | grep -q playing; then + song_name=$(get_metadata | awk -F ' - ' '{print $2}') + if [ -z "$song_name" ]; then + song_name=$(get_metadata) + fi + echo "{\"text\":\"$(truncate_string " $song_name")\",\"tooltip\":\"$(get_metadata)\"}" + elif mpc status 2>/dev/null | grep -q paused; then + artist_name=$(get_metadata | awk -F ' - ' '{print $1}') + if [ -z "$artist_name" ]; then + artist_name=$(get_metadata) + fi + echo "{\"text\":\"$(truncate_string " $artist_name")\",\"tooltip\":\"$(get_metadata)\",\"class\":\"paused\"}" + fi + ''; + format = "{}"; + return-type = "json"; + interval = 2; + max-length = 30; + on-click = "mpc toggle"; + }; + notificationModule = { + exec = pkgs.writeScript "notificationScript" '' + # Run makoctl mode and store the output in a variable + mode_output=$(makoctl mode) + + # Extract the second line after "default" + mode_line=$(echo "$mode_output" | sed -n '/default/{n;p}') + + # Print the notification status with the tooltip + if [[ "$mode_line" == "do-not-disturb" ]]; then + printf '{"text":"󱆥 Off","class":"disabled","tooltip":"Notifications Disabled."}' + else + printf '{"text":" On","tooltip":"Notifications Enabled."}'; + fi + ''; + format = "{}"; + return-type = "json"; + interval = 2; + on-click = "makotoggle"; + }; + weatherModule = { + exec = pkgs.writeScript "weatherScript" '' + # Define variables + CITY="Maple" + API_KEY="18be8db3528f08c33ed9f95698335ea7" + + # Fetch weather data + weather_data=$(curl -s "http://api.openweathermap.org/data/2.5/weather?q=$CITY&appid=$API_KEY") + weather_condition=$(echo $weather_data | jq -r '.weather[0].main') + + # Map weather conditions to emojis + case "$weather_condition" in + "Clear") emoji="☀️";; + "Clouds") emoji="☁️";; + "Rain") emoji="🌧️";; + "Drizzle") emoji="🌦️";; + "Thunderstorm") emoji="⛈️";; + "Snow") emoji="❄️";; + "Mist"|"Fog"|"Haze") emoji="🌫️";; + *) emoji="🌍";; # Default emoji for unknown + esac + + # Extract and format temperature in Celsius + temperature_kelvin=$(echo $weather_data | jq -r '.main.temp') + temperature_celsius=$(echo "$temperature_kelvin - 273.15" | bc) + formatted_temperature=$(printf "%.0f" $temperature_celsius) + + # Display weather emoji and temperature + echo {\"text\":\"$emoji $formatted_temperature°C\",\"tooltip\":\"Weather in $CITY: $weather_condition\"} + ''; + format = "{}"; + return-type = "json"; + on-click = "xdg-open https://openweathermap.org/city/6173577 | notify-send 'Opening weather'"; + interval = 150; + }; + + # Laptop modules + backlightModule = { + format = "{icon} {percent}%"; + format-icons = ["" "󰖨"]; + tooltip = false; + }; + batteryModule = { + interval = 60; + states = { + warning = 30; + critical = 15; + }; + format = "{icon} {capacity}%"; + format-icons = ["" "" "" "" ""]; + }; + in { + enable = true; + settings = { + display1 = { + name = "bar1"; + position = "top"; + layer = "bottom"; + output = [displays.d1 "VGA-1"]; + modules-left = ["sway/workspaces" "sway/window"]; + modules-right = [ + "pulseaudio" + "cpu" + "memory" + "custom/vram" + "custom/clock-long" + "gamemode" + "sway/scratchpad" + "tray" + "bluetooth" + "network" + ]; + "sway/workspaces" = swayWorkspacesModule; + "sway/window" = swayWindowsModule; + "pulseaudio" = pulseModule; + "cpu" = cpuModule; + "memory" = ramModule; + "custom/vram" = vramModule; + "custom/clock-long" = longClockModule; + "gamemode" = gamemodeModule; + "sway/scratchpad" = scratchpadModule; + "tray" = trayModule; + "bluetooth" = bluetoothModule; + "network" = networkModule // {interface = "enp*";}; + }; + display2 = { + name = "bar2"; + position = "top"; + layer = "bottom"; + output = [displays.d2]; + modules-left = ["sway/workspaces" "sway/window"]; + modules-right = [ + "pulseaudio" + "custom/media" + "custom/notifs" + "cpu" + "memory" + "custom/vram" + "custom/clock-long" + ]; + "sway/workspaces" = swayWorkspacesModule; + "sway/window" = swayWindowsModule; + "pulseaudio" = pulseModule; + "custom/media" = mediaModule; + "custom/notifs" = notificationModule; + "cpu" = cpuModule; + "memory" = ramModule; + "custom/vram" = vramModule; + "custom/clock-long" = longClockModule; + }; + display3 = { + name = "bar3"; + position = "top"; + layer = "bottom"; + output = [displays.d3]; + modules-left = ["sway/workspaces" "sway/window"]; + modules-right = [ + "pulseaudio" + "custom/weather" + "cpu" + "memory" + "custom/vram" + "custom/clock-short" + ]; + "sway/workspaces" = swayWorkspacesModule; + "sway/window" = swayWindowsModule; + "pulseaudio" = pulseModule; + "custom/weather" = weatherModule; + "cpu" = cpuModule; + "memory" = ramModule; + "custom/vram" = vramModule; + "custom/clock-short" = shortClockModule; + }; + displayLap = { + name = "laptop"; + position = "top"; + layer = "bottom"; + output = ["eDP-1" "LVDS-1" "DSI-1" "HDMI-A-1"]; + modules-left = ["sway/workspaces" "sway/window"]; + modules-right = [ + "pulseaudio" + "custom/media" + "custom/notifs" + "custom/weather2" + "cpu" + "memory" + "custom/vram" + "backlight" + "battery" + "custom/clock-long" + "gamemode" + "sway/scratchpad" + "tray" + "bluetooth" + "network" + ]; + "sway/workspaces" = swayWorkspacesModule; + "sway/window" = swayWindowsModule; + "pulseaudio" = pulseModule; + "custom/media" = mediaModule; + "custom/notifs" = notificationModule; + "custom/weather2" = weatherModule; + "cpu" = cpuModule; + "memory" = ramModule; + "custom/vram" = vramModule; + "backlight" = backlightModule; + "battery" = batteryModule; + "custom/clock-long" = longClockModule; + "sway/scratchpad" = scratchpadModule; + "tray" = trayModule; + "bluetooth" = bluetoothModule; + "network" = networkModule; + }; + }; + style = '' + * { + border: 0; + border-radius: 0; + min-height: 0; + font-family: ${fonts.main}, ${fonts.nerd}; + font-size: 15.5px; + color: #${colors.text}; + } + #waybar { + background: #${colors.dark}; + } + #workspaces { + padding: 0 6px 0 0; + } + #tray { + padding: 0 2px 0 5px; + } + #network { + padding: 0 10px 0 4px; + } + #network.disconnected,#bluetooth.off { + color: #424242; + } + #bluetooth { + margin: 0 6px 0 4px; + font-size: 13.4px; + } + #workspaces button { + padding: 0 3px; + color: white; + border-bottom: 3px solid transparent; + min-width: 20px; + } + #workspaces button.visible { + border-bottom: 3px solid #${colors.prime}; + background: #${colors.mid}; + } + #workspaces button.urgent { + border-bottom: 3px solid #${colors.urgent}; + } + #workspaces button:hover { + box-shadow: none; + background: #${colors.light}; + } + #scratchpad { + margin-left: 2px; + } + #cpu { + border-bottom: 3px solid #f90000; + margin: 0 5px 0 2px; + } + #memory { + border-bottom: 3px solid #4bffdc; + margin: 0 5px 0 2px; + } + #custom-vram { + border-bottom: 3px solid #33FF00; + margin: 0 5px 0 2px; + } + #custom-media { + border-bottom: 3px solid #ffb066; + margin: 0 5px 0 2px; + } + #custom-clock-long { + border-bottom: 3px solid #0a6cf5; + margin: 0 5px 0 2px; + } + #custom-clock-short { + border-bottom: 3px solid #0a6cf5; + margin: 0 5px 0 2px; + } + #backlight { + border-bottom: 3px solid #5ffca3; + margin: 0 5px 0 2px; + } + #battery { + border-bottom: 3px solid #fcfc16; + margin: 0 5px 0 2px; + } + #custom-media.paused { + color: #888; + } + #custom-weather { + border-bottom: 3px solid #${colors.prime}; + margin: 0 5px 0 2px; + } + #custom-weather2 { + border-bottom: 3px solid #c75bd3; + margin: 0 5px 0 2px; + } + #custom-notifs { + border-bottom: 3px solid #${colors.prime}; + margin: 0 5px 0 2px; + } + #custom-notifs.disabled { + color: #888; + } + #pulseaudio { + margin-right: 5px; + } + #pulseaudio.muted { + color: #424242; + } + ''; + }; +} diff --git a/home-manager/sway/workspaces.nix b/home-manager/sway/workspaces.nix new file mode 100644 index 0000000..1183507 --- /dev/null +++ b/home-manager/sway/workspaces.nix @@ -0,0 +1,22 @@ +{ + # Define the workspace names + w0 = ''0:0''; + w1 = ''1:1''; + w2 = ''2:2''; + w3 = ''3:3''; + w4 = ''4:4''; + w5 = ''5:5''; + w6 = ''6:6''; + w7 = ''7:7''; + w8 = ''8:8''; + w9 = ''9:9''; + w1a = ''11:I''; + w2a = ''22:II''; + w3a = ''33:III''; + w4a = ''44:IV''; + w5a = ''55:V''; + w6a = ''66:VI''; + w7a = ''77:VII''; + w8a = ''88:VIII''; + w9a = ''99:IX''; +} diff --git a/home-manager/tuiapps/fastfetch.nix b/home-manager/tuiapps/fastfetch.nix new file mode 100644 index 0000000..450fd8c --- /dev/null +++ b/home-manager/tuiapps/fastfetch.nix @@ -0,0 +1,156 @@ +{pkgs, ...}: { + home = { + file = let + # Neofetch main config + neoConf = '' + { + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "source": "xenia", + "color": { + "1": "1;97", + "2": "red", + "3": "yellow" + } + }, + "display": { + "separator": " \u001b[33m ", + "color": "red" + }, + "modules": [ + { + "type": "custom", + "format": "\u001b[1m—————————————————————————————————————" + }, + { + "type": "host", + "format": "{5} {2}", + "key": "󰌢 " + }, + { + "type": "cpu", + "key": " " + }, + { + "type": "gpu", + "key": "󰢮 " + }, + { + "type": "disk", + "folders": "/", + "key": " " + }, + { + "type": "memory", + "format": "{/1}{-}{/}{/2}{-}{/}{} / {}", + "key": " " + }, + { + "type": "display", + "compactType": "original", + "key": "󰍹 " + }, + + { + "type": "custom", + "format": "\u001b[1m—————————————————————————————————————" + }, + { + "type": "os", + "format": "{3} {12}", + "key": "󰍛 " + }, + { + "type": "kernel", + "format": "{1} {2}", + "key": " " + }, + { + "type": "wm", + "key": " " + }, + { + "type": "shell", + "key": " " + }, + { + "type": "terminal", + "key": " " + }, + { + "type": "packages", + "key": "󰆧 " + }, + { + "type": "uptime", + "key": "󰅐 " + }, + { + "type": "command", + "text": "date -d @$(stat -c %W /) '+%a %b %d %r %Z %Y'", + "key": "󰶡 " + }, + + { + "type": "custom", + "format": "\u001b[1m—————————————————————————————————————" + }, + { + "type": "custom", + "format": "\u001b[90m󰮯 \u001b[31m󰊠 \u001b[32m󰊠 \u001b[33m󰊠 \u001b[34m󰊠 \u001b[35m󰊠 \u001b[36m󰊠 \u001b[37m󰊠" + } + ] + } + ''; + in { + # Fastfetch config + ".config/fastfetch/config.jsonc".text = neoConf; + }; + packages = let + # Small Neofetch config + pFetch = let + smallConf = pkgs.writeText "smallconf.jsonc" '' + { + "$schema": "https://github.com/fastfetch-cli/fastfetch/raw/dev/doc/json_schema.json", + "logo": { + "source": "nixos_small" + }, + "modules": [ + { + "type": "os", + "format": "{3} {12}", + "key": "󰍛 " + }, + { + "type": "host", + "format": "{5}", + "key": "󰌢 " + }, + { + "type": "kernel", + "format": "{1} {2}", + "key": " " + }, + { + "type": "uptime", + "key": "󰅐 " + }, + { + "type": "packages", + "key": "󰆧 " + }, + { + "type": "memory", + "format": "{/1}{-}{/}{/2}{-}{/}{} / {}", + "key": " " + } + ] + } + ''; + in pkgs.writeScriptBin "pfetch" + ''fastfetch --config ${smallConf}''; + in with pkgs; [ + fastfetch pFetch + ]; + }; +} diff --git a/home-manager/tuiapps/git.nix b/home-manager/tuiapps/git.nix new file mode 100644 index 0000000..6d56f17 --- /dev/null +++ b/home-manager/tuiapps/git.nix @@ -0,0 +1,11 @@ +{ + # Enable git and config + programs.git = let + secrets = import ../../nixos/common/secrets.nix; + in { + enable = true; + lfs.enable = true; + userName = secrets.jimUsername; + userEmail = secrets.jimEmail; + }; +} diff --git a/home-manager/tuiapps/ncmpcpp.nix b/home-manager/tuiapps/ncmpcpp.nix new file mode 100644 index 0000000..37019ac --- /dev/null +++ b/home-manager/tuiapps/ncmpcpp.nix @@ -0,0 +1,18 @@ +{pkgs, ...}: { + # Enable NCMPCPP + programs.ncmpcpp = { + enable = true; + settings = { + browser_sort_mode = "name"; + user_interface = "alternative"; + }; + }; + + # Enable Discord Music RPC + services.mpd-discord-rpc.enable = true; + + # Allow terminal control of mpd + home.packages = with pkgs; [ + mpc-cli + ]; +} diff --git a/home-manager/tuiapps/neovim.nix b/home-manager/tuiapps/neovim.nix new file mode 100644 index 0000000..ac6797a --- /dev/null +++ b/home-manager/tuiapps/neovim.nix @@ -0,0 +1,104 @@ +{pkgs, ...}: { + # Install Neovim and plugins + programs.neovim = { + enable = true; + defaultEditor = true; + viAlias = true; + vimAlias = true; + plugins = with pkgs.vimPlugins; [ + # Vim theme + vim-airline + vim-airline-themes + + # Internal clipboard + vim-vsnip + cmp-vsnip + + # Autocomplete manager + lspkind-nvim + + # Autocomplete plugins + cmp-nvim-lsp + cmp-buffer + cmp-path + cmp-cmdline + nvim-cmp + + # Hex color visualizer and color theme + nvim-colorizer-lua + vim-monokai-pro + ]; + extraConfig = let + # Import colors + colors = import ../style/colors.nix; + in '' + lua <'] = cmp.mapping.scroll_docs(-4), + [''] = cmp.mapping.scroll_docs(4), + [''] = cmp.mapping.complete(), + [''] = cmp.mapping.abort(), + [''] = cmp.mapping.confirm({ select = true }), -- Accept currently selected item. Set `select` to `false` to only confirm explicitly selected items. + }), + sources = cmp.config.sources({ + { name = 'nvim_lsp' }, + { name = 'vsnip' } + }, { + { name = 'buffer' }, + }) + }) + + -- Use buffer source for '/' and '?' + cmp.setup.cmdline({ '/', '?' }, { + mapping = cmp.mapping.preset.cmdline(), + sources = { + { name = 'buffer' } + } + }) + + -- Use cmdline & path source for ':' + cmp.setup.cmdline(':', { + mapping = cmp.mapping.preset.cmdline(), + sources = cmp.config.sources({ + { name = 'path' } + }, { + { name = 'cmdline' } + }) + }) + EOF + + colorscheme monokai_pro + let g:airline_theme='onedark' + let g:airline#extensions#tabline#enabled = 1 + hi Normal guibg=none ctermbg=235 + hi Visual guibg=#${colors.mid} ctermbg=238 + hi Pmenu guibg=#${colors.mid} ctermbg=238 + hi EndOfBuffer guibg=none ctermbg=235 + hi LineNr guibg=none ctermbg=none + lua require'colorizer'.setup() + + set nu rnu + set termguicolors + set mouse=a + + set undofile + set undodir=$HOME/.local/share/nvim/undo + set undolevels=100 + set undoreload=10000 + + nmap :bnext + nmap :bprev + nmap :bd + ''; + }; +} diff --git a/home-manager/tuiapps/pcs.nix b/home-manager/tuiapps/pcs.nix new file mode 100644 index 0000000..e353e65 --- /dev/null +++ b/home-manager/tuiapps/pcs.nix @@ -0,0 +1,30 @@ +{pkgs, inputs, ...}: { + # Select default apps + xdg.mimeApps.defaultApplications = { + "inode/directory" = ["pcmanfm-qt.desktop"]; + "text/plain" = ["nvim.desktop"]; + "image/png" = ["imv.desktop"]; + "image/jpeg" = ["imv.desktop"]; + "video/*" = ["mpv.desktop"]; + }; + + # Set dconf settings + dconf.settings = { + "org/gnome/desktop/interface/color-scheme" = { + color-scheme = "prefer-dark"; + }; + "org/virt-manager/virt-manager/connections" = { + autoconnect = ["qemu:///system"]; + uris = ["qemu:///system"]; + }; + }; + + home.file = let + alsoftConf = '' + drivers=pulse + ''; + in { + # Alsoft config + ".alsoftrc".text = alsoftConf; + }; +} diff --git a/home-manager/tuiapps/ranger.nix b/home-manager/tuiapps/ranger.nix new file mode 100644 index 0000000..81fe1e9 --- /dev/null +++ b/home-manager/tuiapps/ranger.nix @@ -0,0 +1,126 @@ +{pkgs, ...}: { + # Enable Ranger + programs.ranger = { + enable = true; + settings = { + preview_images = true; + preview_images_method = "sixel"; + dirname_in_tabs = true; + cd_tab_fuzzy = true; + autosave_bookmarks = false; + show_hidden = true; + wrap_scroll = true; + column_ratios = "2,2,4"; + hidden_filter = ''^\.|\.(?:pyc|pyo|bak|swp)$|^lost\+found$|^__(py)?cache__$''; + }; + rifle = [ + # Text editing + { + condition = ''ext xml|json|jsonc|m3u|m3u8|csv|tex|py|pl|rb|js|sh|php|md|nix''; + command = ''vim -- "$@"''; + } + + # Media + { + condition = ''mime ^image, has imv, X, flag f''; + command = ''imv -- "$@"''; + } + { + condition = ''mime ^video, terminal, has mpv''; + command = ''mpv -- "$@"''; + } + { + condition = ''mime ^video, terminal, has mpv''; + command = ''mpv --video-rotate=270 -- "$@"''; + } + { + condition = ''mime ^audio|ogg$, terminal, has mpv''; + command = ''mpv --no-audio-display -- "$@"''; + } + { + condition = ''mime ^audio|ogg$, terminal, has mpv''; + command = ''mpv --shuffle --no-audio-display -- "$@"''; + } + { + condition = ''ext x?html?|pdf, has librewolf, X, flag f''; + command = ''librewolf -- "$@"''; + } + { + condition = ''ext pptx?|od[dfgpst]|docx?|sxc|xlsx?|xlt|xlw|gnm|gnumeric, has libreoffice, X, flag f''; + command = ''libreoffice "$@"''; + } + + # Scripts + { + condition = ''sh''; + command = ''sh -- "$1"''; + } + { + condition = ''py''; + command = ''python -- "$1"''; + } + { + condition = ''pl''; + command = ''perl -- "$1"''; + } + { + condition = ''js''; + command = ''node -- "$1"''; + } + { + condition = ''php''; + command = ''php -- "$1"''; + } + + # Misc + { + condition = ''ext exe|msi''; + command = ''wine "$1"''; + } + { + condition = ''ext 7z|ace|ar|arc|bz2?|cab|cpio|cpt|deb|dgc|dmg|gz|iso|jar|pkg|rar|shar|tar|tgz|xar|xpi|xz|zip, has 7z''; + command = ''7z x -- "$@"''; + } + { + condition = ''label open, has xdg-open''; + command = ''xdg-open -- "$@"''; + } + ]; + plugins = [ + { + name = "devicons2"; + src = builtins.fetchGit { + url = "https://github.com/cdump/ranger-devicons2"; + rev = "9606009aa01743768b0f27de0a841f7d8fe196c5"; + }; + } + ]; + extraConfig = '' + default_linemode devicons2 + ''; + }; + + # Ranger's bookmarks + home.file = let + rangerBookmarks = '' + # Local files + k:/home/jimbo/Downloads + v:/home/jimbo/Videos + c:/home/jimbo/.config + L:/home/jimbo/.local + D:/mnt + n:/etc/nixos + + # Remote files + a:/home/jimbo/JimboNFS + K:/home/jimbo/JimboNFS/Downloads + p:/home/jimbo/JimboNFS/Photos + P:/home/jimbo/JimboNFS/Projects + V:/home/jimbo/JimboNFS/Videos/Random + m:/home/jimbo/JimboNFS/Music + s:/home/jimbo/JimboNFS/School + ''; + in { + ".local/share/ranger/bookmarks".text = rangerBookmarks; + }; +} diff --git a/home-manager/tuiapps/tmux.nix b/home-manager/tuiapps/tmux.nix new file mode 100644 index 0000000..3ff224a --- /dev/null +++ b/home-manager/tuiapps/tmux.nix @@ -0,0 +1,22 @@ +{ + # Enable tmux + programs.tmux = { + enable = true; + extraConfig = '' + set -g mouse on + set -g base-index 1 + set -g default-terminal "st-256color" + set -g history-limit 4096 + set -g set-titles on + set -g set-titles-string "#T" + set -g status on + set -g status-left "" + set -g status-position bottom + set -g status-right "#[bg=brightblack]#[fg=dark_purple] #T " + set -g status-style "bg=black" + setw -g pane-base-index 1 + setw -g window-status-format "#[bg=brightmagenta]#[fg=black] #I #[bg=brightblack]#[fg=white] #W " + setw -g window-status-current-format "#[bg=brightmagenta]#[fg=black] #I #[bg=white]#[fg=black] #W " + ''; + }; +} diff --git a/home-manager/tuiapps/zsh.nix b/home-manager/tuiapps/zsh.nix new file mode 100644 index 0000000..05992e9 --- /dev/null +++ b/home-manager/tuiapps/zsh.nix @@ -0,0 +1,52 @@ +{pkgs, ...}: { + programs.zsh = let + auth = import ../common/auth.nix; + nixcfg = import ../common/nixcfg.nix; + in { + enable = true; + autosuggestion.enable = true; + syntaxHighlighting.enable = true; + oh-my-zsh = { + enable = true; + plugins = ["git"]; + }; + shellAliases = { + # NixOS aliases + nixcfg = "${nixcfg.open}"; + nixclean = "${auth.method} nix-store --gc; nix-collect-garbage -d; notify-send 'NixOS store clean finished.'"; + nixpurge = "${auth.method} nix-collect-garbage --delete-old; notify-send 'NixOS generation removed.'"; + nixoptimize = "${auth.method} nix store optimise; notify-send 'NixOS store optimization finished.'"; + + # Shortcut aliases + neo = "clear && fastfetch"; + pfetch = "fastfetch --config ~/.config/fastfetch/small.jsonc"; + ip = "ip -c"; + ls = "${pkgs.eza}/bin/eza -a --color=always --group-directories-first --icons"; + nls = "/usr/bin/env ls"; + cat = "${pkgs.bat}/bin/bat --paging never"; + ncat = "/usr/bin/env cat"; + copycat = "wl-copy <"; + sunshinehost = "WAYLAND_DISPLAY=wayland-1 DISPLAY=:1 sunshine -0"; + seneca = "ssh jhampton1@matrix.senecapolytechnic.ca"; + + # Curl tools + myip = "curl ifconfig.co"; + + # Download from sources + ytdl = "yt-dlp --embed-thumbnail --embed-metadata --output \"%(title)s.%(ext)s\""; + ytmp4 = "ytdl --recode-video webm"; + ytm3u = "yt-dlp -gS proto:m3u8"; + opusdl = "ytdl --recode-video opus"; + ytopus = "opusdl --format 251"; + spotdl = "spotdl --m3u --format opus"; + + # Flakes + buildiso = "${pkgs.nixos-generators}/bin/nixos-generate -f install-iso -c /home/jimbo/Downloads/NixISO/configuration.nix"; + }; + initExtra = '' + ${pkgs.any-nix-shell}/bin/any-nix-shell zsh --info-right | source /dev/stdin; pfetch + setopt HIST_IGNORE_SPACE + setopt RM_STAR_WAIT + ''; + }; +} diff --git a/home-manager/users/jimbo.nix b/home-manager/users/jimbo.nix new file mode 100644 index 0000000..274b856 --- /dev/null +++ b/home-manager/users/jimbo.nix @@ -0,0 +1,11 @@ +{ + home = { + username = "jimbo"; + homeDirectory = "/home/jimbo"; + sessionVariables = { + EDITOR = "nvim"; + LIBVIRT_DEFAULT_URI = "qemu:///system"; + HISTCONTROL = "ignoreboth"; + }; + }; +} diff --git a/nixos/common/ips.nix b/nixos/common/ips.nix new file mode 100644 index 0000000..82e98a1 --- /dev/null +++ b/nixos/common/ips.nix @@ -0,0 +1,7 @@ +rec { + netInt = "eno1"; + localSpan = "10.0.0"; + server = "${localSpan}.2"; + pc = "${localSpan}.3"; + vm = "${localSpan}.4"; +} diff --git a/nixos/desktop.nix b/nixos/desktop.nix new file mode 100644 index 0000000..6800a43 --- /dev/null +++ b/nixos/desktop.nix @@ -0,0 +1,36 @@ +{ + imports = [ + # Base configs + ./modules/base.nix + ./users/jimbo.nix + + # Desktop only + ./desktop/misc.nix + ./desktop/sway.nix + ./desktop/printing.nix + ./desktop/gaming.nix + ./desktop/pipewire.nix + ./desktop/bluetooth.nix + ./desktop/firewall.nix + ./desktop/fonts.nix + + # Modules + ./modules/security.nix + ./modules/networking.nix + + # Hardware + ./hardware/machines/desktop.nix + ./hardware/nvidia.nix + ./hardware/opengl.nix + + # Services + ./services/openssh.nix + ./services/virtualisation.nix + ./services/udev.nix + ./services/sunshine.nix + ./services/mpd.nix + ]; + + services.openssh.ports = [2211]; + networking.hostName = "JimNixDesktop"; +} diff --git a/nixos/desktop/bluetooth.nix b/nixos/desktop/bluetooth.nix new file mode 100644 index 0000000..b519c76 --- /dev/null +++ b/nixos/desktop/bluetooth.nix @@ -0,0 +1,15 @@ +{ + # Enable Bluetooth + hardware.bluetooth = { + enable = true; + settings = { + General.Experimental = "true"; + Policy.AutoEnable = "true"; + }; + }; + + # Enable lingering for Bluetooth + systemd.tmpfiles.rules = [ + "f /var/lib/systemd/linger/jimbo" + ]; +} diff --git a/nixos/desktop/firewall.nix b/nixos/desktop/firewall.nix new file mode 100644 index 0000000..fd28138 --- /dev/null +++ b/nixos/desktop/firewall.nix @@ -0,0 +1,12 @@ +{ + # Networking settings + networking = { + # Enable firewall + firewall = { + allowPing = false; + extraInputRules = '' + ip saddr 10.0.0.2 accept comment "Accept Server Connections" + ''; + }; + }; +} diff --git a/nixos/desktop/fonts.nix b/nixos/desktop/fonts.nix new file mode 100644 index 0000000..b907165 --- /dev/null +++ b/nixos/desktop/fonts.nix @@ -0,0 +1,15 @@ +{pkgs, ...}: { + # Fonts + fonts = { + packages = with pkgs; [ + liberation_ttf + twitter-color-emoji + ubuntu_font_family + noto-fonts + sarasa-gothic + orbitron + (nerdfonts.override {fonts = ["UbuntuMono"];}) + ]; + fontconfig.defaultFonts.emoji = ["Twitter Color Emoji"]; + }; +} diff --git a/nixos/desktop/gaming.nix b/nixos/desktop/gaming.nix new file mode 100644 index 0000000..dc55f75 --- /dev/null +++ b/nixos/desktop/gaming.nix @@ -0,0 +1,23 @@ +{pkgs, ...}: { + # Enable Gamemode to boost games + programs.gamemode = { + enable = true; + settings.general.renice = 10; + }; + + # Enable hardware like the Steam Controller + hardware.steam-hardware.enable = true; + + # Enable the Steam client + programs.steam = { + enable = true; + remotePlay.openFirewall = true; + dedicatedServer.openFirewall = true; + extraPackages = with pkgs; [ + steam-run heroic prismlauncher + ]; + extraCompatPackages = with pkgs; [ + proton-ge-bin + ]; + }; +} diff --git a/nixos/desktop/misc.nix b/nixos/desktop/misc.nix new file mode 100644 index 0000000..b7b5b6a --- /dev/null +++ b/nixos/desktop/misc.nix @@ -0,0 +1,25 @@ +{pkgs, ...}: { + # Enable AppImages + programs.appimage = { + enable = true; + binfmt = true; + }; + + # Network mounts, automounts, and battery saver + services = { + gvfs.enable = true; + udisks2.enable = true; + tlp.enable = true; + }; + + # Security that only makes sense with a GUI + security = { + polkit.enable = true; + rtkit.enable = true; + }; + + # Install programs system-wide + environment.systemPackages = with pkgs; [ + cifs-utils + ]; +} diff --git a/nixos/desktop/pipewire.nix b/nixos/desktop/pipewire.nix new file mode 100644 index 0000000..c166b67 --- /dev/null +++ b/nixos/desktop/pipewire.nix @@ -0,0 +1,26 @@ +{pkgs, ...}: { + # Enabling sound + sound.enable = true; + + # Enable Pipewire + services = { + pipewire = { + enable = true; + audio.enable = true; + wireplumber = { + enable = true; + configPackages = [ + (pkgs.writeTextDir "share/wireplumber/wireplumber.conf.d/11-bluetooth-policy.conf" '' + wireplumber.settings = { bluetooth.autoswitch-to-headset-profile = false } + '') + ]; + }; + alsa = { + enable = true; + support32Bit = true; + }; + pulse.enable = true; + #jack.enable = true; + }; + }; +} diff --git a/nixos/desktop/printing.nix b/nixos/desktop/printing.nix new file mode 100644 index 0000000..842609a --- /dev/null +++ b/nixos/desktop/printing.nix @@ -0,0 +1,20 @@ +{pkgs, ...}: { + # Enable printing + services = { + printing = { + enable = true; + drivers = with pkgs; [hplip]; + webInterface = false; + }; + avahi = { + enable = true; + nssmdns4 = true; + openFirewall = true; + }; + }; + + # Install programs system-wide + environment.systemPackages = with pkgs; [ + system-config-printer + ]; +} diff --git a/nixos/desktop/school.nix b/nixos/desktop/school.nix new file mode 100644 index 0000000..2c2effd --- /dev/null +++ b/nixos/desktop/school.nix @@ -0,0 +1,13 @@ +{pkgs, ...}: { + # Install programs system-wide + environment.systemPackages = with pkgs; [ + remmina + freerdp + globalprotect-openconnect + python3 + zoom-us + ]; + + # Enable Globalprotect VPN + services.globalprotect.enable = true; +} diff --git a/nixos/desktop/sway.nix b/nixos/desktop/sway.nix new file mode 100644 index 0000000..a9f7f88 --- /dev/null +++ b/nixos/desktop/sway.nix @@ -0,0 +1,32 @@ +{pkgs, ...}: { + imports = [ + ./wayland.nix + ]; + + programs.sway = { + enable = true; + xwayland.enable = true; + extraPackages = with pkgs; [ + swaylock + swaybg + ]; + }; + + # Allow swaylock to function + security.pam.services.swaylock = {}; + + # Enable desktop portals for screengrab + xdg.portal = { + wlr = { + enable = true; + settings.screencast = { + max_fps = 60; + chooser_type = "simple"; + chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or -B 00000066 -b 00000099"; + }; + }; + extraPortals = with pkgs; [ + xdg-desktop-portal-gtk + ]; + }; +} diff --git a/nixos/desktop/wayland.nix b/nixos/desktop/wayland.nix new file mode 100644 index 0000000..250e4cc --- /dev/null +++ b/nixos/desktop/wayland.nix @@ -0,0 +1,63 @@ +{pkgs, ...}: { + services = { + # Configure greetd for "auto" login (single user only) + greetd = let + startSway = pkgs.writeScript "startsway" '' + # Use NVIDIA variables if drivers are in use + if lspci -k | grep "Kernel driver in use: nvidia" &> /dev/null; then + # NVIDIA/AMD variables + export LIBVA_DRIVER_NAME=nvidia + export GBM_BACKEND=nvidia-drm + export __GLX_VENDOR_LIBRARY_NAME=nvidia + export WLR_NO_HARDWARE_CURSORS=1 + else + : + fi + + # Sway/Wayland + export XDG_CURRENT_DESKTOP=sway + export QT_QPA_PLATFORM="wayland;xcb" + + # Start Sway + sway --unsupported-gpu + ''; + in { + enable = true; + restart = true; + settings = { + terminal = { + vt = 2; + switch = true; + }; + default_session = { + command = "${startSway}"; + user = "jimbo"; + }; + }; + }; + dbus.enable = true; + }; + + programs.xwayland = { + enable = true; + }; + + # Enable backlight and theme control + programs = { + dconf.enable = true; + light.enable = true; + }; + + # Packages needed for Wayland + environment.systemPackages = with pkgs; [ + wl-clipboard + wdisplays + clipman + libnotify + grim + slurp + swappy + jq + lm_sensors + ]; +} diff --git a/nixos/groups/nfs-share.nix b/nixos/groups/nfs-share.nix new file mode 100644 index 0000000..962d0f3 --- /dev/null +++ b/nixos/groups/nfs-share.nix @@ -0,0 +1,6 @@ +{ + # Define group for NFS access + users.groups = { + nfsShare = {}; + }; +} diff --git a/nixos/hardware/machines/desktop.nix b/nixos/hardware/machines/desktop.nix new file mode 100644 index 0000000..efc1863 --- /dev/null +++ b/nixos/hardware/machines/desktop.nix @@ -0,0 +1,136 @@ +# This file was initially made by 'nixos-generate-config', try not to edit too much +{ + config, + lib, + pkgs, + modulesPath, + ... +}: let + # Set common boot paramaters + commonKernelParams = [ + # Nvidia settings + "nvidia_drm.fbdev=1" + + # VM/GPU passthrough + "amd_iommu=on" + "iommu=pt" + "nested=1" + + # Virtualization nonsense + "transparent_hugepage=never" + + # Isolate devices into IOMMU groups + "pcie_acs_override=downstream,multifunction" + "pci=routeirq" + ]; +in { + imports = [ + (modulesPath + "/installer/scan/not-detected.nix") + ]; + + # Set all boot options + boot = { + # Set a kernel version and load/blacklist drivers + kernelPackages = pkgs.unstable.linuxPackages_zen; + blacklistedKernelModules = [ + "pcspkr" + ]; + kernel.sysctl."vm.max_map_count" = 2147483642; + kernelParams = commonKernelParams ++ [ + "vfio-pci.ids=10de:1f82,10de:10fa" + ]; + initrd = { + availableKernelModules = [ + "nvme" + "xhci_pci" + "ahci" + "usbhid" + "usb_storage" + "sd_mod" + ]; + kernelModules = [ + "vfio" + "vfio_pci" + "vfio_iommu_type1" + "kvm-amd" + ]; + }; + + # Manage supported filesystems + supportedFilesystems = { + ntfs = true; + zfs = lib.mkForce false; + }; + + # Modprobe settings + extraModprobeConfig = '' + options hid_apple fnmode=2 + ''; + + # Use the Systemd-Boot bootloader + loader.systemd-boot = { + enable = true; + netbootxyz.enable = true; + }; + }; + + # Additional entry to boot from the second GPU + specialisation = { + gputwo.configuration = { + boot.kernelParams = commonKernelParams ++ ["vfio-pci.ids=10de:2504,10de:228e"]; + }; + }; + + # Mount everything as necessary + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/f0786b07-8303-416f-87ff-276bfd696387"; + fsType = "bcachefs"; + }; + "/boot" = { + device = "/dev/disk/by-uuid/EF6D-9009"; + fsType = "vfat"; + }; + "/etc/libvirt" = { + device = "/dev/disk/by-label/Qemu"; + options = ["nosuid" "nodev" "nofail"]; + }; + "/var/lib/libvirt" = { + depends = ["/etc/libvirt"]; + device = "/etc/libvirt/varlibvirt"; + options = ["bind" "rw"]; + }; + "/mnt/Linux1" = { + device = "/dev/disk/by-label/Linux1"; + options = ["nosuid" "nodev" "nofail" "x-gvfs-show"]; + }; + "/mnt/Linux2" = { + device = "/dev/disk/by-label/Linux2"; + options = ["nosuid" "nodev" "nofail" "x-gvfs-show"]; + }; + "/mnt/Windows1" = { + device = "/dev/disk/by-label/Windows1"; + options = ["nosuid" "nodev" "noauto"]; + }; + "/mnt/Windows2" = { + device = "/dev/disk/by-label/Windows2"; + options = ["nosuid" "nodev" "noauto"]; + }; + "/home/jimbo/JimboNFS" = { + device = "server:/export/JimboNFS"; + fsType = "nfs4"; + options = ["x-systemd.automount" "_netdev" "nofail" "noauto"]; + }; + }; + + # Set the swap partition + swapDevices = [ + {device = "/dev/disk/by-uuid/2e4c5120-716d-4cdc-84a0-c9e6391760db";} + ]; + + # Enables DHCP on each ethernet and wireless interface. + networking.useDHCP = lib.mkDefault true; + + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.amd.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; +} diff --git a/nixos/hardware/machines/server.nix b/nixos/hardware/machines/server.nix new file mode 100644 index 0000000..24a0dd4 --- /dev/null +++ b/nixos/hardware/machines/server.nix @@ -0,0 +1,112 @@ +{ config, lib, pkgs, modulesPath, ... }: + +{ + imports = [ (modulesPath + "/installer/scan/not-detected.nix") ]; + + # Set all boot options + boot = { + blacklistedKernelModules = [ + "pcspkr" + ]; + initrd = { + availableKernelModules = [ + "xhci_pci" + "ehci_pci" + "ahci" + "nvme" + "usbhid" + "sd_mod" + "sr_mod" + ]; + kernelModules = [ + "kvm-intel" + ]; + }; + + # Use the Systemd-Boot bootloader + loader.systemd-boot = { + enable = true; + netbootxyz.enable = true; + }; + }; + + # Mounting options + fileSystems = { + "/" = { + device = "/dev/disk/by-uuid/8f81cab7-9381-4950-b77f-b85c5fdbad16"; + fsType = "ext4"; + }; + "/boot" = { + device = "/dev/disk/by-uuid/2034-754A"; + fsType = "vfat"; + }; + "/export/JimboNFS" = { + device = "/dev/disk/by-uuid/713fcd92-534c-4153-8e04-e0c6fe5f6a51"; + fsType = "ext4"; + noCheck = true; + }; + "/home/jimbo/JimboNFS" = { + device = "/export/JimboNFS"; + fsType = "none"; + options = [ "bind" ]; + }; + + # Atrocity of var bindmounts + "/mnt/nextcloud/data/JimboNFS" = { + device = "/export/JimboNFS"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/bitwarden_rs" = { + device = "/export/JimboNFS/System/var/lib/bitwarden_rs"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/gitea" = { + device = "/export/JimboNFS/System/var/lib/gitea"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/matrix-synapse" = { + device = "/export/JimboNFS/System/var/lib/matrix-synapse"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/nextcloud" = { + device = "/export/JimboNFS/System/var/lib/nextcloud"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/owncast" = { + device = "/export/JimboNFS/System/var/lib/owncast"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/docker/volumes/azuracast_station_data/_data/jimbops/media/Music" = { + device = "/export/JimboNFS/Music"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/private/pufferpanel/servers" = { + device = "/export/JimboNFS/System/var/lib/pufferpanel/servers"; + fsType = "none"; + options = [ "bind" ]; + }; + "/var/lib/mastodon" = { + device = "/export/JimboNFS/System/var/lib/mastodon"; + fsType = "none"; + options = [ "bind" ]; + }; + }; + swapDevices = [ + { device = "/dev/disk/by-uuid/ec422cad-bf93-4b15-b989-2c807f1073a4"; } + ]; + + # Enables DHCP on each ethernet and wireless interface. + networking.useDHCP = lib.mkDefault true; + + # Hardware settings + nixpkgs.hostPlatform = lib.mkDefault "x86_64-linux"; + hardware.cpu.intel.updateMicrocode = lib.mkDefault config.hardware.enableRedistributableFirmware; + boot.swraid.enable = true; +} diff --git a/nixos/hardware/nvidia.nix b/nixos/hardware/nvidia.nix new file mode 100644 index 0000000..6a1c28c --- /dev/null +++ b/nixos/hardware/nvidia.nix @@ -0,0 +1,11 @@ +{config, ... }: { + # Enable video drivers + services.xserver.videoDrivers = ["nvidia"]; + + hardware.nvidia = { + modesetting.enable = true; + nvidiaSettings = false; + package = config.boot.kernelPackages.nvidiaPackages.beta; + open = true; + }; +} diff --git a/nixos/hardware/opengl.nix b/nixos/hardware/opengl.nix new file mode 100644 index 0000000..58a57c1 --- /dev/null +++ b/nixos/hardware/opengl.nix @@ -0,0 +1,17 @@ +{ + config, + pkgs, + ... +}: { + # Enable OpenGL + hardware.opengl = { + enable = true; + driSupport = true; + driSupport32Bit = true; + extraPackages = with pkgs; [ + vulkan-loader + vulkan-validation-layers + vulkan-extension-layer + ]; + }; +} diff --git a/nixos/hardware/wireless.nix b/nixos/hardware/wireless.nix new file mode 100644 index 0000000..25f1c77 --- /dev/null +++ b/nixos/hardware/wireless.nix @@ -0,0 +1,7 @@ +{ + # Enable wireless networkmanager + networking = { + networkmanager.enable = true; + enableB43Firmware = true; + }; +} diff --git a/nixos/modules/base.nix b/nixos/modules/base.nix new file mode 100644 index 0000000..272b0b1 --- /dev/null +++ b/nixos/modules/base.nix @@ -0,0 +1,106 @@ +# This is your system's configuration file. +# Use this to configure your system environment (it replaces /etc/nixos/configuration.nix) +{ + inputs, + outputs, + lib, + config, + pkgs, + ... +}: { + # You can import other NixOS modules here + imports = [ + # My modules + ]; + + nixpkgs = { + # You can add overlays here + overlays = [ + # Add overlays your own flake exports (from overlays and pkgs dir): + outputs.overlays.additions + outputs.overlays.modifications + outputs.overlays.unstable-packages + ]; + + # Configure your nixpkgs instance + config = { + allowUnfree = true; + }; + }; + + # This will add each flake input as a registry + # To make nix commands consistent with your flake + nix.registry = (lib.mapAttrs (_: flake: {inherit flake;})) ((lib.filterAttrs (_: lib.isType "flake")) inputs); + + # This will additionally add your inputs to the system's legacy channels + # Making legacy nix commands consistent as well, awesome! + nix.nixPath = ["/etc/nix/path"]; + environment.etc = + lib.mapAttrs' + (name: value: { + name = "nix/path/${name}"; + value.source = value.flake; + }) + config.nix.registry; + + # Enable flakes and garbage collection + nix = { + settings = { + # Enable flakes and new 'nix' command + experimental-features = "nix-command flakes"; + # Deduplicate and optimize nix store + auto-optimise-store = true; + }; + gc = { + automatic = true; + dates = "weekly"; + options = "--delete-older-than 14d"; + }; + }; + + # Set timezone + time.timeZone = let + secrets = import ../common/secrets.nix; + in secrets.timeZone; + + # Select internationalisation properties. + console = { + earlySetup = true; + font = "${pkgs.kbd}/share/consolefonts/Lat2-Terminus16.psfu.gz"; + packages = with pkgs; [ + terminus_font + kbd + ]; + useXkbConfig = true; + }; + + # Enable git + programs.git = { + enable = true; + lfs.enable = true; + }; + + # Basic firewall settings + networking.nftables.enable = true; + + # Enable the ZSH shell + programs.zsh.enable = true; + + # Disable Nano + programs.nano.enable = false; + + # Disable the HTML documentation link + documentation = { + nixos.enable = false; + info.enable = false; + }; + + # Allow binary firmware + hardware.enableRedistributableFirmware = true; + + # Force Electron to use Wayland + environment.sessionVariables.NIXOS_OZONE_WL = "1"; + + # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion + system.stateVersion = "24.05"; +} diff --git a/nixos/modules/networking.nix b/nixos/modules/networking.nix new file mode 100644 index 0000000..a51f375 --- /dev/null +++ b/nixos/modules/networking.nix @@ -0,0 +1,17 @@ +{ + # Networking settings + networking = { + # Choose networking method + wireless.enable = false; + dhcpcd.enable = true; + + # Set hostnames + hosts = let + ips = import ../common/ips.nix; + in { + "${ips.server}" = ["server"]; + "${ips.pc}" = ["pc"]; + "${ips.vm}" = ["vm"]; + }; + }; +} diff --git a/nixos/modules/security.nix b/nixos/modules/security.nix new file mode 100644 index 0000000..6dad11f --- /dev/null +++ b/nixos/modules/security.nix @@ -0,0 +1,18 @@ +{ + # Enable AppArmor + security = { + sudo.enable = false; + doas = { + enable = true; + extraRules = [ + # Give wheel root access, allow persistant session + { + groups = ["wheel"]; + keepEnv = true; + persist = true; + } + ]; + }; + apparmor.enable = true; + }; +} diff --git a/nixos/server.nix b/nixos/server.nix new file mode 100644 index 0000000..c15c732 --- /dev/null +++ b/nixos/server.nix @@ -0,0 +1,44 @@ +{ + imports = [ + # Base configs + ./modules/base.nix + ./users/jimbo.nix + + # Import more users + ./users/nextcloud.nix + ./users/nginx.nix + + # Modules + ./modules/security.nix + ./modules/networking.nix + + # Hardware + ./hardware/machines/server.nix + + # Services + ./services/openssh.nix + ./server/acme.nix + ./server/ddclient.nix + ./server/docker.nix + ./server/element.nix + ./server/firewall.nix + ./server/gitea.nix + ./server/lemmy.nix + ./server/mailserver.nix + ./server/mariadb.nix + ./server/mastodon.nix + ./server/misc.nix + ./server/nextcloud.nix + ./server/nfs.nix + ./server/nginx.nix + ./server/owncast.nix + ./server/pufferpanel.nix + ./server/server-misc.nix + ./server/synapse.nix + ./server/tandoor.nix + ./server/vaultwarden.nix + ]; + + services.openssh.ports = [ 2222 ]; + networking.hostName = "JimNixServer"; +} diff --git a/nixos/server/acme.nix b/nixos/server/acme.nix new file mode 100644 index 0000000..c217655 --- /dev/null +++ b/nixos/server/acme.nix @@ -0,0 +1,14 @@ +{ + security.acme = let + secrets = import ../common/secrets.nix; + in { + acceptTerms = true; + defaults.email = secrets.jimEmail; + certs = { + "turn.${secrets.jimDomain}" = { + group = "turnserver"; + postRun = "systemctl restart coturn.service"; + }; + }; + }; +} diff --git a/nixos/server/ddclient.nix b/nixos/server/ddclient.nix new file mode 100644 index 0000000..c66d5cb --- /dev/null +++ b/nixos/server/ddclient.nix @@ -0,0 +1,24 @@ +{pkgs, ...}: { + # DDClient for Dynamic IPs + services.ddclient = let + secrets = import ../common/secrets.nix; + in { + enable = true; + protocol = "cloudflare"; + use = "web, web=https://ipinfo.io/ip"; + zone = "${secrets.jimDomain}"; + username = "token"; + passwordFile = "${pkgs.writeText "cloudflareapikey" secrets.flareApiKey}"; + domains = [ + "${secrets.jimDomain}" + "*.${secrets.jimDomain}" + "beta.${secrets.jimDomain}" + "git.${secrets.jimDomain}" + "john.${secrets.jimDomain}" + "mc.${secrets.jimDomain}" + "mx.${secrets.jimDomain}" + "panel.${secrets.jimDomain}" + "rtmp.${secrets.jimDomain}" + ]; + }; +} diff --git a/nixos/server/docker.nix b/nixos/server/docker.nix new file mode 100644 index 0000000..bb4c735 --- /dev/null +++ b/nixos/server/docker.nix @@ -0,0 +1,6 @@ +{ + virtualisation.docker = { + enable = true; + daemon.settings.log-driver = "json-file"; + }; +} diff --git a/nixos/server/element.nix b/nixos/server/element.nix new file mode 100644 index 0000000..a0e03dc --- /dev/null +++ b/nixos/server/element.nix @@ -0,0 +1,23 @@ +{ + # Configure the Element web server + nixpkgs.config.element-web.conf = let + secrets = import ../common/secrets.nix; + in { + default_server_config = { + "m.homeserver" = { + base_url = "https://matrix.${secrets.jimDomain}"; + server_name = "matrix.${secrets.jimDomain}"; + }; + }; + branding = { + #welcome_background_url = "https://staging.${secrets.jimDomain}/images/backgrounds/bloxelcom-sunset.jpg"; + #auth_header_logo_url = "https://staging.${secrets.jimDomain}/images/logos/bloxelcom.png"; + }; + embedded_pages = { + home_url = "https://www.${secrets.jimDomain}/"; + }; + disable_custom_urls = true; + disable_guests = true; + default_theme = "dark"; + }; +} diff --git a/nixos/server/firewall.nix b/nixos/server/firewall.nix new file mode 100644 index 0000000..39cec06 --- /dev/null +++ b/nixos/server/firewall.nix @@ -0,0 +1,67 @@ +{ + # Allow forwarding + boot.kernel.sysctl."net.ipv4.ip_forward" = 1; + + # Configure firewall + networking = let + ips = import ../common/ips.nix; + secrets = import ../common/secrets.nix; + in { + firewall = { + allowPing = false; + allowedTCPPorts = [ + 80 443 # Nginx + 25565 19132 5657 # Pufferpanel + 2299 # Gitea SSH + 3478 5349 # Coturn + ]; + allowedTCPPortRanges = [ + { from = 8100; to = 8150; } # Azuracast + ]; + allowedUDPPorts = [ + 25565 19132 # Minecraft Voicechat and Bedrock + 3478 5349 # Coturn UDP + ]; + allowedUDPPortRanges = [ + { from = 49000; to = 50000; } # Coturn range + ]; + + # Add extra input rules using nftables + extraInputRules = '' + ip saddr ${ips.localSpan}.0/24 tcp dport 2049 accept comment "Accept NFS" + ip saddr ${ips.localSpan}.0/24 udp dport 53 accept comment "Accept DNS" + ip saddr { ${ips.pc}, ${secrets.lunaIP}, ${secrets.cornIP}, ${secrets.vertIP} } tcp dport { 1935, 1945 } accept comment "Accept RTMP" + ''; + }; + + # Enable nftables and forwarding + nftables = { + enable = true; + tables = { + forwarding = { + family = "ip"; + content = '' + chain PREROUTING { + type nat hook prerouting priority dstnat; policy accept; + tcp dport 2211 dnat to ${ips.pc}:22 comment "SSH to PC" + udp dport { 27005, 27015, 7777 } dnat to ${ips.pc} comment "Games to PC" + + tcp dport { 58010, 57989, 57984 } dnat to ${ips.pc} comment "Sunshine TCP to PC" + udp dport { 57998, 57999, 58000 } dnat to ${ips.pc} comment "Sunshine UDP to PC" + + tcp dport { 38010, 37989, 37984 } dnat to ${ips.vm} comment "Sunshine TCP to VM" + udp dport { 37998, 37999, 38000 } dnat to ${ips.vm} comment "Sunshine UDP to VM" + + ip saddr ${secrets.cornIP} tcp dport { 9943, 9944 } dnat to ${ips.vm} comment "ALVR TCP to VM" + ip saddr ${secrets.cornIP} udp dport { 9943, 9944 } dnat to ${ips.vm} comment "ALVR UDP to VM" + } + chain POSTROUTING { + type nat hook postrouting priority 100; policy accept; + oifname "${ips.netInt}" masquerade + } + ''; + }; + }; + }; + }; +} diff --git a/nixos/server/gitea.nix b/nixos/server/gitea.nix new file mode 100644 index 0000000..ab910ce --- /dev/null +++ b/nixos/server/gitea.nix @@ -0,0 +1,25 @@ +{ + services.gitea = let + secrets = import ../common/secrets.nix; + in { + enable = true; + settings = { + server = { + DOMAIN = "git.${secrets.jimDomain}"; + ROOT_URL = "https://git.${secrets.jimDomain}:443"; + HTTP_PORT = 3110; + SSH_PORT = 2299; + START_SSH_SERVER = true; + }; + mailer = { + ENABLED = true; + SMTP_ADDR = "mx.${secrets.jimDomain}"; + FROM = "Jimbo's Git "; + USER = "noreply@${secrets.jimDomain}"; + PASSWD = secrets.noreplyPassword; + PROTOCOL = "smtps"; + }; + service.REGISTER_EMAIL_CONFIRM = true; + }; + }; +} diff --git a/nixos/server/lemmy.nix b/nixos/server/lemmy.nix new file mode 100644 index 0000000..2b713bf --- /dev/null +++ b/nixos/server/lemmy.nix @@ -0,0 +1,19 @@ +{ + services.lemmy = let + secrets = import ../common/secrets.nix; + in { + enable = true; + nginx.enable = true; + database.createLocally = true; + settings = { + hostname = "lemmy.${secrets.jimDomain}"; + email = { + smtp_server = "mx.${secrets.jimDomain}:587"; + smtp_login = "noreply@${secrets.jimDomain}"; + smtp_from_address = "Jimbo's Lemmy "; + smtp_password = secrets.noreplyPassword; + tls_type = "starttls"; + }; + }; + }; +} diff --git a/nixos/server/mailserver.nix b/nixos/server/mailserver.nix new file mode 100644 index 0000000..c2e13f7 --- /dev/null +++ b/nixos/server/mailserver.nix @@ -0,0 +1,54 @@ +{pkgs, ...}: let + secrets = import ../common/secrets.nix; +in rec { + # Mail server + mailserver = rec { + enable = true; + enableManageSieve = true; + domains = [ "${secrets.jimDomain}" ]; + fqdn = "mx.${secrets.jimDomain}"; + certificateScheme = "acme-nginx"; + localDnsResolver = false; + redis.port = 1515; + + # A list of accounts, passwords generated with nix-shell -p mkpasswd --run 'mkpasswd -sm bcrypt' + loginAccounts = { + "noreply@${secrets.jimDomain}" = { + hashedPasswordFile = pkgs.writeText "noreply" secrets.noreplyMailHash; + sendOnly = true; + }; + "jimbo@${secrets.jimDomain}" = { + hashedPasswordFile = pkgs.writeText "jimbo" secrets.jimboMailHash; + aliases = [ "canada@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; + }; + "lunamoonlight@${secrets.jimDomain}" = { + hashedPasswordFile = pkgs.writeText "luna" secrets.lunaMailHash; + aliases = [ "us@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; + }; + "freecorn1854@${secrets.jimDomain}" = { + hashedPasswordFile = pkgs.writeText "freecorn" secrets.freecornMailHash; + aliases = [ "canada@${secrets.jimDomain}" "contact@${secrets.jimDomain}" ]; + }; + "tinyattack09@${secrets.jimDomain}" = { + hashedPasswordFile = pkgs.writeText "tiny" secrets.tinyMailHash; + }; + }; + }; + + # Related services + services = { + # Roundcube mail server + roundcube = { + enable = true; + hostName = "mail.${secrets.jimDomain}"; + extraConfig = '' + $config['smtp_server'] = "tls://${mailserver.fqdn}"; + $config['smtp_user'] = "%u"; + $config['smtp_pass'] = "%p"; + ''; + }; + + # Force the mailserver to use a different redis port + redis.servers.rspamd.port = 1515; + }; +} diff --git a/nixos/server/mariadb.nix b/nixos/server/mariadb.nix new file mode 100644 index 0000000..fc4b8a1 --- /dev/null +++ b/nixos/server/mariadb.nix @@ -0,0 +1,18 @@ +{pkgs, ...}: { + services.mysql = { + enable = true; + package = pkgs.mariadb; + dataDir = "/var/lib/mysql"; + initialDatabases = [ + { name = "minecraft"; } + ]; + ensureUsers = [ + { + name = "minecraft"; + ensurePermissions = { + "minecraft.*" = "ALL PRIVILEGES"; + }; + } + ]; + }; +} diff --git a/nixos/server/mastodon.nix b/nixos/server/mastodon.nix new file mode 100644 index 0000000..16f1819 --- /dev/null +++ b/nixos/server/mastodon.nix @@ -0,0 +1,19 @@ +{pkgs, ...}: { + services.mastodon = let + secrets = import ../common/secrets.nix; + in { + enable = true; + localDomain = "social.${secrets.jimDomain}"; + streamingProcesses = 4; + configureNginx = true; + smtp = { + createLocally = false; + host = "mx.${secrets.jimDomain}"; + port = 587; + authenticate = true; + fromAddress = "Jimbo's Mastodon "; + user = "noreply@${secrets.jimDomain}"; + passwordFile = pkgs.writeText "smtp_pass.txt" secrets.noreplyPassword; + }; + }; +} diff --git a/nixos/server/misc.nix b/nixos/server/misc.nix new file mode 100644 index 0000000..2cb35c9 --- /dev/null +++ b/nixos/server/misc.nix @@ -0,0 +1,6 @@ +{ + services = { + snowflake-proxy.enable = true; + logrotate.checkConfig = false; + }; +} diff --git a/nixos/server/nextcloud.nix b/nixos/server/nextcloud.nix new file mode 100644 index 0000000..86e0b7f --- /dev/null +++ b/nixos/server/nextcloud.nix @@ -0,0 +1,30 @@ +{pkgs, ...}: let + secrets = import ../common/secrets.nix; +in { + services.nextcloud = { + enable = true; + package = pkgs.nextcloud29; + hostName = "cloud.${secrets.jimDomain}"; + datadir = "/mnt/nextcloud"; + https = true; + config = { + adminuser = "jimbo"; + adminpassFile = "/mnt/nextcloud/password.txt"; + }; + settings = { + trusted_proxies = [ "127.0.0.1" ]; + trusted_domains = [ "cloud.${secrets.jimDomain}" ]; + overwriteprotocol = "https"; + + # Mailserver settings + mail_smtphost = "mx.${secrets.jimDomain}"; + mail_domain = "${secrets.jimDomain}"; + mail_from_address = "noreply"; + mail_smtpauth = "true"; + mail_smtpname = "noreply@${secrets.jimDomain}"; + mail_smtppassword = secrets.noreplyPassword; + mail_smtpmode = "smtp"; + mail_smtpport = 587; + }; + }; +} diff --git a/nixos/server/nfs.nix b/nixos/server/nfs.nix new file mode 100644 index 0000000..6d017de --- /dev/null +++ b/nixos/server/nfs.nix @@ -0,0 +1,11 @@ +{ + # NFS server + services.nfs.server = let + ips = import ../common/ips.nix; + in { + enable = true; + exports = '' + /export/JimboNFS ${ips.localSpan}.0/24(rw,no_subtree_check) + ''; + }; +} diff --git a/nixos/server/nginx.nix b/nixos/server/nginx.nix new file mode 100644 index 0000000..f487d0b --- /dev/null +++ b/nixos/server/nginx.nix @@ -0,0 +1,206 @@ +{pkgs, ...}: { + services.nginx = let + secrets = import ../common/secrets.nix; + in { + enable = true; + package = (pkgs.nginx.override { + modules = with pkgs.nginxModules; [ rtmp ]; + }); + recommendedTlsSettings = true; + recommendedOptimisation = true; + recommendedGzipSettings = true; + recommendedProxySettings = true; + virtualHosts = { + # Homepage redirect + "${secrets.jimDomain}" = { + enableACME = true; + addSSL = true; + root = "/var/www/jimweb"; + locations = { + "/.well-known/matrix/client" = { + extraConfig = '' + default_type application/json; + return 200 ' + { + "m.homeserver": { + "base_url": "https://matrix.${secrets.jimDomain}" + }, + "m.identity_server": { + "base_url": "https://matrix.org" + }, + "org.matrix.msc3575.proxy": { + "url": "https://matrix.${secrets.jimDomain}" + } + }'; + ''; + }; + "/.well-known/matrix/server" = { + extraConfig = '' + default_type application/json; + return 200 '{"m.server": "matrix.${secrets.jimDomain}:443"}'; + ''; + }; + }; + }; + + # Nextcloud Proxy + "cloud.${secrets.jimDomain}" = { + enableACME = true; + addSSL = true; + locations."/" = { + proxyWebsockets = true; + extraConfig = " + location /.well-known/carddav { + return 301 $scheme://$host/remote.php/dav; + } + location /.well-known/caldav { + return 301 $scheme://$host/remote.php/dav; + } + "; + }; + }; + + # Vaultwarden Proxy + "warden.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:8222"; + proxyWebsockets = true; + }; + }; + + # Recipes Proxy + "recipes.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:5030"; + proxyWebsockets = true; + }; + }; + + # Bluemap Proxy + "bluemap.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:31010"; + proxyWebsockets = true; + }; + }; + + # Gitea Proxy + "git.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:3110"; + proxyWebsockets = true; + }; + }; + + # Pufferpanel Proxy + "panel.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:5010"; + proxyWebsockets = true; + }; + }; + + # Matrix Proxy + "matrix.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations = { + "/".extraConfig = ''return 403;''; + "/client".proxyPass = "http://127.0.0.1:8009"; + "/_matrix".proxyPass = "http://127.0.0.1:8008"; + "/_matrix/client/unstable/org.matrix.msc3575/sync".proxyPass = "http://127.0.0.1:8009"; + "/_synapse/client".proxyPass = "http://127.0.0.1:8008"; + }; + }; + + # Element Proxy + "chat.${secrets.jimDomain}" = { + enableACME = true; + addSSL = true; + root = "${pkgs.element-web}"; + }; + + # Coturn Proxy + "turn.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + listen = [ + { addr = "0.0.0.0"; port = 80; ssl = false; } + ]; + locations."/".proxyPass = "http://127.0.0.1:1380"; + }; + + # Radio Proxy + "radio.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:255"; + proxyWebsockets = true; + }; + }; + + # Streaming proxy + "live.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:8060"; + proxyWebsockets = true; + }; + }; + + # Mail certificate proxy + "mx.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + locations."/" = { + proxyPass = "http://127.0.0.1:1390"; + proxyWebsockets = true; + }; + }; + + # Add SSL to Lemmy + "lemmy.${secrets.jimDomain}" = { + enableACME = true; + forceSSL = true; + }; + }; + appendConfig = '' + rtmp { + server { + listen 1935; + chunk_size 4096; + allow publish all; + application stream { + record off; + live on; + allow play all; + hls on; + hls_path /var/www/jimweb/streams/hls; + hls_fragment_naming system; + hls_fragment 3; + hls_playlist_length 40; + } + } + } + ''; + }; + + # Force Nginx to work and be able to read+write the hls path + security.pam.services.nginx.setEnvironment = false; + systemd.services.nginx.serviceConfig = { + SupplementaryGroups = [ "shadow" ]; + ReadWritePaths = [ "/var/www/jimweb/streams/hls/" ]; + }; +} diff --git a/nixos/server/owncast.nix b/nixos/server/owncast.nix new file mode 100644 index 0000000..ba4d842 --- /dev/null +++ b/nixos/server/owncast.nix @@ -0,0 +1,8 @@ +{ + services.owncast = { + enable = true; + port = 8060; + rtmp-port = 1945; + listen = "0.0.0.0"; + }; +} diff --git a/nixos/server/pufferpanel.nix b/nixos/server/pufferpanel.nix new file mode 100644 index 0000000..33689ea --- /dev/null +++ b/nixos/server/pufferpanel.nix @@ -0,0 +1,23 @@ +{pkgs, lib, ...}: { + services.pufferpanel = let + secrets = import ../common/secrets.nix; + in { + enable = true; + environment = { + PUFFER_WEB_HOST = ":5010"; + PUFFER_PANEL_SETTINGS_MASTERURL = "https://panel.${secrets.jimDomain}"; + PUFFER_PANEL_EMAIL_PROVIDER = "smtp"; + PUFFER_PANEL_EMAIL_HOST = "mx.${secrets.jimDomain}:587"; + PUFFER_PANEL_EMAIL_FROM = "noreply@${secrets.jimDomain}"; + PUFFER_PANEL_EMAIL_USERNAME = "noreply@${secrets.jimDomain}"; + PUFFER_PANEL_EMAIL_PASSWORD = secrets.noreplyPassword; + }; + extraPackages = with pkgs; [ bash curl gawk gnutar gzip ]; + package = pkgs.buildFHSEnv { + name = "pufferpanel-fhs"; + meta.mainProgram = "pufferpanel-fhs"; + runScript = lib.getExe pkgs.pufferpanel; + targetPkgs = pkgs': with pkgs'; [ icu openssl zlib ]; + }; + }; +} diff --git a/nixos/server/server-misc.nix b/nixos/server/server-misc.nix new file mode 100644 index 0000000..adbc9b5 --- /dev/null +++ b/nixos/server/server-misc.nix @@ -0,0 +1,6 @@ +{pkgs, ...}: { + # Install programs system-wide + environment.systemPackages = with pkgs; [ + mdadm + ]; +} diff --git a/nixos/server/synapse.nix b/nixos/server/synapse.nix new file mode 100644 index 0000000..fc95bf0 --- /dev/null +++ b/nixos/server/synapse.nix @@ -0,0 +1,96 @@ +{pkgs, config, ...}: { + services = let + secrets = import ../common/secrets.nix; + in { + # Synapse Matrix server + matrix-synapse = with config.services.coturn; { + enable = true; + settings = { + server_name = "${secrets.jimDomain}"; + public_baseurl = "https://matrix.${secrets.jimDomain}"; + suppress_key_server_warning = true; + + # Set the network config + listeners = [{ + # Client config + port = 8008; + bind_addresses = [ "::" "0.0.0.0" ]; + resources = [ { compress = false; names = [ "client" "federation" ]; } ]; + type = "http"; + tls = false; + x_forwarded = true; + }]; + + # Enable smtp for password resets + email = { + notif_from = "Jimbo's Matrix "; + smtp_host = "mx.${secrets.jimDomain}"; + smtp_user = "noreply@${secrets.jimDomain}"; + smtp_pass = secrets.noreplyPassword; + enable_tls = true; + smtp_port = 587; + require_transport_security = true; + }; + + # Disable registration without email + registrations_require_3pid = [ "email" ]; + + # Allow only this range of emails + allowed_local_3pids = [{ + medium = "email"; + pattern = "^[^@]+@jimbosfiles\\.com$"; + }]; + + # Set the type of database + database.name = "sqlite3"; + + # Allow account registration + enable_registration = true; + + # General settings + url_preview_enabled = true; + max_upload_size = "50M"; + report_stats = false; + + # Turn settings + turn_uris = [ + "turn:turn.${secrets.jimDomain}:3478?transport=udp" + "turn:turn.${secrets.jimDomain}:3478?transport=tcp" + ]; + turn_shared_secret = static-auth-secret; + turn_user_lifetime = "1h"; + + # Ratelimiting + burst_count = 15; + }; + }; + + # Sliding sync proxy for Matrix + matrix-sliding-sync = let + matrixSecretFile = pkgs.writeText "matrixsecret" '' + SYNCV3_SECRET=${secrets.matrixSecret} + ''; + in { + enable = true; + settings = { + SYNCV3_SERVER = "https://matrix.${secrets.jimDomain}"; + SYNCV3_BINDADDR = "0.0.0.0:8009"; + }; + environmentFile = "${matrixSecretFile}"; + }; + + # Coturn for VC + coturn = rec { + enable = true; + no-cli = true; + no-tcp-relay = true; + min-port = 49000; + max-port = 50000; + use-auth-secret = true; + static-auth-secret = "will be world readable for local users :("; + realm = "turn.${secrets.jimDomain}"; + cert = "/var/lib/acme/turn.${secrets.jimDomain}.com/fullchain.pem"; + pkey = "/var/lib/acme/turn.${secrets.jimDomain}.com/key.pem"; + }; + }; +} diff --git a/nixos/server/tandoor.nix b/nixos/server/tandoor.nix new file mode 100644 index 0000000..77027f7 --- /dev/null +++ b/nixos/server/tandoor.nix @@ -0,0 +1,6 @@ +{ + services.tandoor-recipes = { + enable = true; + port = 5030; + }; +} diff --git a/nixos/server/vaultwarden.nix b/nixos/server/vaultwarden.nix new file mode 100644 index 0000000..44a9e73 --- /dev/null +++ b/nixos/server/vaultwarden.nix @@ -0,0 +1,24 @@ +{ + services.vaultwarden = let + secrets = import ../common/secrets.nix; + in { + enable = true; + config = { + DOMAIN = "https://warden.${secrets.jimDomain}"; + SIGNUPS_ALLOWED = false; + ROCKET_ADDRESS = "127.0.0.1"; + ROCKET_PORT = 8222; + ROCKET_LOG = "critical"; + + # Smtp email + SMTP_HOST = "mx.${secrets.jimDomain}"; + SMTP_FROM = "Jimbo's Vaultwarden "; + SMTP_FROM_NAME = "Vaultwarden"; + SMTP_USERNAME = "noreply@${secrets.jimDomain}"; + SMTP_PASSWORD = secrets.noreplyPassword; + SMTP_SECURITY = "starttls"; + SMTP_PORT = 587; + SMTP_TIMEOUT = 15; + }; + }; +} diff --git a/nixos/services/mpd.nix b/nixos/services/mpd.nix new file mode 100644 index 0000000..910e1e5 --- /dev/null +++ b/nixos/services/mpd.nix @@ -0,0 +1,23 @@ +{ + config, + pkgs, + ... +}: { + # Enable MPD + services.mpd = { + enable = true; + user = "jimbo"; + group = "users"; + musicDirectory = "/home/jimbo/JimboNFS/Music"; + playlistDirectory = "/home/jimbo/JimboNFS/Music/Playlists"; + extraConfig = '' + audio_output { + type "pipewire" + name "Local Pipewire" + } + ''; + }; + systemd.services.mpd.environment = { + XDG_RUNTIME_DIR = "/run/user/${toString config.users.users.jimbo.uid}"; + }; +} diff --git a/nixos/services/openssh.nix b/nixos/services/openssh.nix new file mode 100644 index 0000000..fe6db48 --- /dev/null +++ b/nixos/services/openssh.nix @@ -0,0 +1,21 @@ +{ + # Enable SSH + services = { + openssh = { + enable = true; + settings = { + PermitRootLogin = "no"; + PrintLastLog = "no"; + PasswordAuthentication = false; + }; + }; + + # Block nefarious SSH connections + fail2ban = { + enable = true; + maxretry = 5; + bantime = "5m"; + ignoreIP = [ "10.0.0.0/24" ]; + }; + }; +} diff --git a/nixos/services/sunshine.nix b/nixos/services/sunshine.nix new file mode 100644 index 0000000..e1f2387 --- /dev/null +++ b/nixos/services/sunshine.nix @@ -0,0 +1,8 @@ +{ + # Enable Sunshine as a service + services.sunshine = { + enable = true; + settings.port = 57989; + autoStart = false; + }; +} diff --git a/nixos/services/udev.nix b/nixos/services/udev.nix new file mode 100644 index 0000000..2fef6c2 --- /dev/null +++ b/nixos/services/udev.nix @@ -0,0 +1,21 @@ +{pkgs, ...}: { + # Make udev rules to make PDP controller and Oculus Rift CV1 work + services.udev = let + oculusRules = pkgs.writeTextFile { + name = "10-oculus.rules"; + text = '' + KERNEL=="hidraw*", ATTRS{idVendor}=="0e6f", ATTRS{idProduct}=="0184", MODE="0660", TAG+="uaccess" + ''; + destination = "/etc/udev/rules.d/10-oculus.rules"; + }; + pdpRules = pkgs.writeTextFile { + name = "10-pdp.rules"; + text = '' + SUBSYSTEM=="usb", ATTR{idVendor}=="2833", MODE="0666" + ''; + destination = "/etc/udev/rules.d/10-pdp.rules"; + }; + in { + packages = [oculusRules pdpRules]; + }; +} diff --git a/nixos/services/virtualisation.nix b/nixos/services/virtualisation.nix new file mode 100644 index 0000000..b3b7a48 --- /dev/null +++ b/nixos/services/virtualisation.nix @@ -0,0 +1,36 @@ +{ + config, + pkgs, + ... +}: { + # Enable virtualization + virtualisation = { + libvirtd = { + enable = true; + onBoot = "ignore"; + onShutdown = "shutdown"; + qemu = { + ovmf = { + enable = true; + packages = [pkgs.OVMFFull.fd]; + }; + swtpm.enable = true; + }; + }; + spiceUSBRedirection.enable = true; + }; + + # Install programs system-wide + environment.systemPackages = with pkgs; [ + virt-manager + virtiofsd + dnsmasq + spice-vdagent + looking-glass-client + ]; + + # Allow Looking-Glass permissions + systemd.tmpfiles.rules = [ + "f /dev/shm/looking-glass 0660 jimbo libvirtd -" + ]; +} diff --git a/nixos/users/jimbo.nix b/nixos/users/jimbo.nix new file mode 100644 index 0000000..a4e4e1e --- /dev/null +++ b/nixos/users/jimbo.nix @@ -0,0 +1,29 @@ +{pkgs, ...}: { + users.users = { + jimbo = let + secrets = import ../common/secrets.nix; + in { + description = "Jimbo"; + hashedPassword = secrets.jimboAccPass; + isNormalUser = true; + openssh.authorizedKeys.keys = secrets.jimKeys; + extraGroups = [ + "wheel" + "audio" + "video" + "input" + "disk" + "dialout" + "networkmanager" + "rtkit" + "kvm" + "libvirtd" + "qemu-libvirtd" + "docker" + "nfsShare" + ]; + uid = 1000; + shell = pkgs.zsh; + }; + }; +} diff --git a/nixos/users/nextcloud.nix b/nixos/users/nextcloud.nix new file mode 100644 index 0000000..f94c29c --- /dev/null +++ b/nixos/users/nextcloud.nix @@ -0,0 +1,9 @@ +{ + # Add service users to extra groups + users.users = { + nextcloud = { + extraGroups = [ "nfsShare" ]; + isSystemUser = true; + }; + }; +} diff --git a/nixos/users/nginx.nix b/nixos/users/nginx.nix new file mode 100644 index 0000000..680f810 --- /dev/null +++ b/nixos/users/nginx.nix @@ -0,0 +1,9 @@ +{ + # Add service users to extra groups + users.users = { + nginx = { + extraGroups = [ "turnserver" "virtualMail" ]; + isSystemUser = true; + }; + }; +} diff --git a/overlays/default.nix b/overlays/default.nix new file mode 100644 index 0000000..92a84a7 --- /dev/null +++ b/overlays/default.nix @@ -0,0 +1,22 @@ +# This file defines overlays +{inputs, ...}: { + # This one brings our custom packages from the 'pkgs' directory + additions = final: _prev: import ../pkgs {pkgs = final;}; + + # This one contains whatever you want to overlay + # You can change versions, add patches, set compilation flags, anything really. + # https://nixos.wiki/wiki/Overlays + modifications = (self: super: { + mpv = super.mpv.override { + scripts = with self.mpvScripts; [mpris sponsorblock thumbnail]; + }; + }); + + # Unstable nixpkgs and nur through 'pkgs.unstable' and 'pkgs.nur' + unstable-packages = final: _prev: { + unstable = import inputs.nixpkgs-unstable { + system = final.system; + config.allowUnfree = true; + }; + }; +} diff --git a/pkgs/default.nix b/pkgs/default.nix new file mode 100644 index 0000000..1cf0055 --- /dev/null +++ b/pkgs/default.nix @@ -0,0 +1,7 @@ +# Custom packages, that can be defined similarly to ones from nixpkgs +# You can build them using 'nix build .#example' +{pkgs, ...}: { + # pkgs + xash3d = pkgs.callPackage ./xash/xash3d.nix {}; + hlsdk = pkgs.callPackage ./xash/hlsdk.nix {}; +} diff --git a/pkgs/xash/hlsdk.nix b/pkgs/xash/hlsdk.nix new file mode 100644 index 0000000..4e52de7 --- /dev/null +++ b/pkgs/xash/hlsdk.nix @@ -0,0 +1,52 @@ +{ lib +, pkgs +, stdenv +, fetchFromGitHub +, gamedir ? "valve" +, enableGoldsourceSupport ? true +, enableVgui ? false +, enableVoicemgr ? false +, enableBugfixes ? false +, enableCrowbarIdleAnim ? false +}: + +stdenv.mkDerivation { + pname = "fwgs-hlsdk"; + version = "2023-03-01"; + + nativeBuildInputs = with pkgs; [cmake]; + + src = fetchFromGitHub { + owner = "FWGS"; + repo = "hlsdk-portable"; + rev = "d11f853464ee5d951e25ce9d0eea001780b92196"; + sha256 = if enableVgui then "sha256-Qd+SUie+jlfxo6aefordYw665ZaNaR3TxufntfIaoCo=" else "sha256-WU+I+mmoyXvW1pvqJLddPaA8/tod3TtvqzVPYJRbGz4="; + fetchSubmodules = enableVgui; + }; + + cmakeFlags = let + optionals = lib.optionals; + optional = (cond: val: optionals cond [val]); + cmakeBool = (x: if x then "ON" else "OFF"); + in [ + "-DUSE_VGUI=${cmakeBool enableVgui}" + "-DGOLDSOURCE_SUPPORT=${cmakeBool enableGoldsourceSupport}" + "-DUSE_VOICEMGR=${cmakeBool enableVoicemgr}" + "-DBARNACLE_FIX_VISIBILITY=${cmakeBool enableBugfixes}" + "-DCROWBAR_DELAY_FIX=${cmakeBool enableBugfixes}" + "-DCROWBAR_FIX_RAPID_CROWBAR=${cmakeBool enableBugfixes}" + "-DGAUSS_OVERCHARGE_FIX=${cmakeBool enableBugfixes}" + "-DTRIPMINE_BEAM_DUPLICATION_FIX=${cmakeBool enableBugfixes}" + "-DHANDGRENADE_DEPLOY_FIX=${cmakeBool enableBugfixes}" + "-DWEAPONS_ANIMATION_TIMES_FIX=${cmakeBool enableBugfixes}" + "-DCROWBAR_IDLE_ANIM=${cmakeBool enableCrowbarIdleAnim}" + ] ++ (optional (gamedir != "valve") "-DGAMEDIR=${gamedir}") + ++ (optional stdenv.is64bit "-D64BIT=ON"); + + meta = with lib; { + description = "Portable Half-Life SDK. GoldSource and Xash3D. Crossplatform."; + homepage = "https://github.com/FWGS/hlsdk-portable"; + license = with licenses; [ unfree ]; + # maintainers = with maintainers; [ chayleaf ]; + }; +} diff --git a/pkgs/xash/xash3d.nix b/pkgs/xash/xash3d.nix new file mode 100644 index 0000000..7afff9e --- /dev/null +++ b/pkgs/xash/xash3d.nix @@ -0,0 +1,68 @@ +{ lib +, pkgs +, stdenv +, fetchFromGitHub +, dedicated ? false # dedicated server +, gamedir ? "valve" +, enableBsp2 ? false # bsp2 support (for quake) +, enableGles1 ? false # gles1 renderer (nanogl) +, enableGles2 ? false # gles2 renderer (glwes) +, enableGl4es ? false # gles2 renderer (gl4es) +, enableGl ? true # opengl renderer +, enableSoft ? true # soft renderer +, enableUtils ? false # mdldec +}: + +stdenv.mkDerivation { + pname = "xash3d-fwgs"; + version = "2023-03-01"; + + nativeBuildInputs = with pkgs; [python3 pkg-config makeWrapper]; + buildInputs = with pkgs; [SDL2 libopus freetype fontconfig]; + + src = fetchFromGitHub { + owner = "FWGS"; + repo = "xash3d-fwgs"; + rev = "7e9d46689ca76d6bf1669ada6344fc724dd683cf"; + sha256 = "sha256-rvONYm1Gz9PpK8KY6RIIJ82FtxGcWe/4YoT2eV4sCOc="; + fetchSubmodules = true; + }; + patches = [ ./change-zip-date.patch ]; + + configurePhase = let + optionals = lib.optionals; + optional = (cond: val: optionals cond [val]); + flags = ["-8" "-P" "--prefix=/"] + ++ (optional dedicated "-d") + ++ (optionals (gamedir != "valve") ["--gamedir" gamedir]) + ++ (optional enableBsp2 "--enable-bsp2") + ++ (optional enableGles1 "--enable-gles1") + ++ (optional enableGles2 "--enable-gles2") + ++ (optional enableGl4es "--enable-gl4es") + ++ (optional (!enableGl) "--disable-gl") + ++ (optional (!enableSoft) "--disable-soft") + ++ (optional enableUtils "--enable-utils") + ; + in '' + python3 ./waf configure -T release ${lib.strings.escapeShellArgs flags} + ''; + + buildPhase = '' + python3 ./waf build + ''; + + installPhase = '' + python3 ./waf install "--destdir=$out" + mkdir $out/bin + makeWrapper $out/lib/xash3d/xash3d $out/bin/xash3d --set XASH3D_EXTRAS_PAK1 $out/share/xash3d/valve/extras.pk3 + ''; + + meta = with lib; { + description = "Xash3D FWGS engine"; + homepage = "https://github.com/FWGS/xash3d-fwgs"; + # this is a mess because of vendoring... + # maybe the correct thing to do use to simply use `[ unfree gpl3Plus ]` instead + license = with licenses; [ unfree gpl2Plus gpl3Plus lgpl3Plus mit bsd3 ]; + # maintainers = with maintainers; [ chayleaf ]; + }; +} diff --git a/preview.png b/preview.png new file mode 100644 index 0000000..08da742 Binary files /dev/null and b/preview.png differ