Compare commits
	
		
			95 Commits
		
	
	
		
			fastback-s
			...
			e5d5847b89
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| e5d5847b89 | |||
| 9e7294e871 | |||
| 69216c6b4c | |||
| 1ea172e690 | |||
| b7be45715e | |||
| 3522a7078b | |||
| b44f0e74e8 | |||
| 7c57f00b27 | |||
| c9d36ec65b | |||
| d8f97b9316 | |||
| d5bb2f6787 | |||
| ced82fc002 | |||
| 3535d2fd90 | |||
| 4e207c3397 | |||
| bc4e75a6a5 | |||
| 2ae922f3e8 | |||
| f263fdca3e | |||
| 1232e9cb30 | |||
| fbb29162ca | |||
| 7ab57a12b7 | |||
| 4e947d4b1e | |||
| b68e82ae03 | |||
| 91489551b9 | |||
| 86c99c2cbb | |||
| 7e2dfc21c6 | |||
| 9ac63220d5 | |||
| ffa5d19854 | |||
| 19fb29213e | |||
| f9870abc9e | |||
| 84ca556c47 | |||
| 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 | 
| @@ -10,7 +10,7 @@ jobs: | ||||
|     runs-on: ubuntu-22.04 | ||||
|     steps: | ||||
|       - uses: actions/checkout@v4 | ||||
|       - uses: cachix/install-nix-action@v23 | ||||
|       - uses: cachix/install-nix-action@v27 | ||||
|         with: | ||||
|           # Gitea will supply a token in GITHUB_TOKEN, which this action will | ||||
|           # try to pass to Nix when downloading from GitHub | ||||
| @@ -18,13 +18,11 @@ jobs: | ||||
|           extra_nix_config: | | ||||
|             # Make sure we're using sandbox | ||||
|             sandbox-fallback = false | ||||
|             # Big C++ projects fill up memory... | ||||
|             cores = 6 | ||||
|  | ||||
|             extra-substituters = https://nix-cache.nul.ie/main | ||||
|             extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8= | ||||
|       - name: Set up attic | ||||
|         run: | | ||||
|           nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \ | ||||
|             login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}" | ||||
|             extra-substituters = https://nix-cache.nul.ie | ||||
|             extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= | ||||
|  | ||||
|       - name: Check flake | ||||
|         run: nix flake check | ||||
| @@ -33,7 +31,9 @@ jobs: | ||||
|         run: | | ||||
|           path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out) | ||||
|           echo "path=$path" >> "$GITHUB_OUTPUT" | ||||
|  | ||||
|       - name: Push to cache | ||||
|         env: | ||||
|           HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }} | ||||
|         run: | | ||||
|           nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \ | ||||
|             push main ${{ steps.build.outputs.path }} | ||||
|           ci/push-to-cache.sh "${{ steps.build.outputs.path }}" | ||||
|   | ||||
| @@ -14,21 +14,15 @@ jobs: | ||||
|         uses: https://github.com/actions/setup-go@v4 | ||||
|         with: | ||||
|           go-version: '>=1.20.1' | ||||
|       - uses: cachix/install-nix-action@v23 | ||||
|       - uses: cachix/install-nix-action@v27 | ||||
|         with: | ||||
|           github_access_token: ${{ secrets.GH_PULL_TOKEN }} | ||||
|           extra_nix_config: | | ||||
|             # Make sure we're using sandbox | ||||
|             sandbox-fallback = false | ||||
|  | ||||
|             extra-substituters = https://nix-cache.nul.ie/main | ||||
|             extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8= | ||||
|       - name: Set up attic | ||||
|         id: setup | ||||
|         run: | | ||||
|           nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \ | ||||
|             login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}" | ||||
|           echo "short_rev=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" | ||||
|             extra-substituters = https://nix-cache.nul.ie | ||||
|             extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= | ||||
|  | ||||
|       - name: Build installer ISO | ||||
|         run: | | ||||
| @@ -39,12 +33,13 @@ jobs: | ||||
|         run: | | ||||
|           nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive | ||||
|           ln -s "$(readlink result)" \ | ||||
|             jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar | ||||
|             jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst | ||||
|  | ||||
|       - name: Create release | ||||
|         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 | ||||
|             jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst | ||||
|   | ||||
							
								
								
									
										1
									
								
								.keys/harmonia.pub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.keys/harmonia.pub
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXRXkYnBf2opIjN+bXE7HmhUpa4hyXJUGmBT+MRccT4 harmonia | ||||
							
								
								
									
										1
									
								
								ci/known_hosts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ci/known_hosts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1 @@ | ||||
| object-ctr.ams1.int.nul.ie ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdHbZErWLmTPO/aEWB1Fup/aGMf31Un5Wk66FJwTz/8 | ||||
							
								
								
									
										29
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,29 @@ | ||||
| #!/bin/sh | ||||
| set -e | ||||
|  | ||||
| REMOTE_STORE=/var/lib/harmonia | ||||
| SSH_HOST="harmonia@object-ctr.ams1.int.nul.ie" | ||||
| SSH_KEY=/tmp/harmonia.key | ||||
| STORE_URI="ssh-ng://$SSH_HOST?ssh-key=$SSH_KEY&remote-store=$REMOTE_STORE" | ||||
|  | ||||
| remote_cmd() { | ||||
|   ssh -i "$SSH_KEY" "$SSH_HOST" env HOME=/run/harmonia NIX_REMOTE="$REMOTE_STORE" "$@" | ||||
| } | ||||
|  | ||||
| umask_old=$(umask) | ||||
| umask 0066 | ||||
| echo "$HARMONIA_SSH_KEY" | base64 -d > "$SSH_KEY" | ||||
| umask $umask_old | ||||
|  | ||||
| mkdir -p ~/.ssh | ||||
| cp ci/known_hosts ~/.ssh/ | ||||
| path="$1" | ||||
|  | ||||
| echo "Pushing $path to cache..." | ||||
| nix copy --no-check-sigs --to "$STORE_URI" "$path" | ||||
|  | ||||
| echo "Updating profile..." | ||||
| remote_cmd nix-env -p "$REMOTE_STORE"/nix/var/nix/profiles/nixfiles --set "$path" | ||||
|  | ||||
| echo "Collecting garbage..." | ||||
| remote_cmd nix-collect-garbage --delete-older-than 30d | ||||
| @@ -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"; | ||||
|   | ||||
| @@ -28,6 +28,5 @@ in | ||||
|       exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@" | ||||
|     '') | ||||
|     home-manager | ||||
|     attic-client | ||||
|   ]; | ||||
| } | ||||
|   | ||||
							
								
								
									
										524
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										524
									
								
								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": 1720542474, | ||||
|         "narHash": "sha256-aKjJ/4l2I9+wNGTaOGRsuS3M1+IoTibqgEMPDikXm04=", | ||||
|         "owner": "zhaofengli", | ||||
|         "repo": "attic", | ||||
|         "rev": "bdafd64910bb2b861cf90fa15f1fc93318b6fbf6", | ||||
|         "rev": "6139576a3ce6bb992e0f6c3022528ec233e45f00", | ||||
|         "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": { | ||||
| @@ -101,11 +103,11 @@ | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1702918879, | ||||
|         "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", | ||||
|         "lastModified": 1717025063, | ||||
|         "narHash": "sha256-dIubLa56W9sNNz0e8jGxrX3CAkPXsq7snuFA/Ie6dn8=", | ||||
|         "owner": "ipetkov", | ||||
|         "repo": "crane", | ||||
|         "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", | ||||
|         "rev": "480dff0be03dac0e51a8dfc26e882b0d123a450e", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -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": 1718194053, | ||||
|         "narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=", | ||||
|         "owner": "serokell", | ||||
|         "repo": "deploy-rs", | ||||
|         "rev": "b709d63debafce9f5645a5ba550c9e0983b3d1f7", | ||||
|         "rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a", | ||||
|         "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": 1719827415, | ||||
|         "narHash": "sha256-pvh+1hStXXAZf0sZ1xIJbWGx4u+OGBC1rVx6Wsw0fBw=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224", | ||||
|         "rev": "f2e3c19867262dbe84fdfab42467fc8dd83a2005", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -485,11 +560,11 @@ | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1703754036, | ||||
|         "narHash": "sha256-JpJdcj9Tg4lMuYikXDpajA8wOp+rHyn9RD2rKBEM4cQ=", | ||||
|         "lastModified": 1720734513, | ||||
|         "narHash": "sha256-neWQ8eNtLTd+YMesb7WjKl1SVCbDyCm46LUgP/g/hdo=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "c24c298562fe41b39909f632c5a7151bbf6b4628", | ||||
|         "rev": "90ae324e2c56af10f20549ab72014804a3064c7f", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -499,11 +574,11 @@ | ||||
|     }, | ||||
|     "impermanence": { | ||||
|       "locked": { | ||||
|         "lastModified": 1703656108, | ||||
|         "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=", | ||||
|         "lastModified": 1719091691, | ||||
|         "narHash": "sha256-AxaLX5cBEcGtE02PeGsfscSb/fWMnyS7zMWBXQWDKbE=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "impermanence", | ||||
|         "rev": "033643a45a4a920660ef91caa391fbffb14da466", | ||||
|         "rev": "23c1f06316b67cb5dabdfe2973da3785cfe9c34a", | ||||
|         "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": 1721079763, | ||||
|         "narHash": "sha256-mlzukvwgiBm9Q8BedrZagnTcsDTXYKaFCf38KiSrsMc=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "e80160eb2ac3a7111d07cc43a15c16b9edca01ea", | ||||
|         "rev": "b4cd56e5afee2cec3e1feca912680539cbb51403", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -567,11 +664,11 @@ | ||||
|     }, | ||||
|     "nixpkgs-mine-stable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1703756491, | ||||
|         "narHash": "sha256-9VL34e0gzomwqRnryRn23V2ImYcaZIQdp7CsWg5TmlE=", | ||||
|         "lastModified": 1720987393, | ||||
|         "narHash": "sha256-aq1reu43552gD+QRyxAMlimAX9+YbGpAIyw82jg0eWY=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "36611f5f7cfd401f51ad4ca76fd6ee85a714bb74", | ||||
|         "rev": "154ab603fb2b794b437f233853aeb3c75f101049", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -583,11 +680,11 @@ | ||||
|     }, | ||||
|     "nixpkgs-stable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1703467016, | ||||
|         "narHash": "sha256-/5A/dNPhbQx/Oa2d+Get174eNI3LERQ7u6WTWOlR1eQ=", | ||||
|         "lastModified": 1720535198, | ||||
|         "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "d02d818f22c777aa4e854efc3242ec451e5d462a", | ||||
|         "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -598,11 +695,11 @@ | ||||
|     }, | ||||
|     "nixpkgs-unstable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1703438236, | ||||
|         "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=", | ||||
|         "lastModified": 1720768451, | ||||
|         "narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b", | ||||
|         "rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9", | ||||
|         "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": 1718869541, | ||||
|         "narHash": "sha256-smhpGh1x/8mNl+sFL8SbeWnx0bK4HWjmdRA3mIwGjPU=", | ||||
|         "owner": "yaxitech", | ||||
|         "repo": "ragenix", | ||||
|         "rev": "281f68c3d477904f79ff1cd5807a8c226cd80a50", | ||||
|         "rev": "8a254bbaa93fbd38e16f70fa81af6782794e046e", | ||||
|         "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,19 +863,40 @@ | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "sharry": { | ||||
|     "sbt": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_10", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ] | ||||
|         "flake-utils": "flake-utils_13", | ||||
|         "nixpkgs": "nixpkgs_5" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1687587666, | ||||
|         "narHash": "sha256-t1VNvdQdDUFTEKTFP2fc7Fb3buQBmP+h9WUeO8b2Bus=", | ||||
|         "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": { | ||||
|         "devshell-tools": "devshell-tools", | ||||
|         "flake-utils": "flake-utils_12", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "sbt": "sbt" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1720592125, | ||||
|         "narHash": "sha256-vR89LefkY8mBPWxDTQ8SNg6Z7/J6Yga80T4kSb6MNdk=", | ||||
|         "owner": "eikek", | ||||
|         "repo": "sharry", | ||||
|         "rev": "a9b3371aa6c7b92088b20fd6e479c251a5556b86", | ||||
|         "rev": "604b20517150599cb05dbe178cd35cd10659aa4c", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -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,7 +24,7 @@ | ||||
|  | ||||
|     # 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"; | ||||
| @@ -115,9 +115,9 @@ | ||||
|         nixos/installer.nix | ||||
|         nixos/boxes/colony | ||||
|         nixos/boxes/tower | ||||
|         nixos/boxes/castle | ||||
|         nixos/boxes/home/stream.nix | ||||
|         nixos/boxes/home/palace | ||||
|         nixos/boxes/home/castle | ||||
|         nixos/boxes/britway | ||||
|         nixos/boxes/kelder | ||||
|  | ||||
|   | ||||
| @@ -199,17 +199,20 @@ in | ||||
|           file | ||||
|           tree | ||||
|           pwgen | ||||
|  | ||||
|           minicom | ||||
|           iperf3 | ||||
|           mosh | ||||
|           wget | ||||
|           hyx | ||||
|           whois | ||||
|           ldns | ||||
|           minicom | ||||
|           mtr | ||||
|  | ||||
|           hyx | ||||
|           ncdu | ||||
|           jq | ||||
|           yq-go | ||||
|           nix-tree | ||||
|         ]; | ||||
|  | ||||
|         sessionVariables = { | ||||
|   | ||||
							
								
								
									
										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"; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
| @@ -59,12 +92,31 @@ in | ||||
|             enable = true; | ||||
|             inherit font; | ||||
|             settings = { | ||||
|               background_opacity = "0.8"; | ||||
|               background_opacity = "0.65"; | ||||
|               tab_bar_edge = "top"; | ||||
|               shell_integration = "no-sudo"; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           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 = { | ||||
| @@ -126,10 +178,11 @@ in | ||||
|           ]; | ||||
|  | ||||
|           pointerCursor = { | ||||
|             package = pkgs.vanilla-dmz; | ||||
|             name = "Vanilla-DMZ"; | ||||
|             size = 16; | ||||
|             package = pkgs.posy-cursors; | ||||
|             name = "Posy_Cursor"; | ||||
|             size = 32; | ||||
|             gtk.enable = true; | ||||
|             x11.enable = true; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
| @@ -162,7 +215,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 +263,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 +343,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() | ||||
										
											Binary file not shown.
										
									
								
							| Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 251 KiB | 
| @@ -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 { | ||||
| @@ -94,10 +98,10 @@ rec { | ||||
|   nix = { | ||||
|     cache = rec { | ||||
|       substituters = [ | ||||
|         "https://nix-cache.${pubDomain}/main" | ||||
|         "https://nix-cache.${pubDomain}" | ||||
|       ]; | ||||
|       keys = [ | ||||
|         "main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=" | ||||
|         "nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=" | ||||
|       ]; | ||||
|       conf = '' | ||||
|         extra-substituters = ${concatStringsSep " " substituters} | ||||
| @@ -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" | ||||
|       "80.111.122.16" | ||||
|       "109.255.252.63" | ||||
|     ]; | ||||
|  | ||||
| @@ -277,6 +293,8 @@ rec { | ||||
|         v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     roceBootModules = [ "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" ]; | ||||
|   }; | ||||
|  | ||||
|   britway = { | ||||
| @@ -327,6 +345,7 @@ rec { | ||||
|     }; | ||||
|  | ||||
|     domain = "hentai.engineer"; | ||||
|     ipv4MTU = 1460; | ||||
|     vpn = { | ||||
|       port = 51820; | ||||
|     }; | ||||
| @@ -340,6 +359,7 @@ rec { | ||||
|     deploy = ../.keys/deploy.pub; | ||||
|     rsyncNet = ../.keys/zh2855.rsync.net.pub; | ||||
|     mailcowAcme = ../.keys/mailcow-acme.pub; | ||||
|     harmonia = ../.keys/harmonia.pub; | ||||
|   }; | ||||
|   sshHostKeys = { | ||||
|     mail-vm = ../.keys/mail-vm-host.pub; | ||||
|   | ||||
| @@ -5,7 +5,7 @@ let | ||||
|     genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types | ||||
|     mkOption mkOverride mkForce mkIf mergeEqualOption optional | ||||
|     showWarnings concatStringsSep flatten unique optionalAttrs | ||||
|     mkBefore; | ||||
|     mkBefore toLower; | ||||
|   inherit (lib.flake) defaultSystems; | ||||
| in | ||||
| rec { | ||||
| @@ -248,10 +248,37 @@ rec { | ||||
|   in | ||||
|   { | ||||
|     trivial = prev.trivial // { | ||||
|       release = "23.12:u-${prev.trivial.release}"; | ||||
|       codeName = "Amogus"; | ||||
|       release = "24.07:u-${prev.trivial.release}"; | ||||
|       codeName = "Diffed"; | ||||
|       revisionWithDefault = default: self.rev or default; | ||||
|       versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}"; | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   netbootKeaClientClasses = { tftpIP, hostname, systems }: | ||||
|   let | ||||
|     testIPXE = "substring(option[user-class].hex, 0, 4) == 'iPXE'"; | ||||
|   in | ||||
|     (mapAttrsToList (name: mac: { | ||||
|       name = "nixos-${name}"; | ||||
|       test = "(${testIPXE}) and (hexstring(pkt4.mac, ':') == '${toLower mac}')"; | ||||
|       next-server = tftpIP; | ||||
|       server-hostname = hostname; | ||||
|       boot-file-name = "http://${hostname}/systems/${name}/menu.ipxe"; | ||||
|     }) systems) ++ [ | ||||
|     { | ||||
|       name = "ipxe"; | ||||
|       test = testIPXE; | ||||
|       next-server = tftpIP; | ||||
|       server-hostname = hostname; | ||||
|       boot-file-name = "http://${hostname}/boot.ipxe"; | ||||
|     } | ||||
|     { | ||||
|       name = "efi-x86_64"; | ||||
|       test = "option[client-system].hex == 0x0007"; | ||||
|       next-server = tftpIP; | ||||
|       server-hostname = hostname; | ||||
|       boot-file-name = "ipxe-x86_64.efi"; | ||||
|     } | ||||
|   ]; | ||||
| } | ||||
|   | ||||
| @@ -5,18 +5,20 @@ let | ||||
|   inherit (lib.my.c.britway) prefixes domain; | ||||
|  | ||||
|   # Can't use overrideAttrs because we need to override `vendorHash` within `buildGoModule` | ||||
|   headscale = pkgs.headscale.override { | ||||
|   headscale = (pkgs.headscale.override { | ||||
|     buildGoModule = args: pkgs.buildGoModule (args // rec { | ||||
|       version = "0.23.0-alpha2"; | ||||
|       version = "0.23.0-alpha12"; | ||||
|       src = pkgs.fetchFromGitHub { | ||||
|         owner = "juanfont"; | ||||
|         repo = "headscale"; | ||||
|         rev = "v${version}"; | ||||
|         hash = "sha256-sz+uQyyq/5YYDe5I44x5x2nvd48swAhNlInB8KZYvDo="; | ||||
|         hash = "sha256-kZZK0cXnFARxblSMz01TDcBbTorkHGAwGpR+a4/mYfU="; | ||||
|       }; | ||||
|       vendorHash = "sha256-u9AmJguQ5dnJpfhOeLN43apvMHuraOrJhvlEIp9RoIc="; | ||||
|       patches = []; | ||||
|       vendorHash = "sha256-EorT2AVwA3usly/LcNor6r5UIhLCdj3L4O4ilgTIC2o="; | ||||
|       doCheck = false; | ||||
|     }); | ||||
|   }); | ||||
|   }; | ||||
|  | ||||
|   advRoutes = concatStringsSep "," [ | ||||
|     lib.my.c.home.prefixes.all.v4 | ||||
| @@ -44,10 +46,12 @@ in | ||||
|           disable_check_updates = true; | ||||
|           unix_socket_permission = "0770"; | ||||
|           server_url = "https://ts.${pubDomain}"; | ||||
|           db_type = "sqlite3"; | ||||
|           db_path = "/var/lib/headscale/db.sqlite3"; | ||||
|           database = { | ||||
|             type = "sqlite3"; | ||||
|             sqlite.path = "/var/lib/headscale/db.sqlite3"; | ||||
|           }; | ||||
|           noise.private_key_path = "/var/lib/headscale/noise_private.key"; | ||||
|           ip_prefixes = with lib.my.c.tailscale.prefix; [ v4 v6 ]; | ||||
|           prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; }; | ||||
|           dns_config = { | ||||
|             # Use IPs that will route inside the VPN to prevent interception | ||||
|             # (e.g. DNS rebinding filtering) | ||||
|   | ||||
| @@ -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 = { | ||||
|   | ||||
| @@ -29,6 +29,9 @@ | ||||
|     }; | ||||
|   in | ||||
|   { | ||||
|     # Kernel Same-Page Merging to attempt memory usage reduction | ||||
|     hardware.ksm.enable = false; | ||||
|  | ||||
|     systemd = { | ||||
|       network = { | ||||
|         links = { | ||||
| @@ -130,7 +133,8 @@ | ||||
|  | ||||
|               (vm.lvmDisk "media") | ||||
|               (vm.lvmDisk "minio") | ||||
|               (vm.lvmDisk "nix-atticd") | ||||
|               (vm.lvmDisk "nix-cache") | ||||
|               (vm.lvmDisk "jam") | ||||
|             ]); | ||||
|           }; | ||||
|  | ||||
| @@ -209,6 +213,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@@ | ||||
|  | ||||
|   | ||||
| @@ -102,34 +102,6 @@ in | ||||
|  | ||||
|             services = { | ||||
|               fstrim = lib.my.c.colony.fstrimConfig; | ||||
|               # Hacks for Jsch (Minecraft FastBack) to work | ||||
|               openssh = { | ||||
|                 hostKeys = [ | ||||
|                   { | ||||
|                     bits = 4096; | ||||
|                     path = "/etc/ssh/ssh_host_rsa_key"; | ||||
|                     type = "rsa"; | ||||
|                   } | ||||
|                   { | ||||
|                     path = "/etc/ssh/ssh_host_ed25519_key"; | ||||
|                     type = "ed25519"; | ||||
|                   } | ||||
|  | ||||
|                   { | ||||
|                     type = "ecdsa-sha2-nistp256"; | ||||
|                     path = "/etc/ssh/ssh_host_ecdsa_key"; | ||||
|                   } | ||||
|                 ]; | ||||
|                 settings = { | ||||
|                   Macs = [ | ||||
|                     "hmac-sha2-512-etm@openssh.com" | ||||
|                     "hmac-sha2-256-etm@openssh.com" | ||||
|                     "umac-128-etm@openssh.com" | ||||
|  | ||||
|                     "hmac-sha2-256" | ||||
|                   ]; | ||||
|                 }; | ||||
|               }; | ||||
|               netdata.enable = true; | ||||
|               nginx = { | ||||
|                 enable = true; | ||||
|   | ||||
							
								
								
									
										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 = "infinity"; | ||||
|           MemoryMax = "4G"; | ||||
|         }; | ||||
|  | ||||
|         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,10 +192,13 @@ 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 = { | ||||
|             }; | ||||
|             matrix-sliding-sync = { | ||||
|               enable = true; | ||||
|               createDatabase = false; | ||||
|               environmentFile = config.age.secrets."chatterbox/syncv3.env".path; | ||||
| @@ -180,7 +207,6 @@ in | ||||
|                 SYNCV3_SERVER = "http://localhost:8008"; | ||||
|               }; | ||||
|             }; | ||||
|             }; | ||||
|  | ||||
|             heisenbridge = { | ||||
|               enable = true; | ||||
| @@ -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 { | ||||
|   | ||||
| @@ -239,6 +239,9 @@ in | ||||
|               ]; | ||||
|  | ||||
|               recommendedTlsSettings = true; | ||||
|               recommendedBrotliSettings = true; | ||||
|               # Uh so nginx is hanging with zstd enabled... maybe let's not for now | ||||
|               # recommendedZstdSettings = true; | ||||
|               clientMaxBodySize = "0"; | ||||
|               serverTokens = true; | ||||
|               resolver = { | ||||
|   | ||||
| @@ -145,7 +145,7 @@ in | ||||
|  | ||||
|       "pass.${pubDomain}" = | ||||
|       let | ||||
|         upstream = "http://vaultwarden-ctr.${domain}"; | ||||
|         upstream = "http://vaultwarden-ctr.${domain}:8080"; | ||||
|       in | ||||
|       { | ||||
|         locations = { | ||||
| @@ -206,7 +206,8 @@ in | ||||
|           # Currently it seems like single quotes aren't escaped like they should be... | ||||
|           conf = { | ||||
|             brand = "/dev/player0 Matrix"; | ||||
|             showLabsSettings = true; | ||||
|             show_labs_settings = true; | ||||
|             default_country_code = "IE"; | ||||
|             disable_guests = true; | ||||
|             default_server_config = { | ||||
|               "m.homeserver" = { | ||||
| @@ -214,9 +215,8 @@ in | ||||
|                 server_name = "nul.ie"; | ||||
|               }; | ||||
|             }; | ||||
|             roomDirectory.servers = [ | ||||
|             room_directory.servers = [ | ||||
|               "nul.ie" | ||||
|               "netsoc.ie" | ||||
|               "matrix.org" | ||||
|             ]; | ||||
|           }; | ||||
| @@ -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 = | ||||
| @@ -395,10 +407,13 @@ in | ||||
|         ignore_invalid_headers off; | ||||
|       ''; | ||||
|  | ||||
|       nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar\.\S+)$''; | ||||
|       nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar.*|serve\/.+)$''; | ||||
|       nixCacheHeaders = '' | ||||
|         add_header Cache-Control $nix_cache_control; | ||||
|         add_header Expires $nix_expires; | ||||
|  | ||||
|         brotli on; | ||||
|         brotli_types application/x-nix-archive; | ||||
|       ''; | ||||
|     in | ||||
|     { | ||||
| @@ -440,9 +455,11 @@ in | ||||
|  | ||||
|       "nix-cache.${pubDomain}" = { | ||||
|         locations = { | ||||
|           "/".proxyPass = "http://${host}:8069"; | ||||
|           "/" = { | ||||
|             proxyPass = "http://${host}:5000"; | ||||
|           }; | ||||
|           "~ ${nixCacheableRegex}" = { | ||||
|             proxyPass = "http://${host}:8069"; | ||||
|             proxyPass = "http://${host}:5000"; | ||||
|             extraConfig = nixCacheHeaders; | ||||
|           }; | ||||
|         }; | ||||
|   | ||||
| @@ -31,6 +31,13 @@ in | ||||
|     { | ||||
|       config = mkMerge [ | ||||
|         { | ||||
|           fileSystems = { | ||||
|             "/var/lib/harmonia" = { | ||||
|               device = "/mnt/nix-cache"; | ||||
|               options = [ "bind" ]; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           my = { | ||||
|             deploy.enable = false; | ||||
|             server.enable = true; | ||||
| @@ -48,7 +55,9 @@ in | ||||
|                   group = config.my.user.config.group; | ||||
|                 }; | ||||
|                 "object/atticd.env" = {}; | ||||
|                 "nix-cache.key" = {}; | ||||
|                 "object/hedgedoc.env" = {}; | ||||
|                 "object/wastebin.env" = {}; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
| @@ -57,7 +66,9 @@ in | ||||
|                 9000 9001 | ||||
|                 config.services.sharry.config.bind.port | ||||
|                 8069 | ||||
|                 5000 | ||||
|                 config.services.hedgedoc.settings.port | ||||
|                 8088 | ||||
|               ]; | ||||
|             }; | ||||
|  | ||||
| @@ -66,14 +77,26 @@ in | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           users = with lib.my.c.ids; let inherit (config.services.atticd) user group; in { | ||||
|           users = with lib.my.c.ids; mkMerge [ | ||||
|             (let inherit (config.services.atticd) user group; in { | ||||
|               users."${user}" = { | ||||
|                 isSystemUser = true; | ||||
|                 uid = uids.atticd; | ||||
|                 group = group; | ||||
|               }; | ||||
|               groups."${user}".gid = gids.atticd; | ||||
|             }) | ||||
|             { | ||||
|               users = { | ||||
|                 harmonia = { | ||||
|                   shell = pkgs.bashInteractive; | ||||
|                   openssh.authorizedKeys.keyFiles = [ | ||||
|                     lib.my.c.sshKeyFiles.harmonia | ||||
|                   ]; | ||||
|                 }; | ||||
|               }; | ||||
|             } | ||||
|           ]; | ||||
|  | ||||
|           systemd = { | ||||
|             network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal; | ||||
| @@ -91,7 +114,9 @@ in | ||||
|                   MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie"; | ||||
|                 }; | ||||
|               }; | ||||
|  | ||||
|               sharry = awaitPostgres; | ||||
|  | ||||
|               atticd = mkMerge [ | ||||
|                 awaitPostgres | ||||
|                 { | ||||
| @@ -102,6 +127,15 @@ in | ||||
|                   }; | ||||
|                 } | ||||
|               ]; | ||||
|               harmonia = { | ||||
|                 environment.NIX_REMOTE = "/var/lib/harmonia"; | ||||
|                 preStart = '' | ||||
|                   ${config.nix.package}/bin/nix store ping | ||||
|                 ''; | ||||
|                 serviceConfig = { | ||||
|                   StateDirectory = "harmonia"; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
| @@ -181,7 +215,7 @@ in | ||||
|             }; | ||||
|  | ||||
|             atticd = { | ||||
|               enable = true; | ||||
|               enable = false; | ||||
|               credentialsFile = config.age.secrets."object/atticd.env".path; | ||||
|               settings = { | ||||
|                 listen = "[::]:8069"; | ||||
| @@ -201,6 +235,14 @@ in | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             harmonia = { | ||||
|               enable = true; | ||||
|               signKeyPath = config.age.secrets."nix-cache.key".path; | ||||
|               settings = { | ||||
|                 priority = 30; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             hedgedoc = { | ||||
|               enable = true; | ||||
|               environmentFile = config.age.secrets."object/hedgedoc.env".path; | ||||
| @@ -220,6 +262,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 { | ||||
|   | ||||
| @@ -83,7 +83,7 @@ in | ||||
|                 DOMAIN = "https://pass.${lib.my.c.pubDomain}"; | ||||
|  | ||||
|                 ROCKET_ADDRESS = "::"; | ||||
|                 ROCKET_PORT = 80; | ||||
|                 ROCKET_PORT = 8080; | ||||
|  | ||||
|                 SMTP_HOST = "mail.nul.ie"; | ||||
|                 SMTP_FROM = "pass@nul.ie"; | ||||
|   | ||||
| @@ -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 [ | ||||
|           { | ||||
| @@ -90,8 +94,8 @@ in | ||||
|                 device = "/dev/disk/by-label/minio"; | ||||
|                 fsType = "xfs"; | ||||
|               }; | ||||
|               "/mnt/atticd" = { | ||||
|                 device = "/dev/disk/by-label/atticd"; | ||||
|               "/mnt/nix-cache" = { | ||||
|                 device = "/dev/disk/by-label/nix-cache"; | ||||
|                 fsType = "ext4"; | ||||
|               }; | ||||
|             }; | ||||
| @@ -202,7 +206,7 @@ in | ||||
|                   object = { | ||||
|                     bindMounts = { | ||||
|                       "/mnt/minio".readOnly = false; | ||||
|                       "/mnt/atticd".readOnly = false; | ||||
|                       "/mnt/nix-cache".readOnly = false; | ||||
|                     }; | ||||
|                   }; | ||||
|                   toot = {}; | ||||
|   | ||||
| @@ -108,46 +108,31 @@ 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 = [ | ||||
|                     { | ||||
|                       type = "bridge"; | ||||
|                       bridge = "oci"; | ||||
|                       isGateway = true; | ||||
|                       ipMasq = false; | ||||
|                       hairpinMode = true; | ||||
|                       ipam = { | ||||
|                         type = "host-local"; | ||||
|                         routes = [ | ||||
|                           { dst = "0.0.0.0/0"; } | ||||
|                           { dst = "::/0"; } | ||||
|                         ]; | ||||
|                         ranges = [ | ||||
|                           [ | ||||
|                   id = "0000000000000000000000000000000000000000000000000000000000000001"; | ||||
|                   driver = "bridge"; | ||||
|                   network_interface = "oci"; | ||||
|                   ipv6_enabled = true; | ||||
|                   internal = false; | ||||
|                   dns_enabled = false; | ||||
|                   subnets = [ | ||||
|                     { | ||||
|                       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; | ||||
|                     } | ||||
|                   ]; | ||||
|                 }; | ||||
|               }; | ||||
|   | ||||
| @@ -25,22 +25,20 @@ let | ||||
|       	email = "simpcraft@nul.ie" | ||||
|       	name = "Simpcraft bot" | ||||
|     ''; | ||||
|     knownHosts = pkgs.writeText "known_hosts" '' | ||||
|       git.nul.ie ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD023ECzYmLeXIpcGVaciPjq6UN/Sjmsys5HP/Nei5GkrUZqPa3OJ2uSXKLUSKGYdeNhxaFTPJe8Yx3TsZxMme8= | ||||
|     ''; | ||||
|   }; | ||||
| 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"; | ||||
|  | ||||
| @@ -52,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 = [ | ||||
| @@ -68,53 +68,77 @@ 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"}'' | ||||
|       #   ]; | ||||
|       # }; | ||||
|     }; | ||||
|         environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ]; | ||||
|  | ||||
|         volumes = [ | ||||
|           "minecraft_staging_data:/data" | ||||
|           "${./icon.png}:/ext/icon.png:ro" | ||||
|           "${fastback.gitConfig}:/data/.config/git/config:ro" | ||||
|           "${fastback.knownHosts}:/data/.ssh/known_hosts:ro" | ||||
|           "${config.age.secrets."whale2/simpcraft-git.key".path}:/data/.ssh/id_rsa" | ||||
|         ]; | ||||
|     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; | ||||
|         }; | ||||
|  | ||||
|         extraOptions = [ | ||||
|           ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}'' | ||||
|         ]; | ||||
|         # Avoid Minecraft poking the files while we back up | ||||
|         preHook = rconCommand "save-off"; | ||||
|         postHook = rconCommand "save-on"; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     systemd = { | ||||
|       services = { | ||||
|         borgbackup-job-simpcraft.serviceConfig.EnvironmentFile = [ config.age.secrets."whale2/simpcraft.env".path ]; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     my = { | ||||
|       secrets.files = { | ||||
|         "whale2/simpcraft.env" = {}; | ||||
|         "whale2/simpcraft-git.key" = { | ||||
|           owner = "1000"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
|   | ||||
| @@ -1,7 +1,8 @@ | ||||
| { lib, ... }: | ||||
| let | ||||
|   inherit (lib.my) net; | ||||
|   inherit (lib.my.c.home) domain vlans prefixes; | ||||
|   inherit (lib.my.c) networkd; | ||||
|   inherit (lib.my.c.home) domain vlans prefixes vips roceBootModules; | ||||
| in | ||||
| { | ||||
|   nixos.systems.castle = { | ||||
| @@ -15,7 +16,7 @@ in | ||||
|         ipv4 = { | ||||
|           address = net.cidr.host 40 prefixes.hi.v4; | ||||
|           mask = 22; | ||||
|           gateway = null; | ||||
|           gateway = vips.hi.v4; | ||||
|         }; | ||||
|         ipv6 = { | ||||
|           iid = "::3:1"; | ||||
| @@ -47,7 +48,7 @@ in | ||||
|             timeout = 10; | ||||
|           }; | ||||
|           kernelPackages = lib.my.c.kernel.latest pkgs; | ||||
|           kernelModules = [ "kvm-amd" ]; | ||||
|           kernelModules = [ "kvm-amd" "dm-snapshot" ]; | ||||
|           kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ]; | ||||
|           kernelPatches = [ | ||||
|             # { | ||||
| @@ -57,27 +58,38 @@ in | ||||
|             # } | ||||
|           ]; | ||||
|           initrd = { | ||||
|             availableKernelModules = [ "thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" ]; | ||||
|             availableKernelModules = [ | ||||
|               "thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" | ||||
|               "8021q" | ||||
|             ] ++ roceBootModules; | ||||
|             systemd.network = { | ||||
|               netdevs = mkVLAN "lan-hi" vlans.hi; | ||||
|               networks = { | ||||
|                 "10-et100g" = { | ||||
|                   matchConfig.Name = "et100g"; | ||||
|                   vlan = [ "lan-hi" ]; | ||||
|                   linkConfig.RequiredForOnline = "no"; | ||||
|                   networkConfig = networkd.noL3; | ||||
|                 }; | ||||
|                 "20-lan-hi" = networkdAssignment "lan-hi" assignments.hi; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         fileSystems = { | ||||
|           "/boot" = { | ||||
|             device = "/dev/disk/by-partuuid/8ce4248a-3ee4-f44f-801f-064a628b4d6e"; | ||||
|             fsType = "vfat"; | ||||
|           }; | ||||
|           "/nix" = { | ||||
|             device = "/dev/disk/by-partuuid/2da23a1d-2daf-d943-b91e-fc175f3dad07"; | ||||
|             device = "/dev/nvmeof/nix"; | ||||
|             fsType = "ext4"; | ||||
|           }; | ||||
| 
 | ||||
|           "/persist" = { | ||||
|             device = "/dev/disk/by-partuuid/f4c80d4f-a022-e941-b5d1-fe2e65e444b9"; | ||||
|             device = "/dev/nvmeof/persist"; | ||||
|             fsType = "ext4"; | ||||
|             neededForBoot = true; | ||||
|           }; | ||||
| 
 | ||||
|           "/home" = { | ||||
|             device = "/dev/disk/by-partuuid/992a93cf-6c9c-324b-b0ce-f8eb2d1ce10d"; | ||||
|             device = "/dev/nvmeof/home"; | ||||
|             fsType = "ext4"; | ||||
|           }; | ||||
|         }; | ||||
| @@ -101,6 +113,12 @@ in | ||||
|             dnssec = "false"; | ||||
|           }; | ||||
| 
 | ||||
|           pipewire.extraConfig.pipewire = { | ||||
|             "10-buffer"."context.properties" = { | ||||
|               "default.clock.quantum" = 128; | ||||
|               "default.clock.max-quantum" = 128; | ||||
|             }; | ||||
|           }; | ||||
|           blueman.enable = true; | ||||
|         }; | ||||
| 
 | ||||
| @@ -114,7 +132,7 @@ in | ||||
|         virtualisation.libvirtd.enable = true; | ||||
| 
 | ||||
|         networking = { | ||||
|           domain = "h.${lib.my.c.pubDomain}"; | ||||
|           inherit domain; | ||||
|           firewall.enable = false; | ||||
|         }; | ||||
| 
 | ||||
| @@ -131,14 +149,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; | ||||
| @@ -146,7 +156,6 @@ in | ||||
| 
 | ||||
|         systemd = { | ||||
|           network = { | ||||
|             wait-online.enable = false; | ||||
|             netdevs = mkMerge [ | ||||
|               (mkVLAN "lan-hi" vlans.hi) | ||||
|             ]; | ||||
| @@ -163,29 +172,20 @@ in | ||||
|                 matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a"; | ||||
|                 linkConfig = { | ||||
|                   Name = "et100g"; | ||||
|                   MTUBytes = "9000"; | ||||
|                   MTUBytes = toString lib.my.c.home.hiMTU; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|             networks = { | ||||
|               "50-lan" = { | ||||
|                 matchConfig.Name = "et2.5g"; | ||||
|                 DHCP = "no"; | ||||
|                 address = [ "10.16.7.1/16" ]; | ||||
|               }; | ||||
| 
 | ||||
|               "50-et100g" = { | ||||
|               "30-et100g" = { | ||||
|                 matchConfig.Name = "et100g"; | ||||
|                 vlan = [ "lan-hi" ]; | ||||
|                 networkConfig.IPv6AcceptRA = false; | ||||
|               }; | ||||
|               "60-lan-hi" = mkMerge [ | ||||
|               "40-lan-hi" = mkMerge [ | ||||
|                 (networkdAssignment "lan-hi" assignments.hi) | ||||
|                 { | ||||
|                   DHCP = "yes"; | ||||
|                   matchConfig.Name = "lan-hi"; | ||||
|                   linkConfig.MTUBytes = "9000"; | ||||
|                 } | ||||
|                 # So we don't drop the IP we use to connect to NVMe-oF! | ||||
|                 { networkConfig.KeepConfiguration = "static"; } | ||||
|               ]; | ||||
|             }; | ||||
|           }; | ||||
| @@ -205,10 +205,7 @@ in | ||||
|                 packages = with pkgs; [ | ||||
|                   jacktrip | ||||
|                   qpwgraph | ||||
|                   # TODO: seems to be borked (infinite recursion???) | ||||
|                   # (writeShellScriptBin "boardie" '' | ||||
|                   #   exec pw-jack ${boardie}/bin/boardie "$@" | ||||
|                   # '') | ||||
|                   boardie | ||||
|                 ]; | ||||
|               }; | ||||
| 
 | ||||
| @@ -222,6 +219,7 @@ in | ||||
|                     HDMI-A-1 = { | ||||
|                       transform = "270"; | ||||
|                       position = "0 0"; | ||||
|                       bg = "${./his-team-player.jpg} fill"; | ||||
|                     }; | ||||
|                     DP-1 = { | ||||
|                       mode = "2560x1440@170Hz"; | ||||
| @@ -243,11 +241,19 @@ in | ||||
|           }; | ||||
| 
 | ||||
|           #deploy.generate.system.mode = "boot"; | ||||
|           deploy.node.hostname = "castle.box.${config.networking.domain}"; | ||||
|           secrets = { | ||||
|             key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlVuTzKObeaUuPocCF41IO/8X+443lzUJLuCIclt2vr"; | ||||
|           }; | ||||
|           nvme.uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b"; | ||||
|           netboot.client = { | ||||
|             enable = true; | ||||
|           }; | ||||
|           nvme = { | ||||
|             uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b"; | ||||
|             boot = { | ||||
|               nqn = "nqn.2016-06.io.spdk:castle"; | ||||
|               address = "192.168.68.80"; | ||||
|             }; | ||||
|           }; | ||||
| 
 | ||||
|           firewall = { | ||||
|             enable = false; | ||||
							
								
								
									
										
											BIN
										
									
								
								nixos/boxes/home/castle/his-team-player.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								nixos/boxes/home/castle/his-team-player.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| After Width: | Height: | Size: 4.2 MiB | 
| @@ -94,7 +94,7 @@ in | ||||
|             extraOptions = [ "-A /var/log/smartd/" "--interval=600" ]; | ||||
|           }; | ||||
|           udev.extraRules = '' | ||||
|             ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="3" | ||||
|             ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="4" | ||||
|           ''; | ||||
|         }; | ||||
|  | ||||
| @@ -188,6 +188,13 @@ in | ||||
|                   VLANId=${toString vlans.hi} | ||||
|                   LinkState=yes | ||||
|                   MACAddress=52:54:00:ac:15:a9 | ||||
|  | ||||
|                   # sfh bridge | ||||
|                   [SR-IOV] | ||||
|                   VirtualFunction=3 | ||||
|                   VLANId=${toString vlans.hi} | ||||
|                   LinkState=yes | ||||
|                   MACAddress=52:54:00:90:34:95 | ||||
|                 ''; | ||||
|               }; | ||||
|               "60-lan-hi" = networkdAssignment "lan-hi" assignments.hi; | ||||
|   | ||||
| @@ -66,6 +66,7 @@ in | ||||
|             ]; | ||||
|  | ||||
|             services = { | ||||
|               fstrim.enable = true; | ||||
|               netdata.enable = true; | ||||
|             }; | ||||
|  | ||||
|   | ||||
| @@ -129,6 +129,12 @@ in | ||||
|             hostnqn = | ||||
|               "nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b"; | ||||
|             serial = "SPDK00000000000002"; | ||||
|           }) ++ (nvmfBdev { | ||||
|             bdev = "NVMeRaidp3"; | ||||
|             nqn = "nqn.2016-06.io.spdk:sfh"; | ||||
|             hostnqn = | ||||
|               "nqn.2014-08.org.nvmexpress:uuid:85d7df36-0de0-431b-b06e-51f7c0a455b4"; | ||||
|             serial = "SPDK00000000000003"; | ||||
|           }); | ||||
|         }; | ||||
|       }; | ||||
|   | ||||
| @@ -2,6 +2,7 @@ | ||||
|   imports = [ | ||||
|     ./cellar | ||||
|     ./river.nix | ||||
|     ./sfh | ||||
|   ]; | ||||
|  | ||||
|   nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }: | ||||
| @@ -57,11 +58,11 @@ | ||||
|  | ||||
|     systemd.services = | ||||
|     let | ||||
|       awaitCellar = { | ||||
|         after = [ "vm@cellar.service" ]; | ||||
|         bindsTo = [ "vm@cellar.service" ]; | ||||
|       awaitVM = system: { | ||||
|         after = [ "vm@${system}.service" ]; | ||||
|         bindsTo = [ "vm@${system}.service" ]; | ||||
|         preStart = '' | ||||
|           until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.cellar.hi.ipv4.address} 22; do | ||||
|           until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.${system}.hi.ipv4.address} 22; do | ||||
|             sleep 1 | ||||
|           done | ||||
|         ''; | ||||
| @@ -81,13 +82,13 @@ | ||||
|         vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device"; | ||||
|       in | ||||
|       mkMerge [ | ||||
|         awaitCellar | ||||
|         (awaitVM "cellar") | ||||
|         { | ||||
|           requires = [ vtapUnit ]; | ||||
|           after = [ vtapUnit ]; | ||||
|         } | ||||
|       ]; | ||||
|       "vm@sfh" = awaitCellar; | ||||
|       "vm@sfh" = (awaitVM "river"); | ||||
|     }; | ||||
|  | ||||
|     my = { | ||||
| @@ -182,6 +183,10 @@ | ||||
|                 index = 0; | ||||
|                 hostBDF = "44:00.3"; | ||||
|               }; | ||||
|               et100g0vf3 = { | ||||
|                 index = 1; | ||||
|                 hostBDF = "44:00.4"; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|   | ||||
| @@ -10,18 +10,7 @@ | ||||
|     let | ||||
|       inherit (lib.my) networkdAssignment mkVLAN; | ||||
|       inherit (lib.my.c) networkd; | ||||
|       inherit (lib.my.c.home) vlans; | ||||
|  | ||||
|       lanLink = { | ||||
|         matchConfig = { | ||||
|           Driver = "mlx5_core"; | ||||
|           PermanentMACAddress = "52:54:00:8a:8a:f2"; | ||||
|         }; | ||||
|         linkConfig = { | ||||
|           Name = "lan"; | ||||
|           MTUBytes = toString lib.my.c.home.hiMTU; | ||||
|         }; | ||||
|       }; | ||||
|       inherit (lib.my.c.home) vlans domain prefixes roceBootModules; | ||||
|     in | ||||
|     { | ||||
|       imports = [ | ||||
| @@ -30,29 +19,17 @@ | ||||
|  | ||||
|       config = { | ||||
|         boot = { | ||||
|           kernelModules = [ "kvm-intel" ]; | ||||
|           kernelModules = [ "kvm-amd" ]; | ||||
|           kernelParams = [ "console=ttyS0,115200n8" ]; | ||||
|           initrd = { | ||||
|             availableKernelModules = [ | ||||
|               "virtio_pci" "ahci" "sr_mod" "virtio_blk" | ||||
|               "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" "8021q" | ||||
|               "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" | ||||
|             ]; | ||||
|             kernelModules = [ "dm-snapshot" "nvme-fabrics" ]; | ||||
|               "8021q" | ||||
|             ] ++ roceBootModules; | ||||
|             kernelModules = [ "dm-snapshot" ]; | ||||
|             systemd = { | ||||
|               extraBin = with pkgs; { | ||||
|                 dmesg = "${util-linux}/bin/dmesg"; | ||||
|                 ip = "${iproute2}/bin/ip"; | ||||
|               }; | ||||
|               extraConfig = '' | ||||
|                 DefaultTimeoutStartSec=50 | ||||
|                 DefaultDeviceTimeoutSec=50 | ||||
|               ''; | ||||
|               network = { | ||||
|                 enable = true; | ||||
|                 wait-online.enable = true; | ||||
|  | ||||
|                 links."10-lan" = lanLink; | ||||
|                 # Don't need to put the link config here, they're copied from main config | ||||
|                 netdevs = mkVLAN "lan-hi" vlans.hi; | ||||
|                 networks = { | ||||
|                   "20-lan" = { | ||||
| @@ -70,9 +47,6 @@ | ||||
|  | ||||
|         hardware = { | ||||
|           enableRedistributableFirmware = true; | ||||
|           cpu = { | ||||
|             intel.updateMicrocode = true; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         fileSystems = { | ||||
| @@ -96,6 +70,7 @@ | ||||
|             boot.thin.enable = true; | ||||
|             dmeventd.enable = true; | ||||
|           }; | ||||
|           fstrim.enable = true; | ||||
|         }; | ||||
|  | ||||
|         systemd.network = { | ||||
| @@ -114,7 +89,16 @@ | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             "10-lan" = lanLink; | ||||
|             "10-lan" = { | ||||
|               matchConfig = { | ||||
|                 Driver = "mlx5_core"; | ||||
|                 PermanentMACAddress = "52:54:00:8a:8a:f2"; | ||||
|               }; | ||||
|               linkConfig = { | ||||
|                 Name = "lan"; | ||||
|                 MTUBytes = toString lib.my.c.home.hiMTU; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           # So we don't drop the IP we use to connect to NVMe-oF! | ||||
| @@ -134,6 +118,14 @@ | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           netboot.server = { | ||||
|             enable = true; | ||||
|             ip = assignments.lo.ipv4.address; | ||||
|             host = "boot.${domain}"; | ||||
|             allowedPrefixes = with prefixes; [ hi.v4 hi.v6 lo.v4 lo.v6 ]; | ||||
|             instances = [ "sfh" "castle" ]; | ||||
|           }; | ||||
|  | ||||
|           deploy.node.hostname = "192.168.68.1"; | ||||
|         }; | ||||
|       }; | ||||
|   | ||||
							
								
								
									
										5
									
								
								nixos/boxes/home/palace/vms/sfh/containers/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								nixos/boxes/home/palace/vms/sfh/containers/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| { | ||||
|   imports = [ | ||||
|     ./unifi.nix | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										64
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,64 @@ | ||||
| { lib, ... }: | ||||
| let | ||||
|   inherit (lib.my) net; | ||||
|   inherit (lib.my.c.home) domain prefixes vips hiMTU; | ||||
| in | ||||
| { | ||||
|   nixos.systems.unifi = { config, ... }: { | ||||
|     system = "x86_64-linux"; | ||||
|     nixpkgs = "mine"; | ||||
|     rendered = config.configuration.config.my.asContainer; | ||||
|  | ||||
|     assignments = { | ||||
|       hi = { | ||||
|         name = "unifi-ctr"; | ||||
|         inherit domain; | ||||
|         mtu = hiMTU; | ||||
|         ipv4 = { | ||||
|           address = net.cidr.host 100 prefixes.hi.v4; | ||||
|           mask = 22; | ||||
|           gateway = vips.hi.v4; | ||||
|         }; | ||||
|         ipv6 = { | ||||
|           iid = "::5:1"; | ||||
|           address = net.cidr.host (65536*5+1) prefixes.hi.v6; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     configuration = { lib, config, pkgs, assignments, ... }: | ||||
|     let | ||||
|       inherit (lib) mkMerge mkIf mkForce; | ||||
|       inherit (lib.my) networkdAssignment; | ||||
|     in | ||||
|     { | ||||
|       config = { | ||||
|         my = { | ||||
|           deploy.enable = false; | ||||
|           server.enable = true; | ||||
|  | ||||
|           secrets = { | ||||
|             key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdgcziQki/RH7E+NH2bYnzSVKaJ27905Yo5TcOjSh/U"; | ||||
|             files = { }; | ||||
|           }; | ||||
|  | ||||
|           firewall = { | ||||
|             tcp.allowed = [ 8443 ]; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         systemd = { | ||||
|           network.networks."80-container-host0" = networkdAssignment "host0" assignments.hi; | ||||
|         }; | ||||
|  | ||||
|         services = { | ||||
|           unifi = { | ||||
|             enable = true; | ||||
|             openFirewall = true; | ||||
|             unifiPackage = pkgs.unifi8; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										157
									
								
								nixos/boxes/home/palace/vms/sfh/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								nixos/boxes/home/palace/vms/sfh/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,157 @@ | ||||
| { lib, ... }: | ||||
| let | ||||
|   inherit (lib.my) net; | ||||
|   inherit (lib.my.c.home) domain prefixes vips hiMTU roceBootModules; | ||||
| in | ||||
| { | ||||
|   imports = [ ./containers ]; | ||||
|  | ||||
|   config.nixos.systems.sfh = { | ||||
|     system = "x86_64-linux"; | ||||
|     nixpkgs = "mine"; | ||||
|     home-manager = "mine"; | ||||
|  | ||||
|     assignments = { | ||||
|       hi = { | ||||
|         inherit domain; | ||||
|         mtu = hiMTU; | ||||
|         ipv4 = { | ||||
|           address = net.cidr.host 81 prefixes.hi.v4; | ||||
|           mask = 22; | ||||
|           gateway = vips.hi.v4; | ||||
|         }; | ||||
|         ipv6 = { | ||||
|           iid = "::4:2"; | ||||
|           address = net.cidr.host (65536*4+2) prefixes.hi.v6; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     configuration = { lib, modulesPath, pkgs, config, assignments, allAssignments, ... }: | ||||
|     let | ||||
|       inherit (lib) mapAttrs mkMerge; | ||||
|       inherit (lib.my) networkdAssignment; | ||||
|       inherit (lib.my.c) networkd; | ||||
|       inherit (lib.my.c.home) domain; | ||||
|     in | ||||
|     { | ||||
|       imports = [ | ||||
|         "${modulesPath}/profiles/qemu-guest.nix" | ||||
|       ]; | ||||
|  | ||||
|       config = { | ||||
|         boot = { | ||||
|           kernelModules = [ "kvm-amd" ]; | ||||
|           kernelParams = [ "console=ttyS0,115200n8" ]; | ||||
|           initrd = { | ||||
|             availableKernelModules = [ | ||||
|               "virtio_pci" "ahci" "sr_mod" "virtio_blk" | ||||
|             ] ++ roceBootModules; | ||||
|             kernelModules = [ "dm-snapshot" ]; | ||||
|             systemd = { | ||||
|               network = { | ||||
|                 networks = { | ||||
|                   "20-lan-hi" = networkdAssignment "lan-hi" assignments.hi; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         hardware = { | ||||
|           enableRedistributableFirmware = true; | ||||
|         }; | ||||
|  | ||||
|         fileSystems = { | ||||
|           "/nix" = { | ||||
|             device = "/dev/main/nix"; | ||||
|             fsType = "ext4"; | ||||
|           }; | ||||
|           "/persist" = { | ||||
|             device = "/dev/main/persist"; | ||||
|             fsType = "ext4"; | ||||
|             neededForBoot = true; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         networking = { inherit domain; }; | ||||
|  | ||||
|         services = { | ||||
|           lvm = { | ||||
|             boot.thin.enable = true; | ||||
|             dmeventd.enable = true; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         systemd.network = { | ||||
|           links = { | ||||
|             "10-lan-hi" = { | ||||
|               matchConfig = { | ||||
|                 Driver = "mlx5_core"; | ||||
|                 PermanentMACAddress = "52:54:00:ac:15:a9"; | ||||
|               }; | ||||
|               linkConfig = { | ||||
|                 Name = "lan-hi"; | ||||
|                 MTUBytes = toString lib.my.c.home.hiMTU; | ||||
|               }; | ||||
|             }; | ||||
|             "10-lan-hi-ctrs" = { | ||||
|               matchConfig = { | ||||
|                 Driver = "mlx5_core"; | ||||
|                 PermanentMACAddress = "52:54:00:90:34:95"; | ||||
|               }; | ||||
|               linkConfig = { | ||||
|                 Name = "lan-hi-ctrs"; | ||||
|                 MTUBytes = toString lib.my.c.home.hiMTU; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           networks = { | ||||
|             "30-lan-hi" = mkMerge [ | ||||
|               (networkdAssignment "lan-hi" assignments.hi) | ||||
|               # So we don't drop the IP we use to connect to NVMe-oF! | ||||
|               { networkConfig.KeepConfiguration = "static"; } | ||||
|             ]; | ||||
|             "30-lan-hi-ctrs" = { | ||||
|               matchConfig.Name = "lan-hi-ctrs"; | ||||
|               linkConfig.RequiredForOnline = "no"; | ||||
|               networkConfig = networkd.noL3; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         my = { | ||||
|           secrets = { | ||||
|             key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAaav5Se1E/AbqEXmADryVszYfNDscyP6jrWioN57R7"; | ||||
|           }; | ||||
|           server.enable = true; | ||||
|  | ||||
|           netboot.client = { | ||||
|             enable = true; | ||||
|           }; | ||||
|           nvme = { | ||||
|             uuid = "85d7df36-0de0-431b-b06e-51f7c0a455b4"; | ||||
|             boot = { | ||||
|               nqn = "nqn.2016-06.io.spdk:sfh"; | ||||
|               address = "192.168.68.80"; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           containers.instances = | ||||
|           let | ||||
|             instances = { | ||||
|               unifi = {}; | ||||
|             }; | ||||
|           in | ||||
|           mkMerge [ | ||||
|             instances | ||||
|             (mapAttrs (n: i: { | ||||
|               networking.macVLAN = "lan-hi-ctrs"; | ||||
|             }) instances) | ||||
|           ]; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| @@ -148,19 +148,33 @@ in | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             nginx.enable = true; | ||||
|           }; | ||||
|  | ||||
|           networking.domain = "h.${pubDomain}"; | ||||
|           networking = { inherit domain; }; | ||||
|  | ||||
|           systemd.services = { | ||||
|             ipsec = | ||||
|           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 | ||||
|   | ||||
| @@ -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 river-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,7 +1,7 @@ | ||||
| index: { lib, pkgs, assignments, ... }: | ||||
| index: { lib, pkgs, config, assignments, allAssignments, ... }: | ||||
| let | ||||
|   inherit (lib) mkForce; | ||||
|   inherit (lib.my) net; | ||||
|   inherit (lib.my) net netbootKeaClientClasses; | ||||
|   inherit (lib.my.c.home) domain prefixes vips hiMTU; | ||||
|  | ||||
|   dns-servers = [ | ||||
| @@ -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,14 @@ in | ||||
|               always-send = true; | ||||
|             } | ||||
|           ]; | ||||
|           client-classes = netbootKeaClientClasses { | ||||
|             tftpIP = allAssignments.river.lo.ipv4.address; | ||||
|             hostname = "boot.${domain}"; | ||||
|             systems = { | ||||
|               sfh = "52:54:00:a5:7e:93"; | ||||
|               castle = "c8:7f:54:6e:17:0f"; | ||||
|             }; | ||||
|           }; | ||||
|           subnet4 = [ | ||||
|             { | ||||
|               id = 1; | ||||
|   | ||||
| @@ -1,52 +1,83 @@ | ||||
| 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; | ||||
|     extraConfig = '' | ||||
|       notify_master "${config.systemd.package}/bin/systemctl start radvd.service" | ||||
|       notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" | ||||
|     ''; | ||||
|     trackScripts = [ "${family}Alive" ]; | ||||
|   }; | ||||
| 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; | ||||
|       }; | ||||
|         v6 = (mkVRRP "v6" 52) // { | ||||
|           extraConfig = '' | ||||
|         vrrp_sync_group main { | ||||
|           group { | ||||
|             v4 | ||||
|             v6 | ||||
|           } | ||||
|         } | ||||
|             notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root | ||||
|             notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root | ||||
|           ''; | ||||
|         }; | ||||
|       }; | ||||
|       # 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 = { | ||||
| @@ -80,6 +82,8 @@ | ||||
|                 ${pkgs.gawk}/bin/awk '{ print $1 }')" | ||||
|             ''; | ||||
|  | ||||
|           boot.supportedFilesystems.nfs = true; | ||||
|  | ||||
|           environment.systemPackages = with pkgs; [ | ||||
|             dhcpcd | ||||
|             lm_sensors | ||||
|   | ||||
| @@ -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,145 @@ 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; | ||||
|           initrd = { | ||||
|             kernelModules = [ "nbd" ]; | ||||
|             availableKernelModules = [ "igb" "igc" ]; | ||||
|  | ||||
|             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=20 | ||||
|                 DefaultDeviceTimeoutSec=20 | ||||
|               ''; | ||||
|  | ||||
|               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" { } '' | ||||
|             export PATH=${pkgs.zstd}/bin:$PATH | ||||
|             ${pkgs.gnutar}/bin/tar --dereference --zstd -cvC ${config.system.build.netbootTree} -f "$out" . | ||||
|           ''; | ||||
|         }; | ||||
|       }) | ||||
|     ]; | ||||
|   }; | ||||
| @@ -77,6 +207,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 +241,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; | ||||
|           }; | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { lib, pkgs, options, config, systems, ... }: | ||||
| let | ||||
|   inherit (builtins) attrNames attrValues all hashString toJSON; | ||||
|   inherit (builtins) attrNames attrValues all hashString toJSON any; | ||||
|   inherit (lib) | ||||
|     groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge; | ||||
|   inherit (lib.my) mkOpt' mkBoolOpt'; | ||||
| @@ -98,6 +98,7 @@ let | ||||
|       }; | ||||
|       networking = { | ||||
|         bridge = mkOpt' (nullOr str) null "Network bridge to connect to."; | ||||
|         macVLAN = mkOpt' (nullOr str) null "Network interface to make MACVLAN interface from."; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| @@ -115,26 +116,19 @@ in | ||||
|           assertion = config.systemd.network.enable; | ||||
|           message = "Containers currently require systemd-networkd!"; | ||||
|         } | ||||
|         { | ||||
|           assertion = all (i: i.networking.bridge == null || i.networking.macVLAN == null) (attrValues cfg.instances); | ||||
|           message = "Only bridge OR MACVLAN can be set"; | ||||
|         } | ||||
|       ]; | ||||
|  | ||||
|       # TODO: Better security | ||||
|       my.firewall.trustedInterfaces = | ||||
|         mapAttrsToList | ||||
|           (n: _: "ve-${n}") | ||||
|           (filterAttrs (_: c: c.networking.bridge == null) cfg.instances); | ||||
|           (filterAttrs (_: c: c.networking.bridge == null && c.networking.macVLAN == 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; | ||||
| @@ -165,6 +159,8 @@ in | ||||
|           }; | ||||
|           networkConfig = if (c.networking.bridge != null) then { | ||||
|             Bridge = c.networking.bridge; | ||||
|           } else if (c.networking.macVLAN != null) then { | ||||
|             MACVLAN = "${c.networking.macVLAN}:host0"; | ||||
|           } else { | ||||
|             VirtualEthernet = true; | ||||
|           }; | ||||
| @@ -182,6 +178,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 +246,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,8 +62,12 @@ let | ||||
|       chain l2mesh-${name} { | ||||
|         ${optionalString mesh.security.enable '' | ||||
|           udp dport isakmp 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); | ||||
|   | ||||
							
								
								
									
										223
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,223 @@ | ||||
| { lib, pkgs, config, ... }: | ||||
| let | ||||
|   inherit (lib) mkMerge mkIf mkForce genAttrs concatMapStringsSep; | ||||
|   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" | ||||
|   ''; | ||||
|  | ||||
|   bootBuilder = pkgs.substituteAll { | ||||
|     src = ./netboot-loader-builder.py; | ||||
|     isExecutable = true; | ||||
|  | ||||
|     inherit (pkgs) python3; | ||||
|     bootspecTools = pkgs.bootspec; | ||||
|     nix = config.nix.package.out; | ||||
|  | ||||
|     inherit (config.system.nixos) distroName; | ||||
|     systemName = config.system.name; | ||||
|     inherit (cfg.client) configurationLimit; | ||||
|     checkMountpoints = pkgs.writeShellScript "check-mountpoints" '' | ||||
|       if ! ${pkgs.util-linuxMinimal}/bin/findmnt /boot > /dev/null; then | ||||
|         echo "/boot is not a mounted partition. Is the path configured correctly?" >&2 | ||||
|         exit 1 | ||||
|       fi | ||||
|     ''; | ||||
|   }; | ||||
| in | ||||
| { | ||||
|   options.my.netboot = with lib.types; { | ||||
|     client = { | ||||
|       enable = mkBoolOpt' false "Whether network booting should be enabled."; | ||||
|       configurationLimit = mkOpt' ints.unsigned 10 "Max generations to show in boot menu."; | ||||
|     }; | ||||
|     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 / NFS."; | ||||
|       allowedPrefixes = mkOpt' (listOf str) null "Prefixes clients should be allowed to connect from (NFS)."; | ||||
|       installer = { | ||||
|         storeSize = mkOpt' str "16GiB" "Total allowed writable size of store."; | ||||
|       }; | ||||
|       instances = mkOpt' (listOf str) [ ] "Systems to hold boot files for."; | ||||
|     }; | ||||
|   }; | ||||
|  | ||||
|   config = mkMerge [ | ||||
|     (mkIf cfg.client.enable { | ||||
|       systemd = { | ||||
|         services = { | ||||
|           mount-boot = { | ||||
|             description = "Mount /boot"; | ||||
|             after = [ "systemd-networkd-wait-online.service" ]; | ||||
|             serviceConfig = { | ||||
|               Type = "oneshot"; | ||||
|               RemainAfterExit = true; | ||||
|             }; | ||||
|             path = with pkgs; [ gnused ldns nfs-utils ]; | ||||
|             script = '' | ||||
|               get_cmdline() { | ||||
|                 sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline | ||||
|               } | ||||
|  | ||||
|               host="$(get_cmdline boothost)" | ||||
|               if [ -z "$host" ]; then | ||||
|                 echo "boothost kernel parameter not found!" >&2 | ||||
|                 exit 1 | ||||
|               fi | ||||
|  | ||||
|               until [ -n "$(drill -Q $host)" ]; do | ||||
|                 sleep 0.1 | ||||
|               done | ||||
|  | ||||
|               mkdir -p /boot | ||||
|               mount.nfs $host:/srv/netboot/systems/${config.system.name} /boot | ||||
|             ''; | ||||
|  | ||||
|             wantedBy = [ "remote-fs.target" ]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|  | ||||
|       boot.supportedFilesystems.nfs = true; | ||||
|       boot.loader = { | ||||
|         grub.enable = false; | ||||
|         systemd-boot.enable = false; | ||||
|       }; | ||||
|       system = { | ||||
|         build.installBootLoader = bootBuilder; | ||||
|         boot.loader.id = "ipxe-netboot"; | ||||
|       }; | ||||
|     }) | ||||
|     (mkIf cfg.server.enable { | ||||
|       environment = { | ||||
|         etc = { | ||||
|           "netboot/menu.ipxe".source = menuFile; | ||||
|           "netboot/shell.efi".source = "${pkgs.edk2-uefi-shell}/shell.efi"; | ||||
|         }; | ||||
|       }; | ||||
|  | ||||
|       systemd = { | ||||
|         tmpfiles.settings."10-netboot" = genAttrs | ||||
|           (map (i: "/srv/netboot/systems/${i}") cfg.server.instances) | ||||
|           (p: { | ||||
|             d = { | ||||
|               user = "root"; | ||||
|               group = "root"; | ||||
|               mode = "0777"; | ||||
|             }; | ||||
|           }); | ||||
|  | ||||
|         services = { | ||||
|           netboot-update = { | ||||
|             description = "Update netboot images"; | ||||
|             after = [ "systemd-networkd-wait-online.service" ]; | ||||
|             serviceConfig.Type = "oneshot"; | ||||
|             path = with pkgs; [ | ||||
|               coreutils curl jq zstd 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}/shell.efi" "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; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         nfs = { | ||||
|           server = { | ||||
|             enable = true; | ||||
|             exports = '' | ||||
|               /srv/netboot/systems ${concatMapStringsSep " " (p: "${p}(rw,all_squash)") cfg.server.allowedPrefixes} | ||||
|             ''; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|  | ||||
|       my = { | ||||
|         tmproot.persistence.config.directories = [ | ||||
|           "/srv/netboot" | ||||
|           { directory = "/var/cache/netboot"; mode = "0700"; } | ||||
|         ]; | ||||
|       }; | ||||
|     }) | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										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 | ||||
							
								
								
									
										280
									
								
								nixos/modules/netboot/netboot-loader-builder.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										280
									
								
								nixos/modules/netboot/netboot-loader-builder.py
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,280 @@ | ||||
| #! @python3@/bin/python3 -B | ||||
| # Based on `nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py` | ||||
| import argparse | ||||
| import datetime | ||||
| import glob | ||||
| import os | ||||
| import os.path | ||||
| import shutil | ||||
| import subprocess | ||||
| import sys | ||||
| import json | ||||
| from typing import NamedTuple, Dict, List | ||||
| from dataclasses import dataclass | ||||
|  | ||||
| BOOT_MOUNT_POINT = '/boot' | ||||
| STORE_DIR = 'nix' | ||||
|  | ||||
| # These values will be replaced with actual values during the package build | ||||
| BOOTSPEC_TOOLS = '@bootspecTools@' | ||||
| NIX = '@nix@' | ||||
| DISTRO_NAME = '@distroName@' | ||||
| SYSTEM_NAME = '@systemName@' | ||||
| CONFIGURATION_LIMIT = int('@configurationLimit@') | ||||
| CHECK_MOUNTPOINTS = "@checkMountpoints@" | ||||
|  | ||||
| @dataclass | ||||
| class BootSpec: | ||||
|   init: str | ||||
|   initrd: str | ||||
|   kernel: str | ||||
|   kernelParams: List[str] | ||||
|   label: str | ||||
|   system: str | ||||
|   toplevel: str | ||||
|   specialisations: Dict[str, 'BootSpec'] | ||||
|   sortKey: str | ||||
|   initrdSecrets: str | None = None | ||||
|  | ||||
| class SystemIdentifier(NamedTuple): | ||||
|   profile: str | None | ||||
|   generation: int | ||||
|   specialisation: str | None | ||||
|  | ||||
| def copy_if_not_exists(source: str, dest: str) -> None: | ||||
|   if not os.path.exists(dest): | ||||
|     shutil.copyfile(source, dest) | ||||
|  | ||||
| def generation_dir(profile: str | None, generation: int) -> str: | ||||
|   if profile: | ||||
|     return f'/nix/var/nix/profiles/system-profiles/{profile}-{generation}-link' | ||||
|   else: | ||||
|     return f'/nix/var/nix/profiles/system-{generation}-link' | ||||
|  | ||||
| def system_dir(i: SystemIdentifier) -> str: | ||||
|   d = generation_dir(i.profile, i.generation) | ||||
|   if i.specialisation: | ||||
|     return os.path.join(d, 'specialisation', i.specialisation) | ||||
|   else: | ||||
|     return d | ||||
|  | ||||
| def entry_key(i: SystemIdentifier) -> str: | ||||
|   pieces = [ | ||||
|     'nixos', | ||||
|     i.profile or None, | ||||
|     'generation', | ||||
|     str(i.generation), | ||||
|     f'specialisation-{i.specialisation}' if i.specialisation else None, | ||||
|   ] | ||||
|   return '-'.join(p for p in pieces if p) | ||||
|  | ||||
| def bootspec_from_json(bootspec_json: Dict) -> BootSpec: | ||||
|   specialisations = bootspec_json['org.nixos.specialisation.v1'] | ||||
|   specialisations = {k: bootspec_from_json(v) for k, v in specialisations.items()} | ||||
|   systemdBootExtension = bootspec_json.get('org.nixos.systemd-boot', {}) | ||||
|   sortKey = systemdBootExtension.get('sortKey', 'nixos') | ||||
|   return BootSpec( | ||||
|     **bootspec_json['org.nixos.bootspec.v1'], | ||||
|     specialisations=specialisations, | ||||
|     sortKey=sortKey | ||||
|   ) | ||||
|  | ||||
| bootspecs = {} | ||||
| def get_bootspec(profile: str | None, generation: int) -> BootSpec: | ||||
|   k = (profile, generation) | ||||
|   if k in bootspecs: | ||||
|     return bootspecs[k] | ||||
|  | ||||
|   system_directory = system_dir(SystemIdentifier(profile, generation, None)) | ||||
|   boot_json_path = os.path.realpath(f'{system_directory}/boot.json') | ||||
|   if os.path.isfile(boot_json_path): | ||||
|     boot_json_f = open(boot_json_path, 'r') | ||||
|     bootspec_json = json.load(boot_json_f) | ||||
|   else: | ||||
|     boot_json_str = subprocess.check_output([ | ||||
|       f'{BOOTSPEC_TOOLS}/bin/synthesize', | ||||
|       '--version', | ||||
|       '1', | ||||
|       system_directory, | ||||
|       '/dev/stdout', | ||||
|     ], | ||||
|     universal_newlines=True) | ||||
|     bootspec_json = json.loads(boot_json_str) | ||||
|  | ||||
|   bs = bootspec_from_json(bootspec_json) | ||||
|   bootspecs[k] = bs | ||||
|   return bs | ||||
|  | ||||
| def copy_from_file(file: str, dry_run: bool = False) -> str: | ||||
|   store_file_path = os.path.realpath(file) | ||||
|   suffix = os.path.basename(store_file_path) | ||||
|   store_dir = os.path.basename(os.path.dirname(store_file_path)) | ||||
|   dst_path = f'/{STORE_DIR}/{store_dir}-{suffix}' | ||||
|   if not dry_run: | ||||
|     copy_if_not_exists(store_file_path, f'{BOOT_MOUNT_POINT}{dst_path}') | ||||
|   return dst_path | ||||
|  | ||||
| MENU_ITEM = 'item {gen_key} {title} Generation {generation} {description}' | ||||
|  | ||||
| BOOT_ENTRY = ''':{gen_key} | ||||
| kernel ${{server}}/systems/{system_name}{kernel} {kernel_params} boothost=${{boothost}} | ||||
| initrd ${{server}}/systems/{system_name}{initrd} | ||||
| boot | ||||
| ''' | ||||
|  | ||||
| def gen_entry(i: SystemIdentifier) -> (str, str): | ||||
|   bootspec = get_bootspec(i.profile, i.generation) | ||||
|   if i.specialisation: | ||||
|     bootspec = bootspec.specialisations[i.specialisation] | ||||
|   kernel = copy_from_file(bootspec.kernel) | ||||
|   initrd = copy_from_file(bootspec.initrd) | ||||
|  | ||||
|   gen_key = entry_key(i) | ||||
|   title = '{name}{profile}{specialisation}'.format( | ||||
|     name=DISTRO_NAME, | ||||
|     profile=' [' + i.profile + ']' if i.profile else '', | ||||
|     specialisation=f' ({i.specialisation})' if i.specialisation else '') | ||||
|  | ||||
|   kernel_params = f'init={bootspec.init} ' | ||||
|  | ||||
|   kernel_params = kernel_params + ' '.join(bootspec.kernelParams) | ||||
|   build_time = int(os.path.getctime(system_dir(i))) | ||||
|   build_date = datetime.datetime.fromtimestamp(build_time).strftime('%F') | ||||
|  | ||||
|   return MENU_ITEM.format( | ||||
|     gen_key=gen_key, | ||||
|     title=title, | ||||
|     description=f'{bootspec.label}, built on {build_date}', | ||||
|     generation=i.generation, | ||||
|   ), BOOT_ENTRY.format( | ||||
|     gen_key=gen_key, | ||||
|     generation=i.generation, | ||||
|     system_name=SYSTEM_NAME, | ||||
|     kernel=kernel, | ||||
|     kernel_params=kernel_params, | ||||
|     initrd=initrd, | ||||
|   ) | ||||
|  | ||||
| def get_generations(profile: str | None = None) -> list[SystemIdentifier]: | ||||
|   gen_list = subprocess.check_output([ | ||||
|     f'{NIX}/bin/nix-env', | ||||
|     '--list-generations', | ||||
|     '-p', | ||||
|     '/nix/var/nix/profiles/' + ('system-profiles/' + profile if profile else 'system')], | ||||
|     universal_newlines=True) | ||||
|   gen_lines = gen_list.split('\n') | ||||
|   gen_lines.pop() | ||||
|  | ||||
|   configurationLimit = CONFIGURATION_LIMIT | ||||
|   configurations = [ | ||||
|     SystemIdentifier( | ||||
|       profile=profile, | ||||
|       generation=int(line.split()[0]), | ||||
|       specialisation=None | ||||
|     ) | ||||
|     for line in gen_lines | ||||
|   ] | ||||
|   return configurations[-configurationLimit:] | ||||
|  | ||||
| def remove_old_files(gens: list[SystemIdentifier]) -> None: | ||||
|   known_paths = [] | ||||
|   for gen in gens: | ||||
|     bootspec = get_bootspec(gen.profile, gen.generation) | ||||
|     known_paths.append(copy_from_file(bootspec.kernel, True)) | ||||
|     known_paths.append(copy_from_file(bootspec.initrd, True)) | ||||
|   for path in glob.iglob(f'{BOOT_MOUNT_POINT}/{STORE_DIR}/*'): | ||||
|     if not path in known_paths and not os.path.isdir(path): | ||||
|       os.unlink(path) | ||||
|  | ||||
| def get_profiles() -> list[str]: | ||||
|   if os.path.isdir('/nix/var/nix/profiles/system-profiles/'): | ||||
|     return [x | ||||
|       for x in os.listdir('/nix/var/nix/profiles/system-profiles/') | ||||
|       if not x.endswith('-link')] | ||||
|   else: | ||||
|     return [] | ||||
|  | ||||
| MENU = '''#!ipxe | ||||
| # Server hostname option | ||||
| set boothost ${{66:string}} | ||||
| set server http://${{boothost}} | ||||
|  | ||||
| :start | ||||
| menu {distro} boot menu | ||||
| item --gap -- Generations | ||||
| {generation_items} | ||||
| item --gap -- Other | ||||
| item --key m main Main netboot menu | ||||
| choose --timeout 5000 --default {menu_default} selected || goto cancel | ||||
| goto ${{selected}} | ||||
|  | ||||
| :cancel | ||||
| shell | ||||
| goto start | ||||
|  | ||||
| :error | ||||
| echo Booting failed, dropping to shell | ||||
| shell | ||||
| goto start | ||||
|  | ||||
| :main | ||||
| chain ${{server}}/boot.ipxe || goto error | ||||
| ''' | ||||
|  | ||||
| def write_menu(gens: list[SystemIdentifier], default: SystemIdentifier) -> None: | ||||
|   gen_menu_items = [] | ||||
|   gen_cmds = [] | ||||
|  | ||||
|   for g in gens: | ||||
|     bootspec = get_bootspec(g.profile, g.generation) | ||||
|     specialisations = [ | ||||
|       SystemIdentifier(profile=g.profile, generation=g.generation, specialisation=s) for s in bootspec.specialisations] | ||||
|     for i in [g] + specialisations: | ||||
|       mi, cmds = gen_entry(i) | ||||
|       gen_menu_items.append(mi) | ||||
|       gen_cmds.append(cmds) | ||||
|  | ||||
|   menu_file = f'{BOOT_MOUNT_POINT}/menu.ipxe' | ||||
|   with open(f'{menu_file}.tmp', 'w') as f: | ||||
|     f.write(MENU.format( | ||||
|       distro=DISTRO_NAME, | ||||
|       generation_items='\n'.join(gen_menu_items), | ||||
|       menu_default=entry_key(default), | ||||
|     )) | ||||
|  | ||||
|     print(file=f) | ||||
|     print('\n\n'.join(gen_cmds), file=f) | ||||
|  | ||||
|   os.rename(f'{menu_file}.tmp', menu_file) | ||||
|  | ||||
| def install_bootloader(args: argparse.Namespace) -> None: | ||||
|   os.makedirs(f'{BOOT_MOUNT_POINT}/{STORE_DIR}', exist_ok=True) | ||||
|  | ||||
|   gens = get_generations() | ||||
|   for profile in get_profiles(): | ||||
|     gens += get_generations(profile) | ||||
|  | ||||
|   gens = sorted(gens, key=lambda g: entry_key(g), reverse=True) | ||||
|  | ||||
|   remove_old_files(gens) | ||||
|  | ||||
|   for g in gens: | ||||
|     if os.path.dirname(get_bootspec(g.profile, g.generation).init) == os.path.realpath(args.default_config): | ||||
|       default = g | ||||
|       break | ||||
|   else: | ||||
|     assert False, 'No default generation found' | ||||
|  | ||||
|   write_menu(gens, default) | ||||
|  | ||||
| def main() -> None: | ||||
|   parser = argparse.ArgumentParser(description=f'Update {DISTRO_NAME}-related netboot files') | ||||
|   parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help=f'The default {DISTRO_NAME} config to boot') | ||||
|   args = parser.parse_args() | ||||
|  | ||||
|   subprocess.check_call(CHECK_MOUNTPOINTS) | ||||
|  | ||||
|   install_bootloader(args) | ||||
|  | ||||
| if __name__ == '__main__': | ||||
|   main() | ||||
| @@ -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 ]; | ||||
|     }); | ||||
|   }; | ||||
|  | ||||
| @@ -33,9 +33,26 @@ in | ||||
|       etc = etc ""; | ||||
|     }; | ||||
|  | ||||
|     boot.initrd.systemd = mkIf (cfg.boot.nqn != null) { | ||||
|     boot = mkIf (cfg.boot.nqn != null) { | ||||
|       initrd = { | ||||
|         availableKernelModules = [ "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" ]; | ||||
|         kernelModules = [ "nvme-fabrics" ]; | ||||
|         systemd = { | ||||
|           contents = etc "/etc/"; | ||||
|       extraBin.nvme = "${nvme-cli}/bin/nvme"; | ||||
|           extraBin = with pkgs; { | ||||
|             dmesg = "${util-linux}/bin/dmesg"; | ||||
|             ip = "${iproute2}/bin/ip"; | ||||
|             nvme = "${nvme-cli}/bin/nvme"; | ||||
|           }; | ||||
|           extraConfig = '' | ||||
|             DefaultTimeoutStartSec=20 | ||||
|             DefaultDeviceTimeoutSec=20 | ||||
|           ''; | ||||
|  | ||||
|           network = { | ||||
|             enable = true; | ||||
|             wait-online.enable = true; | ||||
|           }; | ||||
|  | ||||
|           services.connect-nvme = { | ||||
|             description = "Connect NVMe-oF"; | ||||
| @@ -54,5 +71,7 @@ in | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|  | ||||
|   | ||||
| @@ -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,53 @@ 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); | ||||
|       } | ||||
|       (mkIf config.services.unifi.enable { | ||||
|         my.tmproot.persistence.config.directories = [ | ||||
|           { | ||||
|             directory = "/var/lib/unifi"; | ||||
|             mode = "0750"; | ||||
|             user = "unifi"; | ||||
|             group = "unifi"; | ||||
|           } | ||||
|           { | ||||
|             directory = "/var/cache/unifi"; | ||||
|             mode = "0750"; | ||||
|             user = "unifi"; | ||||
|             group = "unifi"; | ||||
|           } | ||||
|         ]; | ||||
|       }) | ||||
|     ])) | ||||
|   ]); | ||||
|  | ||||
|   | ||||
							
								
								
									
										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)); | ||||
| @@ -7,5 +7,10 @@ in | ||||
|   monocraft' = callPackage ./monocraft.nix { }; | ||||
|   vfio-pci-bind = callPackage ./vfio-pci-bind.nix { }; | ||||
|   librespeed-go = callPackage ./librespeed-go.nix { }; | ||||
|   modrinth-app = callPackage ./modrinth-app { }; | ||||
|   # 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="; | ||||
| } | ||||
| @@ -1,10 +1,10 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBJYzdr | ||||
| b1d2aEtVd3lVb3NBamRwVFpTaTRjZFlCczk4MVIwQUoxWklwN0NrCmFFekpPYUlO | ||||
| YlgvVlQ2WDR6amZDN0ZSY0Q3WWtTME5pUmhQeks1c3dGOVUKLT4gWDI1NTE5IHVK | ||||
| bUZvUVAvL0NmQzFkY3BuYm1wMjcwbFpLRUNpZjJCaW15SEVDUDV0REkKRXFMQ2d1 | ||||
| NlFBejBvTlJrcUtCYWZxSDBkbmxIdExBNTU0aC8zRW5OVWllVQotPiBDLWdyZWFz | ||||
| ZSBkeC4oTFUgO0FtJG9+RyB2IF1QXGhxVwpJS213MXBRMWY1cXlHZwotLS0gRUF2 | ||||
| ZkswNlhvcDhTc2tybCs1dldwa2l6SDZZVmNkNUNjNGlkV1ZVa09pOAp88dxHGxVU | ||||
| vuFQO6JcroY9MF5Te/YV+wMc3hVxksibMnH1TWGh207prwcOWNOEz2iEkZY= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBrMXND | ||||
| Zm1ma0FoNE5lWTFNTGlyeUQzdUZxMkxyVlU0cWdrcTJEakhDVXg4ClkyczJDR1FL | ||||
| eXE3QWFTM0wyeDNvL1gvcmx6eGE4elNuZW9wRHhJZ3Aya2cKLT4gWDI1NTE5IDhO | ||||
| S2JWNDhlclpERFFUTktyUG5HbnNxcVQvWmphOGp1cmNpK0NGZWVTejQKN0dybHl5 | ||||
| eHhicFNpUHQ3WFZDQS90NG5VZW5zVm8rcUxCdkZkOFVqdVFzRQotPiBBLWdyZWFz | ||||
| ZSBaIDMiRCBYO1g6IF9EawpJZwotLS0geXhWb1FORm00RVJoMm4zQjhBT0hERyt3 | ||||
| ekM1YXNzdTgzUTVMeHNsNDUwbwqSjgIVhg9bqtIydYC1FCA4ly2gurTcb1SUCMG8 | ||||
| XA9WAx1jv05xje+U97tRTTongJEW5vw= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,15 +1,17 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBLVlg2 | ||||
| ZUdtUlFUQXBLT3B5YmkycWJnMXJyKzltbyt6K2dJK1RBUm5ydWwwCmRUdjJFSEYz | ||||
| Wnp4cGtzTXZwc0s0SUJQUjRlOUJlQUoyQ3BETXZmY0ppWG8KLT4gWDI1NTE5IGR5 | ||||
| QUJzeG1DQTRLUmRwNnNSRUJRSFFtUDl5VjB0clVLYUp3R1g4TEVKaTgKb09tVlhF | ||||
| R0tmcmIxMHVHcG80RGxRTEhBcngvT3MrdnNPbmpCTlRyZW5xQQotPiA6RzEtZ3Jl | ||||
| YXNlCldSUlN2ejB0MGpyUHYzNS9OQmJTK3MvcXRDakdBVlhuUEt6SFE4QmhnWVN0 | ||||
| V1JMOE1oaEp5QQotLS0gYW1OMTcxNWJrUndmR2h0ZmRDWk5CYnJjc29pSERUMnNk | ||||
| d2VhTGdpOW4yUQrEeH2E9m0YycuW60QrdlRetO1kNU5FaKXRQt46iA9lACIWD4rC | ||||
| Cx6WxhCBgz3hvm9x6iuYiiQxZzgJNK7qXcV2MBeQdivazeEbC7blAKVPhwD/dl+b | ||||
| PzBDXRXG3c3jMjeZFT69fIBGJfZrrLGKpTALVE4dTVXmQmVVQDTp19IC+jUXHBti | ||||
| Pj6Dpc7452s8zPkzZyRbasO9b4PYTwq8IHT6X7ITwbzZZm8gexDYe2SzRZ5VcPz3 | ||||
| El+yoULZ92WbXPSQIP/Slx4BEZjmsQS+sm0N8AnBRNZkWVbHPF9IZRg3VjDAn2i8 | ||||
| F3un5js= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBjQmZr | ||||
| VDl4TVlzK0lCc0YwdFM3TEptU3Q3cWZ1d0FJQUI4Q1g1TVNyOENFCkU4NE5lYVhI | ||||
| d3B0amFJT1A1RTRSaUdUSmZ1WmU1SkVhTU9sdFZJR0p6UXcKLT4gWDI1NTE5IG5O | ||||
| RG1SQnZtSUk0SThNYkRpOHFPS29kbjdUenZyYjBBSTJKdXNUaGpYMG8KME8waXJ0 | ||||
| NWR2NHoyUkN1UUJoaVRxYXVMZlNvTHZqRmYvS2h4QjZpZm5NZwotPiBPclJULlkt | ||||
| Z3JlYXNlIEVdKEBXIDUgXTBzIi58TwpweFJEcUFpR0x2WWhiVDlOTFArenhjNXBB | ||||
| dVo2d1JQWEJyVHlTRnUzdUlFUE45RWlLU3ZRS0c4UWs5Nm1qVHorCko1RVdqOVdz | ||||
| aVAwY09KOUx4WktIVFBQclFXdFJZMTNVWHNKcTZFbDU5Q0xLaExvNVdlZ0pTczUr | ||||
| SkVDTzhDUysKCi0tLSA2VGJMM2lrNkViaU0wcnArSG9PemJrQ3lrUFNnRDRVeE1p | ||||
| V3lxeG1iN3I4Ckf36lD/b7agsT0qW8eGDnxsVor8hEmLBSa35/eeAxqMd0xPvQko | ||||
| REzIxPuEHRQM5dE4s4H/mySTC/AVsiwfcMrnOXInm4o3MNAC9PREcef4NBOP3IMl | ||||
| Mcoifar27EXs21XdXw/lLOVNDX7oDKZh1zXVX4lFTcRW0v8abbwchvuTiayKePMG | ||||
| DrcyFsj4jiwpJ5MmY/Q+n0lZmoAlAJkeTHRUptJxGMq+pWVEGMa8p1vUdrVwWq7G | ||||
| YYO5lPlms01BFJfUsysh07HY1HPkOyFHeEkviZtt4N8hopx0pP4fyAZYYdrBAIdt | ||||
| CLpQFQ== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyAyMWox | ||||
| cEFDWWUrVzJSM1o2azJqei9HV2xFY25oQXV5SzM3akxEaUJiN1J3CjkrQVhjWHY5 | ||||
| Uk01eGp5Q0RKNVREVXJVZytndTM0SXNZSGIvUVp1TnRiNXMKLT4gWDI1NTE5IFZn | ||||
| WjAyR1RMajEyMnFSYnNGT2EyekROVWNoakFJQVZxaFc0YThOMHVyanMKWldrdlAv | ||||
| cVg0OTFHL2loeGJ3RHA0MnlnckN3czF4RUgyc1NjYXVOSXF5cwotPiBvTFQtZ3Jl | ||||
| YXNlIDRsSDp6eikgT1ojIGEzOFZMIFc3MUZGCkttZ3ZLNGxucnlJc01kRXFZTGpC | ||||
| eCsvRzl5WnFUMUIyTWNVWGk4SjQyN3V0bXQ4VzFuM1RjSzVMcDJkaW1JYXMKQkE4 | ||||
| YWI1Mmg3MkpjdVpVYWJkczJQMnM1SVMvNkZhOXBDVEZPCi0tLSB3SVIyU3M5RHBE | ||||
| VFRtMFU4OUFLbkNjbkJmVmhlc2VsYzdsd0pFaFkrUmkwCs+h2KlXoyZ8U++A9wmV | ||||
| kh4N2YyI/a84yPGDNoFdSlXaU8jxUzolnadImXSXyB4CroqQLvGEbkZZlWqPLVfh | ||||
| Iav7Ja8= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBETE9p | ||||
| VVVHeThGT3daNW1xZjBDblFwQWozQ2VSUmR3NlJVak12YXdWUDNNCitTWnBHd1Mv | ||||
| L2ViUWJvR0dtckpTQnRNMWZtazZHQ0tON0RhM0Z3cTlYVUUKLT4gWDI1NTE5IGhV | ||||
| ZEFqcW9CcHUya0s5dmgxc1JqUWRicmpXTllIckxaWjhtYzMrOFp0R2MKNUcxVllk | ||||
| WWJ2cEkzdXdiVFNDQVN2cUVNRnlMQ1BZWEx0QTI2M0FKSHE1ZwotPiBHaCJASk9u | ||||
| LWdyZWFzZSBsIFxuClVieGM0alFSdmttVjVsNDZIT2hjSTdWc1Z2VXRIUC9BbXNL | ||||
| MXArcHI2eDM4QWwyeXhtMU41cEtLQ2tkVllJdjkKTjMvNENSNXd1UjV2bGQzbnJx | ||||
| U3RubVRxQXVSSzJXbG5uQmcKLS0tIFFIeEVhR29qY3FBaUlJd1M4K3FvdDNybHZB | ||||
| MmVMZGxyYUYxVDNydjZLbXMKiPpxBn4WtzaH2iTFfjayYgNFPa0Mi6tIH0LOqkAj | ||||
| RyHNF/6vgWlmnivbhP+74dVaqR8IwUdFQN7S8/fx7eW/7qvtlg== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
							
								
								
									
										33
									
								
								secrets/chatterbox/doublepuppet.yaml.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										33
									
								
								secrets/chatterbox/doublepuppet.yaml.age
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,33 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBSS3E0 | ||||
| YWsxbHZXQXo1R3BzL1BDdERxN3d2ek5acFZWK3F6andTeGVacVNVCnhPR3I4dXFV | ||||
| dFd0N2lsTU5NOCtsM3Z1YUdIaER4YjlrdkNXT1g4dGZXNFkKLT4gWDI1NTE5IDBQ | ||||
| cHBYSG04eHA1ZG9KN1Q5bFk0eXk0T0o4c2pLVUdNbEtWaDdwckdJVmcKd3lkZmVY | ||||
| cDc3dGdXSWViNGlMVW9jZENUWXd5MVNheStiVU1adG5MNEpnNAotPiBfJWZ0eWtP | ||||
| LWdyZWFzZSA/VGRDTT5kSCB4QH05QF96eyAtfUpxQ1ggZU5FQEhZbGMKa2xDUlMw | ||||
| Wml2QldxcS96YXVJT0hPVStqelhmUEd4K2R3ZDM4Uk83MXV6VlVoKzRiMWhxVlJx | ||||
| Ykg4ZTJ6SSswTQpTdjYzUkhMWjFwblhzRWV4bFZOVnRjRGMveDFaUTJWM3diK3lj | ||||
| MUE3dFlhUEVENAotLS0gd2lKQ05PRUF1b1RzZEs0ckY0eFlPaFFBNHRQZ01rZzBV | ||||
| SW01L0VzUUpYSQrJxWuL6pjjZs+hCS0f6DTNwW6HSD33bUwdBpyTCLeLMyDT646H | ||||
| 4pjAhrVjVH1kgBFmuCjTP+SrD2bie/WhkQPSYrG7qygcmXbdNXlJn1tluEedDLzK | ||||
| djbOaSuohlgneGw9Z00Zkm8rz//2NSB89+WiWuT5/6Pm/d6763FteRI1LsPOyWx2 | ||||
| vmTZMIcuclmrGn611T1kKR87R5AkaZ6xyhkOrOvWrb7BktmA69Kd9r5fXyxnLRZD | ||||
| W6vPm4EJLo0b1a4DWlnIvFTy5I6e2fFT9h2+rU1qITn5fwQD5aAYdL8W8ELIEJ98 | ||||
| zYNxpbepHY5fBpHOGvOKM4AAO/R2pjaDaK7DRIFhSx/1RJLJvigXFd7YKl0WWn3w | ||||
| PGK/YxXnhtxnZngEPrnwf3JPj+zQ3RwKDx/v12s+KTbfQu6sGvw3MhDwYsFrRn+J | ||||
| T/jqlcZ/RodnxDngMnJCzc+YPkCJ/yAiot1DthVdpW0mWFiPsZvzN3co7t+6nopR | ||||
| WYnSjp5igjHbO/E3zXQ8qRlOvXSp6zspOIv9AETq49felAxXF7uz28lMnBeCReVq | ||||
| 4hzBII+wDTR1Y/itKcOGm5mTdyvLF4qKRZFJFiJ3ATGZDEYh2dCrO2juaL4VczCl | ||||
| +qwt9gYF+pOgY4ekOtW6BpvOGZ591LHTMWoP52O0MnZADU8GHkh66AvMDemQGumj | ||||
| 7qI6kI49Rwr5CoDMds5XlUBKlzeLgZLSo46FJghWOOQaiFiXWVQ+jYZpZPkgGjkU | ||||
| wDkrnbdglkdPO93bT2drkNbPWziHRkV505lGk1s4zCvsUPMH0D6KYkA6o/hCum4B | ||||
| IK8Sj215CmjQv5LYBwzHTNRusksXDu/+Ud5FpKCNw34aKblLIEPJNSk1BWLwyLzM | ||||
| oCNTiI490ZBh3vcnXpHZorS1Hxzb536SW03l0Z6q1Izn/vfzhZ7HbFY4qS9Qe+je | ||||
| Cvx+upRzt+mIQt8edbhrC1twfo/6whuvpT1HqGQDUr62+4zqVJ3lbccmXRX6uOAq | ||||
| sfK9if7qo0wkfWqa4RutO008ocVSKt0JjDOUpGHHP9Z95NRMyKJiOlv7dgVwWEid | ||||
| J8YMxexAgkmjByzwt1CBC7XizEHl09ZyjJrzN420NMRzaG3C6PY82cnKdbXNfEM2 | ||||
| 0dlN/xUTaOG1dAjdlgr2oMA5o0jFptr3hTFcoOQ/va1zkkNDHvfgjzri9HSID0bP | ||||
| kE0Akj6H9457cyo+xI+gD+2CtJW37TR/A7GLrzc+BDdDNZWtJz8t7oU0STL38h0d | ||||
| rfHgC8uFj7Ozh0nvsPbviwHCw6F+Z3lOT2qaFjzWKMuhnB8s3C//vmMFCfY2XglJ | ||||
| Tmcz+A== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
							
								
								
									
										14
									
								
								secrets/chatterbox/mautrix-instagram.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								secrets/chatterbox/mautrix-instagram.env.age
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBBTHhU | ||||
| TVdvcWhvb0c3NjlTT1JBWlRaRXBYSlFySFJhQVZHRUsxcTFVT1ZzCmVaZW1ucTRG | ||||
| MVN0VnZEWndlVS9iclNhRlB2dkZPT241dHRxcjBRc1BpVncKLT4gWDI1NTE5IGh1 | ||||
| aitYSmVudUZPS0FHbUliUjFCWXJaTWI1RzRlK1Q0ZlpQNmRwN0haemcKaHhQS1JO | ||||
| UVYxYUU1OTR0dXJhTm1EMGdER0hYUXVRd2VmNURwTEdVV09tVQotPiAnbHAtZ3Jl | ||||
| YXNlIH0gLCJ9IDwhIEB2QW0lfSkKMUJLd21ubDVQdWJOR1VvCi0tLSB3N2dJV2o1 | ||||
| WGF2TENYNE8vSzI2UzVPZW01RzRtK1VCaUVKemN1RzVhaGlvChPEVtylQsq+EWK4 | ||||
| X6HxFl3JY+M9clfpicNlSqUjPcB3roEMpD9BmGcG46nVSZVDguVjPzwTltAGE72Q | ||||
| Q4RP8/yhssA2rrLEuWz+JKcaASF/yEmu9QBILrWBIWz0rQyHfTRvBC9d83MdHS5f | ||||
| DQl1abC7Lv8imVm0pJ9vthvB56mXlGgm16fnsd/UhgMQSWZuVLSitaoDEFCz/LWi | ||||
| QAUKYTRVL2UcomgHsQqMx+2g3HT0RYQu1Ud3M5rT9eMSSqPG7IzyjNA3HmH5dw/4 | ||||
| EdnilIaW7c6k1RAYMFY270E6qlxqdQ== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
							
								
								
									
										15
									
								
								secrets/chatterbox/mautrix-messenger.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								secrets/chatterbox/mautrix-messenger.env.age
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,15 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB1QUhX | ||||
| dTlNY3h2SElIMytCTGlmY2syMmlTL1VMeDFnanN2UE9QK3RvRlUwCkVMM3ZKMU52 | ||||
| ZmIrZ1VxUDNWZm1lU2MrWnpkUzBLcDB5cUFCSXZmQ3RXR0UKLT4gWDI1NTE5IE5W | ||||
| cE5uSlpRd3dIRXEyRnpSZ0VHZ253OE1ZVTd1OTJQYkZVd1NRdnh2aE0KNTFTaHJM | ||||
| OE9tc0VkMHFHUGN2dFZVSGFBdTh5Tzk0TGU4SWwzYTBOb3FtdwotPiB9WnwtZ3Jl | ||||
| YXNlIHZVYHxaIEBSbmZ9XiAhfF52YCNwCld0K0RCTFlQamNLeitWM0kwUnVJdXFV | ||||
| QjNFcEYxWFBkVjJ3QlAwTGVvTE1GTkxCTEdDcmlZMC9xbUcrSHp2V3cKdzJLb011 | ||||
| aEM3a0V4eXBTMjhnCi0tLSBOWHozZTRjRldrOXBmM05BZ1lPRDYwaDFCcHBPNHhQ | ||||
| SzlaWGM2RXY1THI4Cj4RzG3G1yGkmDyqxCBciqMNPAQYge4mXOib7mqOuyIbkT+k | ||||
| qrJ8fLnW7Jbnb7+Rzr7BAEC5/dpOfjkyY9JPeg0FRutlkKyPIhRMAEhSsNvUFzXg | ||||
| uwNbnSBI+9Str6nTKI5c9IWT5eT/8zsKwtK1/pr39mApRY/y6NlA5X7ZRIFeku3K | ||||
| 6I/bCI5cT0qhIMJbF5D0KiCnMCnMdmRLrwLzM2zcJoisxRAvj4dNfLktsUQOauZ+ | ||||
| Gta96qQkAewvrdfz8Z4lTYJQmEqeOs1vTA6sAMf4iLp5EhPE0jN0n6D8v7Lq7+2b | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
							
								
								
									
										14
									
								
								secrets/chatterbox/mautrix-whatsapp.env.age
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										14
									
								
								secrets/chatterbox/mautrix-whatsapp.env.age
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,14 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBJbWVs | ||||
| bkt4a1RBaU14cjJzRm9KUGhydnZlWGU0NGVYK0NmWXRsclpjVUU0CmNiVDJTODFw | ||||
| TnloNW1LMUliVmlnUGt0SFFzWmxVTWxZQ3crNWVHVy9IL0EKLT4gWDI1NTE5IDcw | ||||
| TUQva3UxN3o1MXJ5QmVmQWVmeTFLejVwOVdQZks3a0dVQUJTdUdZdzgKajBFK2dX | ||||
| R1NNR3l5d010MnJGUktNWldwVjY2cDIwbU1laEMwOWJITEg0NAotPiBeLS1ncmVh | ||||
| c2UgJjhQIF0pcSB4Ci90SVhIZzRGVlcrd0hRCi0tLSBKdVgwZ0pidC93aEFscm9w | ||||
| Mm5GbEc3RDdZRDRpeTdONHpWN0xHYXkvVU5zCjjFfwumbetHbq8MKrBIx18YXmny | ||||
| z+0ifVbksJhYLYk7hViSUDy+F3RRad23dSPvDdd7JCEpj+2PvcezBLkwfUkFdQe7 | ||||
| uQhUJJ9c62oKSX7PMbQeW1tyX10SVkt/P20z6HPXvBlY715lsXspjZERi+DheZk0 | ||||
| ZDc3dPYMeyoAIWicf40ZxH8C6rWl5HOLIaTMbCOKwpD+wPjpzeZHat605YWReFxR | ||||
| Yd3cKCRqSb2QdAdtZ0XUDSPl7HVwkw0xobCsvtPzmObA3YbLopBq7Dvrvh7XW5ns | ||||
| BPlTaI8WnrI03CplGP00 | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
| @@ -1,13 +1,12 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB2WFY2 | ||||
| MzFnVFYvb0wzc3grRDBrUi9teW1tNmx5dVBIRVc5OUdlcjdvTDJFCmpJL2tlYXND | ||||
| bVJKbzd2S3JkSFVMdG40MS84V0lPTVJSNHVBQlNXSkN1eTAKLT4gWDI1NTE5IFBM | ||||
| ZGo3L2VlNUZqOEE1UHBuMHdqc1pyYlQ3R29ucE9pajU0bHMzamlXRDAKcG1Qdmw2 | ||||
| cUlncDFWNXBOWnpIeDNZSFA3d1E1bjNaVVpKU3lMRjRaSHNtMAotPiB2XUh8eF4t | ||||
| Z3JlYXNlICUrO0cxIH4gaTRoIF81SEpTN0Q5CnpWdEZpb1hZa2t5YkE5RnJFMHVZ | ||||
| WkhkQ2o0eWtyOE9ueDJkeGd2aUhmLzRUUGs1aUc1NURIOTYxczZhOEVmT0EKd2xk | ||||
| TXFHN051d25PQmtNUVZkVEFGUVliZjdmZDF3RWFkaEhNTzd3ZVd5N3dlNzQKLS0t | ||||
| IGZDR1Mxd24zOW05bitzQnN5WWVOOGtCNEc5aXIraEF4eXFUQm5CZUdCV2MKd44C | ||||
| /Trgg0OEZ89/jqbj56z/Hia1Ka3ZsEv6bXPI/kcRvFDBFTgtvG3KWCgMBtTUHXzY | ||||
| TKBPoQqrUf7plH7a/mTx3KR+4Y+yF+1i86s7TzYjD8d1xfFH3BsVtg== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USAwa1k3 | ||||
| S3dka3ZjcVdIQ2hSN0xsb0hTNEhneXFYS3BXNWZDVlBNc2toQ25vCldqSlMrT0hB | ||||
| Rkg2aDZUYlY4U1E4Y2djMVdwT1VsbGdpUm12Z3gzditmMncKLT4gWDI1NTE5IG13 | ||||
| YXF4WWdmNFRPR1JDWkk4OFZkSjdzRS9BbXVzSC9YNG5FRnpqUXJZVk0KV0tOSG9N | ||||
| c2VVWE10WkxUZXpqZjBZZUQyWE14TUFsdStMeWVlcFdJaTRVUQotPiBWaHxWdCYt | ||||
| Z3JlYXNlIDYgdDsgcW97Ii5yIE95Clhqa3RVUmJENngwTDNoR3BCNjlaTkVYc2JR | ||||
| ZWQwb2FOVy9sc2d5MmtkeUhkajJBOFE3TWJTOWViWVlJSTkxWQotLS0gN01aNGdm | ||||
| VjR0ai96VzRqb3QzYU4yRzVCby8ycVhXVlpubVptam5mYldoOAoZnbsXB5we9BQ5 | ||||
| AXQ08mXmMxRMg9iH7qgyCVc1ywR/uo5Fcefhuw23TyluRkYt7tZ9yiuFJIx5Znsr | ||||
| QEqaBioL1UfePVyDLi8LcBvUgnnx5uN05hUvTOt6gqaE | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,30 +1,28 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBuQjBY | ||||
| K1ZTUzR0SmFoYUZLdzUzNUt2M1B4RFdPZzFkcW8rMWJLUjVHOUN3Cjd3ZHdMSzdp | ||||
| OWswditVWUhYNjZCdjV6M1d6U3pNak5hUlZjTHNqSkZPSk0KLT4gWDI1NTE5IGNG | ||||
| ZytHazJQWTExMjNkZWV2aDUwcnZjUGcwcXRkZWl0M0F2R2JpUVlJekUKWTFlbkEz | ||||
| YlN6dkgrMmFFcmlZMjQ0b2oySjlEMC85cUF5QlA4NGF3blBKRQotPiA8M1hbWS1n | ||||
| cmVhc2UgOmlZJFYmJgo3UExzUHhSVi9lbVRjNW4xTnVaUTVGSGVDNzRUNlJ2TnVu | ||||
| U0wrWU5kd3dyR2phcUNVUHJCYjdzeWhjNVFOV011CmZMOVN0WDk5eUg3ajhwbStQ | ||||
| aHExT0EwblpreTBXVHh6Zk1HRkhzcmFQNnoyVUlaeStMUkgKLS0tIG1aY3Zadko3 | ||||
| V3pDMGswSDZCeit4SVhSRCsrZVRVZVkvQkNsQWN1MXFMUGcKcK74YULWqWw9VvkI | ||||
| NH38VHfDPW5ueSiyHHKn8MI9YosPr/TmkwgKd/DOIMVB74ahPalo1QUeg+eaBVnq | ||||
| Uncsbx5ecW3JswthkAhiktWHcdHmioGD6hCcgbWtfA3VvbAYc2gtAF2plfDVH6BD | ||||
| c8veai3B15ZmDmq3b62sgVA9JUgbFaB1eRqcaPXmNgQJR4c8J+CZWXGQ/TKMqtAg | ||||
| chCDuczjLX8IxhMPF1gdCggSt5GtMhY47fpZJRbBUw01l8koqjm63KvEeg2ejFGU | ||||
| +tXonI4jm2JUxlDTqmNSrVpmAgtPoEPszHc+GsnyNjAz4IXMm5UrQAZyDPgxtwQW | ||||
| ZAn0IdOB8rSL/AnRGUpPrecuauINQjONe8CapijjJPQK7g1AHscfxr+OJD1j2eV3 | ||||
| O6TNlz8vKW4t/V7CUf46ykxxExhA0mKJ53ksaXy2+HWoro2+c4nao/bEld5gt08U | ||||
| uCpJtjPKB64X6vdzbY21/l87VRDyxbb3poENfrXlawqS0Z7i2gAbHN5EuiMv+35o | ||||
| sBaR0BfcbTn6VagC3i8HEEOO964FrW65pkqmGJcJMgUdcZSl+Y7gHMjWyodqGPOY | ||||
| evT6xj4iyeM49vXynV2vrJRu5rr02hOS/8rPphV9c9q9ju5n8xbhS6IiybAelPwt | ||||
| sa+xM+w0n+fxVksiXeFj7qD1LDN4+kwqhYP9SlzbA4fT3AkYYrxthTww4IFAweyQ | ||||
| IJkpVL0/IZEIEfRzpr0lWLprAaoyPc64pecl0z/gBJDgz1kSG6iEh6K4qx7ahGde | ||||
| kBBpS2I2ZsdBkvmQxDSM7tYYBzPxcUNZlSFOIeUy3Xl+OGPlKgtMofbnjV8AFqUf | ||||
| tOpgKpLUEkTgXbGUKBxHLj+8pbw7zOFp4sJ00i48ZzLP5D9jom+jS19wGshRc7cH | ||||
| dK92CctvrfndQ85yO0vqlyOdMTqjh/z3P2KmhL5SW6P51q5mseTvj7FNM7331DTs | ||||
| rq7XWaBLE61eWWQ/dZKnqh5YbkSlU1+08Rl6H/vCU5hTC8fht3KTQSWPofkrP+5f | ||||
| We/Pe62LyhV/MbLRA0nmU7Sf4IAnpHfa4kLtlYeB3xiqKd0McM//qzjuk5NoIgE4 | ||||
| nL0T8YXdGt8K01w+nt+j5bo5gFoRz5+1/ZZ9BgN2DOo4SClYnJWQ/x80X061yJ33 | ||||
| 0SGv4eAC3vFi6xE= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBvdjZT | ||||
| WWFyNzdXVENweXlVT1kxNElaUDFUSG1DSGMybTZlN3VKVDNNMGdBCklDRk9oaXdT | ||||
| MEhrR1VTcGE2NWwzdW9NQklwcGFsd1BWSXBpa1YzREdTUUUKLT4gWDI1NTE5IFN4 | ||||
| Nlg1OXFNMjVzbDlRME01WW5iMTZvU05hUTExNnB4MFpUQ1QreXFXbmMKb3BzamRT | ||||
| OVM0TWZIdkJnYlByRjRQUXNtQWtXS1FXRVlFTkpSNHFVTWV3OAotPiBpQy1ncmVh | ||||
| c2UgJT9RYi1YewpadEZzVUpqc3F4U09zUQotLS0gWkg5ZWlxYUJGMUVDd2o0TTJT | ||||
| OTk0WlJ2aE96Z3FGNmQrNEx6Z3N5UkRxbwrp1nF8mtgoTEYfQ/aE7KgzFOei1PVt | ||||
| cLAh3v7wo7C3lxhBOL0v8ToIAVgSoGP6cj9/4k7+9GngpOgot0IOdoXsThVdcg7w | ||||
| soDjArsSWDYn6Th0yZf+trSXfA24BKIS5qQnAMT2ivQQtO9Kqxko2Zj6+wZO4LEj | ||||
| DEr7cqRCWVFfvPLJurkfbCRjGlW2rKMlJotnLMYTE+Ot5SlSwVic5Nu3inGx1U/a | ||||
| gKjCPfWw1h0Gus6PKXpSq8wGrGp+ov4ocpDmumbgh/E0D82JtBBPoWojxuGSFzrm | ||||
| UDKrgx7MObGbjwkj5Xd+SDdKytjNqV+9g8GdRYVGhIr3muLn2JJlKKw/eD4Now86 | ||||
| tPB3ms/E1N0HR/LoQ/Y65WeuHKgv55CZMWauC/1ECxVS/jDAXnQ2lAqFlzmU1ItQ | ||||
| 4EefV7FRWxgMeMOIVKOCus03Js4yZp+5byjJ7+O3MRrOED9/M60B60zXhvPDtwb3 | ||||
| D5sFtC0ZBZT1+d4pUnEnLzSjM8DTf9as1uoNSuzh6ASiSiepAhdKMNtS8xzo85bf | ||||
| Yw2WxiXQfSyN2xWWjSH/YQUXKZRBNATxB0FRMaa1TOFKo0dDYOAu83bY7wwAwSvZ | ||||
| zCZ1QepCCjiWe7ujd9HMPWDgnvd47c8teSYgjX0T4nCEk7EbNpUcrDXcz78ZKAlm | ||||
| VNuu8C5oi5Lk7972SBLj6yLpj27FDMagSvX30k1sMoHcKGiKnkSkdw56B+yHwLYL | ||||
| Iic2mxklXggIYLo1gNq0tQskp/I0dFGUzAF1AblLw0b9Gqj/fHwHtkx/Q5n+NE82 | ||||
| jSVVRTI444cMlXKnyk2sVKKOWR60WXQWs/GdH5Oln42tmFT6yZk8OV7RopLPUXx2 | ||||
| 4jwwWvVOrAMhmTwJDbzUwEIm/nfay7wzJinjNod67u0muq79OP9k0pRB6u3mSYZ4 | ||||
| ZX3RhRoIYiYHCDrw0e8eWKjlhzaA7tI+diHdC62SR1cUbYbRrLiXrU+ZPjG2qDTI | ||||
| eAI8/wUMSHNyXdBejLRZHy7l38LKzAG3SSWBtNuCpAiP/QWCFL4UyEMlQ3Fmmzp/ | ||||
| FDgNLldzhOMDK8eqGAgG+qVRaK+30SJc2/ydjilg2H/KxK8C4F7Q+ul3QV+p66KF | ||||
| D0h1JpWxSRhK5St01FdtFigSsA2QBg4kP87gGFmI/y05jbj/XjG7D3BQtBbRnKVG | ||||
| uQ== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,16 +1,16 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USA3MEFh | ||||
| YURySHY5RjVQa1c0QmMvTkZtZElNd1BIeDFpR1U1YXZ5dndnclUwClA2M0ZYMk90 | ||||
| RmlCZHVISkxZQTZXeEhZVUROSVRGRVg4TmZKZytSL05FcTgKLT4gWDI1NTE5IFY2 | ||||
| V2k3S0VQdGlQZ0hkU2ZoSWdOUG9rQ0p5Ukg3ZHU3MXVvNHlWYVN5VVUKcWtoWDJh | ||||
| LzRwcktWUGQ1bnJvRzVBVlpHU3NhdzYwUDBPTmx3MFNrdWNQYwotPiBKQil6Km0t | ||||
| Z3JlYXNlIFdlRTlUU2cgVlxLIzUgJlVyQiJ8Cng3NzF2b3d6MnlEdURQWHgrSFJv | ||||
| Y1BMUkZyelJSdDJvUUUwY1k5R3ZBMnJaa1R4NWxlUll2azNseW5MQlpvVWUKYUdN | ||||
| d1ZscXVxd1dxSGpzMjBYeWhhYyt5ZlNkSjhmV1ZTTDBTCi0tLSBBTG45VUJOSXZv | ||||
| N3lYNVlyZldMVkpZdUMvS21NdSswVmU3VThZK2M2eis4CjwfWWJVR9Ty5dBXEr5s | ||||
| U+QrifXvyMJJvqOKEfMYYomFLpt/VtbDAUwNlqLnFIk1VZ2xPUBisXPtReiCK3gq | ||||
| P+i6bUONSmPYvmF82VgiuKDuz/kmWqVGg2iSBPIXAGLNIEojndQwmhnrsN9ex4Xy | ||||
| lBHkvVsN8EamUJwZ+FEZe4+PjA5yEnANWpeTELOt2gA92/jwwnNIsr07eVTlkh8X | ||||
| UmQ2owGwktXP7it6//NV3C7sAdazs2bX65WSnog2E8WPNAorKWI8RCYs33CshVFt | ||||
| zzclZ4hRmlAmqMHYqFY= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBQMEJB | ||||
| VVhIL2ViVUx1Ym9IbFV1UW52NjZYMmJlYmpjY0RuMzhiclJVS0ZnCkY5dEZHTHlC | ||||
| K29uamorWWNJSVV0VlVJNG1VNm9GQ3VPdldJRDNSODVoOVUKLT4gWDI1NTE5IEM0 | ||||
| UVQvLzFYRTRRMldWSnNnd3V3aXJTeS8vZ1hkdENYVHk1QVVaQVEyQnMKVmN4OUFH | ||||
| WCtVSW9tREV5RExycnFJejk5UW91dzd5Rm8vcFBTT0ZCdytFWQotPiBCPC0lLTJW | ||||
| LS1ncmVhc2UgRSBjOlg5a0pdQSBSb2YKN0pkalY4VlFDMm8vZzJpQUV4TmdSRHA2 | ||||
| dnB4UzJaWTRXeDdmKzFrUGVMSEFlbFhlNFFycFRQU005d1I2Si9VUQpHbDVxcGxn | ||||
| SVdjZzduSGluYlZnY3lmZmtnOWJYKzkydDhKU0VCNmNvV0EKLS0tIGdaUkpGNy9P | ||||
| Y3BGVGVJenJkTG51c3Z3WFU0eTFXT09pSVFseGRLMmxJVU0KhH9EjbL0zv821Yox | ||||
| FXc54SXGEkq97qPi3xIoPydWd3FbIuftAhe0xPFGfUOO5/zDni4h+PoNJs2hnkOK | ||||
| kHhxtaOj1S6RulI/eYLK/fJjl2aRrTaRFN0TGhFwz5X8HOQe2+Qrq/9wT7pyzOFU | ||||
| LsMwe71OhTjA5XrBTawU9QkWjPx2LZyb/WEkzlLOCGoHTUm4X03xY/1UeHVYZt2k | ||||
| wbLses0JHK1h2ttWnO5y68LovZWJqFdIjoCCkgfo0nNUD5i+e51xEju9OBJMngj+ | ||||
| LnPb6YCqFh4Fxy09WORD0A== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,11 +1,13 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBoYlRq | ||||
| ckk2c21uMVZSR05SdlJpck5MT0FZeUpLTmpTRVN2WDkxWWxmVTBvCjlHZWtEQ2Jh | ||||
| YUdybjJLWkNsZkxabTVIR0JnMno5YlMvVmhodDU1bktrSzgKLT4gWDI1NTE5IFZT | ||||
| Um9lWXhqRFFLTWdNaTR3Sm1acmY4N0l6WE1FSW54ZEtQcEE5RHBRRHcKcE5KYmp1 | ||||
| WVdCVk0wMHZ2SCtUR0xKWU10N0xETXlXZmgxcmZZOFBXYWtBawotPiBlRm1gKGxU | ||||
| LWdyZWFzZSAqXF8gOkU8Tm96IGA4IC1TCjY3NUgKLS0tIDhjaTNrbG1iQ05iTWRS | ||||
| UzIvNzA5TmVGS2ozZmYrYjlBY3J4Z1RRUGRNeWcKUTIEhWqr0fOODu86MDll7k3U | ||||
| ThgmS9nlcUY3fMgXzZLtpHIJ/4ZSI+miu8RmLMaeC61qv6xNThGdx+MvU4tMBWKA | ||||
| Hv3XGi2MYL1jdHh2KYg5PgdqchYuHrFuBPS7c/tQow== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBmSkJo | ||||
| UzFYMVBiNTRBbnliRHh1OXBpME05dUpyYjg1ZVY4WStxRXg4VTF3CkpGQ0Fia1Ew | ||||
| RnBsLzNJZEZMaER0emt2TFVSWHBGcEo5MnYzVDlvOEFrUVkKLT4gWDI1NTE5IHh3 | ||||
| UC80K1piWEdneVExSmQydHRqMFdTL1djd24wL2pDNFc3bjNxc3hZekkKTlI3Umh1 | ||||
| SmdBM0Ziak5GRm12K0pMckZ3UGZXZTNPMm5hZ3lTV0NFVlYwMAotPiBHLWdyZWFz | ||||
| ZSBddkFIRWdHIyBjOXwkT3MgJiBOcUkqRwp6VUMva2JWd0J5ZjBpemFFM2djTzNC | ||||
| RW5POHIzOUZFOG1zRElPMkZZZUxmbklpY1V2R3lqNUtOYnFlSUVMZXlrCnB6REdz | ||||
| ZHFzbmRjMm5mM0RGU3NzeUl2bHBhTEx5MjhXRTJBLzJZRWgyUQotLS0gV1VlUkRD | ||||
| N1ZTZnMwTWN5SXEvQnJaK1NmcEUzMEJ6UVcvb2ptK3VYZU5zNAqgntLnLkQABERv | ||||
| HpNr21t8+KR56PZ8nQS8xALzw/FzdexGvlt4Pzx6o0daBeh4aZx4mgcyG641PsRc | ||||
| eDs4tJm8gmznr6y7B+WNC6WGrWPPIC3pHKU4g9PWzyEZcTEpL8Fp | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,82 +1,80 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBZVkFh | ||||
| RDNNZCtySlNQTTZFbzJvZmF2TEZKVUM5VjFjQWNSeHlNc1JNZ2hNClVac2pEdWdw | ||||
| OVpOTmhWWklVRDA3UzZWWk9QVG1ySUFmTzRSVlFReVdFVFEKLT4gWDI1NTE5IDVD | ||||
| eWN2S29aWVNVTTdldXFxZG1vWUNYK2RrajI0OGNGaklzdFByTzlPUkUKTmsvdTE3 | ||||
| ZFBvalZsdENxR0VnV3FVSnFxTitBRlFWR1BzcjJWd1h0U3hpYwotPiAyOkUlJC1n | ||||
| cmVhc2UgIWFOMiogVDc8IFZETk9BSDVTIHEKQ01rc1ZoNXQxUDdtWGRQUlRCV3k1 | ||||
| djNZeEtOaUl6Tkl5TDA1S2ZXWTFQZEFiV2pWMDJpZ2dkYXdBOGhSTVA2ego4UnBz | ||||
| ZGhXcklMd0NVWlhsc0Voem1wUzMyREViUllCRAotLS0gMU5GQjdJaVdlUFJGMG82 | ||||
| YnZCUm05ak9qcmVyUVJSS0tHaWRRTld3ZkNPMArRgojrBQvlyjMhChn8jgUNDysj | ||||
| 9Nh3BVqf44fiUNMKARTrFTz3wVMlioo6MmKRzJ/yj0fWkZ2h80X68Nq3rQvy+0UK | ||||
| 4PNPRbwY5ib0nf7n3itFKjehrYr8HnOjreQps4it52bT5re2TWIC9ogZhNKBLRvB | ||||
| qv14HjcF5bGnia8TgSU/8nUZJuIaLwHvS5sc9GOtmV4lDwiSTEJQEtGh716Jzuvs | ||||
| XxQLPEVVufAjZUKLp+jWUhXGkvUEeY5bxE2aOLuB8kLfHPC/5p2rl/n2sW3oEDFn | ||||
| Fw+XcNnCHWBzk3DlzKZFXwIaZL6Ocqrt+p8CBpWoNhbssuKyOtEbWQOmJxX3UPMt | ||||
| sBFNdKSKFhoBQ4ukqkKDhgcm0i+8wG4eBbNIMIDwzPBxK0QiVriwlPQHl7RS2M/J | ||||
| LgGeS7qrKC3SgmLu57CdUVUlnogJ4oOg7FPh6x+jQBIIv7gtYCzJb040TUZWZWvi | ||||
| cfKWBBwLqLa+7Y6kEhcosLUgw2c9Et5P4rvNjU598q7qrZq7uK6Mr+PMwD3Pd66O | ||||
| SQyT4nYhhXBnaIsLXZfima2nRzPocaBmfsuXQwlnLJC8JB6yzqEViK0xYKfl0fIi | ||||
| jxuYBw/8Y+MWQhIkF1pP8z+Kw51QdK4CIV33mlLBJnGjlizewsjj04EIgpzQ0+3I | ||||
| ZRyee/SzFmGBBk/pMGN0DizA8LS9yZ9DRGrc13rYVUTN6G5xT5AT1eEtFbQ6DH/n | ||||
| q13Tur4QJ8AqJmwv1cnX+faH61dXahfbinveXWqB5S95/HE3OGnZfAiS5bs1jW4U | ||||
| D3BLaBiFMYD+ccPedg5MLXRgEryVaOWlQ5wuXxqmaCG0KS6YLxl8o0bRR3lKXNZP | ||||
| B7Ye0Px69aYtOs58dTOq0Peu039Fi5iNC0beocdKOjig4tZ6p41uz0jPGMUoDebZ | ||||
| MYHax+a7Qpi5M6ZVGVpF1ieW2hqnm0lfb18cEYHuXjoI/YlgVhFPCGSzHJpuNiDU | ||||
| qJSfOuD8HUB2iXFeEgAi+V3EKTsyjlS+R1zWxkr2awqAk7Uf3svLGWZNINHNoJRe | ||||
| CPPANHzTSHlNPSelQ1CyOhl0W/eMCEJuJ9/6kZsmUC3zvzxEMGofG+Ub9RRBW/+/ | ||||
| TkrVvMrQv7/Va/4dxMPCqrdOQ+3/LkVzGX7qg6tQR76Su0q7aqh38Ki9qWY47bTm | ||||
| lq5I2EcQApt/O1cGQJTFowdXVJXx/qQv436p/jL1mymQ8241iQ6XX3DUjbnqdI33 | ||||
| 4XcPa/B7naRkgSG1Z55Vv+IIBOzcjzUMzeQVP/WM3SFRNYT79mJnV0SsKvUFtUOM | ||||
| 1OxMGEx+ZxfNIZqdp+qo0+uIU00ciokldh4URo9u8EIHjFVcV3Eyb7EbbCxzDiU9 | ||||
| iwoAAaJjwBlyaRQFWYsKhY2J3NEay142WAyAiHmnNBNhZM9TKkCpjton4ehxeRUC | ||||
| hoXpzh4J2lMhdcmXXZ675C3MYiLDpajgLS1dwRp+mAUXwjvQG5rmJd7UWdgpbdpJ | ||||
| K6wABNkl601XgKv3/nV9touE0KQjHg1fzo9vzmf8zVEViTgXxH3NECZHctObwgoo | ||||
| SlbUOW8vihCi2HU9G3tqH7dwkUsgB2a22JFovgwwW8ePKJQpdvwAV/jyFMLL6jyj | ||||
| 6Tf0Gsc/Iut6Mh5TYiTWJdCzvEBjcybOVnppj2zR32/A/vAXUrJQaq0kwKkCwG+e | ||||
| TL0hAQuA2Su27qTR9Xy2QKpQ5NppRH7V9YxCpjGfcLbcCh7XH7AEZaYfrrX8NoP5 | ||||
| zPalFA+7E1IuDRtT29wFNRVb3lAet9t5q0LUHf3x+Qk23dQ7Mdq2JIf9RIo5xZ6X | ||||
| nsKa9eBQ0O5OAv1VGWVvbrVCMpmyiklYV2rcIT+dbrhrgiTu/BvODSvtmeANIkhC | ||||
| uF112/+QW1UNPCENioYq9OWPcEwby+s9JkQf5nTub2o/0lTFKJxNgXa1QBcKKVyC | ||||
| 9aTCRhcxXsfuR7YzbCXRcK2hUW203iS8+UgAfZBVe5GhskOd0ZR0WSkse+jGzPqI | ||||
| tnH5F0yQgLn9emebpL6dNFUVvssjpiMlvkijXFJv1tWSKLb3TxJd2BE/w5Zj7Haz | ||||
| iv7Wz6o5+bY4v2YL2Ev7hGzfSaef+ip7/BYZ9TGuzSoZEHMYa7dNT8kRR18IhfXv | ||||
| Y3wa2xlOhB+WE3AjtYy1oTi2c6Vmd9UKASZy/Eb++j1MSPtxZQLNaj+svCmqqfvO | ||||
| /gElVfGlgkomYwc2EfJvR1lt9u9YGepxKrafPsgvjR6bYPwLF7eHKkKyEiqGCYnW | ||||
| mcNJz/B0egxhFjoGd0U17tNuZcYRD/Tsj9ugGF+4/q+IaEV2YzZTdGzupI3lW17o | ||||
| Q4H+EksxkWYDr0WRlYKn7VT1gTThuggEz77JskjNP4jK29EOIEO9IqGMh39tXsud | ||||
| mhL2Z6XMX6sgxSjSkYxLpFnS1mRZ6uQnSptxHTfnG6jYhq//MTjGX7xmYBj5EoTC | ||||
| duHuaCqjRXc3yHWoNm8jepkpbe1PPbwEbL6RDK16G3g0WVREjZopj+66C2xlY8Bq | ||||
| ZCmHhud22QHs+5r1LLSIynsUlGIOvq30DZ0F2/f9Gm7uayIYbp8gA4z7M7RjmHoZ | ||||
| +XHYSPc4kH4a3T9MucQQGzJMl1k/bifBAWLbu9uPcDUe7Cglfz0wHnPemOu8HZXY | ||||
| 6qS1n6PAHyyGlqX/pNWxR2vQrHJRksdTCvjl4g6256PhaMDop3QAHuQj9meYKIqP | ||||
| MiZexiuOW3KjPJ30Gx1Q7PnUc+w3SjjsKaZEvRgeWKa37rvj1ICTnBQUPq2HV6y8 | ||||
| zaGnJcfd0ENAmFnRaCIbdU6TRonnIAAuSfE2gtLni/PJbmUpznuq82W//kxvH1tR | ||||
| oPx6LuM2+hRncMoyXUTWSUVO1DAUPXgZA+j7fkkwmosi14d/5xe3wO4U3dGZ6wAY | ||||
| D+zlzhq4d/4vIvLIL0NoBcp8yM+xWxPTtvj7HUJ7BOVV06ICnilUlv2wjR+dZLZK | ||||
| DyjWhMoqk8r2TDZbAQr8MNX+sSlp1JxQEgBijpqBvRdF/ulqraF/GFDFRLcEi7D+ | ||||
| AkHPg4TrmaNB5ixsj72j0xruFJxgQJGj8fwQtemJGu8QcuJbCvJ74TI3vu0Pac/C | ||||
| MRov1TAVJB7+iVvVNEgCMlzimJCSCUYh1Zgk5Ci2CDFMFRAEcGoHywIW6v5V8j5o | ||||
| v30mJKZCVFc4Yibivjj1aGhQVO72vgiog4L++i7CeXHIu6Fe1Jmlve5iuxrQA2aM | ||||
| 9vjCbFJIi8k5vQTVcKPRcsto7/qbyxvWvahKBBbHl53XnSb0WtLUyTEaXJ+0l5gy | ||||
| Epxfl6ZRNkt+YBYBqCZL9aK6TNpCR+zTC7OhrKcZntqFYCeRB25YEfc1z0lTH4SE | ||||
| TPymGSMOeUX8YEIr+XNYG0H/I7ZtEdNGBEXaUrC4YUNrvojpq3PS9bhfLhAf5D11 | ||||
| wmI2tS9cqxAuS2zkaBr9Qo5xNEVsyGNFd1K0q0JJosiMnVZDzOA4wJTYhOw5gwcW | ||||
| T1Kh/LDvK4RE0CV0jRqN81YO8V6Jq+/c2kgtwTLzrx1GCcdHRsY2kPhCEWOTLKb8 | ||||
| Jn5nyyvOOjMIkAEYYqoRRxl05UbNWNS9SuO2g9HF6JpNJmw0cmzT8erIIjVvaUs5 | ||||
| dd0Bd5EgkkLq3RMPNTiidQCyIy8QtoElmxYfM11mbf+JMgxsB3sDcRGN4lauUhho | ||||
| JlayuFUfrQEwtHFwyULiJwUC55faVqOQzyvcQ8C9AJezDXS7//ku1kvEgbzK0nFm | ||||
| 3bCCiuog7pG9XlldSReYvlJtnqTmp6E5+m9YaP+yB2E+swKBORHkbCfBu1CuX6R+ | ||||
| aryBYIDeLaIiJs5GWJN//37TT0hVUCipY9QISfTiZ5tIy0aNKRu9syjWphcoTJuv | ||||
| YBaRxKNdZs81ppFTa3sXB824+QXwzRJJPjBndXOtyX/a2U68NK3dqau/A5190VAn | ||||
| bn7jnJ68rhcL9ewwydQRm72qwyxBbRHFXnEXpkJhzYRw6fosglqbOJMxFiy36HWD | ||||
| RkVluvTInw8Em/DhhWgn+UrxLlQN6JnVdpkT9hwrlFWooiM56UKAPO2a1FM2XKXe | ||||
| TqsolY07uWnA+ouiljqIpsaFlVDBcz/sGZWqy4aKKPBTcZlreW88PMsS0c9nixVi | ||||
| nKnmI00HuzeL85zVHGo0IKYfktVVjuZNPzJ6+w18XpKIi8TxHpxELC9M2kVOCnuy | ||||
| uwuntJlRty+GpXVvx2VLi1wBKyLpXUxhyg1tSi2sZyjIdVt4yEOKfajZYOp73JZx | ||||
| IcInD7Cby9olkMsa25YhloljY8YELfW8EWutF13m8tsjGP9c6aOuMIXhrrpwLgYy | ||||
| E27iFh9tHq0mjCMibwQnHld7Ccd4OqO4AKfPofHDxWoY9+ivArOBAXjsCxhxWWWp | ||||
| aLqLJz+JH+idcsVDlw8jJzFW6pQFbM3VxXObvCg9ou5+P+Pc5XYyALJzIlmoOrN+ | ||||
| ns5Z+U/2XKGyySQASUyFXUNml6csSrTd+ejz1QvEX9POU1nLmvS1+aojgnptgdpn | ||||
| sAtksQHMt1Njo1oRug3+/0iC6XWEig== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBtVUdX | ||||
| WWlWOU5Pck0zSWFETUhMZVI5bjNUUk9pc0dRVC83TEJIN0V6aHlBCjJvWkxSaGNq | ||||
| WmxJSEhFekRLSE56K0pDTkxNRlJhOGZTWC9RdEZ4ZGJQNkkKLT4gWDI1NTE5IHNy | ||||
| S2lZdjFYM1M0dksvZlZ1NkFENkhLdHFRVm1rM3B2YmJ3REZEa3poUk0KSURPMW9F | ||||
| T0pWVHh5MnBjNThRcE9WY0E0Z3JtMko4eDFiS1k4L2RBa2wxNAotPiBgWn4tZ3Jl | ||||
| YXNlIFdRamBzSyBlP1wKSHpqbmFWZGpJbkhyRENTZlZtdFgKLS0tIENud0RDdjRt | ||||
| bFhpbVhQbkxXZXJRSHpDZWovUEowUWJxaUkwNGN2aVU3ZVUKlXMwhyxmFiFHHHDQ | ||||
| FDtswK4HmApIhnW3TORhJyKIG6WBKFE1wDN5cDLppbjLdWAZecQbw0Qe8UQP50CM | ||||
| iSZOYSSpS4J6jo2kFCIQELXjXMi7YhmkIa+Svz7kcr+vVROOikBdTr37ZOXp51Dy | ||||
| O+Ygl8rPaDkTV1elWCgwX/Y5KM9wvS/OEVBSKyc5vz83i0lsHMTOgb0QxMrqiAUC | ||||
| cmYk7crzAXmKU8VeKw97dA0ZOrzdEh80M9JVpc6k3ydliXUO1b3seKlocB5cAtnE | ||||
| 9OcsJV2byI0dOvRp9IZLHv3EsHw3sa5MFlw60KBHYZE1NoN2Uo5EqBc/Iz/4T2Do | ||||
| zpQ5YwK8d2fK1tMU/FH/RWxkCXOjiShKsJXSiccHkzXskHU4uP1Y7s+KtFYxAttD | ||||
| IusDOGuvKKpRuYMjRQYSm6ZHDAZc9yZsPqlKmhYg7IWlCd9lTk8p4mGoAe5b37f4 | ||||
| JwACx8asE3lZjNLo+1cwdjhARG535qmOt4i+e0t0x5XoUkenWhbq3Nr2x9fkzt0I | ||||
| 4S0l5IxnxXXO9Flc7g0E+9HNZXTixG7UvhTcLH0BcK2C9CZq8WQmYdLXcbQBJdq9 | ||||
| yfLKzEBdbzPT0qjMw7hua0ceBwc6SF4gzkRVwhSw2kVERPhto15Flr0ybpDIF+tI | ||||
| irSwhTwi9BKJn8XpzgErS9K/Y5Zd7GENY3BdZNzHH37VXK/cEyjWXYmW4sAL0QzQ | ||||
| BA/wujUhOjHrdYKb3QdVZJnym6ErOqzrg5EJ6eXI6nFLWer+2xDRouaXJsQplcyy | ||||
| 5Hr+L/K84/1+s+0ecNqm2XCjgCge/9dFM8Xvb+cBo/yOL5J8Nynv55WfUb3sjVel | ||||
| pTXH33APtzX4wdqsZ3KlB+OgjW9fc4vI+rWyT+Ia1ZxfP3Q6sgznspaIM1BHRW3S | ||||
| ZKTsH1wkSQKmLMZSUCNzpCmKY2bvZMQY4i8VP0GKbEqGjItknCPp4KM15QTOWgap | ||||
| 08T3+WX1uBaHITZKIOIbKfAUd3QAoKvHQBRZalhA+0+Rlq3tu/cEcsgyMnKppCuM | ||||
| my41LOgtjtGi3IRnKYDsVnvu72KsbWzBBn0d/J2ZejwLoAECJN5OaLpIpWCCwody | ||||
| bHWkCYF8eymXncuTbtF0EcGeu+sl+YaATwkEHmPC0Dy6S49BCCfWMK512JE+7WfV | ||||
| pxI2VZ2ncr8te4ki4iZPIncx0uYGTt7Q5WoMoBlave5AemYKr7MgAK9sZx+3VP0V | ||||
| CXcLzQ9GznWxj30U5cro578/3DbvTRrvgD9kifTQZPDhLliqgc0Eiee+2O3LMVuS | ||||
| GBjeyUcIjF2tQ7C6AeZ/qjNZTQK6/zIjd6jwVwO8UDoxLZV4w8rCNEdu7zMUMYYy | ||||
| nhLbrdAcNgBnDT2XRT+JXXZZ2YJmJFczd7tHPpmP8mAPXiypu+VSc4M+a/A+dGyo | ||||
| K8r2p47L6dNbMnJG/lke9V3NbK+5Cqg07KNkBEbFq9e9i3RyEs4KSq9SqqRGKYKt | ||||
| uQ7wRu0u3O7vMsw8gagpSRXeVaEtxJTq2eA6eJWCj6l6ceZ+/nlNPMXudvbD1JlD | ||||
| rt397ucz5ih5NpRFzTWG4iT91hXvZO5yhctCxBlmhLgsfoz9TK90fnmkeWMr/i76 | ||||
| cU+F+v1wYwiZ275occmyR3LxFBT2d8Isz4BbC/yFJ+afTMbAGM+WbUHeYSA/Pq7A | ||||
| YgEhFSLULlM3ChmHm1otOMyyv6bbos5SvtegUtHewWZSx54ETN80kW9bsUBZgY9w | ||||
| XIOG3vW6dFVjpJpAGwcDG2XJpKs31F4eLnX0zq1PJXdp1UYo0H98U/CdP7OCfdT/ | ||||
| AY6eKzdhEMTxEaWAfZvTdbX8p9shoVu1K5TEjQNTHTsIKoVnLbpjq5/iAwn30GIQ | ||||
| dQVBDsU2wTTsdi3HZKEqwbGW/iwqZEhfeTgIv0P5VgcnUa5uQvApxud0y+qf4M1A | ||||
| t6IOfzM7toUNsUGL/PQD7LcpJLwdKjFKPrQl4GyIplQCB1+bIU6JyE9Rr6hfeOTG | ||||
| pbbX1J7dfM/LN4yfdAdod+xTS5VU/4htKOzviZoVfHHoi5s6BuxT57BSseucJbX6 | ||||
| 4wEUBk9wEzTrGRZSrUI9DHkmMTxJ3qORtt2P0ht9GVCFbtAg/Mgg3v1BGlQTTgtw | ||||
| y6/iBgWxTO5OqiBW4EXQCFyfh85vPegvutX4o2oXU7Mz5QRITYDaObxMhyL32rBC | ||||
| wkEf0euFCKabLeutQm6bh0W15IAW/a2SO2knXJmWuP9GRxfFqzF76ZmHWE+cswal | ||||
| /FXJ9BA/IEkbJr+kX87+RhgH5RgsmsFsDXY/jwgUoW4gZR78yB8bq/uQubIMhhAM | ||||
| HLDtYIaOT1Hwrf1v6IGDeFR31zrWudt3kHH6uZBAH77Y2O6C+TuN9a0IhHwLec2S | ||||
| 4AIVTZEm6ZT5o7xQTVzjaxLWAdXtENrW8rArf6TH+JIruznbaeuYT6aeY4KlWlYu | ||||
| rVH/s1wBTWwhecdt9EHauLftK51Uy3GrZhQ1RTvb/DB/cbXM3yz7MbSsu7uqayiG | ||||
| g4+0at+1nk+4sFiM505FVtBVb6qL6HQIr+g65WcAnTUGj+DgYUBAmh38uu3jJbhd | ||||
| TMq/LqoPVyXy1CizKPIcLXTEec7Bh6HwXkn5LMU1HPdrjk9OSwzS4HgcOVR6Blhj | ||||
| fmoDMwuVkzyD0jJ1vRF+uH2krZu3NbBNA4W90XIpZy2FtyFePaTRJQuiZGXx9eGV | ||||
| AlUv8e6SV47vctqRZA2pKSPrmYLOgeHTcB3YehiOghyXnVfC4vBCoaujK6ToQ8aP | ||||
| i4R7Q/9g8xC6oZBtaBMoiVAkL6flDXanYcMQak5x/nPQvyyld+3gSqVVkta0uYg9 | ||||
| 1V54EEiB0TgviF7Gt+7/+UXXEx1dGygRzIV0LdX9dza9VarQmrN5JNhqPePzHiex | ||||
| k5ITcrEWbRc59BTH54s3nYRmqH6V43g4IRmu8VKRZ1QQdl59TWkwZ9gjrw1qZObM | ||||
| 5m9mSeHGd4Hs0h4kpzrhiq+p16q78SAifEIK8D/MKPisL+co3A2nkHPBlhKV3M4V | ||||
| Md23894sXGjMUJUq7lIrfChBdolwLvOqOQmLkWasn+QQ2bSixc1C+AxypTbQNgTD | ||||
| I548k4nDAgvMsd6uyftUR0rjIe85N/xbgD4uEXUx9J/u8C49AprGoMdqe6q4GdTv | ||||
| lwyKsZSPwUV989d6g2C0J8ptt0+5lB9f7H15Da/BemKUeccUZGAjVe55J6hXYkJD | ||||
| xUbYq4yEL+6BcaIo/D7jRSJSXY2xbUgkise/99fH/rdOHZQDamvI+yh2yYXVbsGR | ||||
| bpd2qtc1OGGA3LRQjz68TS3LBq1iXcQXe+/B3ANus/d/YUGm/pjAb56k3+4z6b9U | ||||
| HsXKdEjZ+XCkjmlvlTuCGl0TL8TLn3kOcxJyrTG9MuJ6p55i+QM44ef1Dc2hrnt+ | ||||
| qVPQLxMQMQ++JOJvW0U4YYoA4eP+HggIx3rZ93Im8tnj07/bCtLkFfNvo0O42Opx | ||||
| Kxf8W3d67NyNkA1l3XL58m9/VdfBPjc44wwdMKBy6A4VhNmxvf7Z6A45sihmUAGy | ||||
| nCLO0dG9tIM8njEhaXJBcT3YHQKO2xxaHXWmvR5VssOhP4Ewnup2xJioiP3FweYJ | ||||
| N4Yv3eVGHLYeDH77Yqq4R9q0He1R2iCwAzFlxOahtX03CANh+vUaKhruw7jNY+L2 | ||||
| WbrnNPYkjeiU/hFeVSBVgTeVkSQJPiQFK37E9NUo4T6dibGh9VT/5TEoskeUVmfU | ||||
| W17FzFwjBGQXaZzvChJFbKPbIE/j6ve7RrjdOBk6IBgi1LTib/rTOcGZbDhOTvIm | ||||
| G+1ze435mQVoBK/1MRgpfE4cpssF2TTEeJqs6PfYbqpx/o7cwZG/At3Jra+nKNhq | ||||
| WZs6TjIvNGvO7NUUZmfj2QPktLBRKADjym3YqJy4kGUQAZey5yeDWonMhEV9llAK | ||||
| LUC40BK6XY7ySw5vTmmGR6nnWo1ltT+71XDj3nZtfGF3TTCkNxZKlsX5HBhfXB/E | ||||
| +8PNg6Ova5jyH+IO9Lu7JLqYTh6St6NfVflD7i8ENFLf6X1CiJh6rRseb3TmM2ve | ||||
| aj+LypLV8FJ1N7OklFseZy+gqZ7AYCknoOK3z20zL3KMilw7TwTwwfGe41qIhAHu | ||||
| LLa7dA0EB58T8isNdBp36H2+oQENGHAIi0kxF0HlE1x9NUoFXvoUhyVEGjEj2zcy | ||||
| Rqjb5iSCyELMRJ7qiKyD0e8auH2bQQeHoMmJlCk2E7BXTUUY67eJnNXNrD7ZQg/k | ||||
| Yt7OAinFP24nKn4SY2Bwm35JE60iHZ3USoYnrD4twPBbig62fUSYUqqDoNYc5L2g | ||||
| AtR5C2SbDOsEG7qbehziw8NLp7zbf/FAashRULc5GLTcFoC2YJHEawhb/lWjo1Az | ||||
| nLqXfTB7jXHVbqgjpghJ5vO7PZ+FGg8ylTdUC4aQ/lUWuSeJnjkHDkHFFIfNC4S5 | ||||
| NYRpQIAYMdDRAP80tdAHeOG5BC1OoA51jBKqBi843tCxu8RUQxDlB5/3AYKB5ndC | ||||
| S3Pp6kYXW8wcFAFRluM+LCFzO9VFnZ8BEh5nDX4= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,35 +1,33 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyB3QTU1 | ||||
| TEdvbFNaUmE4U1lCNzI1dlloVDBTNXdURjZ2akRMV0R6dm5ST0FNCk9YclRSakhT | ||||
| NlV2UVJwak9Fa3dQNTNBK0xKWGlkNXdwZTBEMm4xZzc3azQKLT4gc3NoLWVkMjU1 | ||||
| MTkgakk4UkFnIGNBMHNrdG84cUQxd1lqQmJIczlScU1jNk52Y3BtR2tXeDNWdWRX | ||||
| cEFCR0UKVU5vem5MZUFPbGhoQzJTYnF4OTd3OW9jYTRkazdocVJkZ0pRRGNLek93 | ||||
| cwotPiBzc2gtZWQyNTUxOSBnU3hQMFEgQ2RUaEUyV1ZGbGRtZnlIUEtTQXk5MUZF | ||||
| djYxZ0hBUThlV2tXTHNvdXpVSQpMdiswMy9QNUtCb1hkbGRqR0Nia3FXTzE1ajZL | ||||
| UXljSTZqM2YvbzVuWUFzCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBYL1NrRjRaRnFn | ||||
| RlNLdWJ3cThteDM3WmNaY210d3RmZzhCYmNpVXBwVGlVCjBkM0IzZC9zNjhmTTZV | ||||
| R25ySkVoQWxQQ252WWFlWWZFMlc5dWtUN3VvVTgKLT4gWDI1NTE5IE8yUU1pWGFr | ||||
| NzUvZVpwalB6aklkWmJGWUQzTnJiRjNzdzY2MUp6MkY5M1UKR1VIWDVyTFpxem5F | ||||
| TmRNWE9zZStLanRTdlU5d0NOSEJKdWhDUjBCdy9vOAotPiBTJCd2NyFYey1ncmVh | ||||
| c2UgfE4mYSBXfms0TC5FPiBiYmx8IGRFV35mciNoCjVZdHRiVUtMMWxEMlJ4b1F1 | ||||
| TGgxY01XTlZpTEtndkg0T0hRVjlqVUJGMUpSaE5tVlZWR3VGenpkUXY2eXJtbmkK | ||||
| ZCtqRVN4dnZENXdoYkpjNHRWYXkvN2laY1p4YjV0WQotLS0gOHlEVTVOSmlNemNQ | ||||
| TW5ISk1DeDlEM1RoQ2JtUFlyTXRKQjdnT0hiend2VQqrUFvr+76sKn0ldBmZMlEW | ||||
| U2k85DLo2KU+/+GtbkZwVXxxIZHMLpoJgghHk9ptdalUgLGcl0X15x9jVaw8aeta | ||||
| hbeOHotRHY7bC3z0S74riTk3xDMR1eT0QGhDMWHjfo8SkCftOYBlFfhTftevdep3 | ||||
| pKMZsuQMwH9JzxgUfcxIcWE975cZzrEJ85nfWMGvdSjcg51KNxP/UUPRxDlcbCEf | ||||
| 9XX5apSzNsTI3ibGD1n6Qwq8bdVYDMHmy5pAhw4l8L+SdoU1tGdw7JOA16sMCJbx | ||||
| T4bV0ky/PGRonjJuCyDBj8oe9vMe1ZI1O/ITtktekS+wocxBs6QXlY7pIZMlGUn2 | ||||
| 6m59ZEEaf7R4/MdnmBDNDkQuyXaKc7SaTc6h5sKWzXdYScGUKvgUQ7U/WJ2ItUTC | ||||
| N/Xq07GkZZMt5MYBlyEr+/mKWlcy+ylJPGb7EswvQWaHoeM1QF0XLZ1v+W/Xsso0 | ||||
| seIoz+geSu9a02kwfsa8WvWXdIAT5X2pNGPClVNzjQ23pfQfQuW8ZQrGmIFR4g5A | ||||
| 58T1K+vGLdShqqVGyJFMVrSuOzqX5FVmZalu7/++1IQfiRGUlrHKoPlKWnCfFEOu | ||||
| AYjaPeEFX2ByxcqfMK1YVPvUufdISUQeaQOO7mXGE3FqB0oUqmRIUiWZATwhq3Pw | ||||
| p5QdcySTnmMpD/w05hvwski77kCdmYuHlMlLZez/kfhTnIGXris+Vwi/V19bsZ8G | ||||
| zwaZ/Xr6WNC+df5JqSfTGREnXZPFRDkaTt3ri5/eEm6BqliuYjGbuiKsDECi4+JX | ||||
| bHpH6LBBoKQ6ms7jCAn0Ls4cUKF37PcjGAOuWnzCSBU+REht1EDfHzx4C7hNiP8X | ||||
| 87NjEqJbwE9lORho0hQJRTn8uriQcidlVoB3se2SYKbMy8UA4NNnxN9PTj0TuQjL | ||||
| OD3LtqHBElqNPbGNyyEAAJmMBmmkUvPPXlGQ0D99b1+jIdHzYSRtOLshBFykqWYQ | ||||
| LJD61duhGqcQqcLx4+JdQ+oVcfAI2nG7YINnHB0OmS2DOZvvwqQ7ASScSujUWIjA | ||||
| LNQxu3ruMz+bw/G0tYZBBiE= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBqaFcw | ||||
| aURxK3cvaktEVkJIQ2dOOEtqbVVGRDN0SXpXdGI3NzhQV3FmaEJrCmVtclBDY2Zr | ||||
| cVMvUld4dDNybnJ4bHZOODFpNGpJVXdRaDJKY1ZxMy8yMjQKLT4gc3NoLWVkMjU1 | ||||
| MTkgakk4UkFnIEtDRTNkdi9VdGFnNkQvdE1UdHQyRmJXR1RtR21HTXMwa2hiK2xM | ||||
| Ym9xa2sKYTFVQmVCNmJId2pPQk4wd3g4N3pOc1lHcjg3YlBEa0FsQlVsb0RKRjYw | ||||
| RQotPiBzc2gtZWQyNTUxOSBnU3hQMFEgOVM3K2NwalE0Vk1rbWdSL2srbXg2bkF2 | ||||
| MTduekNpMFA1QkFBNHJidERpYwpCbWQreWk4cTllUnluWHZaMXZWREpqZnlwL1Ex | ||||
| R3k0cWhHSGg2SkJPSkNZCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBwdS9CeklwWmpt | ||||
| TkxWYnhTTjVxNVREOFBqQXhRWHlza3FLY202K0wxM1RNCi93YVFOTGJGNmYzZzhF | ||||
| WkpFMDd6V1JIcjR6ZXcwUys5UkE1ejdFOW91MWMKLT4gWDI1NTE5IEk0aGh0c09n | ||||
| T3B0ZkNSc3NTa2doUGs2c0NKTTVMOENPRjJ6KzlodnBxR1EKUnB6azR1V3NHUnRR | ||||
| WmNrWHArZ2dmMUdEaGovYUdndDVNNlB2UW5VaVdnOAotPiAsLWdyZWFzZSAlUSA1 | ||||
| WX0gJwpCMG1tNjBPMVJRMGRlQ25KLzJsblFzZkN2LzNDOGcwWEdSSXlBUjNwCi0t | ||||
| LSAyY2hHNFNmWFBQWEsvb2hxTUxVUXdKL2p3ZkZWSHRDdFlkREJyaWJrVDg0Cis5 | ||||
| gfdBAb92J5/DuoXUt8OirgM7bXucabAp8/U5Az0nmRkGawpSZidB9ecPYHfcdUGp | ||||
| VIv8roO6P0RbbfYXh3szT1YmEMyOXMHFM0+Yunq3u1ca1EHCZDV6Feb+i+lXIBJU | ||||
| GST4oupwMET+ChVT1/yg7A9o4FY68+FgLjGwE1qeHN8gQr6aMz6/yml/z1WzBEXW | ||||
| XEv5fVxGj39eBiq08Z/kCgt5zVDod8RxEq3S3kt1KX5JD+mpGYn2z5CMGhn7fclM | ||||
| mj37LaVbcKfyVnwRlLPoN19NeqR+ltM3mu6ibjC7cOQ0E1D/zjQMIxtzNzmZRFgB | ||||
| l/BEOsX25Zv5vJgLZBU9rMfybNVAjDroG5V1cCVDRR76TP6HVJIXSriyOW5xSFCy | ||||
| Li/VyhWaUXRboGq0Nt4vXWuOTlU/tenlBnBc+d48x35VCExi9IEFpIHj1fUwM/0V | ||||
| dgOfY2WRH9C2cObUc6W51FIARkp777uPXRbT4ZXRDjV18vb18CmwLQQwYupQYnZk | ||||
| c0hZHvoxDwg5QirWxPhuO3bWDqIvHiKy1LYgRrlvr4Wpcb1l0lAYSGX2r1+QVj8z | ||||
| tA+zJcUaPkjUSpaqF4LNVWXrTWEN330gQrVk1knWqPl+hFPoyFEHP50PNYr3yxS0 | ||||
| VxbSpg46cXyxi89ghwlXBqI4LRtWlheUoIOuNyLxvXZECwCI2kmt+XBFph5lbG7F | ||||
| UQaH+ve+trb3oYkkG8ZprCljUC7HvSyt31UIRF3l4sLsULQKHqWwVD/2M4B0N5wQ | ||||
| IzIJkiuWBBE8IX/tI5vUlGx+QWSxmKdHD2mMb/GeMsbo7lOY51cWe8oxe9WcYPhB | ||||
| m4h1xPm4FLo0vHCnWIkXy2o8JYr6fmpjzslC++wYMEbIH3gRBKUVjgUGHywVIXSa | ||||
| uwzRULUiD8uXFNT3cZ+YDnAvZkuYz528DBKjd5jNen4akah35wQ+oYoGuIhUKkGL | ||||
| K59+hTyctWyEGi+fCl1gah2JJ6aF1CXK69ON11YkCEVCI1SK1o1no/0NZj2XtepU | ||||
| MgXln0Pz+pOTZzcjCWhYTO/dNl+Xj6EeeSjjWHqDYg== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,11 +1,12 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBEcDNm | ||||
| ajc3a0gwYmVSdkowak1aakJ3VWZ1Rk50S1JIS0ExVktVSW9OVWljCjJqbUEySlNK | ||||
| a0xyT3NPK1BBMjZzN0RrLzhwVitvS0pzQ25iSnJSc3FmM0EKLT4gWDI1NTE5IHk0 | ||||
| M2pkWHgyMHR1WHc5bE4xWTFDTndKdkhRdTg5bzZIWEU2cm02UDZBQjgKUUY3dS9p | ||||
| U3h1L1ZvTkFPdURLZ2tSYXJXOGNZZ21KVGdIbXdhSUJrd2puYwotPiAoL0RtO0lH | ||||
| OS1ncmVhc2UKVGthN0ZSU0ZFTTg5YW9UOXMwa3RnSzFlMjE2VTN3Ci0tLSBwMEMx | ||||
| Q0tQckd3SzBwUUE4SndMV01kUjVrOTdDWmxlcWs2Zy9TZk5yMzhvCrBXyLBZGuSD | ||||
| dJodNI13obTM3UvX6hSgQ8Su+J3fOKr5NibkhQ0Auvlr2tUXhhDm2WOUlHjqVTq+ | ||||
| jWLSyhioDlIEyBgk8Zrl7KGeDzBi | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBvL0hp | ||||
| WUs1VWxPVlpydU01cjd3Qk9qd3hvWVdvK1VMaUZNT1YzQ1BjdWhvCmJlSDRDSFBj | ||||
| ZGVmVGV3Vmp5YitGbm50aU56VDZCc1hTdjJmSGhEa2dvZWcKLT4gWDI1NTE5IEsy | ||||
| RHVVT1F5d0kxN2VBMG56NnJWYTlEeFFXaHg2VnNqdlJKTHhoR052akEKZjNObUtk | ||||
| RCt4Q2l2R055TnJCSDBrY1lWaUZibk5iUDhnMlhvZkxRRkhpOAotPiB2LWdyZWFz | ||||
| ZSBMdUErIHQpI01mVENmICFrK2dRdjBbIFU5UyI+KjQjCitmdU4ySDhJMDRlbklD | ||||
| aUcvREFqdVNtb1lFZWwxZWo5VXdNUGZQWGt6SVRKaUI4cTcrWEx3NThWZ3VORkor | ||||
| cy8KbG9EaGV1dGVDQQotLS0gQlFJdWpudnkrcmQvbEhpOUM5Y3RCWWRGMEQ2TUV5 | ||||
| eTBFSnBkd0xnYjUrUQrxdaCf14h8hqRfdnMorggnbuCDMRHY7nAnGQ1ET4CBlCog | ||||
| /Rp52aNZHfLh+BFFZazenI7qrvVvEaaB2ZVKa0Z/F8adsGHSGSwz+saqWw== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,15 +1,13 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBzaEo5 | ||||
| RzNndHBLMUl3Z2txdVZoOVJBbWsrTVJwY01WeHQ0VTBaSm5VclY0CnJLYStYNEI5 | ||||
| VTN3dEQ0ZjBKaU1PZSt3d0lldkE5VC9wNHdWazNWV2F6WWMKLT4gWDI1NTE5IEJ5 | ||||
| amlzTDhCOFF0TllPd2RsME5Cb1lRQUZPTGNvOEZnL1J2Wlpnb29GblUKT2t1NFZy | ||||
| blNZSHdxZjlHTlZmaTFYT0laQ1IwOCtDZ21vTjhxM0owdTAvawotPiBLYS1ncmVh | ||||
| c2UgRX0nVGtpSCUgNVNDWCVwIDBuPjM3MwplK2cwc2htQ2RLcFhUZ0RSc21uQlFV | ||||
| Y1QwSStOK3lKYmVVQ0J5RXA3Zytaa0JoMWtlWU9qMHBLNktFZWxtbFpDCnJyS0JJ | ||||
| WEcwbndYbERreFhLZlRyQ3E0czB5NkREancxZk5BTGdWRkR6N2NrZmFrbnhSYlZZ | ||||
| NElHNEEKLS0tIGVLdXAxU0ZaZVkxaHV4dEZNNUVuc2J4N3VRMzZzTktSMDY3bDVB | ||||
| bWtmUVkKigIZ3J0s23vNzmbzJGjSMGBXK6o6xnsA9HXeQZ13VgKv5Qv+UHu+Z0g2 | ||||
| TeKdQSrHbDB3ydIxaiXsi2ivULdrIMCyd96rEJFxrkVuVqSZE0ehG5j+o8lKk4OU | ||||
| PDe70slbZrVYDSu+OOUOCVRSopZreCURlYn2Pc4rjvrMAn5r1r+/AxjZMdkmmQZ0 | ||||
| l0wMBTus5zZzKg== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrVktQ | ||||
| Y05RdDFyeUhGNDBiK3VHNzlrMVhKWlBJQnhodkUvTTlINUZ5K1hVCjJ5bXo2cTd1 | ||||
| a3FCaHJTNVNaL1ZRcDhuTENuZVlhWlpJUUVndVErbDVoR2cKLT4gWDI1NTE5IEVj | ||||
| VTErMFVTdHBoVmtMY2R5SmJSdHV0aTJ2SWZNc1hrN0h5S2dKUnFxRFUKTHpyaHV6 | ||||
| WWFYME5xNndlSklvNU9GSEFrTFpnc1cya0NMQUlqc1Fhd0hNNAotPiBoRSMmKiNW | ||||
| Pi1ncmVhc2UKZDQrM2piclMxdExSdUZqcmhVV3l1K3RHVFlOcFZzN1IycnU0d09k | ||||
| V1dwREZDaEcreDQ0enJYd1FXMDd3d3BVNAowYlpwK1EKLS0tIEwrL09nY0FpSTlq | ||||
| bFhQTUtHOWt2NWV0TDArRy9iaFRFTEIxbms4SmI0ejgKmJRGof5FAIPpGn+u6PDh | ||||
| xSQMKrpFnGvjKs2FicG7K3C19YGVwvMds9XGYzLLdugvZgykzZhq13XK/mSk2b9r | ||||
| 9xkhAvCQ0p1ikQDyX6SuLwJzsJpa7V7wHbEF5HJXQ5NrJUOFwftzxSqYodtP29L4 | ||||
| LiA8sxPzNeqhFYT/C8Ea4lDzgnXCjoWtMcZCpfWMMtOJh8fLLw== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,15 +1,13 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBoZUI4 | ||||
| bEdWSW1pcDdMYVRJLzdQOWhsdTlZMmlyZjRVeEFwU3Z3NzVFa3lBCkxRZ1FYeU9D | ||||
| L2dramp4WFFlREZ3NTFnWUs3clVEcnBhLzExclVac1M2SG8KLT4gWDI1NTE5IHVZ | ||||
| bk9QYy94Tk50c1dVanNvNzhpYWNqeFMzVVR0eTQ5OXozMmp2VFlad2cKaEdvUnR5 | ||||
| ZjhsQ1FRaittQXFkbnRZei85MmtWb3pXRVFsc0RzNzBPMXFMWQotPiAzSXJZb0RE | ||||
| LWdyZWFzZSBudCBGIDklTWIjVnwgM3YvCjRVYUd2TForc0gycnRBR05MbU90QmNu | ||||
| dXlmQVB2bnZyME5heXlyMUdGTmR6SVd5SHcrTThrZEJYRlpnUmdmWnkKU1lyNjQ3 | ||||
| T0J6b3NPQ1FYZnhxTjFrYmN1UUJzMjEwcDBwSTJkTnlmeHl3WmFFTXB4eUVMWm9i | ||||
| NExUZzM2SHlLLwpiZjQKLS0tIHdqakpMSUNOdnlBcVA4RGJHR2d5QnJNT2dVclZN | ||||
| djd4WXBLSUhORktzZ2sKzMjxqL3UPrtGmXDijdfu0AwxLJooK7ZKauYvXWSuZUrR | ||||
| vl5i1QPMEEBYEl+NaZIFgxAFqWpAXHQ1VxSijMWxNjKUd1Chq0tbLrpbh9wXJflK | ||||
| SW19Wyqc9eTb8BnFoOSYWpDvAs2Lbyr2kJkOj2TNrwMv8nDJdOB8XIPlV5drCj1q | ||||
| Dx/1zWqm6NMYxsep6eZkv4AzxA== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA3enI5 | ||||
| NkVZMkxncHRiSFkzRm9seGdwdGNPM2ZFckRoWkZFNlV3Rkl4U0UwClJ0bUZlUlFs | ||||
| MVNsNmZ6aFFYRjJSQmNWdjJMc3F4cTNrejMyME1YRGdQVU0KLT4gWDI1NTE5IHlR | ||||
| VlI3eGVMcS96a0ozWkx2b29wTWtIbFFCcDJEa0g4dWJvdnhGQWFwMUkKZjQ0MzlQ | ||||
| VDlGdkdxNG91bDV2MFZXazM5SlIrUmduYTJacGtXQitnTXU4UQotPiBNQktGOG4t | ||||
| Ky1ncmVhc2UgZzddIElDKW0KZTFiNlIvcEt6aHUvY3h5VFVtb29ZQ0RGODBtTUF1 | ||||
| TS9Ta2lZZDJJUFNyOGp0aU9LCi0tLSAxa0ZNWnM2b2loNzNFMmd4U1V4NUFnZ2RO | ||||
| SVRaUDVpNHVHMUFSczNOcVZzCiJKbkbVr3dPswaIeb/dlP5REMZW0NoxMluj8R73 | ||||
| AcCimbLRWY2KAOx5XU/ci2auvMqjlqMExlp608OwaGHcpmoijNZQsKgTAW8Z4z28 | ||||
| 9UbAMOmSWByLfgAzhoN4Xob5/40JjI2f3wFYwsAf0f/j6dLc2lmqxkhd+Zcj76Yj | ||||
| t2WbVgPlBMqPQIoFd6TtwJweqzzGmLI= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,13 +1,13 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrd0pM | ||||
| TGw1anJNaGoyQ3lMUis1cHVtRWFPcFFNZk9Cdm9TMEh1QTdKc25ZCm9VNzVQcUxE | ||||
| Njh2Wi80RWszSU5NczRNcHpVYXpRMzJNcDRsdGxyWVZsUDgKLT4gWDI1NTE5IFpT | ||||
| MEJVUkcycVFJaVFOUURoL29VT3R0MVJCWW04NXVRVEpKY3hlY1lWRkEKcENya1Jx | ||||
| VnBCMVBrZkc4VDkvMnZoTllCL09vQ0VOZytuMnRvYVQxL2FldwotPiAzLWdyZWFz | ||||
| ZSBCNX0gIiB7InIsfCAkOT9uM2UKUWpSYTZ1dUo3SHNaUlFibTl0UDhTaFh5Mk1n | ||||
| bFp2cjM5RGhqU0s0Qm50Zk1pUVZmT0R6ZjBoUG1EUGlKbHFzVwozQ2t1cWVDVVAv | ||||
| Q21QTjF3NW5UdTBZRldnL0RmSlV3QndHcDB0d0lvZ1RHTTByS1ZwNkNVQnU3WmVn | ||||
| ZwotLS0gb0Fxb2FsYzgwRjJwSUF3ei9hZVR2Vk1ORDlIMWoyZ2RTd09hUmtvMWpD | ||||
| cwrEjdaYfoGZ9i/S97xL9QvA/yii+sJLeuUzzv7a3DE661eQ5ezurV8Qz1tIhxWG | ||||
| RsOppaaj1podFx3U1x7QQbLO6zQbJA458RMjYgc= | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA0N01m | ||||
| Z1RiUHFFbmlDVVgwTWQ5Nmw3WU1NckVFcWQ1SGVsQlZLdGIxSFJzCnZpL3dmRWdY | ||||
| UlVaOW0yT1ZmUXU0VkFHNmRzbFk4cEt3dW91MHdnR240eVEKLT4gWDI1NTE5IGtC | ||||
| RTg1eThyRHlSZ0VsUEVzUm1EYVFIVHZZaHNvY21mOS9mTnlRbW03aEkKQjIraStT | ||||
| WE5sRUx3S29CcTRobHZVQXJDQTQ1YXg4Z2c4cS9zSVhVVElXcwotPiBoM09vUG0t | ||||
| Z3JlYXNlIF4nRnwkeSEgKTRZIHIKT2FXTWZmbW9jSnkrYmp0WWVDVTZHdFFxcXJt | ||||
| Rkg3S08xVGZ0TVVjTHQwaExFbkh3WDB6bWJkVEFKYXpQUDEvSQpGNXY0ZS94SVY5 | ||||
| anViSzJ3NlNOUmp0eUliYms1Smd0RUVXVGhxdlV6TkFNVkpzcwotLS0gQnc2Y0ZS | ||||
| aGNtL2RwUjVxZE9uYlpBeVMwd2M4RTNsdW0wVWpDd2hLLzJSWQq07wZpB40EpZog | ||||
| fW3t5Uokt7EZL4V4RX9PFyd48SaEd/xR1FiEL7jg8IJp0dY7hdfnzObQbueCwUOi | ||||
| lWOfF3n8XpzS8uo5TgLWLtY= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,13 +1,12 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBHNWg0 | ||||
| WGRGZnlTdEhsRm96T0ZMOWx4UUxkTitJa3hMWDE1dVkreEtEa0RVClpvR2I5NGpz | ||||
| aUF0N1VZU05oWXUzTEI1TVBLYlVVang3Zzgwbi9teDVlQlEKLT4gWDI1NTE5IG4v | ||||
| OXRIbzhaZEdXc1pjTnRRWHVxc2ZTcmozSlJkY3lyOGtvd1BVeGprVUkKdUNqSW94 | ||||
| SUIyOWtsNU83cnVOTUxNR1BvWHJPczdzUWc4aGp1MjlpZm5ESQotPiA2KSV2PVx5 | ||||
| LWdyZWFzZSBqezVxOHc9biA+aD4tP20mXwpwRCtMUDhmcVhGNXpCZlFmSllpdDVp | ||||
| SmFZelNhZnJlR25DS2l2MlQ3ZGFtdGxkZEdEWVNrRlk1VEZBRm9GMHBFCkVlQ1hp | ||||
| WnhOTGl2R2s5RDRKN0p5TmF6Y0cyN3ZlR2pDZlhMVjQ1c0FJN3hCbFEKLS0tIEFT | ||||
| bjFiRStXMmJueHdsRm1nU084dDRpS0tBT21ENzZFclJXbE11NWJETm8KyMHU+tZY | ||||
| QELtZCbXKWnP8QC6V84JIFAxoRslACwsIJZpogcZO/IFIV2RGunGjCJk6QBmhOPV | ||||
| kJXRcGO/ndYjWfuU0U3+9HtPocnO | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA4bGQr | ||||
| dzJZbU4reWI1Sk45QTR3UkRoc0NvaDBFcUwrVWlCYWUrcWtYZGpNCm1PWjVzRVlt | ||||
| UDFKY2ZSZTg4S2pVZ0pDNzR1WklYQ3pEclJZLy9kKzdGTGsKLT4gWDI1NTE5IHFO | ||||
| TXVRK2d3azg2cHpRanhUNXp6YnRsZW1MUDJqc3l1bnNYNUhHaTIzMVkKWXp1M09H | ||||
| TnJIazRmb0tOSnE1Q0E1dERiaHZCQkh2YzE1cS9zRUhwaEovMAotPiBzPj5nLWdy | ||||
| ZWFzZQozSThRWnJCcVFFRHpoSi9tZnZMdnJoRlFud2VISHBHSThMem9qZVVWdS9C | ||||
| VFBDVEVzbUVCdFU2Qy9PaGdyc0FaCmk3UFZma2ZiR3hmWG1sa053bDBnY04yZ1VZ | ||||
| TW9jZwotLS0gMDVSaE5aakxHenFPVXpXa1JxczlWQ2x2VGNuQzdwaWZFTTFTaUp6 | ||||
| cnRmZwoomylfwjD5A3N21/mk1Wtt8f4bsK747iZz7KT34kqmoX597rbGYxyip5lg | ||||
| VLZV6CY4LLRjnnSKoC2hIXU0dgudAmvxhztuaQ42fOc= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,11 +1,13 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBOZ1RV | ||||
| VVpOZ0Jhd2x4YklMOHdkNkd0MEM4ekZiYXFKMjRIdXlZVDFkOTFZCkRreDZlK3Bo | ||||
| WmJ1MDBxSU5UYzRuUDMvdnpVc0prNFF4MjM0M1FaZmg4V1EKLT4gWDI1NTE5IEkz | ||||
| THNsVDVCbU9KYWpXL010OVRmNjBVVmVyVzhRZW5McVFJcnA3ZWJvZzQKOE1lQnVX | ||||
| Nk1rWVAvS1lpbDEzb2ViUUE4RlB5NnJOZmNoUGdUMGNuMk1iMAotPiBuYVwtZ3Jl | ||||
| YXNlIHdYXzh3MSB0TyREIGpdTjheeQpJZ2pYUyt6UC9vVmRNZU1uaDdvR2ZUNG0K | ||||
| LS0tIHNCRno2V21tZU9XV1UwR2IvZDdkWEMzZDI4V25Yb0lvdmJadXNEZFV6TEEK | ||||
| 81uT8S3QJNe+mVadi/VpXSPEP0Ygzm0/+1pB5qqYlSQEWTHqS55gCyFCwu+sjaDq | ||||
| DpYTSm1JAk5ql9NRj4fJvCS53lJZ4zo+5c0iJKmuRg== | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBzc05k | ||||
| SWtwMW9tdzAvL1hYenU4Wm9MTGF5MDIzS1Q1eHR5TDNlRHkzWEVBCjBWa1IyaHFr | ||||
| MW1Xb0dSU2tVTlhuT09rTUF1Tnp0Um1EdExGSjk0ejJJSDAKLT4gWDI1NTE5IG55 | ||||
| M1RVRy9YK1dhZnRFMWdpakptVkNmaXJyOWJxSUlLcHV3a2NHa0N3RWcKQ00wUmhY | ||||
| UExuTXZ0bWhjQllQOVB3WnAwbnk5WjlURDdpQ0pqNjVvMExjbwotPiBPfj14Slot | ||||
| LWdyZWFzZSBEPyB1O3spbCBYPCx0b0RQIFtTUmJUOAovelJwVUZibjBibWp0MmZ6 | ||||
| WFNVMDZkbFJOMExlaEFUbFBBWnROWVVtMkNvR29ham9pV1dHVDV6M1BVWjBldU1L | ||||
| CkptRVEyWjNBc3dXdkFWN0NlTld4M3lnCi0tLSByMk13SzY1L3R0NlRCVG9lcVor | ||||
| NVVmT1hxdnpSL0QrU0k2RWxlRUY5SldvCiBWgIk3pt8hcWFRsH6oleoX56bT+nz8 | ||||
| BZx959QwOE0of9n8Prfnviq15L9Uan8yL/CadSS+0kyir8AHhl3sV/VLFe9nlZZ6 | ||||
| Zg81EdhQXSQ= | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
| @@ -1,11 +1,10 @@ | ||||
| -----BEGIN AGE ENCRYPTED FILE----- | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBBOVJi | ||||
| SXdGVDlXWmVGZUM0OTJPUWFYem5qZzAwZWxhNzhpT2t1VjdZU0ZrCjYxWUE2VW5o | ||||
| cGFLZ3g3Y3BpUWlWOUtUYTg4MGZXVHZvdVV3eU9iZW0ybE0KLT4gWDI1NTE5IDIw | ||||
| QmxaWTY0WjJFZUd6TUxqaHhRelpRQ1hGZVBEcm43d3JYUVhpTWp4aGcKVzhJdFFu | ||||
| SEhUUUZVNVk1N2tzekpzUS9RazRCcFBhb2xxbkhRNEwzVys5cwotPiBkeE19PHEm | ||||
| LWdyZWFzZQpwR0xsb05JVlFXQTZZQkJSWHY0akNRdjh1eXFnbmFDWUlCM0xLWXBi | ||||
| QkVuanloRQotLS0gZTkrT212MXdsZy9Kb1AwMkFHU3VsTElweGNlYkZ2UWVXRzkr | ||||
| dnB0SHRnYwrveLSY6SdUDO+QH7WGniLIOPcECTQ7CiTj9lwD5Hm0rYLdvizolb33 | ||||
| CsGX/kSEI2bD | ||||
| YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyA3TXZY | ||||
| OTBpcmd0WmplOWFEbmMwTjVidC9BSFh2OUVqZXo1bzRvcEFvS3hvCkx0NytPaE1Y | ||||
| NDliWk93SnNxb3lOdlV6em04bllsVmZuVllwYnZ0SytLZlUKLT4gWDI1NTE5IHFu | ||||
| bTgzM1NLWXZmWFVqVTQ0em5XajVEbkQvV1JxSXp3anZFc3EzeTdHQVEKYTc3eTVv | ||||
| cUFyYjU0UGErc01GclRhU0xtUWNzQ1F1cm45d2NVdHdDNWNWOAotPiBvWFhMLWdy | ||||
| ZWFzZSBQMV9mNiBrdzVuNSBOOSkKOU9BZE5WUzdIbncKLS0tIGplTzYyQVNBR1g2 | ||||
| N3VUUHRCVjY4cjBGYTV4akpEbGNPUm9SRXhvUzRzcDQKhBEb7xKAjU3SMSgsVxBa | ||||
| 8KA0Rh6lgJ0HOLgfBI8cZTzHcNXeIOgOTae1GmStyVjUkw== | ||||
| -----END AGE ENCRYPTED FILE----- | ||||
|   | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user