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