Compare commits
	
		
			116 Commits
		
	
	
		
			a0e4cf2479
			...
			installer
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 820bb2de5b | |||
| 7d3ad52a44 | |||
| 2cdb98e898 | |||
| b717b1ceb4 | |||
| f31ce61c2b | |||
| aec22942f7 | |||
| fc8676c3bb | |||
| 2915e42a1d | |||
| 5783d3a51e | |||
| 2fe94bba23 | |||
| 4b42960d26 | |||
| 56e9abf945 | |||
| 4e2c2f92f0 | |||
| caa208b288 | |||
| 9e6f885c17 | |||
| d8ca87bfd8 | |||
| e9467e0cc7 | |||
| 6c98ef8944 | |||
| 18981e240b | |||
| df7e5953eb | |||
| 71d1c3f9c2 | |||
| 1453a755c3 | |||
| 970af805e9 | |||
| 383e9a9b1e | |||
| 26a16d0629 | |||
| 208de7654e | |||
| f577e7d58a | |||
| 6130ee73be | |||
| 5d827aa00c | |||
| 173ffc0044 | |||
| b113f2f48d | |||
| 7c67eaff21 | |||
| d1f1b84e82 | |||
| e3cb2adbb6 | |||
| 736c406eb5 | |||
| 8e9b750ac8 | |||
| 51c5578840 | |||
| e174af45f6 | |||
| 198e7188bd | |||
| 571f8f1504 | |||
| 64c3fe682c | |||
| 7c05b6158f | |||
| c9ab90547f | |||
| 63d929c8e8 | |||
| bbb87a2d69 | |||
| 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 | 
| @@ -6,11 +6,11 @@ on: | ||||
|  | ||||
| jobs: | ||||
|   check: | ||||
|     name: Check, build and cache Nix flake | ||||
|     name: Check, build and cache nixfiles | ||||
|     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,22 +18,30 @@ 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 | ||||
|       - name: Build the world | ||||
|         run: nix flake check --no-build | ||||
|  | ||||
|       - name: Build (and cache) the world | ||||
|         id: build | ||||
|         env: | ||||
|           HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }} | ||||
|         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 | ||||
|         run: | | ||||
|           nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \ | ||||
|             push main ${{ steps.build.outputs.path }} | ||||
|           nix eval --json --apply "builtins.attrNames" .#ci.x86_64-linux | jq -cr '.[]' | while read job; do | ||||
|             echo "::group::Build $job" | ||||
|             nix build --no-link .#ci.x86_64-linux."$job" | ||||
|             echo "::endgroup::" | ||||
|  | ||||
|             echo "::group::Cache $job" | ||||
|             ci/push-to-cache.sh "$(nix eval --raw .#ci.x86_64-linux."$job")" | ||||
|             echo "::endgroup::" | ||||
|           done | ||||
|  | ||||
|           echo "Building and caching CI derivation" | ||||
|           nix build --no-link .#ciDrv.x86_64-linux | ||||
|           UPDATE_PROFILE=1 ci/push-to-cache.sh "$(nix eval --raw .#ciDrv.x86_64-linux)" | ||||
|   | ||||
| @@ -14,22 +14,20 @@ 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 | ||||
|             extra-substituters = https://nix-cache.nul.ie | ||||
|             extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= | ||||
|  | ||||
|       - name: Set up vars | ||||
|         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" | ||||
|  | ||||
|       - name: Build installer ISO | ||||
|         run: | | ||||
|           nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso | ||||
| @@ -39,12 +37,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 | ||||
							
								
								
									
										31
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										31
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							| @@ -0,0 +1,31 @@ | ||||
| #!/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" | ||||
|  | ||||
| if [ -n "$UPDATE_PROFILE" ]; then | ||||
|   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 60d | ||||
| fi | ||||
| @@ -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"; | ||||
|     } | ||||
|  | ||||
|     { | ||||
| @@ -77,7 +77,12 @@ in | ||||
|       name = "build-n-switch"; | ||||
|       category = "tasks"; | ||||
|       help = "Shortcut to nixos-rebuild for this flake"; | ||||
|       command = ''doas nixos-rebuild --flake . "$@"''; | ||||
|       command = '' | ||||
|         # HACK: Upstream changes in Git + Nix makes this necessary | ||||
|         # https://github.com/NixOS/nix/issues/10202 | ||||
|         doas git config --global --add safe.directory "$PWD" | ||||
|         doas nixos-rebuild --flake . "$@" | ||||
|       ''; | ||||
|     } | ||||
|     { | ||||
|       name = "run-vm"; | ||||
| @@ -106,8 +111,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"; | ||||
| @@ -115,29 +120,17 @@ in | ||||
|       help = "Build home-manager configuration"; | ||||
|       command = ''nix build "''${@:2}" ".#homeConfigurations.\"$1\".activationPackage"''; | ||||
|     } | ||||
|     { | ||||
|       name = "update-inputs"; | ||||
|       category = "tasks"; | ||||
|       help = "Update flake inputs"; | ||||
|       command = '' | ||||
|         args=() | ||||
|         for f in "$@"; do | ||||
|           args+=(--update-input "$f") | ||||
|         done | ||||
|         nix flake lock "''${args[@]}" | ||||
|       ''; | ||||
|     } | ||||
|     { | ||||
|       name = "update-nixpkgs"; | ||||
|       category = "tasks"; | ||||
|       help = "Update nixpkgs flake inputs"; | ||||
|       command = ''update-inputs nixpkgs-{unstable,stable,mine,mine-stable}''; | ||||
|       command = ''nix flake update nixpkgs-{unstable,stable,mine,mine-stable}''; | ||||
|     } | ||||
|     { | ||||
|       name = "update-home-manager"; | ||||
|       category = "tasks"; | ||||
|       help = "Update home-manager flake inputs"; | ||||
|       command = ''update-inputs home-manager-{unstable,stable}''; | ||||
|       command = ''nix flake update home-manager-{unstable,stable}''; | ||||
|     } | ||||
|     { | ||||
|       name = "update-installer"; | ||||
| @@ -145,5 +138,15 @@ in | ||||
|       help = "Update installer tag (to trigger new release)"; | ||||
|       command = ''git tag -f installer && git push -f origin installer''; | ||||
|     } | ||||
|     { | ||||
|       name = "deploy-multi"; | ||||
|       category = "tasks"; | ||||
|       help = "Deploy multiple flakes at once"; | ||||
|       command = '' | ||||
|         for f in $@; do | ||||
|           deploy "$O" $f | ||||
|         done | ||||
|       ''; | ||||
|     } | ||||
|   ]; | ||||
| } | ||||
|   | ||||
| @@ -11,7 +11,7 @@ in | ||||
|  | ||||
|     NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf" | ||||
|       '' | ||||
|         experimental-features = nix-command flakes ca-derivations repl-flake | ||||
|         experimental-features = nix-command flakes ca-derivations | ||||
|         connect-timeout = 5 | ||||
|         fallback = true | ||||
|         ${lib.my.c.nix.cache.conf} | ||||
| @@ -24,10 +24,10 @@ in | ||||
|     coreutils | ||||
|     nixVersions.stable | ||||
|     rage | ||||
|     wireguard-tools | ||||
|     (pkgs.writeShellScriptBin "deploy" '' | ||||
|       exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@" | ||||
|     '') | ||||
|     home-manager | ||||
|     attic-client | ||||
|   ]; | ||||
| } | ||||
|   | ||||
							
								
								
									
										452
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										452
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							| @@ -8,14 +8,14 @@ | ||||
|           "ragenix", | ||||
|           "nixpkgs" | ||||
|         ], | ||||
|         "systems": "systems_6" | ||||
|         "systems": "systems_7" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1707830867, | ||||
|         "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=", | ||||
|         "lastModified": 1723293904, | ||||
|         "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=", | ||||
|         "owner": "ryantm", | ||||
|         "repo": "agenix", | ||||
|         "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6", | ||||
|         "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -24,69 +24,43 @@ | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "attic": { | ||||
|       "inputs": { | ||||
|         "crane": "crane", | ||||
|         "flake-compat": "flake-compat", | ||||
|         "flake-utils": "flake-utils", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "nixpkgs-stable": [ | ||||
|           "nixpkgs-stable" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1707922053, | ||||
|         "narHash": "sha256-wSZjK+rOXn+UQiP1NbdNn5/UW6UcBxjvlqr2wh++MbM=", | ||||
|         "owner": "zhaofengli", | ||||
|         "repo": "attic", | ||||
|         "rev": "6eabc3f02fae3683bffab483e614bebfcd476b21", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "zhaofengli", | ||||
|         "repo": "attic", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "boardie": { | ||||
|       "inputs": { | ||||
|         "devshell": "devshell", | ||||
|         "flake-utils": "flake-utils_3", | ||||
|         "flake-utils": "flake-utils_2", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "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": { | ||||
|       "inputs": { | ||||
|         "devshell": "devshell_2", | ||||
|         "flake-utils": "flake-utils_6", | ||||
|         "flake-utils": "flake-utils_5", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-mine" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1692446555, | ||||
|         "narHash": "sha256-Uzl8TiGKVBCjwYhkprSwbcu8xlcQwnDNIqsk9rM+P9w=", | ||||
|         "lastModified": 1732994213, | ||||
|         "narHash": "sha256-3v8cTsPB+TIdWmc1gmRNd0Mi0elpfi39CXRsA/2x/Oo=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "borg", | ||||
|         "rev": "44a3dc19b014ebc8d33db0b3e145ed7bfc9a0cb7", | ||||
|         "rev": "795f5009445987d42f32de1b49fdeb2d88326a64", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -96,39 +70,12 @@ | ||||
|       } | ||||
|     }, | ||||
|     "crane": { | ||||
|       "inputs": { | ||||
|         "nixpkgs": [ | ||||
|           "attic", | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1702918879, | ||||
|         "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", | ||||
|         "lastModified": 1725409566, | ||||
|         "narHash": "sha256-PrtLmqhM6UtJP7v7IGyzjBFhbG4eOAHT6LPYOFmYfbk=", | ||||
|         "owner": "ipetkov", | ||||
|         "repo": "crane", | ||||
|         "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "ipetkov", | ||||
|         "repo": "crane", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "crane_2": { | ||||
|       "inputs": { | ||||
|         "nixpkgs": [ | ||||
|           "ragenix", | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1708794349, | ||||
|         "narHash": "sha256-jX+B1VGHT0ruHHL5RwS8L21R6miBn4B6s9iVyUJsJJY=", | ||||
|         "owner": "ipetkov", | ||||
|         "repo": "crane", | ||||
|         "rev": "2c94ff9a6fbeb9f3ea0107f28688edbe9c81deaa", | ||||
|         "rev": "7e4586bad4e3f8f97a9271def747cf58c4b68f3c", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -162,18 +109,18 @@ | ||||
|     }, | ||||
|     "deploy-rs": { | ||||
|       "inputs": { | ||||
|         "flake-compat": "flake-compat_2", | ||||
|         "flake-compat": "flake-compat", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "utils": "utils" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1708091384, | ||||
|         "narHash": "sha256-dTGGw2y8wvfjr+J9CjQbfdulOq72hUG17HXVNxpH1yE=", | ||||
|         "lastModified": 1727447169, | ||||
|         "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=", | ||||
|         "owner": "serokell", | ||||
|         "repo": "deploy-rs", | ||||
|         "rev": "0a0187794ac7f7a1e62cda3dabf8dc041f868790", | ||||
|         "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -184,15 +131,15 @@ | ||||
|     }, | ||||
|     "devshell": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_2", | ||||
|         "flake-utils": "flake-utils", | ||||
|         "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": { | ||||
| @@ -203,7 +150,7 @@ | ||||
|     }, | ||||
|     "devshell-tools": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_11", | ||||
|         "flake-utils": "flake-utils_9", | ||||
|         "nixpkgs": "nixpkgs_4" | ||||
|       }, | ||||
|       "locked": { | ||||
| @@ -222,7 +169,7 @@ | ||||
|     }, | ||||
|     "devshell_2": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_5", | ||||
|         "flake-utils": "flake-utils_4", | ||||
|         "nixpkgs": "nixpkgs_3" | ||||
|       }, | ||||
|       "locked": { | ||||
| @@ -241,17 +188,16 @@ | ||||
|     }, | ||||
|     "devshell_3": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_7", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1710156081, | ||||
|         "narHash": "sha256-4PMY6aumJi5dLFjBzF5O4flKXmadMNq3AGUHKYfchh0=", | ||||
|         "lastModified": 1728330715, | ||||
|         "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "devshell", | ||||
|         "rev": "bc68b058dc7e6d4d6befc4ec6c60082b6e844b7d", | ||||
|         "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -261,22 +207,6 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-compat": { | ||||
|       "flake": false, | ||||
|       "locked": { | ||||
|         "lastModified": 1673956053, | ||||
|         "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=", | ||||
|         "owner": "edolstra", | ||||
|         "repo": "flake-compat", | ||||
|         "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "edolstra", | ||||
|         "repo": "flake-compat", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-compat_2": { | ||||
|       "flake": false, | ||||
|       "locked": { | ||||
|         "lastModified": 1696426674, | ||||
| @@ -293,12 +223,15 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils": { | ||||
|       "inputs": { | ||||
|         "systems": "systems" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1667395993, | ||||
|         "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", | ||||
|         "lastModified": 1701680307, | ||||
|         "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", | ||||
|         "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -309,7 +242,7 @@ | ||||
|     }, | ||||
|     "flake-utils_10": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_7" | ||||
|         "systems": "systems_10" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1705309234, | ||||
| @@ -326,42 +259,6 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_11": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_8" | ||||
|       }, | ||||
|       "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_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_13": { | ||||
|       "locked": { | ||||
|         "lastModified": 1667395993, | ||||
|         "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", | ||||
| @@ -377,12 +274,15 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_2": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_2" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1642700792, | ||||
|         "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", | ||||
|         "lastModified": 1710146030, | ||||
|         "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", | ||||
|         "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -393,14 +293,14 @@ | ||||
|     }, | ||||
|     "flake-utils_3": { | ||||
|       "inputs": { | ||||
|         "systems": "systems" | ||||
|         "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": { | ||||
| @@ -410,24 +310,6 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_4": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_2" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1681202837, | ||||
|         "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "cfacdce06f30d2b68473a46042957675eebb3401", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_5": { | ||||
|       "locked": { | ||||
|         "lastModified": 1642700792, | ||||
|         "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", | ||||
| @@ -442,7 +324,7 @@ | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_6": { | ||||
|     "flake-utils_5": { | ||||
|       "locked": { | ||||
|         "lastModified": 1667395993, | ||||
|         "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", | ||||
| @@ -457,16 +339,31 @@ | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_7": { | ||||
|     "flake-utils_6": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_4" | ||||
|         "systems": "systems_6" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1701680307, | ||||
|         "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", | ||||
|         "lastModified": 1731533236, | ||||
|         "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", | ||||
|         "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_7": { | ||||
|       "locked": { | ||||
|         "lastModified": 1659877975, | ||||
|         "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -477,14 +374,14 @@ | ||||
|     }, | ||||
|     "flake-utils_8": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_5" | ||||
|         "systems": "systems_8" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1701680307, | ||||
|         "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", | ||||
|         "lastModified": 1710146030, | ||||
|         "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "4022d587cbbfd70fe950c1e2083a02621806a725", | ||||
|         "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -494,12 +391,15 @@ | ||||
|       } | ||||
|     }, | ||||
|     "flake-utils_9": { | ||||
|       "inputs": { | ||||
|         "systems": "systems_9" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1659877975, | ||||
|         "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", | ||||
|         "lastModified": 1709126324, | ||||
|         "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=", | ||||
|         "owner": "numtide", | ||||
|         "repo": "flake-utils", | ||||
|         "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", | ||||
|         "rev": "d465f4819400de7c8d874d50b982301f28a84605", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -537,16 +437,16 @@ | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1706981411, | ||||
|         "narHash": "sha256-cLbLPTL1CDmETVh4p0nQtvoF+FSEjsnJTFpTxhXywhQ=", | ||||
|         "lastModified": 1732466619, | ||||
|         "narHash": "sha256-T1e5oceypZu3Q8vzICjv1X/sGs9XfJRMW5OuXHgpB3c=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "652fda4ca6dafeb090943422c34ae9145787af37", | ||||
|         "rev": "f3111f62a23451114433888902a55cf0692b408d", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "id": "home-manager", | ||||
|         "ref": "release-23.11", | ||||
|         "ref": "release-24.11", | ||||
|         "type": "indirect" | ||||
|       } | ||||
|     }, | ||||
| @@ -557,11 +457,11 @@ | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1710714957, | ||||
|         "narHash": "sha256-eZCxuF58YWgaJMMRrn8oRkwRhxooe5kBS/s2wRVr9PA=", | ||||
|         "lastModified": 1732884235, | ||||
|         "narHash": "sha256-r8j6R3nrvwbT1aUp4EPQ1KC7gm0pu9VcV1aNaB+XG6Q=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "home-manager", | ||||
|         "rev": "7b3fca5adcf6c709874a8f2e0c364fe9c58db989", | ||||
|         "rev": "819f682269f4e002884702b87e445c82840c68f2", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -571,11 +471,11 @@ | ||||
|     }, | ||||
|     "impermanence": { | ||||
|       "locked": { | ||||
|         "lastModified": 1708968331, | ||||
|         "narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=", | ||||
|         "lastModified": 1731242966, | ||||
|         "narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=", | ||||
|         "owner": "nix-community", | ||||
|         "repo": "impermanence", | ||||
|         "rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30", | ||||
|         "rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -584,19 +484,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_9", | ||||
|         "flake-utils": "flake-utils_7", | ||||
|         "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": { | ||||
| @@ -607,11 +529,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": { | ||||
| @@ -623,11 +545,11 @@ | ||||
|     }, | ||||
|     "nixpkgs-mine": { | ||||
|       "locked": { | ||||
|         "lastModified": 1710779423, | ||||
|         "narHash": "sha256-p6g1xu9UOCKgptKJUibxWvz+E5kzcbd4YdP0pWeTD8U=", | ||||
|         "lastModified": 1732985787, | ||||
|         "narHash": "sha256-6rSJ9L4QywpHLi/xvpOHdTuPm6/eOJcXxnYzDbP3U1k=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "9bcb3776d5c7ba6faf192761df3d3924f563de14", | ||||
|         "rev": "a28c46933ef5038fb7a2dd483b85152a539c7969", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -639,11 +561,11 @@ | ||||
|     }, | ||||
|     "nixpkgs-mine-stable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1710779149, | ||||
|         "narHash": "sha256-PPVvbwvboZpgWHDFqwLJgWoMmwKEjcv0uebKv21T+pE=", | ||||
|         "lastModified": 1732985894, | ||||
|         "narHash": "sha256-YYuQQCcSF6KjgtAenZJiBmqt5jqP3UvYgC424VQ+22s=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "3bc78f86abcc2e234b92beb0dd98f29c7ae88808", | ||||
|         "rev": "e0a3f4e2bbc5f7b681e344b389dcbab23f2e92a8", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -655,26 +577,26 @@ | ||||
|     }, | ||||
|     "nixpkgs-stable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1710695816, | ||||
|         "narHash": "sha256-3Eh7fhEID17pv9ZxrPwCLfqXnYP006RKzSs0JptsN84=", | ||||
|         "lastModified": 1732824227, | ||||
|         "narHash": "sha256-fYNXgpu1AEeLyd3fQt4Ym0tcVP7cdJ8wRoqJ+CtTRyY=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "614b4613980a522ba49f0d194531beddbb7220d3", | ||||
|         "rev": "c71ad5c34d51dcbda4c15f44ea4e4aa6bb6ac1e9", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "id": "nixpkgs", | ||||
|         "ref": "nixos-23.11", | ||||
|         "ref": "nixos-24.11", | ||||
|         "type": "indirect" | ||||
|       } | ||||
|     }, | ||||
|     "nixpkgs-unstable": { | ||||
|       "locked": { | ||||
|         "lastModified": 1710631334, | ||||
|         "narHash": "sha256-rL5LSYd85kplL5othxK5lmAtjyMOBg390sGBTb3LRMM=", | ||||
|         "lastModified": 1732758367, | ||||
|         "narHash": "sha256-RzaI1RO0UXqLjydtz3GAXSTzHkpb/lLD1JD8a0W4Wpo=", | ||||
|         "owner": "NixOS", | ||||
|         "repo": "nixpkgs", | ||||
|         "rev": "c75037bbf9093a2acb617804ee46320d6d1fea5a", | ||||
|         "rev": "fa42b5a5f401aab8a32bd33c9a4de0738180dc59", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -685,15 +607,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" | ||||
|       } | ||||
| @@ -748,15 +671,18 @@ | ||||
|     }, | ||||
|     "poetry2nix": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_4", | ||||
|         "nixpkgs": "nixpkgs_2" | ||||
|         "flake-utils": "flake-utils_3", | ||||
|         "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": { | ||||
| @@ -768,35 +694,35 @@ | ||||
|     "ragenix": { | ||||
|       "inputs": { | ||||
|         "agenix": "agenix", | ||||
|         "crane": "crane_2", | ||||
|         "flake-utils": "flake-utils_10", | ||||
|         "crane": "crane", | ||||
|         "flake-utils": "flake-utils_8", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "rust-overlay": "rust-overlay" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1709831932, | ||||
|         "narHash": "sha256-WsP8rOFa/SqYNbVtYJ/l2mWWOgyDTJFbITMV8tv0biI=", | ||||
|         "owner": "yaxitech", | ||||
|         "lastModified": 1731774781, | ||||
|         "narHash": "sha256-vwsUUYOIs8J6weeSK1n1mbZf8fgvygGUMsadx0JmG70=", | ||||
|         "owner": "devplayer0", | ||||
|         "repo": "ragenix", | ||||
|         "rev": "06de099ef02840ec463419f12de73729d458e1eb", | ||||
|         "rev": "ec4115da7b67c783b1091811e17dbcba50edd1c6", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "yaxitech", | ||||
|         "owner": "devplayer0", | ||||
|         "ref": "add-rekey-one-flag", | ||||
|         "repo": "ragenix", | ||||
|         "type": "github" | ||||
|       } | ||||
|     }, | ||||
|     "root": { | ||||
|       "inputs": { | ||||
|         "attic": "attic", | ||||
|         "boardie": "boardie", | ||||
|         "borgthin": "borgthin", | ||||
|         "deploy-rs": "deploy-rs", | ||||
|         "devshell": "devshell_3", | ||||
|         "flake-utils": "flake-utils_8", | ||||
|         "flake-utils": "flake-utils_6", | ||||
|         "home-manager-stable": "home-manager-stable", | ||||
|         "home-manager-unstable": "home-manager-unstable", | ||||
|         "impermanence": "impermanence", | ||||
| @@ -811,21 +737,17 @@ | ||||
|     }, | ||||
|     "rust-overlay": { | ||||
|       "inputs": { | ||||
|         "flake-utils": [ | ||||
|           "ragenix", | ||||
|           "flake-utils" | ||||
|         ], | ||||
|         "nixpkgs": [ | ||||
|           "ragenix", | ||||
|           "nixpkgs" | ||||
|         ] | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1708740535, | ||||
|         "narHash": "sha256-NCTw235XwSDbeTAtAwg/hOeNOgwYhVq7JjDdbkOgBeA=", | ||||
|         "lastModified": 1725675754, | ||||
|         "narHash": "sha256-hXW3csqePOcF2e/PYnpXj72KEYyNj2HzTrVNmS/F7Ug=", | ||||
|         "owner": "oxalica", | ||||
|         "repo": "rust-overlay", | ||||
|         "rev": "9b24383d77f598716fa0cbb8b48c97249f5ee1af", | ||||
|         "rev": "8cc45e678e914a16c8e224c3237fb07cf21e5e54", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
| @@ -836,7 +758,7 @@ | ||||
|     }, | ||||
|     "sbt": { | ||||
|       "inputs": { | ||||
|         "flake-utils": "flake-utils_13", | ||||
|         "flake-utils": "flake-utils_11", | ||||
|         "nixpkgs": "nixpkgs_5" | ||||
|       }, | ||||
|       "locked": { | ||||
| @@ -856,22 +778,22 @@ | ||||
|     "sharry": { | ||||
|       "inputs": { | ||||
|         "devshell-tools": "devshell-tools", | ||||
|         "flake-utils": "flake-utils_12", | ||||
|         "flake-utils": "flake-utils_10", | ||||
|         "nixpkgs": [ | ||||
|           "nixpkgs-unstable" | ||||
|         ], | ||||
|         "sbt": "sbt" | ||||
|       }, | ||||
|       "locked": { | ||||
|         "lastModified": 1710796573, | ||||
|         "narHash": "sha256-23fLZFNacZU/skc8i7JExHfD//Mpkslhga6f5ATTqBA=", | ||||
|         "owner": "devplayer0", | ||||
|         "lastModified": 1720592125, | ||||
|         "narHash": "sha256-vR89LefkY8mBPWxDTQ8SNg6Z7/J6Yga80T4kSb6MNdk=", | ||||
|         "owner": "eikek", | ||||
|         "repo": "sharry", | ||||
|         "rev": "4e7a87880ba0807afd5d21706ce383b8b8727990", | ||||
|         "rev": "604b20517150599cb05dbe178cd35cd10659aa4c", | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "devplayer0", | ||||
|         "owner": "eikek", | ||||
|         "repo": "sharry", | ||||
|         "type": "github" | ||||
|       } | ||||
| @@ -891,6 +813,21 @@ | ||||
|         "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_2": { | ||||
|       "locked": { | ||||
|         "lastModified": 1681028828, | ||||
| @@ -931,9 +868,8 @@ | ||||
|         "type": "github" | ||||
|       }, | ||||
|       "original": { | ||||
|         "owner": "nix-systems", | ||||
|         "repo": "default", | ||||
|         "type": "github" | ||||
|         "id": "systems", | ||||
|         "type": "indirect" | ||||
|       } | ||||
|     }, | ||||
|     "systems_5": { | ||||
| @@ -1011,9 +947,31 @@ | ||||
|         "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, | ||||
|   | ||||
							
								
								
									
										35
									
								
								flake.nix
									
									
									
									
									
								
							
							
						
						
									
										35
									
								
								flake.nix
									
									
									
									
									
								
							| @@ -7,37 +7,34 @@ | ||||
|     devshell.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|  | ||||
|     nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; | ||||
|     nixpkgs-stable.url = "nixpkgs/nixos-23.11"; | ||||
|     nixpkgs-stable.url = "nixpkgs/nixos-24.11"; | ||||
|     nixpkgs-mine.url = "github:devplayer0/nixpkgs/devplayer0"; | ||||
|     nixpkgs-mine-stable.url = "github:devplayer0/nixpkgs/devplayer0-stable"; | ||||
|  | ||||
|     home-manager-unstable.url = "home-manager"; | ||||
|     home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|     home-manager-stable.url = "home-manager/release-23.11"; | ||||
|     home-manager-stable.url = "home-manager/release-24.11"; | ||||
|     home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable"; | ||||
|  | ||||
|     # Stuff used by the flake for build / deployment | ||||
|     ragenix.url = "github:yaxitech/ragenix"; | ||||
|     # ragenix.url = "github:yaxitech/ragenix"; | ||||
|     ragenix.url = "github:devplayer0/ragenix/add-rekey-one-flag"; | ||||
|     ragenix.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|     deploy-rs.url = "github:serokell/deploy-rs"; | ||||
|     deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|  | ||||
|     # Stuff used by systems | ||||
|     impermanence.url = "github:nix-community/impermanence"; | ||||
|     boardie.url = "github:devplayer0/boardie"; | ||||
|     boardie.url = "git+https://git.nul.ie/dev/boardie"; | ||||
|     boardie.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|     nixGL.url = "github:nix-community/nixGL"; | ||||
|     nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|  | ||||
|     # Packages not in nixpkgs | ||||
|     # sharry.url = "github:eikek/sharry"; | ||||
|     sharry.url = "github:devplayer0/sharry"; | ||||
|     sharry.url = "github:eikek/sharry"; | ||||
|     sharry.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|     borgthin.url = "github:devplayer0/borg"; | ||||
|     borgthin.inputs.nixpkgs.follows = "nixpkgs-mine"; | ||||
|     attic.url = "github:zhaofengli/attic"; | ||||
|     attic.inputs.nixpkgs.follows = "nixpkgs-unstable"; | ||||
|     attic.inputs.nixpkgs-stable.follows = "nixpkgs-stable"; | ||||
|   }; | ||||
|  | ||||
|   outputs = | ||||
| @@ -52,7 +49,7 @@ | ||||
|       ... | ||||
|     }: | ||||
|     let | ||||
|       inherit (builtins) mapAttrs replaceStrings; | ||||
|       inherit (builtins) mapAttrs replaceStrings elem; | ||||
|       inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules; | ||||
|       inherit (lib.flake) flattenTree eachDefaultSystem; | ||||
|       inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay; | ||||
| @@ -96,7 +93,6 @@ | ||||
|             inputs.ragenix.overlays.default | ||||
|             inputs.deploy-rs.overlay | ||||
|             (flakePackageOverlay inputs.home-manager-unstable system) | ||||
|             inputs.attic.overlays.default | ||||
|           ]; | ||||
|         })) | ||||
|         pkgsFlakes; | ||||
| @@ -108,6 +104,16 @@ | ||||
|             pkgsLibOverlay | ||||
|             myPkgsOverlay | ||||
|           ]; | ||||
|  | ||||
|           config = { | ||||
|             # RMS forgive me... | ||||
|             # Normally this is set modularly, but sometimes we need to use other pkgs | ||||
|             allowUnfreePredicate = p: elem (lib.getName p) [ | ||||
|               "widevine-cdm" | ||||
|               "chromium-unwrapped" | ||||
|               "chromium" | ||||
|             ]; | ||||
|           }; | ||||
|         })) | ||||
|         pkgsFlakes; | ||||
|  | ||||
| @@ -116,9 +122,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 | ||||
|  | ||||
| @@ -198,8 +204,9 @@ | ||||
|         systems' = mapAttrs' (n: v: nameValuePair "system-${n}" v) systems; | ||||
|         packages' = mapAttrs' (n: v: nameValuePair "package-${n}" v) packages; | ||||
|       in | ||||
|         pkgs.linkFarm "ci" (homes' // systems' // packages' // { | ||||
|         homes' // systems' // packages' // { | ||||
|           inherit shell; | ||||
|         }); | ||||
|         }; | ||||
|       ciDrv = pkgs.linkFarm "ci" ci; | ||||
|     })); | ||||
| } | ||||
|   | ||||
| @@ -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' | ||||
| @@ -1,6 +1,6 @@ | ||||
| { lib, pkgs, config, ... }: | ||||
| { lib, pkgs', pkgs, config, ... }: | ||||
| let | ||||
|   inherit (lib) genAttrs mkIf mkMerge mkForce; | ||||
|   inherit (lib) genAttrs mkIf mkMerge mkForce mapAttrs mkOptionDefault; | ||||
|   inherit (lib.my) mkBoolOpt'; | ||||
|  | ||||
|   cfg = config.my.gui; | ||||
| @@ -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 = { | ||||
| @@ -22,10 +39,11 @@ in | ||||
|       { | ||||
|         home = { | ||||
|           packages = with pkgs; [ | ||||
|             xdg-utils | ||||
|  | ||||
|             font.package | ||||
|             (nerdfonts.override { | ||||
|               fonts = [ "DroidSansMono" "SourceCodePro" ]; | ||||
|             }) | ||||
|             nerd-fonts.sauce-code-pro | ||||
|             nerd-fonts.droid-sans-mono | ||||
|             noto-fonts-emoji | ||||
|  | ||||
|             grim | ||||
| @@ -36,7 +54,17 @@ in | ||||
|             nil # nix language server | ||||
|             zls # zig language server | ||||
|             rust-analyzer | ||||
|  | ||||
|             cowsay | ||||
|             fortune | ||||
|             jp2a | ||||
|             terminaltexteffects | ||||
|             screenfetch | ||||
|             neofetch | ||||
|             cmatrix | ||||
|             doomsaver | ||||
|  | ||||
|             xournalpp | ||||
|           ]; | ||||
|         }; | ||||
|  | ||||
| @@ -51,7 +79,15 @@ in | ||||
|           alacritty = { | ||||
|             enable = true; | ||||
|             settings = { | ||||
|               font.normal.family = font.name; | ||||
|               general.import = [ ./alacritty-xterm.toml ]; | ||||
|  | ||||
|               font = { | ||||
|                 size = font.size; | ||||
|                 normal = { | ||||
|                   family = font.name; | ||||
|                   style = "Regular"; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
| @@ -59,9 +95,29 @@ in | ||||
|             enable = true; | ||||
|             inherit font; | ||||
|             settings = { | ||||
|               background_opacity = "0.8"; | ||||
|               background_opacity = "0.65"; | ||||
|               tab_bar_edge = "top"; | ||||
|               shell_integration = "no-sudo"; | ||||
|               font_features = "${font.name} -liga"; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           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"; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
| @@ -108,6 +164,19 @@ in | ||||
|               }; | ||||
|               Install.RequiredBy = [ "sway-session.target" ]; | ||||
|             }; | ||||
|  | ||||
|             activate-linux = { | ||||
|               Unit = { | ||||
|                 Description = "Linux activation watermark"; | ||||
|                 After = "graphical-session.target"; | ||||
|                 PartOf = "graphical-session.target"; | ||||
|               }; | ||||
|               Service = { | ||||
|                 Type = "simple"; | ||||
|                 ExecStart = "${pkgs.activate-linux}/bin/activate-linux"; | ||||
|               }; | ||||
|               Install.RequiredBy = [ "graphical-session.target" ]; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
| @@ -117,6 +186,7 @@ in | ||||
|             wl-clipboard | ||||
|             wev | ||||
|             wdisplays | ||||
|             swaysome | ||||
|  | ||||
|             pavucontrol | ||||
|             libsecret | ||||
| @@ -126,10 +196,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; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
| @@ -138,9 +209,36 @@ in | ||||
|         xsession.preferStatusNotifierItems = true; | ||||
|         wayland = { | ||||
|           windowManager = { | ||||
|             sway = { | ||||
|             sway = | ||||
|             let | ||||
|               cfg = config.wayland.windowManager.sway.config; | ||||
|               mod = cfg.modifier; | ||||
|  | ||||
|               renameWs = pkgs.writeShellScript "sway-rename-ws" '' | ||||
|                 focused_ws="$(swaymsg -t get_workspaces | jq ".[] | select(.focused)")" | ||||
|                 focused_num="$(jq -r ".num" <<< "$focused_ws")" | ||||
|                 focused_name="$(jq -r ".name" <<< "$focused_ws")" | ||||
|                 placeholder="$(sed -E 's/[0-9]+: //' <<< "$focused_name")" | ||||
|  | ||||
|                 name="$(rofi -dmenu -p "rename ws $focused_num" -theme+entry+placeholder "\"$placeholder\"")" | ||||
|                 if [ -n "$name" ]; then | ||||
|                   swaymsg rename workspace "$focused_name" to "$focused_num: $name" | ||||
|                 fi | ||||
|               ''; | ||||
|               clearWsName = pkgs.writeShellScript "sway-clear-ws-name" '' | ||||
|                 focused_ws="$(swaymsg -t get_workspaces | jq ".[] | select(.focused)")" | ||||
|                 focused_num="$(jq -r ".num" <<< "$focused_ws")" | ||||
|                 focused_name="$(jq -r ".name" <<< "$focused_ws")" | ||||
|  | ||||
|                 swaymsg rename workspace "$focused_name" to "$focused_num" | ||||
|               ''; | ||||
|             in | ||||
|             { | ||||
|               enable = true; | ||||
|               xwayland = true; | ||||
|               extraConfigEarly = '' | ||||
|                 set $mod ${mod} | ||||
|               ''; | ||||
|               config = { | ||||
|                 input = { | ||||
|                   "type:touchpad" = { | ||||
| @@ -155,31 +253,95 @@ in | ||||
|  | ||||
|                 modifier = "Mod4"; | ||||
|                 terminal = "kitty"; | ||||
|                 keybindings = | ||||
|                   let | ||||
|                     cfg = config.wayland.windowManager.sway.config; | ||||
|                     mod = cfg.modifier; | ||||
|                   in | ||||
|                   lib.mkOptionDefault { | ||||
|                     "${mod}+d" = null; | ||||
|                     "${mod}+l" = "exec swaylock -i ${./lock.png} -s stretch"; | ||||
|                     "${mod}+x" = "exec ${cfg.menu}"; | ||||
|                     "${mod}+Shift+x" = "exec rofi -show drun"; | ||||
|                     "${mod}+q" = "kill"; | ||||
|                     "${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'"; | ||||
|                     "${mod}+Shift+d" = ''exec grim - | swappy -f -''; | ||||
|                     "${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -''; | ||||
|                     "${mod}+Shift+e" = "exec rofi -show emoji"; | ||||
|                     # Config for this doesn't seem to work :/ | ||||
|                     "${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"''; | ||||
|                 keybindings = mapAttrs (k: mkOptionDefault) { | ||||
|                   "${mod}+Left" = "focus left"; | ||||
|                   "${mod}+Down" = "focus down"; | ||||
|                   "${mod}+Up" = "focus up"; | ||||
|                   "${mod}+Right" = "focus right"; | ||||
|  | ||||
|                     "XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5"; | ||||
|                     "XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; | ||||
|                     "XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play"; | ||||
|                     "XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause"; | ||||
|                     "XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next"; | ||||
|                     "XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous"; | ||||
|                   }; | ||||
|                   "${mod}+Shift+Left" = "move left"; | ||||
|                   "${mod}+Shift+Down" = "move down"; | ||||
|                   "${mod}+Shift+Up" = "move up"; | ||||
|                   "${mod}+Shift+Right" = "move right"; | ||||
|  | ||||
|                   "${mod}+b" = "splith"; | ||||
|                   "${mod}+v" = "splitv"; | ||||
|                   "${mod}+f" = "fullscreen toggle"; | ||||
|                   "${mod}+a" = "focus parent"; | ||||
|  | ||||
|                   "${mod}+s" = "layout stacking"; | ||||
|                   "${mod}+w" = "layout tabbed"; | ||||
|                   "${mod}+e" = "layout toggle split"; | ||||
|  | ||||
|                   "${mod}+Shift+space" = "floating toggle"; | ||||
|                   "${mod}+space" = "focus mode_toggle"; | ||||
|  | ||||
|                   "${mod}+1" = "workspace number 1"; | ||||
|                   "${mod}+2" = "workspace number 2"; | ||||
|                   "${mod}+3" = "workspace number 3"; | ||||
|                   "${mod}+4" = "workspace number 4"; | ||||
|                   "${mod}+5" = "workspace number 5"; | ||||
|                   "${mod}+6" = "workspace number 6"; | ||||
|                   "${mod}+7" = "workspace number 7"; | ||||
|                   "${mod}+8" = "workspace number 8"; | ||||
|                   "${mod}+9" = "workspace number 9"; | ||||
|                   "${mod}+0" = "workspace number 10"; | ||||
|  | ||||
|                   "${mod}+Shift+1" = | ||||
|                     "move container to workspace number 1"; | ||||
|                   "${mod}+Shift+2" = | ||||
|                     "move container to workspace number 2"; | ||||
|                   "${mod}+Shift+3" = | ||||
|                     "move container to workspace number 3"; | ||||
|                   "${mod}+Shift+4" = | ||||
|                     "move container to workspace number 4"; | ||||
|                   "${mod}+Shift+5" = | ||||
|                     "move container to workspace number 5"; | ||||
|                   "${mod}+Shift+6" = | ||||
|                     "move container to workspace number 6"; | ||||
|                   "${mod}+Shift+7" = | ||||
|                     "move container to workspace number 7"; | ||||
|                   "${mod}+Shift+8" = | ||||
|                     "move container to workspace number 8"; | ||||
|                   "${mod}+Shift+9" = | ||||
|                     "move container to workspace number 9"; | ||||
|                   "${mod}+Shift+0" = | ||||
|                     "move container to workspace number 10"; | ||||
|  | ||||
|                   "${mod}+Shift+minus" = "move scratchpad"; | ||||
|                   "${mod}+minus" = "scratchpad show"; | ||||
|  | ||||
|                   "${mod}+Return" = "exec ${cfg.terminal}"; | ||||
|                   "${mod}+r" = "mode resize"; | ||||
|                   "${mod}+d" = null; | ||||
|                   "${mod}+l" = "exec ${doomsaver}/bin/doomsaver"; | ||||
|                   "${mod}+q" = "kill"; | ||||
|                   "${mod}+Shift+c" = "reload"; | ||||
|                   "${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'"; | ||||
|  | ||||
|                   # rofi | ||||
|                   "${mod}+x" = "exec ${cfg.menu}"; | ||||
|                   "${mod}+Shift+x" = "exec rofi -show drun"; | ||||
|                   "${mod}+Shift+e" = "exec rofi -show emoji"; | ||||
|                   # Config for this doesn't seem to work :/ | ||||
|                   "${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"''; | ||||
|                   "${mod}+Shift+r" = "exec ${renameWs}"; | ||||
|                   "${mod}+Shift+n" = "exec ${clearWsName}"; | ||||
|  | ||||
|                   # Screenshots | ||||
|                   "${mod}+Shift+d" = ''exec grim - | swappy -f -''; | ||||
|                   "${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -''; | ||||
|  | ||||
|                   "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-"; | ||||
|                   "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%"; | ||||
|  | ||||
|                   "XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5"; | ||||
|                   "XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; | ||||
|                   "XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play"; | ||||
|                   "XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause"; | ||||
|                   "XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next"; | ||||
|                   "XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous"; | ||||
|                 }; | ||||
|                 keycodebindings = { | ||||
|                   # keycode for XF86AudioPlayPause (no sym for some reason) | ||||
|                   "172" = "exec ${pkgs.playerctl}/bin/playerctl play-pause"; | ||||
| @@ -188,6 +350,9 @@ in | ||||
|                 menu = "rofi -show run"; | ||||
|                 bars = mkForce [ ]; | ||||
|               }; | ||||
|               extraConfig = '' | ||||
|                 include ${./swaysome.conf} | ||||
|               ''; | ||||
|  | ||||
|               swaynag = { | ||||
|                 enable = true; | ||||
| @@ -210,17 +375,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; | ||||
| @@ -245,6 +403,7 @@ in | ||||
|             diff-so-fancy.enable = true; | ||||
|             userEmail = "jackos1998@gmail.com"; | ||||
|             userName = "Jack O'Sullivan"; | ||||
|             lfs.enable = true; | ||||
|             extraConfig = { | ||||
|               pull.rebase = true; | ||||
|             }; | ||||
| @@ -252,11 +411,13 @@ in | ||||
|  | ||||
|           waybar = import ./waybar.nix { inherit lib pkgs config font; }; | ||||
|           rofi = { | ||||
|             package = pkgs.rofi-wayland; | ||||
|             enable = true; | ||||
|             font = "${font.name} ${toString font.size}"; | ||||
|             plugins = with pkgs; [ | ||||
|             plugins = with pkgs; (map (p: p.override { rofi-unwrapped = rofi-wayland-unwrapped; }) [ | ||||
|               rofi-calc | ||||
|               rofi-emoji | ||||
|             ]) ++ [ | ||||
|               rofi-emoji-wayland | ||||
|             ]; | ||||
|             extraConfig = { | ||||
|               modes = "window,run,ssh,filebrowser,calc,emoji"; | ||||
| @@ -271,7 +432,7 @@ in | ||||
|  | ||||
|           chromium = { | ||||
|             enable = true; | ||||
|             package = (pkgs.chromium.override { enableWideVine = true; }).overrideAttrs (old: { | ||||
|             package = (pkgs'.unstable.chromium.override { enableWideVine = true; }).overrideAttrs (old: { | ||||
|               buildCommand = '' | ||||
|                 ${old.buildCommand} | ||||
|  | ||||
| @@ -297,6 +458,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 | 
							
								
								
									
										66
									
								
								home-manager/modules/gui/swaysome.conf
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								home-manager/modules/gui/swaysome.conf
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,66 @@ | ||||
| # Use (un)bindcode or (un)bindsym, depending on what you used in your main sway config file. | ||||
| # The `--no-warn` setting is only added to shortcuts that exist in the default config. You may want to add or remove | ||||
| # that flag on some bindings depending on your config. | ||||
|  | ||||
|  | ||||
| # Change focus between workspaces | ||||
| bindsym $mod+Alt+1 exec "swaysome focus 1" | ||||
| bindsym $mod+Alt+2 exec "swaysome focus 2" | ||||
| bindsym $mod+Alt+3 exec "swaysome focus 3" | ||||
| bindsym $mod+Alt+4 exec "swaysome focus 4" | ||||
| bindsym $mod+Alt+5 exec "swaysome focus 5" | ||||
| bindsym $mod+Alt+6 exec "swaysome focus 6" | ||||
| bindsym $mod+Alt+7 exec "swaysome focus 7" | ||||
| bindsym $mod+Alt+8 exec "swaysome focus 8" | ||||
| bindsym $mod+Alt+9 exec "swaysome focus 9" | ||||
| bindsym $mod+Alt+0 exec "swaysome focus 0" | ||||
|  | ||||
| # Focus workspace groups | ||||
| bindsym --no-warn $mod+1 exec "swaysome focus-group 1" | ||||
| bindsym --no-warn $mod+2 exec "swaysome focus-group 2" | ||||
| bindsym --no-warn $mod+3 exec "swaysome focus-group 3" | ||||
| bindsym --no-warn $mod+4 exec "swaysome focus-group 4" | ||||
| bindsym --no-warn $mod+5 exec "swaysome focus-group 5" | ||||
| bindsym --no-warn $mod+6 exec "swaysome focus-group 6" | ||||
| bindsym --no-warn $mod+7 exec "swaysome focus-group 7" | ||||
| bindsym --no-warn $mod+8 exec "swaysome focus-group 8" | ||||
| bindsym --no-warn $mod+9 exec "swaysome focus-group 9" | ||||
| bindsym --no-warn $mod+0 exec "swaysome focus-group 0" | ||||
|  | ||||
| # Move containers between workspaces | ||||
| bindsym $mod+Alt+Shift+1 exec "swaysome move 1" | ||||
| bindsym $mod+Alt+Shift+2 exec "swaysome move 2" | ||||
| bindsym $mod+Alt+Shift+3 exec "swaysome move 3" | ||||
| bindsym $mod+Alt+Shift+4 exec "swaysome move 4" | ||||
| bindsym $mod+Alt+Shift+5 exec "swaysome move 5" | ||||
| bindsym $mod+Alt+Shift+6 exec "swaysome move 6" | ||||
| bindsym $mod+Alt+Shift+7 exec "swaysome move 7" | ||||
| bindsym $mod+Alt+Shift+8 exec "swaysome move 8" | ||||
| bindsym $mod+Alt+Shift+9 exec "swaysome move 9" | ||||
| bindsym $mod+Alt+Shift+0 exec "swaysome move 0" | ||||
|  | ||||
| # Move containers to other workspace groups | ||||
| bindsym --no-warn $mod+Shift+1 exec "swaysome move-to-group 1" | ||||
| bindsym --no-warn $mod+Shift+2 exec "swaysome move-to-group 2" | ||||
| bindsym --no-warn $mod+Shift+3 exec "swaysome move-to-group 3" | ||||
| bindsym --no-warn $mod+Shift+4 exec "swaysome move-to-group 4" | ||||
| bindsym --no-warn $mod+Shift+5 exec "swaysome move-to-group 5" | ||||
| bindsym --no-warn $mod+Shift+6 exec "swaysome move-to-group 6" | ||||
| bindsym --no-warn $mod+Shift+7 exec "swaysome move-to-group 7" | ||||
| bindsym --no-warn $mod+Shift+8 exec "swaysome move-to-group 8" | ||||
| bindsym --no-warn $mod+Shift+9 exec "swaysome move-to-group 9" | ||||
| bindsym --no-warn $mod+Shift+0 exec "swaysome move-to-group 0" | ||||
|  | ||||
| # Move focused container to next output | ||||
| bindsym $mod+Alt+Right exec "swaysome next-output" | ||||
| # Move focused container to previous output | ||||
| bindsym $mod+Alt+Left exec "swaysome prev-output" | ||||
|  | ||||
| # Move focused workspace group to next output | ||||
| bindsym $mod+Shift+Alt+Right exec "swaysome workspace-group-next-output" | ||||
| # Move focused workspace group to previous output | ||||
| bindsym $mod+Shift+Alt+Left exec "swaysome workspace-group-prev-output" | ||||
|  | ||||
| # Init workspaces for every screen | ||||
| exec "swaysome init 1" | ||||
|  | ||||
| @@ -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_6; | ||||
|     latest = pkgs: pkgs.linuxKernel.packages.linux_6_8; | ||||
|     latest = pkgs: pkgs.linuxKernel.packages.linux_6_12; | ||||
|   }; | ||||
|  | ||||
|   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 { | ||||
| @@ -131,6 +135,9 @@ rec { | ||||
|         v4 = subnet 8 3 all.v4; | ||||
|         v6 = subnet 4 3 all.v6; | ||||
|       }; | ||||
|       qclk = { | ||||
|         v4 = subnet 8 4 all.v4; | ||||
|       }; | ||||
|  | ||||
|       cust = { | ||||
|         v4 = subnet 8 100 all.v4; # single ip for routing only | ||||
| @@ -144,6 +151,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 +167,16 @@ 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; | ||||
|     }; | ||||
|  | ||||
|     qclk = { | ||||
|       wgPort = 51821; | ||||
|     }; | ||||
|  | ||||
|     firewallForwards = aa: [ | ||||
|       { | ||||
|         port = "http"; | ||||
| @@ -169,6 +190,7 @@ rec { | ||||
|         port = 8448; | ||||
|         dst = aa.middleman.internal.ipv4.address; | ||||
|       } | ||||
|  | ||||
|       { | ||||
|         port = 25565; | ||||
|         dst = aa.simpcraft-oci.internal.ipv4.address; | ||||
| @@ -177,6 +199,7 @@ rec { | ||||
|         port = 25566; | ||||
|         dst = aa.simpcraft-staging-oci.internal.ipv4.address; | ||||
|       } | ||||
|  | ||||
|       { | ||||
|         port = 25575; | ||||
|         dst = aa.simpcraft-oci.internal.ipv4.address; | ||||
| @@ -204,6 +227,23 @@ rec { | ||||
|         dst = aa.simpcraft-oci.internal.ipv4.address; | ||||
|         proto = "udp"; | ||||
|       } | ||||
|  | ||||
|       { | ||||
|         port = 15636; | ||||
|         dst = aa.enshrouded-oci.internal.ipv4.address; | ||||
|         proto = "udp"; | ||||
|       } | ||||
|       { | ||||
|         port = 15637; | ||||
|         dst = aa.enshrouded-oci.internal.ipv4.address; | ||||
|         proto = "udp"; | ||||
|       } | ||||
|  | ||||
|       { | ||||
|         port = qclk.wgPort; | ||||
|         dst = aa.qclk.internal.ipv4.address; | ||||
|         proto = "udp"; | ||||
|       } | ||||
|     ]; | ||||
|  | ||||
|     fstrimConfig = { | ||||
| @@ -227,7 +267,7 @@ rec { | ||||
|       "stream" | ||||
|     ]; | ||||
|     routersPubV4 = [ | ||||
|       "109.255.31.158" | ||||
|       "109.255.31.155" | ||||
|       "109.255.252.63" | ||||
|     ]; | ||||
|  | ||||
| @@ -277,6 +317,8 @@ rec { | ||||
|         v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     roceBootModules = [ "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" ]; | ||||
|   }; | ||||
|  | ||||
|   britway = { | ||||
| @@ -327,6 +369,7 @@ rec { | ||||
|     }; | ||||
|  | ||||
|     domain = "hentai.engineer"; | ||||
|     ipv4MTU = 1460; | ||||
|     vpn = { | ||||
|       port = 51820; | ||||
|     }; | ||||
| @@ -340,6 +383,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 = "24.03:u-${prev.trivial.release}"; | ||||
|       codeName = "Bruh"; | ||||
|       release = "24.12:u-${prev.trivial.release}"; | ||||
|       codeName = "Epic"; | ||||
|       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"; | ||||
|     } | ||||
|   ]; | ||||
| } | ||||
|   | ||||
| @@ -106,7 +106,7 @@ in | ||||
|                   { | ||||
|                     matchConfig.Name = "as211024"; | ||||
|                     networkConfig.IPv6AcceptRA = mkForce false; | ||||
|                     routes = map (r: { routeConfig = r; }) [ | ||||
|                     routes = [ | ||||
|                       { | ||||
|                         Destination = lib.my.c.colony.prefixes.all.v4; | ||||
|                         Gateway = allAssignments.estuary.as211024.ipv4.address; | ||||
| @@ -123,7 +123,7 @@ in | ||||
|                         Table = "ts-extra"; | ||||
|                       } | ||||
|                     ]; | ||||
|                     routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ | ||||
|                     routingPolicyRules = [ | ||||
|                       { | ||||
|                         IncomingInterface = "tailscale0"; | ||||
|                         To = lib.my.c.colony.prefixes.all.v6; | ||||
|   | ||||
| @@ -80,7 +80,7 @@ in | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             "ts.${pubDomain}" = { | ||||
|             "hs.${pubDomain}" = { | ||||
|               locations."/" = { | ||||
|                 proxyPass = "http://localhost:${toString config.services.headscale.port}"; | ||||
|                 proxyWebsockets = true; | ||||
|   | ||||
| @@ -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 | ||||
| @@ -39,19 +41,20 @@ in | ||||
|     services = { | ||||
|       headscale = { | ||||
|         enable = true; | ||||
|         package = headscale; | ||||
|         settings = { | ||||
|           disable_check_updates = true; | ||||
|           unix_socket_permission = "0770"; | ||||
|           server_url = "https://ts.${pubDomain}"; | ||||
|           db_type = "sqlite3"; | ||||
|           db_path = "/var/lib/headscale/db.sqlite3"; | ||||
|           server_url = "https://hs.${pubDomain}"; | ||||
|           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 ]; | ||||
|           dns_config = { | ||||
|           prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; }; | ||||
|           dns = { | ||||
|             # Use IPs that will route inside the VPN to prevent interception | ||||
|             # (e.g. DNS rebinding filtering) | ||||
|             restricted_nameservers = { | ||||
|             nameservers.split = { | ||||
|               "${domain}" = pubNameservers; | ||||
|               "${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [ | ||||
|                 ipv4.address ipv6.address | ||||
| @@ -65,7 +68,6 @@ in | ||||
|             }; | ||||
|             magic_dns = true; | ||||
|             base_domain = "ts.${pubDomain}"; | ||||
|             override_local_dns = false; | ||||
|           }; | ||||
|           oidc = { | ||||
|             only_start_if_oidc_is_available = true; | ||||
| @@ -85,7 +87,7 @@ in | ||||
|         interfaceName = "tailscale0"; | ||||
|         extraUpFlags = [ | ||||
|           "--operator=${config.my.user.config.name}" | ||||
|           "--login-server=https://ts.nul.ie" | ||||
|           "--login-server=https://hs.nul.ie" | ||||
|           "--netfilter-mode=off" | ||||
|           "--advertise-exit-node" | ||||
|           "--advertise-routes=${advRoutes}" | ||||
|   | ||||
| @@ -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 = { | ||||
| @@ -252,10 +252,10 @@ in | ||||
|                   }; | ||||
|                   ipv6Prefixes = [ | ||||
|                     { | ||||
|                       ipv6PrefixConfig.Prefix = prefixes.vms.v6; | ||||
|                       Prefix = prefixes.vms.v6; | ||||
|                     } | ||||
|                   ]; | ||||
|                   routes = map (r: { routeConfig = r; }) [ | ||||
|                   routes = [ | ||||
|                     { | ||||
|                       Destination = prefixes.ctrs.v4; | ||||
|                       Gateway = allAssignments.shill.routing.ipv4.address; | ||||
| @@ -264,10 +264,12 @@ in | ||||
|                       Destination = prefixes.ctrs.v6; | ||||
|                       Gateway = allAssignments.shill.internal.ipv6.address; | ||||
|                     } | ||||
|  | ||||
|                     { | ||||
|                       Destination = allAssignments.shill.internal.ipv4.address; | ||||
|                       Gateway = allAssignments.shill.routing.ipv4.address; | ||||
|                     } | ||||
|  | ||||
|                     { | ||||
|                       Destination = lib.my.c.tailscale.prefix.v4; | ||||
|                       Gateway = allAssignments.shill.routing.ipv4.address; | ||||
| @@ -276,6 +278,15 @@ in | ||||
|                       Destination = lib.my.c.tailscale.prefix.v6; | ||||
|                       Gateway = allAssignments.shill.internal.ipv6.address; | ||||
|                     } | ||||
|                     { | ||||
|                       Destination = prefixes.qclk.v4; | ||||
|                       Gateway = allAssignments.shill.routing.ipv4.address; | ||||
|                     } | ||||
|  | ||||
|                     { | ||||
|                       Destination = prefixes.jam.v6; | ||||
|                       Gateway = allAssignments.shill.internal.ipv6.address; | ||||
|                     } | ||||
|  | ||||
|                     { | ||||
|                       Destination = prefixes.oci.v4; | ||||
| @@ -307,7 +318,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 = { | ||||
| @@ -316,10 +327,10 @@ in | ||||
|                 }; | ||||
|                 ipv6Prefixes = [ | ||||
|                   { | ||||
|                     ipv6PrefixConfig.Prefix = prefixes.mail.v6; | ||||
|                     Prefix = prefixes.mail.v6; | ||||
|                   } | ||||
|                 ]; | ||||
|                 routes = map (r: { routeConfig = r; }) [ | ||||
|                 routes = [ | ||||
|                   { | ||||
|                     Destination = prefixes.mail.v4; | ||||
|                     Scope = "link"; | ||||
| @@ -330,7 +341,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 = { | ||||
| @@ -339,10 +350,10 @@ in | ||||
|                 }; | ||||
|                 ipv6Prefixes = [ | ||||
|                   { | ||||
|                     ipv6PrefixConfig.Prefix = prefixes.darts.v6; | ||||
|                     Prefix = prefixes.darts.v6; | ||||
|                   } | ||||
|                 ]; | ||||
|                 routes = map (r: { routeConfig = r; }) [ | ||||
|                 routes = [ | ||||
|                   { | ||||
|                     Destination = prefixes.darts.v4; | ||||
|                     Scope = "link"; | ||||
|   | ||||
| @@ -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 = { | ||||
| @@ -163,11 +164,9 @@ in | ||||
|                     }; | ||||
|                     wireguardPeers = [ | ||||
|                       { | ||||
|                         wireguardPeerConfig = { | ||||
|                           PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E="; | ||||
|                           AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ]; | ||||
|                           PersistentKeepalive = 25; | ||||
|                         }; | ||||
|                         PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E="; | ||||
|                         AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ]; | ||||
|                         PersistentKeepalive = 25; | ||||
|                       } | ||||
|                     ]; | ||||
|                   }; | ||||
| @@ -277,47 +276,51 @@ in | ||||
|                     }; | ||||
|                     ipv6Prefixes = [ | ||||
|                       { | ||||
|                         ipv6PrefixConfig.Prefix = prefixes.base.v6; | ||||
|                         Prefix = prefixes.base.v6; | ||||
|                       } | ||||
|                     ]; | ||||
|                     routes = map (r: { routeConfig = r; }) (flatten | ||||
|                       ([ | ||||
|                         { | ||||
|                           Destination = prefixes.vip1; | ||||
|                           Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                         } | ||||
|                         { | ||||
|                           Destination = prefixes.vip3; | ||||
|                           Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                         } | ||||
|                         { | ||||
|                           Destination = prefixes.darts.v4; | ||||
|                           Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                         } | ||||
|                         { | ||||
|                           Destination = prefixes.cust.v6; | ||||
|                           Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                         } | ||||
|                     routes = flatten ([ | ||||
|                       { | ||||
|                         Destination = prefixes.vip1; | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                       } | ||||
|                       { | ||||
|                         Destination = prefixes.vip3; | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                       } | ||||
|                       { | ||||
|                         Destination = prefixes.darts.v4; | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                       } | ||||
|                       { | ||||
|                         Destination = prefixes.cust.v6; | ||||
|                         Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                       } | ||||
|  | ||||
|                         { | ||||
|                           Destination = lib.my.c.tailscale.prefix.v4; | ||||
|                           Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                         } | ||||
|                         { | ||||
|                           Destination = lib.my.c.tailscale.prefix.v6; | ||||
|                           Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                         } | ||||
|                       ] ++ | ||||
|                       (map (pName: [ | ||||
|                         { | ||||
|                           Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                           Destination = prefixes."${pName}".v4; | ||||
|                         } | ||||
|                         { | ||||
|                           Destination = prefixes."${pName}".v6; | ||||
|                           Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                         } | ||||
|                       ]) [ "vms" "ctrs" "oci" ]))); | ||||
|                       { | ||||
|                         Destination = lib.my.c.tailscale.prefix.v4; | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                       } | ||||
|                       { | ||||
|                         Destination = lib.my.c.tailscale.prefix.v6; | ||||
|                         Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                       } | ||||
|  | ||||
|                       { | ||||
|                         Destination = prefixes.qclk.v4; | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                       } | ||||
|                     ] ++ | ||||
|                     (map (pName: [ | ||||
|                       { | ||||
|                         Gateway = allAssignments.colony.routing.ipv4.address; | ||||
|                         Destination = prefixes."${pName}".v4; | ||||
|                       } | ||||
|                       { | ||||
|                         Destination = prefixes."${pName}".v6; | ||||
|                         Gateway = allAssignments.colony.internal.ipv6.address; | ||||
|                       } | ||||
|                     ]) [ "vms" "ctrs" "oci" ])); | ||||
|                   } | ||||
|                 ]; | ||||
|  | ||||
| @@ -326,7 +329,7 @@ in | ||||
|                   { | ||||
|                     matchConfig.Name = "as211024"; | ||||
|                     networkConfig.IPv6AcceptRA = mkForce false; | ||||
|                     routes = map (r: { routeConfig = r; }) [ | ||||
|                     routes = [ | ||||
|                       { | ||||
|                         Destination = lib.my.c.home.prefixes.all.v4; | ||||
|                         Gateway = lib.my.c.home.vips.as211024.v4; | ||||
| @@ -338,10 +341,8 @@ in | ||||
|                   matchConfig.Name = "kelder"; | ||||
|                   routes = [ | ||||
|                     { | ||||
|                       routeConfig = { | ||||
|                         Destination = allAssignments.kelder.estuary.ipv4.address; | ||||
|                         Scope = "link"; | ||||
|                       }; | ||||
|                       Destination = allAssignments.kelder.estuary.ipv4.address; | ||||
|                       Scope = "link"; | ||||
|                     } | ||||
|                   ]; | ||||
|                 }; | ||||
| @@ -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 | ||||
| @@ -403,6 +407,7 @@ in | ||||
|                       ip6 daddr ${aa.valheim-oci.internal.ipv6.address} udp dport { 2456-2457 } accept | ||||
|                       ip6 daddr ${aa.waffletail.internal.ipv6.address} udp dport 41641 accept | ||||
|                       ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} udp dport 25565 accept | ||||
|                       ip6 daddr ${aa.enshrouded-oci.internal.ipv6.address} udp dport { 15636-15637 } accept | ||||
|                       return | ||||
|                     } | ||||
|                     chain filter-routing { | ||||
|   | ||||
| @@ -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 | ||||
| @@ -153,6 +153,7 @@ in | ||||
|             simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address} | ||||
|             simpcraft-staging IN A ${assignments.internal.ipv4.address} | ||||
|             simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address} | ||||
|             enshrouded IN A ${assignments.internal.ipv4.address} | ||||
|  | ||||
|             mail-vm IN A ${net.cidr.host 0 prefixes.mail.v4} | ||||
|             mail-vm IN AAAA ${net.cidr.host 1 prefixes.mail.v6} | ||||
| @@ -162,6 +163,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@@ | ||||
|  | ||||
|   | ||||
| @@ -35,6 +35,11 @@ in | ||||
|           ]; | ||||
|           url = "https://git.${pubDomain}"; | ||||
|           tokenFile = config.age.secrets."gitea/actions-runner.env".path; | ||||
|           settings = { | ||||
|             runner = { | ||||
|               timeout = "8h"; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   | ||||
							
								
								
									
										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 = [ | ||||
|           { | ||||
|             Prefix = prefixes.jam.v6; | ||||
|           } | ||||
|         ]; | ||||
|         routes = [ | ||||
|           { | ||||
|             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,9 +45,22 @@ in | ||||
|                   owner = "matrix-synapse"; | ||||
|                   group = "matrix-synapse"; | ||||
|                 }; | ||||
|                 "chatterbox/syncv3.env" = { | ||||
|                   owner = "matrix-syncv3"; | ||||
|                   group = "matrix-syncv3"; | ||||
|                 "chatterbox/doublepuppet.yaml" = { | ||||
|                   owner = "matrix-synapse"; | ||||
|                   group = "matrix-synapse"; | ||||
|                 }; | ||||
|  | ||||
|                 "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,29 +72,24 @@ in | ||||
|  | ||||
|           users = with lib.my.c.ids; { | ||||
|             users = { | ||||
|               matrix-syncv3 = { | ||||
|                 isSystemUser = true; | ||||
|                 uid = uids.matrix-syncv3; | ||||
|                 group = "matrix-syncv3"; | ||||
|               }; | ||||
|             }; | ||||
|             groups = { | ||||
|               matrix-syncv3.gid = gids.matrix-syncv3; | ||||
|               matrix-synapse.extraGroups = [ | ||||
|                 "mautrix-whatsapp" | ||||
|               ]; | ||||
|             }; | ||||
|             groups = { }; | ||||
|           }; | ||||
|  | ||||
|           systemd = { | ||||
|             network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal; | ||||
|             services = { | ||||
|               matrix-sliding-sync.serviceConfig = { | ||||
|                 # Needs to be able to read its secrets | ||||
|                 DynamicUser = mkForce false; | ||||
|                 User = "matrix-syncv3"; | ||||
|                 Group = "matrix-syncv3"; | ||||
|               }; | ||||
|             }; | ||||
|             services = { } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: { | ||||
|               # ffmpeg needed to convert GIFs to video | ||||
|               path = with pkgs; [ ffmpeg ]; | ||||
|             })); | ||||
|           }; | ||||
|  | ||||
|           # TODO/FIXME: https://github.com/NixOS/nixpkgs/issues/336052 | ||||
|           nixpkgs.config.permittedInsecurePackages = [ "olm-3.2.16" ]; | ||||
|  | ||||
|           services = { | ||||
|             netdata.enable = true; | ||||
|             matrix-synapse = { | ||||
| @@ -168,19 +176,11 @@ in | ||||
|  | ||||
|                 app_service_config_files = [ | ||||
|                   "/var/lib/heisenbridge/registration.yml" | ||||
|                   config.age.secrets."chatterbox/doublepuppet.yaml".path | ||||
|                 ]; | ||||
|               }; | ||||
|  | ||||
|             }; | ||||
|             matrix-sliding-sync = { | ||||
|               enable = true; | ||||
|               createDatabase = false; | ||||
|               environmentFile = config.age.secrets."chatterbox/syncv3.env".path; | ||||
|               settings = { | ||||
|                 SYNCV3_BINDADDR = "[::]:8009"; | ||||
|                 SYNCV3_SERVER = "http://localhost:8008"; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             heisenbridge = { | ||||
|               enable = true; | ||||
| @@ -195,6 +195,144 @@ 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"; | ||||
|                     }; | ||||
|                   }; | ||||
|                   network = { | ||||
|                     mode = "messenger"; | ||||
|                     displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FBM)''; | ||||
|                   }; | ||||
|                   bridge = { | ||||
|                     username_template = "fbm2_{{.}}"; | ||||
|                     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"; | ||||
|                     }; | ||||
|                   }; | ||||
|                   network = { | ||||
|                     mode = "instagram"; | ||||
|                     displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (IG)''; | ||||
|                   }; | ||||
|                   bridge = { | ||||
|                     username_template = "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 { | ||||
|   | ||||
| @@ -8,5 +8,6 @@ | ||||
|     ./object.nix | ||||
|     ./toot.nix | ||||
|     ./waffletail.nix | ||||
|     ./qclk | ||||
|   ]; | ||||
| } | ||||
|   | ||||
| @@ -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,9 +87,21 @@ in | ||||
|               RootDirectoryStartOnly = lib.mkForce false; | ||||
|               RootDirectory = lib.mkForce ""; | ||||
|             }; | ||||
|             photoprism.serviceConfig = { | ||||
|               # Needs to be able to access its data | ||||
|               DynamicUser = mkForce false; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         nixpkgs.config.permittedInsecurePackages = [ | ||||
|           # FIXME: This is needed for Sonarr | ||||
|           "aspnetcore-runtime-wrapped-6.0.36" | ||||
|           "aspnetcore-runtime-6.0.36" | ||||
|           "dotnet-sdk-wrapped-6.0.428" | ||||
|           "dotnet-sdk-6.0.428" | ||||
|         ]; | ||||
|  | ||||
|         services = { | ||||
|           netdata.enable = true; | ||||
|  | ||||
| @@ -117,6 +140,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 { | ||||
| @@ -71,14 +71,12 @@ in | ||||
|               RouteTable = routeTable; | ||||
|             }; | ||||
|             wireguardPeers = [ | ||||
|               # AirVPN NL | ||||
|               { | ||||
|                 # AirVPN NL | ||||
|                 wireguardPeerConfig = { | ||||
|                   Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637"; | ||||
|                   PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; | ||||
|                   PresharedKeyFile = config.age.secrets."${pskFile}".path; | ||||
|                   AllowedIPs = [ "0.0.0.0/0" "::/0" ]; | ||||
|                 }; | ||||
|                 Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637"; | ||||
|                 PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; | ||||
|                 PresharedKeyFile = config.age.secrets."${pskFile}".path; | ||||
|                 AllowedIPs = [ "0.0.0.0/0" "::/0" ]; | ||||
|               } | ||||
|             ]; | ||||
|           }; | ||||
| @@ -94,7 +92,7 @@ in | ||||
|               matchConfig.Name = "vpn"; | ||||
|               address = [ "10.182.97.37/32" "fd7d:76ee:e68f:a993:735d:ef5e:6907:b122/128" ]; | ||||
|               dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ]; | ||||
|               routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ | ||||
|               routingPolicyRules = [ | ||||
|                 { | ||||
|                   Family = "both"; | ||||
|                   SuppressPrefixLength = 0; | ||||
|   | ||||
| @@ -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 = { | ||||
|   | ||||
| @@ -2,7 +2,7 @@ | ||||
| let | ||||
|   inherit (builtins) mapAttrs toJSON; | ||||
|   inherit (lib) mkMerge mkDefault genAttrs flatten concatStringsSep; | ||||
|   inherit (lib.my.c) pubDomain; | ||||
|   inherit (lib.my.c) pubDomain home; | ||||
|   inherit (lib.my.c.nginx) proxyHeaders; | ||||
|   inherit (config.networking) domain; | ||||
|  | ||||
| @@ -35,7 +35,6 @@ let | ||||
|       # For clients | ||||
|       (mkWellKnown "matrix/client" (toJSON { | ||||
|         "m.homeserver".base_url = "https://matrix.nul.ie"; | ||||
|         "org.matrix.msc3575.proxy".url = "https://matrix-syncv3.nul.ie"; | ||||
|       })) | ||||
|     ]; | ||||
|   }; | ||||
| @@ -145,7 +144,7 @@ in | ||||
|  | ||||
|       "pass.${pubDomain}" = | ||||
|       let | ||||
|         upstream = "http://vaultwarden-ctr.${domain}"; | ||||
|         upstream = "http://vaultwarden-ctr.${domain}:8080"; | ||||
|       in | ||||
|       { | ||||
|         locations = { | ||||
| @@ -182,10 +181,6 @@ in | ||||
|         ]; | ||||
|         useACMEHost = pubDomain; | ||||
|       }; | ||||
|       "matrix-syncv3.${pubDomain}" = { | ||||
|         locations."/".proxyPass = "http://chatterbox-ctr.${domain}:8009"; | ||||
|         useACMEHost = pubDomain; | ||||
|       }; | ||||
|  | ||||
|       "element.${pubDomain}" = | ||||
|       let | ||||
| @@ -206,7 +201,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 +210,8 @@ in | ||||
|                 server_name = "nul.ie"; | ||||
|               }; | ||||
|             }; | ||||
|             roomDirectory.servers = [ | ||||
|             room_directory.servers = [ | ||||
|               "nul.ie" | ||||
|               "netsoc.ie" | ||||
|               "matrix.org" | ||||
|             ]; | ||||
|           }; | ||||
| @@ -388,6 +383,36 @@ in | ||||
|         locations."/".proxyPass = "http://object-ctr.${domain}:8088"; | ||||
|         useACMEHost = pubDomain; | ||||
|       }; | ||||
|       "photos.${pubDomain}" = { | ||||
|         locations."/" = { | ||||
|           proxyPass = "http://jackflix-ctr.${domain}:2342"; | ||||
|           proxyWebsockets = true; | ||||
|           extraConfig = proxyHeaders; | ||||
|         }; | ||||
|         useACMEHost = pubDomain; | ||||
|       }; | ||||
|  | ||||
|       "pront.${pubDomain}" = mkMerge [ | ||||
|         { | ||||
|           locations."/" = mkMerge [ | ||||
|             { | ||||
|               proxyPass = "http://stream-hi.${home.domain}:5000"; | ||||
|               proxyWebsockets = true; | ||||
|               extraConfig = proxyHeaders; | ||||
|             } | ||||
|             (ssoLoc "generic") | ||||
|           ]; | ||||
|           locations."~* ^/webcam/(.*)" = mkMerge [ | ||||
|             { | ||||
|               proxyPass = "http://stream-hi.${home.domain}:5050/$1$is_args$args"; | ||||
|               extraConfig = proxyHeaders; | ||||
|             } | ||||
|             (ssoLoc "generic") | ||||
|           ]; | ||||
|           useACMEHost = pubDomain; | ||||
|         } | ||||
|         (ssoServer "generic") | ||||
|       ]; | ||||
|     }; | ||||
|  | ||||
|     minio = | ||||
| @@ -399,10 +424,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 | ||||
|     { | ||||
| @@ -444,9 +472,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,6 +55,7 @@ in | ||||
|                   group = config.my.user.config.group; | ||||
|                 }; | ||||
|                 "object/atticd.env" = {}; | ||||
|                 "nix-cache.key" = {}; | ||||
|                 "object/hedgedoc.env" = {}; | ||||
|                 "object/wastebin.env" = {}; | ||||
|               }; | ||||
| @@ -58,6 +66,7 @@ in | ||||
|                 9000 9001 | ||||
|                 config.services.sharry.config.bind.port | ||||
|                 8069 | ||||
|                 5000 | ||||
|                 config.services.hedgedoc.settings.port | ||||
|                 8088 | ||||
|               ]; | ||||
| @@ -68,14 +77,26 @@ in | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           users = with lib.my.c.ids; let inherit (config.services.atticd) user group; in { | ||||
|             users."${user}" = { | ||||
|               isSystemUser = true; | ||||
|               uid = uids.atticd; | ||||
|               group = group; | ||||
|             }; | ||||
|             groups."${user}".gid = gids.atticd; | ||||
|           }; | ||||
|           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; | ||||
| @@ -93,7 +114,9 @@ in | ||||
|                   MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie"; | ||||
|                 }; | ||||
|               }; | ||||
|  | ||||
|               sharry = awaitPostgres; | ||||
|  | ||||
|               atticd = mkMerge [ | ||||
|                 awaitPostgres | ||||
|                 { | ||||
| @@ -104,6 +127,15 @@ in | ||||
|                   }; | ||||
|                 } | ||||
|               ]; | ||||
|               harmonia = { | ||||
|                 environment.NIX_REMOTE = "/var/lib/harmonia"; | ||||
|                 preStart = '' | ||||
|                   ${config.nix.package}/bin/nix store ping | ||||
|                 ''; | ||||
|                 serviceConfig = { | ||||
|                   StateDirectory = "harmonia"; | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
| @@ -183,8 +215,8 @@ in | ||||
|             }; | ||||
|  | ||||
|             atticd = { | ||||
|               enable = true; | ||||
|               credentialsFile = config.age.secrets."object/atticd.env".path; | ||||
|               enable = false; | ||||
|               environmentFile = config.age.secrets."object/atticd.env".path; | ||||
|               settings = { | ||||
|                 listen = "[::]:8069"; | ||||
|                 allowed-hosts = [ "nix-cache.${pubDomain}" ]; | ||||
| @@ -203,6 +235,14 @@ in | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             harmonia = { | ||||
|               enable = true; | ||||
|               signKeyPaths = [ config.age.secrets."nix-cache.key".path ]; | ||||
|               settings = { | ||||
|                 priority = 30; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             hedgedoc = { | ||||
|               enable = true; | ||||
|               environmentFile = config.age.secrets."object/hedgedoc.env".path; | ||||
| @@ -226,10 +266,10 @@ in | ||||
|             wastebin = { | ||||
|               enable = true; | ||||
|               settings = { | ||||
|                 WASTEBIN_MAX_BODY_SIZE = "67108864"; # 16 MiB | ||||
|                 WASTEBIN_MAX_BODY_SIZE = 67108864; # 16 MiB | ||||
|                 WASTEBIN_PASSWORD_SALT = "TeGhaemeer0Siez3"; | ||||
|               }; | ||||
|               extraSettingsFile = config.age.secrets."object/wastebin.env".path; | ||||
|               secretFile = config.age.secrets."object/wastebin.env".path; | ||||
|             }; | ||||
|           }; | ||||
|         } | ||||
|   | ||||
							
								
								
									
										115
									
								
								nixos/boxes/colony/vms/shill/containers/qclk/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								nixos/boxes/colony/vms/shill/containers/qclk/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| { lib, ... }: | ||||
| let | ||||
|   inherit (lib.my) net; | ||||
|   inherit (lib.my.c.colony) domain prefixes qclk; | ||||
| in | ||||
| { | ||||
|   nixos.systems.qclk = { config, ... }: { | ||||
|     system = "x86_64-linux"; | ||||
|     nixpkgs = "mine"; | ||||
|     rendered = config.configuration.config.my.asContainer; | ||||
|  | ||||
|     assignments = { | ||||
|       internal = { | ||||
|         name = "qclk-ctr"; | ||||
|         inherit domain; | ||||
|         ipv4.address = net.cidr.host 10 prefixes.ctrs.v4; | ||||
|         ipv6 = { | ||||
|           iid = "::a"; | ||||
|           address = net.cidr.host 10 prefixes.ctrs.v6; | ||||
|         }; | ||||
|       }; | ||||
|       qclk = { | ||||
|         ipv4 = { | ||||
|           address = net.cidr.host 1 prefixes.qclk.v4; | ||||
|           gateway = null; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     configuration = { lib, pkgs, config, assignments, ... }: | ||||
|     let | ||||
|       inherit (lib) concatStringsSep mkMerge mkIf mkForce; | ||||
|       inherit (lib.my) networkdAssignment; | ||||
|  | ||||
|       apiPort = 8080; | ||||
|  | ||||
|       instances = [ | ||||
|         { | ||||
|           host = 2; | ||||
|           wgKey = "D7z1FhcdxpnrGCE0wBW5PZb5BKuhCu6tcZ/5ZaYxdwQ="; | ||||
|         } | ||||
|       ]; | ||||
|       ipFor = i: net.cidr.host i.host prefixes.qclk.v4; | ||||
|     in | ||||
|     { | ||||
|       config = { | ||||
|         environment = { | ||||
|           systemPackages = with pkgs; [ | ||||
|             wireguard-tools | ||||
|           ]; | ||||
|         }; | ||||
|  | ||||
|         my = { | ||||
|           deploy.enable = false; | ||||
|           server.enable = true; | ||||
|  | ||||
|           secrets = { | ||||
|             key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC1kcfvahYmSk8IJKaUIcGkhxf/8Yse2XnU7Qqgcglyq"; | ||||
|             files = { | ||||
|               "qclk/wg.key" = { | ||||
|                 group = "systemd-network"; | ||||
|                 mode = "440"; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
|  | ||||
|           firewall = { | ||||
|             udp.allowed = [ qclk.wgPort ]; | ||||
|             extraRules = '' | ||||
|               table inet filter { | ||||
|                 chain input { | ||||
|                   iifname management tcp dport ${toString apiPort} accept | ||||
|                 } | ||||
|                 chain forward { | ||||
|                   iifname host0 oifname management ip saddr { ${concatStringsSep ", " lib.my.c.as211024.trusted.v4} } accept | ||||
|                 } | ||||
|               } | ||||
|               table inet nat { | ||||
|                 chain postrouting { | ||||
|                   iifname host0 oifname management snat ip to ${assignments.qclk.ipv4.address} | ||||
|                 } | ||||
|               } | ||||
|             ''; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         systemd = { | ||||
|           network = { | ||||
|             netdevs."30-management" = { | ||||
|               netdevConfig = { | ||||
|                 Name = "management"; | ||||
|                 Kind = "wireguard"; | ||||
|               }; | ||||
|               wireguardConfig = { | ||||
|                 PrivateKeyFile = config.age.secrets."qclk/wg.key".path; | ||||
|                 ListenPort = qclk.wgPort; | ||||
|               }; | ||||
|               wireguardPeers = map (i: { | ||||
|                 PublicKey = i.wgKey; | ||||
|                 AllowedIPs = [ (ipFor i) ]; | ||||
|               }) instances; | ||||
|             }; | ||||
|             networks = { | ||||
|               "30-container-host0" = networkdAssignment "host0" assignments.internal; | ||||
|  | ||||
|               "30-management" = networkdAssignment "management" assignments.qclk; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         services = { }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| @@ -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"; | ||||
| @@ -99,6 +99,8 @@ in | ||||
|             }; | ||||
|  | ||||
|             borgbackup.jobs.vaultwarden = { | ||||
|               readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ]; | ||||
|  | ||||
|               paths = [ vwData ]; | ||||
|               repo = "zh2855@zh2855.rsync.net:borg/vaultwarden2"; | ||||
|               doInit = true; | ||||
|   | ||||
| @@ -86,7 +86,7 @@ in | ||||
|             interfaceName = "tailscale0"; | ||||
|             extraUpFlags = [ | ||||
|               "--operator=${config.my.user.config.name}" | ||||
|               "--login-server=https://ts.nul.ie" | ||||
|               "--login-server=https://hs.nul.ie" | ||||
|               "--netfilter-mode=off" | ||||
|               "--advertise-exit-node" | ||||
|               "--advertise-routes=${advRoutes}" | ||||
|   | ||||
| @@ -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"; | ||||
|               }; | ||||
|             }; | ||||
| @@ -136,10 +140,10 @@ in | ||||
|                     }; | ||||
|                     ipv6Prefixes = [ | ||||
|                       { | ||||
|                         ipv6PrefixConfig.Prefix = prefixes.ctrs.v6; | ||||
|                         Prefix = prefixes.ctrs.v6; | ||||
|                       } | ||||
|                     ]; | ||||
|                     routes = map (r: { routeConfig = r; }) [ | ||||
|                     routes = [ | ||||
|                       { | ||||
|                         Destination = lib.my.c.tailscale.prefix.v4; | ||||
|                         Gateway = allAssignments.waffletail.internal.ipv4.address; | ||||
| @@ -148,6 +152,11 @@ in | ||||
|                         Destination = lib.my.c.tailscale.prefix.v6; | ||||
|                         Gateway = allAssignments.waffletail.internal.ipv6.address; | ||||
|                       } | ||||
|  | ||||
|                       { | ||||
|                         Destination = prefixes.qclk.v4; | ||||
|                         Gateway = allAssignments.qclk.internal.ipv4.address; | ||||
|                       } | ||||
|                     ]; | ||||
|                   } | ||||
|                 ]; | ||||
| @@ -202,11 +211,12 @@ in | ||||
|                   object = { | ||||
|                     bindMounts = { | ||||
|                       "/mnt/minio".readOnly = false; | ||||
|                       "/mnt/atticd".readOnly = false; | ||||
|                       "/mnt/nix-cache".readOnly = false; | ||||
|                     }; | ||||
|                   }; | ||||
|                   toot = {}; | ||||
|                   waffletail = {}; | ||||
|                   qclk = {}; | ||||
|                 }; | ||||
|               in | ||||
|               mkMerge [ | ||||
|   | ||||
| @@ -52,6 +52,7 @@ in | ||||
|       valheim-oci = 2; | ||||
|       simpcraft-oci = 3; | ||||
|       simpcraft-staging-oci = 4; | ||||
|       enshrouded-oci = 5; | ||||
|     }; | ||||
|  | ||||
|     configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }: | ||||
| @@ -66,6 +67,7 @@ in | ||||
|  | ||||
|           ./valheim.nix | ||||
|           ./minecraft | ||||
|           # ./enshrouded.nix | ||||
|         ]; | ||||
|  | ||||
|         config = mkMerge [ | ||||
| @@ -108,45 +110,30 @@ in | ||||
|               oci-containers = { | ||||
|                 backend = "podman"; | ||||
|               }; | ||||
|               # NixOS has switched to using netavark, which is native to podman. It's currently missing an option to | ||||
|               # disable iptables rules generation, which is very annoying. | ||||
|               containers.containersConf.settings.network.network_backend = mkForce "cni"; | ||||
|               containers.containersConf.settings.network = { | ||||
|                 network_backend = "netavark"; | ||||
|                 firewall_driver = "none"; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             environment = { | ||||
|               etc = { | ||||
|                 "cni/net.d/90-colony.conflist".text = toJSON { | ||||
|                   cniVersion = "0.4.0"; | ||||
|                 "containers/networks/colony.json".text = toJSON { | ||||
|                   name = "colony"; | ||||
|                   plugins = [ | ||||
|                   id = "0000000000000000000000000000000000000000000000000000000000000001"; | ||||
|                   driver = "bridge"; | ||||
|                   network_interface = "oci"; | ||||
|                   ipv6_enabled = true; | ||||
|                   internal = false; | ||||
|                   dns_enabled = false; | ||||
|                   subnets = [ | ||||
|                     { | ||||
|                       type = "bridge"; | ||||
|                       bridge = "oci"; | ||||
|                       isGateway = true; | ||||
|                       ipMasq = false; | ||||
|                       hairpinMode = true; | ||||
|                       ipam = { | ||||
|                         type = "host-local"; | ||||
|                         routes = [ | ||||
|                           { dst = "0.0.0.0/0"; } | ||||
|                           { dst = "::/0"; } | ||||
|                         ]; | ||||
|                         ranges = [ | ||||
|                           [ | ||||
|                             { | ||||
|                               subnet = prefixes.oci.v4; | ||||
|                               gateway = net.cidr.host 1 prefixes.oci.v4; | ||||
|                             } | ||||
|                           ] | ||||
|                           [ | ||||
|                             { | ||||
|                               subnet = prefixes.oci.v6; | ||||
|                               gateway = net.cidr.host 1 prefixes.oci.v6; | ||||
|                             } | ||||
|                           ] | ||||
|                         ]; | ||||
|                       }; | ||||
|                       capabilities.ips = true; | ||||
|                       subnet = prefixes.oci.v4; | ||||
|                       gateway = net.cidr.host 1 prefixes.oci.v4; | ||||
|                     } | ||||
|                     { | ||||
|                       subnet = prefixes.oci.v6; | ||||
|                       gateway = net.cidr.host 1 prefixes.oci.v6; | ||||
|                     } | ||||
|                   ]; | ||||
|                 }; | ||||
|   | ||||
							
								
								
									
										35
									
								
								nixos/boxes/colony/vms/whale2/enshrouded.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								nixos/boxes/colony/vms/whale2/enshrouded.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| { lib, config, allAssignments, ... }: | ||||
| let | ||||
|   inherit (lib) concatStringsSep; | ||||
|   inherit (lib.my) dockerNetAssignment; | ||||
| in | ||||
| { | ||||
|   config = { | ||||
|     virtualisation.oci-containers.containers = { | ||||
|       enshrouded = { | ||||
|         image = "sknnr/enshrouded-dedicated-server@sha256:f163e8ba9caa2115d8a0a7b16c3696968242fb6fba82706d9a77a882df083497"; | ||||
|  | ||||
|         environment = { | ||||
|           SERVER_NAME = "UWUshrouded"; | ||||
|           # SERVER_IP = "::"; # no IPv6?? :( | ||||
|           TZ = "Europe/Dublin"; | ||||
|         }; | ||||
|         environmentFiles = [ config.age.secrets."whale2/enshrouded.env".path ]; | ||||
|  | ||||
|         volumes = [ | ||||
|           "enshrouded:/home/steam/enshrouded/savegame" | ||||
|         ]; | ||||
|  | ||||
|         extraOptions = [ | ||||
|           ''--network=colony:${dockerNetAssignment allAssignments "enshrouded-oci"}'' | ||||
|         ]; | ||||
|       }; | ||||
|     }; | ||||
|  | ||||
|     my = { | ||||
|       secrets.files = { | ||||
|         "whale2/enshrouded.env" = {}; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
| @@ -123,6 +123,7 @@ in | ||||
|           within = "12H"; | ||||
|           hourly = 48; | ||||
|         }; | ||||
|         readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ]; | ||||
|  | ||||
|         # Avoid Minecraft poking the files while we back up | ||||
|         preHook = rconCommand "save-off"; | ||||
|   | ||||
| @@ -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"; | ||||
| @@ -35,7 +36,7 @@ in | ||||
|           cpu = { | ||||
|             amd.updateMicrocode = true; | ||||
|           }; | ||||
|           opengl.extraPackages = with pkgs; [ | ||||
|           graphics.extraPackages = with pkgs; [ | ||||
|             intel-media-driver | ||||
|           ]; | ||||
|           bluetooth.enable = true; | ||||
| @@ -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,40 @@ 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; | ||||
|               }; | ||||
|             }; | ||||
|           }; | ||||
| 
 | ||||
|           binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ]; | ||||
|         }; | ||||
| 
 | ||||
|         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"; | ||||
|           }; | ||||
|         }; | ||||
| @@ -102,7 +116,7 @@ in | ||||
|           }; | ||||
| 
 | ||||
|           pipewire.extraConfig.pipewire = { | ||||
|             "context.properties" = { | ||||
|             "10-buffer"."context.properties" = { | ||||
|               "default.clock.quantum" = 128; | ||||
|               "default.clock.max-quantum" = 128; | ||||
|             }; | ||||
| @@ -120,7 +134,7 @@ in | ||||
|         virtualisation.libvirtd.enable = true; | ||||
| 
 | ||||
|         networking = { | ||||
|           domain = "h.${lib.my.c.pubDomain}"; | ||||
|           inherit domain; | ||||
|           firewall.enable = false; | ||||
|         }; | ||||
| 
 | ||||
| @@ -140,11 +154,14 @@ in | ||||
| 
 | ||||
|         nix = { | ||||
|           gc.automatic = false; | ||||
|           settings = { | ||||
|             experimental-features = [ "recursive-nix" ]; | ||||
|             system-features = [ "nixos-test" "benchmark" "big-parallel" "kvm" "recursive-nix" ]; | ||||
|           }; | ||||
|         }; | ||||
| 
 | ||||
|         systemd = { | ||||
|           network = { | ||||
|             wait-online.enable = false; | ||||
|             netdevs = mkMerge [ | ||||
|               (mkVLAN "lan-hi" vlans.hi) | ||||
|             ]; | ||||
| @@ -161,29 +178,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"; } | ||||
|               ]; | ||||
|             }; | ||||
|           }; | ||||
| @@ -203,10 +211,7 @@ in | ||||
|                 packages = with pkgs; [ | ||||
|                   jacktrip | ||||
|                   qpwgraph | ||||
|                   # TODO: seems to be borked (infinite recursion???) | ||||
|                   # (writeShellScriptBin "boardie" '' | ||||
|                   #   exec pw-jack ${boardie}/bin/boardie "$@" | ||||
|                   # '') | ||||
|                   boardie | ||||
|                 ]; | ||||
|               }; | ||||
| 
 | ||||
| @@ -220,6 +225,7 @@ in | ||||
|                     HDMI-A-1 = { | ||||
|                       transform = "270"; | ||||
|                       position = "0 0"; | ||||
|                       bg = "${./his-team-player.jpg} fill"; | ||||
|                     }; | ||||
|                     DP-1 = { | ||||
|                       mode = "2560x1440@170Hz"; | ||||
| @@ -241,11 +247,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 | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										65
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										65
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,65 @@ | ||||
| { 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; | ||||
|             mongodbPackage = pkgs.mongodb-6_0; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										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,9 +148,11 @@ in | ||||
|                 }; | ||||
|               }; | ||||
|             }; | ||||
|  | ||||
|             nginx.enable = true; | ||||
|           }; | ||||
|  | ||||
|           networking.domain = "h.${pubDomain}"; | ||||
|           networking = { inherit domain; }; | ||||
|  | ||||
|           systemd.services = | ||||
|           let | ||||
| @@ -225,7 +227,7 @@ in | ||||
|                   networkConfig = networkd.noL3; | ||||
|                   extraConfig = '' | ||||
|                     [CAKE] | ||||
|                     Bandwidth=235M | ||||
|                     Bandwidth=490M | ||||
|                     RTTSec=50ms | ||||
|                     PriorityQueueingPreset=besteffort | ||||
|                     # DOCSIS preset | ||||
| @@ -249,7 +251,7 @@ in | ||||
|                     extraConfig = '' | ||||
|                       [CAKE] | ||||
|                       Parent=root | ||||
|                       Bandwidth=24M | ||||
|                       Bandwidth=48M | ||||
|                       RTTSec=50ms | ||||
|                     ''; | ||||
|                   } | ||||
| @@ -274,7 +276,7 @@ in | ||||
|                   { | ||||
|                     matchConfig.Name = "as211024"; | ||||
|                     networkConfig.IPv6AcceptRA = mkForce false; | ||||
|                     routes = map (r: { routeConfig = r; }) [ | ||||
|                     routes = [ | ||||
|                       { | ||||
|                         Destination = lib.my.c.colony.prefixes.all.v4; | ||||
|                         Gateway = allAssignments.estuary.as211024.ipv4.address; | ||||
| @@ -299,7 +301,7 @@ in | ||||
|  | ||||
|               { | ||||
|                 "60-lan-hi" = { | ||||
|                   routes = map (r: { routeConfig = r; }) [ | ||||
|                   routes = [ | ||||
|                     { | ||||
|                       Destination = elemAt routersPubV4 otherIndex; | ||||
|                       Gateway = net.cidr.host (otherIndex + 1) prefixes.hi.v4; | ||||
| @@ -375,6 +377,10 @@ in | ||||
|  | ||||
|                     # 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} | ||||
|   | ||||
| @@ -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 | ||||
|           ''; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
| @@ -157,8 +170,9 @@ in | ||||
|               hostname = "${otherName}.${config.networking.domain}"; | ||||
|               server = net.cidr.host (otherIndex + 1) prefixes.hi.v4; | ||||
|             }} | ||||
|             ${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6} | ||||
|             ${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6} | ||||
|             ${elemAt routers 0} IN AAAA ${allAssignments."${elemAt routers 0}".as211024.ipv6.address} | ||||
|             ${elemAt routers 1} IN AAAA ${allAssignments."${elemAt routers 1}".as211024.ipv6.address} | ||||
|             boot IN CNAME river-hi.${config.networking.domain}. | ||||
|  | ||||
|             @ IN NS ns1 | ||||
|             @ IN NS ns2 | ||||
| @@ -185,7 +199,7 @@ in | ||||
|             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} | ||||
|             ; 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 = [ | ||||
| @@ -63,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 = '' | ||||
|             notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root | ||||
|             notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root | ||||
|           ''; | ||||
|         }; | ||||
|       }; | ||||
|       extraConfig = '' | ||||
|         vrrp_sync_group main { | ||||
|           group { | ||||
|             v4 | ||||
|             v6 | ||||
|           } | ||||
|         } | ||||
|       ''; | ||||
|       # Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken... | ||||
|       # extraConfig = '' | ||||
|       #   vrrp_sync_group main { | ||||
|       #     group { | ||||
|       #       v4 | ||||
|       #       v6 | ||||
|       #     } | ||||
|       #   } | ||||
|       # ''; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
|   | ||||
| @@ -43,6 +43,38 @@ | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         services = { | ||||
|           mjpg-streamer = { | ||||
|             enable = true; | ||||
|             inputPlugin = "input_uvc.so"; | ||||
|             outputPlugin = "output_http.so -w @www@ -n -p 5050"; | ||||
|           }; | ||||
|           octoprint = { | ||||
|             enable = true; | ||||
|             host = "::"; | ||||
|             extraConfig = { | ||||
|               plugins = { | ||||
|                 classicwebcam = { | ||||
|                   snapshot = "/webcam/?action=snapshot"; | ||||
|                   stream = "/webcam/?action=stream"; | ||||
|                   streamRatio = "4:3"; | ||||
|                 }; | ||||
|               }; | ||||
|               serial = { | ||||
|                 port = "/dev/ttyACM0"; | ||||
|                 baudrate = 115200; | ||||
|               }; | ||||
|               temperature.profiles = [ | ||||
|                 { | ||||
|                   bed = 60; | ||||
|                   extruder = 215; | ||||
|                   name = "PLA"; | ||||
|                 } | ||||
|               ]; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         systemd.network = { | ||||
|           netdevs = { | ||||
|             "25-lan" = { | ||||
| @@ -123,7 +155,7 @@ | ||||
|             key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb"; | ||||
|           }; | ||||
|           server.enable = true; | ||||
|           deploy.node.hostname = "192.168.68.2"; | ||||
|           # deploy.node.hostname = "192.168.68.2"; | ||||
|         }; | ||||
|       }; | ||||
|     }; | ||||
|   | ||||
| @@ -26,7 +26,7 @@ in | ||||
|  | ||||
|       config = { | ||||
|         # Hardware acceleration for Jellyfin | ||||
|         hardware.opengl = { | ||||
|         hardware.graphics = { | ||||
|           enable = true; | ||||
|           extraPackages = with pkgs; [ | ||||
|             vaapiIntel | ||||
| @@ -78,6 +78,14 @@ in | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         nixpkgs.config.permittedInsecurePackages = [ | ||||
|           # FIXME: This is needed for Sonarr | ||||
|           "aspnetcore-runtime-wrapped-6.0.36" | ||||
|           "aspnetcore-runtime-6.0.36" | ||||
|           "dotnet-sdk-wrapped-6.0.428" | ||||
|           "dotnet-sdk-6.0.428" | ||||
|         ]; | ||||
|  | ||||
|         services = { | ||||
|           transmission = { | ||||
|             enable = true; | ||||
|   | ||||
| @@ -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"; | ||||
| @@ -72,14 +73,12 @@ in | ||||
|               RouteTable = routeTable; | ||||
|             }; | ||||
|             wireguardPeers = [ | ||||
|               # AirVPN IE | ||||
|               { | ||||
|                 # AirVPN IE | ||||
|                 wireguardPeerConfig = { | ||||
|                   Endpoint = "146.70.94.2:1637"; | ||||
|                   PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; | ||||
|                   PresharedKeyFile = config.age.secrets."${pskFile}".path; | ||||
|                   AllowedIPs = [ "0.0.0.0/0" "::/0" ]; | ||||
|                 }; | ||||
|                 Endpoint = "146.70.94.2:1637"; | ||||
|                 PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; | ||||
|                 PresharedKeyFile = config.age.secrets."${pskFile}".path; | ||||
|                 AllowedIPs = [ "0.0.0.0/0" "::/0" ]; | ||||
|               } | ||||
|             ]; | ||||
|           }; | ||||
| @@ -89,13 +88,14 @@ in | ||||
|               (networkdAssignment "host0" assignments.internal) | ||||
|               { | ||||
|                 networkConfig.DNSDefaultRoute = false; | ||||
|                 linkConfig.MTUBytes = toString ipv4MTU; | ||||
|               } | ||||
|             ]; | ||||
|             "90-vpn" = with wg; { | ||||
|               matchConfig.Name = "vpn"; | ||||
|               address = [ "10.161.170.28/32" "fd7d:76ee:e68f:a993:b12d:6d15:c80a:9516/128" ]; | ||||
|               dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ]; | ||||
|               routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ | ||||
|               routingPolicyRules = [ | ||||
|                 { | ||||
|                   Family = "both"; | ||||
|                   SuppressPrefixLength = 0; | ||||
|   | ||||
| @@ -92,7 +92,7 @@ in | ||||
|  | ||||
|           nextcloud = { | ||||
|             enable = true; | ||||
|             package = pkgs.nextcloud28; | ||||
|             package = pkgs.nextcloud29; | ||||
|             datadir = "/mnt/storage/nextcloud"; | ||||
|             hostName = "cloud.${domain}"; | ||||
|             https = true; | ||||
|   | ||||
| @@ -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 ]; | ||||
| @@ -121,8 +121,7 @@ in | ||||
|  | ||||
|             samba = { | ||||
|               enable = true; | ||||
|               enableNmbd = true; | ||||
|               shares = { | ||||
|               settings = { | ||||
|                 storage = { | ||||
|                   path = "/mnt/storage"; | ||||
|                   browseable = "yes"; | ||||
| @@ -131,6 +130,8 @@ in | ||||
|                   "directory mask" = "0775"; | ||||
|                 }; | ||||
|               }; | ||||
|  | ||||
|               nmbd.enable = true; | ||||
|             }; | ||||
|             samba-wsdd.enable = true; | ||||
|  | ||||
| @@ -180,12 +181,10 @@ in | ||||
|                   }; | ||||
|                   wireguardPeers = [ | ||||
|                     { | ||||
|                       wireguardPeerConfig = { | ||||
|                         PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU="; | ||||
|                         Endpoint = "estuary-vm.${lib.my.c.colony.domain}:${toString lib.my.c.kelder.vpn.port}"; | ||||
|                         AllowedIPs = [ "0.0.0.0/0" ]; | ||||
|                         PersistentKeepalive = 25; | ||||
|                       }; | ||||
|                       PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU="; | ||||
|                       Endpoint = "${allAssignments.estuary.internal.ipv4.address}:${toString lib.my.c.kelder.vpn.port}"; | ||||
|                       AllowedIPs = [ "0.0.0.0/0" ]; | ||||
|                       PersistentKeepalive = 25; | ||||
|                     } | ||||
|                   ]; | ||||
|                 }; | ||||
| @@ -200,6 +199,7 @@ in | ||||
|                 "50-lan" = { | ||||
|                   matchConfig.Name = "et1g0"; | ||||
|                   DHCP = "yes"; | ||||
|                   linkConfig.MTUBytes = toString ipv4MTU; | ||||
|                 }; | ||||
|                 "80-ctrs" = mkMerge [ | ||||
|                   (networkdAssignment "ctrs" assignments.ctrs) | ||||
| @@ -212,7 +212,7 @@ in | ||||
|                   address = with assignments.estuary; [ | ||||
|                     (with ipv4; "${address}/${toString mask}") | ||||
|                   ]; | ||||
|                   routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ | ||||
|                   routingPolicyRules = [ | ||||
|                     { | ||||
|                       Family = "both"; | ||||
|                       SuppressPrefixLength = 0; | ||||
| @@ -272,7 +272,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 = { | ||||
|   | ||||
| @@ -14,7 +14,7 @@ | ||||
|           cpu = { | ||||
|             intel.updateMicrocode = true; | ||||
|           }; | ||||
|           opengl.extraPackages = with pkgs; [ | ||||
|           graphics.extraPackages = with pkgs; [ | ||||
|             intel-media-driver | ||||
|           ]; | ||||
|           bluetooth.enable = true; | ||||
| @@ -129,10 +129,9 @@ | ||||
|             wifi = { | ||||
|               backend = "wpa_supplicant"; | ||||
|             }; | ||||
|             extraConfig = '' | ||||
|               [main] | ||||
|               no-auto-default=* | ||||
|             ''; | ||||
|             settings = { | ||||
|               main.no-auto-default = "*"; | ||||
|             }; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
| @@ -178,7 +177,7 @@ | ||||
|               programs = { | ||||
|                 fish = { | ||||
|                   shellAbbrs = { | ||||
|                     tsup = "doas tailscale up --login-server=https://ts.nul.ie --accept-routes"; | ||||
|                     tsup = "doas tailscale up --login-server=https://hs.nul.ie --accept-routes"; | ||||
|                   }; | ||||
|                 }; | ||||
|               }; | ||||
|   | ||||
| @@ -35,7 +35,7 @@ let | ||||
|       system = null; | ||||
|  | ||||
|       # Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports | ||||
|       specialArgs = { inherit inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; }; | ||||
|       specialArgs = { inherit self inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; }; | ||||
|  | ||||
|       # `baseModules` informs the manual which modules to document | ||||
|       baseModules = | ||||
| @@ -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 = { | ||||
| @@ -59,8 +61,8 @@ | ||||
|           }; | ||||
|  | ||||
|           networking = { | ||||
|             # Will be set dynamically | ||||
|             hostName = ""; | ||||
|             # Will be set dynamically, but need something to satisfy `/etc/os-release` stuff | ||||
|             hostName = "installer"; | ||||
|             useNetworkd = false; | ||||
|           }; | ||||
|  | ||||
| @@ -80,6 +82,8 @@ | ||||
|                 ${pkgs.gawk}/bin/awk '{ print $1 }')" | ||||
|             ''; | ||||
|  | ||||
|           boot.supportedFilesystems.nfs = true; | ||||
|  | ||||
|           environment.systemPackages = with pkgs; [ | ||||
|             dhcpcd | ||||
|             lm_sensors | ||||
|   | ||||
| @@ -20,6 +20,6 @@ | ||||
|     nvme = ./nvme; | ||||
|     spdk = ./spdk.nix; | ||||
|     librespeed = ./librespeed; | ||||
|     wastebin = ./wastebin.nix; | ||||
|     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', self, inputs, config, ... }: | ||||
| let | ||||
|   inherit (lib) mkIf mkDefault mkMerge; | ||||
|   inherit (lib.my) mkDefault'; | ||||
| @@ -12,7 +12,6 @@ in | ||||
|     inputs.impermanence.nixosModule | ||||
|     inputs.ragenix.nixosModules.age | ||||
|     inputs.sharry.nixosModules.default | ||||
|     inputs.attic.nixosModules.atticd | ||||
|   ]; | ||||
|  | ||||
|   config = mkMerge [ | ||||
| @@ -41,6 +40,7 @@ in | ||||
|  | ||||
|       nix = { | ||||
|         package = pkgs'.mine.nix; | ||||
|         channel.enable = false; | ||||
|         settings = with lib.my.c.nix; { | ||||
|           trusted-users = [ "@wheel" ]; | ||||
|           experimental-features = [ "nix-command" "flakes" "ca-derivations" ]; | ||||
| @@ -53,7 +53,7 @@ in | ||||
|           pkgs = { | ||||
|             to = { | ||||
|               type = "path"; | ||||
|               path = "${pkgs.path}"; | ||||
|               path = "${pkgsFlake}"; | ||||
|             }; | ||||
|             exact = true; | ||||
|           }; | ||||
| @@ -127,6 +127,9 @@ in | ||||
|         }; | ||||
|       }; | ||||
|  | ||||
|       environment.etc = { | ||||
|         "nixos/flake.nix".source = "/run/nixfiles/flake.nix"; | ||||
|       }; | ||||
|       environment.systemPackages = with pkgs; mkMerge [ | ||||
|         [ | ||||
|           bash-completion | ||||
| @@ -142,7 +145,10 @@ in | ||||
|         fish.enable = mkDefault true; | ||||
|         # TODO: This is expecting to look up the channel for the database... | ||||
|         command-not-found.enable = mkDefault false; | ||||
|         vim.defaultEditor = true; | ||||
|         vim = { | ||||
|           enable = true; | ||||
|           defaultEditor = true; | ||||
|         }; | ||||
|       }; | ||||
|  | ||||
|       services = { | ||||
| @@ -209,14 +215,35 @@ in | ||||
|             # python.d plugin script does #!/usr/bin/env bash | ||||
|             path = with pkgs; [ bash ]; | ||||
|           }; | ||||
|  | ||||
|           nixfiles-mutable = { | ||||
|             description = "Mutable nixfiles"; | ||||
|             serviceConfig = { | ||||
|               Type = "oneshot"; | ||||
|               RemainAfterExit = true; | ||||
|             }; | ||||
|  | ||||
|             path = with pkgs; [ util-linux ]; | ||||
|             script = '' | ||||
|               nixfilesDir="${self}" | ||||
|  | ||||
|               mkdir -p /run/nixfiles{,/.rw,/.work} | ||||
|               mount -t overlay overlay -o lowerdir="$nixfilesDir",upperdir=/run/nixfiles/.rw,workdir=/run/nixfiles/.work /run/nixfiles | ||||
|               chmod -R u+w /run/nixfiles | ||||
|             ''; | ||||
|             preStop = '' | ||||
|               umount /run/nixfiles | ||||
|               rm -rf /run/nixfiles | ||||
|             ''; | ||||
|  | ||||
|             wantedBy = [ "multi-user.target" ]; | ||||
|           }; | ||||
|         }; | ||||
|       }; | ||||
|     } | ||||
|     (mkIf config.services.kmscon.enable { | ||||
|       fonts.fonts = with pkgs; [ | ||||
|         (nerdfonts.override { | ||||
|           fonts = [ "SourceCodePro" ]; | ||||
|         }) | ||||
|         nerd-fonts.sauce-code-pro | ||||
|       ]; | ||||
|     }) | ||||
|   ]; | ||||
|   | ||||
| @@ -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 | ||||
|   | ||||
| @@ -12,7 +12,7 @@ in | ||||
|  | ||||
|   config = mkIf cfg.enable { | ||||
|     hardware = { | ||||
|       opengl.enable = mkDefault true; | ||||
|       graphics.enable = mkDefault true; | ||||
|     }; | ||||
|  | ||||
|     systemd = { | ||||
| @@ -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,10 @@ 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" | ||||
|           # /dev/player0 | ||||
|           SUBSYSTEM=="usb", ATTR{idVendor}=="6969", MODE="0664", GROUP="wheel" | ||||
|         ''; | ||||
|       }; | ||||
|     }; | ||||
|   | ||||
| @@ -36,18 +36,16 @@ 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 | ||||
|       toString (mesh.baseMTU - overhead); | ||||
|  | ||||
|       bridgeFDBs = mapAttrsToList (n: peer: { | ||||
|         bridgeFDBConfig = { | ||||
|           MACAddress = "00:00:00:00:00:00"; | ||||
|           Destination = peer.addr; | ||||
|         }; | ||||
|         MACAddress = "00:00:00:00:00:00"; | ||||
|         Destination = peer.addr; | ||||
|       }) otherPeers; | ||||
|     }; | ||||
|   }; | ||||
| @@ -62,7 +60,11 @@ let | ||||
|       chain l2mesh-${name} { | ||||
|         ${optionalString mesh.security.enable '' | ||||
|           udp dport isakmp accept | ||||
|           meta l4proto esp accept | ||||
|           ${if mesh.udpEncapsulation then '' | ||||
|             udp dport ipsec-nat-t accept | ||||
|           '' else '' | ||||
|             meta l4proto esp accept | ||||
|           ''} | ||||
|         ''} | ||||
|         ${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)} | ||||
|         return | ||||
| @@ -94,6 +96,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); | ||||
|   | ||||
							
								
								
									
										232
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										232
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,232 @@ | ||||
| { lib, pkgs, config, ... }: | ||||
| let | ||||
|   inherit (lib) mkMerge mkIf mkForce genAttrs concatMapStringsSep; | ||||
|   inherit (lib.my) mkOpt' mkBoolOpt'; | ||||
|  | ||||
|   cfg = config.my.netboot; | ||||
|  | ||||
|   ipxe = pkgs.ipxe.overrideAttrs (o: rec { | ||||
|     version = "1.21.1-unstable-2024-06-27"; | ||||
|     src = pkgs.fetchFromGitHub { | ||||
|       owner = "ipxe"; | ||||
|       repo = "ipxe"; | ||||
|       rev = "b66e27d9b29a172a097c737ab4d378d60fe01b05"; | ||||
|       hash = "sha256-TKZ4WjNV2oZIYNefch7E7m1JpeoC/d7O1kofoNv8G40="; | ||||
|     }; | ||||
|   }); | ||||
|   tftpRoot = pkgs.linkFarm "tftp-root" [ | ||||
|     { | ||||
|       name = "ipxe-x86_64.efi"; | ||||
|       path = "${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() | ||||
| @@ -5,7 +5,15 @@ let | ||||
|  | ||||
|   cfg = config.my.nvme; | ||||
|   nvme-cli = pkgs.nvme-cli.override { | ||||
|     libnvme = pkgs.libnvme.overrideAttrs (o: { | ||||
|     libnvme = pkgs.libnvme.overrideAttrs (o: rec { | ||||
|       # TODO: Remove when 1.11.1 releases (see https://github.com/linux-nvme/libnvme/pull/914) | ||||
|       version = "1.11.1"; | ||||
|       src = pkgs.fetchFromGitHub { | ||||
|         owner = "linux-nvme"; | ||||
|         repo = "libnvme"; | ||||
|         rev = "v${version}"; | ||||
|         hash = "sha256-CEGr7PDOVRi210XvICH8iLYDKn8S9bGruBO4tycvsT8="; | ||||
|       }; | ||||
|       patches = (if (o ? patches) then o.patches else [ ]) ++ [ ./libnvme-hostconf.patch ]; | ||||
|     }); | ||||
|   }; | ||||
| @@ -33,24 +41,43 @@ in | ||||
|       etc = etc ""; | ||||
|     }; | ||||
|  | ||||
|     boot.initrd.systemd = mkIf (cfg.boot.nqn != null) { | ||||
|       contents = etc "/etc/"; | ||||
|       extraBin.nvme = "${nvme-cli}/bin/nvme"; | ||||
|     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 = with pkgs; { | ||||
|             dmesg = "${util-linux}/bin/dmesg"; | ||||
|             ip = "${iproute2}/bin/ip"; | ||||
|             nvme = "${nvme-cli}/bin/nvme"; | ||||
|           }; | ||||
|           extraConfig = '' | ||||
|             DefaultTimeoutStartSec=20 | ||||
|             DefaultDeviceTimeoutSec=20 | ||||
|           ''; | ||||
|  | ||||
|       services.connect-nvme = { | ||||
|         description = "Connect NVMe-oF"; | ||||
|         before = [ "initrd-root-device.target" ]; | ||||
|         after = [ "systemd-networkd-wait-online.service" ]; | ||||
|         requires = [ "systemd-networkd-wait-online.service" ]; | ||||
|           network = { | ||||
|             enable = true; | ||||
|             wait-online.enable = true; | ||||
|           }; | ||||
|  | ||||
|         serviceConfig = { | ||||
|           Type = "oneshot"; | ||||
|           ExecStart = "${nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn}"; | ||||
|           Restart = "on-failure"; | ||||
|           RestartSec = 10; | ||||
|           services.connect-nvme = { | ||||
|             description = "Connect NVMe-oF"; | ||||
|             before = [ "initrd-root-device.target" ]; | ||||
|             after = [ "systemd-networkd-wait-online.service" ]; | ||||
|             requires = [ "systemd-networkd-wait-online.service" ]; | ||||
|  | ||||
|             serviceConfig = { | ||||
|               Type = "oneshot"; | ||||
|               ExecStart = "${nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn}"; | ||||
|               Restart = "on-failure"; | ||||
|               RestartSec = 10; | ||||
|             }; | ||||
|  | ||||
|             wantedBy = [ "initrd-root-device.target" ]; | ||||
|           }; | ||||
|         }; | ||||
|  | ||||
|         wantedBy = [ "initrd-root-device.target" ]; | ||||
|       }; | ||||
|     }; | ||||
|   }; | ||||
|   | ||||
| @@ -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; | ||||
| @@ -147,6 +147,15 @@ in | ||||
|             "/var/lib/systemd" | ||||
|  | ||||
|             { directory = "/root/.cache/nix"; mode = "0700"; } | ||||
|             # Including these unconditionally due to infinite recursion problems... | ||||
|             { | ||||
|               directory = "/etc/lvm/archive"; | ||||
|               mode = "0700"; | ||||
|             } | ||||
|             { | ||||
|               directory = "/etc/lvm/backup"; | ||||
|               mode = "0700"; | ||||
|             } | ||||
|           ]; | ||||
|           files = [ | ||||
|             "/etc/machine-id" | ||||
| @@ -260,18 +269,6 @@ in | ||||
|         my.tmproot.persistence.config.files = | ||||
|           concatMap (k: [ k.path "${k.path}.pub" ]) config.services.openssh.hostKeys; | ||||
|       }) | ||||
|       (mkIf config.services.lvm.enable { | ||||
|         my.tmproot.persistence.config.directories = [ | ||||
|           { | ||||
|             directory = "/etc/lvm/archive"; | ||||
|             mode = "0700"; | ||||
|           } | ||||
|           { | ||||
|             directory = "/etc/lvm/backup"; | ||||
|             mode = "0700"; | ||||
|           } | ||||
|         ]; | ||||
|       }) | ||||
|       (mkIf (config.security.acme.certs != { }) { | ||||
|         my.tmproot.persistence.config.directories = [ | ||||
|           { | ||||
| @@ -495,6 +492,65 @@ 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"; | ||||
|           } | ||||
|         ]; | ||||
|       }) | ||||
|       (persistSimpleSvc "octoprint") | ||||
|       (mkIf (config.services.borgbackup.jobs != { }) { | ||||
|         my.tmproot.persistence.config.directories = [ | ||||
|           "/var/lib/borgbackup" | ||||
|           "/var/cache/borgbackup" | ||||
|         ]; | ||||
|  | ||||
|         services.borgbackup.package = pkgs.borgbackup.overrideAttrs (o: { | ||||
|           makeWrapperArgs = o.makeWrapperArgs ++ [ | ||||
|             "--set-default BORG_BASE_DIR /var/lib/borgbackup" | ||||
|             "--set-default BORG_CONFIG_DIR /var/lib/borgbackup/config" | ||||
|             "--set-default BORG_CACHE_DIR /var/cache/borgbackup" | ||||
|           ]; | ||||
|         }); | ||||
|       }) | ||||
|     ])) | ||||
|   ]); | ||||
|  | ||||
|   | ||||
| @@ -82,6 +82,10 @@ in | ||||
|       # NOTE: As the "outermost" module is still being evaluated in NixOS land, special params (e.g. pkgs) won't be | ||||
|       # passed to it | ||||
|       home-manager.users.${user'.name} = mkAliasDefinitions options.my.user.homeConfig; | ||||
|  | ||||
|       systemd.services.nixfiles-mutable.script = '' | ||||
|         chown -R ${user'.name} /run/nixfiles | ||||
|       ''; | ||||
|     } | ||||
|     (mkIf (cfg.passwordSecret != null) { | ||||
|       my = { | ||||
|   | ||||
| @@ -1,35 +0,0 @@ | ||||
| { lib, pkgs, config, ... }: | ||||
| let | ||||
|   inherit (lib) mkIf mkDefault; | ||||
|   inherit (lib.my) mkOpt' mkBoolOpt'; | ||||
|  | ||||
|   cfg = config.services.wastebin; | ||||
| in | ||||
| { | ||||
|   options.services.wastebin = with lib.types; { | ||||
|     enable = mkBoolOpt' false "Whether to enable wastebin."; | ||||
|     package = mkOpt' package pkgs.wastebin "Package to use."; | ||||
|     settings = mkOpt' (attrsOf str) { } "Environment variable settings."; | ||||
|     extraSettingsFile = mkOpt' (nullOr str) null "Extra environment file (e.g. for signing key)."; | ||||
|   }; | ||||
|  | ||||
|   config = mkIf cfg.enable { | ||||
|     services.wastebin.settings = { | ||||
|       WASTEBIN_ADDRESS_PORT = mkDefault "[::]:8088"; | ||||
|       WASTEBIN_DATABASE_PATH = mkDefault "/var/lib/wastebin/db.sqlite3"; | ||||
|     }; | ||||
|  | ||||
|     systemd.services.wastebin = { | ||||
|       description = "wastebin minimal pastebin"; | ||||
|       after = [ "network.target" ]; | ||||
|       environment = cfg.settings; | ||||
|       serviceConfig = { | ||||
|         EnvironmentFile = mkIf (cfg.extraSettingsFile != null) cfg.extraSettingsFile; | ||||
|         DynamicUser = true; | ||||
|         StateDirectory = "wastebin"; | ||||
|         ExecStart = "${cfg.package}/bin/wastebin"; | ||||
|       }; | ||||
|       wantedBy = [ "multi-user.target" ]; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										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,7 +7,9 @@ in | ||||
|   monocraft' = callPackage ./monocraft.nix { }; | ||||
|   vfio-pci-bind = callPackage ./vfio-pci-bind.nix { }; | ||||
|   librespeed-go = callPackage ./librespeed-go.nix { }; | ||||
|   modrinth-app = callPackage ./modrinth-app { }; | ||||
|   wastebin = callPackage ./wastebin { }; | ||||
|   glfw-minecraft = callPackage ./glfw-minecraft { }; | ||||
|   # modrinth-app = callPackage ./modrinth-app { }; | ||||
|   chocolate-doom2xx = callPackage ./chocolate-doom2xx { }; | ||||
|   windowtolayer = callPackage ./windowtolayer.nix { }; | ||||
|   swaylock-plugin = callPackage ./swaylock-plugin.nix { }; | ||||
|   terminaltexteffects = callPackage ./terminaltexteffects.nix { }; | ||||
| } | ||||
|   | ||||
| @@ -1,6 +0,0 @@ | ||||
| { lib, glfw-wayland-minecraft, ... }: | ||||
| glfw-wayland-minecraft.overrideAttrs (o: { | ||||
|   patches = [ | ||||
|     ./suppress-wayland-errors.patch | ||||
|   ]; | ||||
| }) | ||||
| @@ -1,43 +0,0 @@ | ||||
| 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, | ||||
							
								
								
									
										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 | ||||
|   ]; | ||||
| } | ||||
							
								
								
									
										2161
									
								
								pkgs/wastebin/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										2161
									
								
								pkgs/wastebin/Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							| @@ -1,22 +0,0 @@ | ||||
| { lib | ||||
| , fetchFromGitHub | ||||
| , rustPlatform | ||||
| }: | ||||
| rustPlatform.buildRustPackage rec { | ||||
|   pname = "wastebin"; | ||||
|   version = "2.4.2"; | ||||
|  | ||||
|   src = fetchFromGitHub { | ||||
|     owner = "matze"; | ||||
|     repo = pname; | ||||
|     rev = version; | ||||
|     hash = "sha256-9SsNtIZfRK9HwWaqlsuSCs7eNK/7KnzDtCe0fFslXwA="; | ||||
|   }; | ||||
|  | ||||
|   cargoLock = { | ||||
|     lockFile = ./Cargo.lock; | ||||
|     outputHashes = { | ||||
|       "rusqlite_migration-1.1.0" = "sha256-FpIwgISYWEg7IQxG4tJ3u6b8+qanaqanZrq0Bz5WlLs="; | ||||
|     }; | ||||
|   }; | ||||
| } | ||||
							
								
								
									
										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 +0,0 @@ | ||||
| -----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= | ||||
| -----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