Compare commits
	
		
			66 Commits
		
	
	
		
			fastback-s
			...
			5c7f147a2e
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 5c7f147a2e | |||
| 9f2651e352 | |||
| bce876ec42 | |||
| bc8adcecad | |||
| 8878ce56c4 | |||
| dd9439b7fa | |||
| bc9f266ef0 | |||
| 1b083d298b | |||
| 83ba26735e | |||
| 50bd96ccdf | |||
| a133cfb189 | |||
| 051e68254e | |||
| 3fa8ab43ef | |||
| c6720f87c1 | |||
| 55ecdddadb | |||
| 9b5173a587 | |||
| 73f5a690bb | |||
| 54db751e23 | |||
| 85299b65dc | |||
| 45bda5b588 | |||
| 9114f5ce74 | |||
| 3925c1090e | |||
| e74538a1a9 | |||
| b8ee21b6e8 | |||
| 41fd54cfad | |||
| 1df34e0515 | |||
| ce0c194761 | |||
| a5e51ddd6b | |||
| 746e0b9dc4 | |||
| 77600a64fc | |||
| c6d5705097 | |||
| 6eefe97764 | |||
| 4bc4fe3ee8 | |||
| 57ec2bfc1b | |||
| d9d1150feb | |||
| 92896d8e52 | |||
| 477ffca33e | |||
| fdc65c544e | |||
| 945302b7c0 | |||
| 5ccf19cab8 | |||
| 7b61dd7f03 | |||
| 682865a0e1 | |||
| a0e4cf2479 | |||
| a5880d66f4 | |||
| 27a4583879 | |||
| fdbf5f8aca | |||
| 40c491aa14 | |||
| 1a8740fb9c | |||
| f857e751b5 | |||
| b420f2377c | |||
| 7d90b5ecb8 | |||
| ace979c226 | |||
| f540edb361 | |||
| 6bc5cd79da | |||
| 5ec77dfde6 | |||
| 52623d458e | |||
| 23b29f0707 | |||
| 338902497f | |||
| 977846991a | |||
| 0e8aec58fb | |||
| 0f1de58917 | |||
| 32183bd331 | |||
| 1813ca1927 | |||
| 51d44e472a | |||
| 44e87aa387 | |||
| f90deabb50 | 
@@ -45,6 +45,7 @@ jobs:
 | 
			
		||||
        uses: https://gitea.com/actions/release-action@main
 | 
			
		||||
        with:
 | 
			
		||||
          title: Latest installer
 | 
			
		||||
          api_key: '${{ secrets.RELEASE_TOKEN }}'
 | 
			
		||||
          files: |
 | 
			
		||||
            jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
 | 
			
		||||
            jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
			
		||||
 
 | 
			
		||||
@@ -20,7 +20,7 @@ in
 | 
			
		||||
          [ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
 | 
			
		||||
 | 
			
		||||
          mkdir -p "$(dirname "${homeFlake}")"
 | 
			
		||||
          ln -s "$(pwd)/flake.nix" "${homeFlake}"
 | 
			
		||||
          ln -sf "$(pwd)/flake.nix" "${homeFlake}"
 | 
			
		||||
          echo "Installed link to $(pwd)/flake.nix at ${homeFlake}"
 | 
			
		||||
        '';
 | 
			
		||||
    }
 | 
			
		||||
@@ -52,7 +52,7 @@ in
 | 
			
		||||
      name = "json2nix";
 | 
			
		||||
      category = "utilities";
 | 
			
		||||
      help = "Convert JSON to formatted Nix";
 | 
			
		||||
      command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt}/bin/nixfmt";
 | 
			
		||||
      command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt-rfc-style}/bin/nixfmt";
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    {
 | 
			
		||||
@@ -106,8 +106,8 @@ in
 | 
			
		||||
    {
 | 
			
		||||
      name = "build-netboot";
 | 
			
		||||
      category = "tasks";
 | 
			
		||||
      help = "Build NixOS configuration as netboot archive";
 | 
			
		||||
      command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootArchive"'';
 | 
			
		||||
      help = "Build NixOS configuration as netboot tree";
 | 
			
		||||
      command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootTree"'';
 | 
			
		||||
    }
 | 
			
		||||
    {
 | 
			
		||||
      name = "build-home";
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										516
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										516
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@@ -3,17 +3,19 @@
 | 
			
		||||
    "agenix": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "darwin": "darwin",
 | 
			
		||||
        "home-manager": "home-manager",
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
        ],
 | 
			
		||||
        "systems": "systems_8"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1682101079,
 | 
			
		||||
        "narHash": "sha256-MdAhtjrLKnk2uiqun1FWABbKpLH090oeqCSiWemtuck=",
 | 
			
		||||
        "lastModified": 1707830867,
 | 
			
		||||
        "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=",
 | 
			
		||||
        "owner": "ryantm",
 | 
			
		||||
        "repo": "agenix",
 | 
			
		||||
        "rev": "2994d002dcff5353ca1ac48ec584c7f6589fe447",
 | 
			
		||||
        "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -35,11 +37,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1702969472,
 | 
			
		||||
        "narHash": "sha256-IJP9sC+/gLUdWhm6TsnWpw6A1zQWUfn53ym63KeLXvU=",
 | 
			
		||||
        "lastModified": 1711742460,
 | 
			
		||||
        "narHash": "sha256-0O4v6e4a1toxXZ2gf5INhg4WPE5C5T+SVvsBt+45Mcc=",
 | 
			
		||||
        "owner": "zhaofengli",
 | 
			
		||||
        "repo": "attic",
 | 
			
		||||
        "rev": "bdafd64910bb2b861cf90fa15f1fc93318b6fbf6",
 | 
			
		||||
        "rev": "4dbdbee45728d8ce5788db6461aaaa89d98081f0",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -58,17 +60,17 @@
 | 
			
		||||
        "poetry2nix": "poetry2nix"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1682289679,
 | 
			
		||||
        "narHash": "sha256-DbhSJ6y62VAO2VsJwoz3VsxCEP/4KMeFVs0wIz6Im04=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "boardie",
 | 
			
		||||
        "rev": "e4b977f75bf7b4f656a691efca492ae057672a77",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
        "lastModified": 1718746012,
 | 
			
		||||
        "narHash": "sha256-sp9vGl3vWXvD/C2JeMDi5nbW6CkKIC3Q2JMGKwexYEs=",
 | 
			
		||||
        "ref": "refs/heads/master",
 | 
			
		||||
        "rev": "ea24100bd4a914b9e044a2085a3785a6bd3a3833",
 | 
			
		||||
        "revCount": 5,
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://git.nul.ie/dev/boardie"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "boardie",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
        "type": "git",
 | 
			
		||||
        "url": "https://git.nul.ie/dev/boardie"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "borgthin": {
 | 
			
		||||
@@ -116,26 +118,17 @@
 | 
			
		||||
    },
 | 
			
		||||
    "crane_2": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-compat": "flake-compat_3",
 | 
			
		||||
        "flake-utils": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
          "flake-utils"
 | 
			
		||||
        ],
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ],
 | 
			
		||||
        "rust-overlay": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
          "rust-overlay"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681680516,
 | 
			
		||||
        "narHash": "sha256-EB8Adaeg4zgcYDJn9sR6UMjN/OHdIiMMK19+3LmmXQY=",
 | 
			
		||||
        "lastModified": 1708794349,
 | 
			
		||||
        "narHash": "sha256-jX+B1VGHT0ruHHL5RwS8L21R6miBn4B6s9iVyUJsJJY=",
 | 
			
		||||
        "owner": "ipetkov",
 | 
			
		||||
        "repo": "crane",
 | 
			
		||||
        "rev": "54b63c8eae4c50172cb50b612946ff1d2bc1c75c",
 | 
			
		||||
        "rev": "2c94ff9a6fbeb9f3ea0107f28688edbe9c81deaa",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -153,11 +146,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1673295039,
 | 
			
		||||
        "narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
 | 
			
		||||
        "lastModified": 1700795494,
 | 
			
		||||
        "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
 | 
			
		||||
        "owner": "lnl7",
 | 
			
		||||
        "repo": "nix-darwin",
 | 
			
		||||
        "rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
 | 
			
		||||
        "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -176,11 +169,11 @@
 | 
			
		||||
        "utils": "utils"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703087360,
 | 
			
		||||
        "narHash": "sha256-0VUbWBW8VyiDRuimMuLsEO4elGuUw/nc2WDeuO1eN1M=",
 | 
			
		||||
        "lastModified": 1715699772,
 | 
			
		||||
        "narHash": "sha256-sKhqIgucN5sI/7UQgBwsonzR4fONjfMr9OcHK/vPits=",
 | 
			
		||||
        "owner": "serokell",
 | 
			
		||||
        "repo": "deploy-rs",
 | 
			
		||||
        "rev": "b709d63debafce9f5645a5ba550c9e0983b3d1f7",
 | 
			
		||||
        "rev": "b3ea6f333f9057b77efd9091119ba67089399ced",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -195,11 +188,11 @@
 | 
			
		||||
        "nixpkgs": "nixpkgs"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1678957337,
 | 
			
		||||
        "narHash": "sha256-Gw4nVbuKRdTwPngeOZQOzH/IFowmz4LryMPDiJN/ah4=",
 | 
			
		||||
        "lastModified": 1717408969,
 | 
			
		||||
        "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "devshell",
 | 
			
		||||
        "rev": "3e0e60ab37cd0bf7ab59888f5c32499d851edb47",
 | 
			
		||||
        "rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -208,6 +201,25 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "devshell-tools": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_11",
 | 
			
		||||
        "nixpkgs": "nixpkgs_4"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1710099997,
 | 
			
		||||
        "narHash": "sha256-WmBKTLdth6I/D+0//9enbIXohGsBjepbjIAm9pCYj0U=",
 | 
			
		||||
        "owner": "eikek",
 | 
			
		||||
        "repo": "devshell-tools",
 | 
			
		||||
        "rev": "e82faf976d318b3829f6f7f6785db6f3c7b65267",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "eikek",
 | 
			
		||||
        "repo": "devshell-tools",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "devshell_2": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_5",
 | 
			
		||||
@@ -229,17 +241,17 @@
 | 
			
		||||
    },
 | 
			
		||||
    "devshell_3": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_7",
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ],
 | 
			
		||||
        "systems": "systems_4"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701787589,
 | 
			
		||||
        "narHash": "sha256-ce+oQR4Zq9VOsLoh9bZT8Ip9PaMLcjjBUHVPzW5d7Cw=",
 | 
			
		||||
        "lastModified": 1713532798,
 | 
			
		||||
        "narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "devshell",
 | 
			
		||||
        "rev": "44ddedcbcfc2d52a76b64fb6122f209881bd3e1e",
 | 
			
		||||
        "rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -280,22 +292,6 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-compat_3": {
 | 
			
		||||
      "flake": false,
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1673956053,
 | 
			
		||||
        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
 | 
			
		||||
        "owner": "edolstra",
 | 
			
		||||
        "repo": "flake-compat",
 | 
			
		||||
        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "edolstra",
 | 
			
		||||
        "repo": "flake-compat",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1667395993,
 | 
			
		||||
@@ -312,6 +308,60 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_10": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_9"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1705309234,
 | 
			
		||||
        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_11": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_10"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1709126324,
 | 
			
		||||
        "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "d465f4819400de7c8d874d50b982301f28a84605",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_12": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_11"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1705309234,
 | 
			
		||||
        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_13": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1667395993,
 | 
			
		||||
        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
 | 
			
		||||
@@ -327,12 +377,15 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_2": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1642700792,
 | 
			
		||||
        "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
 | 
			
		||||
        "lastModified": 1701680307,
 | 
			
		||||
        "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
 | 
			
		||||
        "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -343,14 +396,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_3": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems"
 | 
			
		||||
        "systems": "systems_2"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681202837,
 | 
			
		||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
			
		||||
        "lastModified": 1710146030,
 | 
			
		||||
        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
			
		||||
        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -361,14 +414,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_4": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_2"
 | 
			
		||||
        "systems": "systems_3"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681202837,
 | 
			
		||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
			
		||||
        "lastModified": 1710146030,
 | 
			
		||||
        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
			
		||||
        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -409,7 +462,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_7": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_5"
 | 
			
		||||
        "systems": "systems_6"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701680307,
 | 
			
		||||
@@ -426,6 +479,24 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_8": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_7"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1710146030,
 | 
			
		||||
        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_9": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1659877975,
 | 
			
		||||
        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
 | 
			
		||||
@@ -440,21 +511,25 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_9": {
 | 
			
		||||
    "home-manager": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_6"
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
          "agenix",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681202837,
 | 
			
		||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
			
		||||
        "lastModified": 1703113217,
 | 
			
		||||
        "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
@@ -465,11 +540,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703367386,
 | 
			
		||||
        "narHash": "sha256-FMbm48UGrBfOWGt8+opuS+uLBLQlRfhiYXhHNcYMS5k=",
 | 
			
		||||
        "lastModified": 1716729592,
 | 
			
		||||
        "narHash": "sha256-Y3bOjoh2cFBqZN0Jw1zUdyr7tjygyxl2bD/QY73GZP0=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224",
 | 
			
		||||
        "rev": "2c78a57c544dd19b07442350727ced097e1aa6e6",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -485,11 +560,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703754036,
 | 
			
		||||
        "narHash": "sha256-JpJdcj9Tg4lMuYikXDpajA8wOp+rHyn9RD2rKBEM4cQ=",
 | 
			
		||||
        "lastModified": 1717097707,
 | 
			
		||||
        "narHash": "sha256-HC5vJ3oYsjwsCaSbkIPv80e4ebJpNvFKQTBOGlHvjLs=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "rev": "c24c298562fe41b39909f632c5a7151bbf6b4628",
 | 
			
		||||
        "rev": "0eb314b4f0ba337e88123e0b1e57ef58346aafd9",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -499,11 +574,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "impermanence": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703656108,
 | 
			
		||||
        "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=",
 | 
			
		||||
        "lastModified": 1708968331,
 | 
			
		||||
        "narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "impermanence",
 | 
			
		||||
        "rev": "033643a45a4a920660ef91caa391fbffb14da466",
 | 
			
		||||
        "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -512,19 +587,41 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "nix-github-actions": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "boardie",
 | 
			
		||||
          "poetry2nix",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703863825,
 | 
			
		||||
        "narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "nix-github-actions",
 | 
			
		||||
        "rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "nix-github-actions",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "nixGL": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_8",
 | 
			
		||||
        "flake-utils": "flake-utils_9",
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1685908677,
 | 
			
		||||
        "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=",
 | 
			
		||||
        "lastModified": 1713543440,
 | 
			
		||||
        "narHash": "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "nixGL",
 | 
			
		||||
        "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5",
 | 
			
		||||
        "rev": "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -535,11 +632,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1677383253,
 | 
			
		||||
        "narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=",
 | 
			
		||||
        "lastModified": 1704161960,
 | 
			
		||||
        "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "9952d6bc395f5841262b006fbace8dd7e143b634",
 | 
			
		||||
        "rev": "63143ac2c9186be6d9da6035fa22620018c85932",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -551,11 +648,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-mine": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703756459,
 | 
			
		||||
        "narHash": "sha256-ztEMyPQZh3Pb+LOoWl5lbIK2LenP59sOUBC86CDmLio=",
 | 
			
		||||
        "lastModified": 1717628902,
 | 
			
		||||
        "narHash": "sha256-qMAW+oKis3F8jXTjX9Ng02/LzZd+7YOK05Qa33h9yqY=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "e80160eb2ac3a7111d07cc43a15c16b9edca01ea",
 | 
			
		||||
        "rev": "3e0ee08114e1563b1a0fd6a907563b5e86258fb4",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -567,11 +664,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-mine-stable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703756491,
 | 
			
		||||
        "narHash": "sha256-9VL34e0gzomwqRnryRn23V2ImYcaZIQdp7CsWg5TmlE=",
 | 
			
		||||
        "lastModified": 1717245305,
 | 
			
		||||
        "narHash": "sha256-LrIS3+Aa4F2VmuJPQOASRd3W+uToj878PoUKSLVw/vE=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "36611f5f7cfd401f51ad4ca76fd6ee85a714bb74",
 | 
			
		||||
        "rev": "17a50249712512f600eced89bebcc3252b5f630f",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -583,11 +680,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-stable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703467016,
 | 
			
		||||
        "narHash": "sha256-/5A/dNPhbQx/Oa2d+Get174eNI3LERQ7u6WTWOlR1eQ=",
 | 
			
		||||
        "lastModified": 1716991068,
 | 
			
		||||
        "narHash": "sha256-Av0UWCCiIGJxsZ6TFc+OiKCJNqwoxMNVYDBChmhjNpo=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "d02d818f22c777aa4e854efc3242ec451e5d462a",
 | 
			
		||||
        "rev": "25cf937a30bf0801447f6bf544fc7486c6309234",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -598,11 +695,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-unstable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703438236,
 | 
			
		||||
        "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
 | 
			
		||||
        "lastModified": 1716948383,
 | 
			
		||||
        "narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
 | 
			
		||||
        "rev": "ad57eef4ef0659193044870c731987a6df5cf56b",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -613,15 +710,16 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs_2": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681756206,
 | 
			
		||||
        "narHash": "sha256-7B2Jc1zosXvZJKlxTPBlGew0LeX/7cxguG/d3syc1JI=",
 | 
			
		||||
        "lastModified": 1718632497,
 | 
			
		||||
        "narHash": "sha256-YtlyfqOdYMuu7gumZtK0Kg7jr4OKfHUhJkZfNUryw68=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "6eceb07c28016ec50dd683fda94995702b67e855",
 | 
			
		||||
        "rev": "c58b4a9118498c1055c5908a5bbe666e56abe949",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "ref": "nixos-unstable-small",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
@@ -642,17 +740,52 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs_4": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1709309926,
 | 
			
		||||
        "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "79baff8812a0d68e24a836df0a364c678089e2c7",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "ref": "nixos-23.11",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs_5": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1674990008,
 | 
			
		||||
        "narHash": "sha256-4zOyp+hFW2Y7imxIpZqZGT8CEqKmDjwgfD6BzRUE0mQ=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "d2bbcbe6c626d339b25a4995711f07625b508214",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "ref": "nixpkgs-unstable",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "poetry2nix": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_4",
 | 
			
		||||
        "nixpkgs": "nixpkgs_2"
 | 
			
		||||
        "nix-github-actions": "nix-github-actions",
 | 
			
		||||
        "nixpkgs": "nixpkgs_2",
 | 
			
		||||
        "systems": "systems_4",
 | 
			
		||||
        "treefmt-nix": "treefmt-nix"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681532901,
 | 
			
		||||
        "narHash": "sha256-9ZN/gaCOlkx53km4J2QkLQh4bS+6UCBsjdi87kw6+jc=",
 | 
			
		||||
        "lastModified": 1718726452,
 | 
			
		||||
        "narHash": "sha256-w4hJSYvACz0i5XHtxc6XNyHwbxpisN13M2kA2Y7937o=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "poetry2nix",
 | 
			
		||||
        "rev": "2e66fd2623eccb3086e52929c2cefd882faac8a8",
 | 
			
		||||
        "rev": "53e534a08c0cd2a9fa7587ed1c3e7f6aeb804a2c",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -665,18 +798,18 @@
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "agenix": "agenix",
 | 
			
		||||
        "crane": "crane_2",
 | 
			
		||||
        "flake-utils": "flake-utils_9",
 | 
			
		||||
        "flake-utils": "flake-utils_10",
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ],
 | 
			
		||||
        "rust-overlay": "rust-overlay"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1682237245,
 | 
			
		||||
        "narHash": "sha256-xbBR7LNK+d5Yi/D6FXQGc1R6u2VV2nwr/Df5iaEbOEQ=",
 | 
			
		||||
        "lastModified": 1709831932,
 | 
			
		||||
        "narHash": "sha256-WsP8rOFa/SqYNbVtYJ/l2mWWOgyDTJFbITMV8tv0biI=",
 | 
			
		||||
        "owner": "yaxitech",
 | 
			
		||||
        "repo": "ragenix",
 | 
			
		||||
        "rev": "281f68c3d477904f79ff1cd5807a8c226cd80a50",
 | 
			
		||||
        "rev": "06de099ef02840ec463419f12de73729d458e1eb",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -692,7 +825,7 @@
 | 
			
		||||
        "borgthin": "borgthin",
 | 
			
		||||
        "deploy-rs": "deploy-rs",
 | 
			
		||||
        "devshell": "devshell_3",
 | 
			
		||||
        "flake-utils": "flake-utils_7",
 | 
			
		||||
        "flake-utils": "flake-utils_8",
 | 
			
		||||
        "home-manager-stable": "home-manager-stable",
 | 
			
		||||
        "home-manager-unstable": "home-manager-unstable",
 | 
			
		||||
        "impermanence": "impermanence",
 | 
			
		||||
@@ -717,11 +850,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1682129965,
 | 
			
		||||
        "narHash": "sha256-1KRPIorEL6pLpJR04FwAqqnt4Tzcm4MqD84yhlD+XSk=",
 | 
			
		||||
        "lastModified": 1708740535,
 | 
			
		||||
        "narHash": "sha256-NCTw235XwSDbeTAtAwg/hOeNOgwYhVq7JjDdbkOgBeA=",
 | 
			
		||||
        "owner": "oxalica",
 | 
			
		||||
        "repo": "rust-overlay",
 | 
			
		||||
        "rev": "2c417c0460b788328220120c698630947547ee83",
 | 
			
		||||
        "rev": "9b24383d77f598716fa0cbb8b48c97249f5ee1af",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -730,23 +863,44 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "sbt": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_13",
 | 
			
		||||
        "nixpkgs": "nixpkgs_5"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1698464090,
 | 
			
		||||
        "narHash": "sha256-Pnej7WZIPomYWg8f/CZ65sfW85IfIUjYhphMMg7/LT0=",
 | 
			
		||||
        "owner": "zaninime",
 | 
			
		||||
        "repo": "sbt-derivation",
 | 
			
		||||
        "rev": "6762cf2c31de50efd9ff905cbcc87239995a4ef9",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "zaninime",
 | 
			
		||||
        "repo": "sbt-derivation",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "sharry": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": "flake-utils_10",
 | 
			
		||||
        "devshell-tools": "devshell-tools",
 | 
			
		||||
        "flake-utils": "flake-utils_12",
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ]
 | 
			
		||||
        ],
 | 
			
		||||
        "sbt": "sbt"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1687587666,
 | 
			
		||||
        "narHash": "sha256-t1VNvdQdDUFTEKTFP2fc7Fb3buQBmP+h9WUeO8b2Bus=",
 | 
			
		||||
        "owner": "eikek",
 | 
			
		||||
        "lastModified": 1710796573,
 | 
			
		||||
        "narHash": "sha256-23fLZFNacZU/skc8i7JExHfD//Mpkslhga6f5ATTqBA=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "sharry",
 | 
			
		||||
        "rev": "a9b3371aa6c7b92088b20fd6e479c251a5556b86",
 | 
			
		||||
        "rev": "4e7a87880ba0807afd5d21706ce383b8b8727990",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "eikek",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "sharry",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
@@ -766,6 +920,36 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_10": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_11": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_2": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
@@ -806,9 +990,8 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
        "id": "systems",
 | 
			
		||||
        "type": "indirect"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_5": {
 | 
			
		||||
@@ -841,9 +1024,76 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_7": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_8": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_9": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "treefmt-nix": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "boardie",
 | 
			
		||||
          "poetry2nix",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1718522839,
 | 
			
		||||
        "narHash": "sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "treefmt-nix",
 | 
			
		||||
        "rev": "68eb1dc333ce82d0ab0c0357363ea17c31ea1f81",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "treefmt-nix",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "utils": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_3"
 | 
			
		||||
        "systems": "systems_5"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701680307,
 | 
			
		||||
 
 | 
			
		||||
@@ -24,13 +24,14 @@
 | 
			
		||||
 | 
			
		||||
    # Stuff used by systems
 | 
			
		||||
    impermanence.url = "github:nix-community/impermanence";
 | 
			
		||||
    boardie.url = "github:devplayer0/boardie";
 | 
			
		||||
    boardie.url = "git+https://git.nul.ie/dev/boardie";
 | 
			
		||||
    boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
			
		||||
    nixGL.url = "github:nix-community/nixGL";
 | 
			
		||||
    nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
			
		||||
 | 
			
		||||
    # Packages not in nixpkgs
 | 
			
		||||
    sharry.url = "github:eikek/sharry";
 | 
			
		||||
    # sharry.url = "github:eikek/sharry";
 | 
			
		||||
    sharry.url = "github:devplayer0/sharry";
 | 
			
		||||
    sharry.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
			
		||||
    borgthin.url = "github:devplayer0/borg";
 | 
			
		||||
    borgthin.inputs.nixpkgs.follows = "nixpkgs-mine";
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										28
									
								
								home-manager/modules/gui/alacritty-xterm.toml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								home-manager/modules/gui/alacritty-xterm.toml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,28 @@
 | 
			
		||||
# XTerm's default colors
 | 
			
		||||
 | 
			
		||||
# Default colors
 | 
			
		||||
[colors.primary]
 | 
			
		||||
background = '#000000'
 | 
			
		||||
foreground = '#ffffff'
 | 
			
		||||
 | 
			
		||||
# Normal colors
 | 
			
		||||
[colors.normal]
 | 
			
		||||
black   = '#000000'
 | 
			
		||||
red     = '#cd0000'
 | 
			
		||||
green   = '#00cd00'
 | 
			
		||||
yellow  = '#cdcd00'
 | 
			
		||||
blue    = '#0000ee'
 | 
			
		||||
magenta = '#cd00cd'
 | 
			
		||||
cyan    = '#00cdcd'
 | 
			
		||||
white   = '#e5e5e5'
 | 
			
		||||
 | 
			
		||||
# Bright colors
 | 
			
		||||
[colors.bright]
 | 
			
		||||
black   = '#7f7f7f'
 | 
			
		||||
red     = '#ff0000'
 | 
			
		||||
green   = '#00ff00'
 | 
			
		||||
yellow  = '#ffff00'
 | 
			
		||||
blue    = '#5c5cff'
 | 
			
		||||
magenta = '#ff00ff'
 | 
			
		||||
cyan    = '#00ffff'
 | 
			
		||||
white   = '#ffffff'
 | 
			
		||||
@@ -10,6 +10,23 @@ let
 | 
			
		||||
    name = "Monocraft";
 | 
			
		||||
    size = 10;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  doomWad = pkgs.fetchurl {
 | 
			
		||||
    url = "https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad";
 | 
			
		||||
    hash = "sha256-HX1DvlAeZ9kn5BXguPPinDvzMHXoWXIYFvZSpSbKx3E=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  doomsaver = pkgs.runCommand "doomsaver" {
 | 
			
		||||
    inherit (pkgs) windowtolayer;
 | 
			
		||||
    chocoDoom = pkgs.chocolate-doom2xx;
 | 
			
		||||
    python = pkgs.python3.withPackages (ps: [ ps.filelock ]);
 | 
			
		||||
    inherit doomWad;
 | 
			
		||||
    enojy = ./enojy.jpg;
 | 
			
		||||
  } ''
 | 
			
		||||
    mkdir -p "$out"/bin
 | 
			
		||||
    substituteAll ${./screensaver.py} "$out"/bin/doomsaver
 | 
			
		||||
    chmod +x "$out"/bin/doomsaver
 | 
			
		||||
  '';
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  options.my.gui = {
 | 
			
		||||
@@ -32,11 +49,19 @@ in
 | 
			
		||||
            slurp
 | 
			
		||||
            swappy
 | 
			
		||||
 | 
			
		||||
            python310Packages.python-lsp-server
 | 
			
		||||
            python3Packages.python-lsp-server
 | 
			
		||||
            nil # nix language server
 | 
			
		||||
            zls # zig language server
 | 
			
		||||
            rust-analyzer
 | 
			
		||||
 | 
			
		||||
            cowsay
 | 
			
		||||
            fortune
 | 
			
		||||
            jp2a
 | 
			
		||||
            terminaltexteffects
 | 
			
		||||
            screenfetch
 | 
			
		||||
            neofetch
 | 
			
		||||
            cmatrix
 | 
			
		||||
            doomsaver
 | 
			
		||||
          ];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -51,7 +76,15 @@ in
 | 
			
		||||
          alacritty = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
              font.normal.family = font.name;
 | 
			
		||||
              import = [ ./alacritty-xterm.toml ];
 | 
			
		||||
 | 
			
		||||
              font = {
 | 
			
		||||
                size = font.size;
 | 
			
		||||
                normal = {
 | 
			
		||||
                  family = font.name;
 | 
			
		||||
                  style = "Regular";
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
@@ -65,6 +98,25 @@ in
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          termite = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            font = "${font.name} ${toString font.size}";
 | 
			
		||||
            backgroundColor = "rgba(0, 0, 0, 0.8)";
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          foot = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
              main = {
 | 
			
		||||
                font = "${font.name}:size=${toString font.size}";
 | 
			
		||||
              };
 | 
			
		||||
              colors = {
 | 
			
		||||
                alpha = 0.8;
 | 
			
		||||
                background = "000000";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          helix = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
@@ -162,7 +214,7 @@ in
 | 
			
		||||
                  in
 | 
			
		||||
                  lib.mkOptionDefault {
 | 
			
		||||
                    "${mod}+d" = null;
 | 
			
		||||
                    "${mod}+l" = "exec swaylock -i ${./lock.png} -s stretch";
 | 
			
		||||
                    "${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
 | 
			
		||||
                    "${mod}+x" = "exec ${cfg.menu}";
 | 
			
		||||
                    "${mod}+Shift+x" = "exec rofi -show drun";
 | 
			
		||||
                    "${mod}+q" = "kill";
 | 
			
		||||
@@ -210,17 +262,10 @@ in
 | 
			
		||||
        };
 | 
			
		||||
        qt = {
 | 
			
		||||
          enable = true;
 | 
			
		||||
          platformTheme = "gtk";
 | 
			
		||||
          platformTheme.name = "gtk";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        services = {
 | 
			
		||||
          swaync = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
              widgets = [ "title" "dnd" "mpris" "notifications" ];
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          playerctld.enable = true;
 | 
			
		||||
          spotifyd = {
 | 
			
		||||
            enable = false;
 | 
			
		||||
@@ -297,6 +342,15 @@ in
 | 
			
		||||
            ] (_: "chromium-browser.desktop");
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        my = {
 | 
			
		||||
          swaync = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            settings = {
 | 
			
		||||
              widgets = [ "title" "dnd" "mpris" "notifications" ];
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      })
 | 
			
		||||
 | 
			
		||||
      (mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) {
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										
											BIN
										
									
								
								home-manager/modules/gui/enojy.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								home-manager/modules/gui/enojy.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.4 KiB  | 
							
								
								
									
										209
									
								
								home-manager/modules/gui/screensaver.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										209
									
								
								home-manager/modules/gui/screensaver.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,209 @@
 | 
			
		||||
#!@python@/bin/python
 | 
			
		||||
import argparse
 | 
			
		||||
import json
 | 
			
		||||
import os
 | 
			
		||||
import random
 | 
			
		||||
import signal
 | 
			
		||||
import subprocess
 | 
			
		||||
import sys
 | 
			
		||||
 | 
			
		||||
import filelock
 | 
			
		||||
 | 
			
		||||
class Screensaver:
 | 
			
		||||
    def __init__(self, cmd, env=None, weight=1):
 | 
			
		||||
        self.cmd = cmd
 | 
			
		||||
        self.weight = weight
 | 
			
		||||
 | 
			
		||||
        if env is not None:
 | 
			
		||||
            self.env = os.environ.copy()
 | 
			
		||||
            for k, v in env.items():
 | 
			
		||||
                self.env[k] = v
 | 
			
		||||
        else:
 | 
			
		||||
            self.env = None
 | 
			
		||||
        self.proc = None
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        assert self.proc is None
 | 
			
		||||
        self.proc = subprocess.Popen(self.cmd, env=self.env)
 | 
			
		||||
 | 
			
		||||
    def wait(self):
 | 
			
		||||
        assert self.proc is not None
 | 
			
		||||
        self.proc.wait()
 | 
			
		||||
 | 
			
		||||
    def stop(self, kill=False):
 | 
			
		||||
        assert self.proc is not None
 | 
			
		||||
        if kill:
 | 
			
		||||
            self.proc.kill()
 | 
			
		||||
        else:
 | 
			
		||||
            self.proc.terminate()
 | 
			
		||||
 | 
			
		||||
class DoomSaver(Screensaver):
 | 
			
		||||
    wad = '@doomWad@'
 | 
			
		||||
 | 
			
		||||
    def __init__(self, demo_index, weight=1.5):
 | 
			
		||||
        super().__init__(
 | 
			
		||||
            ['@chocoDoom@/bin/chocolate-doom',
 | 
			
		||||
             '-iwad', self.wad,
 | 
			
		||||
             '-demoloopi', str(demo_index)],
 | 
			
		||||
            env={
 | 
			
		||||
                'SDL_AUDIODRIVER': 'null',
 | 
			
		||||
                'SDL_VIDEODRIVER': 'caca',
 | 
			
		||||
                'CACA_DRIVER': 'ncurses',
 | 
			
		||||
            },
 | 
			
		||||
            weight=weight,
 | 
			
		||||
        )
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        super().stop(kill=True)
 | 
			
		||||
 | 
			
		||||
class TTESaver(Screensaver):
 | 
			
		||||
    effects = (
 | 
			
		||||
        'beams,binarypath,blackhole,bouncyballs,bubbles,burn,colorshift,crumble,'
 | 
			
		||||
        'decrypt,errorcorrect,expand,fireworks,middleout,orbittingvolley,overflow,'
 | 
			
		||||
        'pour,print,rain,randomsequence,rings,scattered,slice,slide,spotlights,'
 | 
			
		||||
        'spray,swarm,synthgrid,unstable,vhstape,waves,wipe'
 | 
			
		||||
    ).split(',')
 | 
			
		||||
 | 
			
		||||
    def __init__(self, cmd, env=None, weight=1):
 | 
			
		||||
        super().__init__(cmd, env=env, weight=weight)
 | 
			
		||||
        self.running = False
 | 
			
		||||
 | 
			
		||||
    def start(self):
 | 
			
		||||
        self.running = True
 | 
			
		||||
 | 
			
		||||
    def wait(self):
 | 
			
		||||
        while self.running:
 | 
			
		||||
            effect_cmd = ['tte', random.choice(self.effects)]
 | 
			
		||||
            print(f"$ {self.cmd} | {' '.join(effect_cmd)}")
 | 
			
		||||
            content = subprocess.check_output(self.cmd, shell=True, env=self.env, stderr=subprocess.DEVNULL)
 | 
			
		||||
 | 
			
		||||
            self.proc = subprocess.Popen(effect_cmd, stdin=subprocess.PIPE)
 | 
			
		||||
            self.proc.stdin.write(content)
 | 
			
		||||
            self.proc.stdin.close()
 | 
			
		||||
            self.proc.wait()
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        self.running = False
 | 
			
		||||
        self.proc.terminate()
 | 
			
		||||
 | 
			
		||||
class MultiSaver:
 | 
			
		||||
    savers = [
 | 
			
		||||
        DoomSaver(0),
 | 
			
		||||
        DoomSaver(1),
 | 
			
		||||
        DoomSaver(2),
 | 
			
		||||
 | 
			
		||||
        Screensaver(['cmatrix']),
 | 
			
		||||
 | 
			
		||||
        TTESaver('screenfetch -N'),
 | 
			
		||||
        TTESaver('fortune | cowsay'),
 | 
			
		||||
        TTESaver('top -bn1 | head -n50'),
 | 
			
		||||
        TTESaver('ss -nltu'),
 | 
			
		||||
        TTESaver('ss -ntu'),
 | 
			
		||||
        TTESaver('jp2a --width=100 @enojy@'),
 | 
			
		||||
    ]
 | 
			
		||||
    state_filename = 'screensaver.json'
 | 
			
		||||
 | 
			
		||||
    def __init__(self, select=None):
 | 
			
		||||
        self.state_path = os.path.join(f'/run/user/{os.geteuid()}', self.state_filename)
 | 
			
		||||
        self.lock = filelock.FileLock(f'{self.state_path}.lock')
 | 
			
		||||
 | 
			
		||||
        if select is not None:
 | 
			
		||||
            assert select >= 0 and select < len(self.savers), 'Invalid screensaver index'
 | 
			
		||||
            self.selected = self.savers[select]
 | 
			
		||||
        else:
 | 
			
		||||
            self.selected = None
 | 
			
		||||
        self.cleaned_up = False
 | 
			
		||||
 | 
			
		||||
    def select(self):
 | 
			
		||||
        with self.lock:
 | 
			
		||||
            if not os.path.exists(self.state_path):
 | 
			
		||||
                state = {'instances': []}
 | 
			
		||||
            else:
 | 
			
		||||
                with open(self.state_path) as f:
 | 
			
		||||
                    state = json.load(f)
 | 
			
		||||
 | 
			
		||||
            if self.selected is None:
 | 
			
		||||
                available = set(range(len(self.savers)))
 | 
			
		||||
                new_instances = []
 | 
			
		||||
                for instance in state['instances']:
 | 
			
		||||
                    if not os.path.exists(f"/proc/{instance['pid']}"):
 | 
			
		||||
                        continue
 | 
			
		||||
 | 
			
		||||
                    new_instances.append(instance)
 | 
			
		||||
                    i = instance['saver']
 | 
			
		||||
                    assert i in available
 | 
			
		||||
                    available.remove(i)
 | 
			
		||||
                assert available, 'No screensavers left'
 | 
			
		||||
                available = list(available)
 | 
			
		||||
 | 
			
		||||
                weights = []
 | 
			
		||||
                for i in available:
 | 
			
		||||
                    weights.append(self.savers[i].weight)
 | 
			
		||||
                selected_i = random.choices(available, weights=weights)[0]
 | 
			
		||||
 | 
			
		||||
                new_instances.append({'pid': os.getpid(), 'saver': selected_i})
 | 
			
		||||
                state['instances'] = new_instances
 | 
			
		||||
 | 
			
		||||
                # print(f'Selected saver {selected_i}')
 | 
			
		||||
                self.selected = self.savers[selected_i]
 | 
			
		||||
 | 
			
		||||
            with open(self.state_path, 'w') as f:
 | 
			
		||||
                json.dump(state, f)
 | 
			
		||||
 | 
			
		||||
    def cleanup(self):
 | 
			
		||||
        if self.cleaned_up:
 | 
			
		||||
            return
 | 
			
		||||
        self.cleaned_up = True
 | 
			
		||||
 | 
			
		||||
        with self.lock:
 | 
			
		||||
            with open(self.state_path) as f:
 | 
			
		||||
                state = json.load(f)
 | 
			
		||||
 | 
			
		||||
            for i, instance in enumerate(state['instances']):
 | 
			
		||||
                if instance['pid'] == os.getpid():
 | 
			
		||||
                    del state['instances'][i]
 | 
			
		||||
 | 
			
		||||
            with open(self.state_path, 'w') as f:
 | 
			
		||||
                json.dump(state, f)
 | 
			
		||||
 | 
			
		||||
    def run(self):
 | 
			
		||||
        assert self.selected is not None
 | 
			
		||||
        self.selected.start()
 | 
			
		||||
 | 
			
		||||
        signal.signal(signal.SIGINT, self._sighandler)
 | 
			
		||||
        signal.signal(signal.SIGTERM, self._sighandler)
 | 
			
		||||
        signal.signal(signal.SIGHUP, self._sighandler)
 | 
			
		||||
        self.selected.wait()
 | 
			
		||||
        self.cleanup()
 | 
			
		||||
 | 
			
		||||
    def stop(self):
 | 
			
		||||
        assert self.selected is not None
 | 
			
		||||
        print('Shutting down')
 | 
			
		||||
        self.selected.stop()
 | 
			
		||||
        self.cleanup()
 | 
			
		||||
    def _sighandler(self, signum, frame):
 | 
			
		||||
        self.stop()
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Wayland terminal-based lock screen')
 | 
			
		||||
    parser.add_argument('-l', '--locker-cmd', default='swaylock-plugin', help='swaylock-plugin command to use')
 | 
			
		||||
    parser.add_argument('-t', '--terminal', default='alacritty', help='Terminal emulator to use')
 | 
			
		||||
    parser.add_argument('-i', '--instance', action='store_true', help='Run as instance')
 | 
			
		||||
    parser.add_argument('-s', '--screensaver', type=int, help='Force use of specific screensaver')
 | 
			
		||||
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
    if not args.instance:
 | 
			
		||||
        cmd = [
 | 
			
		||||
            args.locker_cmd, '--command-each',
 | 
			
		||||
            f'@windowtolayer@/bin/windowtolayer -- {args.terminal} -e {sys.argv[0]} --instance']
 | 
			
		||||
        if args.screensaver is not None:
 | 
			
		||||
            cmd[-1] += f' --screensaver {args.screensaver}'
 | 
			
		||||
        subprocess.check_call(cmd)
 | 
			
		||||
        return
 | 
			
		||||
 | 
			
		||||
    ms = MultiSaver(select=args.screensaver)
 | 
			
		||||
    ms.select()
 | 
			
		||||
    ms.run()
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
@@ -146,9 +146,9 @@ in
 | 
			
		||||
          dnd-none = "";
 | 
			
		||||
        };
 | 
			
		||||
        return-type = "json";
 | 
			
		||||
        exec = "${config.services.swaync.package}/bin/swaync-client -swb";
 | 
			
		||||
        on-click = "${config.services.swaync.package}/bin/swaync-client -t -sw";
 | 
			
		||||
        on-click-right = "${config.services.swaync.package}/bin/swaync-client -d -sw";
 | 
			
		||||
        exec = "${config.my.swaync.package}/bin/swaync-client -swb";
 | 
			
		||||
        on-click = "${config.my.swaync.package}/bin/swaync-client -t -sw";
 | 
			
		||||
        on-click-right = "${config.my.swaync.package}/bin/swaync-client -d -sw";
 | 
			
		||||
        escape = true;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -19,10 +19,10 @@ let
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  cfg = config.services.swaync;
 | 
			
		||||
  cfg = config.my.swaync;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  options.services.swaync = with lib.types; {
 | 
			
		||||
  options.my.swaync = with lib.types; {
 | 
			
		||||
    enable = mkEnableOption "Sway Notification Center";
 | 
			
		||||
    package = mkOption {
 | 
			
		||||
      type = package;
 | 
			
		||||
 
 | 
			
		||||
@@ -11,6 +11,8 @@ rec {
 | 
			
		||||
      jellyseerr = 402;
 | 
			
		||||
      atticd = 403;
 | 
			
		||||
      kea = 404;
 | 
			
		||||
      keepalived_script = 405;
 | 
			
		||||
      photoprism = 406;
 | 
			
		||||
    };
 | 
			
		||||
    gids = {
 | 
			
		||||
      matrix-syncv3 = 400;
 | 
			
		||||
@@ -18,12 +20,14 @@ rec {
 | 
			
		||||
      jellyseerr = 402;
 | 
			
		||||
      atticd = 403;
 | 
			
		||||
      kea = 404;
 | 
			
		||||
      keepalived_script = 405;
 | 
			
		||||
      photoprism = 406;
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  kernel = {
 | 
			
		||||
    lts = pkgs: pkgs.linuxKernel.packages.linux_6_1;
 | 
			
		||||
    latest = pkgs: pkgs.linuxKernel.packages.linux_6_6;
 | 
			
		||||
    lts = pkgs: pkgs.linuxKernel.packages.linux_6_6;
 | 
			
		||||
    latest = pkgs: pkgs.linuxKernel.packages.linux_6_9;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  nginx = rec {
 | 
			
		||||
@@ -107,7 +111,7 @@ rec {
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  pubDomain = "nul.ie";
 | 
			
		||||
  colony = {
 | 
			
		||||
  colony = rec {
 | 
			
		||||
    domain = "ams1.int.${pubDomain}";
 | 
			
		||||
    pubV4 = "94.142.240.44";
 | 
			
		||||
    prefixes = with lib.my.net.cidr; rec {
 | 
			
		||||
@@ -144,6 +148,10 @@ rec {
 | 
			
		||||
        v4 = "94.142.242.255/32";
 | 
			
		||||
        v6 = subnet 8 1 cust.v6;
 | 
			
		||||
      };
 | 
			
		||||
      jam = {
 | 
			
		||||
        v4 = subnet 8 4 cust.v4;
 | 
			
		||||
        v6 = subnet 8 2 cust.v6;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      vip1 = "94.142.241.224/30";
 | 
			
		||||
      vip2 = "94.142.242.254/31";
 | 
			
		||||
@@ -156,6 +164,12 @@ rec {
 | 
			
		||||
      home.v6 = "2a0e:97c0:4d0::/48";
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    custRouting = with lib.my.net.cidr; {
 | 
			
		||||
      mail-vm = host 1 prefixes.cust.v4;
 | 
			
		||||
      darts-vm = host 2 prefixes.cust.v4;
 | 
			
		||||
      jam-ctr = host 3 prefixes.cust.v4;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    firewallForwards = aa: [
 | 
			
		||||
      {
 | 
			
		||||
        port = "http";
 | 
			
		||||
@@ -169,6 +183,7 @@ rec {
 | 
			
		||||
        port = 8448;
 | 
			
		||||
        dst = aa.middleman.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      {
 | 
			
		||||
        port = 25565;
 | 
			
		||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
			
		||||
@@ -177,6 +192,7 @@ rec {
 | 
			
		||||
        port = 25566;
 | 
			
		||||
        dst = aa.simpcraft-staging-oci.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      {
 | 
			
		||||
        port = 25575;
 | 
			
		||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
			
		||||
@@ -227,7 +243,7 @@ rec {
 | 
			
		||||
      "stream"
 | 
			
		||||
    ];
 | 
			
		||||
    routersPubV4 = [
 | 
			
		||||
      "109.255.1.246"
 | 
			
		||||
      "188.141.14.7"
 | 
			
		||||
      "109.255.252.63"
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
@@ -327,6 +343,7 @@ rec {
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    domain = "hentai.engineer";
 | 
			
		||||
    ipv4MTU = 1460;
 | 
			
		||||
    vpn = {
 | 
			
		||||
      port = 51820;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -248,8 +248,8 @@ rec {
 | 
			
		||||
  in
 | 
			
		||||
  {
 | 
			
		||||
    trivial = prev.trivial // {
 | 
			
		||||
      release = "23.12:u-${prev.trivial.release}";
 | 
			
		||||
      codeName = "Amogus";
 | 
			
		||||
      release = "24.06:u-${prev.trivial.release}";
 | 
			
		||||
      codeName = "Carbrain";
 | 
			
		||||
      revisionWithDefault = default: self.rev or default;
 | 
			
		||||
      versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}";
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -101,6 +101,12 @@ in
 | 
			
		||||
            dnssec = "false";
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          pipewire.extraConfig.pipewire = {
 | 
			
		||||
            "10-buffer"."context.properties" = {
 | 
			
		||||
              "default.clock.quantum" = 128;
 | 
			
		||||
              "default.clock.max-quantum" = 128;
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
          blueman.enable = true;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -131,14 +137,6 @@ in
 | 
			
		||||
          qperf
 | 
			
		||||
          ethtool
 | 
			
		||||
        ];
 | 
			
		||||
        environment.etc = {
 | 
			
		||||
          "pipewire/pipewire.conf.d/sample-size.conf".text = ''
 | 
			
		||||
            context.properties = {
 | 
			
		||||
              default.clock.quantum = 128
 | 
			
		||||
              default.clock.max-quantum = 128
 | 
			
		||||
            }
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        nix = {
 | 
			
		||||
          gc.automatic = false;
 | 
			
		||||
@@ -205,10 +203,7 @@ in
 | 
			
		||||
                packages = with pkgs; [
 | 
			
		||||
                  jacktrip
 | 
			
		||||
                  qpwgraph
 | 
			
		||||
                  # TODO: seems to be borked (infinite recursion???)
 | 
			
		||||
                  # (writeShellScriptBin "boardie" ''
 | 
			
		||||
                  #   exec pw-jack ${boardie}/bin/boardie "$@"
 | 
			
		||||
                  # '')
 | 
			
		||||
                  boardie
 | 
			
		||||
                ];
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c.colony) domain prefixes firewallForwards;
 | 
			
		||||
  inherit (lib.my.c.colony) domain prefixes custRouting firewallForwards;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  imports = [ ./vms ];
 | 
			
		||||
@@ -60,8 +60,8 @@ in
 | 
			
		||||
          kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
 | 
			
		||||
            kernel = super.kernel.override {
 | 
			
		||||
              structuredExtraConfig = with lib.kernel; {
 | 
			
		||||
                #SOME_OPT = yes;
 | 
			
		||||
                #A_MOD = module;
 | 
			
		||||
                ACPI_APEI_PCIEAER = yes;
 | 
			
		||||
                PCIEAER = yes;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          });
 | 
			
		||||
@@ -150,12 +150,12 @@ in
 | 
			
		||||
            "serial-getty@ttyS1".enable = true;
 | 
			
		||||
            lvm-activate-main = {
 | 
			
		||||
              description = "Activate remaining LVs";
 | 
			
		||||
              before = [ "local-fs-pre.target" ];
 | 
			
		||||
              unitConfig.DefaultDependencies = false;
 | 
			
		||||
              serviceConfig = {
 | 
			
		||||
                Type = "oneshot";
 | 
			
		||||
                ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
 | 
			
		||||
              };
 | 
			
		||||
              wantedBy = [ "sysinit.target" ];
 | 
			
		||||
              wantedBy = [ "local-fs-pre.target" ];
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            rsync-lvm-meta = {
 | 
			
		||||
@@ -276,6 +276,10 @@ in
 | 
			
		||||
                      Destination = lib.my.c.tailscale.prefix.v6;
 | 
			
		||||
                      Gateway = allAssignments.shill.internal.ipv6.address;
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                      Destination = prefixes.jam.v6;
 | 
			
		||||
                      Gateway = allAssignments.shill.internal.ipv6.address;
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    {
 | 
			
		||||
                      Destination = prefixes.oci.v4;
 | 
			
		||||
@@ -307,7 +311,7 @@ in
 | 
			
		||||
              "90-vm-mail" = {
 | 
			
		||||
                matchConfig.Name = "vm-mail";
 | 
			
		||||
                address = [
 | 
			
		||||
                  (net.cidr.subnet 8 1 prefixes.cust.v4)
 | 
			
		||||
                  "${custRouting.mail-vm}/32"
 | 
			
		||||
                  prefixes.mail.v6
 | 
			
		||||
                ];
 | 
			
		||||
                networkConfig = {
 | 
			
		||||
@@ -330,7 +334,7 @@ in
 | 
			
		||||
              "90-vm-darts" = {
 | 
			
		||||
                matchConfig.Name = "vm-darts";
 | 
			
		||||
                address = [
 | 
			
		||||
                  (net.cidr.subnet 8 2 prefixes.cust.v4)
 | 
			
		||||
                  "${custRouting.darts-vm}/32"
 | 
			
		||||
                  prefixes.darts.v6
 | 
			
		||||
                ];
 | 
			
		||||
                networkConfig = {
 | 
			
		||||
 
 | 
			
		||||
@@ -131,6 +131,7 @@
 | 
			
		||||
              (vm.lvmDisk "media")
 | 
			
		||||
              (vm.lvmDisk "minio")
 | 
			
		||||
              (vm.lvmDisk "nix-atticd")
 | 
			
		||||
              (vm.lvmDisk "jam")
 | 
			
		||||
            ]);
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
@@ -209,6 +210,7 @@
 | 
			
		||||
            drives = [
 | 
			
		||||
              (mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ])
 | 
			
		||||
              (vm.lvmDisk' "media" "darts-media")
 | 
			
		||||
              (vm.lvmDisk' "ext" "darts-ext")
 | 
			
		||||
            ];
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -9,6 +9,7 @@ in
 | 
			
		||||
    vpns = {
 | 
			
		||||
      l2 = {
 | 
			
		||||
        as211024 = {
 | 
			
		||||
          udpEncapsulation = true;
 | 
			
		||||
          vni = 211024;
 | 
			
		||||
          security.enable = true;
 | 
			
		||||
          peers = {
 | 
			
		||||
@@ -393,6 +394,9 @@ in
 | 
			
		||||
                      # Safe enough to allow all SSH
 | 
			
		||||
                      tcp dport ssh accept
 | 
			
		||||
 | 
			
		||||
                      # jam-ctr forwards
 | 
			
		||||
                      ip daddr ${aa.shill.internal.ipv4.address} tcp dport 60022 accept
 | 
			
		||||
 | 
			
		||||
                      ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept
 | 
			
		||||
                      ${matchInet "tcp dport { http, https } accept" "git"}
 | 
			
		||||
                      ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) attrNames;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c.colony) prefixes;
 | 
			
		||||
  inherit (lib.my.c.colony) prefixes custRouting;
 | 
			
		||||
 | 
			
		||||
  authZones = attrNames config.my.pdns.auth.bind.zones;
 | 
			
		||||
in
 | 
			
		||||
@@ -162,6 +162,10 @@ in
 | 
			
		||||
 | 
			
		||||
            andrey-cust IN A ${allAssignments.kelder.estuary.ipv4.address}
 | 
			
		||||
 | 
			
		||||
            jam-cust IN A ${net.cidr.host 0 prefixes.jam.v4}
 | 
			
		||||
            jam-fwd IN A ${allAssignments.shill.internal.ipv4.address}
 | 
			
		||||
            jam-cust IN AAAA ${net.cidr.host 1 prefixes.jam.v6}
 | 
			
		||||
 | 
			
		||||
            $TTL 3
 | 
			
		||||
            _acme-challenge IN LUA TXT @@FILE@@
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										105
									
								
								nixos/boxes/colony/vms/shill/containers-ext.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								nixos/boxes/colony/vms/shill/containers-ext.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
			
		||||
{ lib, pkgs, assignments, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c.colony) prefixes custRouting;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  fileSystems = {
 | 
			
		||||
    "/mnt/jam" = {
 | 
			
		||||
      device = "/dev/disk/by-label/jam";
 | 
			
		||||
      fsType = "ext4";
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    "/var/lib/machines/jam" = {
 | 
			
		||||
      device = "/mnt/jam";
 | 
			
		||||
      options = [ "bind" ];
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  systemd = {
 | 
			
		||||
    nspawn = {
 | 
			
		||||
      jam = {
 | 
			
		||||
        enable = true;
 | 
			
		||||
        execConfig = {
 | 
			
		||||
          Boot = true;
 | 
			
		||||
          PrivateUsers = "pick";
 | 
			
		||||
          LinkJournal = false;
 | 
			
		||||
        };
 | 
			
		||||
        networkConfig = {
 | 
			
		||||
          Private = true;
 | 
			
		||||
          VirtualEthernet = true;
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
    network.networks = {
 | 
			
		||||
      "50-ve-jam" = {
 | 
			
		||||
        matchConfig = {
 | 
			
		||||
          Kind = "veth";
 | 
			
		||||
          Name = "ve-jam";
 | 
			
		||||
        };
 | 
			
		||||
        address = [
 | 
			
		||||
          custRouting.jam-ctr
 | 
			
		||||
          prefixes.jam.v6
 | 
			
		||||
        ];
 | 
			
		||||
        networkConfig = {
 | 
			
		||||
          IPv6AcceptRA = false;
 | 
			
		||||
          IPv6SendRA = true;
 | 
			
		||||
        };
 | 
			
		||||
        ipv6Prefixes = [
 | 
			
		||||
          {
 | 
			
		||||
            ipv6PrefixConfig.Prefix = prefixes.jam.v6;
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
        routes = map (r: { routeConfig = r; }) [
 | 
			
		||||
          {
 | 
			
		||||
            Destination = prefixes.jam.v4;
 | 
			
		||||
            Scope = "link";
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
    services = {
 | 
			
		||||
      "systemd-nspawn@jam" = {
 | 
			
		||||
        overrideStrategy = "asDropin";
 | 
			
		||||
 | 
			
		||||
        serviceConfig = {
 | 
			
		||||
          CPUQuota = "400%";
 | 
			
		||||
          MemoryHigh = "4G";
 | 
			
		||||
          MemoryMax = "4.5G";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        wantedBy = [ "machines.target" ];
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  my = {
 | 
			
		||||
    firewall =
 | 
			
		||||
    let
 | 
			
		||||
      jamIP = net.cidr.host 0 prefixes.jam.v4;
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
      nat.forwardPorts."${assignments.internal.ipv4.address}" = [
 | 
			
		||||
        {
 | 
			
		||||
          port = 60022;
 | 
			
		||||
          dst = jamIP;
 | 
			
		||||
          dstPort = "ssh";
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
      extraRules = ''
 | 
			
		||||
        table inet filter {
 | 
			
		||||
          chain forward {
 | 
			
		||||
            iifname { ve-jam } oifname vms accept
 | 
			
		||||
            iifname vms oifname { ve-jam } accept
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        table inet nat {
 | 
			
		||||
          chain postrouting {
 | 
			
		||||
            ip saddr ${jamIP} snat to ${assignments.internal.ipv4.address}
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      '';
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
@@ -24,7 +24,7 @@ in
 | 
			
		||||
 | 
			
		||||
    configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
 | 
			
		||||
    let
 | 
			
		||||
      inherit (lib) mkMerge mkIf mkForce;
 | 
			
		||||
      inherit (lib) genAttrs mkMerge mkIf mkForce;
 | 
			
		||||
      inherit (lib.my) networkdAssignment;
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
@@ -45,10 +45,28 @@ in
 | 
			
		||||
                  owner = "matrix-synapse";
 | 
			
		||||
                  group = "matrix-synapse";
 | 
			
		||||
                };
 | 
			
		||||
                "chatterbox/doublepuppet.yaml" = {
 | 
			
		||||
                  owner = "matrix-synapse";
 | 
			
		||||
                  group = "matrix-synapse";
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                "chatterbox/syncv3.env" = {
 | 
			
		||||
                  owner = "matrix-syncv3";
 | 
			
		||||
                  group = "matrix-syncv3";
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                "chatterbox/mautrix-whatsapp.env" = {
 | 
			
		||||
                  owner = "mautrix-whatsapp";
 | 
			
		||||
                  group = "mautrix-whatsapp";
 | 
			
		||||
                };
 | 
			
		||||
                "chatterbox/mautrix-messenger.env" = {
 | 
			
		||||
                  owner = "mautrix-meta-messenger";
 | 
			
		||||
                  group = "mautrix-meta";
 | 
			
		||||
                };
 | 
			
		||||
                "chatterbox/mautrix-instagram.env" = {
 | 
			
		||||
                  owner = "mautrix-meta-instagram";
 | 
			
		||||
                  group = "mautrix-meta";
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -59,6 +77,9 @@ in
 | 
			
		||||
 | 
			
		||||
          users = with lib.my.c.ids; {
 | 
			
		||||
            users = {
 | 
			
		||||
              matrix-synapse.extraGroups = [
 | 
			
		||||
                "mautrix-whatsapp"
 | 
			
		||||
              ];
 | 
			
		||||
              matrix-syncv3 = {
 | 
			
		||||
                isSystemUser = true;
 | 
			
		||||
                uid = uids.matrix-syncv3;
 | 
			
		||||
@@ -79,7 +100,10 @@ in
 | 
			
		||||
                User = "matrix-syncv3";
 | 
			
		||||
                Group = "matrix-syncv3";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
            } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: {
 | 
			
		||||
              # ffmpeg needed to convert GIFs to video
 | 
			
		||||
              path = with pkgs; [ ffmpeg ];
 | 
			
		||||
            }));
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          services = {
 | 
			
		||||
@@ -168,17 +192,19 @@ in
 | 
			
		||||
 | 
			
		||||
                app_service_config_files = [
 | 
			
		||||
                  "/var/lib/heisenbridge/registration.yml"
 | 
			
		||||
                  config.age.secrets."chatterbox/doublepuppet.yaml".path
 | 
			
		||||
                  "/var/lib/mautrix-whatsapp/whatsapp-registration.yaml"
 | 
			
		||||
                ];
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              sliding-sync = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                createDatabase = false;
 | 
			
		||||
                environmentFile = config.age.secrets."chatterbox/syncv3.env".path;
 | 
			
		||||
                settings = {
 | 
			
		||||
                  SYNCV3_BINDADDR = "[::]:8009";
 | 
			
		||||
                  SYNCV3_SERVER = "http://localhost:8008";
 | 
			
		||||
                };
 | 
			
		||||
            };
 | 
			
		||||
            matrix-sliding-sync = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              createDatabase = false;
 | 
			
		||||
              environmentFile = config.age.secrets."chatterbox/syncv3.env".path;
 | 
			
		||||
              settings = {
 | 
			
		||||
                SYNCV3_BINDADDR = "[::]:8009";
 | 
			
		||||
                SYNCV3_SERVER = "http://localhost:8008";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -195,6 +221,140 @@ in
 | 
			
		||||
                ];
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            mautrix-whatsapp = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              environmentFile = config.age.secrets."chatterbox/mautrix-whatsapp.env".path;
 | 
			
		||||
              settings = {
 | 
			
		||||
                homeserver = {
 | 
			
		||||
                  address = "http://localhost:8008";
 | 
			
		||||
                  domain = "nul.ie";
 | 
			
		||||
                };
 | 
			
		||||
                appservice = {
 | 
			
		||||
                  database = {
 | 
			
		||||
                    type = "postgres";
 | 
			
		||||
                    uri = "$MAU_WAPP_PSQL_URI";
 | 
			
		||||
                  };
 | 
			
		||||
                  id = "whatsapp2";
 | 
			
		||||
                  bot = {
 | 
			
		||||
                    username = "whatsapp2";
 | 
			
		||||
                    displayname = "WhatsApp Bridge Bot";
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
                bridge = {
 | 
			
		||||
                  username_template = "wapp2_{{.}}";
 | 
			
		||||
                  displayname_template = "{{or .BusinessName .PushName .JID}} (WA)";
 | 
			
		||||
                  personal_filtering_spaces = true;
 | 
			
		||||
                  delivery_receipts = true;
 | 
			
		||||
                  allow_user_invite = true;
 | 
			
		||||
                  url_previews = true;
 | 
			
		||||
                  command_prefix = "!wa";
 | 
			
		||||
                  login_shared_secret_map."nul.ie" = "$MAU_WAPP_DOUBLE_PUPPET_TOKEN";
 | 
			
		||||
                  encryption = {
 | 
			
		||||
                    allow = true;
 | 
			
		||||
                    default = true;
 | 
			
		||||
                    require = true;
 | 
			
		||||
                  };
 | 
			
		||||
                  permissions = {
 | 
			
		||||
                    "@dev:nul.ie" = "admin";
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            mautrix-meta.instances = {
 | 
			
		||||
              messenger = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                registerToSynapse = true;
 | 
			
		||||
                dataDir = "mautrix-messenger";
 | 
			
		||||
                environmentFile = config.age.secrets."chatterbox/mautrix-messenger.env".path;
 | 
			
		||||
                settings = {
 | 
			
		||||
                  homeserver = {
 | 
			
		||||
                    address = "http://localhost:8008";
 | 
			
		||||
                    domain = "nul.ie";
 | 
			
		||||
                  };
 | 
			
		||||
                  appservice = {
 | 
			
		||||
                    database = {
 | 
			
		||||
                      type = "postgres";
 | 
			
		||||
                      uri = "$MAU_FBM_PSQL_URI";
 | 
			
		||||
                    };
 | 
			
		||||
                    id = "fbm2";
 | 
			
		||||
                    bot = {
 | 
			
		||||
                      username = "messenger2";
 | 
			
		||||
                      displayname = "Messenger Bridge Bot";
 | 
			
		||||
                      avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak";
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                  meta.mode = "messenger";
 | 
			
		||||
                  bridge = {
 | 
			
		||||
                    username_template = "fbm2_{{.}}";
 | 
			
		||||
                    displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FBM)'';
 | 
			
		||||
                    personal_filtering_spaces = true;
 | 
			
		||||
                    delivery_receipts = true;
 | 
			
		||||
                    management_room_text.welcome = "Hello, I'm a Messenger bridge bot.";
 | 
			
		||||
                    command_prefix = "!fbm";
 | 
			
		||||
                    login_shared_secret_map."nul.ie" = "$MAU_FBM_DOUBLE_PUPPET_TOKEN";
 | 
			
		||||
                    backfill = {
 | 
			
		||||
                      history_fetch_pages = 5;
 | 
			
		||||
                    };
 | 
			
		||||
                    encryption = {
 | 
			
		||||
                      allow = true;
 | 
			
		||||
                      default = true;
 | 
			
		||||
                      require = true;
 | 
			
		||||
                    };
 | 
			
		||||
                    permissions = {
 | 
			
		||||
                      "@dev:nul.ie" = "admin";
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              instagram = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                registerToSynapse = true;
 | 
			
		||||
                dataDir = "mautrix-instagram";
 | 
			
		||||
                environmentFile = config.age.secrets."chatterbox/mautrix-instagram.env".path;
 | 
			
		||||
                settings = {
 | 
			
		||||
                  homeserver = {
 | 
			
		||||
                    address = "http://localhost:8008";
 | 
			
		||||
                    domain = "nul.ie";
 | 
			
		||||
                  };
 | 
			
		||||
                  appservice = {
 | 
			
		||||
                    database = {
 | 
			
		||||
                      type = "postgres";
 | 
			
		||||
                      uri = "$MAU_IG_PSQL_URI";
 | 
			
		||||
                    };
 | 
			
		||||
                    id = "instagram";
 | 
			
		||||
                    bot = {
 | 
			
		||||
                      username = "instagram";
 | 
			
		||||
                      displayname = "Instagram Bridge Bot";
 | 
			
		||||
                      avatar = "mxc://maunium.net/JxjlbZUlCPULEeHZSwleUXQv";
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                  meta.mode = "instagram";
 | 
			
		||||
                  bridge = {
 | 
			
		||||
                    username_template = "ig_{{.}}";
 | 
			
		||||
                    displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (IG)'';
 | 
			
		||||
                    personal_filtering_spaces = true;
 | 
			
		||||
                    delivery_receipts = true;
 | 
			
		||||
                    management_room_text.welcome = "Hello, I'm an Instagram bridge bot.";
 | 
			
		||||
                    command_prefix = "!ig";
 | 
			
		||||
                    login_shared_secret_map."nul.ie" = "$MAU_IG_DOUBLE_PUPPET_TOKEN";
 | 
			
		||||
                    backfill = {
 | 
			
		||||
                      history_fetch_pages = 5;
 | 
			
		||||
                    };
 | 
			
		||||
                    encryption = {
 | 
			
		||||
                      allow = true;
 | 
			
		||||
                      default = true;
 | 
			
		||||
                      require = true;
 | 
			
		||||
                    };
 | 
			
		||||
                    permissions = {
 | 
			
		||||
                      "@dev:nul.ie" = "admin";
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
        (mkIf config.my.build.isDevVM {
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,8 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) concatStringsSep;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c) pubDomain;
 | 
			
		||||
  inherit (lib.my.c.colony) domain prefixes;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
@@ -35,6 +37,9 @@ in
 | 
			
		||||
 | 
			
		||||
          secrets = {
 | 
			
		||||
            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPUv1ntVrZv5ripsKpcOAnyDQX2PHjowzyhqWK10Ml53";
 | 
			
		||||
            files = {
 | 
			
		||||
              "jackflix/photoprism-pass.txt" = {};
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -50,10 +55,16 @@ in
 | 
			
		||||
              uid = uids.jellyseerr;
 | 
			
		||||
              group = "jellyseerr";
 | 
			
		||||
            };
 | 
			
		||||
            photoprism = {
 | 
			
		||||
              isSystemUser = true;
 | 
			
		||||
              uid = uids.photoprism;
 | 
			
		||||
              group = "photoprism";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
          groups = {
 | 
			
		||||
            media.gid = 2000;
 | 
			
		||||
            jellyseerr.gid = gids.jellyseerr;
 | 
			
		||||
            photoprism.gid = gids.photoprism;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -76,6 +87,10 @@ in
 | 
			
		||||
              RootDirectoryStartOnly = lib.mkForce false;
 | 
			
		||||
              RootDirectory = lib.mkForce "";
 | 
			
		||||
            };
 | 
			
		||||
            photoprism.serviceConfig = {
 | 
			
		||||
              # Needs to be able to access its data
 | 
			
		||||
              DynamicUser = mkForce false;
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -117,6 +132,24 @@ in
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          jellyfin.enable = true;
 | 
			
		||||
 | 
			
		||||
          photoprism = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            address = "[::]";
 | 
			
		||||
            port = 2342;
 | 
			
		||||
            originalsPath = "/mnt/media/photoprism/originals";
 | 
			
		||||
            importPath = "/mnt/media/photoprism/import";
 | 
			
		||||
            passwordFile = config.age.secrets."jackflix/photoprism-pass.txt".path;
 | 
			
		||||
            settings = {
 | 
			
		||||
              PHOTOPRISM_AUTH_MODE = "password";
 | 
			
		||||
              PHOTOPRISM_ADMIN_USER = "dev";
 | 
			
		||||
              PHOTOPRISM_APP_NAME = "/dev/player0 Photos";
 | 
			
		||||
              PHOTOPRISM_SITE_URL = "https://photos.${pubDomain}/";
 | 
			
		||||
              PHOTOPRISM_SITE_TITLE = "/dev/player0 Photos";
 | 
			
		||||
              PHOTOPRISM_TRUSTED_PROXY = concatStringsSep "," (with prefixes.ctrs; [ v4 v6 ]);
 | 
			
		||||
              PHOTOPRISM_DATABASE_DRIVER = "sqlite";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -37,7 +37,7 @@ in
 | 
			
		||||
                tcp dport ${toString transmissionPeerPort} accept
 | 
			
		||||
                iifname vpn return
 | 
			
		||||
 | 
			
		||||
                tcp dport { 19999, 9091, 9117, 7878, 8989, 8096 } accept
 | 
			
		||||
                tcp dport { 19999, 9091, 9117, 7878, 8989, 8096, 2342 } accept
 | 
			
		||||
                return
 | 
			
		||||
              }
 | 
			
		||||
              chain input {
 | 
			
		||||
 
 | 
			
		||||
@@ -364,7 +364,7 @@ in
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
      "mc-rail.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://simpcraft-staging-oci.${domain}:3876";
 | 
			
		||||
        locations."/".proxyPass = "http://simpcraft-oci.${domain}:3876";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
@@ -384,6 +384,18 @@ in
 | 
			
		||||
        };
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
      "pb.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://object-ctr.${domain}:8088";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
      "photos.${pubDomain}" = {
 | 
			
		||||
        locations."/" = {
 | 
			
		||||
          proxyPass = "http://jackflix-ctr.${domain}:2342";
 | 
			
		||||
          proxyWebsockets = true;
 | 
			
		||||
          extraConfig = proxyHeaders;
 | 
			
		||||
        };
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    minio =
 | 
			
		||||
 
 | 
			
		||||
@@ -49,6 +49,7 @@ in
 | 
			
		||||
                };
 | 
			
		||||
                "object/atticd.env" = {};
 | 
			
		||||
                "object/hedgedoc.env" = {};
 | 
			
		||||
                "object/wastebin.env" = {};
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -58,6 +59,7 @@ in
 | 
			
		||||
                config.services.sharry.config.bind.port
 | 
			
		||||
                8069
 | 
			
		||||
                config.services.hedgedoc.settings.port
 | 
			
		||||
                8088
 | 
			
		||||
              ];
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -220,6 +222,15 @@ in
 | 
			
		||||
                allowEmailRegister = false;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            wastebin = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              settings = {
 | 
			
		||||
                WASTEBIN_MAX_BODY_SIZE = 67108864; # 16 MiB
 | 
			
		||||
                WASTEBIN_PASSWORD_SALT = "TeGhaemeer0Siez3";
 | 
			
		||||
              };
 | 
			
		||||
              secretFile = config.age.secrets."object/wastebin.env".path;
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
        (mkIf config.my.build.isDevVM {
 | 
			
		||||
 
 | 
			
		||||
@@ -49,7 +49,11 @@ in
 | 
			
		||||
        inherit (lib.my) networkdAssignment;
 | 
			
		||||
      in
 | 
			
		||||
      {
 | 
			
		||||
        imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
 | 
			
		||||
        imports = [
 | 
			
		||||
          "${modulesPath}/profiles/qemu-guest.nix"
 | 
			
		||||
 | 
			
		||||
          ./containers-ext.nix
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        config = mkMerge [
 | 
			
		||||
          {
 | 
			
		||||
 
 | 
			
		||||
@@ -108,45 +108,30 @@ in
 | 
			
		||||
              oci-containers = {
 | 
			
		||||
                backend = "podman";
 | 
			
		||||
              };
 | 
			
		||||
              # NixOS has switched to using netavark, which is native to podman. It's currently missing an option to
 | 
			
		||||
              # disable iptables rules generation, which is very annoying.
 | 
			
		||||
              containers.containersConf.settings.network.network_backend = mkForce "cni";
 | 
			
		||||
              containers.containersConf.settings.network = {
 | 
			
		||||
                network_backend = "netavark";
 | 
			
		||||
                firewall_driver = "none";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            environment = {
 | 
			
		||||
              etc = {
 | 
			
		||||
                "cni/net.d/90-colony.conflist".text = toJSON {
 | 
			
		||||
                  cniVersion = "0.4.0";
 | 
			
		||||
                "containers/networks/colony.json".text = toJSON {
 | 
			
		||||
                  name = "colony";
 | 
			
		||||
                  plugins = [
 | 
			
		||||
                  id = "0000000000000000000000000000000000000000000000000000000000000001";
 | 
			
		||||
                  driver = "bridge";
 | 
			
		||||
                  network_interface = "oci";
 | 
			
		||||
                  ipv6_enabled = true;
 | 
			
		||||
                  internal = false;
 | 
			
		||||
                  dns_enabled = false;
 | 
			
		||||
                  subnets = [
 | 
			
		||||
                    {
 | 
			
		||||
                      type = "bridge";
 | 
			
		||||
                      bridge = "oci";
 | 
			
		||||
                      isGateway = true;
 | 
			
		||||
                      ipMasq = false;
 | 
			
		||||
                      hairpinMode = true;
 | 
			
		||||
                      ipam = {
 | 
			
		||||
                        type = "host-local";
 | 
			
		||||
                        routes = [
 | 
			
		||||
                          { dst = "0.0.0.0/0"; }
 | 
			
		||||
                          { dst = "::/0"; }
 | 
			
		||||
                        ];
 | 
			
		||||
                        ranges = [
 | 
			
		||||
                          [
 | 
			
		||||
                            {
 | 
			
		||||
                              subnet = prefixes.oci.v4;
 | 
			
		||||
                              gateway = net.cidr.host 1 prefixes.oci.v4;
 | 
			
		||||
                            }
 | 
			
		||||
                          ]
 | 
			
		||||
                          [
 | 
			
		||||
                            {
 | 
			
		||||
                              subnet = prefixes.oci.v6;
 | 
			
		||||
                              gateway = net.cidr.host 1 prefixes.oci.v6;
 | 
			
		||||
                            }
 | 
			
		||||
                          ]
 | 
			
		||||
                        ];
 | 
			
		||||
                      };
 | 
			
		||||
                      capabilities.ips = true;
 | 
			
		||||
                      subnet = prefixes.oci.v4;
 | 
			
		||||
                      gateway = net.cidr.host 1 prefixes.oci.v4;
 | 
			
		||||
                    }
 | 
			
		||||
                    {
 | 
			
		||||
                      subnet = prefixes.oci.v6;
 | 
			
		||||
                      gateway = net.cidr.host 1 prefixes.oci.v6;
 | 
			
		||||
                    }
 | 
			
		||||
                  ];
 | 
			
		||||
                };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
{ lib, config, allAssignments, ... }:
 | 
			
		||||
{ lib, pkgs, config, allAssignments, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) concatStringsSep;
 | 
			
		||||
  inherit (lib.my) dockerNetAssignment;
 | 
			
		||||
@@ -18,18 +18,27 @@ let
 | 
			
		||||
    "d6ec4c91-5da2-44eb-b89d-71dc8fe017a0" # Eefah98
 | 
			
		||||
    "096a7348-fabe-4b2d-93fc-fd1fd5608fb0" # ToTheMoonStar
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  fastback = {
 | 
			
		||||
    gitConfig = pkgs.writeText "git-config" ''
 | 
			
		||||
      [user]
 | 
			
		||||
      	email = "simpcraft@nul.ie"
 | 
			
		||||
      	name = "Simpcraft bot"
 | 
			
		||||
    '';
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  config = {
 | 
			
		||||
    virtualisation.oci-containers.containers = {
 | 
			
		||||
      simpcraft = {
 | 
			
		||||
        image = "ghcr.io/itzg/minecraft-server:2023.12.2-java17-alpine";
 | 
			
		||||
        image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
			
		||||
 | 
			
		||||
        environment = {
 | 
			
		||||
          TYPE = "MODRINTH";
 | 
			
		||||
 | 
			
		||||
          EULA = "true";
 | 
			
		||||
          ENABLE_QUERY = "true";
 | 
			
		||||
          ENABLE_RCON = "true";
 | 
			
		||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t §4§k-----";
 | 
			
		||||
          ICON = "/ext/icon.png";
 | 
			
		||||
 | 
			
		||||
@@ -41,15 +50,17 @@ in
 | 
			
		||||
          SPAWN_PROTECTION = "0";
 | 
			
		||||
          VIEW_DISTANCE = "20";
 | 
			
		||||
 | 
			
		||||
          MAX_MEMORY = "6G";
 | 
			
		||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/cdj2bSKg/Simpcraft-0.1.2.mrpack";
 | 
			
		||||
          MAX_MEMORY = "8G";
 | 
			
		||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/NGutsQSd/Simpcraft-0.2.1.mrpack";
 | 
			
		||||
 | 
			
		||||
          TZ = "Europe/Dublin";
 | 
			
		||||
        };
 | 
			
		||||
        environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
			
		||||
 | 
			
		||||
        volumes = [
 | 
			
		||||
          "minecraft_data:/data"
 | 
			
		||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
			
		||||
          "${fastback.gitConfig}:/data/.config/git/config:ro"
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        extraOptions = [
 | 
			
		||||
@@ -57,41 +68,71 @@ in
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      simpcraft-staging = {
 | 
			
		||||
        image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
			
		||||
      # simpcraft-staging = {
 | 
			
		||||
      #   image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
			
		||||
 | 
			
		||||
        environment = {
 | 
			
		||||
          TYPE = "MODRINTH";
 | 
			
		||||
      #   environment = {
 | 
			
		||||
      #     TYPE = "MODRINTH";
 | 
			
		||||
 | 
			
		||||
          EULA = "true";
 | 
			
		||||
          ENABLE_QUERY = "true";
 | 
			
		||||
          ENABLE_RCON = "true";
 | 
			
		||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
 | 
			
		||||
          ICON = "/ext/icon.png";
 | 
			
		||||
      #     EULA = "true";
 | 
			
		||||
      #     ENABLE_QUERY = "true";
 | 
			
		||||
      #     ENABLE_RCON = "true";
 | 
			
		||||
      #     MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
 | 
			
		||||
      #     ICON = "/ext/icon.png";
 | 
			
		||||
 | 
			
		||||
          EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
			
		||||
          WHITELIST = whitelist;
 | 
			
		||||
          EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
			
		||||
          OPS = op;
 | 
			
		||||
          DIFFICULTY = "normal";
 | 
			
		||||
          SPAWN_PROTECTION = "0";
 | 
			
		||||
          VIEW_DISTANCE = "20";
 | 
			
		||||
      #     EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
			
		||||
      #     WHITELIST = whitelist;
 | 
			
		||||
      #     EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
			
		||||
      #     OPS = op;
 | 
			
		||||
      #     DIFFICULTY = "normal";
 | 
			
		||||
      #     SPAWN_PROTECTION = "0";
 | 
			
		||||
      #     VIEW_DISTANCE = "20";
 | 
			
		||||
 | 
			
		||||
          MAX_MEMORY = "4G";
 | 
			
		||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
 | 
			
		||||
      #     MAX_MEMORY = "4G";
 | 
			
		||||
      #     MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
 | 
			
		||||
 | 
			
		||||
          TZ = "Europe/Dublin";
 | 
			
		||||
      #     TZ = "Europe/Dublin";
 | 
			
		||||
      #   };
 | 
			
		||||
      #   environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
			
		||||
 | 
			
		||||
      #   volumes = [
 | 
			
		||||
      #     "minecraft_staging_data:/data"
 | 
			
		||||
      #     "${./icon.png}:/ext/icon.png:ro"
 | 
			
		||||
      #   ];
 | 
			
		||||
 | 
			
		||||
      #   extraOptions = [
 | 
			
		||||
      #     ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
 | 
			
		||||
      #   ];
 | 
			
		||||
      # };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    services = {
 | 
			
		||||
      borgbackup.jobs.simpcraft =
 | 
			
		||||
      let
 | 
			
		||||
        rconCommand = cmd: ''${pkgs.mcrcon}/bin/mcrcon -H simpcraft-oci -p "$RCON_PASSWORD" "${cmd}"'';
 | 
			
		||||
      in
 | 
			
		||||
      {
 | 
			
		||||
        paths = [ "/var/lib/containers/storage/volumes/minecraft_data/_data/world" ];
 | 
			
		||||
        repo = "/var/lib/containers/backup/simpcraft";
 | 
			
		||||
        doInit = true;
 | 
			
		||||
        encryption.mode = "none";
 | 
			
		||||
        compression = "zstd,10";
 | 
			
		||||
        # every ~15 minutes offset from 5 minute intervals (Minecraft seems to save at precise times?)
 | 
			
		||||
        startAt = "*:03,17,33,47";
 | 
			
		||||
        prune.keep = {
 | 
			
		||||
          within = "12H";
 | 
			
		||||
          hourly = 48;
 | 
			
		||||
        };
 | 
			
		||||
        environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
			
		||||
 | 
			
		||||
        volumes = [
 | 
			
		||||
          "minecraft_staging_data:/data"
 | 
			
		||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
			
		||||
        ];
 | 
			
		||||
        # Avoid Minecraft poking the files while we back up
 | 
			
		||||
        preHook = rconCommand "save-off";
 | 
			
		||||
        postHook = rconCommand "save-on";
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
        extraOptions = [
 | 
			
		||||
          ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
 | 
			
		||||
        ];
 | 
			
		||||
    systemd = {
 | 
			
		||||
      services = {
 | 
			
		||||
        borgbackup-job-simpcraft.serviceConfig.EnvironmentFile = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -148,19 +148,33 @@ in
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            nginx.enable = true;
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          networking.domain = "h.${pubDomain}";
 | 
			
		||||
          networking = { inherit domain; };
 | 
			
		||||
 | 
			
		||||
          systemd.services = {
 | 
			
		||||
            ipsec =
 | 
			
		||||
            let
 | 
			
		||||
              waitOnline = "systemd-networkd-wait-online@wan.service";
 | 
			
		||||
            in
 | 
			
		||||
            {
 | 
			
		||||
          systemd.services =
 | 
			
		||||
          let
 | 
			
		||||
            waitOnline = "systemd-networkd-wait-online@wan.service";
 | 
			
		||||
          in
 | 
			
		||||
          {
 | 
			
		||||
            ipsec = {
 | 
			
		||||
              after = [ waitOnline ];
 | 
			
		||||
              requires = [ waitOnline ];
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            ipv6-clear-default-route = {
 | 
			
		||||
              description = "Clear IPv6 RA default route";
 | 
			
		||||
              after = [ waitOnline ];
 | 
			
		||||
              requires = [ waitOnline ];
 | 
			
		||||
              script = ''
 | 
			
		||||
                # Seems like we can sometimes pick up a default route somehow...
 | 
			
		||||
                ${pkgs.iproute2}/bin/ip -6 route del default via fe80::1 || true
 | 
			
		||||
              '';
 | 
			
		||||
              serviceConfig.Type = "oneshot";
 | 
			
		||||
              wantedBy = [ "multi-user.target" ];
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          systemd.network = {
 | 
			
		||||
@@ -214,7 +228,7 @@ in
 | 
			
		||||
                  extraConfig = ''
 | 
			
		||||
                    [CAKE]
 | 
			
		||||
                    Bandwidth=235M
 | 
			
		||||
                    RTTSec=10ms
 | 
			
		||||
                    RTTSec=50ms
 | 
			
		||||
                    PriorityQueueingPreset=besteffort
 | 
			
		||||
                    # DOCSIS preset
 | 
			
		||||
                    OverheadBytes=18
 | 
			
		||||
@@ -238,7 +252,7 @@ in
 | 
			
		||||
                      [CAKE]
 | 
			
		||||
                      Parent=root
 | 
			
		||||
                      Bandwidth=24M
 | 
			
		||||
                      RTTSec=1ms
 | 
			
		||||
                      RTTSec=50ms
 | 
			
		||||
                    '';
 | 
			
		||||
                  }
 | 
			
		||||
                ];
 | 
			
		||||
@@ -358,6 +372,16 @@ in
 | 
			
		||||
                    return
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  chain forward-early {
 | 
			
		||||
                    type filter hook forward priority -1; policy accept;
 | 
			
		||||
 | 
			
		||||
                    # MSS clamping to workaround IPv6 PMTUD being broken...
 | 
			
		||||
                    tcp flags syn tcp option maxseg size set rt mtu counter
 | 
			
		||||
 | 
			
		||||
                    # More Disney+ discrimination...
 | 
			
		||||
                    # TODO: This prefix could change (random AWS block)
 | 
			
		||||
                    ip6 daddr 2600:9000:2245::/48 drop
 | 
			
		||||
                  }
 | 
			
		||||
                  chain forward {
 | 
			
		||||
                    ${lib.my.c.as211024.nftTrust}
 | 
			
		||||
                    iifname lan-untrusted jump filter-untrusted
 | 
			
		||||
@@ -377,6 +401,11 @@ in
 | 
			
		||||
                }
 | 
			
		||||
              '';
 | 
			
		||||
            };
 | 
			
		||||
            netboot.server = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              ip = vips.lo.v4;
 | 
			
		||||
              host = "boot.${domain}";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 
 | 
			
		||||
@@ -61,6 +61,19 @@ in
 | 
			
		||||
          webserver = true;
 | 
			
		||||
          webserver-address = "::";
 | 
			
		||||
          webserver-allow-from = [ "127.0.0.1" "::1" ];
 | 
			
		||||
 | 
			
		||||
          lua-dns-script = pkgs.writeText "pdns-script.lua" ''
 | 
			
		||||
            -- Disney+ doesn't like our IP space...
 | 
			
		||||
            function preresolve(dq)
 | 
			
		||||
              local name = dq.qname:toString()
 | 
			
		||||
              if dq.qtype == pdns.AAAA and (string.find(name, "disneyplus") or string.find(name, "disney-plus") or string.find(name , "disney.api")) then
 | 
			
		||||
                dq.rcode = 0
 | 
			
		||||
                return true
 | 
			
		||||
              end
 | 
			
		||||
 | 
			
		||||
              return false
 | 
			
		||||
            end
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
@@ -159,6 +172,7 @@ in
 | 
			
		||||
            }}
 | 
			
		||||
            ${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6}
 | 
			
		||||
            ${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6}
 | 
			
		||||
            boot IN CNAME router-hi.${config.networking.domain}.
 | 
			
		||||
 | 
			
		||||
            @ IN NS ns1
 | 
			
		||||
            @ IN NS ns2
 | 
			
		||||
@@ -182,8 +196,10 @@ in
 | 
			
		||||
            dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
 | 
			
		||||
            dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6}
 | 
			
		||||
 | 
			
		||||
            ;ap0 IN A ${net.cidr.host 12 prefixes.hi.v4}
 | 
			
		||||
            ;ap0 IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
 | 
			
		||||
            shytzel IN A ${net.cidr.host 12 prefixes.core.v4}
 | 
			
		||||
 | 
			
		||||
            wave IN A ${net.cidr.host 12 prefixes.hi.v4}
 | 
			
		||||
            wave IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
 | 
			
		||||
            vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
 | 
			
		||||
            vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
index: { lib, pkgs, assignments, ... }:
 | 
			
		||||
index: { lib, pkgs, config, assignments, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) mkForce;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
@@ -26,7 +26,11 @@ in
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  systemd.services = {
 | 
			
		||||
    kea-dhcp4-server.serviceConfig.DynamicUser = mkForce false;
 | 
			
		||||
    kea-dhcp4-server.serviceConfig = {
 | 
			
		||||
      # Sometimes interfaces might not be ready in time and Kea doesn't like that
 | 
			
		||||
      Restart = "on-failure";
 | 
			
		||||
      DynamicUser = mkForce false;
 | 
			
		||||
    };
 | 
			
		||||
    kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
@@ -59,6 +63,7 @@ in
 | 
			
		||||
              always-send = true;
 | 
			
		||||
            }
 | 
			
		||||
          ];
 | 
			
		||||
          client-classes = config.my.netboot.server.keaClientClasses;
 | 
			
		||||
          subnet4 = [
 | 
			
		||||
            {
 | 
			
		||||
              id = 1;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,52 +1,82 @@
 | 
			
		||||
index: { lib, pkgs, config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) attrNames concatMap;
 | 
			
		||||
  inherit (lib) optional;
 | 
			
		||||
  inherit (builtins) attrNames concatMap length;
 | 
			
		||||
  inherit (lib) optional concatMapStringsSep;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c.home) prefixes vips;
 | 
			
		||||
 | 
			
		||||
  pingScriptFor = name: ips:
 | 
			
		||||
  let
 | 
			
		||||
    script' = pkgs.writeShellScript
 | 
			
		||||
      "keepalived-ping-${name}"
 | 
			
		||||
      (concatMapStringsSep " || " (ip: "${pkgs.iputils}/bin/ping -qnc 1 -W 1 ${ip}") ips);
 | 
			
		||||
  in
 | 
			
		||||
  {
 | 
			
		||||
    script = toString script';
 | 
			
		||||
    interval = 1;
 | 
			
		||||
    timeout = (length ips) + 1;
 | 
			
		||||
    rise = 3;
 | 
			
		||||
    fall = 3;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  vlanIface = vlan: if vlan == "as211024" then vlan else "lan-${vlan}";
 | 
			
		||||
  vrrpIPs = family: concatMap (vlan: [
 | 
			
		||||
  vrrpIPs = family: concatMap (vlan: (optional (family == "v6") {
 | 
			
		||||
      addr = "fe80::1/64";
 | 
			
		||||
      dev = vlanIface vlan;
 | 
			
		||||
    }) ++ [
 | 
			
		||||
    {
 | 
			
		||||
      addr = "${vips.${vlan}.${family}}/${toString (net.cidr.length prefixes.${vlan}.${family})}";
 | 
			
		||||
      dev = vlanIface vlan;
 | 
			
		||||
    }
 | 
			
		||||
  ] ++ (optional (family == "v6") {
 | 
			
		||||
    addr = "fe80::1/64";
 | 
			
		||||
    dev = vlanIface vlan;
 | 
			
		||||
  })) (attrNames vips);
 | 
			
		||||
  ]) (attrNames vips);
 | 
			
		||||
  mkVRRP = family: routerId: {
 | 
			
		||||
    state = if index == 0 then "MASTER" else "BACKUP";
 | 
			
		||||
    interface = "lan-core";
 | 
			
		||||
    priority = 255 - index;
 | 
			
		||||
    virtualRouterId = routerId;
 | 
			
		||||
    virtualIps = vrrpIPs family;
 | 
			
		||||
    trackScripts = [ "${family}Alive" ];
 | 
			
		||||
    extraConfig = ''
 | 
			
		||||
      notify_master "${config.systemd.package}/bin/systemctl start radvd.service"
 | 
			
		||||
      notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service"
 | 
			
		||||
      notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root
 | 
			
		||||
      notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root
 | 
			
		||||
    '';
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  users = with lib.my.c.ids; {
 | 
			
		||||
    users.keepalived_script = {
 | 
			
		||||
      uid = uids.keepalived_script;
 | 
			
		||||
      isSystemUser = true;
 | 
			
		||||
      group = "keepalived_script";
 | 
			
		||||
    };
 | 
			
		||||
    groups.keepalived_script.gid = gids.keepalived_script;
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  services = {
 | 
			
		||||
    keepalived = {
 | 
			
		||||
      enable = true;
 | 
			
		||||
      enableScriptSecurity = true;
 | 
			
		||||
      extraGlobalDefs = ''
 | 
			
		||||
        vrrp_version 3
 | 
			
		||||
        nftables keepalived
 | 
			
		||||
      '';
 | 
			
		||||
      vrrpScripts = {
 | 
			
		||||
        v4Alive = pingScriptFor "v4" [ "1.1.1.1" "8.8.8.8" "216.218.236.2" ];
 | 
			
		||||
        v6Alive = pingScriptFor "v6" [ "2606:4700:4700::1111" "2001:4860:4860::8888" "2600::" ];
 | 
			
		||||
      };
 | 
			
		||||
      vrrpInstances = {
 | 
			
		||||
        v4 = mkVRRP "v4" 51;
 | 
			
		||||
        v6 = mkVRRP "v6" 52;
 | 
			
		||||
      };
 | 
			
		||||
      extraConfig = ''
 | 
			
		||||
        vrrp_sync_group main {
 | 
			
		||||
          group {
 | 
			
		||||
            v4
 | 
			
		||||
            v6
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      '';
 | 
			
		||||
      # Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken...
 | 
			
		||||
      # extraConfig = ''
 | 
			
		||||
      #   vrrp_sync_group main {
 | 
			
		||||
      #     group {
 | 
			
		||||
      #       v4
 | 
			
		||||
      #       v6
 | 
			
		||||
      #     }
 | 
			
		||||
      #   }
 | 
			
		||||
      # '';
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -123,7 +123,7 @@
 | 
			
		||||
            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb";
 | 
			
		||||
          };
 | 
			
		||||
          server.enable = true;
 | 
			
		||||
          deploy.node.hostname = "192.168.68.2";
 | 
			
		||||
          # deploy.node.hostname = "192.168.68.2";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -65,7 +65,13 @@ in
 | 
			
		||||
        systemd = {
 | 
			
		||||
          services = {
 | 
			
		||||
            jackett.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
			
		||||
 | 
			
		||||
            transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
			
		||||
            # https://github.com/NixOS/nixpkgs/issues/258793#issuecomment-1748168206
 | 
			
		||||
            transmission.serviceConfig = {
 | 
			
		||||
              RootDirectoryStartOnly = lib.mkForce false;
 | 
			
		||||
              RootDirectory = lib.mkForce "";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            radarr.serviceConfig.UMask = "0002";
 | 
			
		||||
            sonarr.serviceConfig.UMask = "0002";
 | 
			
		||||
 
 | 
			
		||||
@@ -2,6 +2,7 @@
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) mkMerge mkIf;
 | 
			
		||||
  inherit (lib.my) networkdAssignment;
 | 
			
		||||
  inherit (lib.my.c.kelder) ipv4MTU;
 | 
			
		||||
 | 
			
		||||
  wg = {
 | 
			
		||||
    keyFile = "kelder/acquisition/airvpn-privkey";
 | 
			
		||||
@@ -89,6 +90,7 @@ in
 | 
			
		||||
              (networkdAssignment "host0" assignments.internal)
 | 
			
		||||
              {
 | 
			
		||||
                networkConfig.DNSDefaultRoute = false;
 | 
			
		||||
                linkConfig.MTUBytes = toString ipv4MTU;
 | 
			
		||||
              }
 | 
			
		||||
            ];
 | 
			
		||||
            "90-vpn" = with wg; {
 | 
			
		||||
 
 | 
			
		||||
@@ -92,17 +92,17 @@ in
 | 
			
		||||
 | 
			
		||||
          nextcloud = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            package = pkgs.nextcloud28;
 | 
			
		||||
            package = pkgs.nextcloud29;
 | 
			
		||||
            datadir = "/mnt/storage/nextcloud";
 | 
			
		||||
            hostName = "cloud.${domain}";
 | 
			
		||||
            https = true;
 | 
			
		||||
            config = {
 | 
			
		||||
              extraTrustedDomains = [ "cloud-local.${domain}" ];
 | 
			
		||||
              adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path;
 | 
			
		||||
              defaultPhoneRegion = "IE";
 | 
			
		||||
            };
 | 
			
		||||
            extraOptions = {
 | 
			
		||||
            settings = {
 | 
			
		||||
              updatechecker = false;
 | 
			
		||||
              trusted_domains = [ "cloud-local.${domain}" ];
 | 
			
		||||
              default_phone_region = "IE";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -84,6 +84,7 @@ in
 | 
			
		||||
            c
 | 
			
		||||
          ];
 | 
			
		||||
          acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}";
 | 
			
		||||
          # This is kinda borked because Virgin Media filters DNS responses with local IPs...
 | 
			
		||||
          localRedirect = to: ''
 | 
			
		||||
            rewrite_by_lua_block {
 | 
			
		||||
              if ngx.var.remote_addr == pub_ip then
 | 
			
		||||
@@ -103,7 +104,7 @@ in
 | 
			
		||||
 | 
			
		||||
            "monitor.${domain}" = withAuth {
 | 
			
		||||
              serverAliases = [ "monitor-local.${domain}" ];
 | 
			
		||||
              extraConfig = localRedirect "monitor-local.${domain}";
 | 
			
		||||
              # extraConfig = localRedirect "monitor-local.${domain}";
 | 
			
		||||
              locations = {
 | 
			
		||||
                "/" = {
 | 
			
		||||
                  proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999";
 | 
			
		||||
@@ -136,17 +137,17 @@ in
 | 
			
		||||
            };
 | 
			
		||||
            "torrents.${domain}" = withAuth {
 | 
			
		||||
              serverAliases = [ "torrents-local.${domain}" ];
 | 
			
		||||
              extraConfig = localRedirect "torrents-local.${domain}";
 | 
			
		||||
              # extraConfig = localRedirect "torrents-local.${domain}";
 | 
			
		||||
              locations."/".proxyPass = "${acquisition}:9091";
 | 
			
		||||
            };
 | 
			
		||||
            "jackett.${domain}" = withAuth {
 | 
			
		||||
              serverAliases = [ "jackett-local.${domain}" ];
 | 
			
		||||
              extraConfig = localRedirect "jackett-local.${domain}";
 | 
			
		||||
              # extraConfig = localRedirect "jackett-local.${domain}";
 | 
			
		||||
              locations."/".proxyPass = "${acquisition}:9117";
 | 
			
		||||
            };
 | 
			
		||||
            "radarr.${domain}" = withAuth {
 | 
			
		||||
              serverAliases = [ "radarr-local.${domain}" ];
 | 
			
		||||
              extraConfig = localRedirect "radarr-local.${domain}";
 | 
			
		||||
              # extraConfig = localRedirect "radarr-local.${domain}";
 | 
			
		||||
              locations."/" = {
 | 
			
		||||
                proxyPass = "${acquisition}:7878";
 | 
			
		||||
                proxyWebsockets = true;
 | 
			
		||||
@@ -155,7 +156,7 @@ in
 | 
			
		||||
            };
 | 
			
		||||
            "sonarr.${domain}" = withAuth {
 | 
			
		||||
              serverAliases = [ "sonarr-local.${domain}" ];
 | 
			
		||||
              extraConfig = localRedirect "sonarr-local.${domain}";
 | 
			
		||||
              # extraConfig = localRedirect "sonarr-local.${domain}";
 | 
			
		||||
              locations."/" = {
 | 
			
		||||
                proxyPass = "${acquisition}:8989";
 | 
			
		||||
                proxyWebsockets = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c.kelder) domain prefixes;
 | 
			
		||||
  inherit (lib.my.c.kelder) domain prefixes ipv4MTU;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  imports = [ ./containers ];
 | 
			
		||||
@@ -182,7 +182,7 @@ in
 | 
			
		||||
                    {
 | 
			
		||||
                      wireguardPeerConfig = {
 | 
			
		||||
                        PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
 | 
			
		||||
                        Endpoint = "estuary-vm.${lib.my.c.colony.domain}:${toString lib.my.c.kelder.vpn.port}";
 | 
			
		||||
                        Endpoint = "${allAssignments.estuary.internal.ipv4.address}:${toString lib.my.c.kelder.vpn.port}";
 | 
			
		||||
                        AllowedIPs = [ "0.0.0.0/0" ];
 | 
			
		||||
                        PersistentKeepalive = 25;
 | 
			
		||||
                      };
 | 
			
		||||
@@ -200,6 +200,7 @@ in
 | 
			
		||||
                "50-lan" = {
 | 
			
		||||
                  matchConfig.Name = "et1g0";
 | 
			
		||||
                  DHCP = "yes";
 | 
			
		||||
                  linkConfig.MTUBytes = toString ipv4MTU;
 | 
			
		||||
                };
 | 
			
		||||
                "80-ctrs" = mkMerge [
 | 
			
		||||
                  (networkdAssignment "ctrs" assignments.ctrs)
 | 
			
		||||
@@ -272,7 +273,7 @@ in
 | 
			
		||||
              config.name = "kontent";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            #deploy.node.hostname = "10.16.9.21";
 | 
			
		||||
            # deploy.node.hostname = "192.168.0.69";
 | 
			
		||||
            secrets = {
 | 
			
		||||
              key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi";
 | 
			
		||||
              files = {
 | 
			
		||||
 
 | 
			
		||||
@@ -129,10 +129,9 @@
 | 
			
		||||
            wifi = {
 | 
			
		||||
              backend = "wpa_supplicant";
 | 
			
		||||
            };
 | 
			
		||||
            extraConfig = ''
 | 
			
		||||
              [main]
 | 
			
		||||
              no-auto-default=*
 | 
			
		||||
            '';
 | 
			
		||||
            settings = {
 | 
			
		||||
              main.no-auto-default = "*";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -135,6 +135,7 @@ let
 | 
			
		||||
      ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6.";
 | 
			
		||||
      baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with.";
 | 
			
		||||
      l3Overhead = mkOpt' ints.unsigned 40 "Overhead of L3 header (to calculate MTU).";
 | 
			
		||||
      udpEncapsulation = mkBoolOpt' false "Whether to encapsulate ESP frames in UDP.";
 | 
			
		||||
      firewall = mkBoolOpt' true "Whether to generate firewall rules.";
 | 
			
		||||
      vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
 | 
			
		||||
      peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{
 | 
			
		||||
  nixos.systems.installer = { config, ... }: {
 | 
			
		||||
    system = "x86_64-linux";
 | 
			
		||||
    nixpkgs = "unstable";
 | 
			
		||||
    nixpkgs = "mine";
 | 
			
		||||
    docCustom = false;
 | 
			
		||||
    rendered = config.configuration.config.my.asISO;
 | 
			
		||||
 | 
			
		||||
@@ -52,6 +52,8 @@
 | 
			
		||||
            home.shellAliases = {
 | 
			
		||||
              show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT";
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            my.gui.enable = false;
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          services = {
 | 
			
		||||
 
 | 
			
		||||
@@ -20,5 +20,6 @@
 | 
			
		||||
    nvme = ./nvme;
 | 
			
		||||
    spdk = ./spdk.nix;
 | 
			
		||||
    librespeed = ./librespeed;
 | 
			
		||||
    netboot = ./netboot;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,6 +1,6 @@
 | 
			
		||||
{ lib, pkgs, extendModules, modulesPath, options, config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge flatten optional;
 | 
			
		||||
  inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge mkForce flatten optional;
 | 
			
		||||
  inherit (lib.my) mkBoolOpt' dummyOption;
 | 
			
		||||
 | 
			
		||||
  cfg = config.my.build;
 | 
			
		||||
@@ -43,15 +43,155 @@ let
 | 
			
		||||
    modules = flatten [
 | 
			
		||||
      "${modulesPath}/installer/netboot/netboot.nix"
 | 
			
		||||
      allHardware
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  asNetboot = extendModules {
 | 
			
		||||
    modules = flatten [
 | 
			
		||||
      allHardware
 | 
			
		||||
      ({ pkgs, config, ... }: {
 | 
			
		||||
        system.build.netbootArchive = pkgs.runCommand "netboot-${config.system.name}-archive.tar" { } ''
 | 
			
		||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.kernel}" \
 | 
			
		||||
            -f "$out" "${config.system.boot.loader.kernelFile}"
 | 
			
		||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootRamdisk}" \
 | 
			
		||||
            -f "$out" initrd
 | 
			
		||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootIpxeScript}" \
 | 
			
		||||
            -f "$out" netboot.ipxe
 | 
			
		||||
        '';
 | 
			
		||||
        boot = {
 | 
			
		||||
          loader.grub.enable = false;
 | 
			
		||||
          kernelParams = [ "console=ttyS0,115200n8" ];
 | 
			
		||||
          initrd = {
 | 
			
		||||
            kernelModules = [ "nbd" ];
 | 
			
		||||
 | 
			
		||||
            systemd = {
 | 
			
		||||
              storePaths = with pkgs; [
 | 
			
		||||
                gnused
 | 
			
		||||
                nbd
 | 
			
		||||
                netcat
 | 
			
		||||
              ];
 | 
			
		||||
              extraBin = with pkgs; {
 | 
			
		||||
                dmesg = "${util-linux}/bin/dmesg";
 | 
			
		||||
                ip = "${iproute2}/bin/ip";
 | 
			
		||||
                nbd-client = "${nbd}/bin/nbd-client";
 | 
			
		||||
              };
 | 
			
		||||
              extraConfig = ''
 | 
			
		||||
                DefaultTimeoutStartSec=10
 | 
			
		||||
                DefaultDeviceTimeoutSec=10
 | 
			
		||||
              '';
 | 
			
		||||
 | 
			
		||||
              network = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                wait-online.enable = true;
 | 
			
		||||
 | 
			
		||||
                networks."10-netboot" = {
 | 
			
		||||
                  matchConfig.Name = "et-boot";
 | 
			
		||||
                  DHCP = "yes";
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              services = {
 | 
			
		||||
                nbd = {
 | 
			
		||||
                  description = "NBD Root FS";
 | 
			
		||||
 | 
			
		||||
                  script = ''
 | 
			
		||||
                    get_cmdline() {
 | 
			
		||||
                      ${pkgs.gnused}/bin/sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
 | 
			
		||||
                    }
 | 
			
		||||
 | 
			
		||||
                    s="$(get_cmdline nbd_server)"
 | 
			
		||||
                    until ${pkgs.netcat}/bin/nc -zv "$s" 22; do
 | 
			
		||||
                      sleep 0.1
 | 
			
		||||
                    done
 | 
			
		||||
 | 
			
		||||
                    exec ${pkgs.nbd}/bin/nbd-client -systemd-mark -N "$(get_cmdline nbd_export)" "$s" /dev/nbd0
 | 
			
		||||
                  '';
 | 
			
		||||
                  unitConfig = {
 | 
			
		||||
                    IgnoreOnIsolate = "yes";
 | 
			
		||||
                    DefaultDependencies = "no";
 | 
			
		||||
                  };
 | 
			
		||||
                  serviceConfig = {
 | 
			
		||||
                    Type = "forking";
 | 
			
		||||
                    Restart = "on-failure";
 | 
			
		||||
                    RestartSec = 10;
 | 
			
		||||
                  };
 | 
			
		||||
 | 
			
		||||
                  wantedBy = [ "initrd-root-device.target" ];
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          postBootCommands = ''
 | 
			
		||||
            # After booting, register the contents of the Nix store
 | 
			
		||||
            # in the Nix database in the COW root.
 | 
			
		||||
            ${config.nix.package}/bin/nix-store --load-db < /nix-path-registration
 | 
			
		||||
 | 
			
		||||
            # nixos-rebuild also requires a "system" profile and an
 | 
			
		||||
            # /etc/NIXOS tag.
 | 
			
		||||
            touch /etc/NIXOS
 | 
			
		||||
            ${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        programs.nbd.enable = true;
 | 
			
		||||
 | 
			
		||||
        fileSystems = {
 | 
			
		||||
          "/" = {
 | 
			
		||||
            fsType = "ext4";
 | 
			
		||||
            device = "/dev/nbd0";
 | 
			
		||||
            noCheck = true;
 | 
			
		||||
            autoResize = true;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        networking.useNetworkd = mkForce true;
 | 
			
		||||
 | 
			
		||||
        systemd = {
 | 
			
		||||
          network.networks."10-boot" = {
 | 
			
		||||
            matchConfig.Name = "et-boot";
 | 
			
		||||
            DHCP = "yes";
 | 
			
		||||
            networkConfig.KeepConfiguration = "yes";
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        system.build = {
 | 
			
		||||
          rootImage = pkgs.callPackage "${modulesPath}/../lib/make-ext4-fs.nix" {
 | 
			
		||||
            storePaths = [ config.system.build.toplevel ];
 | 
			
		||||
            volumeLabel = "netboot-root";
 | 
			
		||||
          };
 | 
			
		||||
          netbootScript = pkgs.writeText "boot.ipxe" ''
 | 
			
		||||
            #!ipxe
 | 
			
		||||
            kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ifname=et-boot:''${mac} nbd_server=''${next-server} ${toString config.boot.kernelParams} ''${cmdline}
 | 
			
		||||
            initrd initrd
 | 
			
		||||
            boot
 | 
			
		||||
          '';
 | 
			
		||||
 | 
			
		||||
          netbootTree = pkgs.linkFarm "netboot-${config.system.name}" [
 | 
			
		||||
            {
 | 
			
		||||
              name = config.system.boot.loader.kernelFile;
 | 
			
		||||
              path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
 | 
			
		||||
            }
 | 
			
		||||
            {
 | 
			
		||||
              name = "initrd";
 | 
			
		||||
              path = "${config.system.build.initialRamdisk}/initrd";
 | 
			
		||||
            }
 | 
			
		||||
            {
 | 
			
		||||
              name = "rootfs.ext4";
 | 
			
		||||
              path = config.system.build.rootImage;
 | 
			
		||||
            }
 | 
			
		||||
            {
 | 
			
		||||
              name = "boot.ipxe";
 | 
			
		||||
              path = config.system.build.netbootScript;
 | 
			
		||||
            }
 | 
			
		||||
          ];
 | 
			
		||||
          netbootArchive = pkgs.runCommand "netboot-${config.system.name}.tar.zst" { } ''
 | 
			
		||||
            add() {
 | 
			
		||||
              ${pkgs.gnutar}/bin/tar --dereference --zstd -rvC "$1" -f "$out" "$2"
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            add "${config.system.build.kernel}" "${config.system.boot.loader.kernelFile}"
 | 
			
		||||
            add "${config.system.build.initialRamdisk}" initrd
 | 
			
		||||
 | 
			
		||||
            tmpdir="$(mktemp -d rootImage.XXXXXX)"
 | 
			
		||||
            ln -s "${config.system.build.rootImage}" "$tmpdir"/rootfs.ext4
 | 
			
		||||
            add "$tmpdir" rootfs.ext4
 | 
			
		||||
 | 
			
		||||
            add "${config.system.build.netbootScript}" boot.ipxe
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
      })
 | 
			
		||||
    ];
 | 
			
		||||
  };
 | 
			
		||||
@@ -77,6 +217,7 @@ in
 | 
			
		||||
      asISO = mkAsOpt asISO "a bootable .iso image";
 | 
			
		||||
      asContainer = mkAsOpt asContainer "a container";
 | 
			
		||||
      asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
 | 
			
		||||
      asNetboot = mkAsOpt asNetboot "a netboot-able kernel initrd, and iPXE script";
 | 
			
		||||
 | 
			
		||||
      buildAs = options.system.build;
 | 
			
		||||
    };
 | 
			
		||||
@@ -110,7 +251,8 @@ in
 | 
			
		||||
        iso = config.my.asISO.config.system.build.isoImage;
 | 
			
		||||
        container = config.my.asContainer.config.system.build.toplevel;
 | 
			
		||||
        kexecTree = config.my.asKexecTree.config.system.build.kexecTree;
 | 
			
		||||
        netbootArchive = config.my.asKexecTree.config.system.build.netbootArchive;
 | 
			
		||||
        netbootTree = config.my.asNetboot.config.system.build.netbootTree;
 | 
			
		||||
        netbootArchive = config.my.asNetboot.config.system.build.netbootArchive;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
{ lib, pkgs, pkgs', inputs, config, ... }:
 | 
			
		||||
{ lib, pkgsFlake, pkgs, pkgs', inputs, config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) mkIf mkDefault mkMerge;
 | 
			
		||||
  inherit (lib.my) mkDefault';
 | 
			
		||||
@@ -53,7 +53,7 @@ in
 | 
			
		||||
          pkgs = {
 | 
			
		||||
            to = {
 | 
			
		||||
              type = "path";
 | 
			
		||||
              path = "${pkgs.path}";
 | 
			
		||||
              path = "${pkgsFlake}";
 | 
			
		||||
            };
 | 
			
		||||
            exact = true;
 | 
			
		||||
          };
 | 
			
		||||
 
 | 
			
		||||
@@ -123,18 +123,7 @@ in
 | 
			
		||||
          (n: _: "ve-${n}")
 | 
			
		||||
          (filterAttrs (_: c: c.networking.bridge == null) cfg.instances);
 | 
			
		||||
 | 
			
		||||
      systemd = mkMerge ([
 | 
			
		||||
        {
 | 
			
		||||
          # By symlinking to the original systemd-nspawn@.service for every instance we force the unit generator to
 | 
			
		||||
          # create overrides instead of replacing the unit entirely
 | 
			
		||||
          packages = [
 | 
			
		||||
            (pkgs.linkFarm "systemd-nspawn-containers" (map (n: {
 | 
			
		||||
              name = "etc/systemd/system/systemd-nspawn@${n}.service";
 | 
			
		||||
              path = "${pkgs.systemd}/example/systemd/system/systemd-nspawn@.service";
 | 
			
		||||
            }) (attrNames cfg.instances)))
 | 
			
		||||
          ];
 | 
			
		||||
        }
 | 
			
		||||
      ] ++ (mapAttrsToList (n: c: {
 | 
			
		||||
      systemd = mkMerge (mapAttrsToList (n: c: {
 | 
			
		||||
        nspawn."${n}" = {
 | 
			
		||||
          execConfig = {
 | 
			
		||||
            Boot = true;
 | 
			
		||||
@@ -182,6 +171,9 @@ in
 | 
			
		||||
            c.containerSystem;
 | 
			
		||||
        in
 | 
			
		||||
        {
 | 
			
		||||
          # To prevent creating a whole new unit file
 | 
			
		||||
          overrideStrategy = "asDropin";
 | 
			
		||||
 | 
			
		||||
          environment = {
 | 
			
		||||
            # systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths
 | 
			
		||||
            root = "/run/machines/${n}";
 | 
			
		||||
@@ -247,7 +239,7 @@ in
 | 
			
		||||
            Bridge = c.networking.bridge;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      }) cfg.instances));
 | 
			
		||||
      }) cfg.instances);
 | 
			
		||||
    })
 | 
			
		||||
 | 
			
		||||
    # Inside container
 | 
			
		||||
 
 | 
			
		||||
@@ -23,13 +23,13 @@ in
 | 
			
		||||
 | 
			
		||||
    security = {
 | 
			
		||||
      polkit.enable = true;
 | 
			
		||||
      pam.services.swaylock = {};
 | 
			
		||||
      pam.services.swaylock-plugin = {};
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    environment.systemPackages = with pkgs; [
 | 
			
		||||
      # for pw-jack
 | 
			
		||||
      pipewire.jack
 | 
			
		||||
      swaylock
 | 
			
		||||
      swaylock-plugin
 | 
			
		||||
    ];
 | 
			
		||||
    services = {
 | 
			
		||||
      pipewire = {
 | 
			
		||||
@@ -51,6 +51,8 @@ in
 | 
			
		||||
          SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
 | 
			
		||||
          # Nintendo
 | 
			
		||||
          SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
 | 
			
		||||
          # FT
 | 
			
		||||
          SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel"
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -36,8 +36,8 @@ let
 | 
			
		||||
        espOverhead =
 | 
			
		||||
          if (!mesh.security.enable) then 0
 | 
			
		||||
          else
 | 
			
		||||
            # SPI + seq + IV + pad / header + ICV
 | 
			
		||||
            4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16;
 | 
			
		||||
            # UDP encap + SPI + seq + IV + pad / header + ICV
 | 
			
		||||
            (if mesh.udpEncapsulation then 8 else 0) + 4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16;
 | 
			
		||||
        # UDP + VXLAN + Ethernet + L3 (IPv4/IPv6)
 | 
			
		||||
        overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead;
 | 
			
		||||
      in
 | 
			
		||||
@@ -62,7 +62,11 @@ let
 | 
			
		||||
      chain l2mesh-${name} {
 | 
			
		||||
        ${optionalString mesh.security.enable ''
 | 
			
		||||
          udp dport isakmp accept
 | 
			
		||||
          meta l4proto esp accept
 | 
			
		||||
          ${if mesh.udpEncapsulation then ''
 | 
			
		||||
            udp dport ipsec-nat-t accept
 | 
			
		||||
          '' else ''
 | 
			
		||||
            meta l4proto esp accept
 | 
			
		||||
          ''}
 | 
			
		||||
        ''}
 | 
			
		||||
        ${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)}
 | 
			
		||||
        return
 | 
			
		||||
@@ -94,6 +98,7 @@ let
 | 
			
		||||
          esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"}
 | 
			
		||||
          ikev2=yes
 | 
			
		||||
          modecfgpull=no
 | 
			
		||||
          encapsulation=${if mesh.udpEncapsulation then "yes" else "no"}
 | 
			
		||||
        '';
 | 
			
		||||
      })
 | 
			
		||||
    otherPeers);
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										165
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,165 @@
 | 
			
		||||
{ lib, pkgs, config, systems, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) mkMerge mkIf mkForce mkOption;
 | 
			
		||||
  inherit (lib.my) mkOpt' mkBoolOpt';
 | 
			
		||||
 | 
			
		||||
  cfg = config.my.netboot;
 | 
			
		||||
 | 
			
		||||
  tftpRoot = pkgs.linkFarm "tftp-root" [
 | 
			
		||||
    {
 | 
			
		||||
      name = "ipxe-x86_64.efi";
 | 
			
		||||
      path = "${pkgs.ipxe}/ipxe.efi";
 | 
			
		||||
    }
 | 
			
		||||
  ];
 | 
			
		||||
  menuFile = pkgs.runCommand "menu.ipxe" {
 | 
			
		||||
    bootHost = cfg.server.host;
 | 
			
		||||
  } ''
 | 
			
		||||
    substituteAll ${./menu.ipxe} "$out"
 | 
			
		||||
  '';
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  options.my.netboot = with lib.types; {
 | 
			
		||||
    client = {
 | 
			
		||||
      enable = mkBoolOpt' false "Whether network booting should be enabled.";
 | 
			
		||||
    };
 | 
			
		||||
    server = {
 | 
			
		||||
      enable = mkBoolOpt' false "Whether a netboot server should be enabled.";
 | 
			
		||||
      ip = mkOpt' str null "IP clients should connect to via TFTP.";
 | 
			
		||||
      host = mkOpt' str config.networking.fqdn "Hostname clients should connect to over HTTP.";
 | 
			
		||||
      installer = {
 | 
			
		||||
        storeSize = mkOpt' str "16GiB" "Total allowed writable size of store.";
 | 
			
		||||
      };
 | 
			
		||||
      instances = mkOpt' (listOf str) [ ] "Systems to hold boot files for.";
 | 
			
		||||
      keaClientClasses = mkOption {
 | 
			
		||||
        type = listOf (attrsOf str);
 | 
			
		||||
        description = "Kea client classes for PXE boot.";
 | 
			
		||||
        readOnly = true;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  config = mkMerge [
 | 
			
		||||
    (mkIf cfg.client.enable {
 | 
			
		||||
      # TODO: Implement!
 | 
			
		||||
    })
 | 
			
		||||
    (mkIf cfg.server.enable {
 | 
			
		||||
      environment = {
 | 
			
		||||
        etc = {
 | 
			
		||||
          "netboot/menu.ipxe".source = menuFile;
 | 
			
		||||
          "netboot/shell.efi".source = "${pkgs.edk2-uefi-shell}/shell.efi";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      systemd = {
 | 
			
		||||
        services = {
 | 
			
		||||
          netboot-update = {
 | 
			
		||||
            description = "Update netboot images";
 | 
			
		||||
            after = [ "systemd-networkd-wait-online.service" ];
 | 
			
		||||
            serviceConfig = {
 | 
			
		||||
              Type = "oneshot";
 | 
			
		||||
              RemainAfterExit = true;
 | 
			
		||||
            };
 | 
			
		||||
            path = with pkgs; [
 | 
			
		||||
              coreutils curl jq gnutar
 | 
			
		||||
            ];
 | 
			
		||||
            script = ''
 | 
			
		||||
              update_nixos() {
 | 
			
		||||
                latestShort="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/tags/installer \
 | 
			
		||||
                             | jq -r .commit.sha | cut -c -7)"
 | 
			
		||||
                if [ -f nixos-installer/tag.txt ] && [ "$(< nixos-installer/tag.txt)" = "$latestShort" ]; then
 | 
			
		||||
                  echo "NixOS installer is up to date"
 | 
			
		||||
                  return
 | 
			
		||||
                fi
 | 
			
		||||
 | 
			
		||||
                echo "Updating NixOS installer to $latestShort"
 | 
			
		||||
                mkdir -p nixos-installer
 | 
			
		||||
                fname="jackos-installer-netboot-$latestShort.tar.zst"
 | 
			
		||||
                downloadUrl="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/releases/tags/installer | \
 | 
			
		||||
                               jq -r ".assets[] | select(.name == \"$fname\").browser_download_url")"
 | 
			
		||||
                curl -Lo /tmp/nixos-installer-netboot.tar.zst "$downloadUrl"
 | 
			
		||||
                tar -C nixos-installer --zstd -xf /tmp/nixos-installer-netboot.tar.zst
 | 
			
		||||
                truncate -s "${cfg.server.installer.storeSize}" nixos-installer/rootfs.ext4
 | 
			
		||||
                rm /tmp/nixos-installer-netboot.tar.zst
 | 
			
		||||
                echo "$latestShort" > nixos-installer/tag.txt
 | 
			
		||||
              }
 | 
			
		||||
 | 
			
		||||
              mkdir -p /srv/netboot
 | 
			
		||||
              cd /srv/netboot
 | 
			
		||||
 | 
			
		||||
              ln -sf ${menuFile} boot.ipxe
 | 
			
		||||
              ln -sf "${pkgs.edk2-uefi-shell}/efi-shell-${config.nixpkgs.localSystem.linuxArch}.efi"
 | 
			
		||||
              update_nixos
 | 
			
		||||
            '';
 | 
			
		||||
            startAt = "06:00";
 | 
			
		||||
            wantedBy = [ "network-online.target" ];
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          nbd-server = {
 | 
			
		||||
            serviceConfig = {
 | 
			
		||||
              PrivateUsers = mkForce false;
 | 
			
		||||
              CacheDirectory = "netboot";
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      services = {
 | 
			
		||||
        atftpd = {
 | 
			
		||||
          enable = true;
 | 
			
		||||
          root = tftpRoot;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        nginx = {
 | 
			
		||||
          virtualHosts."${cfg.server.host}" = {
 | 
			
		||||
            locations."/" = {
 | 
			
		||||
              root = "/srv/netboot";
 | 
			
		||||
              extraConfig = ''
 | 
			
		||||
                autoindex on;
 | 
			
		||||
              '';
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        nbd.server = {
 | 
			
		||||
          enable = true;
 | 
			
		||||
          extraOptions = {
 | 
			
		||||
            allowlist = true;
 | 
			
		||||
          };
 | 
			
		||||
          exports = {
 | 
			
		||||
            nixos-installer = {
 | 
			
		||||
              path = "/srv/netboot/nixos-installer/rootfs.ext4";
 | 
			
		||||
              extraOptions = {
 | 
			
		||||
                copyonwrite = true;
 | 
			
		||||
                cowdir = "/var/cache/netboot";
 | 
			
		||||
                sparse_cow = true;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      my = {
 | 
			
		||||
        tmproot.persistence.config.directories = [
 | 
			
		||||
          "/srv/netboot"
 | 
			
		||||
          { directory = "/var/cache/netboot"; mode = "0700"; }
 | 
			
		||||
        ];
 | 
			
		||||
        netboot.server.keaClientClasses = [
 | 
			
		||||
          {
 | 
			
		||||
            name = "ipxe";
 | 
			
		||||
            test = "substring(option[user-class].hex, 0, 4) == 'iPXE'";
 | 
			
		||||
            next-server = cfg.server.ip;
 | 
			
		||||
            server-hostname = cfg.server.host;
 | 
			
		||||
            boot-file-name = "http://${cfg.server.host}/boot.ipxe";
 | 
			
		||||
          }
 | 
			
		||||
          {
 | 
			
		||||
            name = "efi-x86_64";
 | 
			
		||||
            test = "option[client-system].hex == 0x0007";
 | 
			
		||||
            next-server = cfg.server.ip;
 | 
			
		||||
            server-hostname = cfg.server.host;
 | 
			
		||||
            boot-file-name = "ipxe-x86_64.efi";
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
    })
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										68
									
								
								nixos/modules/netboot/menu.ipxe
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								nixos/modules/netboot/menu.ipxe
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
			
		||||
#!ipxe
 | 
			
		||||
 | 
			
		||||
set server http://@bootHost@
 | 
			
		||||
 | 
			
		||||
# Figure out if client is 64-bit capable
 | 
			
		||||
cpuid --ext 29 && set arch x86_64 || set arch i386
 | 
			
		||||
 | 
			
		||||
isset ${menu-default} || set menu-default exit
 | 
			
		||||
 | 
			
		||||
:start
 | 
			
		||||
menu Welcome to /dev/player0's humble iPXE boot menu
 | 
			
		||||
item --gap --           Operating Systems
 | 
			
		||||
iseq ${arch} x86_64 &&
 | 
			
		||||
item --key n nixos      NixOS installer
 | 
			
		||||
# iseq ${arch} x86_64 &&
 | 
			
		||||
# item --key a archlinux Arch Linux (archiso x86_64)
 | 
			
		||||
# iseq ${arch} x86_64 &&
 | 
			
		||||
# item --key p alpine   Alpine Linux
 | 
			
		||||
item --gap --           Other Options
 | 
			
		||||
item --key e efi_shell  UEFI Shell
 | 
			
		||||
item --key x xyz        netboot.xyz
 | 
			
		||||
item --key c config     iPXE settings
 | 
			
		||||
item --key s shell      Drop to iPXE shell
 | 
			
		||||
item --key r reboot     Reboot
 | 
			
		||||
item --key q exit       Exit (and continue to next boot device)
 | 
			
		||||
choose --timeout 0 --default ${menu-default} selected || goto cancel
 | 
			
		||||
goto ${selected}
 | 
			
		||||
 | 
			
		||||
:cancel
 | 
			
		||||
echo You cancelled the menu, dropping you to an iPXE shell
 | 
			
		||||
 | 
			
		||||
:shell
 | 
			
		||||
echo Type 'exit' to go back to the menu
 | 
			
		||||
shell
 | 
			
		||||
set menu-default nixos
 | 
			
		||||
goto start
 | 
			
		||||
 | 
			
		||||
:failed
 | 
			
		||||
echo Booting failed, dropping to shell
 | 
			
		||||
goto shell
 | 
			
		||||
 | 
			
		||||
:reboot
 | 
			
		||||
reboot
 | 
			
		||||
 | 
			
		||||
:exit
 | 
			
		||||
exit
 | 
			
		||||
 | 
			
		||||
:config
 | 
			
		||||
config
 | 
			
		||||
set menu-default config
 | 
			
		||||
goto start
 | 
			
		||||
 | 
			
		||||
:efi_shell
 | 
			
		||||
chain ${server}/efi-shell-${arch}.efi || goto failed
 | 
			
		||||
 | 
			
		||||
:xyz
 | 
			
		||||
chain --autofree https://boot.netboot.xyz || goto failed
 | 
			
		||||
 | 
			
		||||
:nixos
 | 
			
		||||
set cmdline nbd_export=nixos-installer
 | 
			
		||||
chain ${server}/nixos-installer/boot.ipxe || goto failed
 | 
			
		||||
 | 
			
		||||
:archlinux
 | 
			
		||||
# set mirrorurl https://arch.nul.ie/
 | 
			
		||||
chain ${server}/arch.ipxe || goto failed
 | 
			
		||||
 | 
			
		||||
:alpine
 | 
			
		||||
chain ${server}/alpine.ipxe || goto failed
 | 
			
		||||
@@ -6,7 +6,7 @@ let
 | 
			
		||||
  cfg = config.my.nvme;
 | 
			
		||||
  nvme-cli = pkgs.nvme-cli.override {
 | 
			
		||||
    libnvme = pkgs.libnvme.overrideAttrs (o: {
 | 
			
		||||
      patches = o.patches ++ [ ./libnvme-hostconf.patch ];
 | 
			
		||||
      patches = (if (o ? patches) then o.patches else [ ]) ++ [ ./libnvme-hostconf.patch ];
 | 
			
		||||
    });
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,7 @@
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib)
 | 
			
		||||
    optionalString concatStringsSep concatMap concatMapStringsSep mkIf mkDefault mkMerge mkForce mkVMOverride
 | 
			
		||||
    mkAliasDefinitions;
 | 
			
		||||
    mkAliasDefinitions mapAttrsToList filterAttrs;
 | 
			
		||||
  inherit (lib.my) mkOpt' mkBoolOpt' mkVMOverride';
 | 
			
		||||
 | 
			
		||||
  cfg = config.my.tmproot;
 | 
			
		||||
@@ -492,6 +492,37 @@ in
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      })
 | 
			
		||||
      (mkIf config.services.wastebin.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [ "/var/lib/private/wastebin" ];
 | 
			
		||||
      })
 | 
			
		||||
      (mkIf config.services.photoprism.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [
 | 
			
		||||
          {
 | 
			
		||||
            directory = config.services.photoprism.storagePath;
 | 
			
		||||
            mode = "0750";
 | 
			
		||||
            user = "photoprism";
 | 
			
		||||
            group = "photoprism";
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      })
 | 
			
		||||
      (mkIf config.services.mautrix-whatsapp.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [
 | 
			
		||||
          {
 | 
			
		||||
            directory = "/var/lib/mautrix-whatsapp";
 | 
			
		||||
            mode = "0750";
 | 
			
		||||
            user = "mautrix-whatsapp";
 | 
			
		||||
            group = "mautrix-whatsapp";
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      })
 | 
			
		||||
      {
 | 
			
		||||
        my.tmproot.persistence.config.directories = mapAttrsToList (n: i: {
 | 
			
		||||
          directory = "/var/lib/${i.dataDir}";
 | 
			
		||||
          mode = "0750";
 | 
			
		||||
          user = "mautrix-meta-${n}";
 | 
			
		||||
          group = "mautrix-meta";
 | 
			
		||||
        }) (filterAttrs (_: i: i.enable) config.services.mautrix-meta.instances);
 | 
			
		||||
      }
 | 
			
		||||
    ]))
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										49
									
								
								pkgs/chocolate-doom2xx/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								pkgs/chocolate-doom2xx/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
			
		||||
{ lib, stdenv, autoreconfHook, pkg-config, SDL, SDL_mixer, SDL_net
 | 
			
		||||
, fetchFromGitHub, fetchpatch, python3 }:
 | 
			
		||||
 | 
			
		||||
stdenv.mkDerivation rec {
 | 
			
		||||
  pname = "chocolate-doom";
 | 
			
		||||
  version = "2.3.0";
 | 
			
		||||
 | 
			
		||||
  src = fetchFromGitHub {
 | 
			
		||||
    owner = "chocolate-doom";
 | 
			
		||||
    repo = pname;
 | 
			
		||||
    rev = "${pname}-${version}";
 | 
			
		||||
    sha256 = "sha256-1uw/1CYKBvDNgT5XxRBY24Evt3f4Y6YQ6bScU+KNHgM=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  patches = [
 | 
			
		||||
    # Pull upstream patch to fix build against gcc-10:
 | 
			
		||||
    #   https://github.com/chocolate-doom/chocolate-doom/pull/1257
 | 
			
		||||
    (fetchpatch {
 | 
			
		||||
      name = "fno-common.patch";
 | 
			
		||||
      url = "https://github.com/chocolate-doom/chocolate-doom/commit/a8fd4b1f563d24d4296c3e8225c8404e2724d4c2.patch";
 | 
			
		||||
      sha256 = "1dmbygn952sy5n8qqp0asg11pmygwgygl17lrj7i0fxa0nrhixhj";
 | 
			
		||||
    })
 | 
			
		||||
    ./demoloopi.patch
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  outputs = [ "out" "man" ];
 | 
			
		||||
 | 
			
		||||
  postPatch = ''
 | 
			
		||||
    patchShebangs --build man/{simplecpp,docgen}
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  nativeBuildInputs = [
 | 
			
		||||
    autoreconfHook
 | 
			
		||||
    pkg-config
 | 
			
		||||
    # for documentation
 | 
			
		||||
    python3
 | 
			
		||||
  ];
 | 
			
		||||
  buildInputs = [ (SDL.override { cacaSupport = true; }) SDL_mixer SDL_net ];
 | 
			
		||||
  enableParallelBuilding = true;
 | 
			
		||||
 | 
			
		||||
  meta = {
 | 
			
		||||
    homepage = "http://chocolate-doom.org/";
 | 
			
		||||
    description = "A Doom source port that accurately reproduces the experience of Doom as it was played in the 1990s";
 | 
			
		||||
    license = lib.licenses.gpl2Plus;
 | 
			
		||||
    platforms = lib.platforms.unix;
 | 
			
		||||
    hydraPlatforms = lib.platforms.linux; # darwin times out
 | 
			
		||||
    maintainers = with lib.maintainers; [ ];
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										91
									
								
								pkgs/chocolate-doom2xx/demoloopi.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								pkgs/chocolate-doom2xx/demoloopi.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
			
		||||
diff --git a/src/doom/d_main.c b/src/doom/d_main.c
 | 
			
		||||
index 65a39a10..3f799b0f 100644
 | 
			
		||||
--- a/src/doom/d_main.c
 | 
			
		||||
+++ b/src/doom/d_main.c
 | 
			
		||||
@@ -483,6 +483,8 @@ void D_DoomLoop (void)
 | 
			
		||||
 //  DEMO LOOP
 | 
			
		||||
 //
 | 
			
		||||
 int             demosequence;
 | 
			
		||||
+int             demoloopi;
 | 
			
		||||
+char            demoloopname[9];
 | 
			
		||||
 int             pagetic;
 | 
			
		||||
 char                    *pagename;
 | 
			
		||||
 
 | 
			
		||||
@@ -524,6 +526,8 @@ void D_AdvanceDemo (void)
 | 
			
		||||
 //
 | 
			
		||||
 void D_DoAdvanceDemo (void)
 | 
			
		||||
 {
 | 
			
		||||
+    int havedemo4;
 | 
			
		||||
+
 | 
			
		||||
     players[consoleplayer].playerstate = PST_LIVE;  // not reborn
 | 
			
		||||
     advancedemo = false;
 | 
			
		||||
     usergame = false;               // no save / end game here
 | 
			
		||||
@@ -539,10 +543,14 @@ void D_DoAdvanceDemo (void)
 | 
			
		||||
     // However! There is an alternate version of Final Doom that
 | 
			
		||||
     // includes a fixed executable.
 | 
			
		||||
 
 | 
			
		||||
-    if (gameversion == exe_ultimate || gameversion == exe_final)
 | 
			
		||||
+    havedemo4 = gameversion == exe_ultimate || gameversion == exe_final;
 | 
			
		||||
+    if (havedemo4)
 | 
			
		||||
       demosequence = (demosequence+1)%7;
 | 
			
		||||
     else
 | 
			
		||||
       demosequence = (demosequence+1)%6;
 | 
			
		||||
+
 | 
			
		||||
+    if (demoloopi < 0 || demoloopi > (havedemo4 ? 3 : 2))
 | 
			
		||||
+      I_Error("Invalid demo loop start %d", demoloopi);
 | 
			
		||||
     
 | 
			
		||||
     switch (demosequence)
 | 
			
		||||
     {
 | 
			
		||||
@@ -558,17 +566,11 @@ void D_DoAdvanceDemo (void)
 | 
			
		||||
 	else
 | 
			
		||||
 	  S_StartMusic (mus_intro);
 | 
			
		||||
 	break;
 | 
			
		||||
-      case 1:
 | 
			
		||||
-	G_DeferedPlayDemo(DEH_String("demo1"));
 | 
			
		||||
-	break;
 | 
			
		||||
       case 2:
 | 
			
		||||
 	pagetic = 200;
 | 
			
		||||
 	gamestate = GS_DEMOSCREEN;
 | 
			
		||||
 	pagename = DEH_String("CREDIT");
 | 
			
		||||
 	break;
 | 
			
		||||
-      case 3:
 | 
			
		||||
-	G_DeferedPlayDemo(DEH_String("demo2"));
 | 
			
		||||
-	break;
 | 
			
		||||
       case 4:
 | 
			
		||||
 	gamestate = GS_DEMOSCREEN;
 | 
			
		||||
 	if ( gamemode == commercial)
 | 
			
		||||
@@ -587,12 +589,14 @@ void D_DoAdvanceDemo (void)
 | 
			
		||||
 	      pagename = DEH_String("HELP2");
 | 
			
		||||
 	}
 | 
			
		||||
 	break;
 | 
			
		||||
+      case 1:
 | 
			
		||||
+      case 3:
 | 
			
		||||
       case 5:
 | 
			
		||||
-	G_DeferedPlayDemo(DEH_String("demo3"));
 | 
			
		||||
-	break;
 | 
			
		||||
         // THE DEFINITIVE DOOM Special Edition demo
 | 
			
		||||
       case 6:
 | 
			
		||||
-	G_DeferedPlayDemo(DEH_String("demo4"));
 | 
			
		||||
+	DEH_snprintf(demoloopname, 9, "demo%d", demoloopi + 1);
 | 
			
		||||
+	G_DeferedPlayDemo(demoloopname);
 | 
			
		||||
+	demoloopi = (demoloopi+1) % (havedemo4 ? 4 : 3);
 | 
			
		||||
 	break;
 | 
			
		||||
     }
 | 
			
		||||
 
 | 
			
		||||
@@ -1891,7 +1895,15 @@ void D_DoomMain (void)
 | 
			
		||||
 	G_TimeDemo (demolumpname);
 | 
			
		||||
 	D_DoomLoop ();  // never returns
 | 
			
		||||
     }
 | 
			
		||||
-	
 | 
			
		||||
+
 | 
			
		||||
+    p = M_CheckParmWithArgs("-demoloopi", 1);
 | 
			
		||||
+    if (p)
 | 
			
		||||
+    {
 | 
			
		||||
+        demoloopi = atoi(myargv[p+1]);
 | 
			
		||||
+    } else {
 | 
			
		||||
+        demoloopi = 0;
 | 
			
		||||
+    }
 | 
			
		||||
+
 | 
			
		||||
     if (startloadgame >= 0)
 | 
			
		||||
     {
 | 
			
		||||
         M_StringCopy(file, P_SaveGameFile(startloadgame), sizeof(file));
 | 
			
		||||
@@ -8,4 +8,9 @@ in
 | 
			
		||||
  vfio-pci-bind = callPackage ./vfio-pci-bind.nix { };
 | 
			
		||||
  librespeed-go = callPackage ./librespeed-go.nix { };
 | 
			
		||||
  modrinth-app = callPackage ./modrinth-app { };
 | 
			
		||||
  glfw-minecraft = callPackage ./glfw-minecraft { };
 | 
			
		||||
  chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
 | 
			
		||||
  windowtolayer = callPackage ./windowtolayer.nix { };
 | 
			
		||||
  swaylock-plugin = callPackage ./swaylock-plugin.nix { };
 | 
			
		||||
  terminaltexteffects = callPackage ./terminaltexteffects.nix { };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										6
									
								
								pkgs/glfw-minecraft/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								pkgs/glfw-minecraft/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
			
		||||
{ lib, glfw-wayland-minecraft, ... }:
 | 
			
		||||
glfw-wayland-minecraft.overrideAttrs (o: {
 | 
			
		||||
  patches = [
 | 
			
		||||
    ./suppress-wayland-errors.patch
 | 
			
		||||
  ];
 | 
			
		||||
})
 | 
			
		||||
							
								
								
									
										43
									
								
								pkgs/glfw-minecraft/suppress-wayland-errors.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkgs/glfw-minecraft/suppress-wayland-errors.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
			
		||||
diff --git a/src/wl_window.c b/src/wl_window.c
 | 
			
		||||
index 7c509896..db9a6451 100644
 | 
			
		||||
--- a/src/wl_window.c
 | 
			
		||||
+++ b/src/wl_window.c
 | 
			
		||||
@@ -2115,25 +2115,21 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
 | 
			
		||||
 void _glfwSetWindowIconWayland(_GLFWwindow* window,
 | 
			
		||||
                                int count, const GLFWimage* images)
 | 
			
		||||
 {
 | 
			
		||||
-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
			
		||||
-                    "Wayland: The platform does not support setting the window icon");
 | 
			
		||||
+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
 | 
			
		||||
 {
 | 
			
		||||
     // A Wayland client is not aware of its position, so just warn and leave it
 | 
			
		||||
     // as (0, 0)
 | 
			
		||||
-
 | 
			
		||||
-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
			
		||||
-                    "Wayland: The platform does not provide the window position");
 | 
			
		||||
+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not provide the window position\n");
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos)
 | 
			
		||||
 {
 | 
			
		||||
     // A Wayland client can not set its position, so just warn
 | 
			
		||||
 
 | 
			
		||||
-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
			
		||||
-                    "Wayland: The platform does not support setting the window position");
 | 
			
		||||
+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window position\n");
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height)
 | 
			
		||||
@@ -2359,8 +2355,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
 | 
			
		||||
 
 | 
			
		||||
 void _glfwFocusWindowWayland(_GLFWwindow* window)
 | 
			
		||||
 {
 | 
			
		||||
-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
			
		||||
-                    "Wayland: The platform does not support setting the input focus");
 | 
			
		||||
+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
 | 
			
		||||
 }
 | 
			
		||||
 
 | 
			
		||||
 void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
 | 
			
		||||
@@ -81,7 +81,7 @@ rustPlatform.buildRustPackage rec {
 | 
			
		||||
 | 
			
		||||
    dontFixup = true;
 | 
			
		||||
    outputHashMode = "recursive";
 | 
			
		||||
    outputHash = "sha256-9HtTdIotG3sNIlWhd76v7Ia6P69ufp/FFqZfINXSkVc=";
 | 
			
		||||
    outputHash = "sha256-Txttk8qZpDsAuiF8laKbZss/KEoT1Z+oepbj2s4XjE8=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  preBuild = ''
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										41
									
								
								pkgs/swaylock-plugin.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkgs/swaylock-plugin.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
			
		||||
{ lib, stdenv, fetchFromGitHub, fetchpatch
 | 
			
		||||
, meson, ninja, pkg-config, scdoc, wayland-scanner
 | 
			
		||||
, wayland, wayland-protocols, libxkbcommon, cairo, gdk-pixbuf, pam
 | 
			
		||||
}:
 | 
			
		||||
 | 
			
		||||
stdenv.mkDerivation rec {
 | 
			
		||||
  pname = "swaylock-plugin";
 | 
			
		||||
  version = "1dd15b6";
 | 
			
		||||
 | 
			
		||||
  src = fetchFromGitHub {
 | 
			
		||||
    owner = "mstoeckl";
 | 
			
		||||
    repo = pname;
 | 
			
		||||
    rev = "1dd15b6ecbe91be7a3dc4a0fa9514fb166fb2e07";
 | 
			
		||||
    hash = "sha256-xWyDDT8sXAL58HtA9ifzCenKMmOZquzXZaz3ttGGJuY=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  strictDeps = true;
 | 
			
		||||
  depsBuildBuild = [ pkg-config ];
 | 
			
		||||
  nativeBuildInputs = [ meson ninja pkg-config scdoc wayland-scanner ];
 | 
			
		||||
  buildInputs = [ wayland wayland-protocols libxkbcommon cairo gdk-pixbuf pam ];
 | 
			
		||||
 | 
			
		||||
  mesonFlags = [
 | 
			
		||||
    "-Dpam=enabled" "-Dgdk-pixbuf=enabled" "-Dman-pages=enabled"
 | 
			
		||||
  ];
 | 
			
		||||
  env.NIX_CFLAGS_COMPILE = "-Wno-maybe-uninitialized";
 | 
			
		||||
 | 
			
		||||
  meta = with lib; {
 | 
			
		||||
    description = "Screen locker for Wayland -- fork with background plugin support";
 | 
			
		||||
    longDescription = ''
 | 
			
		||||
      Fork of swaylock, a screen locking utility for Wayland compositors.
 | 
			
		||||
      With swaylock-plugin, you can for your lockscreen background display
 | 
			
		||||
      the animated output from any wallpaper program that implements the
 | 
			
		||||
      wlr-layer-shell-unstable-v1 protocol.
 | 
			
		||||
    '';
 | 
			
		||||
    inherit (src.meta) homepage;
 | 
			
		||||
    mainProgram = "swaylock";
 | 
			
		||||
    license = licenses.mit;
 | 
			
		||||
    platforms = platforms.linux;
 | 
			
		||||
    maintainers = with maintainers; [ devplayer0 ];
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										19
									
								
								pkgs/terminaltexteffects.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								pkgs/terminaltexteffects.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
			
		||||
{ lib
 | 
			
		||||
, python3Packages
 | 
			
		||||
, fetchPypi
 | 
			
		||||
}:
 | 
			
		||||
 | 
			
		||||
python3Packages.buildPythonApplication rec {
 | 
			
		||||
  pname = "terminaltexteffects";
 | 
			
		||||
  version = "0.10.1";
 | 
			
		||||
  pyproject = true;
 | 
			
		||||
 | 
			
		||||
  src = fetchPypi {
 | 
			
		||||
    inherit pname version;
 | 
			
		||||
    hash = "sha256-NyWPfdgLeXAxKPJOzB7j4aT+zjrURN59CGcv0Vt99y0=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  build-system = with python3Packages; [
 | 
			
		||||
    poetry-core
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										18
									
								
								pkgs/windowtolayer.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								pkgs/windowtolayer.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
			
		||||
{ lib
 | 
			
		||||
, fetchFromGitLab
 | 
			
		||||
, rustPlatform
 | 
			
		||||
}:
 | 
			
		||||
rustPlatform.buildRustPackage rec {
 | 
			
		||||
  pname = "windowtolayer";
 | 
			
		||||
  version = "a5b89c3c";
 | 
			
		||||
 | 
			
		||||
  src = fetchFromGitLab {
 | 
			
		||||
    domain = "gitlab.freedesktop.org";
 | 
			
		||||
    owner = "mstoeckl";
 | 
			
		||||
    repo = pname;
 | 
			
		||||
    rev = "a5b89c3c047297fd574932860a6c89e9ea02ba5d";
 | 
			
		||||
    hash = "sha256-rssL2XkbTqUvJqfUFhzULeE4/VBzjeBC5iZWSJ8MJ+M=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  cargoHash = "sha256-XHmLsx9qdjlBz4xJFFiO24bR9CMw1o5368K+YMpMIBA=";
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										31
									
								
								secrets/chatterbox/doublepuppet.yaml.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										31
									
								
								secrets/chatterbox/doublepuppet.yaml.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,31 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB5WDhJ
 | 
			
		||||
U3BNdEFYR2xVb21wQmhuM3h2TWpwSm40aW5ycjJJZ0NQNjNEdDBNCllpZlRtcjFM
 | 
			
		||||
UE1TbE02ZStsMk44YVZ2T1piZmh3REFlV0Q0RWVGMERaRkEKLT4gWDI1NTE5IFRz
 | 
			
		||||
T1grT3ZMRmVUaWhFU1BJbnpDTDYvRUUwUTZYUFQ2OXhQbS9KeTlUWHMKQU9UaThT
 | 
			
		||||
bHFaYXM4VWhPU0xBZFI1WDkzdzlQUGlJNStjT2UwblZ0S1V4VQotPiBbbGBjW3wt
 | 
			
		||||
Z3JlYXNlICUgRiVYCk4rMVEzMnVMSTg4VHpPcTIvRkZZd20yMVlJbXdTK3UyTkVn
 | 
			
		||||
V3B1OFZiNCs1R0F0WmFYc3BDaW5FajNCUgotLS0gajBSMklJUDgzZlNFTlFkZTFm
 | 
			
		||||
amNxblljWkVsc2w5NUVZM0x4VGl2NWZDNApDqGhViG2eQSuIEEwEh2rxVBAVkCBj
 | 
			
		||||
EXUYBqrcqlRFRT+cN8EM+aT6ppUeVuuOv3aTYx+tM2M2yzjWvrckeVj0fr5GwpIT
 | 
			
		||||
vZaj2yceTl/6M/Z7fK5AT7SqFp/sxSJZcDWInPcPc3MfvcSC5ca7UFcTd/iqtpgD
 | 
			
		||||
gSkiDlYrZKV3PtLrp/WO06q9zrBAiJbeBLvHM/Ym8ctSl4w/SjETDmhm3LzbX+Ow
 | 
			
		||||
uk/hSuk9m+pTeBPJ6CWrUVHVLitcyk2YwLwLRLvGQAQF6xQgEtL3M/pGsQp3Q6TA
 | 
			
		||||
ju17Kmh+kIdkgEDj9PzA8Q7QfxU3WdC6RoIXEuQQHVcJd8IAT8i3ZuuI312sXeX3
 | 
			
		||||
7+2Rav480GIF+5bHQGJkvBTvxj3OFGUuyREFO8nXaGwUrcdCfmkhuSs1TGZj6qZQ
 | 
			
		||||
xVUnp+k9X6gH5xYjka/c3Ov5rTKE7CGqJ1VBdZAcuIjhH4D33RmaVmTg7SquXZc8
 | 
			
		||||
cHqaoYcB/s273Wxv5qZUEfEz9ssJCxCqEOG7uQIeXgLsp7O5VtvEJfCo6Q7boN3h
 | 
			
		||||
Qom+6LJfnNMew2mwLQS4jV8abrVXTcmH9cA4OdtLtTO/m123AlamJc7Dmv+EDYLV
 | 
			
		||||
qu9jm2Dk6hz+jgJ5ruDFPyAaxcfQqEBFbKI0eB3D6qu3YcN49q8+JI05aTDyf4T3
 | 
			
		||||
8Mv9oe0Jlv7Gf3JqORw6dhDatyRzc2FrbkpF7mwxtLTDPKsgCBFNIfVitZdXFxN/
 | 
			
		||||
adu1nSBl6APznPJJZ4Xb6HmJHb/mDCeWmwt4fDwQlg0d6G8EFGYexSZOjA8yxXlr
 | 
			
		||||
vwhaPYldJsxlkL24nRu4wUFi3jkEepU/KsBbYMgAp2+DIzluzKErvZh2WUAr96AH
 | 
			
		||||
dMWdNlbmhNKwM/vfkzonZ1jSFIuad7c67cWo8nUFVxKU3tAjMFTgrasHzPyLK2HC
 | 
			
		||||
WJnEpmMvQsji/blPVR7AOEAzNXwpOj0N/erPCtWp2v5Vyfs/ej/sLGp6tfCdZeUv
 | 
			
		||||
13aNG8pYtQbHgT8qekVKRsjRlCyVYWd1lFEd3rqldtX6z8oT4cIj/c6QYzC1Rwxp
 | 
			
		||||
aNPqMA3e3da9t4kkHol05grDPy+5fQ7/5B5kfbidHIjCoA9DVUEh70QYuNi4JlgM
 | 
			
		||||
54Jh1v3N3+525YmavPbuwgDGsRkz6Sh5padEWFQ2Xw6B58Vgm6flA1ZSXNSp8bK1
 | 
			
		||||
3g3lyCJSimFT6B7Q8gyf6gNJVpZuHrAEexCed3qhK+Ijl2SIvsTFCWLSokOPeX/F
 | 
			
		||||
cy7xQ94GuLZqPedDvZ8wVOQ3X1/E46lWoY1w3qzD5l1OHuDUqJcW1ae8lXTmh8Z0
 | 
			
		||||
kxRFPfNaJA1y1NaD33t+gis7SA==
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
							
								
								
									
										15
									
								
								secrets/chatterbox/mautrix-instagram.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								secrets/chatterbox/mautrix-instagram.env.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,15 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBhVkhZ
 | 
			
		||||
azNHVFdNUnJ6MVpJaGo0T0h0L3ZMbHB3RG9Ic2ZZajQ4amt1S3dVCmo0YnZxL0p3
 | 
			
		||||
Y2RHVWFUSVlySTNDNThYMks0aGdOdHdGQjdrRTZZdTFpdlUKLT4gWDI1NTE5IGxZ
 | 
			
		||||
elhYTEtMUHR6VlR2b0VwM01XNnFNR0tuK2hFenlhWTIwS3hSMlVIR0kKbVNLWFRZ
 | 
			
		||||
c0ZrK3YraTdhR1IzL3FxMEFQYndsYm5NUmpDd3M4Sm43aUJ3VQotPiBuZ0BNPnxi
 | 
			
		||||
Ny1ncmVhc2UgUHIgJ0hvbT0oCmMwcmVHR2dTd3VaSFpHUWh1ajA5M1FUTS9WQkNQ
 | 
			
		||||
UzZqK0JETmlUOU44eFQ4emw0Ci0tLSBhT01BQ3VVdHBQK29GdmN0VEtoazNCcFpY
 | 
			
		||||
WFhIeTh4VTlHeDBhcG1lNUhrCmxtBrEH3ornrPQi4eIIOskkKMTDs1Ow3Z70WuEd
 | 
			
		||||
FyXGsYXFwpibxFxAWWLwAYiq7cMTEE0GmYRlNYt7bWwJn12Kv5LVZCL8HXTNXCLl
 | 
			
		||||
xf0za7pHvXF8XWaZwU2eMMZRdkzE6HNnbLt+DB0TKS9vf33i7tmwduqJ8oiUtTRD
 | 
			
		||||
XTm5IPyULH2rikDuDm0aAvaZhSFlzPIe1MKr93ZaHGrvcnbzhADyt5DRmmDuYSk4
 | 
			
		||||
SSSrhHP3P0LB0OoMGVU8DM9O7QNVwScs07T7ll238Jc/JG/KHj1kT2K9LYAiNl4Q
 | 
			
		||||
JfhOOA==
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
							
								
								
									
										14
									
								
								secrets/chatterbox/mautrix-messenger.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								secrets/chatterbox/mautrix-messenger.env.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,14 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBOb1dR
 | 
			
		||||
V1hVcGZMRm1yeUtKTUdBdkVjazJsS3l1aHR1Zzc4VGx1SmVyNHhZCkxZY2RLNW1m
 | 
			
		||||
eFVzRG00eGN3eGNoOGh0ZHhNZWZhcmxoVzV5elM4bGdxUTAKLT4gWDI1NTE5IGw3
 | 
			
		||||
ZThQM1JESU1lZk9Pc1ljanU4dVUwb0xuZENWSFcrZ01vejhRT3E5ZzQKTXZ4Q0Zn
 | 
			
		||||
OWFHb0xoZi9UL1NSUWNEQytmd0dqVXFydUduYnZGVGhKK0JVTQotPiBPc0RaXl5+
 | 
			
		||||
Wi1ncmVhc2UKYUtBRGZhVlY2MlAzRjJ5YQotLS0gSllJbHVXbDZtZGFac1JqN1I4
 | 
			
		||||
bUdyNSs4c3VLSEJUVmo5VkpZVmkzRzlHOAow5ki6UNCCQQt0YXMr6OGjsDg9yYkH
 | 
			
		||||
ssU+hO1wKXepVj6QSROZubLLTyV4Cm5rHWESMiSGTV3rcGNDUuphrS1va+stkJqK
 | 
			
		||||
O7ZHP68QmCPLdlu1ghNXw7etm0K+BqqQTpPfgrusW9emUV8gIY5/SWmK6hDQLR/T
 | 
			
		||||
ibC6GqP+ZCEQOL5OgB59PUCKwEjia6O6xFKPHVLNzfhg4ZmMCNNS70gqpTFRyN/E
 | 
			
		||||
s9HMiwYVuvKjEODV9kM2jhfTTD3Ri10SmHurBqdbpzWhOoLz3oMTQTyW206Air/G
 | 
			
		||||
8RoM1RYcVS3DI69rNg==
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
							
								
								
									
										16
									
								
								secrets/chatterbox/mautrix-whatsapp.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								secrets/chatterbox/mautrix-whatsapp.env.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,16 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBTZGdy
 | 
			
		||||
cnNwTkkzOHBlcngzYTZycE11RlljK1RtSCthVkxSa1B0SllGZW1jCk1RbzVSMldJ
 | 
			
		||||
SFg4ZlFnT3ZJTTlsM0lWYlRTRkdMZU5YS2FpTmxCaVNSOGcKLT4gWDI1NTE5IFRU
 | 
			
		||||
RVF0NXV4bFB2ektiQVN0SkFvOXN3MGZFeDdHK25NQXBqelBvaVg3alkKaWhCRTkz
 | 
			
		||||
S2o5bjFWQ0VuZzZxTGpsOXBRajlGSmt3bURQN254SXhyRm8zNAotPiB7MFM0TDEr
 | 
			
		||||
Si1ncmVhc2UgJG0gNkggLAppL0RJQnJRQ09yb3IzaTNiQTBBOGlrbjEzNjhBNWdU
 | 
			
		||||
Z0VFZ1o1OEI5M3lOaHg3eW0xQlUvbVBGOEpwRXdDZlZXCjB1SSsvZmZtSlU2RzhY
 | 
			
		||||
ak5lcy9FbjVlZlVmMFUKLS0tIG5ZMXZhMDYrMU1DOThYNEZxTnI1d0I0TXlNeDU3
 | 
			
		||||
ZkFoWnBVOEx1WjRmTncKZcV/oJCkeY+Tp4Xwdy5s+vuMpnhy0cndBUE4KrfkX7xd
 | 
			
		||||
NXTWQ1mQdy9W5MII8s1aFtxYoShZPsoNTikzZIAqxhTMHloUqKaAG0XKCKj1ZzcV
 | 
			
		||||
WMj8+IOnPD1y7uwETg7l0lw0u/L2bb37zrlvrf6JjA5b4iO79+wg9AvJigdbkNou
 | 
			
		||||
gfNFyZuxaIwM7FOakVWV8hKhKPYd1X0y3cUQCSb0/oiogHT+9KREXsL5Jt8hVoQ0
 | 
			
		||||
r0asxVOASXxVRkEDQDe9RHnEMEo3+UOBtAB0DVSeGOa4LEt8SEoCfas5vo+LqMZs
 | 
			
		||||
fDA=
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
							
								
								
									
										12
									
								
								secrets/jackflix/photoprism-pass.txt.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								secrets/jackflix/photoprism-pass.txt.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGhNYTRudyBGWFZS
 | 
			
		||||
Umg0Zm44TlY2djBaSUNuRGdRSTFob290aHJ2a0xnL2ZXSE9qUndNCnBJUVNUcEpF
 | 
			
		||||
M3F6UUYzanlENmM1Wm11WHllRzVyc1hEemtpT010ZjdKcFUKLT4gWDI1NTE5IHJV
 | 
			
		||||
KzdZUm5HUldPdlBHcFd1L2lEMy84ZVBqL1BoRUdlTjVMMjQ0U0dmMUUKeXFDejl5
 | 
			
		||||
TW5sVkJoQzFZb0R5MStoOFJKbUluN3gvTXBmd2E0MmR1ZHgxTQotPiB9SC1ncmVh
 | 
			
		||||
c2UgbyBKbWN2WE1kCjdESDIwMkN4NXpxU3A1cnJLamRoUUpSN2x6U2VPaEhNODdn
 | 
			
		||||
c05uSHBOQ0Q0a2FpY2RQc1hvUFVMZlJqdm53WjAKRGlvN1JjUnd2RWp2ZzN0Z3pv
 | 
			
		||||
RVozT1lueWZhck40T1VMMkd5TjZOclFhamU5NjgKLS0tIFcvemlDZ1B5d1h4cHJI
 | 
			
		||||
ejNuRFRERk5vU1BKbzZkUEtKSlk3K2NxTzFUQ1EK8tR8pcagaUMue5Rjz2BLNbU4
 | 
			
		||||
8SL2h7FsScBnIHka3122jwjgxviwH7T0YfgHpZCf+yLwVg==
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
							
								
								
									
										12
									
								
								secrets/object/wastebin.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								secrets/object/wastebin.env.age
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,12 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGhrYnR2ZyBmbDlE
 | 
			
		||||
Ylh6RVBabVdnMnoxRnR5U0RZS09iMUk3TEl5Ry9vbGNFQ1F4V2tNCjRyWTZUOVhp
 | 
			
		||||
L2NBUzJ0OXlsU2F1VGMvK2Z2d2k4N2VaSExOTDVjKzdPODQKLT4gWDI1NTE5IEkr
 | 
			
		||||
ckZzSi9DaWRDYXgyUVNBejErdHhnME5aeWc2QjA4RFQrZjIvM2JhZ2sKZWRkUE9U
 | 
			
		||||
a3g5M1lMY3FCbVRzbFRBVzVKRmM3TFQ4RGYyK0M4K0lETFhuYwotPiA/TTJyQi1n
 | 
			
		||||
cmVhc2UgdTNFPyMgQGVffGEKQmViTERtRXpSSStDVlY0YXV6dwotLS0gYkdDVzFP
 | 
			
		||||
NnhmbnFaWVpKTDMza09qQzd3MnB5NkZGQi8vZ2Mxd29sM2Z4UQr6g8tdM6ChbRgt
 | 
			
		||||
g+2KGxwrUaicgMiVNbXJjbRRYq/3Ml/ZUSwiyu/+jUOlrpCxpasrADwifILD3M/c
 | 
			
		||||
sWW4dzVVR80t7k9FSDwy+EF/XvCxCRbLrqEbKNttfpig+9PRpB8R+so7YyYMhbc0
 | 
			
		||||
84nzB7gvJUlnKDVS
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
		Reference in New Issue
	
	Block a user