Compare commits
	
		
			116 Commits
		
	
	
		
			fastback-s
			...
			26a16d0629
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 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 | |||
| a0e4cf2479 | |||
| a5880d66f4 | |||
| 27a4583879 | |||
| fdbf5f8aca | |||
| 40c491aa14 | |||
| 1a8740fb9c | |||
| f857e751b5 | |||
| b420f2377c | |||
| 7d90b5ecb8 | |||
| ace979c226 | |||
| f540edb361 | |||
| 6bc5cd79da | |||
| 5ec77dfde6 | |||
| 52623d458e | |||
| 23b29f0707 | |||
| 338902497f | |||
| 977846991a | |||
| 0e8aec58fb | |||
| 0f1de58917 | |||
| 32183bd331 | |||
| 1813ca1927 | |||
| 51d44e472a | |||
| 44e87aa387 | |||
| f90deabb50 | 
@@ -10,7 +10,7 @@ jobs:
 | 
				
			|||||||
    runs-on: ubuntu-22.04
 | 
					    runs-on: ubuntu-22.04
 | 
				
			||||||
    steps:
 | 
					    steps:
 | 
				
			||||||
      - uses: actions/checkout@v4
 | 
					      - uses: actions/checkout@v4
 | 
				
			||||||
      - uses: cachix/install-nix-action@v23
 | 
					      - uses: cachix/install-nix-action@v27
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          # Gitea will supply a token in GITHUB_TOKEN, which this action will
 | 
					          # Gitea will supply a token in GITHUB_TOKEN, which this action will
 | 
				
			||||||
          # try to pass to Nix when downloading from GitHub
 | 
					          # try to pass to Nix when downloading from GitHub
 | 
				
			||||||
@@ -18,13 +18,11 @@ jobs:
 | 
				
			|||||||
          extra_nix_config: |
 | 
					          extra_nix_config: |
 | 
				
			||||||
            # Make sure we're using sandbox
 | 
					            # Make sure we're using sandbox
 | 
				
			||||||
            sandbox-fallback = false
 | 
					            sandbox-fallback = false
 | 
				
			||||||
 | 
					            # Big C++ projects fill up memory...
 | 
				
			||||||
 | 
					            cores = 6
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            extra-substituters = https://nix-cache.nul.ie/main
 | 
					            extra-substituters = https://nix-cache.nul.ie
 | 
				
			||||||
            extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=
 | 
					            extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
 | 
				
			||||||
      - 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 }}"
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Check flake
 | 
					      - name: Check flake
 | 
				
			||||||
        run: nix flake check
 | 
					        run: nix flake check
 | 
				
			||||||
@@ -33,7 +31,9 @@ jobs:
 | 
				
			|||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out)
 | 
					          path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out)
 | 
				
			||||||
          echo "path=$path" >> "$GITHUB_OUTPUT"
 | 
					          echo "path=$path" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      - name: Push to cache
 | 
					      - name: Push to cache
 | 
				
			||||||
 | 
					        env:
 | 
				
			||||||
 | 
					          HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }}
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
 | 
					          ci/push-to-cache.sh "${{ steps.build.outputs.path }}"
 | 
				
			||||||
            push main ${{ steps.build.outputs.path }}
 | 
					 | 
				
			||||||
 
 | 
				
			|||||||
@@ -14,22 +14,20 @@ jobs:
 | 
				
			|||||||
        uses: https://github.com/actions/setup-go@v4
 | 
					        uses: https://github.com/actions/setup-go@v4
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          go-version: '>=1.20.1'
 | 
					          go-version: '>=1.20.1'
 | 
				
			||||||
      - uses: cachix/install-nix-action@v23
 | 
					      - uses: cachix/install-nix-action@v27
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          github_access_token: ${{ secrets.GH_PULL_TOKEN }}
 | 
					          github_access_token: ${{ secrets.GH_PULL_TOKEN }}
 | 
				
			||||||
          extra_nix_config: |
 | 
					          extra_nix_config: |
 | 
				
			||||||
            # Make sure we're using sandbox
 | 
					            # Make sure we're using sandbox
 | 
				
			||||||
            sandbox-fallback = false
 | 
					            sandbox-fallback = false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            extra-substituters = https://nix-cache.nul.ie/main
 | 
					            extra-substituters = https://nix-cache.nul.ie
 | 
				
			||||||
            extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=
 | 
					            extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
 | 
				
			||||||
      - name: Set up attic
 | 
					
 | 
				
			||||||
 | 
					      - name: Set up vars
 | 
				
			||||||
        id: setup
 | 
					        id: setup
 | 
				
			||||||
        run: |
 | 
					        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"
 | 
					          echo "short_rev=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
 | 
				
			||||||
 | 
					 | 
				
			||||||
      - name: Build installer ISO
 | 
					      - name: Build installer ISO
 | 
				
			||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso
 | 
					          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso
 | 
				
			||||||
@@ -39,12 +37,13 @@ jobs:
 | 
				
			|||||||
        run: |
 | 
					        run: |
 | 
				
			||||||
          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive
 | 
					          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive
 | 
				
			||||||
          ln -s "$(readlink result)" \
 | 
					          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
 | 
					      - name: Create release
 | 
				
			||||||
        uses: https://gitea.com/actions/release-action@main
 | 
					        uses: https://gitea.com/actions/release-action@main
 | 
				
			||||||
        with:
 | 
					        with:
 | 
				
			||||||
          title: Latest installer
 | 
					          title: Latest installer
 | 
				
			||||||
 | 
					          api_key: '${{ secrets.RELEASE_TOKEN }}'
 | 
				
			||||||
          files: |
 | 
					          files: |
 | 
				
			||||||
            jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
 | 
					            jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
 | 
				
			||||||
            jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
					            jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										1
									
								
								.keys/harmonia.pub
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								.keys/harmonia.pub
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXRXkYnBf2opIjN+bXE7HmhUpa4hyXJUGmBT+MRccT4 harmonia
 | 
				
			||||||
							
								
								
									
										1
									
								
								ci/known_hosts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								ci/known_hosts
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1 @@
 | 
				
			|||||||
 | 
					object-ctr.ams1.int.nul.ie ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdHbZErWLmTPO/aEWB1Fup/aGMf31Un5Wk66FJwTz/8
 | 
				
			||||||
							
								
								
									
										29
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										29
									
								
								ci/push-to-cache.sh
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,29 @@
 | 
				
			|||||||
 | 
					#!/bin/sh
 | 
				
			||||||
 | 
					set -e
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					REMOTE_STORE=/var/lib/harmonia
 | 
				
			||||||
 | 
					SSH_HOST="harmonia@object-ctr.ams1.int.nul.ie"
 | 
				
			||||||
 | 
					SSH_KEY=/tmp/harmonia.key
 | 
				
			||||||
 | 
					STORE_URI="ssh-ng://$SSH_HOST?ssh-key=$SSH_KEY&remote-store=$REMOTE_STORE"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					remote_cmd() {
 | 
				
			||||||
 | 
					  ssh -i "$SSH_KEY" "$SSH_HOST" env HOME=/run/harmonia NIX_REMOTE="$REMOTE_STORE" "$@"
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					umask_old=$(umask)
 | 
				
			||||||
 | 
					umask 0066
 | 
				
			||||||
 | 
					echo "$HARMONIA_SSH_KEY" | base64 -d > "$SSH_KEY"
 | 
				
			||||||
 | 
					umask $umask_old
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					mkdir -p ~/.ssh
 | 
				
			||||||
 | 
					cp ci/known_hosts ~/.ssh/
 | 
				
			||||||
 | 
					path="$1"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Pushing $path to cache..."
 | 
				
			||||||
 | 
					nix copy --no-check-sigs --to "$STORE_URI" "$path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Updating profile..."
 | 
				
			||||||
 | 
					remote_cmd nix-env -p "$REMOTE_STORE"/nix/var/nix/profiles/nixfiles --set "$path"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					echo "Collecting garbage..."
 | 
				
			||||||
 | 
					remote_cmd nix-collect-garbage --delete-older-than 30d
 | 
				
			||||||
@@ -20,7 +20,7 @@ in
 | 
				
			|||||||
          [ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
 | 
					          [ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          mkdir -p "$(dirname "${homeFlake}")"
 | 
					          mkdir -p "$(dirname "${homeFlake}")"
 | 
				
			||||||
          ln -s "$(pwd)/flake.nix" "${homeFlake}"
 | 
					          ln -sf "$(pwd)/flake.nix" "${homeFlake}"
 | 
				
			||||||
          echo "Installed link to $(pwd)/flake.nix at ${homeFlake}"
 | 
					          echo "Installed link to $(pwd)/flake.nix at ${homeFlake}"
 | 
				
			||||||
        '';
 | 
					        '';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
@@ -52,7 +52,7 @@ in
 | 
				
			|||||||
      name = "json2nix";
 | 
					      name = "json2nix";
 | 
				
			||||||
      category = "utilities";
 | 
					      category = "utilities";
 | 
				
			||||||
      help = "Convert JSON to formatted Nix";
 | 
					      help = "Convert JSON to formatted Nix";
 | 
				
			||||||
      command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt}/bin/nixfmt";
 | 
					      command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt-rfc-style}/bin/nixfmt";
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -106,8 +106,8 @@ in
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
      name = "build-netboot";
 | 
					      name = "build-netboot";
 | 
				
			||||||
      category = "tasks";
 | 
					      category = "tasks";
 | 
				
			||||||
      help = "Build NixOS configuration as netboot archive";
 | 
					      help = "Build NixOS configuration as netboot tree";
 | 
				
			||||||
      command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootArchive"'';
 | 
					      command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootTree"'';
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      name = "build-home";
 | 
					      name = "build-home";
 | 
				
			||||||
@@ -145,5 +145,15 @@ in
 | 
				
			|||||||
      help = "Update installer tag (to trigger new release)";
 | 
					      help = "Update installer tag (to trigger new release)";
 | 
				
			||||||
      command = ''git tag -f installer && git push -f origin installer'';
 | 
					      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
 | 
				
			||||||
 | 
					      '';
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -24,10 +24,10 @@ in
 | 
				
			|||||||
    coreutils
 | 
					    coreutils
 | 
				
			||||||
    nixVersions.stable
 | 
					    nixVersions.stable
 | 
				
			||||||
    rage
 | 
					    rage
 | 
				
			||||||
 | 
					    wireguard-tools
 | 
				
			||||||
    (pkgs.writeShellScriptBin "deploy" ''
 | 
					    (pkgs.writeShellScriptBin "deploy" ''
 | 
				
			||||||
      exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@"
 | 
					      exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@"
 | 
				
			||||||
    '')
 | 
					    '')
 | 
				
			||||||
    home-manager
 | 
					    home-manager
 | 
				
			||||||
    attic-client
 | 
					 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										529
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										529
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@@ -3,17 +3,19 @@
 | 
				
			|||||||
    "agenix": {
 | 
					    "agenix": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "darwin": "darwin",
 | 
					        "darwin": "darwin",
 | 
				
			||||||
 | 
					        "home-manager": "home-manager",
 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": [
 | 
				
			||||||
          "ragenix",
 | 
					          "ragenix",
 | 
				
			||||||
          "nixpkgs"
 | 
					          "nixpkgs"
 | 
				
			||||||
        ]
 | 
					        ],
 | 
				
			||||||
 | 
					        "systems": "systems_8"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1682101079,
 | 
					        "lastModified": 1707830867,
 | 
				
			||||||
        "narHash": "sha256-MdAhtjrLKnk2uiqun1FWABbKpLH090oeqCSiWemtuck=",
 | 
					        "narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=",
 | 
				
			||||||
        "owner": "ryantm",
 | 
					        "owner": "ryantm",
 | 
				
			||||||
        "repo": "agenix",
 | 
					        "repo": "agenix",
 | 
				
			||||||
        "rev": "2994d002dcff5353ca1ac48ec584c7f6589fe447",
 | 
					        "rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -35,11 +37,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1702969472,
 | 
					        "lastModified": 1720542474,
 | 
				
			||||||
        "narHash": "sha256-IJP9sC+/gLUdWhm6TsnWpw6A1zQWUfn53ym63KeLXvU=",
 | 
					        "narHash": "sha256-aKjJ/4l2I9+wNGTaOGRsuS3M1+IoTibqgEMPDikXm04=",
 | 
				
			||||||
        "owner": "zhaofengli",
 | 
					        "owner": "zhaofengli",
 | 
				
			||||||
        "repo": "attic",
 | 
					        "repo": "attic",
 | 
				
			||||||
        "rev": "bdafd64910bb2b861cf90fa15f1fc93318b6fbf6",
 | 
					        "rev": "6139576a3ce6bb992e0f6c3022528ec233e45f00",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -58,17 +60,17 @@
 | 
				
			|||||||
        "poetry2nix": "poetry2nix"
 | 
					        "poetry2nix": "poetry2nix"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1682289679,
 | 
					        "lastModified": 1718746012,
 | 
				
			||||||
        "narHash": "sha256-DbhSJ6y62VAO2VsJwoz3VsxCEP/4KMeFVs0wIz6Im04=",
 | 
					        "narHash": "sha256-sp9vGl3vWXvD/C2JeMDi5nbW6CkKIC3Q2JMGKwexYEs=",
 | 
				
			||||||
        "owner": "devplayer0",
 | 
					        "ref": "refs/heads/master",
 | 
				
			||||||
        "repo": "boardie",
 | 
					        "rev": "ea24100bd4a914b9e044a2085a3785a6bd3a3833",
 | 
				
			||||||
        "rev": "e4b977f75bf7b4f656a691efca492ae057672a77",
 | 
					        "revCount": 5,
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "git",
 | 
				
			||||||
 | 
					        "url": "https://git.nul.ie/dev/boardie"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "devplayer0",
 | 
					        "type": "git",
 | 
				
			||||||
        "repo": "boardie",
 | 
					        "url": "https://git.nul.ie/dev/boardie"
 | 
				
			||||||
        "type": "github"
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "borgthin": {
 | 
					    "borgthin": {
 | 
				
			||||||
@@ -101,11 +103,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1702918879,
 | 
					        "lastModified": 1717025063,
 | 
				
			||||||
        "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=",
 | 
					        "narHash": "sha256-dIubLa56W9sNNz0e8jGxrX3CAkPXsq7snuFA/Ie6dn8=",
 | 
				
			||||||
        "owner": "ipetkov",
 | 
					        "owner": "ipetkov",
 | 
				
			||||||
        "repo": "crane",
 | 
					        "repo": "crane",
 | 
				
			||||||
        "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb",
 | 
					        "rev": "480dff0be03dac0e51a8dfc26e882b0d123a450e",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -116,26 +118,17 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "crane_2": {
 | 
					    "crane_2": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-compat": "flake-compat_3",
 | 
					 | 
				
			||||||
        "flake-utils": [
 | 
					 | 
				
			||||||
          "ragenix",
 | 
					 | 
				
			||||||
          "flake-utils"
 | 
					 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": [
 | 
				
			||||||
          "ragenix",
 | 
					          "ragenix",
 | 
				
			||||||
          "nixpkgs"
 | 
					          "nixpkgs"
 | 
				
			||||||
        ],
 | 
					 | 
				
			||||||
        "rust-overlay": [
 | 
					 | 
				
			||||||
          "ragenix",
 | 
					 | 
				
			||||||
          "rust-overlay"
 | 
					 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681680516,
 | 
					        "lastModified": 1708794349,
 | 
				
			||||||
        "narHash": "sha256-EB8Adaeg4zgcYDJn9sR6UMjN/OHdIiMMK19+3LmmXQY=",
 | 
					        "narHash": "sha256-jX+B1VGHT0ruHHL5RwS8L21R6miBn4B6s9iVyUJsJJY=",
 | 
				
			||||||
        "owner": "ipetkov",
 | 
					        "owner": "ipetkov",
 | 
				
			||||||
        "repo": "crane",
 | 
					        "repo": "crane",
 | 
				
			||||||
        "rev": "54b63c8eae4c50172cb50b612946ff1d2bc1c75c",
 | 
					        "rev": "2c94ff9a6fbeb9f3ea0107f28688edbe9c81deaa",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -153,11 +146,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1673295039,
 | 
					        "lastModified": 1700795494,
 | 
				
			||||||
        "narHash": "sha256-AsdYgE8/GPwcelGgrntlijMg4t3hLFJFCRF3tL5WVjA=",
 | 
					        "narHash": "sha256-gzGLZSiOhf155FW7262kdHo2YDeugp3VuIFb4/GGng0=",
 | 
				
			||||||
        "owner": "lnl7",
 | 
					        "owner": "lnl7",
 | 
				
			||||||
        "repo": "nix-darwin",
 | 
					        "repo": "nix-darwin",
 | 
				
			||||||
        "rev": "87b9d090ad39b25b2400029c64825fc2a8868943",
 | 
					        "rev": "4b9b83d5a92e8c1fbfd8eb27eda375908c11ec4d",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -176,11 +169,11 @@
 | 
				
			|||||||
        "utils": "utils"
 | 
					        "utils": "utils"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703087360,
 | 
					        "lastModified": 1718194053,
 | 
				
			||||||
        "narHash": "sha256-0VUbWBW8VyiDRuimMuLsEO4elGuUw/nc2WDeuO1eN1M=",
 | 
					        "narHash": "sha256-FaGrf7qwZ99ehPJCAwgvNY5sLCqQ3GDiE/6uLhxxwSY=",
 | 
				
			||||||
        "owner": "serokell",
 | 
					        "owner": "serokell",
 | 
				
			||||||
        "repo": "deploy-rs",
 | 
					        "repo": "deploy-rs",
 | 
				
			||||||
        "rev": "b709d63debafce9f5645a5ba550c9e0983b3d1f7",
 | 
					        "rev": "3867348fa92bc892eba5d9ddb2d7a97b9e127a8a",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -195,11 +188,11 @@
 | 
				
			|||||||
        "nixpkgs": "nixpkgs"
 | 
					        "nixpkgs": "nixpkgs"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1678957337,
 | 
					        "lastModified": 1717408969,
 | 
				
			||||||
        "narHash": "sha256-Gw4nVbuKRdTwPngeOZQOzH/IFowmz4LryMPDiJN/ah4=",
 | 
					        "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "devshell",
 | 
					        "repo": "devshell",
 | 
				
			||||||
        "rev": "3e0e60ab37cd0bf7ab59888f5c32499d851edb47",
 | 
					        "rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -208,6 +201,25 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "devshell-tools": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils_11",
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs_4"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1710099997,
 | 
				
			||||||
 | 
					        "narHash": "sha256-WmBKTLdth6I/D+0//9enbIXohGsBjepbjIAm9pCYj0U=",
 | 
				
			||||||
 | 
					        "owner": "eikek",
 | 
				
			||||||
 | 
					        "repo": "devshell-tools",
 | 
				
			||||||
 | 
					        "rev": "e82faf976d318b3829f6f7f6785db6f3c7b65267",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "eikek",
 | 
				
			||||||
 | 
					        "repo": "devshell-tools",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "devshell_2": {
 | 
					    "devshell_2": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-utils": "flake-utils_5",
 | 
					        "flake-utils": "flake-utils_5",
 | 
				
			||||||
@@ -229,17 +241,17 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "devshell_3": {
 | 
					    "devshell_3": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils_7",
 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": [
 | 
				
			||||||
          "nixpkgs-unstable"
 | 
					          "nixpkgs-unstable"
 | 
				
			||||||
        ],
 | 
					        ]
 | 
				
			||||||
        "systems": "systems_4"
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1701787589,
 | 
					        "lastModified": 1713532798,
 | 
				
			||||||
        "narHash": "sha256-ce+oQR4Zq9VOsLoh9bZT8Ip9PaMLcjjBUHVPzW5d7Cw=",
 | 
					        "narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "devshell",
 | 
					        "repo": "devshell",
 | 
				
			||||||
        "rev": "44ddedcbcfc2d52a76b64fb6122f209881bd3e1e",
 | 
					        "rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -280,22 +292,6 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-compat_3": {
 | 
					 | 
				
			||||||
      "flake": false,
 | 
					 | 
				
			||||||
      "locked": {
 | 
					 | 
				
			||||||
        "lastModified": 1673956053,
 | 
					 | 
				
			||||||
        "narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
 | 
					 | 
				
			||||||
        "owner": "edolstra",
 | 
					 | 
				
			||||||
        "repo": "flake-compat",
 | 
					 | 
				
			||||||
        "rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
 | 
					 | 
				
			||||||
        "type": "github"
 | 
					 | 
				
			||||||
      },
 | 
					 | 
				
			||||||
      "original": {
 | 
					 | 
				
			||||||
        "owner": "edolstra",
 | 
					 | 
				
			||||||
        "repo": "flake-compat",
 | 
					 | 
				
			||||||
        "type": "github"
 | 
					 | 
				
			||||||
      }
 | 
					 | 
				
			||||||
    },
 | 
					 | 
				
			||||||
    "flake-utils": {
 | 
					    "flake-utils": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1667395993,
 | 
					        "lastModified": 1667395993,
 | 
				
			||||||
@@ -312,6 +308,60 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_10": {
 | 
					    "flake-utils_10": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems_9"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1705309234,
 | 
				
			||||||
 | 
					        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "flake-utils_11": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems_10"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1709126324,
 | 
				
			||||||
 | 
					        "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "d465f4819400de7c8d874d50b982301f28a84605",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "flake-utils_12": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems_11"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1705309234,
 | 
				
			||||||
 | 
					        "narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "flake-utils_13": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1667395993,
 | 
					        "lastModified": 1667395993,
 | 
				
			||||||
        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
 | 
					        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
 | 
				
			||||||
@@ -327,12 +377,15 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_2": {
 | 
					    "flake-utils_2": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1642700792,
 | 
					        "lastModified": 1701680307,
 | 
				
			||||||
        "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
 | 
					        "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "846b2ae0fc4cc943637d3d1def4454213e203cba",
 | 
					        "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -343,14 +396,14 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_3": {
 | 
					    "flake-utils_3": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "systems": "systems"
 | 
					        "systems": "systems_2"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681202837,
 | 
					        "lastModified": 1710146030,
 | 
				
			||||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
					        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
					        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -361,14 +414,14 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_4": {
 | 
					    "flake-utils_4": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "systems": "systems_2"
 | 
					        "systems": "systems_3"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681202837,
 | 
					        "lastModified": 1710146030,
 | 
				
			||||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
					        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "numtide",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
					        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -409,7 +462,7 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_7": {
 | 
					    "flake-utils_7": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "systems": "systems_5"
 | 
					        "systems": "systems_6"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1701680307,
 | 
					        "lastModified": 1701680307,
 | 
				
			||||||
@@ -426,6 +479,24 @@
 | 
				
			|||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_8": {
 | 
					    "flake-utils_8": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "systems": "systems_7"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1710146030,
 | 
				
			||||||
 | 
					        "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "flake-utils",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "flake-utils_9": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1659877975,
 | 
					        "lastModified": 1659877975,
 | 
				
			||||||
        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
 | 
					        "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
 | 
				
			||||||
@@ -440,21 +511,25 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "flake-utils_9": {
 | 
					    "home-manager": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "systems": "systems_6"
 | 
					        "nixpkgs": [
 | 
				
			||||||
 | 
					          "ragenix",
 | 
				
			||||||
 | 
					          "agenix",
 | 
				
			||||||
 | 
					          "nixpkgs"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681202837,
 | 
					        "lastModified": 1703113217,
 | 
				
			||||||
        "narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
 | 
					        "narHash": "sha256-7ulcXOk63TIT2lVDSExj7XzFx09LpdSAPtvgtM7yQPE=",
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "home-manager",
 | 
				
			||||||
        "rev": "cfacdce06f30d2b68473a46042957675eebb3401",
 | 
					        "rev": "3bfaacf46133c037bb356193bd2f1765d9dc82c1",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "numtide",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "flake-utils",
 | 
					        "repo": "home-manager",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
@@ -465,11 +540,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703367386,
 | 
					        "lastModified": 1719827415,
 | 
				
			||||||
        "narHash": "sha256-FMbm48UGrBfOWGt8+opuS+uLBLQlRfhiYXhHNcYMS5k=",
 | 
					        "narHash": "sha256-pvh+1hStXXAZf0sZ1xIJbWGx4u+OGBC1rVx6Wsw0fBw=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "home-manager",
 | 
					        "repo": "home-manager",
 | 
				
			||||||
        "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224",
 | 
					        "rev": "f2e3c19867262dbe84fdfab42467fc8dd83a2005",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -485,11 +560,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703754036,
 | 
					        "lastModified": 1720734513,
 | 
				
			||||||
        "narHash": "sha256-JpJdcj9Tg4lMuYikXDpajA8wOp+rHyn9RD2rKBEM4cQ=",
 | 
					        "narHash": "sha256-neWQ8eNtLTd+YMesb7WjKl1SVCbDyCm46LUgP/g/hdo=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "home-manager",
 | 
					        "repo": "home-manager",
 | 
				
			||||||
        "rev": "c24c298562fe41b39909f632c5a7151bbf6b4628",
 | 
					        "rev": "90ae324e2c56af10f20549ab72014804a3064c7f",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -499,11 +574,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "impermanence": {
 | 
					    "impermanence": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703656108,
 | 
					        "lastModified": 1719091691,
 | 
				
			||||||
        "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=",
 | 
					        "narHash": "sha256-AxaLX5cBEcGtE02PeGsfscSb/fWMnyS7zMWBXQWDKbE=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "impermanence",
 | 
					        "repo": "impermanence",
 | 
				
			||||||
        "rev": "033643a45a4a920660ef91caa391fbffb14da466",
 | 
					        "rev": "23c1f06316b67cb5dabdfe2973da3785cfe9c34a",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -512,19 +587,41 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "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": {
 | 
					    "nixGL": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-utils": "flake-utils_8",
 | 
					        "flake-utils": "flake-utils_9",
 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": [
 | 
				
			||||||
          "nixpkgs-unstable"
 | 
					          "nixpkgs-unstable"
 | 
				
			||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1685908677,
 | 
					        "lastModified": 1713543440,
 | 
				
			||||||
        "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=",
 | 
					        "narHash": "sha256-lnzZQYG0+EXl/6NkGpyIz+FEOc/DSEG57AP1VsdeNrM=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "nixGL",
 | 
					        "repo": "nixGL",
 | 
				
			||||||
        "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5",
 | 
					        "rev": "310f8e49a149e4c9ea52f1adf70cdc768ec53f8a",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -535,11 +632,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs": {
 | 
					    "nixpkgs": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1677383253,
 | 
					        "lastModified": 1704161960,
 | 
				
			||||||
        "narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=",
 | 
					        "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "9952d6bc395f5841262b006fbace8dd7e143b634",
 | 
					        "rev": "63143ac2c9186be6d9da6035fa22620018c85932",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -551,11 +648,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs-mine": {
 | 
					    "nixpkgs-mine": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703756459,
 | 
					        "lastModified": 1724669894,
 | 
				
			||||||
        "narHash": "sha256-ztEMyPQZh3Pb+LOoWl5lbIK2LenP59sOUBC86CDmLio=",
 | 
					        "narHash": "sha256-oHDWt37dN3Bq12E016HDw0rnjBlRg51hg66b7qG6cro=",
 | 
				
			||||||
        "owner": "devplayer0",
 | 
					        "owner": "devplayer0",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "e80160eb2ac3a7111d07cc43a15c16b9edca01ea",
 | 
					        "rev": "01d95eaee35f63ed8e48dedb573f48a1a3028f88",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -567,11 +664,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs-mine-stable": {
 | 
					    "nixpkgs-mine-stable": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703756491,
 | 
					        "lastModified": 1720987393,
 | 
				
			||||||
        "narHash": "sha256-9VL34e0gzomwqRnryRn23V2ImYcaZIQdp7CsWg5TmlE=",
 | 
					        "narHash": "sha256-aq1reu43552gD+QRyxAMlimAX9+YbGpAIyw82jg0eWY=",
 | 
				
			||||||
        "owner": "devplayer0",
 | 
					        "owner": "devplayer0",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "36611f5f7cfd401f51ad4ca76fd6ee85a714bb74",
 | 
					        "rev": "154ab603fb2b794b437f233853aeb3c75f101049",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -583,11 +680,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs-stable": {
 | 
					    "nixpkgs-stable": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703467016,
 | 
					        "lastModified": 1720535198,
 | 
				
			||||||
        "narHash": "sha256-/5A/dNPhbQx/Oa2d+Get174eNI3LERQ7u6WTWOlR1eQ=",
 | 
					        "narHash": "sha256-zwVvxrdIzralnSbcpghA92tWu2DV2lwv89xZc8MTrbg=",
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "d02d818f22c777aa4e854efc3242ec451e5d462a",
 | 
					        "rev": "205fd4226592cc83fd4c0885a3e4c9c400efabb5",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -598,11 +695,11 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs-unstable": {
 | 
					    "nixpkgs-unstable": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1703438236,
 | 
					        "lastModified": 1723175592,
 | 
				
			||||||
        "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
 | 
					        "narHash": "sha256-M0xJ3FbDUc4fRZ84dPGx5VvgFsOzds77KiBMW/mMTnI=",
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
 | 
					        "rev": "5e0ca22929f3342b19569b21b2f3462f053e497b",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -613,15 +710,16 @@
 | 
				
			|||||||
    },
 | 
					    },
 | 
				
			||||||
    "nixpkgs_2": {
 | 
					    "nixpkgs_2": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681756206,
 | 
					        "lastModified": 1718632497,
 | 
				
			||||||
        "narHash": "sha256-7B2Jc1zosXvZJKlxTPBlGew0LeX/7cxguG/d3syc1JI=",
 | 
					        "narHash": "sha256-YtlyfqOdYMuu7gumZtK0Kg7jr4OKfHUhJkZfNUryw68=",
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "rev": "6eceb07c28016ec50dd683fda94995702b67e855",
 | 
					        "rev": "c58b4a9118498c1055c5908a5bbe666e56abe949",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "NixOS",
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixos-unstable-small",
 | 
				
			||||||
        "repo": "nixpkgs",
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -642,17 +740,52 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "nixpkgs_4": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1709309926,
 | 
				
			||||||
 | 
					        "narHash": "sha256-VZFBtXGVD9LWTecGi6eXrE0hJ/mVB3zGUlHImUs2Qak=",
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "rev": "79baff8812a0d68e24a836df0a364c678089e2c7",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixos-23.11",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "nixpkgs_5": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1674990008,
 | 
				
			||||||
 | 
					        "narHash": "sha256-4zOyp+hFW2Y7imxIpZqZGT8CEqKmDjwgfD6BzRUE0mQ=",
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "rev": "d2bbcbe6c626d339b25a4995711f07625b508214",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "NixOS",
 | 
				
			||||||
 | 
					        "ref": "nixpkgs-unstable",
 | 
				
			||||||
 | 
					        "repo": "nixpkgs",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "poetry2nix": {
 | 
					    "poetry2nix": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-utils": "flake-utils_4",
 | 
					        "flake-utils": "flake-utils_4",
 | 
				
			||||||
        "nixpkgs": "nixpkgs_2"
 | 
					        "nix-github-actions": "nix-github-actions",
 | 
				
			||||||
 | 
					        "nixpkgs": "nixpkgs_2",
 | 
				
			||||||
 | 
					        "systems": "systems_4",
 | 
				
			||||||
 | 
					        "treefmt-nix": "treefmt-nix"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681532901,
 | 
					        "lastModified": 1718726452,
 | 
				
			||||||
        "narHash": "sha256-9ZN/gaCOlkx53km4J2QkLQh4bS+6UCBsjdi87kw6+jc=",
 | 
					        "narHash": "sha256-w4hJSYvACz0i5XHtxc6XNyHwbxpisN13M2kA2Y7937o=",
 | 
				
			||||||
        "owner": "nix-community",
 | 
					        "owner": "nix-community",
 | 
				
			||||||
        "repo": "poetry2nix",
 | 
					        "repo": "poetry2nix",
 | 
				
			||||||
        "rev": "2e66fd2623eccb3086e52929c2cefd882faac8a8",
 | 
					        "rev": "53e534a08c0cd2a9fa7587ed1c3e7f6aeb804a2c",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -665,22 +798,23 @@
 | 
				
			|||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "agenix": "agenix",
 | 
					        "agenix": "agenix",
 | 
				
			||||||
        "crane": "crane_2",
 | 
					        "crane": "crane_2",
 | 
				
			||||||
        "flake-utils": "flake-utils_9",
 | 
					        "flake-utils": "flake-utils_10",
 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": [
 | 
				
			||||||
          "nixpkgs-unstable"
 | 
					          "nixpkgs-unstable"
 | 
				
			||||||
        ],
 | 
					        ],
 | 
				
			||||||
        "rust-overlay": "rust-overlay"
 | 
					        "rust-overlay": "rust-overlay"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1682237245,
 | 
					        "lastModified": 1725195663,
 | 
				
			||||||
        "narHash": "sha256-xbBR7LNK+d5Yi/D6FXQGc1R6u2VV2nwr/Df5iaEbOEQ=",
 | 
					        "narHash": "sha256-vnmQ0tMkQpiOW5xvM9WVVDLr4OjYKquq0iOaAlPriqA=",
 | 
				
			||||||
        "owner": "yaxitech",
 | 
					        "owner": "devplayer0",
 | 
				
			||||||
        "repo": "ragenix",
 | 
					        "repo": "ragenix",
 | 
				
			||||||
        "rev": "281f68c3d477904f79ff1cd5807a8c226cd80a50",
 | 
					        "rev": "58820d99352a5e7067ec98374b8c4519c8e225b6",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "yaxitech",
 | 
					        "owner": "devplayer0",
 | 
				
			||||||
 | 
					        "ref": "add-rekey-one-flag",
 | 
				
			||||||
        "repo": "ragenix",
 | 
					        "repo": "ragenix",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -692,7 +826,7 @@
 | 
				
			|||||||
        "borgthin": "borgthin",
 | 
					        "borgthin": "borgthin",
 | 
				
			||||||
        "deploy-rs": "deploy-rs",
 | 
					        "deploy-rs": "deploy-rs",
 | 
				
			||||||
        "devshell": "devshell_3",
 | 
					        "devshell": "devshell_3",
 | 
				
			||||||
        "flake-utils": "flake-utils_7",
 | 
					        "flake-utils": "flake-utils_8",
 | 
				
			||||||
        "home-manager-stable": "home-manager-stable",
 | 
					        "home-manager-stable": "home-manager-stable",
 | 
				
			||||||
        "home-manager-unstable": "home-manager-unstable",
 | 
					        "home-manager-unstable": "home-manager-unstable",
 | 
				
			||||||
        "impermanence": "impermanence",
 | 
					        "impermanence": "impermanence",
 | 
				
			||||||
@@ -717,11 +851,11 @@
 | 
				
			|||||||
        ]
 | 
					        ]
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1682129965,
 | 
					        "lastModified": 1708740535,
 | 
				
			||||||
        "narHash": "sha256-1KRPIorEL6pLpJR04FwAqqnt4Tzcm4MqD84yhlD+XSk=",
 | 
					        "narHash": "sha256-NCTw235XwSDbeTAtAwg/hOeNOgwYhVq7JjDdbkOgBeA=",
 | 
				
			||||||
        "owner": "oxalica",
 | 
					        "owner": "oxalica",
 | 
				
			||||||
        "repo": "rust-overlay",
 | 
					        "repo": "rust-overlay",
 | 
				
			||||||
        "rev": "2c417c0460b788328220120c698630947547ee83",
 | 
					        "rev": "9b24383d77f598716fa0cbb8b48c97249f5ee1af",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -730,19 +864,40 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "sharry": {
 | 
					    "sbt": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "flake-utils": "flake-utils_10",
 | 
					        "flake-utils": "flake-utils_13",
 | 
				
			||||||
        "nixpkgs": [
 | 
					        "nixpkgs": "nixpkgs_5"
 | 
				
			||||||
          "nixpkgs-unstable"
 | 
					 | 
				
			||||||
        ]
 | 
					 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1687587666,
 | 
					        "lastModified": 1698464090,
 | 
				
			||||||
        "narHash": "sha256-t1VNvdQdDUFTEKTFP2fc7Fb3buQBmP+h9WUeO8b2Bus=",
 | 
					        "narHash": "sha256-Pnej7WZIPomYWg8f/CZ65sfW85IfIUjYhphMMg7/LT0=",
 | 
				
			||||||
 | 
					        "owner": "zaninime",
 | 
				
			||||||
 | 
					        "repo": "sbt-derivation",
 | 
				
			||||||
 | 
					        "rev": "6762cf2c31de50efd9ff905cbcc87239995a4ef9",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "zaninime",
 | 
				
			||||||
 | 
					        "repo": "sbt-derivation",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "sharry": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "devshell-tools": "devshell-tools",
 | 
				
			||||||
 | 
					        "flake-utils": "flake-utils_12",
 | 
				
			||||||
 | 
					        "nixpkgs": [
 | 
				
			||||||
 | 
					          "nixpkgs-unstable"
 | 
				
			||||||
 | 
					        ],
 | 
				
			||||||
 | 
					        "sbt": "sbt"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1720592125,
 | 
				
			||||||
 | 
					        "narHash": "sha256-vR89LefkY8mBPWxDTQ8SNg6Z7/J6Yga80T4kSb6MNdk=",
 | 
				
			||||||
        "owner": "eikek",
 | 
					        "owner": "eikek",
 | 
				
			||||||
        "repo": "sharry",
 | 
					        "repo": "sharry",
 | 
				
			||||||
        "rev": "a9b3371aa6c7b92088b20fd6e479c251a5556b86",
 | 
					        "rev": "604b20517150599cb05dbe178cd35cd10659aa4c",
 | 
				
			||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
@@ -766,6 +921,36 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "systems_10": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "systems_11": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "systems_2": {
 | 
					    "systems_2": {
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1681028828,
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
@@ -806,9 +991,8 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "original": {
 | 
					      "original": {
 | 
				
			||||||
        "owner": "nix-systems",
 | 
					        "id": "systems",
 | 
				
			||||||
        "repo": "default",
 | 
					        "type": "indirect"
 | 
				
			||||||
        "type": "github"
 | 
					 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "systems_5": {
 | 
					    "systems_5": {
 | 
				
			||||||
@@ -841,9 +1025,76 @@
 | 
				
			|||||||
        "type": "github"
 | 
					        "type": "github"
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
 | 
					    "systems_7": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "systems_8": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "systems_9": {
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1681028828,
 | 
				
			||||||
 | 
					        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "nix-systems",
 | 
				
			||||||
 | 
					        "repo": "default",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
 | 
					    "treefmt-nix": {
 | 
				
			||||||
 | 
					      "inputs": {
 | 
				
			||||||
 | 
					        "nixpkgs": [
 | 
				
			||||||
 | 
					          "boardie",
 | 
				
			||||||
 | 
					          "poetry2nix",
 | 
				
			||||||
 | 
					          "nixpkgs"
 | 
				
			||||||
 | 
					        ]
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "locked": {
 | 
				
			||||||
 | 
					        "lastModified": 1718522839,
 | 
				
			||||||
 | 
					        "narHash": "sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls=",
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "treefmt-nix",
 | 
				
			||||||
 | 
					        "rev": "68eb1dc333ce82d0ab0c0357363ea17c31ea1f81",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      },
 | 
				
			||||||
 | 
					      "original": {
 | 
				
			||||||
 | 
					        "owner": "numtide",
 | 
				
			||||||
 | 
					        "repo": "treefmt-nix",
 | 
				
			||||||
 | 
					        "type": "github"
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    },
 | 
				
			||||||
    "utils": {
 | 
					    "utils": {
 | 
				
			||||||
      "inputs": {
 | 
					      "inputs": {
 | 
				
			||||||
        "systems": "systems_3"
 | 
					        "systems": "systems_5"
 | 
				
			||||||
      },
 | 
					      },
 | 
				
			||||||
      "locked": {
 | 
					      "locked": {
 | 
				
			||||||
        "lastModified": 1701680307,
 | 
					        "lastModified": 1701680307,
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										19
									
								
								flake.nix
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								flake.nix
									
									
									
									
									
								
							@@ -17,14 +17,15 @@
 | 
				
			|||||||
    home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
 | 
					    home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Stuff used by the flake for build / deployment
 | 
					    # 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";
 | 
					    ragenix.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
				
			||||||
    deploy-rs.url = "github:serokell/deploy-rs";
 | 
					    deploy-rs.url = "github:serokell/deploy-rs";
 | 
				
			||||||
    deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
					    deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Stuff used by systems
 | 
					    # Stuff used by systems
 | 
				
			||||||
    impermanence.url = "github:nix-community/impermanence";
 | 
					    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";
 | 
					    boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
				
			||||||
    nixGL.url = "github:nix-community/nixGL";
 | 
					    nixGL.url = "github:nix-community/nixGL";
 | 
				
			||||||
    nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
					    nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
				
			||||||
@@ -51,7 +52,7 @@
 | 
				
			|||||||
      ...
 | 
					      ...
 | 
				
			||||||
    }:
 | 
					    }:
 | 
				
			||||||
    let
 | 
					    let
 | 
				
			||||||
      inherit (builtins) mapAttrs replaceStrings;
 | 
					      inherit (builtins) mapAttrs replaceStrings elem;
 | 
				
			||||||
      inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules;
 | 
					      inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules;
 | 
				
			||||||
      inherit (lib.flake) flattenTree eachDefaultSystem;
 | 
					      inherit (lib.flake) flattenTree eachDefaultSystem;
 | 
				
			||||||
      inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay;
 | 
					      inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay;
 | 
				
			||||||
@@ -107,6 +108,16 @@
 | 
				
			|||||||
            pkgsLibOverlay
 | 
					            pkgsLibOverlay
 | 
				
			||||||
            myPkgsOverlay
 | 
					            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;
 | 
					        pkgsFlakes;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -115,9 +126,9 @@
 | 
				
			|||||||
        nixos/installer.nix
 | 
					        nixos/installer.nix
 | 
				
			||||||
        nixos/boxes/colony
 | 
					        nixos/boxes/colony
 | 
				
			||||||
        nixos/boxes/tower
 | 
					        nixos/boxes/tower
 | 
				
			||||||
        nixos/boxes/castle
 | 
					 | 
				
			||||||
        nixos/boxes/home/stream.nix
 | 
					        nixos/boxes/home/stream.nix
 | 
				
			||||||
        nixos/boxes/home/palace
 | 
					        nixos/boxes/home/palace
 | 
				
			||||||
 | 
					        nixos/boxes/home/castle
 | 
				
			||||||
        nixos/boxes/britway
 | 
					        nixos/boxes/britway
 | 
				
			||||||
        nixos/boxes/kelder
 | 
					        nixos/boxes/kelder
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -199,17 +199,20 @@ in
 | 
				
			|||||||
          file
 | 
					          file
 | 
				
			||||||
          tree
 | 
					          tree
 | 
				
			||||||
          pwgen
 | 
					          pwgen
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          minicom
 | 
				
			||||||
          iperf3
 | 
					          iperf3
 | 
				
			||||||
          mosh
 | 
					          mosh
 | 
				
			||||||
          wget
 | 
					          wget
 | 
				
			||||||
          hyx
 | 
					 | 
				
			||||||
          whois
 | 
					          whois
 | 
				
			||||||
          ldns
 | 
					          ldns
 | 
				
			||||||
          minicom
 | 
					 | 
				
			||||||
          mtr
 | 
					          mtr
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          hyx
 | 
				
			||||||
          ncdu
 | 
					          ncdu
 | 
				
			||||||
          jq
 | 
					          jq
 | 
				
			||||||
          yq-go
 | 
					          yq-go
 | 
				
			||||||
 | 
					          nix-tree
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        sessionVariables = {
 | 
					        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,4 +1,4 @@
 | 
				
			|||||||
{ lib, pkgs, config, ... }:
 | 
					{ lib, pkgs', pkgs, config, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib) genAttrs mkIf mkMerge mkForce;
 | 
					  inherit (lib) genAttrs mkIf mkMerge mkForce;
 | 
				
			||||||
  inherit (lib.my) mkBoolOpt';
 | 
					  inherit (lib.my) mkBoolOpt';
 | 
				
			||||||
@@ -10,6 +10,23 @@ let
 | 
				
			|||||||
    name = "Monocraft";
 | 
					    name = "Monocraft";
 | 
				
			||||||
    size = 10;
 | 
					    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
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  options.my.gui = {
 | 
					  options.my.gui = {
 | 
				
			||||||
@@ -22,6 +39,8 @@ in
 | 
				
			|||||||
      {
 | 
					      {
 | 
				
			||||||
        home = {
 | 
					        home = {
 | 
				
			||||||
          packages = with pkgs; [
 | 
					          packages = with pkgs; [
 | 
				
			||||||
 | 
					            xdg-utils
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            font.package
 | 
					            font.package
 | 
				
			||||||
            (nerdfonts.override {
 | 
					            (nerdfonts.override {
 | 
				
			||||||
              fonts = [ "DroidSansMono" "SourceCodePro" ];
 | 
					              fonts = [ "DroidSansMono" "SourceCodePro" ];
 | 
				
			||||||
@@ -32,11 +51,21 @@ in
 | 
				
			|||||||
            slurp
 | 
					            slurp
 | 
				
			||||||
            swappy
 | 
					            swappy
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            python310Packages.python-lsp-server
 | 
					            python3Packages.python-lsp-server
 | 
				
			||||||
            nil # nix language server
 | 
					            nil # nix language server
 | 
				
			||||||
            zls # zig language server
 | 
					            zls # zig language server
 | 
				
			||||||
            rust-analyzer
 | 
					            rust-analyzer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            cowsay
 | 
				
			||||||
 | 
					            fortune
 | 
				
			||||||
 | 
					            jp2a
 | 
				
			||||||
 | 
					            terminaltexteffects
 | 
				
			||||||
 | 
					            screenfetch
 | 
				
			||||||
            neofetch
 | 
					            neofetch
 | 
				
			||||||
 | 
					            cmatrix
 | 
				
			||||||
 | 
					            doomsaver
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            xournalpp
 | 
				
			||||||
          ];
 | 
					          ];
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -51,7 +80,15 @@ in
 | 
				
			|||||||
          alacritty = {
 | 
					          alacritty = {
 | 
				
			||||||
            enable = true;
 | 
					            enable = true;
 | 
				
			||||||
            settings = {
 | 
					            settings = {
 | 
				
			||||||
              font.normal.family = font.name;
 | 
					              import = [ ./alacritty-xterm.toml ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              font = {
 | 
				
			||||||
 | 
					                size = font.size;
 | 
				
			||||||
 | 
					                normal = {
 | 
				
			||||||
 | 
					                  family = font.name;
 | 
				
			||||||
 | 
					                  style = "Regular";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,9 +96,29 @@ in
 | 
				
			|||||||
            enable = true;
 | 
					            enable = true;
 | 
				
			||||||
            inherit font;
 | 
					            inherit font;
 | 
				
			||||||
            settings = {
 | 
					            settings = {
 | 
				
			||||||
              background_opacity = "0.8";
 | 
					              background_opacity = "0.65";
 | 
				
			||||||
              tab_bar_edge = "top";
 | 
					              tab_bar_edge = "top";
 | 
				
			||||||
              shell_integration = "no-sudo";
 | 
					              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 +165,19 @@ in
 | 
				
			|||||||
              };
 | 
					              };
 | 
				
			||||||
              Install.RequiredBy = [ "sway-session.target" ];
 | 
					              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" ];
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -126,10 +196,11 @@ in
 | 
				
			|||||||
          ];
 | 
					          ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          pointerCursor = {
 | 
					          pointerCursor = {
 | 
				
			||||||
            package = pkgs.vanilla-dmz;
 | 
					            package = pkgs.posy-cursors;
 | 
				
			||||||
            name = "Vanilla-DMZ";
 | 
					            name = "Posy_Cursor";
 | 
				
			||||||
            size = 16;
 | 
					            size = 32;
 | 
				
			||||||
            gtk.enable = true;
 | 
					            gtk.enable = true;
 | 
				
			||||||
 | 
					            x11.enable = true;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -162,7 +233,7 @@ in
 | 
				
			|||||||
                  in
 | 
					                  in
 | 
				
			||||||
                  lib.mkOptionDefault {
 | 
					                  lib.mkOptionDefault {
 | 
				
			||||||
                    "${mod}+d" = null;
 | 
					                    "${mod}+d" = null;
 | 
				
			||||||
                    "${mod}+l" = "exec swaylock -i ${./lock.png} -s stretch";
 | 
					                    "${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
 | 
				
			||||||
                    "${mod}+x" = "exec ${cfg.menu}";
 | 
					                    "${mod}+x" = "exec ${cfg.menu}";
 | 
				
			||||||
                    "${mod}+Shift+x" = "exec rofi -show drun";
 | 
					                    "${mod}+Shift+x" = "exec rofi -show drun";
 | 
				
			||||||
                    "${mod}+q" = "kill";
 | 
					                    "${mod}+q" = "kill";
 | 
				
			||||||
@@ -210,17 +281,10 @@ in
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        qt = {
 | 
					        qt = {
 | 
				
			||||||
          enable = true;
 | 
					          enable = true;
 | 
				
			||||||
          platformTheme = "gtk";
 | 
					          platformTheme.name = "gtk";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        services = {
 | 
					        services = {
 | 
				
			||||||
          swaync = {
 | 
					 | 
				
			||||||
            enable = true;
 | 
					 | 
				
			||||||
            settings = {
 | 
					 | 
				
			||||||
              widgets = [ "title" "dnd" "mpris" "notifications" ];
 | 
					 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
          playerctld.enable = true;
 | 
					          playerctld.enable = true;
 | 
				
			||||||
          spotifyd = {
 | 
					          spotifyd = {
 | 
				
			||||||
            enable = false;
 | 
					            enable = false;
 | 
				
			||||||
@@ -245,6 +309,7 @@ in
 | 
				
			|||||||
            diff-so-fancy.enable = true;
 | 
					            diff-so-fancy.enable = true;
 | 
				
			||||||
            userEmail = "jackos1998@gmail.com";
 | 
					            userEmail = "jackos1998@gmail.com";
 | 
				
			||||||
            userName = "Jack O'Sullivan";
 | 
					            userName = "Jack O'Sullivan";
 | 
				
			||||||
 | 
					            lfs.enable = true;
 | 
				
			||||||
            extraConfig = {
 | 
					            extraConfig = {
 | 
				
			||||||
              pull.rebase = true;
 | 
					              pull.rebase = true;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
@@ -252,12 +317,13 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          waybar = import ./waybar.nix { inherit lib pkgs config font; };
 | 
					          waybar = import ./waybar.nix { inherit lib pkgs config font; };
 | 
				
			||||||
          rofi = {
 | 
					          rofi = {
 | 
				
			||||||
 | 
					            package = pkgs.rofi-wayland;
 | 
				
			||||||
            enable = true;
 | 
					            enable = true;
 | 
				
			||||||
            font = "${font.name} ${toString font.size}";
 | 
					            font = "${font.name} ${toString font.size}";
 | 
				
			||||||
            plugins = with pkgs; [
 | 
					            plugins = with pkgs; (map (p: p.override { rofi-unwrapped = rofi-wayland-unwrapped; }) [
 | 
				
			||||||
              rofi-calc
 | 
					              rofi-calc
 | 
				
			||||||
              rofi-emoji
 | 
					              rofi-emoji
 | 
				
			||||||
            ];
 | 
					            ]);
 | 
				
			||||||
            extraConfig = {
 | 
					            extraConfig = {
 | 
				
			||||||
              modes = "window,run,ssh,filebrowser,calc,emoji";
 | 
					              modes = "window,run,ssh,filebrowser,calc,emoji";
 | 
				
			||||||
              emoji-mode = "copy";
 | 
					              emoji-mode = "copy";
 | 
				
			||||||
@@ -271,7 +337,7 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          chromium = {
 | 
					          chromium = {
 | 
				
			||||||
            enable = true;
 | 
					            enable = true;
 | 
				
			||||||
            package = (pkgs.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
 | 
					            package = (pkgs'.unstable.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
 | 
				
			||||||
              buildCommand = ''
 | 
					              buildCommand = ''
 | 
				
			||||||
                ${old.buildCommand}
 | 
					                ${old.buildCommand}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -297,6 +363,15 @@ in
 | 
				
			|||||||
            ] (_: "chromium-browser.desktop");
 | 
					            ] (_: "chromium-browser.desktop");
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        my = {
 | 
				
			||||||
 | 
					          swaync = {
 | 
				
			||||||
 | 
					            enable = true;
 | 
				
			||||||
 | 
					            settings = {
 | 
				
			||||||
 | 
					              widgets = [ "title" "dnd" "mpris" "notifications" ];
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      (mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) {
 | 
					      (mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										
											BIN
										
									
								
								home-manager/modules/gui/enojy.jpg
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										
											BIN
										
									
								
								home-manager/modules/gui/enojy.jpg
									
									
									
									
									
										Normal file
									
								
							
										
											Binary file not shown.
										
									
								
							| 
		 After Width: | Height: | Size: 7.4 KiB  | 
							
								
								
									
										209
									
								
								home-manager/modules/gui/screensaver.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										209
									
								
								home-manager/modules/gui/screensaver.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,209 @@
 | 
				
			|||||||
 | 
					#!@python@/bin/python
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import random
 | 
				
			||||||
 | 
					import signal
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import filelock
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class Screensaver:
 | 
				
			||||||
 | 
					    def __init__(self, cmd, env=None, weight=1):
 | 
				
			||||||
 | 
					        self.cmd = cmd
 | 
				
			||||||
 | 
					        self.weight = weight
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if env is not None:
 | 
				
			||||||
 | 
					            self.env = os.environ.copy()
 | 
				
			||||||
 | 
					            for k, v in env.items():
 | 
				
			||||||
 | 
					                self.env[k] = v
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.env = None
 | 
				
			||||||
 | 
					        self.proc = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self):
 | 
				
			||||||
 | 
					        assert self.proc is None
 | 
				
			||||||
 | 
					        self.proc = subprocess.Popen(self.cmd, env=self.env)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def wait(self):
 | 
				
			||||||
 | 
					        assert self.proc is not None
 | 
				
			||||||
 | 
					        self.proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stop(self, kill=False):
 | 
				
			||||||
 | 
					        assert self.proc is not None
 | 
				
			||||||
 | 
					        if kill:
 | 
				
			||||||
 | 
					            self.proc.kill()
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.proc.terminate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class DoomSaver(Screensaver):
 | 
				
			||||||
 | 
					    wad = '@doomWad@'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, demo_index, weight=1.5):
 | 
				
			||||||
 | 
					        super().__init__(
 | 
				
			||||||
 | 
					            ['@chocoDoom@/bin/chocolate-doom',
 | 
				
			||||||
 | 
					             '-iwad', self.wad,
 | 
				
			||||||
 | 
					             '-demoloopi', str(demo_index)],
 | 
				
			||||||
 | 
					            env={
 | 
				
			||||||
 | 
					                'SDL_AUDIODRIVER': 'null',
 | 
				
			||||||
 | 
					                'SDL_VIDEODRIVER': 'caca',
 | 
				
			||||||
 | 
					                'CACA_DRIVER': 'ncurses',
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					            weight=weight,
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stop(self):
 | 
				
			||||||
 | 
					        super().stop(kill=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class TTESaver(Screensaver):
 | 
				
			||||||
 | 
					    effects = (
 | 
				
			||||||
 | 
					        'beams,binarypath,blackhole,bouncyballs,bubbles,burn,colorshift,crumble,'
 | 
				
			||||||
 | 
					        'decrypt,errorcorrect,expand,fireworks,middleout,orbittingvolley,overflow,'
 | 
				
			||||||
 | 
					        'pour,print,rain,randomsequence,rings,scattered,slice,slide,spotlights,'
 | 
				
			||||||
 | 
					        'spray,swarm,synthgrid,unstable,vhstape,waves,wipe'
 | 
				
			||||||
 | 
					    ).split(',')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, cmd, env=None, weight=1):
 | 
				
			||||||
 | 
					        super().__init__(cmd, env=env, weight=weight)
 | 
				
			||||||
 | 
					        self.running = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def start(self):
 | 
				
			||||||
 | 
					        self.running = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def wait(self):
 | 
				
			||||||
 | 
					        while self.running:
 | 
				
			||||||
 | 
					            effect_cmd = ['tte', random.choice(self.effects)]
 | 
				
			||||||
 | 
					            print(f"$ {self.cmd} | {' '.join(effect_cmd)}")
 | 
				
			||||||
 | 
					            content = subprocess.check_output(self.cmd, shell=True, env=self.env, stderr=subprocess.DEVNULL)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            self.proc = subprocess.Popen(effect_cmd, stdin=subprocess.PIPE)
 | 
				
			||||||
 | 
					            self.proc.stdin.write(content)
 | 
				
			||||||
 | 
					            self.proc.stdin.close()
 | 
				
			||||||
 | 
					            self.proc.wait()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stop(self):
 | 
				
			||||||
 | 
					        self.running = False
 | 
				
			||||||
 | 
					        self.proc.terminate()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class MultiSaver:
 | 
				
			||||||
 | 
					    savers = [
 | 
				
			||||||
 | 
					        DoomSaver(0),
 | 
				
			||||||
 | 
					        DoomSaver(1),
 | 
				
			||||||
 | 
					        DoomSaver(2),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        Screensaver(['cmatrix']),
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        TTESaver('screenfetch -N'),
 | 
				
			||||||
 | 
					        TTESaver('fortune | cowsay'),
 | 
				
			||||||
 | 
					        TTESaver('top -bn1 | head -n50'),
 | 
				
			||||||
 | 
					        TTESaver('ss -nltu'),
 | 
				
			||||||
 | 
					        TTESaver('ss -ntu'),
 | 
				
			||||||
 | 
					        TTESaver('jp2a --width=100 @enojy@'),
 | 
				
			||||||
 | 
					    ]
 | 
				
			||||||
 | 
					    state_filename = 'screensaver.json'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def __init__(self, select=None):
 | 
				
			||||||
 | 
					        self.state_path = os.path.join(f'/run/user/{os.geteuid()}', self.state_filename)
 | 
				
			||||||
 | 
					        self.lock = filelock.FileLock(f'{self.state_path}.lock')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        if select is not None:
 | 
				
			||||||
 | 
					            assert select >= 0 and select < len(self.savers), 'Invalid screensaver index'
 | 
				
			||||||
 | 
					            self.selected = self.savers[select]
 | 
				
			||||||
 | 
					        else:
 | 
				
			||||||
 | 
					            self.selected = None
 | 
				
			||||||
 | 
					        self.cleaned_up = False
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def select(self):
 | 
				
			||||||
 | 
					        with self.lock:
 | 
				
			||||||
 | 
					            if not os.path.exists(self.state_path):
 | 
				
			||||||
 | 
					                state = {'instances': []}
 | 
				
			||||||
 | 
					            else:
 | 
				
			||||||
 | 
					                with open(self.state_path) as f:
 | 
				
			||||||
 | 
					                    state = json.load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            if self.selected is None:
 | 
				
			||||||
 | 
					                available = set(range(len(self.savers)))
 | 
				
			||||||
 | 
					                new_instances = []
 | 
				
			||||||
 | 
					                for instance in state['instances']:
 | 
				
			||||||
 | 
					                    if not os.path.exists(f"/proc/{instance['pid']}"):
 | 
				
			||||||
 | 
					                        continue
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    new_instances.append(instance)
 | 
				
			||||||
 | 
					                    i = instance['saver']
 | 
				
			||||||
 | 
					                    assert i in available
 | 
				
			||||||
 | 
					                    available.remove(i)
 | 
				
			||||||
 | 
					                assert available, 'No screensavers left'
 | 
				
			||||||
 | 
					                available = list(available)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                weights = []
 | 
				
			||||||
 | 
					                for i in available:
 | 
				
			||||||
 | 
					                    weights.append(self.savers[i].weight)
 | 
				
			||||||
 | 
					                selected_i = random.choices(available, weights=weights)[0]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                new_instances.append({'pid': os.getpid(), 'saver': selected_i})
 | 
				
			||||||
 | 
					                state['instances'] = new_instances
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                # print(f'Selected saver {selected_i}')
 | 
				
			||||||
 | 
					                self.selected = self.savers[selected_i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            with open(self.state_path, 'w') as f:
 | 
				
			||||||
 | 
					                json.dump(state, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def cleanup(self):
 | 
				
			||||||
 | 
					        if self.cleaned_up:
 | 
				
			||||||
 | 
					            return
 | 
				
			||||||
 | 
					        self.cleaned_up = True
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        with self.lock:
 | 
				
			||||||
 | 
					            with open(self.state_path) as f:
 | 
				
			||||||
 | 
					                state = json.load(f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            for i, instance in enumerate(state['instances']):
 | 
				
			||||||
 | 
					                if instance['pid'] == os.getpid():
 | 
				
			||||||
 | 
					                    del state['instances'][i]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            with open(self.state_path, 'w') as f:
 | 
				
			||||||
 | 
					                json.dump(state, f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def run(self):
 | 
				
			||||||
 | 
					        assert self.selected is not None
 | 
				
			||||||
 | 
					        self.selected.start()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        signal.signal(signal.SIGINT, self._sighandler)
 | 
				
			||||||
 | 
					        signal.signal(signal.SIGTERM, self._sighandler)
 | 
				
			||||||
 | 
					        signal.signal(signal.SIGHUP, self._sighandler)
 | 
				
			||||||
 | 
					        self.selected.wait()
 | 
				
			||||||
 | 
					        self.cleanup()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def stop(self):
 | 
				
			||||||
 | 
					        assert self.selected is not None
 | 
				
			||||||
 | 
					        print('Shutting down')
 | 
				
			||||||
 | 
					        self.selected.stop()
 | 
				
			||||||
 | 
					        self.cleanup()
 | 
				
			||||||
 | 
					    def _sighandler(self, signum, frame):
 | 
				
			||||||
 | 
					        self.stop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main():
 | 
				
			||||||
 | 
					    parser = argparse.ArgumentParser(description='Wayland terminal-based lock screen')
 | 
				
			||||||
 | 
					    parser.add_argument('-l', '--locker-cmd', default='swaylock-plugin', help='swaylock-plugin command to use')
 | 
				
			||||||
 | 
					    parser.add_argument('-t', '--terminal', default='alacritty', help='Terminal emulator to use')
 | 
				
			||||||
 | 
					    parser.add_argument('-i', '--instance', action='store_true', help='Run as instance')
 | 
				
			||||||
 | 
					    parser.add_argument('-s', '--screensaver', type=int, help='Force use of specific screensaver')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    args = parser.parse_args()
 | 
				
			||||||
 | 
					    if not args.instance:
 | 
				
			||||||
 | 
					        cmd = [
 | 
				
			||||||
 | 
					            args.locker_cmd, '--command-each',
 | 
				
			||||||
 | 
					            f'@windowtolayer@/bin/windowtolayer -- {args.terminal} -e {sys.argv[0]} --instance']
 | 
				
			||||||
 | 
					        if args.screensaver is not None:
 | 
				
			||||||
 | 
					            cmd[-1] += f' --screensaver {args.screensaver}'
 | 
				
			||||||
 | 
					        subprocess.check_call(cmd)
 | 
				
			||||||
 | 
					        return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ms = MultiSaver(select=args.screensaver)
 | 
				
			||||||
 | 
					    ms.select()
 | 
				
			||||||
 | 
					    ms.run()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					    main()
 | 
				
			||||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 249 KiB After Width: | Height: | Size: 251 KiB  | 
@@ -146,9 +146,9 @@ in
 | 
				
			|||||||
          dnd-none = "";
 | 
					          dnd-none = "";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        return-type = "json";
 | 
					        return-type = "json";
 | 
				
			||||||
        exec = "${config.services.swaync.package}/bin/swaync-client -swb";
 | 
					        exec = "${config.my.swaync.package}/bin/swaync-client -swb";
 | 
				
			||||||
        on-click = "${config.services.swaync.package}/bin/swaync-client -t -sw";
 | 
					        on-click = "${config.my.swaync.package}/bin/swaync-client -t -sw";
 | 
				
			||||||
        on-click-right = "${config.services.swaync.package}/bin/swaync-client -d -sw";
 | 
					        on-click-right = "${config.my.swaync.package}/bin/swaync-client -d -sw";
 | 
				
			||||||
        escape = true;
 | 
					        escape = true;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -19,10 +19,10 @@ let
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cfg = config.services.swaync;
 | 
					  cfg = config.my.swaync;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  options.services.swaync = with lib.types; {
 | 
					  options.my.swaync = with lib.types; {
 | 
				
			||||||
    enable = mkEnableOption "Sway Notification Center";
 | 
					    enable = mkEnableOption "Sway Notification Center";
 | 
				
			||||||
    package = mkOption {
 | 
					    package = mkOption {
 | 
				
			||||||
      type = package;
 | 
					      type = package;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -11,6 +11,8 @@ rec {
 | 
				
			|||||||
      jellyseerr = 402;
 | 
					      jellyseerr = 402;
 | 
				
			||||||
      atticd = 403;
 | 
					      atticd = 403;
 | 
				
			||||||
      kea = 404;
 | 
					      kea = 404;
 | 
				
			||||||
 | 
					      keepalived_script = 405;
 | 
				
			||||||
 | 
					      photoprism = 406;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
    gids = {
 | 
					    gids = {
 | 
				
			||||||
      matrix-syncv3 = 400;
 | 
					      matrix-syncv3 = 400;
 | 
				
			||||||
@@ -18,12 +20,14 @@ rec {
 | 
				
			|||||||
      jellyseerr = 402;
 | 
					      jellyseerr = 402;
 | 
				
			||||||
      atticd = 403;
 | 
					      atticd = 403;
 | 
				
			||||||
      kea = 404;
 | 
					      kea = 404;
 | 
				
			||||||
 | 
					      keepalived_script = 405;
 | 
				
			||||||
 | 
					      photoprism = 406;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  kernel = {
 | 
					  kernel = {
 | 
				
			||||||
    lts = pkgs: pkgs.linuxKernel.packages.linux_6_1;
 | 
					    lts = pkgs: pkgs.linuxKernel.packages.linux_6_6;
 | 
				
			||||||
    latest = pkgs: pkgs.linuxKernel.packages.linux_6_6;
 | 
					    latest = pkgs: pkgs.linuxKernel.packages.linux_6_9;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  nginx = rec {
 | 
					  nginx = rec {
 | 
				
			||||||
@@ -94,10 +98,10 @@ rec {
 | 
				
			|||||||
  nix = {
 | 
					  nix = {
 | 
				
			||||||
    cache = rec {
 | 
					    cache = rec {
 | 
				
			||||||
      substituters = [
 | 
					      substituters = [
 | 
				
			||||||
        "https://nix-cache.${pubDomain}/main"
 | 
					        "https://nix-cache.${pubDomain}"
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      keys = [
 | 
					      keys = [
 | 
				
			||||||
        "main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8="
 | 
					        "nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4="
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      conf = ''
 | 
					      conf = ''
 | 
				
			||||||
        extra-substituters = ${concatStringsSep " " substituters}
 | 
					        extra-substituters = ${concatStringsSep " " substituters}
 | 
				
			||||||
@@ -107,7 +111,7 @@ rec {
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  pubDomain = "nul.ie";
 | 
					  pubDomain = "nul.ie";
 | 
				
			||||||
  colony = {
 | 
					  colony = rec {
 | 
				
			||||||
    domain = "ams1.int.${pubDomain}";
 | 
					    domain = "ams1.int.${pubDomain}";
 | 
				
			||||||
    pubV4 = "94.142.240.44";
 | 
					    pubV4 = "94.142.240.44";
 | 
				
			||||||
    prefixes = with lib.my.net.cidr; rec {
 | 
					    prefixes = with lib.my.net.cidr; rec {
 | 
				
			||||||
@@ -131,6 +135,9 @@ rec {
 | 
				
			|||||||
        v4 = subnet 8 3 all.v4;
 | 
					        v4 = subnet 8 3 all.v4;
 | 
				
			||||||
        v6 = subnet 4 3 all.v6;
 | 
					        v6 = subnet 4 3 all.v6;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					      qclk = {
 | 
				
			||||||
 | 
					        v4 = subnet 8 4 all.v4;
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      cust = {
 | 
					      cust = {
 | 
				
			||||||
        v4 = subnet 8 100 all.v4; # single ip for routing only
 | 
					        v4 = subnet 8 100 all.v4; # single ip for routing only
 | 
				
			||||||
@@ -144,6 +151,10 @@ rec {
 | 
				
			|||||||
        v4 = "94.142.242.255/32";
 | 
					        v4 = "94.142.242.255/32";
 | 
				
			||||||
        v6 = subnet 8 1 cust.v6;
 | 
					        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";
 | 
					      vip1 = "94.142.241.224/30";
 | 
				
			||||||
      vip2 = "94.142.242.254/31";
 | 
					      vip2 = "94.142.242.254/31";
 | 
				
			||||||
@@ -156,6 +167,16 @@ rec {
 | 
				
			|||||||
      home.v6 = "2a0e:97c0:4d0::/48";
 | 
					      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: [
 | 
					    firewallForwards = aa: [
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        port = "http";
 | 
					        port = "http";
 | 
				
			||||||
@@ -169,6 +190,7 @@ rec {
 | 
				
			|||||||
        port = 8448;
 | 
					        port = 8448;
 | 
				
			||||||
        dst = aa.middleman.internal.ipv4.address;
 | 
					        dst = aa.middleman.internal.ipv4.address;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        port = 25565;
 | 
					        port = 25565;
 | 
				
			||||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
					        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
				
			||||||
@@ -177,6 +199,7 @@ rec {
 | 
				
			|||||||
        port = 25566;
 | 
					        port = 25566;
 | 
				
			||||||
        dst = aa.simpcraft-staging-oci.internal.ipv4.address;
 | 
					        dst = aa.simpcraft-staging-oci.internal.ipv4.address;
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        port = 25575;
 | 
					        port = 25575;
 | 
				
			||||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
					        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
				
			||||||
@@ -204,6 +227,12 @@ rec {
 | 
				
			|||||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
					        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
				
			||||||
        proto = "udp";
 | 
					        proto = "udp";
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        port = qclk.wgPort;
 | 
				
			||||||
 | 
					        dst = aa.qclk.internal.ipv4.address;
 | 
				
			||||||
 | 
					        proto = "udp";
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    fstrimConfig = {
 | 
					    fstrimConfig = {
 | 
				
			||||||
@@ -227,7 +256,7 @@ rec {
 | 
				
			|||||||
      "stream"
 | 
					      "stream"
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    routersPubV4 = [
 | 
					    routersPubV4 = [
 | 
				
			||||||
      "109.255.1.246"
 | 
					      "80.111.122.16"
 | 
				
			||||||
      "109.255.252.63"
 | 
					      "109.255.252.63"
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -277,6 +306,8 @@ rec {
 | 
				
			|||||||
        v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6;
 | 
					        v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    roceBootModules = [ "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" ];
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  britway = {
 | 
					  britway = {
 | 
				
			||||||
@@ -327,6 +358,7 @@ rec {
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    domain = "hentai.engineer";
 | 
					    domain = "hentai.engineer";
 | 
				
			||||||
 | 
					    ipv4MTU = 1460;
 | 
				
			||||||
    vpn = {
 | 
					    vpn = {
 | 
				
			||||||
      port = 51820;
 | 
					      port = 51820;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -340,6 +372,7 @@ rec {
 | 
				
			|||||||
    deploy = ../.keys/deploy.pub;
 | 
					    deploy = ../.keys/deploy.pub;
 | 
				
			||||||
    rsyncNet = ../.keys/zh2855.rsync.net.pub;
 | 
					    rsyncNet = ../.keys/zh2855.rsync.net.pub;
 | 
				
			||||||
    mailcowAcme = ../.keys/mailcow-acme.pub;
 | 
					    mailcowAcme = ../.keys/mailcow-acme.pub;
 | 
				
			||||||
 | 
					    harmonia = ../.keys/harmonia.pub;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
  sshHostKeys = {
 | 
					  sshHostKeys = {
 | 
				
			||||||
    mail-vm = ../.keys/mail-vm-host.pub;
 | 
					    mail-vm = ../.keys/mail-vm-host.pub;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -5,7 +5,7 @@ let
 | 
				
			|||||||
    genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types
 | 
					    genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types
 | 
				
			||||||
    mkOption mkOverride mkForce mkIf mergeEqualOption optional
 | 
					    mkOption mkOverride mkForce mkIf mergeEqualOption optional
 | 
				
			||||||
    showWarnings concatStringsSep flatten unique optionalAttrs
 | 
					    showWarnings concatStringsSep flatten unique optionalAttrs
 | 
				
			||||||
    mkBefore;
 | 
					    mkBefore toLower;
 | 
				
			||||||
  inherit (lib.flake) defaultSystems;
 | 
					  inherit (lib.flake) defaultSystems;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
rec {
 | 
					rec {
 | 
				
			||||||
@@ -248,10 +248,37 @@ rec {
 | 
				
			|||||||
  in
 | 
					  in
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
    trivial = prev.trivial // {
 | 
					    trivial = prev.trivial // {
 | 
				
			||||||
      release = "23.12:u-${prev.trivial.release}";
 | 
					      release = "24.07:u-${prev.trivial.release}";
 | 
				
			||||||
      codeName = "Amogus";
 | 
					      codeName = "Diffed";
 | 
				
			||||||
      revisionWithDefault = default: self.rev or default;
 | 
					      revisionWithDefault = default: self.rev or default;
 | 
				
			||||||
      versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}";
 | 
					      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";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,27 +1,24 @@
 | 
				
			|||||||
{ lib, pkgs, config, assignments, allAssignments, ... }:
 | 
					{ lib, pkgs, config, assignments, allAssignments, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib) concatStringsSep;
 | 
					 | 
				
			||||||
  inherit (lib.my.c) pubDomain;
 | 
					  inherit (lib.my.c) pubDomain;
 | 
				
			||||||
  inherit (lib.my.c.britway) prefixes domain;
 | 
					  inherit (lib.my.c.britway) prefixes domain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  # Can't use overrideAttrs because we need to override `vendorHash` within `buildGoModule`
 | 
					  # 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 {
 | 
					    buildGoModule = args: pkgs.buildGoModule (args // rec {
 | 
				
			||||||
      version = "0.23.0-alpha2";
 | 
					      version = "0.23.0-alpha12";
 | 
				
			||||||
      src = pkgs.fetchFromGitHub {
 | 
					      src = pkgs.fetchFromGitHub {
 | 
				
			||||||
        owner = "juanfont";
 | 
					        owner = "juanfont";
 | 
				
			||||||
        repo = "headscale";
 | 
					        repo = "headscale";
 | 
				
			||||||
        rev = "v${version}";
 | 
					        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
 | 
					 | 
				
			||||||
    lib.my.c.home.prefixes.all.v6
 | 
					 | 
				
			||||||
  ];
 | 
					 | 
				
			||||||
  pubNameservers = [
 | 
					  pubNameservers = [
 | 
				
			||||||
    "1.1.1.1"
 | 
					    "1.1.1.1"
 | 
				
			||||||
    "1.0.0.1"
 | 
					    "1.0.0.1"
 | 
				
			||||||
@@ -44,10 +41,12 @@ in
 | 
				
			|||||||
          disable_check_updates = true;
 | 
					          disable_check_updates = true;
 | 
				
			||||||
          unix_socket_permission = "0770";
 | 
					          unix_socket_permission = "0770";
 | 
				
			||||||
          server_url = "https://ts.${pubDomain}";
 | 
					          server_url = "https://ts.${pubDomain}";
 | 
				
			||||||
          db_type = "sqlite3";
 | 
					          database = {
 | 
				
			||||||
          db_path = "/var/lib/headscale/db.sqlite3";
 | 
					            type = "sqlite3";
 | 
				
			||||||
 | 
					            sqlite.path = "/var/lib/headscale/db.sqlite3";
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
          noise.private_key_path = "/var/lib/headscale/noise_private.key";
 | 
					          noise.private_key_path = "/var/lib/headscale/noise_private.key";
 | 
				
			||||||
          ip_prefixes = with lib.my.c.tailscale.prefix; [ v4 v6 ];
 | 
					          prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; };
 | 
				
			||||||
          dns_config = {
 | 
					          dns_config = {
 | 
				
			||||||
            # Use IPs that will route inside the VPN to prevent interception
 | 
					            # Use IPs that will route inside the VPN to prevent interception
 | 
				
			||||||
            # (e.g. DNS rebinding filtering)
 | 
					            # (e.g. DNS rebinding filtering)
 | 
				
			||||||
@@ -88,7 +87,6 @@ in
 | 
				
			|||||||
          "--login-server=https://ts.nul.ie"
 | 
					          "--login-server=https://ts.nul.ie"
 | 
				
			||||||
          "--netfilter-mode=off"
 | 
					          "--netfilter-mode=off"
 | 
				
			||||||
          "--advertise-exit-node"
 | 
					          "--advertise-exit-node"
 | 
				
			||||||
          "--advertise-routes=${advRoutes}"
 | 
					 | 
				
			||||||
          "--accept-routes=false"
 | 
					          "--accept-routes=false"
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{ lib, ... }:
 | 
					{ lib, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
  inherit (lib.my.c.colony) domain prefixes firewallForwards;
 | 
					  inherit (lib.my.c.colony) domain prefixes custRouting firewallForwards;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  imports = [ ./vms ];
 | 
					  imports = [ ./vms ];
 | 
				
			||||||
@@ -60,8 +60,8 @@ in
 | 
				
			|||||||
          kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
 | 
					          kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
 | 
				
			||||||
            kernel = super.kernel.override {
 | 
					            kernel = super.kernel.override {
 | 
				
			||||||
              structuredExtraConfig = with lib.kernel; {
 | 
					              structuredExtraConfig = with lib.kernel; {
 | 
				
			||||||
                #SOME_OPT = yes;
 | 
					                ACPI_APEI_PCIEAER = yes;
 | 
				
			||||||
                #A_MOD = module;
 | 
					                PCIEAER = yes;
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          });
 | 
					          });
 | 
				
			||||||
@@ -150,12 +150,12 @@ in
 | 
				
			|||||||
            "serial-getty@ttyS1".enable = true;
 | 
					            "serial-getty@ttyS1".enable = true;
 | 
				
			||||||
            lvm-activate-main = {
 | 
					            lvm-activate-main = {
 | 
				
			||||||
              description = "Activate remaining LVs";
 | 
					              description = "Activate remaining LVs";
 | 
				
			||||||
              before = [ "local-fs-pre.target" ];
 | 
					              unitConfig.DefaultDependencies = false;
 | 
				
			||||||
              serviceConfig = {
 | 
					              serviceConfig = {
 | 
				
			||||||
                Type = "oneshot";
 | 
					                Type = "oneshot";
 | 
				
			||||||
                ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
 | 
					                ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              wantedBy = [ "sysinit.target" ];
 | 
					              wantedBy = [ "local-fs-pre.target" ];
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            rsync-lvm-meta = {
 | 
					            rsync-lvm-meta = {
 | 
				
			||||||
@@ -264,10 +264,12 @@ in
 | 
				
			|||||||
                      Destination = prefixes.ctrs.v6;
 | 
					                      Destination = prefixes.ctrs.v6;
 | 
				
			||||||
                      Gateway = allAssignments.shill.internal.ipv6.address;
 | 
					                      Gateway = allAssignments.shill.internal.ipv6.address;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      Destination = allAssignments.shill.internal.ipv4.address;
 | 
					                      Destination = allAssignments.shill.internal.ipv4.address;
 | 
				
			||||||
                      Gateway = allAssignments.shill.routing.ipv4.address;
 | 
					                      Gateway = allAssignments.shill.routing.ipv4.address;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      Destination = lib.my.c.tailscale.prefix.v4;
 | 
					                      Destination = lib.my.c.tailscale.prefix.v4;
 | 
				
			||||||
                      Gateway = allAssignments.shill.routing.ipv4.address;
 | 
					                      Gateway = allAssignments.shill.routing.ipv4.address;
 | 
				
			||||||
@@ -276,6 +278,15 @@ in
 | 
				
			|||||||
                      Destination = lib.my.c.tailscale.prefix.v6;
 | 
					                      Destination = lib.my.c.tailscale.prefix.v6;
 | 
				
			||||||
                      Gateway = allAssignments.shill.internal.ipv6.address;
 | 
					                      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;
 | 
					                      Destination = prefixes.oci.v4;
 | 
				
			||||||
@@ -307,7 +318,7 @@ in
 | 
				
			|||||||
              "90-vm-mail" = {
 | 
					              "90-vm-mail" = {
 | 
				
			||||||
                matchConfig.Name = "vm-mail";
 | 
					                matchConfig.Name = "vm-mail";
 | 
				
			||||||
                address = [
 | 
					                address = [
 | 
				
			||||||
                  (net.cidr.subnet 8 1 prefixes.cust.v4)
 | 
					                  "${custRouting.mail-vm}/32"
 | 
				
			||||||
                  prefixes.mail.v6
 | 
					                  prefixes.mail.v6
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
                networkConfig = {
 | 
					                networkConfig = {
 | 
				
			||||||
@@ -330,7 +341,7 @@ in
 | 
				
			|||||||
              "90-vm-darts" = {
 | 
					              "90-vm-darts" = {
 | 
				
			||||||
                matchConfig.Name = "vm-darts";
 | 
					                matchConfig.Name = "vm-darts";
 | 
				
			||||||
                address = [
 | 
					                address = [
 | 
				
			||||||
                  (net.cidr.subnet 8 2 prefixes.cust.v4)
 | 
					                  "${custRouting.darts-vm}/32"
 | 
				
			||||||
                  prefixes.darts.v6
 | 
					                  prefixes.darts.v6
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
                networkConfig = {
 | 
					                networkConfig = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -29,6 +29,9 @@
 | 
				
			|||||||
    };
 | 
					    };
 | 
				
			||||||
  in
 | 
					  in
 | 
				
			||||||
  {
 | 
					  {
 | 
				
			||||||
 | 
					    # Kernel Same-Page Merging to attempt memory usage reduction
 | 
				
			||||||
 | 
					    hardware.ksm.enable = false;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    systemd = {
 | 
					    systemd = {
 | 
				
			||||||
      network = {
 | 
					      network = {
 | 
				
			||||||
        links = {
 | 
					        links = {
 | 
				
			||||||
@@ -130,7 +133,8 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
              (vm.lvmDisk "media")
 | 
					              (vm.lvmDisk "media")
 | 
				
			||||||
              (vm.lvmDisk "minio")
 | 
					              (vm.lvmDisk "minio")
 | 
				
			||||||
              (vm.lvmDisk "nix-atticd")
 | 
					              (vm.lvmDisk "nix-cache")
 | 
				
			||||||
 | 
					              (vm.lvmDisk "jam")
 | 
				
			||||||
            ]);
 | 
					            ]);
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -209,6 +213,7 @@
 | 
				
			|||||||
            drives = [
 | 
					            drives = [
 | 
				
			||||||
              (mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ])
 | 
					              (mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ])
 | 
				
			||||||
              (vm.lvmDisk' "media" "darts-media")
 | 
					              (vm.lvmDisk' "media" "darts-media")
 | 
				
			||||||
 | 
					              (vm.lvmDisk' "ext" "darts-ext")
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -9,6 +9,7 @@ in
 | 
				
			|||||||
    vpns = {
 | 
					    vpns = {
 | 
				
			||||||
      l2 = {
 | 
					      l2 = {
 | 
				
			||||||
        as211024 = {
 | 
					        as211024 = {
 | 
				
			||||||
 | 
					          udpEncapsulation = true;
 | 
				
			||||||
          vni = 211024;
 | 
					          vni = 211024;
 | 
				
			||||||
          security.enable = true;
 | 
					          security.enable = true;
 | 
				
			||||||
          peers = {
 | 
					          peers = {
 | 
				
			||||||
@@ -307,6 +308,11 @@ in
 | 
				
			|||||||
                          Destination = lib.my.c.tailscale.prefix.v6;
 | 
					                          Destination = lib.my.c.tailscale.prefix.v6;
 | 
				
			||||||
                          Gateway = allAssignments.colony.internal.ipv6.address;
 | 
					                          Gateway = allAssignments.colony.internal.ipv6.address;
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                        {
 | 
				
			||||||
 | 
					                          Destination = prefixes.qclk.v4;
 | 
				
			||||||
 | 
					                          Gateway = allAssignments.colony.routing.ipv4.address;
 | 
				
			||||||
 | 
					                        }
 | 
				
			||||||
                      ] ++
 | 
					                      ] ++
 | 
				
			||||||
                      (map (pName: [
 | 
					                      (map (pName: [
 | 
				
			||||||
                        {
 | 
					                        {
 | 
				
			||||||
@@ -393,6 +399,9 @@ in
 | 
				
			|||||||
                      # Safe enough to allow all SSH
 | 
					                      # Safe enough to allow all SSH
 | 
				
			||||||
                      tcp dport ssh accept
 | 
					                      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
 | 
					                      ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept
 | 
				
			||||||
                      ${matchInet "tcp dport { http, https } accept" "git"}
 | 
					                      ${matchInet "tcp dport { http, https } accept" "git"}
 | 
				
			||||||
                      ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept
 | 
					                      ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
let
 | 
					let
 | 
				
			||||||
  inherit (builtins) attrNames;
 | 
					  inherit (builtins) attrNames;
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  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;
 | 
					  authZones = attrNames config.my.pdns.auth.bind.zones;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
@@ -162,6 +162,10 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            andrey-cust IN A ${allAssignments.kelder.estuary.ipv4.address}
 | 
					            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
 | 
					            $TTL 3
 | 
				
			||||||
            _acme-challenge IN LUA TXT @@FILE@@
 | 
					            _acme-challenge IN LUA TXT @@FILE@@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										105
									
								
								nixos/boxes/colony/vms/shill/containers-ext.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								nixos/boxes/colony/vms/shill/containers-ext.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,105 @@
 | 
				
			|||||||
 | 
					{ lib, pkgs, assignments, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
 | 
					  inherit (lib.my.c.colony) prefixes custRouting;
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  fileSystems = {
 | 
				
			||||||
 | 
					    "/mnt/jam" = {
 | 
				
			||||||
 | 
					      device = "/dev/disk/by-label/jam";
 | 
				
			||||||
 | 
					      fsType = "ext4";
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    "/var/lib/machines/jam" = {
 | 
				
			||||||
 | 
					      device = "/mnt/jam";
 | 
				
			||||||
 | 
					      options = [ "bind" ];
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  systemd = {
 | 
				
			||||||
 | 
					    nspawn = {
 | 
				
			||||||
 | 
					      jam = {
 | 
				
			||||||
 | 
					        enable = true;
 | 
				
			||||||
 | 
					        execConfig = {
 | 
				
			||||||
 | 
					          Boot = true;
 | 
				
			||||||
 | 
					          PrivateUsers = "pick";
 | 
				
			||||||
 | 
					          LinkJournal = false;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        networkConfig = {
 | 
				
			||||||
 | 
					          Private = true;
 | 
				
			||||||
 | 
					          VirtualEthernet = true;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    network.networks = {
 | 
				
			||||||
 | 
					      "50-ve-jam" = {
 | 
				
			||||||
 | 
					        matchConfig = {
 | 
				
			||||||
 | 
					          Kind = "veth";
 | 
				
			||||||
 | 
					          Name = "ve-jam";
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        address = [
 | 
				
			||||||
 | 
					          custRouting.jam-ctr
 | 
				
			||||||
 | 
					          prefixes.jam.v6
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        networkConfig = {
 | 
				
			||||||
 | 
					          IPv6AcceptRA = false;
 | 
				
			||||||
 | 
					          IPv6SendRA = true;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        ipv6Prefixes = [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            ipv6PrefixConfig.Prefix = prefixes.jam.v6;
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					        routes = map (r: { routeConfig = r; }) [
 | 
				
			||||||
 | 
					          {
 | 
				
			||||||
 | 
					            Destination = prefixes.jam.v4;
 | 
				
			||||||
 | 
					            Scope = "link";
 | 
				
			||||||
 | 
					          }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    services = {
 | 
				
			||||||
 | 
					      "systemd-nspawn@jam" = {
 | 
				
			||||||
 | 
					        overrideStrategy = "asDropin";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        serviceConfig = {
 | 
				
			||||||
 | 
					          CPUQuota = "400%";
 | 
				
			||||||
 | 
					          MemoryHigh = "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, ... }:
 | 
					    configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
 | 
				
			||||||
    let
 | 
					    let
 | 
				
			||||||
      inherit (lib) mkMerge mkIf mkForce;
 | 
					      inherit (lib) genAttrs mkMerge mkIf mkForce;
 | 
				
			||||||
      inherit (lib.my) networkdAssignment;
 | 
					      inherit (lib.my) networkdAssignment;
 | 
				
			||||||
    in
 | 
					    in
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -45,10 +45,28 @@ in
 | 
				
			|||||||
                  owner = "matrix-synapse";
 | 
					                  owner = "matrix-synapse";
 | 
				
			||||||
                  group = "matrix-synapse";
 | 
					                  group = "matrix-synapse";
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					                "chatterbox/doublepuppet.yaml" = {
 | 
				
			||||||
 | 
					                  owner = "matrix-synapse";
 | 
				
			||||||
 | 
					                  group = "matrix-synapse";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                "chatterbox/syncv3.env" = {
 | 
					                "chatterbox/syncv3.env" = {
 | 
				
			||||||
                  owner = "matrix-syncv3";
 | 
					                  owner = "matrix-syncv3";
 | 
				
			||||||
                  group = "matrix-syncv3";
 | 
					                  group = "matrix-syncv3";
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                "chatterbox/mautrix-whatsapp.env" = {
 | 
				
			||||||
 | 
					                  owner = "mautrix-whatsapp";
 | 
				
			||||||
 | 
					                  group = "mautrix-whatsapp";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                "chatterbox/mautrix-messenger.env" = {
 | 
				
			||||||
 | 
					                  owner = "mautrix-meta-messenger";
 | 
				
			||||||
 | 
					                  group = "mautrix-meta";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                "chatterbox/mautrix-instagram.env" = {
 | 
				
			||||||
 | 
					                  owner = "mautrix-meta-instagram";
 | 
				
			||||||
 | 
					                  group = "mautrix-meta";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,6 +77,9 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          users = with lib.my.c.ids; {
 | 
					          users = with lib.my.c.ids; {
 | 
				
			||||||
            users = {
 | 
					            users = {
 | 
				
			||||||
 | 
					              matrix-synapse.extraGroups = [
 | 
				
			||||||
 | 
					                "mautrix-whatsapp"
 | 
				
			||||||
 | 
					              ];
 | 
				
			||||||
              matrix-syncv3 = {
 | 
					              matrix-syncv3 = {
 | 
				
			||||||
                isSystemUser = true;
 | 
					                isSystemUser = true;
 | 
				
			||||||
                uid = uids.matrix-syncv3;
 | 
					                uid = uids.matrix-syncv3;
 | 
				
			||||||
@@ -79,7 +100,10 @@ in
 | 
				
			|||||||
                User = "matrix-syncv3";
 | 
					                User = "matrix-syncv3";
 | 
				
			||||||
                Group = "matrix-syncv3";
 | 
					                Group = "matrix-syncv3";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: {
 | 
				
			||||||
 | 
					              # ffmpeg needed to convert GIFs to video
 | 
				
			||||||
 | 
					              path = with pkgs; [ ffmpeg ];
 | 
				
			||||||
 | 
					            }));
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          services = {
 | 
					          services = {
 | 
				
			||||||
@@ -168,10 +192,13 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
                app_service_config_files = [
 | 
					                app_service_config_files = [
 | 
				
			||||||
                  "/var/lib/heisenbridge/registration.yml"
 | 
					                  "/var/lib/heisenbridge/registration.yml"
 | 
				
			||||||
 | 
					                  config.age.secrets."chatterbox/doublepuppet.yaml".path
 | 
				
			||||||
 | 
					                  "/var/lib/mautrix-whatsapp/whatsapp-registration.yaml"
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              sliding-sync = {
 | 
					            };
 | 
				
			||||||
 | 
					            matrix-sliding-sync = {
 | 
				
			||||||
              enable = true;
 | 
					              enable = true;
 | 
				
			||||||
              createDatabase = false;
 | 
					              createDatabase = false;
 | 
				
			||||||
              environmentFile = config.age.secrets."chatterbox/syncv3.env".path;
 | 
					              environmentFile = config.age.secrets."chatterbox/syncv3.env".path;
 | 
				
			||||||
@@ -180,7 +207,6 @@ in
 | 
				
			|||||||
                SYNCV3_SERVER = "http://localhost:8008";
 | 
					                SYNCV3_SERVER = "http://localhost:8008";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
            heisenbridge = {
 | 
					            heisenbridge = {
 | 
				
			||||||
              enable = true;
 | 
					              enable = true;
 | 
				
			||||||
@@ -195,6 +221,140 @@ in
 | 
				
			|||||||
                ];
 | 
					                ];
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            mautrix-whatsapp = {
 | 
				
			||||||
 | 
					              enable = true;
 | 
				
			||||||
 | 
					              environmentFile = config.age.secrets."chatterbox/mautrix-whatsapp.env".path;
 | 
				
			||||||
 | 
					              settings = {
 | 
				
			||||||
 | 
					                homeserver = {
 | 
				
			||||||
 | 
					                  address = "http://localhost:8008";
 | 
				
			||||||
 | 
					                  domain = "nul.ie";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                appservice = {
 | 
				
			||||||
 | 
					                  database = {
 | 
				
			||||||
 | 
					                    type = "postgres";
 | 
				
			||||||
 | 
					                    uri = "$MAU_WAPP_PSQL_URI";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  id = "whatsapp2";
 | 
				
			||||||
 | 
					                  bot = {
 | 
				
			||||||
 | 
					                    username = "whatsapp2";
 | 
				
			||||||
 | 
					                    displayname = "WhatsApp Bridge Bot";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					                bridge = {
 | 
				
			||||||
 | 
					                  username_template = "wapp2_{{.}}";
 | 
				
			||||||
 | 
					                  displayname_template = "{{or .BusinessName .PushName .JID}} (WA)";
 | 
				
			||||||
 | 
					                  personal_filtering_spaces = true;
 | 
				
			||||||
 | 
					                  delivery_receipts = true;
 | 
				
			||||||
 | 
					                  allow_user_invite = true;
 | 
				
			||||||
 | 
					                  url_previews = true;
 | 
				
			||||||
 | 
					                  command_prefix = "!wa";
 | 
				
			||||||
 | 
					                  login_shared_secret_map."nul.ie" = "$MAU_WAPP_DOUBLE_PUPPET_TOKEN";
 | 
				
			||||||
 | 
					                  encryption = {
 | 
				
			||||||
 | 
					                    allow = true;
 | 
				
			||||||
 | 
					                    default = true;
 | 
				
			||||||
 | 
					                    require = true;
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  permissions = {
 | 
				
			||||||
 | 
					                    "@dev:nul.ie" = "admin";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            mautrix-meta.instances = {
 | 
				
			||||||
 | 
					              messenger = {
 | 
				
			||||||
 | 
					                enable = true;
 | 
				
			||||||
 | 
					                registerToSynapse = true;
 | 
				
			||||||
 | 
					                dataDir = "mautrix-messenger";
 | 
				
			||||||
 | 
					                environmentFile = config.age.secrets."chatterbox/mautrix-messenger.env".path;
 | 
				
			||||||
 | 
					                settings = {
 | 
				
			||||||
 | 
					                  homeserver = {
 | 
				
			||||||
 | 
					                    address = "http://localhost:8008";
 | 
				
			||||||
 | 
					                    domain = "nul.ie";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  appservice = {
 | 
				
			||||||
 | 
					                    database = {
 | 
				
			||||||
 | 
					                      type = "postgres";
 | 
				
			||||||
 | 
					                      uri = "$MAU_FBM_PSQL_URI";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    id = "fbm2";
 | 
				
			||||||
 | 
					                    bot = {
 | 
				
			||||||
 | 
					                      username = "messenger2";
 | 
				
			||||||
 | 
					                      displayname = "Messenger Bridge Bot";
 | 
				
			||||||
 | 
					                      avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  meta.mode = "messenger";
 | 
				
			||||||
 | 
					                  bridge = {
 | 
				
			||||||
 | 
					                    username_template = "fbm2_{{.}}";
 | 
				
			||||||
 | 
					                    displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FBM)'';
 | 
				
			||||||
 | 
					                    personal_filtering_spaces = true;
 | 
				
			||||||
 | 
					                    delivery_receipts = true;
 | 
				
			||||||
 | 
					                    management_room_text.welcome = "Hello, I'm a Messenger bridge bot.";
 | 
				
			||||||
 | 
					                    command_prefix = "!fbm";
 | 
				
			||||||
 | 
					                    login_shared_secret_map."nul.ie" = "$MAU_FBM_DOUBLE_PUPPET_TOKEN";
 | 
				
			||||||
 | 
					                    backfill = {
 | 
				
			||||||
 | 
					                      history_fetch_pages = 5;
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    encryption = {
 | 
				
			||||||
 | 
					                      allow = true;
 | 
				
			||||||
 | 
					                      default = true;
 | 
				
			||||||
 | 
					                      require = true;
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    permissions = {
 | 
				
			||||||
 | 
					                      "@dev:nul.ie" = "admin";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              instagram = {
 | 
				
			||||||
 | 
					                enable = true;
 | 
				
			||||||
 | 
					                registerToSynapse = true;
 | 
				
			||||||
 | 
					                dataDir = "mautrix-instagram";
 | 
				
			||||||
 | 
					                environmentFile = config.age.secrets."chatterbox/mautrix-instagram.env".path;
 | 
				
			||||||
 | 
					                settings = {
 | 
				
			||||||
 | 
					                  homeserver = {
 | 
				
			||||||
 | 
					                    address = "http://localhost:8008";
 | 
				
			||||||
 | 
					                    domain = "nul.ie";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  appservice = {
 | 
				
			||||||
 | 
					                    database = {
 | 
				
			||||||
 | 
					                      type = "postgres";
 | 
				
			||||||
 | 
					                      uri = "$MAU_IG_PSQL_URI";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    id = "instagram";
 | 
				
			||||||
 | 
					                    bot = {
 | 
				
			||||||
 | 
					                      username = "instagram";
 | 
				
			||||||
 | 
					                      displayname = "Instagram Bridge Bot";
 | 
				
			||||||
 | 
					                      avatar = "mxc://maunium.net/JxjlbZUlCPULEeHZSwleUXQv";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                  meta.mode = "instagram";
 | 
				
			||||||
 | 
					                  bridge = {
 | 
				
			||||||
 | 
					                    username_template = "ig_{{.}}";
 | 
				
			||||||
 | 
					                    displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (IG)'';
 | 
				
			||||||
 | 
					                    personal_filtering_spaces = true;
 | 
				
			||||||
 | 
					                    delivery_receipts = true;
 | 
				
			||||||
 | 
					                    management_room_text.welcome = "Hello, I'm an Instagram bridge bot.";
 | 
				
			||||||
 | 
					                    command_prefix = "!ig";
 | 
				
			||||||
 | 
					                    login_shared_secret_map."nul.ie" = "$MAU_IG_DOUBLE_PUPPET_TOKEN";
 | 
				
			||||||
 | 
					                    backfill = {
 | 
				
			||||||
 | 
					                      history_fetch_pages = 5;
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    encryption = {
 | 
				
			||||||
 | 
					                      allow = true;
 | 
				
			||||||
 | 
					                      default = true;
 | 
				
			||||||
 | 
					                      require = true;
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                    permissions = {
 | 
				
			||||||
 | 
					                      "@dev:nul.ie" = "admin";
 | 
				
			||||||
 | 
					                    };
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        (mkIf config.my.build.isDevVM {
 | 
					        (mkIf config.my.build.isDevVM {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -8,5 +8,6 @@
 | 
				
			|||||||
    ./object.nix
 | 
					    ./object.nix
 | 
				
			||||||
    ./toot.nix
 | 
					    ./toot.nix
 | 
				
			||||||
    ./waffletail.nix
 | 
					    ./waffletail.nix
 | 
				
			||||||
 | 
					    ./qclk
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,8 @@
 | 
				
			|||||||
{ lib, ... }:
 | 
					{ lib, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
 | 
					  inherit (lib) concatStringsSep;
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
 | 
					  inherit (lib.my.c) pubDomain;
 | 
				
			||||||
  inherit (lib.my.c.colony) domain prefixes;
 | 
					  inherit (lib.my.c.colony) domain prefixes;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
@@ -35,6 +37,9 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          secrets = {
 | 
					          secrets = {
 | 
				
			||||||
            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPUv1ntVrZv5ripsKpcOAnyDQX2PHjowzyhqWK10Ml53";
 | 
					            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPUv1ntVrZv5ripsKpcOAnyDQX2PHjowzyhqWK10Ml53";
 | 
				
			||||||
 | 
					            files = {
 | 
				
			||||||
 | 
					              "jackflix/photoprism-pass.txt" = {};
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -50,10 +55,16 @@ in
 | 
				
			|||||||
              uid = uids.jellyseerr;
 | 
					              uid = uids.jellyseerr;
 | 
				
			||||||
              group = "jellyseerr";
 | 
					              group = "jellyseerr";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            photoprism = {
 | 
				
			||||||
 | 
					              isSystemUser = true;
 | 
				
			||||||
 | 
					              uid = uids.photoprism;
 | 
				
			||||||
 | 
					              group = "photoprism";
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          groups = {
 | 
					          groups = {
 | 
				
			||||||
            media.gid = 2000;
 | 
					            media.gid = 2000;
 | 
				
			||||||
            jellyseerr.gid = gids.jellyseerr;
 | 
					            jellyseerr.gid = gids.jellyseerr;
 | 
				
			||||||
 | 
					            photoprism.gid = gids.photoprism;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -76,6 +87,10 @@ in
 | 
				
			|||||||
              RootDirectoryStartOnly = lib.mkForce false;
 | 
					              RootDirectoryStartOnly = lib.mkForce false;
 | 
				
			||||||
              RootDirectory = lib.mkForce "";
 | 
					              RootDirectory = lib.mkForce "";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					            photoprism.serviceConfig = {
 | 
				
			||||||
 | 
					              # Needs to be able to access its data
 | 
				
			||||||
 | 
					              DynamicUser = mkForce false;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -117,6 +132,24 @@ in
 | 
				
			|||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          jellyfin.enable = true;
 | 
					          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
 | 
					                tcp dport ${toString transmissionPeerPort} accept
 | 
				
			||||||
                iifname vpn return
 | 
					                iifname vpn return
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                tcp dport { 19999, 9091, 9117, 7878, 8989, 8096 } accept
 | 
					                tcp dport { 19999, 9091, 9117, 7878, 8989, 8096, 2342 } accept
 | 
				
			||||||
                return
 | 
					                return
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
              chain input {
 | 
					              chain input {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -239,6 +239,9 @@ in
 | 
				
			|||||||
              ];
 | 
					              ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              recommendedTlsSettings = true;
 | 
					              recommendedTlsSettings = true;
 | 
				
			||||||
 | 
					              recommendedBrotliSettings = true;
 | 
				
			||||||
 | 
					              # Uh so nginx is hanging with zstd enabled... maybe let's not for now
 | 
				
			||||||
 | 
					              # recommendedZstdSettings = true;
 | 
				
			||||||
              clientMaxBodySize = "0";
 | 
					              clientMaxBodySize = "0";
 | 
				
			||||||
              serverTokens = true;
 | 
					              serverTokens = true;
 | 
				
			||||||
              resolver = {
 | 
					              resolver = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
let
 | 
					let
 | 
				
			||||||
  inherit (builtins) mapAttrs toJSON;
 | 
					  inherit (builtins) mapAttrs toJSON;
 | 
				
			||||||
  inherit (lib) mkMerge mkDefault genAttrs flatten concatStringsSep;
 | 
					  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 (lib.my.c.nginx) proxyHeaders;
 | 
				
			||||||
  inherit (config.networking) domain;
 | 
					  inherit (config.networking) domain;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -145,7 +145,7 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      "pass.${pubDomain}" =
 | 
					      "pass.${pubDomain}" =
 | 
				
			||||||
      let
 | 
					      let
 | 
				
			||||||
        upstream = "http://vaultwarden-ctr.${domain}";
 | 
					        upstream = "http://vaultwarden-ctr.${domain}:8080";
 | 
				
			||||||
      in
 | 
					      in
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        locations = {
 | 
					        locations = {
 | 
				
			||||||
@@ -206,7 +206,8 @@ in
 | 
				
			|||||||
          # Currently it seems like single quotes aren't escaped like they should be...
 | 
					          # Currently it seems like single quotes aren't escaped like they should be...
 | 
				
			||||||
          conf = {
 | 
					          conf = {
 | 
				
			||||||
            brand = "/dev/player0 Matrix";
 | 
					            brand = "/dev/player0 Matrix";
 | 
				
			||||||
            showLabsSettings = true;
 | 
					            show_labs_settings = true;
 | 
				
			||||||
 | 
					            default_country_code = "IE";
 | 
				
			||||||
            disable_guests = true;
 | 
					            disable_guests = true;
 | 
				
			||||||
            default_server_config = {
 | 
					            default_server_config = {
 | 
				
			||||||
              "m.homeserver" = {
 | 
					              "m.homeserver" = {
 | 
				
			||||||
@@ -214,9 +215,8 @@ in
 | 
				
			|||||||
                server_name = "nul.ie";
 | 
					                server_name = "nul.ie";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            roomDirectory.servers = [
 | 
					            room_directory.servers = [
 | 
				
			||||||
              "nul.ie"
 | 
					              "nul.ie"
 | 
				
			||||||
              "netsoc.ie"
 | 
					 | 
				
			||||||
              "matrix.org"
 | 
					              "matrix.org"
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
@@ -364,7 +364,7 @@ in
 | 
				
			|||||||
        useACMEHost = pubDomain;
 | 
					        useACMEHost = pubDomain;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
      "mc-rail.${pubDomain}" = {
 | 
					      "mc-rail.${pubDomain}" = {
 | 
				
			||||||
        locations."/".proxyPass = "http://simpcraft-staging-oci.${domain}:3876";
 | 
					        locations."/".proxyPass = "http://simpcraft-oci.${domain}:3876";
 | 
				
			||||||
        useACMEHost = pubDomain;
 | 
					        useACMEHost = pubDomain;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -384,6 +384,40 @@ in
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
        useACMEHost = pubDomain;
 | 
					        useACMEHost = pubDomain;
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					      "pb.${pubDomain}" = {
 | 
				
			||||||
 | 
					        locations."/".proxyPass = "http://object-ctr.${domain}:8088";
 | 
				
			||||||
 | 
					        useACMEHost = pubDomain;
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      "photos.${pubDomain}" = {
 | 
				
			||||||
 | 
					        locations."/" = {
 | 
				
			||||||
 | 
					          proxyPass = "http://jackflix-ctr.${domain}:2342";
 | 
				
			||||||
 | 
					          proxyWebsockets = true;
 | 
				
			||||||
 | 
					          extraConfig = proxyHeaders;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        useACMEHost = pubDomain;
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      "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 =
 | 
					    minio =
 | 
				
			||||||
@@ -395,10 +429,13 @@ in
 | 
				
			|||||||
        ignore_invalid_headers off;
 | 
					        ignore_invalid_headers off;
 | 
				
			||||||
      '';
 | 
					      '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar\.\S+)$'';
 | 
					      nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar.*|serve\/.+)$'';
 | 
				
			||||||
      nixCacheHeaders = ''
 | 
					      nixCacheHeaders = ''
 | 
				
			||||||
        add_header Cache-Control $nix_cache_control;
 | 
					        add_header Cache-Control $nix_cache_control;
 | 
				
			||||||
        add_header Expires $nix_expires;
 | 
					        add_header Expires $nix_expires;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        brotli on;
 | 
				
			||||||
 | 
					        brotli_types application/x-nix-archive;
 | 
				
			||||||
      '';
 | 
					      '';
 | 
				
			||||||
    in
 | 
					    in
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
@@ -440,9 +477,11 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      "nix-cache.${pubDomain}" = {
 | 
					      "nix-cache.${pubDomain}" = {
 | 
				
			||||||
        locations = {
 | 
					        locations = {
 | 
				
			||||||
          "/".proxyPass = "http://${host}:8069";
 | 
					          "/" = {
 | 
				
			||||||
 | 
					            proxyPass = "http://${host}:5000";
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
          "~ ${nixCacheableRegex}" = {
 | 
					          "~ ${nixCacheableRegex}" = {
 | 
				
			||||||
            proxyPass = "http://${host}:8069";
 | 
					            proxyPass = "http://${host}:5000";
 | 
				
			||||||
            extraConfig = nixCacheHeaders;
 | 
					            extraConfig = nixCacheHeaders;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -31,6 +31,13 @@ in
 | 
				
			|||||||
    {
 | 
					    {
 | 
				
			||||||
      config = mkMerge [
 | 
					      config = mkMerge [
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          fileSystems = {
 | 
				
			||||||
 | 
					            "/var/lib/harmonia" = {
 | 
				
			||||||
 | 
					              device = "/mnt/nix-cache";
 | 
				
			||||||
 | 
					              options = [ "bind" ];
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          my = {
 | 
					          my = {
 | 
				
			||||||
            deploy.enable = false;
 | 
					            deploy.enable = false;
 | 
				
			||||||
            server.enable = true;
 | 
					            server.enable = true;
 | 
				
			||||||
@@ -48,7 +55,9 @@ in
 | 
				
			|||||||
                  group = config.my.user.config.group;
 | 
					                  group = config.my.user.config.group;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                "object/atticd.env" = {};
 | 
					                "object/atticd.env" = {};
 | 
				
			||||||
 | 
					                "nix-cache.key" = {};
 | 
				
			||||||
                "object/hedgedoc.env" = {};
 | 
					                "object/hedgedoc.env" = {};
 | 
				
			||||||
 | 
					                "object/wastebin.env" = {};
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -57,7 +66,9 @@ in
 | 
				
			|||||||
                9000 9001
 | 
					                9000 9001
 | 
				
			||||||
                config.services.sharry.config.bind.port
 | 
					                config.services.sharry.config.bind.port
 | 
				
			||||||
                8069
 | 
					                8069
 | 
				
			||||||
 | 
					                5000
 | 
				
			||||||
                config.services.hedgedoc.settings.port
 | 
					                config.services.hedgedoc.settings.port
 | 
				
			||||||
 | 
					                8088
 | 
				
			||||||
              ];
 | 
					              ];
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -66,14 +77,26 @@ in
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          users = with lib.my.c.ids; let inherit (config.services.atticd) user group; in {
 | 
					          users = with lib.my.c.ids; mkMerge [
 | 
				
			||||||
 | 
					            (let inherit (config.services.atticd) user group; in {
 | 
				
			||||||
              users."${user}" = {
 | 
					              users."${user}" = {
 | 
				
			||||||
                isSystemUser = true;
 | 
					                isSystemUser = true;
 | 
				
			||||||
                uid = uids.atticd;
 | 
					                uid = uids.atticd;
 | 
				
			||||||
                group = group;
 | 
					                group = group;
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              groups."${user}".gid = gids.atticd;
 | 
					              groups."${user}".gid = gids.atticd;
 | 
				
			||||||
 | 
					            })
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              users = {
 | 
				
			||||||
 | 
					                harmonia = {
 | 
				
			||||||
 | 
					                  shell = pkgs.bashInteractive;
 | 
				
			||||||
 | 
					                  openssh.authorizedKeys.keyFiles = [
 | 
				
			||||||
 | 
					                    lib.my.c.sshKeyFiles.harmonia
 | 
				
			||||||
 | 
					                  ];
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          systemd = {
 | 
					          systemd = {
 | 
				
			||||||
            network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
 | 
					            network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
 | 
				
			||||||
@@ -91,7 +114,9 @@ in
 | 
				
			|||||||
                  MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie";
 | 
					                  MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie";
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              sharry = awaitPostgres;
 | 
					              sharry = awaitPostgres;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
              atticd = mkMerge [
 | 
					              atticd = mkMerge [
 | 
				
			||||||
                awaitPostgres
 | 
					                awaitPostgres
 | 
				
			||||||
                {
 | 
					                {
 | 
				
			||||||
@@ -102,6 +127,15 @@ in
 | 
				
			|||||||
                  };
 | 
					                  };
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
              ];
 | 
					              ];
 | 
				
			||||||
 | 
					              harmonia = {
 | 
				
			||||||
 | 
					                environment.NIX_REMOTE = "/var/lib/harmonia";
 | 
				
			||||||
 | 
					                preStart = ''
 | 
				
			||||||
 | 
					                  ${config.nix.package}/bin/nix store ping
 | 
				
			||||||
 | 
					                '';
 | 
				
			||||||
 | 
					                serviceConfig = {
 | 
				
			||||||
 | 
					                  StateDirectory = "harmonia";
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -181,7 +215,7 @@ in
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            atticd = {
 | 
					            atticd = {
 | 
				
			||||||
              enable = true;
 | 
					              enable = false;
 | 
				
			||||||
              credentialsFile = config.age.secrets."object/atticd.env".path;
 | 
					              credentialsFile = config.age.secrets."object/atticd.env".path;
 | 
				
			||||||
              settings = {
 | 
					              settings = {
 | 
				
			||||||
                listen = "[::]:8069";
 | 
					                listen = "[::]:8069";
 | 
				
			||||||
@@ -201,6 +235,14 @@ in
 | 
				
			|||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            harmonia = {
 | 
				
			||||||
 | 
					              enable = true;
 | 
				
			||||||
 | 
					              signKeyPath = config.age.secrets."nix-cache.key".path;
 | 
				
			||||||
 | 
					              settings = {
 | 
				
			||||||
 | 
					                priority = 30;
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            hedgedoc = {
 | 
					            hedgedoc = {
 | 
				
			||||||
              enable = true;
 | 
					              enable = true;
 | 
				
			||||||
              environmentFile = config.age.secrets."object/hedgedoc.env".path;
 | 
					              environmentFile = config.age.secrets."object/hedgedoc.env".path;
 | 
				
			||||||
@@ -220,6 +262,15 @@ in
 | 
				
			|||||||
                allowEmailRegister = false;
 | 
					                allowEmailRegister = false;
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            wastebin = {
 | 
				
			||||||
 | 
					              enable = true;
 | 
				
			||||||
 | 
					              settings = {
 | 
				
			||||||
 | 
					                WASTEBIN_MAX_BODY_SIZE = 67108864; # 16 MiB
 | 
				
			||||||
 | 
					                WASTEBIN_PASSWORD_SALT = "TeGhaemeer0Siez3";
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              secretFile = config.age.secrets."object/wastebin.env".path;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
        (mkIf config.my.build.isDevVM {
 | 
					        (mkIf config.my.build.isDevVM {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										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}";
 | 
					                DOMAIN = "https://pass.${lib.my.c.pubDomain}";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                ROCKET_ADDRESS = "::";
 | 
					                ROCKET_ADDRESS = "::";
 | 
				
			||||||
                ROCKET_PORT = 80;
 | 
					                ROCKET_PORT = 8080;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                SMTP_HOST = "mail.nul.ie";
 | 
					                SMTP_HOST = "mail.nul.ie";
 | 
				
			||||||
                SMTP_FROM = "pass@nul.ie";
 | 
					                SMTP_FROM = "pass@nul.ie";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -49,7 +49,11 @@ in
 | 
				
			|||||||
        inherit (lib.my) networkdAssignment;
 | 
					        inherit (lib.my) networkdAssignment;
 | 
				
			||||||
      in
 | 
					      in
 | 
				
			||||||
      {
 | 
					      {
 | 
				
			||||||
        imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
 | 
					        imports = [
 | 
				
			||||||
 | 
					          "${modulesPath}/profiles/qemu-guest.nix"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          ./containers-ext.nix
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        config = mkMerge [
 | 
					        config = mkMerge [
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
@@ -90,8 +94,8 @@ in
 | 
				
			|||||||
                device = "/dev/disk/by-label/minio";
 | 
					                device = "/dev/disk/by-label/minio";
 | 
				
			||||||
                fsType = "xfs";
 | 
					                fsType = "xfs";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              "/mnt/atticd" = {
 | 
					              "/mnt/nix-cache" = {
 | 
				
			||||||
                device = "/dev/disk/by-label/atticd";
 | 
					                device = "/dev/disk/by-label/nix-cache";
 | 
				
			||||||
                fsType = "ext4";
 | 
					                fsType = "ext4";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
@@ -148,6 +152,11 @@ in
 | 
				
			|||||||
                        Destination = lib.my.c.tailscale.prefix.v6;
 | 
					                        Destination = lib.my.c.tailscale.prefix.v6;
 | 
				
			||||||
                        Gateway = allAssignments.waffletail.internal.ipv6.address;
 | 
					                        Gateway = allAssignments.waffletail.internal.ipv6.address;
 | 
				
			||||||
                      }
 | 
					                      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                      {
 | 
				
			||||||
 | 
					                        Destination = prefixes.qclk.v4;
 | 
				
			||||||
 | 
					                        Gateway = allAssignments.qclk.internal.ipv4.address;
 | 
				
			||||||
 | 
					                      }
 | 
				
			||||||
                    ];
 | 
					                    ];
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
@@ -202,11 +211,12 @@ in
 | 
				
			|||||||
                  object = {
 | 
					                  object = {
 | 
				
			||||||
                    bindMounts = {
 | 
					                    bindMounts = {
 | 
				
			||||||
                      "/mnt/minio".readOnly = false;
 | 
					                      "/mnt/minio".readOnly = false;
 | 
				
			||||||
                      "/mnt/atticd".readOnly = false;
 | 
					                      "/mnt/nix-cache".readOnly = false;
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                  };
 | 
					                  };
 | 
				
			||||||
                  toot = {};
 | 
					                  toot = {};
 | 
				
			||||||
                  waffletail = {};
 | 
					                  waffletail = {};
 | 
				
			||||||
 | 
					                  qclk = {};
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
              in
 | 
					              in
 | 
				
			||||||
              mkMerge [
 | 
					              mkMerge [
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -108,46 +108,31 @@ in
 | 
				
			|||||||
              oci-containers = {
 | 
					              oci-containers = {
 | 
				
			||||||
                backend = "podman";
 | 
					                backend = "podman";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              # NixOS has switched to using netavark, which is native to podman. It's currently missing an option to
 | 
					              containers.containersConf.settings.network = {
 | 
				
			||||||
              # disable iptables rules generation, which is very annoying.
 | 
					                network_backend = "netavark";
 | 
				
			||||||
              containers.containersConf.settings.network.network_backend = mkForce "cni";
 | 
					                firewall_driver = "none";
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            environment = {
 | 
					            environment = {
 | 
				
			||||||
              etc = {
 | 
					              etc = {
 | 
				
			||||||
                "cni/net.d/90-colony.conflist".text = toJSON {
 | 
					                "containers/networks/colony.json".text = toJSON {
 | 
				
			||||||
                  cniVersion = "0.4.0";
 | 
					 | 
				
			||||||
                  name = "colony";
 | 
					                  name = "colony";
 | 
				
			||||||
                  plugins = [
 | 
					                  id = "0000000000000000000000000000000000000000000000000000000000000001";
 | 
				
			||||||
                    {
 | 
					                  driver = "bridge";
 | 
				
			||||||
                      type = "bridge";
 | 
					                  network_interface = "oci";
 | 
				
			||||||
                      bridge = "oci";
 | 
					                  ipv6_enabled = true;
 | 
				
			||||||
                      isGateway = true;
 | 
					                  internal = false;
 | 
				
			||||||
                      ipMasq = false;
 | 
					                  dns_enabled = false;
 | 
				
			||||||
                      hairpinMode = true;
 | 
					                  subnets = [
 | 
				
			||||||
                      ipam = {
 | 
					 | 
				
			||||||
                        type = "host-local";
 | 
					 | 
				
			||||||
                        routes = [
 | 
					 | 
				
			||||||
                          { dst = "0.0.0.0/0"; }
 | 
					 | 
				
			||||||
                          { dst = "::/0"; }
 | 
					 | 
				
			||||||
                        ];
 | 
					 | 
				
			||||||
                        ranges = [
 | 
					 | 
				
			||||||
                          [
 | 
					 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      subnet = prefixes.oci.v4;
 | 
					                      subnet = prefixes.oci.v4;
 | 
				
			||||||
                      gateway = net.cidr.host 1 prefixes.oci.v4;
 | 
					                      gateway = net.cidr.host 1 prefixes.oci.v4;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                          ]
 | 
					 | 
				
			||||||
                          [
 | 
					 | 
				
			||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      subnet = prefixes.oci.v6;
 | 
					                      subnet = prefixes.oci.v6;
 | 
				
			||||||
                      gateway = net.cidr.host 1 prefixes.oci.v6;
 | 
					                      gateway = net.cidr.host 1 prefixes.oci.v6;
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                          ]
 | 
					 | 
				
			||||||
                        ];
 | 
					 | 
				
			||||||
                      };
 | 
					 | 
				
			||||||
                      capabilities.ips = true;
 | 
					 | 
				
			||||||
                    }
 | 
					 | 
				
			||||||
                  ];
 | 
					                  ];
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,4 +1,4 @@
 | 
				
			|||||||
{ lib, config, allAssignments, ... }:
 | 
					{ lib, pkgs, config, allAssignments, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib) concatStringsSep;
 | 
					  inherit (lib) concatStringsSep;
 | 
				
			||||||
  inherit (lib.my) dockerNetAssignment;
 | 
					  inherit (lib.my) dockerNetAssignment;
 | 
				
			||||||
@@ -18,18 +18,27 @@ let
 | 
				
			|||||||
    "d6ec4c91-5da2-44eb-b89d-71dc8fe017a0" # Eefah98
 | 
					    "d6ec4c91-5da2-44eb-b89d-71dc8fe017a0" # Eefah98
 | 
				
			||||||
    "096a7348-fabe-4b2d-93fc-fd1fd5608fb0" # ToTheMoonStar
 | 
					    "096a7348-fabe-4b2d-93fc-fd1fd5608fb0" # ToTheMoonStar
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  fastback = {
 | 
				
			||||||
 | 
					    gitConfig = pkgs.writeText "git-config" ''
 | 
				
			||||||
 | 
					      [user]
 | 
				
			||||||
 | 
					      	email = "simpcraft@nul.ie"
 | 
				
			||||||
 | 
					      	name = "Simpcraft bot"
 | 
				
			||||||
 | 
					    '';
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  config = {
 | 
					  config = {
 | 
				
			||||||
    virtualisation.oci-containers.containers = {
 | 
					    virtualisation.oci-containers.containers = {
 | 
				
			||||||
      simpcraft = {
 | 
					      simpcraft = {
 | 
				
			||||||
        image = "ghcr.io/itzg/minecraft-server:2023.12.2-java17-alpine";
 | 
					        image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        environment = {
 | 
					        environment = {
 | 
				
			||||||
          TYPE = "MODRINTH";
 | 
					          TYPE = "MODRINTH";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          EULA = "true";
 | 
					          EULA = "true";
 | 
				
			||||||
          ENABLE_QUERY = "true";
 | 
					          ENABLE_QUERY = "true";
 | 
				
			||||||
 | 
					          ENABLE_RCON = "true";
 | 
				
			||||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t §4§k-----";
 | 
					          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t §4§k-----";
 | 
				
			||||||
          ICON = "/ext/icon.png";
 | 
					          ICON = "/ext/icon.png";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -41,15 +50,17 @@ in
 | 
				
			|||||||
          SPAWN_PROTECTION = "0";
 | 
					          SPAWN_PROTECTION = "0";
 | 
				
			||||||
          VIEW_DISTANCE = "20";
 | 
					          VIEW_DISTANCE = "20";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          MAX_MEMORY = "6G";
 | 
					          MAX_MEMORY = "8G";
 | 
				
			||||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/cdj2bSKg/Simpcraft-0.1.2.mrpack";
 | 
					          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/NGutsQSd/Simpcraft-0.2.1.mrpack";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          TZ = "Europe/Dublin";
 | 
					          TZ = "Europe/Dublin";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					        environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        volumes = [
 | 
					        volumes = [
 | 
				
			||||||
          "minecraft_data:/data"
 | 
					          "minecraft_data:/data"
 | 
				
			||||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
					          "${./icon.png}:/ext/icon.png:ro"
 | 
				
			||||||
 | 
					          "${fastback.gitConfig}:/data/.config/git/config:ro"
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        extraOptions = [
 | 
					        extraOptions = [
 | 
				
			||||||
@@ -57,41 +68,71 @@ in
 | 
				
			|||||||
        ];
 | 
					        ];
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      simpcraft-staging = {
 | 
					      # simpcraft-staging = {
 | 
				
			||||||
        image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
					      #   image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        environment = {
 | 
					      #   environment = {
 | 
				
			||||||
          TYPE = "MODRINTH";
 | 
					      #     TYPE = "MODRINTH";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          EULA = "true";
 | 
					      #     EULA = "true";
 | 
				
			||||||
          ENABLE_QUERY = "true";
 | 
					      #     ENABLE_QUERY = "true";
 | 
				
			||||||
          ENABLE_RCON = "true";
 | 
					      #     ENABLE_RCON = "true";
 | 
				
			||||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
 | 
					      #     MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
 | 
				
			||||||
          ICON = "/ext/icon.png";
 | 
					      #     ICON = "/ext/icon.png";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
					      #     EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
				
			||||||
          WHITELIST = whitelist;
 | 
					      #     WHITELIST = whitelist;
 | 
				
			||||||
          EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
					      #     EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
				
			||||||
          OPS = op;
 | 
					      #     OPS = op;
 | 
				
			||||||
          DIFFICULTY = "normal";
 | 
					      #     DIFFICULTY = "normal";
 | 
				
			||||||
          SPAWN_PROTECTION = "0";
 | 
					      #     SPAWN_PROTECTION = "0";
 | 
				
			||||||
          VIEW_DISTANCE = "20";
 | 
					      #     VIEW_DISTANCE = "20";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          MAX_MEMORY = "4G";
 | 
					      #     MAX_MEMORY = "4G";
 | 
				
			||||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
 | 
					      #     MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          TZ = "Europe/Dublin";
 | 
					      #     TZ = "Europe/Dublin";
 | 
				
			||||||
 | 
					      #   };
 | 
				
			||||||
 | 
					      #   environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      #   volumes = [
 | 
				
			||||||
 | 
					      #     "minecraft_staging_data:/data"
 | 
				
			||||||
 | 
					      #     "${./icon.png}:/ext/icon.png:ro"
 | 
				
			||||||
 | 
					      #   ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      #   extraOptions = [
 | 
				
			||||||
 | 
					      #     ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
 | 
				
			||||||
 | 
					      #   ];
 | 
				
			||||||
 | 
					      # };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
        environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        volumes = [
 | 
					    services = {
 | 
				
			||||||
          "minecraft_staging_data:/data"
 | 
					      borgbackup.jobs.simpcraft =
 | 
				
			||||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
					      let
 | 
				
			||||||
        ];
 | 
					        rconCommand = cmd: ''${pkgs.mcrcon}/bin/mcrcon -H simpcraft-oci -p "$RCON_PASSWORD" "${cmd}"'';
 | 
				
			||||||
 | 
					      in
 | 
				
			||||||
 | 
					      {
 | 
				
			||||||
 | 
					        paths = [ "/var/lib/containers/storage/volumes/minecraft_data/_data/world" ];
 | 
				
			||||||
 | 
					        repo = "/var/lib/containers/backup/simpcraft";
 | 
				
			||||||
 | 
					        doInit = true;
 | 
				
			||||||
 | 
					        encryption.mode = "none";
 | 
				
			||||||
 | 
					        compression = "zstd,10";
 | 
				
			||||||
 | 
					        # every ~15 minutes offset from 5 minute intervals (Minecraft seems to save at precise times?)
 | 
				
			||||||
 | 
					        startAt = "*:03,17,33,47";
 | 
				
			||||||
 | 
					        prune.keep = {
 | 
				
			||||||
 | 
					          within = "12H";
 | 
				
			||||||
 | 
					          hourly = 48;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        extraOptions = [
 | 
					        # Avoid Minecraft poking the files while we back up
 | 
				
			||||||
          ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
 | 
					        preHook = rconCommand "save-off";
 | 
				
			||||||
        ];
 | 
					        postHook = rconCommand "save-on";
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    systemd = {
 | 
				
			||||||
 | 
					      services = {
 | 
				
			||||||
 | 
					        borgbackup-job-simpcraft.serviceConfig.EnvironmentFile = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,8 @@
 | 
				
			|||||||
{ lib, ... }:
 | 
					{ lib, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  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
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  nixos.systems.castle = {
 | 
					  nixos.systems.castle = {
 | 
				
			||||||
@@ -15,7 +16,7 @@ in
 | 
				
			|||||||
        ipv4 = {
 | 
					        ipv4 = {
 | 
				
			||||||
          address = net.cidr.host 40 prefixes.hi.v4;
 | 
					          address = net.cidr.host 40 prefixes.hi.v4;
 | 
				
			||||||
          mask = 22;
 | 
					          mask = 22;
 | 
				
			||||||
          gateway = null;
 | 
					          gateway = vips.hi.v4;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
        ipv6 = {
 | 
					        ipv6 = {
 | 
				
			||||||
          iid = "::3:1";
 | 
					          iid = "::3:1";
 | 
				
			||||||
@@ -47,7 +48,7 @@ in
 | 
				
			|||||||
            timeout = 10;
 | 
					            timeout = 10;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          kernelPackages = lib.my.c.kernel.latest pkgs;
 | 
					          kernelPackages = lib.my.c.kernel.latest pkgs;
 | 
				
			||||||
          kernelModules = [ "kvm-amd" ];
 | 
					          kernelModules = [ "kvm-amd" "dm-snapshot" ];
 | 
				
			||||||
          kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ];
 | 
					          kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ];
 | 
				
			||||||
          kernelPatches = [
 | 
					          kernelPatches = [
 | 
				
			||||||
            # {
 | 
					            # {
 | 
				
			||||||
@@ -57,27 +58,40 @@ in
 | 
				
			|||||||
            # }
 | 
					            # }
 | 
				
			||||||
          ];
 | 
					          ];
 | 
				
			||||||
          initrd = {
 | 
					          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 = {
 | 
					        fileSystems = {
 | 
				
			||||||
          "/boot" = {
 | 
					 | 
				
			||||||
            device = "/dev/disk/by-partuuid/8ce4248a-3ee4-f44f-801f-064a628b4d6e";
 | 
					 | 
				
			||||||
            fsType = "vfat";
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
          "/nix" = {
 | 
					          "/nix" = {
 | 
				
			||||||
            device = "/dev/disk/by-partuuid/2da23a1d-2daf-d943-b91e-fc175f3dad07";
 | 
					            device = "/dev/nvmeof/nix";
 | 
				
			||||||
            fsType = "ext4";
 | 
					            fsType = "ext4";
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					 | 
				
			||||||
          "/persist" = {
 | 
					          "/persist" = {
 | 
				
			||||||
            device = "/dev/disk/by-partuuid/f4c80d4f-a022-e941-b5d1-fe2e65e444b9";
 | 
					            device = "/dev/nvmeof/persist";
 | 
				
			||||||
            fsType = "ext4";
 | 
					            fsType = "ext4";
 | 
				
			||||||
            neededForBoot = true;
 | 
					            neededForBoot = true;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          "/home" = {
 | 
					          "/home" = {
 | 
				
			||||||
            device = "/dev/disk/by-partuuid/992a93cf-6c9c-324b-b0ce-f8eb2d1ce10d";
 | 
					            device = "/dev/nvmeof/home";
 | 
				
			||||||
            fsType = "ext4";
 | 
					            fsType = "ext4";
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
@@ -101,6 +115,12 @@ in
 | 
				
			|||||||
            dnssec = "false";
 | 
					            dnssec = "false";
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          pipewire.extraConfig.pipewire = {
 | 
				
			||||||
 | 
					            "10-buffer"."context.properties" = {
 | 
				
			||||||
 | 
					              "default.clock.quantum" = 128;
 | 
				
			||||||
 | 
					              "default.clock.max-quantum" = 128;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
          blueman.enable = true;
 | 
					          blueman.enable = true;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -114,7 +134,7 @@ in
 | 
				
			|||||||
        virtualisation.libvirtd.enable = true;
 | 
					        virtualisation.libvirtd.enable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        networking = {
 | 
					        networking = {
 | 
				
			||||||
          domain = "h.${lib.my.c.pubDomain}";
 | 
					          inherit domain;
 | 
				
			||||||
          firewall.enable = false;
 | 
					          firewall.enable = false;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -131,22 +151,17 @@ in
 | 
				
			|||||||
          qperf
 | 
					          qperf
 | 
				
			||||||
          ethtool
 | 
					          ethtool
 | 
				
			||||||
        ];
 | 
					        ];
 | 
				
			||||||
        environment.etc = {
 | 
					 | 
				
			||||||
          "pipewire/pipewire.conf.d/sample-size.conf".text = ''
 | 
					 | 
				
			||||||
            context.properties = {
 | 
					 | 
				
			||||||
              default.clock.quantum = 128
 | 
					 | 
				
			||||||
              default.clock.max-quantum = 128
 | 
					 | 
				
			||||||
            }
 | 
					 | 
				
			||||||
          '';
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        nix = {
 | 
					        nix = {
 | 
				
			||||||
          gc.automatic = false;
 | 
					          gc.automatic = false;
 | 
				
			||||||
 | 
					          settings = {
 | 
				
			||||||
 | 
					            experimental-features = [ "recursive-nix" ];
 | 
				
			||||||
 | 
					            system-features = [ "nixos-test" "benchmark" "big-parallel" "kvm" "recursive-nix" ];
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        systemd = {
 | 
					        systemd = {
 | 
				
			||||||
          network = {
 | 
					          network = {
 | 
				
			||||||
            wait-online.enable = false;
 | 
					 | 
				
			||||||
            netdevs = mkMerge [
 | 
					            netdevs = mkMerge [
 | 
				
			||||||
              (mkVLAN "lan-hi" vlans.hi)
 | 
					              (mkVLAN "lan-hi" vlans.hi)
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
@@ -163,29 +178,20 @@ in
 | 
				
			|||||||
                matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a";
 | 
					                matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a";
 | 
				
			||||||
                linkConfig = {
 | 
					                linkConfig = {
 | 
				
			||||||
                  Name = "et100g";
 | 
					                  Name = "et100g";
 | 
				
			||||||
                  MTUBytes = "9000";
 | 
					                  MTUBytes = toString lib.my.c.home.hiMTU;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            networks = {
 | 
					            networks = {
 | 
				
			||||||
              "50-lan" = {
 | 
					              "30-et100g" = {
 | 
				
			||||||
                matchConfig.Name = "et2.5g";
 | 
					 | 
				
			||||||
                DHCP = "no";
 | 
					 | 
				
			||||||
                address = [ "10.16.7.1/16" ];
 | 
					 | 
				
			||||||
              };
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
              "50-et100g" = {
 | 
					 | 
				
			||||||
                matchConfig.Name = "et100g";
 | 
					                matchConfig.Name = "et100g";
 | 
				
			||||||
                vlan = [ "lan-hi" ];
 | 
					                vlan = [ "lan-hi" ];
 | 
				
			||||||
                networkConfig.IPv6AcceptRA = false;
 | 
					                networkConfig.IPv6AcceptRA = false;
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
              "60-lan-hi" = mkMerge [
 | 
					              "40-lan-hi" = mkMerge [
 | 
				
			||||||
                (networkdAssignment "lan-hi" assignments.hi)
 | 
					                (networkdAssignment "lan-hi" assignments.hi)
 | 
				
			||||||
                {
 | 
					                # So we don't drop the IP we use to connect to NVMe-oF!
 | 
				
			||||||
                  DHCP = "yes";
 | 
					                { networkConfig.KeepConfiguration = "static"; }
 | 
				
			||||||
                  matchConfig.Name = "lan-hi";
 | 
					 | 
				
			||||||
                  linkConfig.MTUBytes = "9000";
 | 
					 | 
				
			||||||
                }
 | 
					 | 
				
			||||||
              ];
 | 
					              ];
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
@@ -205,10 +211,7 @@ in
 | 
				
			|||||||
                packages = with pkgs; [
 | 
					                packages = with pkgs; [
 | 
				
			||||||
                  jacktrip
 | 
					                  jacktrip
 | 
				
			||||||
                  qpwgraph
 | 
					                  qpwgraph
 | 
				
			||||||
                  # TODO: seems to be borked (infinite recursion???)
 | 
					                  boardie
 | 
				
			||||||
                  # (writeShellScriptBin "boardie" ''
 | 
					 | 
				
			||||||
                  #   exec pw-jack ${boardie}/bin/boardie "$@"
 | 
					 | 
				
			||||||
                  # '')
 | 
					 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -222,6 +225,7 @@ in
 | 
				
			|||||||
                    HDMI-A-1 = {
 | 
					                    HDMI-A-1 = {
 | 
				
			||||||
                      transform = "270";
 | 
					                      transform = "270";
 | 
				
			||||||
                      position = "0 0";
 | 
					                      position = "0 0";
 | 
				
			||||||
 | 
					                      bg = "${./his-team-player.jpg} fill";
 | 
				
			||||||
                    };
 | 
					                    };
 | 
				
			||||||
                    DP-1 = {
 | 
					                    DP-1 = {
 | 
				
			||||||
                      mode = "2560x1440@170Hz";
 | 
					                      mode = "2560x1440@170Hz";
 | 
				
			||||||
@@ -243,11 +247,19 @@ in
 | 
				
			|||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          #deploy.generate.system.mode = "boot";
 | 
					          #deploy.generate.system.mode = "boot";
 | 
				
			||||||
          deploy.node.hostname = "castle.box.${config.networking.domain}";
 | 
					 | 
				
			||||||
          secrets = {
 | 
					          secrets = {
 | 
				
			||||||
            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlVuTzKObeaUuPocCF41IO/8X+443lzUJLuCIclt2vr";
 | 
					            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 = {
 | 
					          firewall = {
 | 
				
			||||||
            enable = false;
 | 
					            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" ];
 | 
					            extraOptions = [ "-A /var/log/smartd/" "--interval=600" ];
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          udev.extraRules = ''
 | 
					          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}
 | 
					                  VLANId=${toString vlans.hi}
 | 
				
			||||||
                  LinkState=yes
 | 
					                  LinkState=yes
 | 
				
			||||||
                  MACAddress=52:54:00:ac:15:a9
 | 
					                  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;
 | 
					              "60-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -66,6 +66,7 @@ in
 | 
				
			|||||||
            ];
 | 
					            ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            services = {
 | 
					            services = {
 | 
				
			||||||
 | 
					              fstrim.enable = true;
 | 
				
			||||||
              netdata.enable = true;
 | 
					              netdata.enable = true;
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,6 +129,12 @@ in
 | 
				
			|||||||
            hostnqn =
 | 
					            hostnqn =
 | 
				
			||||||
              "nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b";
 | 
					              "nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b";
 | 
				
			||||||
            serial = "SPDK00000000000002";
 | 
					            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 = [
 | 
					  imports = [
 | 
				
			||||||
    ./cellar
 | 
					    ./cellar
 | 
				
			||||||
    ./river.nix
 | 
					    ./river.nix
 | 
				
			||||||
 | 
					    ./sfh
 | 
				
			||||||
  ];
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }:
 | 
					  nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }:
 | 
				
			||||||
@@ -57,11 +58,11 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    systemd.services =
 | 
					    systemd.services =
 | 
				
			||||||
    let
 | 
					    let
 | 
				
			||||||
      awaitCellar = {
 | 
					      awaitVM = system: {
 | 
				
			||||||
        after = [ "vm@cellar.service" ];
 | 
					        after = [ "vm@${system}.service" ];
 | 
				
			||||||
        bindsTo = [ "vm@cellar.service" ];
 | 
					        bindsTo = [ "vm@${system}.service" ];
 | 
				
			||||||
        preStart = ''
 | 
					        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
 | 
					            sleep 1
 | 
				
			||||||
          done
 | 
					          done
 | 
				
			||||||
        '';
 | 
					        '';
 | 
				
			||||||
@@ -81,13 +82,13 @@
 | 
				
			|||||||
        vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
 | 
					        vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
 | 
				
			||||||
      in
 | 
					      in
 | 
				
			||||||
      mkMerge [
 | 
					      mkMerge [
 | 
				
			||||||
        awaitCellar
 | 
					        (awaitVM "cellar")
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
          requires = [ vtapUnit ];
 | 
					          requires = [ vtapUnit ];
 | 
				
			||||||
          after = [ vtapUnit ];
 | 
					          after = [ vtapUnit ];
 | 
				
			||||||
        }
 | 
					        }
 | 
				
			||||||
      ];
 | 
					      ];
 | 
				
			||||||
      "vm@sfh" = awaitCellar;
 | 
					      "vm@sfh" = (awaitVM "river");
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    my = {
 | 
					    my = {
 | 
				
			||||||
@@ -182,6 +183,10 @@
 | 
				
			|||||||
                index = 0;
 | 
					                index = 0;
 | 
				
			||||||
                hostBDF = "44:00.3";
 | 
					                hostBDF = "44:00.3";
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					              et100g0vf3 = {
 | 
				
			||||||
 | 
					                index = 1;
 | 
				
			||||||
 | 
					                hostBDF = "44:00.4";
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -10,18 +10,7 @@
 | 
				
			|||||||
    let
 | 
					    let
 | 
				
			||||||
      inherit (lib.my) networkdAssignment mkVLAN;
 | 
					      inherit (lib.my) networkdAssignment mkVLAN;
 | 
				
			||||||
      inherit (lib.my.c) networkd;
 | 
					      inherit (lib.my.c) networkd;
 | 
				
			||||||
      inherit (lib.my.c.home) vlans;
 | 
					      inherit (lib.my.c.home) vlans domain prefixes roceBootModules;
 | 
				
			||||||
 | 
					 | 
				
			||||||
      lanLink = {
 | 
					 | 
				
			||||||
        matchConfig = {
 | 
					 | 
				
			||||||
          Driver = "mlx5_core";
 | 
					 | 
				
			||||||
          PermanentMACAddress = "52:54:00:8a:8a:f2";
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
        linkConfig = {
 | 
					 | 
				
			||||||
          Name = "lan";
 | 
					 | 
				
			||||||
          MTUBytes = toString lib.my.c.home.hiMTU;
 | 
					 | 
				
			||||||
        };
 | 
					 | 
				
			||||||
      };
 | 
					 | 
				
			||||||
    in
 | 
					    in
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      imports = [
 | 
					      imports = [
 | 
				
			||||||
@@ -30,29 +19,17 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
      config = {
 | 
					      config = {
 | 
				
			||||||
        boot = {
 | 
					        boot = {
 | 
				
			||||||
          kernelModules = [ "kvm-intel" ];
 | 
					          kernelModules = [ "kvm-amd" ];
 | 
				
			||||||
          kernelParams = [ "console=ttyS0,115200n8" ];
 | 
					          kernelParams = [ "console=ttyS0,115200n8" ];
 | 
				
			||||||
          initrd = {
 | 
					          initrd = {
 | 
				
			||||||
            availableKernelModules = [
 | 
					            availableKernelModules = [
 | 
				
			||||||
              "virtio_pci" "ahci" "sr_mod" "virtio_blk"
 | 
					              "virtio_pci" "ahci" "sr_mod" "virtio_blk"
 | 
				
			||||||
              "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" "8021q"
 | 
					              "8021q"
 | 
				
			||||||
              "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma"
 | 
					            ] ++ roceBootModules;
 | 
				
			||||||
            ];
 | 
					            kernelModules = [ "dm-snapshot" ];
 | 
				
			||||||
            kernelModules = [ "dm-snapshot" "nvme-fabrics" ];
 | 
					 | 
				
			||||||
            systemd = {
 | 
					            systemd = {
 | 
				
			||||||
              extraBin = with pkgs; {
 | 
					 | 
				
			||||||
                dmesg = "${util-linux}/bin/dmesg";
 | 
					 | 
				
			||||||
                ip = "${iproute2}/bin/ip";
 | 
					 | 
				
			||||||
              };
 | 
					 | 
				
			||||||
              extraConfig = ''
 | 
					 | 
				
			||||||
                DefaultTimeoutStartSec=50
 | 
					 | 
				
			||||||
                DefaultDeviceTimeoutSec=50
 | 
					 | 
				
			||||||
              '';
 | 
					 | 
				
			||||||
              network = {
 | 
					              network = {
 | 
				
			||||||
                enable = true;
 | 
					                # Don't need to put the link config here, they're copied from main config
 | 
				
			||||||
                wait-online.enable = true;
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
                links."10-lan" = lanLink;
 | 
					 | 
				
			||||||
                netdevs = mkVLAN "lan-hi" vlans.hi;
 | 
					                netdevs = mkVLAN "lan-hi" vlans.hi;
 | 
				
			||||||
                networks = {
 | 
					                networks = {
 | 
				
			||||||
                  "20-lan" = {
 | 
					                  "20-lan" = {
 | 
				
			||||||
@@ -70,9 +47,6 @@
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
        hardware = {
 | 
					        hardware = {
 | 
				
			||||||
          enableRedistributableFirmware = true;
 | 
					          enableRedistributableFirmware = true;
 | 
				
			||||||
          cpu = {
 | 
					 | 
				
			||||||
            intel.updateMicrocode = true;
 | 
					 | 
				
			||||||
          };
 | 
					 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fileSystems = {
 | 
					        fileSystems = {
 | 
				
			||||||
@@ -96,6 +70,7 @@
 | 
				
			|||||||
            boot.thin.enable = true;
 | 
					            boot.thin.enable = true;
 | 
				
			||||||
            dmeventd.enable = true;
 | 
					            dmeventd.enable = true;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					          fstrim.enable = true;
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        systemd.network = {
 | 
					        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!
 | 
					          # 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";
 | 
					          deploy.node.hostname = "192.168.68.1";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										5
									
								
								nixos/boxes/home/palace/vms/sfh/containers/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								nixos/boxes/home/palace/vms/sfh/containers/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,5 @@
 | 
				
			|||||||
 | 
					{
 | 
				
			||||||
 | 
					  imports = [
 | 
				
			||||||
 | 
					    ./unifi.nix
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										64
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										64
									
								
								nixos/boxes/home/palace/vms/sfh/containers/unifi.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,64 @@
 | 
				
			|||||||
 | 
					{ lib, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
 | 
					  inherit (lib.my.c.home) domain prefixes vips hiMTU;
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  nixos.systems.unifi = { config, ... }: {
 | 
				
			||||||
 | 
					    system = "x86_64-linux";
 | 
				
			||||||
 | 
					    nixpkgs = "mine";
 | 
				
			||||||
 | 
					    rendered = config.configuration.config.my.asContainer;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assignments = {
 | 
				
			||||||
 | 
					      hi = {
 | 
				
			||||||
 | 
					        name = "unifi-ctr";
 | 
				
			||||||
 | 
					        inherit domain;
 | 
				
			||||||
 | 
					        mtu = hiMTU;
 | 
				
			||||||
 | 
					        ipv4 = {
 | 
				
			||||||
 | 
					          address = net.cidr.host 100 prefixes.hi.v4;
 | 
				
			||||||
 | 
					          mask = 22;
 | 
				
			||||||
 | 
					          gateway = vips.hi.v4;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        ipv6 = {
 | 
				
			||||||
 | 
					          iid = "::5:1";
 | 
				
			||||||
 | 
					          address = net.cidr.host (65536*5+1) prefixes.hi.v6;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    configuration = { lib, config, pkgs, assignments, ... }:
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					      inherit (lib) mkMerge mkIf mkForce;
 | 
				
			||||||
 | 
					      inherit (lib.my) networkdAssignment;
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      config = {
 | 
				
			||||||
 | 
					        my = {
 | 
				
			||||||
 | 
					          deploy.enable = false;
 | 
				
			||||||
 | 
					          server.enable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          secrets = {
 | 
				
			||||||
 | 
					            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdgcziQki/RH7E+NH2bYnzSVKaJ27905Yo5TcOjSh/U";
 | 
				
			||||||
 | 
					            files = { };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          firewall = {
 | 
				
			||||||
 | 
					            tcp.allowed = [ 8443 ];
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        systemd = {
 | 
				
			||||||
 | 
					          network.networks."80-container-host0" = networkdAssignment "host0" assignments.hi;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        services = {
 | 
				
			||||||
 | 
					          unifi = {
 | 
				
			||||||
 | 
					            enable = true;
 | 
				
			||||||
 | 
					            openFirewall = true;
 | 
				
			||||||
 | 
					            unifiPackage = pkgs.unifi8;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										157
									
								
								nixos/boxes/home/palace/vms/sfh/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										157
									
								
								nixos/boxes/home/palace/vms/sfh/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,157 @@
 | 
				
			|||||||
 | 
					{ lib, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
 | 
					  inherit (lib.my.c.home) domain prefixes vips hiMTU roceBootModules;
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  imports = [ ./containers ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  config.nixos.systems.sfh = {
 | 
				
			||||||
 | 
					    system = "x86_64-linux";
 | 
				
			||||||
 | 
					    nixpkgs = "mine";
 | 
				
			||||||
 | 
					    home-manager = "mine";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    assignments = {
 | 
				
			||||||
 | 
					      hi = {
 | 
				
			||||||
 | 
					        inherit domain;
 | 
				
			||||||
 | 
					        mtu = hiMTU;
 | 
				
			||||||
 | 
					        ipv4 = {
 | 
				
			||||||
 | 
					          address = net.cidr.host 81 prefixes.hi.v4;
 | 
				
			||||||
 | 
					          mask = 22;
 | 
				
			||||||
 | 
					          gateway = vips.hi.v4;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					        ipv6 = {
 | 
				
			||||||
 | 
					          iid = "::4:2";
 | 
				
			||||||
 | 
					          address = net.cidr.host (65536*4+2) prefixes.hi.v6;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    configuration = { lib, modulesPath, pkgs, config, assignments, allAssignments, ... }:
 | 
				
			||||||
 | 
					    let
 | 
				
			||||||
 | 
					      inherit (lib) mapAttrs mkMerge;
 | 
				
			||||||
 | 
					      inherit (lib.my) networkdAssignment;
 | 
				
			||||||
 | 
					      inherit (lib.my.c) networkd;
 | 
				
			||||||
 | 
					      inherit (lib.my.c.home) domain;
 | 
				
			||||||
 | 
					    in
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      imports = [
 | 
				
			||||||
 | 
					        "${modulesPath}/profiles/qemu-guest.nix"
 | 
				
			||||||
 | 
					      ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      config = {
 | 
				
			||||||
 | 
					        boot = {
 | 
				
			||||||
 | 
					          kernelModules = [ "kvm-amd" ];
 | 
				
			||||||
 | 
					          kernelParams = [ "console=ttyS0,115200n8" ];
 | 
				
			||||||
 | 
					          initrd = {
 | 
				
			||||||
 | 
					            availableKernelModules = [
 | 
				
			||||||
 | 
					              "virtio_pci" "ahci" "sr_mod" "virtio_blk"
 | 
				
			||||||
 | 
					            ] ++ roceBootModules;
 | 
				
			||||||
 | 
					            kernelModules = [ "dm-snapshot" ];
 | 
				
			||||||
 | 
					            systemd = {
 | 
				
			||||||
 | 
					              network = {
 | 
				
			||||||
 | 
					                networks = {
 | 
				
			||||||
 | 
					                  "20-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
 | 
				
			||||||
 | 
					                };
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        hardware = {
 | 
				
			||||||
 | 
					          enableRedistributableFirmware = true;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        fileSystems = {
 | 
				
			||||||
 | 
					          "/nix" = {
 | 
				
			||||||
 | 
					            device = "/dev/main/nix";
 | 
				
			||||||
 | 
					            fsType = "ext4";
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					          "/persist" = {
 | 
				
			||||||
 | 
					            device = "/dev/main/persist";
 | 
				
			||||||
 | 
					            fsType = "ext4";
 | 
				
			||||||
 | 
					            neededForBoot = true;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        networking = { inherit domain; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        services = {
 | 
				
			||||||
 | 
					          lvm = {
 | 
				
			||||||
 | 
					            boot.thin.enable = true;
 | 
				
			||||||
 | 
					            dmeventd.enable = true;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        systemd.network = {
 | 
				
			||||||
 | 
					          links = {
 | 
				
			||||||
 | 
					            "10-lan-hi" = {
 | 
				
			||||||
 | 
					              matchConfig = {
 | 
				
			||||||
 | 
					                Driver = "mlx5_core";
 | 
				
			||||||
 | 
					                PermanentMACAddress = "52:54:00:ac:15:a9";
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              linkConfig = {
 | 
				
			||||||
 | 
					                Name = "lan-hi";
 | 
				
			||||||
 | 
					                MTUBytes = toString lib.my.c.home.hiMTU;
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            "10-lan-hi-ctrs" = {
 | 
				
			||||||
 | 
					              matchConfig = {
 | 
				
			||||||
 | 
					                Driver = "mlx5_core";
 | 
				
			||||||
 | 
					                PermanentMACAddress = "52:54:00:90:34:95";
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					              linkConfig = {
 | 
				
			||||||
 | 
					                Name = "lan-hi-ctrs";
 | 
				
			||||||
 | 
					                MTUBytes = toString lib.my.c.home.hiMTU;
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          networks = {
 | 
				
			||||||
 | 
					            "30-lan-hi" = mkMerge [
 | 
				
			||||||
 | 
					              (networkdAssignment "lan-hi" assignments.hi)
 | 
				
			||||||
 | 
					              # So we don't drop the IP we use to connect to NVMe-oF!
 | 
				
			||||||
 | 
					              { networkConfig.KeepConfiguration = "static"; }
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					            "30-lan-hi-ctrs" = {
 | 
				
			||||||
 | 
					              matchConfig.Name = "lan-hi-ctrs";
 | 
				
			||||||
 | 
					              linkConfig.RequiredForOnline = "no";
 | 
				
			||||||
 | 
					              networkConfig = networkd.noL3;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        my = {
 | 
				
			||||||
 | 
					          secrets = {
 | 
				
			||||||
 | 
					            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAaav5Se1E/AbqEXmADryVszYfNDscyP6jrWioN57R7";
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					          server.enable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          netboot.client = {
 | 
				
			||||||
 | 
					            enable = true;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					          nvme = {
 | 
				
			||||||
 | 
					            uuid = "85d7df36-0de0-431b-b06e-51f7c0a455b4";
 | 
				
			||||||
 | 
					            boot = {
 | 
				
			||||||
 | 
					              nqn = "nqn.2016-06.io.spdk:sfh";
 | 
				
			||||||
 | 
					              address = "192.168.68.80";
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          containers.instances =
 | 
				
			||||||
 | 
					          let
 | 
				
			||||||
 | 
					            instances = {
 | 
				
			||||||
 | 
					              unifi = {};
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          in
 | 
				
			||||||
 | 
					          mkMerge [
 | 
				
			||||||
 | 
					            instances
 | 
				
			||||||
 | 
					            (mapAttrs (n: i: {
 | 
				
			||||||
 | 
					              networking.macVLAN = "lan-hi-ctrs";
 | 
				
			||||||
 | 
					            }) instances)
 | 
				
			||||||
 | 
					          ];
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,6 +1,7 @@
 | 
				
			|||||||
index: { lib, allAssignments, ... }:
 | 
					index: { lib, allAssignments, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (builtins) elemAt;
 | 
					  inherit (builtins) elemAt;
 | 
				
			||||||
 | 
					  inherit (lib) concatStringsSep;
 | 
				
			||||||
  inherit (lib.my) net mkVLAN;
 | 
					  inherit (lib.my) net mkVLAN;
 | 
				
			||||||
  inherit (lib.my.c) pubDomain;
 | 
					  inherit (lib.my.c) pubDomain;
 | 
				
			||||||
  inherit (lib.my.c.home) domain vlans prefixes vips routers routersPubV4;
 | 
					  inherit (lib.my.c.home) domain vlans prefixes vips routers routersPubV4;
 | 
				
			||||||
@@ -148,19 +149,55 @@ in
 | 
				
			|||||||
                };
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            nginx.enable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            tailscale =
 | 
				
			||||||
 | 
					            let
 | 
				
			||||||
 | 
					              advRoutes = concatStringsSep "," [
 | 
				
			||||||
 | 
					                prefixes.all.v4
 | 
				
			||||||
 | 
					                prefixes.all.v6
 | 
				
			||||||
 | 
					              ];
 | 
				
			||||||
 | 
					            in
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					              enable = true;
 | 
				
			||||||
 | 
					              authKeyFile = config.age.secrets."tailscale-auth.key".path;
 | 
				
			||||||
 | 
					              openFirewall = true;
 | 
				
			||||||
 | 
					              interfaceName = "tailscale0";
 | 
				
			||||||
 | 
					              extraUpFlags = [
 | 
				
			||||||
 | 
					                "--operator=${config.my.user.config.name}"
 | 
				
			||||||
 | 
					                "--login-server=https://ts.nul.ie"
 | 
				
			||||||
 | 
					                "--netfilter-mode=off"
 | 
				
			||||||
 | 
					                "--advertise-exit-node"
 | 
				
			||||||
 | 
					                "--advertise-routes=${advRoutes}"
 | 
				
			||||||
 | 
					                "--accept-routes=false"
 | 
				
			||||||
 | 
					              ];
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          networking.domain = "h.${pubDomain}";
 | 
					          networking = { inherit domain; };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          systemd.services = {
 | 
					          systemd.services =
 | 
				
			||||||
            ipsec =
 | 
					 | 
				
			||||||
          let
 | 
					          let
 | 
				
			||||||
            waitOnline = "systemd-networkd-wait-online@wan.service";
 | 
					            waitOnline = "systemd-networkd-wait-online@wan.service";
 | 
				
			||||||
          in
 | 
					          in
 | 
				
			||||||
          {
 | 
					          {
 | 
				
			||||||
 | 
					            ipsec = {
 | 
				
			||||||
              after = [ waitOnline ];
 | 
					              after = [ waitOnline ];
 | 
				
			||||||
              requires = [ waitOnline ];
 | 
					              requires = [ waitOnline ];
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            ipv6-clear-default-route = {
 | 
				
			||||||
 | 
					              description = "Clear IPv6 RA default route";
 | 
				
			||||||
 | 
					              after = [ waitOnline ];
 | 
				
			||||||
 | 
					              requires = [ waitOnline ];
 | 
				
			||||||
 | 
					              script = ''
 | 
				
			||||||
 | 
					                # Seems like we can sometimes pick up a default route somehow...
 | 
				
			||||||
 | 
					                ${pkgs.iproute2}/bin/ip -6 route del default via fe80::1 || true
 | 
				
			||||||
 | 
					              '';
 | 
				
			||||||
 | 
					              serviceConfig.Type = "oneshot";
 | 
				
			||||||
 | 
					              wantedBy = [ "multi-user.target" ];
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          systemd.network = {
 | 
					          systemd.network = {
 | 
				
			||||||
@@ -213,8 +250,8 @@ in
 | 
				
			|||||||
                  networkConfig = networkd.noL3;
 | 
					                  networkConfig = networkd.noL3;
 | 
				
			||||||
                  extraConfig = ''
 | 
					                  extraConfig = ''
 | 
				
			||||||
                    [CAKE]
 | 
					                    [CAKE]
 | 
				
			||||||
                    Bandwidth=235M
 | 
					                    Bandwidth=490M
 | 
				
			||||||
                    RTTSec=10ms
 | 
					                    RTTSec=50ms
 | 
				
			||||||
                    PriorityQueueingPreset=besteffort
 | 
					                    PriorityQueueingPreset=besteffort
 | 
				
			||||||
                    # DOCSIS preset
 | 
					                    # DOCSIS preset
 | 
				
			||||||
                    OverheadBytes=18
 | 
					                    OverheadBytes=18
 | 
				
			||||||
@@ -237,8 +274,8 @@ in
 | 
				
			|||||||
                    extraConfig = ''
 | 
					                    extraConfig = ''
 | 
				
			||||||
                      [CAKE]
 | 
					                      [CAKE]
 | 
				
			||||||
                      Parent=root
 | 
					                      Parent=root
 | 
				
			||||||
                      Bandwidth=24M
 | 
					                      Bandwidth=48M
 | 
				
			||||||
                      RTTSec=1ms
 | 
					                      RTTSec=50ms
 | 
				
			||||||
                    '';
 | 
					                    '';
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
@@ -267,15 +304,6 @@ in
 | 
				
			|||||||
                        Destination = lib.my.c.colony.prefixes.all.v4;
 | 
					                        Destination = lib.my.c.colony.prefixes.all.v4;
 | 
				
			||||||
                        Gateway = allAssignments.estuary.as211024.ipv4.address;
 | 
					                        Gateway = allAssignments.estuary.as211024.ipv4.address;
 | 
				
			||||||
                      }
 | 
					                      }
 | 
				
			||||||
 | 
					 | 
				
			||||||
                      {
 | 
					 | 
				
			||||||
                        Destination = lib.my.c.tailscale.prefix.v4;
 | 
					 | 
				
			||||||
                        Gateway = allAssignments.britway.as211024.ipv4.address;
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                      {
 | 
					 | 
				
			||||||
                        Destination = lib.my.c.tailscale.prefix.v6;
 | 
					 | 
				
			||||||
                        Gateway = allAssignments.britway.as211024.ipv6.address;
 | 
					 | 
				
			||||||
                      }
 | 
					 | 
				
			||||||
                    ];
 | 
					                    ];
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
                ];
 | 
					                ];
 | 
				
			||||||
@@ -302,6 +330,7 @@ in
 | 
				
			|||||||
            secrets = {
 | 
					            secrets = {
 | 
				
			||||||
              files = {
 | 
					              files = {
 | 
				
			||||||
                "l2mesh/as211024.key" = {};
 | 
					                "l2mesh/as211024.key" = {};
 | 
				
			||||||
 | 
					                "tailscale-auth.key" = {};
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -311,7 +340,7 @@ in
 | 
				
			|||||||
              };
 | 
					              };
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            firewall = {
 | 
					            firewall = {
 | 
				
			||||||
              trustedInterfaces = [ "lan-hi" "lan-lo" ];
 | 
					              trustedInterfaces = [ "lan-hi" "lan-lo" "tailscale0" ];
 | 
				
			||||||
              udp.allowed = [ 5353 ];
 | 
					              udp.allowed = [ 5353 ];
 | 
				
			||||||
              tcp.allowed = [ 5353 ];
 | 
					              tcp.allowed = [ 5353 ];
 | 
				
			||||||
              nat = {
 | 
					              nat = {
 | 
				
			||||||
@@ -358,6 +387,16 @@ in
 | 
				
			|||||||
                    return
 | 
					                    return
 | 
				
			||||||
                  }
 | 
					                  }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                  chain forward-early {
 | 
				
			||||||
 | 
					                    type filter hook forward priority -1; policy accept;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # MSS clamping to workaround IPv6 PMTUD being broken...
 | 
				
			||||||
 | 
					                    tcp flags syn tcp option maxseg size set rt mtu counter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                    # More Disney+ discrimination...
 | 
				
			||||||
 | 
					                    # TODO: This prefix could change (random AWS block)
 | 
				
			||||||
 | 
					                    ip6 daddr 2600:9000:2245::/48 drop
 | 
				
			||||||
 | 
					                  }
 | 
				
			||||||
                  chain forward {
 | 
					                  chain forward {
 | 
				
			||||||
                    ${lib.my.c.as211024.nftTrust}
 | 
					                    ${lib.my.c.as211024.nftTrust}
 | 
				
			||||||
                    iifname lan-untrusted jump filter-untrusted
 | 
					                    iifname lan-untrusted jump filter-untrusted
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -61,6 +61,19 @@ in
 | 
				
			|||||||
          webserver = true;
 | 
					          webserver = true;
 | 
				
			||||||
          webserver-address = "::";
 | 
					          webserver-address = "::";
 | 
				
			||||||
          webserver-allow-from = [ "127.0.0.1" "::1" ];
 | 
					          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}";
 | 
					              hostname = "${otherName}.${config.networking.domain}";
 | 
				
			||||||
              server = net.cidr.host (otherIndex + 1) prefixes.hi.v4;
 | 
					              server = net.cidr.host (otherIndex + 1) prefixes.hi.v4;
 | 
				
			||||||
            }}
 | 
					            }}
 | 
				
			||||||
            ${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6}
 | 
					            ${elemAt routers 0} IN AAAA ${allAssignments."${elemAt routers 0}".as211024.ipv6.address}
 | 
				
			||||||
            ${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6}
 | 
					            ${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 ns1
 | 
				
			||||||
            @ IN NS ns2
 | 
					            @ IN NS ns2
 | 
				
			||||||
@@ -182,8 +196,10 @@ in
 | 
				
			|||||||
            dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
 | 
					            dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
 | 
				
			||||||
            dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6}
 | 
					            dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            ;ap0 IN A ${net.cidr.host 12 prefixes.hi.v4}
 | 
					            shytzel IN A ${net.cidr.host 12 prefixes.core.v4}
 | 
				
			||||||
            ;ap0 IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
 | 
					
 | 
				
			||||||
 | 
					            wave IN A ${net.cidr.host 12 prefixes.hi.v4}
 | 
				
			||||||
 | 
					            ; wave IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
 | 
				
			||||||
            vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
 | 
					            vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
 | 
				
			||||||
            vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6}
 | 
					            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
 | 
					let
 | 
				
			||||||
  inherit (lib) mkForce;
 | 
					  inherit (lib) mkForce;
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  inherit (lib.my) net netbootKeaClientClasses;
 | 
				
			||||||
  inherit (lib.my.c.home) domain prefixes vips hiMTU;
 | 
					  inherit (lib.my.c.home) domain prefixes vips hiMTU;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  dns-servers = [
 | 
					  dns-servers = [
 | 
				
			||||||
@@ -26,7 +26,11 @@ in
 | 
				
			|||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  systemd.services = {
 | 
					  systemd.services = {
 | 
				
			||||||
    kea-dhcp4-server.serviceConfig.DynamicUser = mkForce false;
 | 
					    kea-dhcp4-server.serviceConfig = {
 | 
				
			||||||
 | 
					      # Sometimes interfaces might not be ready in time and Kea doesn't like that
 | 
				
			||||||
 | 
					      Restart = "on-failure";
 | 
				
			||||||
 | 
					      DynamicUser = mkForce false;
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
    kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false;
 | 
					    kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -59,6 +63,14 @@ in
 | 
				
			|||||||
              always-send = true;
 | 
					              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 = [
 | 
					          subnet4 = [
 | 
				
			||||||
            {
 | 
					            {
 | 
				
			||||||
              id = 1;
 | 
					              id = 1;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,52 +1,88 @@
 | 
				
			|||||||
index: { lib, pkgs, config, ... }:
 | 
					index: { lib, pkgs, config, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (builtins) attrNames concatMap;
 | 
					  inherit (builtins) attrNames concatMap length;
 | 
				
			||||||
  inherit (lib) optional;
 | 
					  inherit (lib) optional concatMapStringsSep;
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
  inherit (lib.my.c.home) prefixes vips;
 | 
					  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}";
 | 
					  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})}";
 | 
					      addr = "${vips.${vlan}.${family}}/${toString (net.cidr.length prefixes.${vlan}.${family})}";
 | 
				
			||||||
      dev = vlanIface vlan;
 | 
					      dev = vlanIface vlan;
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ] ++ (optional (family == "v6") {
 | 
					  ]) (attrNames vips);
 | 
				
			||||||
    addr = "fe80::1/64";
 | 
					 | 
				
			||||||
    dev = vlanIface vlan;
 | 
					 | 
				
			||||||
  })) (attrNames vips);
 | 
					 | 
				
			||||||
  mkVRRP = family: routerId: {
 | 
					  mkVRRP = family: routerId: {
 | 
				
			||||||
    state = if index == 0 then "MASTER" else "BACKUP";
 | 
					    state = if index == 0 then "MASTER" else "BACKUP";
 | 
				
			||||||
    interface = "lan-core";
 | 
					    interface = "lan-core";
 | 
				
			||||||
    priority = 255 - index;
 | 
					    priority = 255 - index;
 | 
				
			||||||
    virtualRouterId = routerId;
 | 
					    virtualRouterId = routerId;
 | 
				
			||||||
    virtualIps = vrrpIPs family;
 | 
					    virtualIps = vrrpIPs family;
 | 
				
			||||||
    extraConfig = ''
 | 
					    trackScripts = [ "${family}Alive" ];
 | 
				
			||||||
      notify_master "${config.systemd.package}/bin/systemctl start radvd.service"
 | 
					 | 
				
			||||||
      notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service"
 | 
					 | 
				
			||||||
    '';
 | 
					 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
in
 | 
					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 = {
 | 
					  services = {
 | 
				
			||||||
    keepalived = {
 | 
					    keepalived = {
 | 
				
			||||||
      enable = true;
 | 
					      enable = true;
 | 
				
			||||||
 | 
					      enableScriptSecurity = true;
 | 
				
			||||||
      extraGlobalDefs = ''
 | 
					      extraGlobalDefs = ''
 | 
				
			||||||
        vrrp_version 3
 | 
					        vrrp_version 3
 | 
				
			||||||
        nftables keepalived
 | 
					        nftables keepalived
 | 
				
			||||||
      '';
 | 
					      '';
 | 
				
			||||||
      vrrpInstances = {
 | 
					      vrrpScripts = {
 | 
				
			||||||
        v4 = mkVRRP "v4" 51;
 | 
					        v4Alive = pingScriptFor "v4" [ "1.1.1.1" "8.8.8.8" "216.218.236.2" ];
 | 
				
			||||||
        v6 = mkVRRP "v6" 52;
 | 
					        v6Alive = pingScriptFor "v6" [ "2606:4700:4700::1111" "2001:4860:4860::8888" "2600::" ];
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					      vrrpInstances = {
 | 
				
			||||||
 | 
					        v4 = mkVRRP "v4" 51 // {
 | 
				
			||||||
          extraConfig = ''
 | 
					          extraConfig = ''
 | 
				
			||||||
        vrrp_sync_group main {
 | 
					            notify_master "${config.systemd.package}/bin/systemctl start tailscaled.service" root
 | 
				
			||||||
          group {
 | 
					            notify_backup "${config.systemd.package}/bin/systemctl stop tailscaled.service" root
 | 
				
			||||||
            v4
 | 
					          '';
 | 
				
			||||||
            v6
 | 
					        };
 | 
				
			||||||
          }
 | 
					        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
 | 
				
			||||||
          '';
 | 
					          '';
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					      # 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 = {
 | 
					        systemd.network = {
 | 
				
			||||||
          netdevs = {
 | 
					          netdevs = {
 | 
				
			||||||
            "25-lan" = {
 | 
					            "25-lan" = {
 | 
				
			||||||
@@ -123,7 +155,7 @@
 | 
				
			|||||||
            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb";
 | 
					            key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb";
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
          server.enable = true;
 | 
					          server.enable = true;
 | 
				
			||||||
          deploy.node.hostname = "192.168.68.2";
 | 
					          # deploy.node.hostname = "192.168.68.2";
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -65,7 +65,13 @@ in
 | 
				
			|||||||
        systemd = {
 | 
					        systemd = {
 | 
				
			||||||
          services = {
 | 
					          services = {
 | 
				
			||||||
            jackett.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
					            jackett.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
					            transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
 | 
				
			||||||
 | 
					            # https://github.com/NixOS/nixpkgs/issues/258793#issuecomment-1748168206
 | 
				
			||||||
 | 
					            transmission.serviceConfig = {
 | 
				
			||||||
 | 
					              RootDirectoryStartOnly = lib.mkForce false;
 | 
				
			||||||
 | 
					              RootDirectory = lib.mkForce "";
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            radarr.serviceConfig.UMask = "0002";
 | 
					            radarr.serviceConfig.UMask = "0002";
 | 
				
			||||||
            sonarr.serviceConfig.UMask = "0002";
 | 
					            sonarr.serviceConfig.UMask = "0002";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,6 +2,7 @@
 | 
				
			|||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib) mkMerge mkIf;
 | 
					  inherit (lib) mkMerge mkIf;
 | 
				
			||||||
  inherit (lib.my) networkdAssignment;
 | 
					  inherit (lib.my) networkdAssignment;
 | 
				
			||||||
 | 
					  inherit (lib.my.c.kelder) ipv4MTU;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  wg = {
 | 
					  wg = {
 | 
				
			||||||
    keyFile = "kelder/acquisition/airvpn-privkey";
 | 
					    keyFile = "kelder/acquisition/airvpn-privkey";
 | 
				
			||||||
@@ -89,6 +90,7 @@ in
 | 
				
			|||||||
              (networkdAssignment "host0" assignments.internal)
 | 
					              (networkdAssignment "host0" assignments.internal)
 | 
				
			||||||
              {
 | 
					              {
 | 
				
			||||||
                networkConfig.DNSDefaultRoute = false;
 | 
					                networkConfig.DNSDefaultRoute = false;
 | 
				
			||||||
 | 
					                linkConfig.MTUBytes = toString ipv4MTU;
 | 
				
			||||||
              }
 | 
					              }
 | 
				
			||||||
            ];
 | 
					            ];
 | 
				
			||||||
            "90-vpn" = with wg; {
 | 
					            "90-vpn" = with wg; {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -92,17 +92,17 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
          nextcloud = {
 | 
					          nextcloud = {
 | 
				
			||||||
            enable = true;
 | 
					            enable = true;
 | 
				
			||||||
            package = pkgs.nextcloud28;
 | 
					            package = pkgs.nextcloud29;
 | 
				
			||||||
            datadir = "/mnt/storage/nextcloud";
 | 
					            datadir = "/mnt/storage/nextcloud";
 | 
				
			||||||
            hostName = "cloud.${domain}";
 | 
					            hostName = "cloud.${domain}";
 | 
				
			||||||
            https = true;
 | 
					            https = true;
 | 
				
			||||||
            config = {
 | 
					            config = {
 | 
				
			||||||
              extraTrustedDomains = [ "cloud-local.${domain}" ];
 | 
					 | 
				
			||||||
              adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path;
 | 
					              adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path;
 | 
				
			||||||
              defaultPhoneRegion = "IE";
 | 
					 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            extraOptions = {
 | 
					            settings = {
 | 
				
			||||||
              updatechecker = false;
 | 
					              updatechecker = false;
 | 
				
			||||||
 | 
					              trusted_domains = [ "cloud-local.${domain}" ];
 | 
				
			||||||
 | 
					              default_phone_region = "IE";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -84,6 +84,7 @@ in
 | 
				
			|||||||
            c
 | 
					            c
 | 
				
			||||||
          ];
 | 
					          ];
 | 
				
			||||||
          acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}";
 | 
					          acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}";
 | 
				
			||||||
 | 
					          # This is kinda borked because Virgin Media filters DNS responses with local IPs...
 | 
				
			||||||
          localRedirect = to: ''
 | 
					          localRedirect = to: ''
 | 
				
			||||||
            rewrite_by_lua_block {
 | 
					            rewrite_by_lua_block {
 | 
				
			||||||
              if ngx.var.remote_addr == pub_ip then
 | 
					              if ngx.var.remote_addr == pub_ip then
 | 
				
			||||||
@@ -103,7 +104,7 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
            "monitor.${domain}" = withAuth {
 | 
					            "monitor.${domain}" = withAuth {
 | 
				
			||||||
              serverAliases = [ "monitor-local.${domain}" ];
 | 
					              serverAliases = [ "monitor-local.${domain}" ];
 | 
				
			||||||
              extraConfig = localRedirect "monitor-local.${domain}";
 | 
					              # extraConfig = localRedirect "monitor-local.${domain}";
 | 
				
			||||||
              locations = {
 | 
					              locations = {
 | 
				
			||||||
                "/" = {
 | 
					                "/" = {
 | 
				
			||||||
                  proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999";
 | 
					                  proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999";
 | 
				
			||||||
@@ -136,17 +137,17 @@ in
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
            "torrents.${domain}" = withAuth {
 | 
					            "torrents.${domain}" = withAuth {
 | 
				
			||||||
              serverAliases = [ "torrents-local.${domain}" ];
 | 
					              serverAliases = [ "torrents-local.${domain}" ];
 | 
				
			||||||
              extraConfig = localRedirect "torrents-local.${domain}";
 | 
					              # extraConfig = localRedirect "torrents-local.${domain}";
 | 
				
			||||||
              locations."/".proxyPass = "${acquisition}:9091";
 | 
					              locations."/".proxyPass = "${acquisition}:9091";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            "jackett.${domain}" = withAuth {
 | 
					            "jackett.${domain}" = withAuth {
 | 
				
			||||||
              serverAliases = [ "jackett-local.${domain}" ];
 | 
					              serverAliases = [ "jackett-local.${domain}" ];
 | 
				
			||||||
              extraConfig = localRedirect "jackett-local.${domain}";
 | 
					              # extraConfig = localRedirect "jackett-local.${domain}";
 | 
				
			||||||
              locations."/".proxyPass = "${acquisition}:9117";
 | 
					              locations."/".proxyPass = "${acquisition}:9117";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            "radarr.${domain}" = withAuth {
 | 
					            "radarr.${domain}" = withAuth {
 | 
				
			||||||
              serverAliases = [ "radarr-local.${domain}" ];
 | 
					              serverAliases = [ "radarr-local.${domain}" ];
 | 
				
			||||||
              extraConfig = localRedirect "radarr-local.${domain}";
 | 
					              # extraConfig = localRedirect "radarr-local.${domain}";
 | 
				
			||||||
              locations."/" = {
 | 
					              locations."/" = {
 | 
				
			||||||
                proxyPass = "${acquisition}:7878";
 | 
					                proxyPass = "${acquisition}:7878";
 | 
				
			||||||
                proxyWebsockets = true;
 | 
					                proxyWebsockets = true;
 | 
				
			||||||
@@ -155,7 +156,7 @@ in
 | 
				
			|||||||
            };
 | 
					            };
 | 
				
			||||||
            "sonarr.${domain}" = withAuth {
 | 
					            "sonarr.${domain}" = withAuth {
 | 
				
			||||||
              serverAliases = [ "sonarr-local.${domain}" ];
 | 
					              serverAliases = [ "sonarr-local.${domain}" ];
 | 
				
			||||||
              extraConfig = localRedirect "sonarr-local.${domain}";
 | 
					              # extraConfig = localRedirect "sonarr-local.${domain}";
 | 
				
			||||||
              locations."/" = {
 | 
					              locations."/" = {
 | 
				
			||||||
                proxyPass = "${acquisition}:8989";
 | 
					                proxyPass = "${acquisition}:8989";
 | 
				
			||||||
                proxyWebsockets = true;
 | 
					                proxyWebsockets = true;
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{ lib, ... }:
 | 
					{ lib, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib.my) net;
 | 
					  inherit (lib.my) net;
 | 
				
			||||||
  inherit (lib.my.c.kelder) domain prefixes;
 | 
					  inherit (lib.my.c.kelder) domain prefixes ipv4MTU;
 | 
				
			||||||
in
 | 
					in
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
  imports = [ ./containers ];
 | 
					  imports = [ ./containers ];
 | 
				
			||||||
@@ -182,7 +182,7 @@ in
 | 
				
			|||||||
                    {
 | 
					                    {
 | 
				
			||||||
                      wireguardPeerConfig = {
 | 
					                      wireguardPeerConfig = {
 | 
				
			||||||
                        PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
 | 
					                        PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
 | 
				
			||||||
                        Endpoint = "estuary-vm.${lib.my.c.colony.domain}:${toString lib.my.c.kelder.vpn.port}";
 | 
					                        Endpoint = "${allAssignments.estuary.internal.ipv4.address}:${toString lib.my.c.kelder.vpn.port}";
 | 
				
			||||||
                        AllowedIPs = [ "0.0.0.0/0" ];
 | 
					                        AllowedIPs = [ "0.0.0.0/0" ];
 | 
				
			||||||
                        PersistentKeepalive = 25;
 | 
					                        PersistentKeepalive = 25;
 | 
				
			||||||
                      };
 | 
					                      };
 | 
				
			||||||
@@ -200,6 +200,7 @@ in
 | 
				
			|||||||
                "50-lan" = {
 | 
					                "50-lan" = {
 | 
				
			||||||
                  matchConfig.Name = "et1g0";
 | 
					                  matchConfig.Name = "et1g0";
 | 
				
			||||||
                  DHCP = "yes";
 | 
					                  DHCP = "yes";
 | 
				
			||||||
 | 
					                  linkConfig.MTUBytes = toString ipv4MTU;
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
                "80-ctrs" = mkMerge [
 | 
					                "80-ctrs" = mkMerge [
 | 
				
			||||||
                  (networkdAssignment "ctrs" assignments.ctrs)
 | 
					                  (networkdAssignment "ctrs" assignments.ctrs)
 | 
				
			||||||
@@ -272,7 +273,7 @@ in
 | 
				
			|||||||
              config.name = "kontent";
 | 
					              config.name = "kontent";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
            #deploy.node.hostname = "10.16.9.21";
 | 
					            # deploy.node.hostname = "192.168.0.69";
 | 
				
			||||||
            secrets = {
 | 
					            secrets = {
 | 
				
			||||||
              key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi";
 | 
					              key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi";
 | 
				
			||||||
              files = {
 | 
					              files = {
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -129,10 +129,9 @@
 | 
				
			|||||||
            wifi = {
 | 
					            wifi = {
 | 
				
			||||||
              backend = "wpa_supplicant";
 | 
					              backend = "wpa_supplicant";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            extraConfig = ''
 | 
					            settings = {
 | 
				
			||||||
              [main]
 | 
					              main.no-auto-default = "*";
 | 
				
			||||||
              no-auto-default=*
 | 
					            };
 | 
				
			||||||
            '';
 | 
					 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -191,6 +190,10 @@
 | 
				
			|||||||
                config = {
 | 
					                config = {
 | 
				
			||||||
                  input."1:1:AT_Translated_Set_2_keyboard".xkb_layout = "ie";
 | 
					                  input."1:1:AT_Translated_Set_2_keyboard".xkb_layout = "ie";
 | 
				
			||||||
                  output.eDP-1.scale = "1";
 | 
					                  output.eDP-1.scale = "1";
 | 
				
			||||||
 | 
					                  keybindings = lib.mkOptionDefault {
 | 
				
			||||||
 | 
					                    "XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
 | 
				
			||||||
 | 
					                    "XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
 | 
				
			||||||
 | 
					                  };
 | 
				
			||||||
                };
 | 
					                };
 | 
				
			||||||
              };
 | 
					              };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -35,7 +35,7 @@ let
 | 
				
			|||||||
      system = null;
 | 
					      system = null;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      # Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports
 | 
					      # 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` informs the manual which modules to document
 | 
				
			||||||
      baseModules =
 | 
					      baseModules =
 | 
				
			||||||
@@ -135,6 +135,7 @@ let
 | 
				
			|||||||
      ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6.";
 | 
					      ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6.";
 | 
				
			||||||
      baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with.";
 | 
					      baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with.";
 | 
				
			||||||
      l3Overhead = mkOpt' ints.unsigned 40 "Overhead of L3 header (to calculate MTU).";
 | 
					      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.";
 | 
					      firewall = mkBoolOpt' true "Whether to generate firewall rules.";
 | 
				
			||||||
      vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
 | 
					      vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
 | 
				
			||||||
      peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";
 | 
					      peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,7 +1,7 @@
 | 
				
			|||||||
{
 | 
					{
 | 
				
			||||||
  nixos.systems.installer = { config, ... }: {
 | 
					  nixos.systems.installer = { config, ... }: {
 | 
				
			||||||
    system = "x86_64-linux";
 | 
					    system = "x86_64-linux";
 | 
				
			||||||
    nixpkgs = "unstable";
 | 
					    nixpkgs = "mine";
 | 
				
			||||||
    docCustom = false;
 | 
					    docCustom = false;
 | 
				
			||||||
    rendered = config.configuration.config.my.asISO;
 | 
					    rendered = config.configuration.config.my.asISO;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -52,6 +52,8 @@
 | 
				
			|||||||
            home.shellAliases = {
 | 
					            home.shellAliases = {
 | 
				
			||||||
              show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT";
 | 
					              show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            my.gui.enable = false;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          services = {
 | 
					          services = {
 | 
				
			||||||
@@ -80,6 +82,8 @@
 | 
				
			|||||||
                ${pkgs.gawk}/bin/awk '{ print $1 }')"
 | 
					                ${pkgs.gawk}/bin/awk '{ print $1 }')"
 | 
				
			||||||
            '';
 | 
					            '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          boot.supportedFilesystems.nfs = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          environment.systemPackages = with pkgs; [
 | 
					          environment.systemPackages = with pkgs; [
 | 
				
			||||||
            dhcpcd
 | 
					            dhcpcd
 | 
				
			||||||
            lm_sensors
 | 
					            lm_sensors
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -20,5 +20,6 @@
 | 
				
			|||||||
    nvme = ./nvme;
 | 
					    nvme = ./nvme;
 | 
				
			||||||
    spdk = ./spdk.nix;
 | 
					    spdk = ./spdk.nix;
 | 
				
			||||||
    librespeed = ./librespeed;
 | 
					    librespeed = ./librespeed;
 | 
				
			||||||
 | 
					    netboot = ./netboot;
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{ lib, pkgs, extendModules, modulesPath, options, config, ... }:
 | 
					{ lib, pkgs, extendModules, modulesPath, options, config, ... }:
 | 
				
			||||||
let
 | 
					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;
 | 
					  inherit (lib.my) mkBoolOpt' dummyOption;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cfg = config.my.build;
 | 
					  cfg = config.my.build;
 | 
				
			||||||
@@ -43,15 +43,145 @@ let
 | 
				
			|||||||
    modules = flatten [
 | 
					    modules = flatten [
 | 
				
			||||||
      "${modulesPath}/installer/netboot/netboot.nix"
 | 
					      "${modulesPath}/installer/netboot/netboot.nix"
 | 
				
			||||||
      allHardware
 | 
					      allHardware
 | 
				
			||||||
 | 
					    ];
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  asNetboot = extendModules {
 | 
				
			||||||
 | 
					    modules = flatten [
 | 
				
			||||||
 | 
					      allHardware
 | 
				
			||||||
      ({ pkgs, config, ... }: {
 | 
					      ({ pkgs, config, ... }: {
 | 
				
			||||||
        system.build.netbootArchive = pkgs.runCommand "netboot-${config.system.name}-archive.tar" { } ''
 | 
					        boot = {
 | 
				
			||||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.kernel}" \
 | 
					          loader.grub.enable = false;
 | 
				
			||||||
            -f "$out" "${config.system.boot.loader.kernelFile}"
 | 
					          initrd = {
 | 
				
			||||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootRamdisk}" \
 | 
					            kernelModules = [ "nbd" ];
 | 
				
			||||||
            -f "$out" initrd
 | 
					            availableKernelModules = [ "igb" "igc" ];
 | 
				
			||||||
          ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootIpxeScript}" \
 | 
					
 | 
				
			||||||
            -f "$out" netboot.ipxe
 | 
					            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";
 | 
					      asISO = mkAsOpt asISO "a bootable .iso image";
 | 
				
			||||||
      asContainer = mkAsOpt asContainer "a container";
 | 
					      asContainer = mkAsOpt asContainer "a container";
 | 
				
			||||||
      asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
 | 
					      asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
 | 
				
			||||||
 | 
					      asNetboot = mkAsOpt asNetboot "a netboot-able kernel initrd, and iPXE script";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      buildAs = options.system.build;
 | 
					      buildAs = options.system.build;
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
@@ -110,7 +241,8 @@ in
 | 
				
			|||||||
        iso = config.my.asISO.config.system.build.isoImage;
 | 
					        iso = config.my.asISO.config.system.build.isoImage;
 | 
				
			||||||
        container = config.my.asContainer.config.system.build.toplevel;
 | 
					        container = config.my.asContainer.config.system.build.toplevel;
 | 
				
			||||||
        kexecTree = config.my.asKexecTree.config.system.build.kexecTree;
 | 
					        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
 | 
					let
 | 
				
			||||||
  inherit (lib) mkIf mkDefault mkMerge;
 | 
					  inherit (lib) mkIf mkDefault mkMerge;
 | 
				
			||||||
  inherit (lib.my) mkDefault';
 | 
					  inherit (lib.my) mkDefault';
 | 
				
			||||||
@@ -53,7 +53,7 @@ in
 | 
				
			|||||||
          pkgs = {
 | 
					          pkgs = {
 | 
				
			||||||
            to = {
 | 
					            to = {
 | 
				
			||||||
              type = "path";
 | 
					              type = "path";
 | 
				
			||||||
              path = "${pkgs.path}";
 | 
					              path = "${pkgsFlake}";
 | 
				
			||||||
            };
 | 
					            };
 | 
				
			||||||
            exact = true;
 | 
					            exact = true;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
@@ -127,6 +127,9 @@ in
 | 
				
			|||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      environment.etc = {
 | 
				
			||||||
 | 
					        "nixos/flake.nix".source = "/run/nixfiles/flake.nix";
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
      environment.systemPackages = with pkgs; mkMerge [
 | 
					      environment.systemPackages = with pkgs; mkMerge [
 | 
				
			||||||
        [
 | 
					        [
 | 
				
			||||||
          bash-completion
 | 
					          bash-completion
 | 
				
			||||||
@@ -209,6 +212,29 @@ in
 | 
				
			|||||||
            # python.d plugin script does #!/usr/bin/env bash
 | 
					            # python.d plugin script does #!/usr/bin/env bash
 | 
				
			||||||
            path = with pkgs; [ 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" ];
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,6 +1,6 @@
 | 
				
			|||||||
{ lib, pkgs, options, config, systems, ... }:
 | 
					{ lib, pkgs, options, config, systems, ... }:
 | 
				
			||||||
let
 | 
					let
 | 
				
			||||||
  inherit (builtins) attrNames attrValues all hashString toJSON;
 | 
					  inherit (builtins) attrNames attrValues all hashString toJSON any;
 | 
				
			||||||
  inherit (lib)
 | 
					  inherit (lib)
 | 
				
			||||||
    groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge;
 | 
					    groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge;
 | 
				
			||||||
  inherit (lib.my) mkOpt' mkBoolOpt';
 | 
					  inherit (lib.my) mkOpt' mkBoolOpt';
 | 
				
			||||||
@@ -98,6 +98,7 @@ let
 | 
				
			|||||||
      };
 | 
					      };
 | 
				
			||||||
      networking = {
 | 
					      networking = {
 | 
				
			||||||
        bridge = mkOpt' (nullOr str) null "Network bridge to connect to.";
 | 
					        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;
 | 
					          assertion = config.systemd.network.enable;
 | 
				
			||||||
          message = "Containers currently require systemd-networkd!";
 | 
					          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
 | 
					      # TODO: Better security
 | 
				
			||||||
      my.firewall.trustedInterfaces =
 | 
					      my.firewall.trustedInterfaces =
 | 
				
			||||||
        mapAttrsToList
 | 
					        mapAttrsToList
 | 
				
			||||||
          (n: _: "ve-${n}")
 | 
					          (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 ([
 | 
					      systemd = mkMerge (mapAttrsToList (n: c: {
 | 
				
			||||||
        {
 | 
					 | 
				
			||||||
          # 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: {
 | 
					 | 
				
			||||||
        nspawn."${n}" = {
 | 
					        nspawn."${n}" = {
 | 
				
			||||||
          execConfig = {
 | 
					          execConfig = {
 | 
				
			||||||
            Boot = true;
 | 
					            Boot = true;
 | 
				
			||||||
@@ -165,6 +159,8 @@ in
 | 
				
			|||||||
          };
 | 
					          };
 | 
				
			||||||
          networkConfig = if (c.networking.bridge != null) then {
 | 
					          networkConfig = if (c.networking.bridge != null) then {
 | 
				
			||||||
            Bridge = c.networking.bridge;
 | 
					            Bridge = c.networking.bridge;
 | 
				
			||||||
 | 
					          } else if (c.networking.macVLAN != null) then {
 | 
				
			||||||
 | 
					            MACVLAN = "${c.networking.macVLAN}:host0";
 | 
				
			||||||
          } else {
 | 
					          } else {
 | 
				
			||||||
            VirtualEthernet = true;
 | 
					            VirtualEthernet = true;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
@@ -182,6 +178,9 @@ in
 | 
				
			|||||||
            c.containerSystem;
 | 
					            c.containerSystem;
 | 
				
			||||||
        in
 | 
					        in
 | 
				
			||||||
        {
 | 
					        {
 | 
				
			||||||
 | 
					          # To prevent creating a whole new unit file
 | 
				
			||||||
 | 
					          overrideStrategy = "asDropin";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          environment = {
 | 
					          environment = {
 | 
				
			||||||
            # systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths
 | 
					            # systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths
 | 
				
			||||||
            root = "/run/machines/${n}";
 | 
					            root = "/run/machines/${n}";
 | 
				
			||||||
@@ -247,7 +246,7 @@ in
 | 
				
			|||||||
            Bridge = c.networking.bridge;
 | 
					            Bridge = c.networking.bridge;
 | 
				
			||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      }) cfg.instances));
 | 
					      }) cfg.instances);
 | 
				
			||||||
    })
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    # Inside container
 | 
					    # Inside container
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -23,13 +23,13 @@ in
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    security = {
 | 
					    security = {
 | 
				
			||||||
      polkit.enable = true;
 | 
					      polkit.enable = true;
 | 
				
			||||||
      pam.services.swaylock = {};
 | 
					      pam.services.swaylock-plugin = {};
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    environment.systemPackages = with pkgs; [
 | 
					    environment.systemPackages = with pkgs; [
 | 
				
			||||||
      # for pw-jack
 | 
					      # for pw-jack
 | 
				
			||||||
      pipewire.jack
 | 
					      pipewire.jack
 | 
				
			||||||
      swaylock
 | 
					      swaylock-plugin
 | 
				
			||||||
    ];
 | 
					    ];
 | 
				
			||||||
    services = {
 | 
					    services = {
 | 
				
			||||||
      pipewire = {
 | 
					      pipewire = {
 | 
				
			||||||
@@ -51,6 +51,8 @@ in
 | 
				
			|||||||
          SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
 | 
					          SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
 | 
				
			||||||
          # Nintendo
 | 
					          # Nintendo
 | 
				
			||||||
          SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
 | 
					          SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
 | 
				
			||||||
 | 
					          # FT
 | 
				
			||||||
 | 
					          SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel"
 | 
				
			||||||
        '';
 | 
					        '';
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -36,8 +36,8 @@ let
 | 
				
			|||||||
        espOverhead =
 | 
					        espOverhead =
 | 
				
			||||||
          if (!mesh.security.enable) then 0
 | 
					          if (!mesh.security.enable) then 0
 | 
				
			||||||
          else
 | 
					          else
 | 
				
			||||||
            # SPI + seq + IV + pad / header + ICV
 | 
					            # UDP encap + SPI + seq + IV + pad / header + ICV
 | 
				
			||||||
            4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16;
 | 
					            (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)
 | 
					        # UDP + VXLAN + Ethernet + L3 (IPv4/IPv6)
 | 
				
			||||||
        overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead;
 | 
					        overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead;
 | 
				
			||||||
      in
 | 
					      in
 | 
				
			||||||
@@ -62,8 +62,12 @@ let
 | 
				
			|||||||
      chain l2mesh-${name} {
 | 
					      chain l2mesh-${name} {
 | 
				
			||||||
        ${optionalString mesh.security.enable ''
 | 
					        ${optionalString mesh.security.enable ''
 | 
				
			||||||
          udp dport isakmp accept
 | 
					          udp dport isakmp accept
 | 
				
			||||||
 | 
					          ${if mesh.udpEncapsulation then ''
 | 
				
			||||||
 | 
					            udp dport ipsec-nat-t accept
 | 
				
			||||||
 | 
					          '' else ''
 | 
				
			||||||
            meta l4proto esp accept
 | 
					            meta l4proto esp accept
 | 
				
			||||||
          ''}
 | 
					          ''}
 | 
				
			||||||
 | 
					        ''}
 | 
				
			||||||
        ${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)}
 | 
					        ${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)}
 | 
				
			||||||
        return
 | 
					        return
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
@@ -94,6 +98,7 @@ let
 | 
				
			|||||||
          esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"}
 | 
					          esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"}
 | 
				
			||||||
          ikev2=yes
 | 
					          ikev2=yes
 | 
				
			||||||
          modecfgpull=no
 | 
					          modecfgpull=no
 | 
				
			||||||
 | 
					          encapsulation=${if mesh.udpEncapsulation then "yes" else "no"}
 | 
				
			||||||
        '';
 | 
					        '';
 | 
				
			||||||
      })
 | 
					      })
 | 
				
			||||||
    otherPeers);
 | 
					    otherPeers);
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										223
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										223
									
								
								nixos/modules/netboot/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,223 @@
 | 
				
			|||||||
 | 
					{ lib, pkgs, config, ... }:
 | 
				
			||||||
 | 
					let
 | 
				
			||||||
 | 
					  inherit (lib) mkMerge mkIf mkForce genAttrs concatMapStringsSep;
 | 
				
			||||||
 | 
					  inherit (lib.my) mkOpt' mkBoolOpt';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cfg = config.my.netboot;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  tftpRoot = pkgs.linkFarm "tftp-root" [
 | 
				
			||||||
 | 
					    {
 | 
				
			||||||
 | 
					      name = "ipxe-x86_64.efi";
 | 
				
			||||||
 | 
					      path = "${pkgs.ipxe}/ipxe.efi";
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  menuFile = pkgs.runCommand "menu.ipxe" {
 | 
				
			||||||
 | 
					    bootHost = cfg.server.host;
 | 
				
			||||||
 | 
					  } ''
 | 
				
			||||||
 | 
					    substituteAll ${./menu.ipxe} "$out"
 | 
				
			||||||
 | 
					  '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bootBuilder = pkgs.substituteAll {
 | 
				
			||||||
 | 
					    src = ./netboot-loader-builder.py;
 | 
				
			||||||
 | 
					    isExecutable = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inherit (pkgs) python3;
 | 
				
			||||||
 | 
					    bootspecTools = pkgs.bootspec;
 | 
				
			||||||
 | 
					    nix = config.nix.package.out;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    inherit (config.system.nixos) distroName;
 | 
				
			||||||
 | 
					    systemName = config.system.name;
 | 
				
			||||||
 | 
					    inherit (cfg.client) configurationLimit;
 | 
				
			||||||
 | 
					    checkMountpoints = pkgs.writeShellScript "check-mountpoints" ''
 | 
				
			||||||
 | 
					      if ! ${pkgs.util-linuxMinimal}/bin/findmnt /boot > /dev/null; then
 | 
				
			||||||
 | 
					        echo "/boot is not a mounted partition. Is the path configured correctly?" >&2
 | 
				
			||||||
 | 
					        exit 1
 | 
				
			||||||
 | 
					      fi
 | 
				
			||||||
 | 
					    '';
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					in
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
					  options.my.netboot = with lib.types; {
 | 
				
			||||||
 | 
					    client = {
 | 
				
			||||||
 | 
					      enable = mkBoolOpt' false "Whether network booting should be enabled.";
 | 
				
			||||||
 | 
					      configurationLimit = mkOpt' ints.unsigned 10 "Max generations to show in boot menu.";
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					    server = {
 | 
				
			||||||
 | 
					      enable = mkBoolOpt' false "Whether a netboot server should be enabled.";
 | 
				
			||||||
 | 
					      ip = mkOpt' str null "IP clients should connect to via TFTP.";
 | 
				
			||||||
 | 
					      host = mkOpt' str config.networking.fqdn "Hostname clients should connect to over HTTP / NFS.";
 | 
				
			||||||
 | 
					      allowedPrefixes = mkOpt' (listOf str) null "Prefixes clients should be allowed to connect from (NFS).";
 | 
				
			||||||
 | 
					      installer = {
 | 
				
			||||||
 | 
					        storeSize = mkOpt' str "16GiB" "Total allowed writable size of store.";
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      instances = mkOpt' (listOf str) [ ] "Systems to hold boot files for.";
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  config = mkMerge [
 | 
				
			||||||
 | 
					    (mkIf cfg.client.enable {
 | 
				
			||||||
 | 
					      systemd = {
 | 
				
			||||||
 | 
					        services = {
 | 
				
			||||||
 | 
					          mount-boot = {
 | 
				
			||||||
 | 
					            description = "Mount /boot";
 | 
				
			||||||
 | 
					            after = [ "systemd-networkd-wait-online.service" ];
 | 
				
			||||||
 | 
					            serviceConfig = {
 | 
				
			||||||
 | 
					              Type = "oneshot";
 | 
				
			||||||
 | 
					              RemainAfterExit = true;
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					            path = with pkgs; [ gnused ldns nfs-utils ];
 | 
				
			||||||
 | 
					            script = ''
 | 
				
			||||||
 | 
					              get_cmdline() {
 | 
				
			||||||
 | 
					                sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              host="$(get_cmdline boothost)"
 | 
				
			||||||
 | 
					              if [ -z "$host" ]; then
 | 
				
			||||||
 | 
					                echo "boothost kernel parameter not found!" >&2
 | 
				
			||||||
 | 
					                exit 1
 | 
				
			||||||
 | 
					              fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              until [ -n "$(drill -Q $host)" ]; do
 | 
				
			||||||
 | 
					                sleep 0.1
 | 
				
			||||||
 | 
					              done
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              mkdir -p /boot
 | 
				
			||||||
 | 
					              mount.nfs $host:/srv/netboot/systems/${config.system.name} /boot
 | 
				
			||||||
 | 
					            '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            wantedBy = [ "remote-fs.target" ];
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      boot.supportedFilesystems.nfs = true;
 | 
				
			||||||
 | 
					      boot.loader = {
 | 
				
			||||||
 | 
					        grub.enable = false;
 | 
				
			||||||
 | 
					        systemd-boot.enable = false;
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					      system = {
 | 
				
			||||||
 | 
					        build.installBootLoader = bootBuilder;
 | 
				
			||||||
 | 
					        boot.loader.id = "ipxe-netboot";
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    (mkIf cfg.server.enable {
 | 
				
			||||||
 | 
					      environment = {
 | 
				
			||||||
 | 
					        etc = {
 | 
				
			||||||
 | 
					          "netboot/menu.ipxe".source = menuFile;
 | 
				
			||||||
 | 
					          "netboot/shell.efi".source = "${pkgs.edk2-uefi-shell}/shell.efi";
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      systemd = {
 | 
				
			||||||
 | 
					        tmpfiles.settings."10-netboot" = genAttrs
 | 
				
			||||||
 | 
					          (map (i: "/srv/netboot/systems/${i}") cfg.server.instances)
 | 
				
			||||||
 | 
					          (p: {
 | 
				
			||||||
 | 
					            d = {
 | 
				
			||||||
 | 
					              user = "root";
 | 
				
			||||||
 | 
					              group = "root";
 | 
				
			||||||
 | 
					              mode = "0777";
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          });
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        services = {
 | 
				
			||||||
 | 
					          netboot-update = {
 | 
				
			||||||
 | 
					            description = "Update netboot images";
 | 
				
			||||||
 | 
					            after = [ "systemd-networkd-wait-online.service" ];
 | 
				
			||||||
 | 
					            serviceConfig.Type = "oneshot";
 | 
				
			||||||
 | 
					            path = with pkgs; [
 | 
				
			||||||
 | 
					              coreutils curl jq zstd gnutar
 | 
				
			||||||
 | 
					            ];
 | 
				
			||||||
 | 
					            script = ''
 | 
				
			||||||
 | 
					              update_nixos() {
 | 
				
			||||||
 | 
					                latestShort="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/tags/installer \
 | 
				
			||||||
 | 
					                             | jq -r .commit.sha | cut -c -7)"
 | 
				
			||||||
 | 
					                if [ -f nixos-installer/tag.txt ] && [ "$(< nixos-installer/tag.txt)" = "$latestShort" ]; then
 | 
				
			||||||
 | 
					                  echo "NixOS installer is up to date"
 | 
				
			||||||
 | 
					                  return
 | 
				
			||||||
 | 
					                fi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					                echo "Updating NixOS installer to $latestShort"
 | 
				
			||||||
 | 
					                mkdir -p nixos-installer
 | 
				
			||||||
 | 
					                fname="jackos-installer-netboot-$latestShort.tar.zst"
 | 
				
			||||||
 | 
					                downloadUrl="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/releases/tags/installer | \
 | 
				
			||||||
 | 
					                               jq -r ".assets[] | select(.name == \"$fname\").browser_download_url")"
 | 
				
			||||||
 | 
					                curl -Lo /tmp/nixos-installer-netboot.tar.zst "$downloadUrl"
 | 
				
			||||||
 | 
					                tar -C nixos-installer --zstd -xf /tmp/nixos-installer-netboot.tar.zst
 | 
				
			||||||
 | 
					                truncate -s "${cfg.server.installer.storeSize}" nixos-installer/rootfs.ext4
 | 
				
			||||||
 | 
					                rm /tmp/nixos-installer-netboot.tar.zst
 | 
				
			||||||
 | 
					                echo "$latestShort" > nixos-installer/tag.txt
 | 
				
			||||||
 | 
					              }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              mkdir -p /srv/netboot
 | 
				
			||||||
 | 
					              cd /srv/netboot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					              ln -sf ${menuFile} boot.ipxe
 | 
				
			||||||
 | 
					              ln -sf "${pkgs.edk2-uefi-shell}/shell.efi" "efi-shell-${config.nixpkgs.localSystem.linuxArch}.efi"
 | 
				
			||||||
 | 
					              update_nixos
 | 
				
			||||||
 | 
					            '';
 | 
				
			||||||
 | 
					            startAt = "06:00";
 | 
				
			||||||
 | 
					            wantedBy = [ "network-online.target" ];
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          nbd-server = {
 | 
				
			||||||
 | 
					            serviceConfig = {
 | 
				
			||||||
 | 
					              PrivateUsers = mkForce false;
 | 
				
			||||||
 | 
					              CacheDirectory = "netboot";
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      services = {
 | 
				
			||||||
 | 
					        atftpd = {
 | 
				
			||||||
 | 
					          enable = true;
 | 
				
			||||||
 | 
					          root = tftpRoot;
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nginx = {
 | 
				
			||||||
 | 
					          virtualHosts."${cfg.server.host}" = {
 | 
				
			||||||
 | 
					            locations."/" = {
 | 
				
			||||||
 | 
					              root = "/srv/netboot";
 | 
				
			||||||
 | 
					              extraConfig = ''
 | 
				
			||||||
 | 
					                autoindex on;
 | 
				
			||||||
 | 
					              '';
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nbd.server = {
 | 
				
			||||||
 | 
					          enable = true;
 | 
				
			||||||
 | 
					          extraOptions = {
 | 
				
			||||||
 | 
					            allowlist = true;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					          exports = {
 | 
				
			||||||
 | 
					            nixos-installer = {
 | 
				
			||||||
 | 
					              path = "/srv/netboot/nixos-installer/rootfs.ext4";
 | 
				
			||||||
 | 
					              extraOptions = {
 | 
				
			||||||
 | 
					                copyonwrite = true;
 | 
				
			||||||
 | 
					                cowdir = "/var/cache/netboot";
 | 
				
			||||||
 | 
					                sparse_cow = true;
 | 
				
			||||||
 | 
					              };
 | 
				
			||||||
 | 
					            };
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        nfs = {
 | 
				
			||||||
 | 
					          server = {
 | 
				
			||||||
 | 
					            enable = true;
 | 
				
			||||||
 | 
					            exports = ''
 | 
				
			||||||
 | 
					              /srv/netboot/systems ${concatMapStringsSep " " (p: "${p}(rw,all_squash)") cfg.server.allowedPrefixes}
 | 
				
			||||||
 | 
					            '';
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					        };
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      my = {
 | 
				
			||||||
 | 
					        tmproot.persistence.config.directories = [
 | 
				
			||||||
 | 
					          "/srv/netboot"
 | 
				
			||||||
 | 
					          { directory = "/var/cache/netboot"; mode = "0700"; }
 | 
				
			||||||
 | 
					        ];
 | 
				
			||||||
 | 
					      };
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										68
									
								
								nixos/modules/netboot/menu.ipxe
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								nixos/modules/netboot/menu.ipxe
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,68 @@
 | 
				
			|||||||
 | 
					#!ipxe
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					set server http://@bootHost@
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# Figure out if client is 64-bit capable
 | 
				
			||||||
 | 
					cpuid --ext 29 && set arch x86_64 || set arch i386
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					isset ${menu-default} || set menu-default exit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:start
 | 
				
			||||||
 | 
					menu Welcome to /dev/player0's humble iPXE boot menu
 | 
				
			||||||
 | 
					item --gap --           Operating Systems
 | 
				
			||||||
 | 
					iseq ${arch} x86_64 &&
 | 
				
			||||||
 | 
					item --key n nixos      NixOS installer
 | 
				
			||||||
 | 
					# iseq ${arch} x86_64 &&
 | 
				
			||||||
 | 
					# item --key a archlinux Arch Linux (archiso x86_64)
 | 
				
			||||||
 | 
					# iseq ${arch} x86_64 &&
 | 
				
			||||||
 | 
					# item --key p alpine   Alpine Linux
 | 
				
			||||||
 | 
					item --gap --           Other Options
 | 
				
			||||||
 | 
					item --key e efi_shell  UEFI Shell
 | 
				
			||||||
 | 
					item --key x xyz        netboot.xyz
 | 
				
			||||||
 | 
					item --key c config     iPXE settings
 | 
				
			||||||
 | 
					item --key s shell      Drop to iPXE shell
 | 
				
			||||||
 | 
					item --key r reboot     Reboot
 | 
				
			||||||
 | 
					item --key q exit       Exit (and continue to next boot device)
 | 
				
			||||||
 | 
					choose --timeout 0 --default ${menu-default} selected || goto cancel
 | 
				
			||||||
 | 
					goto ${selected}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:cancel
 | 
				
			||||||
 | 
					echo You cancelled the menu, dropping you to an iPXE shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:shell
 | 
				
			||||||
 | 
					echo Type 'exit' to go back to the menu
 | 
				
			||||||
 | 
					shell
 | 
				
			||||||
 | 
					set menu-default nixos
 | 
				
			||||||
 | 
					goto start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:failed
 | 
				
			||||||
 | 
					echo Booting failed, dropping to shell
 | 
				
			||||||
 | 
					goto shell
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:reboot
 | 
				
			||||||
 | 
					reboot
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:exit
 | 
				
			||||||
 | 
					exit
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:config
 | 
				
			||||||
 | 
					config
 | 
				
			||||||
 | 
					set menu-default config
 | 
				
			||||||
 | 
					goto start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:efi_shell
 | 
				
			||||||
 | 
					chain ${server}/efi-shell-${arch}.efi || goto failed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:xyz
 | 
				
			||||||
 | 
					chain --autofree https://boot.netboot.xyz || goto failed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:nixos
 | 
				
			||||||
 | 
					set cmdline nbd_export=nixos-installer
 | 
				
			||||||
 | 
					chain ${server}/nixos-installer/boot.ipxe || goto failed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:archlinux
 | 
				
			||||||
 | 
					# set mirrorurl https://arch.nul.ie/
 | 
				
			||||||
 | 
					chain ${server}/arch.ipxe || goto failed
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:alpine
 | 
				
			||||||
 | 
					chain ${server}/alpine.ipxe || goto failed
 | 
				
			||||||
							
								
								
									
										280
									
								
								nixos/modules/netboot/netboot-loader-builder.py
									
									
									
									
									
										Executable file
									
								
							
							
						
						
									
										280
									
								
								nixos/modules/netboot/netboot-loader-builder.py
									
									
									
									
									
										Executable file
									
								
							@@ -0,0 +1,280 @@
 | 
				
			|||||||
 | 
					#! @python3@/bin/python3 -B
 | 
				
			||||||
 | 
					# Based on `nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py`
 | 
				
			||||||
 | 
					import argparse
 | 
				
			||||||
 | 
					import datetime
 | 
				
			||||||
 | 
					import glob
 | 
				
			||||||
 | 
					import os
 | 
				
			||||||
 | 
					import os.path
 | 
				
			||||||
 | 
					import shutil
 | 
				
			||||||
 | 
					import subprocess
 | 
				
			||||||
 | 
					import sys
 | 
				
			||||||
 | 
					import json
 | 
				
			||||||
 | 
					from typing import NamedTuple, Dict, List
 | 
				
			||||||
 | 
					from dataclasses import dataclass
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOT_MOUNT_POINT = '/boot'
 | 
				
			||||||
 | 
					STORE_DIR = 'nix'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					# These values will be replaced with actual values during the package build
 | 
				
			||||||
 | 
					BOOTSPEC_TOOLS = '@bootspecTools@'
 | 
				
			||||||
 | 
					NIX = '@nix@'
 | 
				
			||||||
 | 
					DISTRO_NAME = '@distroName@'
 | 
				
			||||||
 | 
					SYSTEM_NAME = '@systemName@'
 | 
				
			||||||
 | 
					CONFIGURATION_LIMIT = int('@configurationLimit@')
 | 
				
			||||||
 | 
					CHECK_MOUNTPOINTS = "@checkMountpoints@"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					@dataclass
 | 
				
			||||||
 | 
					class BootSpec:
 | 
				
			||||||
 | 
					  init: str
 | 
				
			||||||
 | 
					  initrd: str
 | 
				
			||||||
 | 
					  kernel: str
 | 
				
			||||||
 | 
					  kernelParams: List[str]
 | 
				
			||||||
 | 
					  label: str
 | 
				
			||||||
 | 
					  system: str
 | 
				
			||||||
 | 
					  toplevel: str
 | 
				
			||||||
 | 
					  specialisations: Dict[str, 'BootSpec']
 | 
				
			||||||
 | 
					  sortKey: str
 | 
				
			||||||
 | 
					  initrdSecrets: str | None = None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class SystemIdentifier(NamedTuple):
 | 
				
			||||||
 | 
					  profile: str | None
 | 
				
			||||||
 | 
					  generation: int
 | 
				
			||||||
 | 
					  specialisation: str | None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def copy_if_not_exists(source: str, dest: str) -> None:
 | 
				
			||||||
 | 
					  if not os.path.exists(dest):
 | 
				
			||||||
 | 
					    shutil.copyfile(source, dest)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def generation_dir(profile: str | None, generation: int) -> str:
 | 
				
			||||||
 | 
					  if profile:
 | 
				
			||||||
 | 
					    return f'/nix/var/nix/profiles/system-profiles/{profile}-{generation}-link'
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    return f'/nix/var/nix/profiles/system-{generation}-link'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def system_dir(i: SystemIdentifier) -> str:
 | 
				
			||||||
 | 
					  d = generation_dir(i.profile, i.generation)
 | 
				
			||||||
 | 
					  if i.specialisation:
 | 
				
			||||||
 | 
					    return os.path.join(d, 'specialisation', i.specialisation)
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    return d
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def entry_key(i: SystemIdentifier) -> str:
 | 
				
			||||||
 | 
					  pieces = [
 | 
				
			||||||
 | 
					    'nixos',
 | 
				
			||||||
 | 
					    i.profile or None,
 | 
				
			||||||
 | 
					    'generation',
 | 
				
			||||||
 | 
					    str(i.generation),
 | 
				
			||||||
 | 
					    f'specialisation-{i.specialisation}' if i.specialisation else None,
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					  return '-'.join(p for p in pieces if p)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def bootspec_from_json(bootspec_json: Dict) -> BootSpec:
 | 
				
			||||||
 | 
					  specialisations = bootspec_json['org.nixos.specialisation.v1']
 | 
				
			||||||
 | 
					  specialisations = {k: bootspec_from_json(v) for k, v in specialisations.items()}
 | 
				
			||||||
 | 
					  systemdBootExtension = bootspec_json.get('org.nixos.systemd-boot', {})
 | 
				
			||||||
 | 
					  sortKey = systemdBootExtension.get('sortKey', 'nixos')
 | 
				
			||||||
 | 
					  return BootSpec(
 | 
				
			||||||
 | 
					    **bootspec_json['org.nixos.bootspec.v1'],
 | 
				
			||||||
 | 
					    specialisations=specialisations,
 | 
				
			||||||
 | 
					    sortKey=sortKey
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					bootspecs = {}
 | 
				
			||||||
 | 
					def get_bootspec(profile: str | None, generation: int) -> BootSpec:
 | 
				
			||||||
 | 
					  k = (profile, generation)
 | 
				
			||||||
 | 
					  if k in bootspecs:
 | 
				
			||||||
 | 
					    return bootspecs[k]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  system_directory = system_dir(SystemIdentifier(profile, generation, None))
 | 
				
			||||||
 | 
					  boot_json_path = os.path.realpath(f'{system_directory}/boot.json')
 | 
				
			||||||
 | 
					  if os.path.isfile(boot_json_path):
 | 
				
			||||||
 | 
					    boot_json_f = open(boot_json_path, 'r')
 | 
				
			||||||
 | 
					    bootspec_json = json.load(boot_json_f)
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    boot_json_str = subprocess.check_output([
 | 
				
			||||||
 | 
					      f'{BOOTSPEC_TOOLS}/bin/synthesize',
 | 
				
			||||||
 | 
					      '--version',
 | 
				
			||||||
 | 
					      '1',
 | 
				
			||||||
 | 
					      system_directory,
 | 
				
			||||||
 | 
					      '/dev/stdout',
 | 
				
			||||||
 | 
					    ],
 | 
				
			||||||
 | 
					    universal_newlines=True)
 | 
				
			||||||
 | 
					    bootspec_json = json.loads(boot_json_str)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  bs = bootspec_from_json(bootspec_json)
 | 
				
			||||||
 | 
					  bootspecs[k] = bs
 | 
				
			||||||
 | 
					  return bs
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def copy_from_file(file: str, dry_run: bool = False) -> str:
 | 
				
			||||||
 | 
					  store_file_path = os.path.realpath(file)
 | 
				
			||||||
 | 
					  suffix = os.path.basename(store_file_path)
 | 
				
			||||||
 | 
					  store_dir = os.path.basename(os.path.dirname(store_file_path))
 | 
				
			||||||
 | 
					  dst_path = f'/{STORE_DIR}/{store_dir}-{suffix}'
 | 
				
			||||||
 | 
					  if not dry_run:
 | 
				
			||||||
 | 
					    copy_if_not_exists(store_file_path, f'{BOOT_MOUNT_POINT}{dst_path}')
 | 
				
			||||||
 | 
					  return dst_path
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MENU_ITEM = 'item {gen_key} {title} Generation {generation} {description}'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					BOOT_ENTRY = ''':{gen_key}
 | 
				
			||||||
 | 
					kernel ${{server}}/systems/{system_name}{kernel} {kernel_params} boothost=${{boothost}}
 | 
				
			||||||
 | 
					initrd ${{server}}/systems/{system_name}{initrd}
 | 
				
			||||||
 | 
					boot
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def gen_entry(i: SystemIdentifier) -> (str, str):
 | 
				
			||||||
 | 
					  bootspec = get_bootspec(i.profile, i.generation)
 | 
				
			||||||
 | 
					  if i.specialisation:
 | 
				
			||||||
 | 
					    bootspec = bootspec.specialisations[i.specialisation]
 | 
				
			||||||
 | 
					  kernel = copy_from_file(bootspec.kernel)
 | 
				
			||||||
 | 
					  initrd = copy_from_file(bootspec.initrd)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gen_key = entry_key(i)
 | 
				
			||||||
 | 
					  title = '{name}{profile}{specialisation}'.format(
 | 
				
			||||||
 | 
					    name=DISTRO_NAME,
 | 
				
			||||||
 | 
					    profile=' [' + i.profile + ']' if i.profile else '',
 | 
				
			||||||
 | 
					    specialisation=f' ({i.specialisation})' if i.specialisation else '')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  kernel_params = f'init={bootspec.init} '
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  kernel_params = kernel_params + ' '.join(bootspec.kernelParams)
 | 
				
			||||||
 | 
					  build_time = int(os.path.getctime(system_dir(i)))
 | 
				
			||||||
 | 
					  build_date = datetime.datetime.fromtimestamp(build_time).strftime('%F')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return MENU_ITEM.format(
 | 
				
			||||||
 | 
					    gen_key=gen_key,
 | 
				
			||||||
 | 
					    title=title,
 | 
				
			||||||
 | 
					    description=f'{bootspec.label}, built on {build_date}',
 | 
				
			||||||
 | 
					    generation=i.generation,
 | 
				
			||||||
 | 
					  ), BOOT_ENTRY.format(
 | 
				
			||||||
 | 
					    gen_key=gen_key,
 | 
				
			||||||
 | 
					    generation=i.generation,
 | 
				
			||||||
 | 
					    system_name=SYSTEM_NAME,
 | 
				
			||||||
 | 
					    kernel=kernel,
 | 
				
			||||||
 | 
					    kernel_params=kernel_params,
 | 
				
			||||||
 | 
					    initrd=initrd,
 | 
				
			||||||
 | 
					  )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
 | 
				
			||||||
 | 
					  gen_list = subprocess.check_output([
 | 
				
			||||||
 | 
					    f'{NIX}/bin/nix-env',
 | 
				
			||||||
 | 
					    '--list-generations',
 | 
				
			||||||
 | 
					    '-p',
 | 
				
			||||||
 | 
					    '/nix/var/nix/profiles/' + ('system-profiles/' + profile if profile else 'system')],
 | 
				
			||||||
 | 
					    universal_newlines=True)
 | 
				
			||||||
 | 
					  gen_lines = gen_list.split('\n')
 | 
				
			||||||
 | 
					  gen_lines.pop()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  configurationLimit = CONFIGURATION_LIMIT
 | 
				
			||||||
 | 
					  configurations = [
 | 
				
			||||||
 | 
					    SystemIdentifier(
 | 
				
			||||||
 | 
					      profile=profile,
 | 
				
			||||||
 | 
					      generation=int(line.split()[0]),
 | 
				
			||||||
 | 
					      specialisation=None
 | 
				
			||||||
 | 
					    )
 | 
				
			||||||
 | 
					    for line in gen_lines
 | 
				
			||||||
 | 
					  ]
 | 
				
			||||||
 | 
					  return configurations[-configurationLimit:]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def remove_old_files(gens: list[SystemIdentifier]) -> None:
 | 
				
			||||||
 | 
					  known_paths = []
 | 
				
			||||||
 | 
					  for gen in gens:
 | 
				
			||||||
 | 
					    bootspec = get_bootspec(gen.profile, gen.generation)
 | 
				
			||||||
 | 
					    known_paths.append(copy_from_file(bootspec.kernel, True))
 | 
				
			||||||
 | 
					    known_paths.append(copy_from_file(bootspec.initrd, True))
 | 
				
			||||||
 | 
					  for path in glob.iglob(f'{BOOT_MOUNT_POINT}/{STORE_DIR}/*'):
 | 
				
			||||||
 | 
					    if not path in known_paths and not os.path.isdir(path):
 | 
				
			||||||
 | 
					      os.unlink(path)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def get_profiles() -> list[str]:
 | 
				
			||||||
 | 
					  if os.path.isdir('/nix/var/nix/profiles/system-profiles/'):
 | 
				
			||||||
 | 
					    return [x
 | 
				
			||||||
 | 
					      for x in os.listdir('/nix/var/nix/profiles/system-profiles/')
 | 
				
			||||||
 | 
					      if not x.endswith('-link')]
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    return []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					MENU = '''#!ipxe
 | 
				
			||||||
 | 
					# Server hostname option
 | 
				
			||||||
 | 
					set boothost ${{66:string}}
 | 
				
			||||||
 | 
					set server http://${{boothost}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:start
 | 
				
			||||||
 | 
					menu {distro} boot menu
 | 
				
			||||||
 | 
					item --gap -- Generations
 | 
				
			||||||
 | 
					{generation_items}
 | 
				
			||||||
 | 
					item --gap -- Other
 | 
				
			||||||
 | 
					item --key m main Main netboot menu
 | 
				
			||||||
 | 
					choose --timeout 5000 --default {menu_default} selected || goto cancel
 | 
				
			||||||
 | 
					goto ${{selected}}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:cancel
 | 
				
			||||||
 | 
					shell
 | 
				
			||||||
 | 
					goto start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:error
 | 
				
			||||||
 | 
					echo Booting failed, dropping to shell
 | 
				
			||||||
 | 
					shell
 | 
				
			||||||
 | 
					goto start
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					:main
 | 
				
			||||||
 | 
					chain ${{server}}/boot.ipxe || goto error
 | 
				
			||||||
 | 
					'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def write_menu(gens: list[SystemIdentifier], default: SystemIdentifier) -> None:
 | 
				
			||||||
 | 
					  gen_menu_items = []
 | 
				
			||||||
 | 
					  gen_cmds = []
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for g in gens:
 | 
				
			||||||
 | 
					    bootspec = get_bootspec(g.profile, g.generation)
 | 
				
			||||||
 | 
					    specialisations = [
 | 
				
			||||||
 | 
					      SystemIdentifier(profile=g.profile, generation=g.generation, specialisation=s) for s in bootspec.specialisations]
 | 
				
			||||||
 | 
					    for i in [g] + specialisations:
 | 
				
			||||||
 | 
					      mi, cmds = gen_entry(i)
 | 
				
			||||||
 | 
					      gen_menu_items.append(mi)
 | 
				
			||||||
 | 
					      gen_cmds.append(cmds)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  menu_file = f'{BOOT_MOUNT_POINT}/menu.ipxe'
 | 
				
			||||||
 | 
					  with open(f'{menu_file}.tmp', 'w') as f:
 | 
				
			||||||
 | 
					    f.write(MENU.format(
 | 
				
			||||||
 | 
					      distro=DISTRO_NAME,
 | 
				
			||||||
 | 
					      generation_items='\n'.join(gen_menu_items),
 | 
				
			||||||
 | 
					      menu_default=entry_key(default),
 | 
				
			||||||
 | 
					    ))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    print(file=f)
 | 
				
			||||||
 | 
					    print('\n\n'.join(gen_cmds), file=f)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  os.rename(f'{menu_file}.tmp', menu_file)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def install_bootloader(args: argparse.Namespace) -> None:
 | 
				
			||||||
 | 
					  os.makedirs(f'{BOOT_MOUNT_POINT}/{STORE_DIR}', exist_ok=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gens = get_generations()
 | 
				
			||||||
 | 
					  for profile in get_profiles():
 | 
				
			||||||
 | 
					    gens += get_generations(profile)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  gens = sorted(gens, key=lambda g: entry_key(g), reverse=True)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  remove_old_files(gens)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  for g in gens:
 | 
				
			||||||
 | 
					    if os.path.dirname(get_bootspec(g.profile, g.generation).init) == os.path.realpath(args.default_config):
 | 
				
			||||||
 | 
					      default = g
 | 
				
			||||||
 | 
					      break
 | 
				
			||||||
 | 
					  else:
 | 
				
			||||||
 | 
					    assert False, 'No default generation found'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  write_menu(gens, default)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					def main() -> None:
 | 
				
			||||||
 | 
					  parser = argparse.ArgumentParser(description=f'Update {DISTRO_NAME}-related netboot files')
 | 
				
			||||||
 | 
					  parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help=f'The default {DISTRO_NAME} config to boot')
 | 
				
			||||||
 | 
					  args = parser.parse_args()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  subprocess.check_call(CHECK_MOUNTPOINTS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  install_bootloader(args)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					if __name__ == '__main__':
 | 
				
			||||||
 | 
					  main()
 | 
				
			||||||
@@ -6,7 +6,7 @@ let
 | 
				
			|||||||
  cfg = config.my.nvme;
 | 
					  cfg = config.my.nvme;
 | 
				
			||||||
  nvme-cli = pkgs.nvme-cli.override {
 | 
					  nvme-cli = pkgs.nvme-cli.override {
 | 
				
			||||||
    libnvme = pkgs.libnvme.overrideAttrs (o: {
 | 
					    libnvme = pkgs.libnvme.overrideAttrs (o: {
 | 
				
			||||||
      patches = o.patches ++ [ ./libnvme-hostconf.patch ];
 | 
					      patches = (if (o ? patches) then o.patches else [ ]) ++ [ ./libnvme-hostconf.patch ];
 | 
				
			||||||
    });
 | 
					    });
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
@@ -33,9 +33,26 @@ in
 | 
				
			|||||||
      etc = etc "";
 | 
					      etc = etc "";
 | 
				
			||||||
    };
 | 
					    };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    boot.initrd.systemd = mkIf (cfg.boot.nqn != null) {
 | 
					    boot = mkIf (cfg.boot.nqn != null) {
 | 
				
			||||||
 | 
					      initrd = {
 | 
				
			||||||
 | 
					        availableKernelModules = [ "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" ];
 | 
				
			||||||
 | 
					        kernelModules = [ "nvme-fabrics" ];
 | 
				
			||||||
 | 
					        systemd = {
 | 
				
			||||||
          contents = etc "/etc/";
 | 
					          contents = etc "/etc/";
 | 
				
			||||||
      extraBin.nvme = "${nvme-cli}/bin/nvme";
 | 
					          extraBin = with pkgs; {
 | 
				
			||||||
 | 
					            dmesg = "${util-linux}/bin/dmesg";
 | 
				
			||||||
 | 
					            ip = "${iproute2}/bin/ip";
 | 
				
			||||||
 | 
					            nvme = "${nvme-cli}/bin/nvme";
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					          extraConfig = ''
 | 
				
			||||||
 | 
					            DefaultTimeoutStartSec=20
 | 
				
			||||||
 | 
					            DefaultDeviceTimeoutSec=20
 | 
				
			||||||
 | 
					          '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					          network = {
 | 
				
			||||||
 | 
					            enable = true;
 | 
				
			||||||
 | 
					            wait-online.enable = true;
 | 
				
			||||||
 | 
					          };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
          services.connect-nvme = {
 | 
					          services.connect-nvme = {
 | 
				
			||||||
            description = "Connect NVMe-oF";
 | 
					            description = "Connect NVMe-oF";
 | 
				
			||||||
@@ -54,5 +71,7 @@ in
 | 
				
			|||||||
          };
 | 
					          };
 | 
				
			||||||
        };
 | 
					        };
 | 
				
			||||||
      };
 | 
					      };
 | 
				
			||||||
 | 
					    };
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -2,7 +2,7 @@
 | 
				
			|||||||
let
 | 
					let
 | 
				
			||||||
  inherit (lib)
 | 
					  inherit (lib)
 | 
				
			||||||
    optionalString concatStringsSep concatMap concatMapStringsSep mkIf mkDefault mkMerge mkForce mkVMOverride
 | 
					    optionalString concatStringsSep concatMap concatMapStringsSep mkIf mkDefault mkMerge mkForce mkVMOverride
 | 
				
			||||||
    mkAliasDefinitions;
 | 
					    mkAliasDefinitions mapAttrsToList filterAttrs;
 | 
				
			||||||
  inherit (lib.my) mkOpt' mkBoolOpt' mkVMOverride';
 | 
					  inherit (lib.my) mkOpt' mkBoolOpt' mkVMOverride';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  cfg = config.my.tmproot;
 | 
					  cfg = config.my.tmproot;
 | 
				
			||||||
@@ -492,6 +492,54 @@ 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")
 | 
				
			||||||
    ]))
 | 
					    ]))
 | 
				
			||||||
  ]);
 | 
					  ]);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -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
 | 
					      # NOTE: As the "outermost" module is still being evaluated in NixOS land, special params (e.g. pkgs) won't be
 | 
				
			||||||
      # passed to it
 | 
					      # passed to it
 | 
				
			||||||
      home-manager.users.${user'.name} = mkAliasDefinitions options.my.user.homeConfig;
 | 
					      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) {
 | 
					    (mkIf (cfg.passwordSecret != null) {
 | 
				
			||||||
      my = {
 | 
					      my = {
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										49
									
								
								pkgs/chocolate-doom2xx/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										49
									
								
								pkgs/chocolate-doom2xx/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,49 @@
 | 
				
			|||||||
 | 
					{ lib, stdenv, autoreconfHook, pkg-config, SDL, SDL_mixer, SDL_net
 | 
				
			||||||
 | 
					, fetchFromGitHub, fetchpatch, python3 }:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stdenv.mkDerivation rec {
 | 
				
			||||||
 | 
					  pname = "chocolate-doom";
 | 
				
			||||||
 | 
					  version = "2.3.0";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  src = fetchFromGitHub {
 | 
				
			||||||
 | 
					    owner = "chocolate-doom";
 | 
				
			||||||
 | 
					    repo = pname;
 | 
				
			||||||
 | 
					    rev = "${pname}-${version}";
 | 
				
			||||||
 | 
					    sha256 = "sha256-1uw/1CYKBvDNgT5XxRBY24Evt3f4Y6YQ6bScU+KNHgM=";
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  patches = [
 | 
				
			||||||
 | 
					    # Pull upstream patch to fix build against gcc-10:
 | 
				
			||||||
 | 
					    #   https://github.com/chocolate-doom/chocolate-doom/pull/1257
 | 
				
			||||||
 | 
					    (fetchpatch {
 | 
				
			||||||
 | 
					      name = "fno-common.patch";
 | 
				
			||||||
 | 
					      url = "https://github.com/chocolate-doom/chocolate-doom/commit/a8fd4b1f563d24d4296c3e8225c8404e2724d4c2.patch";
 | 
				
			||||||
 | 
					      sha256 = "1dmbygn952sy5n8qqp0asg11pmygwgygl17lrj7i0fxa0nrhixhj";
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					    ./demoloopi.patch
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  outputs = [ "out" "man" ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  postPatch = ''
 | 
				
			||||||
 | 
					    patchShebangs --build man/{simplecpp,docgen}
 | 
				
			||||||
 | 
					  '';
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  nativeBuildInputs = [
 | 
				
			||||||
 | 
					    autoreconfHook
 | 
				
			||||||
 | 
					    pkg-config
 | 
				
			||||||
 | 
					    # for documentation
 | 
				
			||||||
 | 
					    python3
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  buildInputs = [ (SDL.override { cacaSupport = true; }) SDL_mixer SDL_net ];
 | 
				
			||||||
 | 
					  enableParallelBuilding = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  meta = {
 | 
				
			||||||
 | 
					    homepage = "http://chocolate-doom.org/";
 | 
				
			||||||
 | 
					    description = "A Doom source port that accurately reproduces the experience of Doom as it was played in the 1990s";
 | 
				
			||||||
 | 
					    license = lib.licenses.gpl2Plus;
 | 
				
			||||||
 | 
					    platforms = lib.platforms.unix;
 | 
				
			||||||
 | 
					    hydraPlatforms = lib.platforms.linux; # darwin times out
 | 
				
			||||||
 | 
					    maintainers = with lib.maintainers; [ ];
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										91
									
								
								pkgs/chocolate-doom2xx/demoloopi.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										91
									
								
								pkgs/chocolate-doom2xx/demoloopi.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,91 @@
 | 
				
			|||||||
 | 
					diff --git a/src/doom/d_main.c b/src/doom/d_main.c
 | 
				
			||||||
 | 
					index 65a39a10..3f799b0f 100644
 | 
				
			||||||
 | 
					--- a/src/doom/d_main.c
 | 
				
			||||||
 | 
					+++ b/src/doom/d_main.c
 | 
				
			||||||
 | 
					@@ -483,6 +483,8 @@ void D_DoomLoop (void)
 | 
				
			||||||
 | 
					 //  DEMO LOOP
 | 
				
			||||||
 | 
					 //
 | 
				
			||||||
 | 
					 int             demosequence;
 | 
				
			||||||
 | 
					+int             demoloopi;
 | 
				
			||||||
 | 
					+char            demoloopname[9];
 | 
				
			||||||
 | 
					 int             pagetic;
 | 
				
			||||||
 | 
					 char                    *pagename;
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -524,6 +526,8 @@ void D_AdvanceDemo (void)
 | 
				
			||||||
 | 
					 //
 | 
				
			||||||
 | 
					 void D_DoAdvanceDemo (void)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					+    int havedemo4;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					     players[consoleplayer].playerstate = PST_LIVE;  // not reborn
 | 
				
			||||||
 | 
					     advancedemo = false;
 | 
				
			||||||
 | 
					     usergame = false;               // no save / end game here
 | 
				
			||||||
 | 
					@@ -539,10 +543,14 @@ void D_DoAdvanceDemo (void)
 | 
				
			||||||
 | 
					     // However! There is an alternate version of Final Doom that
 | 
				
			||||||
 | 
					     // includes a fixed executable.
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-    if (gameversion == exe_ultimate || gameversion == exe_final)
 | 
				
			||||||
 | 
					+    havedemo4 = gameversion == exe_ultimate || gameversion == exe_final;
 | 
				
			||||||
 | 
					+    if (havedemo4)
 | 
				
			||||||
 | 
					       demosequence = (demosequence+1)%7;
 | 
				
			||||||
 | 
					     else
 | 
				
			||||||
 | 
					       demosequence = (demosequence+1)%6;
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+    if (demoloopi < 0 || demoloopi > (havedemo4 ? 3 : 2))
 | 
				
			||||||
 | 
					+      I_Error("Invalid demo loop start %d", demoloopi);
 | 
				
			||||||
 | 
					     
 | 
				
			||||||
 | 
					     switch (demosequence)
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					@@ -558,17 +566,11 @@ void D_DoAdvanceDemo (void)
 | 
				
			||||||
 | 
					 	else
 | 
				
			||||||
 | 
					 	  S_StartMusic (mus_intro);
 | 
				
			||||||
 | 
					 	break;
 | 
				
			||||||
 | 
					-      case 1:
 | 
				
			||||||
 | 
					-	G_DeferedPlayDemo(DEH_String("demo1"));
 | 
				
			||||||
 | 
					-	break;
 | 
				
			||||||
 | 
					       case 2:
 | 
				
			||||||
 | 
					 	pagetic = 200;
 | 
				
			||||||
 | 
					 	gamestate = GS_DEMOSCREEN;
 | 
				
			||||||
 | 
					 	pagename = DEH_String("CREDIT");
 | 
				
			||||||
 | 
					 	break;
 | 
				
			||||||
 | 
					-      case 3:
 | 
				
			||||||
 | 
					-	G_DeferedPlayDemo(DEH_String("demo2"));
 | 
				
			||||||
 | 
					-	break;
 | 
				
			||||||
 | 
					       case 4:
 | 
				
			||||||
 | 
					 	gamestate = GS_DEMOSCREEN;
 | 
				
			||||||
 | 
					 	if ( gamemode == commercial)
 | 
				
			||||||
 | 
					@@ -587,12 +589,14 @@ void D_DoAdvanceDemo (void)
 | 
				
			||||||
 | 
					 	      pagename = DEH_String("HELP2");
 | 
				
			||||||
 | 
					 	}
 | 
				
			||||||
 | 
					 	break;
 | 
				
			||||||
 | 
					+      case 1:
 | 
				
			||||||
 | 
					+      case 3:
 | 
				
			||||||
 | 
					       case 5:
 | 
				
			||||||
 | 
					-	G_DeferedPlayDemo(DEH_String("demo3"));
 | 
				
			||||||
 | 
					-	break;
 | 
				
			||||||
 | 
					         // THE DEFINITIVE DOOM Special Edition demo
 | 
				
			||||||
 | 
					       case 6:
 | 
				
			||||||
 | 
					-	G_DeferedPlayDemo(DEH_String("demo4"));
 | 
				
			||||||
 | 
					+	DEH_snprintf(demoloopname, 9, "demo%d", demoloopi + 1);
 | 
				
			||||||
 | 
					+	G_DeferedPlayDemo(demoloopname);
 | 
				
			||||||
 | 
					+	demoloopi = (demoloopi+1) % (havedemo4 ? 4 : 3);
 | 
				
			||||||
 | 
					 	break;
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					@@ -1891,7 +1895,15 @@ void D_DoomMain (void)
 | 
				
			||||||
 | 
					 	G_TimeDemo (demolumpname);
 | 
				
			||||||
 | 
					 	D_DoomLoop ();  // never returns
 | 
				
			||||||
 | 
					     }
 | 
				
			||||||
 | 
					-	
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					+    p = M_CheckParmWithArgs("-demoloopi", 1);
 | 
				
			||||||
 | 
					+    if (p)
 | 
				
			||||||
 | 
					+    {
 | 
				
			||||||
 | 
					+        demoloopi = atoi(myargv[p+1]);
 | 
				
			||||||
 | 
					+    } else {
 | 
				
			||||||
 | 
					+        demoloopi = 0;
 | 
				
			||||||
 | 
					+    }
 | 
				
			||||||
 | 
					+
 | 
				
			||||||
 | 
					     if (startloadgame >= 0)
 | 
				
			||||||
 | 
					     {
 | 
				
			||||||
 | 
					         M_StringCopy(file, P_SaveGameFile(startloadgame), sizeof(file));
 | 
				
			||||||
@@ -7,5 +7,10 @@ in
 | 
				
			|||||||
  monocraft' = callPackage ./monocraft.nix { };
 | 
					  monocraft' = callPackage ./monocraft.nix { };
 | 
				
			||||||
  vfio-pci-bind = callPackage ./vfio-pci-bind.nix { };
 | 
					  vfio-pci-bind = callPackage ./vfio-pci-bind.nix { };
 | 
				
			||||||
  librespeed-go = callPackage ./librespeed-go.nix { };
 | 
					  librespeed-go = callPackage ./librespeed-go.nix { };
 | 
				
			||||||
  modrinth-app = callPackage ./modrinth-app { };
 | 
					  # modrinth-app = callPackage ./modrinth-app { };
 | 
				
			||||||
 | 
					  glfw-minecraft = callPackage ./glfw-minecraft { };
 | 
				
			||||||
 | 
					  chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
 | 
				
			||||||
 | 
					  windowtolayer = callPackage ./windowtolayer.nix { };
 | 
				
			||||||
 | 
					  swaylock-plugin = callPackage ./swaylock-plugin.nix { };
 | 
				
			||||||
 | 
					  terminaltexteffects = callPackage ./terminaltexteffects.nix { };
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										6
									
								
								pkgs/glfw-minecraft/default.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								pkgs/glfw-minecraft/default.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,6 @@
 | 
				
			|||||||
 | 
					{ lib, glfw-wayland-minecraft, ... }:
 | 
				
			||||||
 | 
					glfw-wayland-minecraft.overrideAttrs (o: {
 | 
				
			||||||
 | 
					  patches = [
 | 
				
			||||||
 | 
					    ./suppress-wayland-errors.patch
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
							
								
								
									
										43
									
								
								pkgs/glfw-minecraft/suppress-wayland-errors.patch
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								pkgs/glfw-minecraft/suppress-wayland-errors.patch
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,43 @@
 | 
				
			|||||||
 | 
					diff --git a/src/wl_window.c b/src/wl_window.c
 | 
				
			||||||
 | 
					index 7c509896..db9a6451 100644
 | 
				
			||||||
 | 
					--- a/src/wl_window.c
 | 
				
			||||||
 | 
					+++ b/src/wl_window.c
 | 
				
			||||||
 | 
					@@ -2115,25 +2115,21 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
 | 
				
			||||||
 | 
					 void _glfwSetWindowIconWayland(_GLFWwindow* window,
 | 
				
			||||||
 | 
					                                int count, const GLFWimage* images)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
				
			||||||
 | 
					-                    "Wayland: The platform does not support setting the window icon");
 | 
				
			||||||
 | 
					+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					     // A Wayland client is not aware of its position, so just warn and leave it
 | 
				
			||||||
 | 
					     // as (0, 0)
 | 
				
			||||||
 | 
					-
 | 
				
			||||||
 | 
					-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
				
			||||||
 | 
					-                    "Wayland: The platform does not provide the window position");
 | 
				
			||||||
 | 
					+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not provide the window position\n");
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					     // A Wayland client can not set its position, so just warn
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
				
			||||||
 | 
					-                    "Wayland: The platform does not support setting the window position");
 | 
				
			||||||
 | 
					+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window position\n");
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height)
 | 
				
			||||||
 | 
					@@ -2359,8 +2355,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void _glfwFocusWindowWayland(_GLFWwindow* window)
 | 
				
			||||||
 | 
					 {
 | 
				
			||||||
 | 
					-    _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
 | 
				
			||||||
 | 
					-                    "Wayland: The platform does not support setting the input focus");
 | 
				
			||||||
 | 
					+    fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
 | 
				
			||||||
 | 
					 }
 | 
				
			||||||
 | 
					 
 | 
				
			||||||
 | 
					 void _glfwSetWindowMonitorWayland(_GLFWwindow* window,
 | 
				
			||||||
@@ -81,7 +81,7 @@ rustPlatform.buildRustPackage rec {
 | 
				
			|||||||
 | 
					
 | 
				
			||||||
    dontFixup = true;
 | 
					    dontFixup = true;
 | 
				
			||||||
    outputHashMode = "recursive";
 | 
					    outputHashMode = "recursive";
 | 
				
			||||||
    outputHash = "sha256-9HtTdIotG3sNIlWhd76v7Ia6P69ufp/FFqZfINXSkVc=";
 | 
					    outputHash = "sha256-Txttk8qZpDsAuiF8laKbZss/KEoT1Z+oepbj2s4XjE8=";
 | 
				
			||||||
  };
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  preBuild = ''
 | 
					  preBuild = ''
 | 
				
			||||||
 
 | 
				
			|||||||
							
								
								
									
										41
									
								
								pkgs/swaylock-plugin.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								pkgs/swaylock-plugin.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,41 @@
 | 
				
			|||||||
 | 
					{ lib, stdenv, fetchFromGitHub, fetchpatch
 | 
				
			||||||
 | 
					, meson, ninja, pkg-config, scdoc, wayland-scanner
 | 
				
			||||||
 | 
					, wayland, wayland-protocols, libxkbcommon, cairo, gdk-pixbuf, pam
 | 
				
			||||||
 | 
					}:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					stdenv.mkDerivation rec {
 | 
				
			||||||
 | 
					  pname = "swaylock-plugin";
 | 
				
			||||||
 | 
					  version = "1dd15b6";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  src = fetchFromGitHub {
 | 
				
			||||||
 | 
					    owner = "mstoeckl";
 | 
				
			||||||
 | 
					    repo = pname;
 | 
				
			||||||
 | 
					    rev = "1dd15b6ecbe91be7a3dc4a0fa9514fb166fb2e07";
 | 
				
			||||||
 | 
					    hash = "sha256-xWyDDT8sXAL58HtA9ifzCenKMmOZquzXZaz3ttGGJuY=";
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  strictDeps = true;
 | 
				
			||||||
 | 
					  depsBuildBuild = [ pkg-config ];
 | 
				
			||||||
 | 
					  nativeBuildInputs = [ meson ninja pkg-config scdoc wayland-scanner ];
 | 
				
			||||||
 | 
					  buildInputs = [ wayland wayland-protocols libxkbcommon cairo gdk-pixbuf pam ];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  mesonFlags = [
 | 
				
			||||||
 | 
					    "-Dpam=enabled" "-Dgdk-pixbuf=enabled" "-Dman-pages=enabled"
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					  env.NIX_CFLAGS_COMPILE = "-Wno-maybe-uninitialized";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  meta = with lib; {
 | 
				
			||||||
 | 
					    description = "Screen locker for Wayland -- fork with background plugin support";
 | 
				
			||||||
 | 
					    longDescription = ''
 | 
				
			||||||
 | 
					      Fork of swaylock, a screen locking utility for Wayland compositors.
 | 
				
			||||||
 | 
					      With swaylock-plugin, you can for your lockscreen background display
 | 
				
			||||||
 | 
					      the animated output from any wallpaper program that implements the
 | 
				
			||||||
 | 
					      wlr-layer-shell-unstable-v1 protocol.
 | 
				
			||||||
 | 
					    '';
 | 
				
			||||||
 | 
					    inherit (src.meta) homepage;
 | 
				
			||||||
 | 
					    mainProgram = "swaylock";
 | 
				
			||||||
 | 
					    license = licenses.mit;
 | 
				
			||||||
 | 
					    platforms = platforms.linux;
 | 
				
			||||||
 | 
					    maintainers = with maintainers; [ devplayer0 ];
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										19
									
								
								pkgs/terminaltexteffects.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										19
									
								
								pkgs/terminaltexteffects.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,19 @@
 | 
				
			|||||||
 | 
					{ lib
 | 
				
			||||||
 | 
					, python3Packages
 | 
				
			||||||
 | 
					, fetchPypi
 | 
				
			||||||
 | 
					}:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					python3Packages.buildPythonApplication rec {
 | 
				
			||||||
 | 
					  pname = "terminaltexteffects";
 | 
				
			||||||
 | 
					  version = "0.10.1";
 | 
				
			||||||
 | 
					  pyproject = true;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  src = fetchPypi {
 | 
				
			||||||
 | 
					    inherit pname version;
 | 
				
			||||||
 | 
					    hash = "sha256-NyWPfdgLeXAxKPJOzB7j4aT+zjrURN59CGcv0Vt99y0=";
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  build-system = with python3Packages; [
 | 
				
			||||||
 | 
					    poetry-core
 | 
				
			||||||
 | 
					  ];
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
							
								
								
									
										18
									
								
								pkgs/windowtolayer.nix
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										18
									
								
								pkgs/windowtolayer.nix
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,18 @@
 | 
				
			|||||||
 | 
					{ lib
 | 
				
			||||||
 | 
					, fetchFromGitLab
 | 
				
			||||||
 | 
					, rustPlatform
 | 
				
			||||||
 | 
					}:
 | 
				
			||||||
 | 
					rustPlatform.buildRustPackage rec {
 | 
				
			||||||
 | 
					  pname = "windowtolayer";
 | 
				
			||||||
 | 
					  version = "a5b89c3c";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  src = fetchFromGitLab {
 | 
				
			||||||
 | 
					    domain = "gitlab.freedesktop.org";
 | 
				
			||||||
 | 
					    owner = "mstoeckl";
 | 
				
			||||||
 | 
					    repo = pname;
 | 
				
			||||||
 | 
					    rev = "a5b89c3c047297fd574932860a6c89e9ea02ba5d";
 | 
				
			||||||
 | 
					    hash = "sha256-rssL2XkbTqUvJqfUFhzULeE4/VBzjeBC5iZWSJ8MJ+M=";
 | 
				
			||||||
 | 
					  };
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  cargoHash = "sha256-XHmLsx9qdjlBz4xJFFiO24bR9CMw1o5368K+YMpMIBA=";
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
@@ -1,10 +1,10 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBJYzdr
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBrMXND
 | 
				
			||||||
b1d2aEtVd3lVb3NBamRwVFpTaTRjZFlCczk4MVIwQUoxWklwN0NrCmFFekpPYUlO
 | 
					Zm1ma0FoNE5lWTFNTGlyeUQzdUZxMkxyVlU0cWdrcTJEakhDVXg4ClkyczJDR1FL
 | 
				
			||||||
YlgvVlQ2WDR6amZDN0ZSY0Q3WWtTME5pUmhQeks1c3dGOVUKLT4gWDI1NTE5IHVK
 | 
					eXE3QWFTM0wyeDNvL1gvcmx6eGE4elNuZW9wRHhJZ3Aya2cKLT4gWDI1NTE5IDhO
 | 
				
			||||||
bUZvUVAvL0NmQzFkY3BuYm1wMjcwbFpLRUNpZjJCaW15SEVDUDV0REkKRXFMQ2d1
 | 
					S2JWNDhlclpERFFUTktyUG5HbnNxcVQvWmphOGp1cmNpK0NGZWVTejQKN0dybHl5
 | 
				
			||||||
NlFBejBvTlJrcUtCYWZxSDBkbmxIdExBNTU0aC8zRW5OVWllVQotPiBDLWdyZWFz
 | 
					eHhicFNpUHQ3WFZDQS90NG5VZW5zVm8rcUxCdkZkOFVqdVFzRQotPiBBLWdyZWFz
 | 
				
			||||||
ZSBkeC4oTFUgO0FtJG9+RyB2IF1QXGhxVwpJS213MXBRMWY1cXlHZwotLS0gRUF2
 | 
					ZSBaIDMiRCBYO1g6IF9EawpJZwotLS0geXhWb1FORm00RVJoMm4zQjhBT0hERyt3
 | 
				
			||||||
ZkswNlhvcDhTc2tybCs1dldwa2l6SDZZVmNkNUNjNGlkV1ZVa09pOAp88dxHGxVU
 | 
					ekM1YXNzdTgzUTVMeHNsNDUwbwqSjgIVhg9bqtIydYC1FCA4ly2gurTcb1SUCMG8
 | 
				
			||||||
vuFQO6JcroY9MF5Te/YV+wMc3hVxksibMnH1TWGh207prwcOWNOEz2iEkZY=
 | 
					XA9WAx1jv05xje+U97tRTTongJEW5vw=
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,17 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBLVlg2
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBjQmZr
 | 
				
			||||||
ZUdtUlFUQXBLT3B5YmkycWJnMXJyKzltbyt6K2dJK1RBUm5ydWwwCmRUdjJFSEYz
 | 
					VDl4TVlzK0lCc0YwdFM3TEptU3Q3cWZ1d0FJQUI4Q1g1TVNyOENFCkU4NE5lYVhI
 | 
				
			||||||
Wnp4cGtzTXZwc0s0SUJQUjRlOUJlQUoyQ3BETXZmY0ppWG8KLT4gWDI1NTE5IGR5
 | 
					d3B0amFJT1A1RTRSaUdUSmZ1WmU1SkVhTU9sdFZJR0p6UXcKLT4gWDI1NTE5IG5O
 | 
				
			||||||
QUJzeG1DQTRLUmRwNnNSRUJRSFFtUDl5VjB0clVLYUp3R1g4TEVKaTgKb09tVlhF
 | 
					RG1SQnZtSUk0SThNYkRpOHFPS29kbjdUenZyYjBBSTJKdXNUaGpYMG8KME8waXJ0
 | 
				
			||||||
R0tmcmIxMHVHcG80RGxRTEhBcngvT3MrdnNPbmpCTlRyZW5xQQotPiA6RzEtZ3Jl
 | 
					NWR2NHoyUkN1UUJoaVRxYXVMZlNvTHZqRmYvS2h4QjZpZm5NZwotPiBPclJULlkt
 | 
				
			||||||
YXNlCldSUlN2ejB0MGpyUHYzNS9OQmJTK3MvcXRDakdBVlhuUEt6SFE4QmhnWVN0
 | 
					Z3JlYXNlIEVdKEBXIDUgXTBzIi58TwpweFJEcUFpR0x2WWhiVDlOTFArenhjNXBB
 | 
				
			||||||
V1JMOE1oaEp5QQotLS0gYW1OMTcxNWJrUndmR2h0ZmRDWk5CYnJjc29pSERUMnNk
 | 
					dVo2d1JQWEJyVHlTRnUzdUlFUE45RWlLU3ZRS0c4UWs5Nm1qVHorCko1RVdqOVdz
 | 
				
			||||||
d2VhTGdpOW4yUQrEeH2E9m0YycuW60QrdlRetO1kNU5FaKXRQt46iA9lACIWD4rC
 | 
					aVAwY09KOUx4WktIVFBQclFXdFJZMTNVWHNKcTZFbDU5Q0xLaExvNVdlZ0pTczUr
 | 
				
			||||||
Cx6WxhCBgz3hvm9x6iuYiiQxZzgJNK7qXcV2MBeQdivazeEbC7blAKVPhwD/dl+b
 | 
					SkVDTzhDUysKCi0tLSA2VGJMM2lrNkViaU0wcnArSG9PemJrQ3lrUFNnRDRVeE1p
 | 
				
			||||||
PzBDXRXG3c3jMjeZFT69fIBGJfZrrLGKpTALVE4dTVXmQmVVQDTp19IC+jUXHBti
 | 
					V3lxeG1iN3I4Ckf36lD/b7agsT0qW8eGDnxsVor8hEmLBSa35/eeAxqMd0xPvQko
 | 
				
			||||||
Pj6Dpc7452s8zPkzZyRbasO9b4PYTwq8IHT6X7ITwbzZZm8gexDYe2SzRZ5VcPz3
 | 
					REzIxPuEHRQM5dE4s4H/mySTC/AVsiwfcMrnOXInm4o3MNAC9PREcef4NBOP3IMl
 | 
				
			||||||
El+yoULZ92WbXPSQIP/Slx4BEZjmsQS+sm0N8AnBRNZkWVbHPF9IZRg3VjDAn2i8
 | 
					Mcoifar27EXs21XdXw/lLOVNDX7oDKZh1zXVX4lFTcRW0v8abbwchvuTiayKePMG
 | 
				
			||||||
F3un5js=
 | 
					DrcyFsj4jiwpJ5MmY/Q+n0lZmoAlAJkeTHRUptJxGMq+pWVEGMa8p1vUdrVwWq7G
 | 
				
			||||||
 | 
					YYO5lPlms01BFJfUsysh07HY1HPkOyFHeEkviZtt4N8hopx0pP4fyAZYYdrBAIdt
 | 
				
			||||||
 | 
					CLpQFQ==
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,12 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyAyMWox
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBETE9p
 | 
				
			||||||
cEFDWWUrVzJSM1o2azJqei9HV2xFY25oQXV5SzM3akxEaUJiN1J3CjkrQVhjWHY5
 | 
					VVVHeThGT3daNW1xZjBDblFwQWozQ2VSUmR3NlJVak12YXdWUDNNCitTWnBHd1Mv
 | 
				
			||||||
Uk01eGp5Q0RKNVREVXJVZytndTM0SXNZSGIvUVp1TnRiNXMKLT4gWDI1NTE5IFZn
 | 
					L2ViUWJvR0dtckpTQnRNMWZtazZHQ0tON0RhM0Z3cTlYVUUKLT4gWDI1NTE5IGhV
 | 
				
			||||||
WjAyR1RMajEyMnFSYnNGT2EyekROVWNoakFJQVZxaFc0YThOMHVyanMKWldrdlAv
 | 
					ZEFqcW9CcHUya0s5dmgxc1JqUWRicmpXTllIckxaWjhtYzMrOFp0R2MKNUcxVllk
 | 
				
			||||||
cVg0OTFHL2loeGJ3RHA0MnlnckN3czF4RUgyc1NjYXVOSXF5cwotPiBvTFQtZ3Jl
 | 
					WWJ2cEkzdXdiVFNDQVN2cUVNRnlMQ1BZWEx0QTI2M0FKSHE1ZwotPiBHaCJASk9u
 | 
				
			||||||
YXNlIDRsSDp6eikgT1ojIGEzOFZMIFc3MUZGCkttZ3ZLNGxucnlJc01kRXFZTGpC
 | 
					LWdyZWFzZSBsIFxuClVieGM0alFSdmttVjVsNDZIT2hjSTdWc1Z2VXRIUC9BbXNL
 | 
				
			||||||
eCsvRzl5WnFUMUIyTWNVWGk4SjQyN3V0bXQ4VzFuM1RjSzVMcDJkaW1JYXMKQkE4
 | 
					MXArcHI2eDM4QWwyeXhtMU41cEtLQ2tkVllJdjkKTjMvNENSNXd1UjV2bGQzbnJx
 | 
				
			||||||
YWI1Mmg3MkpjdVpVYWJkczJQMnM1SVMvNkZhOXBDVEZPCi0tLSB3SVIyU3M5RHBE
 | 
					U3RubVRxQXVSSzJXbG5uQmcKLS0tIFFIeEVhR29qY3FBaUlJd1M4K3FvdDNybHZB
 | 
				
			||||||
VFRtMFU4OUFLbkNjbkJmVmhlc2VsYzdsd0pFaFkrUmkwCs+h2KlXoyZ8U++A9wmV
 | 
					MmVMZGxyYUYxVDNydjZLbXMKiPpxBn4WtzaH2iTFfjayYgNFPa0Mi6tIH0LOqkAj
 | 
				
			||||||
kh4N2YyI/a84yPGDNoFdSlXaU8jxUzolnadImXSXyB4CroqQLvGEbkZZlWqPLVfh
 | 
					RyHNF/6vgWlmnivbhP+74dVaqR8IwUdFQN7S8/fx7eW/7qvtlg==
 | 
				
			||||||
Iav7Ja8=
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----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-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB2WFY2
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USAwa1k3
 | 
				
			||||||
MzFnVFYvb0wzc3grRDBrUi9teW1tNmx5dVBIRVc5OUdlcjdvTDJFCmpJL2tlYXND
 | 
					S3dka3ZjcVdIQ2hSN0xsb0hTNEhneXFYS3BXNWZDVlBNc2toQ25vCldqSlMrT0hB
 | 
				
			||||||
bVJKbzd2S3JkSFVMdG40MS84V0lPTVJSNHVBQlNXSkN1eTAKLT4gWDI1NTE5IFBM
 | 
					Rkg2aDZUYlY4U1E4Y2djMVdwT1VsbGdpUm12Z3gzditmMncKLT4gWDI1NTE5IG13
 | 
				
			||||||
ZGo3L2VlNUZqOEE1UHBuMHdqc1pyYlQ3R29ucE9pajU0bHMzamlXRDAKcG1Qdmw2
 | 
					YXF4WWdmNFRPR1JDWkk4OFZkSjdzRS9BbXVzSC9YNG5FRnpqUXJZVk0KV0tOSG9N
 | 
				
			||||||
cUlncDFWNXBOWnpIeDNZSFA3d1E1bjNaVVpKU3lMRjRaSHNtMAotPiB2XUh8eF4t
 | 
					c2VVWE10WkxUZXpqZjBZZUQyWE14TUFsdStMeWVlcFdJaTRVUQotPiBWaHxWdCYt
 | 
				
			||||||
Z3JlYXNlICUrO0cxIH4gaTRoIF81SEpTN0Q5CnpWdEZpb1hZa2t5YkE5RnJFMHVZ
 | 
					Z3JlYXNlIDYgdDsgcW97Ii5yIE95Clhqa3RVUmJENngwTDNoR3BCNjlaTkVYc2JR
 | 
				
			||||||
WkhkQ2o0eWtyOE9ueDJkeGd2aUhmLzRUUGs1aUc1NURIOTYxczZhOEVmT0EKd2xk
 | 
					ZWQwb2FOVy9sc2d5MmtkeUhkajJBOFE3TWJTOWViWVlJSTkxWQotLS0gN01aNGdm
 | 
				
			||||||
TXFHN051d25PQmtNUVZkVEFGUVliZjdmZDF3RWFkaEhNTzd3ZVd5N3dlNzQKLS0t
 | 
					VjR0ai96VzRqb3QzYU4yRzVCby8ycVhXVlpubVptam5mYldoOAoZnbsXB5we9BQ5
 | 
				
			||||||
IGZDR1Mxd24zOW05bitzQnN5WWVOOGtCNEc5aXIraEF4eXFUQm5CZUdCV2MKd44C
 | 
					AXQ08mXmMxRMg9iH7qgyCVc1ywR/uo5Fcefhuw23TyluRkYt7tZ9yiuFJIx5Znsr
 | 
				
			||||||
/Trgg0OEZ89/jqbj56z/Hia1Ka3ZsEv6bXPI/kcRvFDBFTgtvG3KWCgMBtTUHXzY
 | 
					QEqaBioL1UfePVyDLi8LcBvUgnnx5uN05hUvTOt6gqaE
 | 
				
			||||||
TKBPoQqrUf7plH7a/mTx3KR+4Y+yF+1i86s7TzYjD8d1xfFH3BsVtg==
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,30 +1,28 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBuQjBY
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBvdjZT
 | 
				
			||||||
K1ZTUzR0SmFoYUZLdzUzNUt2M1B4RFdPZzFkcW8rMWJLUjVHOUN3Cjd3ZHdMSzdp
 | 
					WWFyNzdXVENweXlVT1kxNElaUDFUSG1DSGMybTZlN3VKVDNNMGdBCklDRk9oaXdT
 | 
				
			||||||
OWswditVWUhYNjZCdjV6M1d6U3pNak5hUlZjTHNqSkZPSk0KLT4gWDI1NTE5IGNG
 | 
					MEhrR1VTcGE2NWwzdW9NQklwcGFsd1BWSXBpa1YzREdTUUUKLT4gWDI1NTE5IFN4
 | 
				
			||||||
ZytHazJQWTExMjNkZWV2aDUwcnZjUGcwcXRkZWl0M0F2R2JpUVlJekUKWTFlbkEz
 | 
					Nlg1OXFNMjVzbDlRME01WW5iMTZvU05hUTExNnB4MFpUQ1QreXFXbmMKb3BzamRT
 | 
				
			||||||
YlN6dkgrMmFFcmlZMjQ0b2oySjlEMC85cUF5QlA4NGF3blBKRQotPiA8M1hbWS1n
 | 
					OVM0TWZIdkJnYlByRjRQUXNtQWtXS1FXRVlFTkpSNHFVTWV3OAotPiBpQy1ncmVh
 | 
				
			||||||
cmVhc2UgOmlZJFYmJgo3UExzUHhSVi9lbVRjNW4xTnVaUTVGSGVDNzRUNlJ2TnVu
 | 
					c2UgJT9RYi1YewpadEZzVUpqc3F4U09zUQotLS0gWkg5ZWlxYUJGMUVDd2o0TTJT
 | 
				
			||||||
U0wrWU5kd3dyR2phcUNVUHJCYjdzeWhjNVFOV011CmZMOVN0WDk5eUg3ajhwbStQ
 | 
					OTk0WlJ2aE96Z3FGNmQrNEx6Z3N5UkRxbwrp1nF8mtgoTEYfQ/aE7KgzFOei1PVt
 | 
				
			||||||
aHExT0EwblpreTBXVHh6Zk1HRkhzcmFQNnoyVUlaeStMUkgKLS0tIG1aY3Zadko3
 | 
					cLAh3v7wo7C3lxhBOL0v8ToIAVgSoGP6cj9/4k7+9GngpOgot0IOdoXsThVdcg7w
 | 
				
			||||||
V3pDMGswSDZCeit4SVhSRCsrZVRVZVkvQkNsQWN1MXFMUGcKcK74YULWqWw9VvkI
 | 
					soDjArsSWDYn6Th0yZf+trSXfA24BKIS5qQnAMT2ivQQtO9Kqxko2Zj6+wZO4LEj
 | 
				
			||||||
NH38VHfDPW5ueSiyHHKn8MI9YosPr/TmkwgKd/DOIMVB74ahPalo1QUeg+eaBVnq
 | 
					DEr7cqRCWVFfvPLJurkfbCRjGlW2rKMlJotnLMYTE+Ot5SlSwVic5Nu3inGx1U/a
 | 
				
			||||||
Uncsbx5ecW3JswthkAhiktWHcdHmioGD6hCcgbWtfA3VvbAYc2gtAF2plfDVH6BD
 | 
					gKjCPfWw1h0Gus6PKXpSq8wGrGp+ov4ocpDmumbgh/E0D82JtBBPoWojxuGSFzrm
 | 
				
			||||||
c8veai3B15ZmDmq3b62sgVA9JUgbFaB1eRqcaPXmNgQJR4c8J+CZWXGQ/TKMqtAg
 | 
					UDKrgx7MObGbjwkj5Xd+SDdKytjNqV+9g8GdRYVGhIr3muLn2JJlKKw/eD4Now86
 | 
				
			||||||
chCDuczjLX8IxhMPF1gdCggSt5GtMhY47fpZJRbBUw01l8koqjm63KvEeg2ejFGU
 | 
					tPB3ms/E1N0HR/LoQ/Y65WeuHKgv55CZMWauC/1ECxVS/jDAXnQ2lAqFlzmU1ItQ
 | 
				
			||||||
+tXonI4jm2JUxlDTqmNSrVpmAgtPoEPszHc+GsnyNjAz4IXMm5UrQAZyDPgxtwQW
 | 
					4EefV7FRWxgMeMOIVKOCus03Js4yZp+5byjJ7+O3MRrOED9/M60B60zXhvPDtwb3
 | 
				
			||||||
ZAn0IdOB8rSL/AnRGUpPrecuauINQjONe8CapijjJPQK7g1AHscfxr+OJD1j2eV3
 | 
					D5sFtC0ZBZT1+d4pUnEnLzSjM8DTf9as1uoNSuzh6ASiSiepAhdKMNtS8xzo85bf
 | 
				
			||||||
O6TNlz8vKW4t/V7CUf46ykxxExhA0mKJ53ksaXy2+HWoro2+c4nao/bEld5gt08U
 | 
					Yw2WxiXQfSyN2xWWjSH/YQUXKZRBNATxB0FRMaa1TOFKo0dDYOAu83bY7wwAwSvZ
 | 
				
			||||||
uCpJtjPKB64X6vdzbY21/l87VRDyxbb3poENfrXlawqS0Z7i2gAbHN5EuiMv+35o
 | 
					zCZ1QepCCjiWe7ujd9HMPWDgnvd47c8teSYgjX0T4nCEk7EbNpUcrDXcz78ZKAlm
 | 
				
			||||||
sBaR0BfcbTn6VagC3i8HEEOO964FrW65pkqmGJcJMgUdcZSl+Y7gHMjWyodqGPOY
 | 
					VNuu8C5oi5Lk7972SBLj6yLpj27FDMagSvX30k1sMoHcKGiKnkSkdw56B+yHwLYL
 | 
				
			||||||
evT6xj4iyeM49vXynV2vrJRu5rr02hOS/8rPphV9c9q9ju5n8xbhS6IiybAelPwt
 | 
					Iic2mxklXggIYLo1gNq0tQskp/I0dFGUzAF1AblLw0b9Gqj/fHwHtkx/Q5n+NE82
 | 
				
			||||||
sa+xM+w0n+fxVksiXeFj7qD1LDN4+kwqhYP9SlzbA4fT3AkYYrxthTww4IFAweyQ
 | 
					jSVVRTI444cMlXKnyk2sVKKOWR60WXQWs/GdH5Oln42tmFT6yZk8OV7RopLPUXx2
 | 
				
			||||||
IJkpVL0/IZEIEfRzpr0lWLprAaoyPc64pecl0z/gBJDgz1kSG6iEh6K4qx7ahGde
 | 
					4jwwWvVOrAMhmTwJDbzUwEIm/nfay7wzJinjNod67u0muq79OP9k0pRB6u3mSYZ4
 | 
				
			||||||
kBBpS2I2ZsdBkvmQxDSM7tYYBzPxcUNZlSFOIeUy3Xl+OGPlKgtMofbnjV8AFqUf
 | 
					ZX3RhRoIYiYHCDrw0e8eWKjlhzaA7tI+diHdC62SR1cUbYbRrLiXrU+ZPjG2qDTI
 | 
				
			||||||
tOpgKpLUEkTgXbGUKBxHLj+8pbw7zOFp4sJ00i48ZzLP5D9jom+jS19wGshRc7cH
 | 
					eAI8/wUMSHNyXdBejLRZHy7l38LKzAG3SSWBtNuCpAiP/QWCFL4UyEMlQ3Fmmzp/
 | 
				
			||||||
dK92CctvrfndQ85yO0vqlyOdMTqjh/z3P2KmhL5SW6P51q5mseTvj7FNM7331DTs
 | 
					FDgNLldzhOMDK8eqGAgG+qVRaK+30SJc2/ydjilg2H/KxK8C4F7Q+ul3QV+p66KF
 | 
				
			||||||
rq7XWaBLE61eWWQ/dZKnqh5YbkSlU1+08Rl6H/vCU5hTC8fht3KTQSWPofkrP+5f
 | 
					D0h1JpWxSRhK5St01FdtFigSsA2QBg4kP87gGFmI/y05jbj/XjG7D3BQtBbRnKVG
 | 
				
			||||||
We/Pe62LyhV/MbLRA0nmU7Sf4IAnpHfa4kLtlYeB3xiqKd0McM//qzjuk5NoIgE4
 | 
					uQ==
 | 
				
			||||||
nL0T8YXdGt8K01w+nt+j5bo5gFoRz5+1/ZZ9BgN2DOo4SClYnJWQ/x80X061yJ33
 | 
					 | 
				
			||||||
0SGv4eAC3vFi6xE=
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,16 +1,16 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USA3MEFh
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBQMEJB
 | 
				
			||||||
YURySHY5RjVQa1c0QmMvTkZtZElNd1BIeDFpR1U1YXZ5dndnclUwClA2M0ZYMk90
 | 
					VVhIL2ViVUx1Ym9IbFV1UW52NjZYMmJlYmpjY0RuMzhiclJVS0ZnCkY5dEZHTHlC
 | 
				
			||||||
RmlCZHVISkxZQTZXeEhZVUROSVRGRVg4TmZKZytSL05FcTgKLT4gWDI1NTE5IFY2
 | 
					K29uamorWWNJSVV0VlVJNG1VNm9GQ3VPdldJRDNSODVoOVUKLT4gWDI1NTE5IEM0
 | 
				
			||||||
V2k3S0VQdGlQZ0hkU2ZoSWdOUG9rQ0p5Ukg3ZHU3MXVvNHlWYVN5VVUKcWtoWDJh
 | 
					UVQvLzFYRTRRMldWSnNnd3V3aXJTeS8vZ1hkdENYVHk1QVVaQVEyQnMKVmN4OUFH
 | 
				
			||||||
LzRwcktWUGQ1bnJvRzVBVlpHU3NhdzYwUDBPTmx3MFNrdWNQYwotPiBKQil6Km0t
 | 
					WCtVSW9tREV5RExycnFJejk5UW91dzd5Rm8vcFBTT0ZCdytFWQotPiBCPC0lLTJW
 | 
				
			||||||
Z3JlYXNlIFdlRTlUU2cgVlxLIzUgJlVyQiJ8Cng3NzF2b3d6MnlEdURQWHgrSFJv
 | 
					LS1ncmVhc2UgRSBjOlg5a0pdQSBSb2YKN0pkalY4VlFDMm8vZzJpQUV4TmdSRHA2
 | 
				
			||||||
Y1BMUkZyelJSdDJvUUUwY1k5R3ZBMnJaa1R4NWxlUll2azNseW5MQlpvVWUKYUdN
 | 
					dnB4UzJaWTRXeDdmKzFrUGVMSEFlbFhlNFFycFRQU005d1I2Si9VUQpHbDVxcGxn
 | 
				
			||||||
d1ZscXVxd1dxSGpzMjBYeWhhYyt5ZlNkSjhmV1ZTTDBTCi0tLSBBTG45VUJOSXZv
 | 
					SVdjZzduSGluYlZnY3lmZmtnOWJYKzkydDhKU0VCNmNvV0EKLS0tIGdaUkpGNy9P
 | 
				
			||||||
N3lYNVlyZldMVkpZdUMvS21NdSswVmU3VThZK2M2eis4CjwfWWJVR9Ty5dBXEr5s
 | 
					Y3BGVGVJenJkTG51c3Z3WFU0eTFXT09pSVFseGRLMmxJVU0KhH9EjbL0zv821Yox
 | 
				
			||||||
U+QrifXvyMJJvqOKEfMYYomFLpt/VtbDAUwNlqLnFIk1VZ2xPUBisXPtReiCK3gq
 | 
					FXc54SXGEkq97qPi3xIoPydWd3FbIuftAhe0xPFGfUOO5/zDni4h+PoNJs2hnkOK
 | 
				
			||||||
P+i6bUONSmPYvmF82VgiuKDuz/kmWqVGg2iSBPIXAGLNIEojndQwmhnrsN9ex4Xy
 | 
					kHhxtaOj1S6RulI/eYLK/fJjl2aRrTaRFN0TGhFwz5X8HOQe2+Qrq/9wT7pyzOFU
 | 
				
			||||||
lBHkvVsN8EamUJwZ+FEZe4+PjA5yEnANWpeTELOt2gA92/jwwnNIsr07eVTlkh8X
 | 
					LsMwe71OhTjA5XrBTawU9QkWjPx2LZyb/WEkzlLOCGoHTUm4X03xY/1UeHVYZt2k
 | 
				
			||||||
UmQ2owGwktXP7it6//NV3C7sAdazs2bX65WSnog2E8WPNAorKWI8RCYs33CshVFt
 | 
					wbLses0JHK1h2ttWnO5y68LovZWJqFdIjoCCkgfo0nNUD5i+e51xEju9OBJMngj+
 | 
				
			||||||
zzclZ4hRmlAmqMHYqFY=
 | 
					LnPb6YCqFh4Fxy09WORD0A==
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,13 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBoYlRq
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBmSkJo
 | 
				
			||||||
ckk2c21uMVZSR05SdlJpck5MT0FZeUpLTmpTRVN2WDkxWWxmVTBvCjlHZWtEQ2Jh
 | 
					UzFYMVBiNTRBbnliRHh1OXBpME05dUpyYjg1ZVY4WStxRXg4VTF3CkpGQ0Fia1Ew
 | 
				
			||||||
YUdybjJLWkNsZkxabTVIR0JnMno5YlMvVmhodDU1bktrSzgKLT4gWDI1NTE5IFZT
 | 
					RnBsLzNJZEZMaER0emt2TFVSWHBGcEo5MnYzVDlvOEFrUVkKLT4gWDI1NTE5IHh3
 | 
				
			||||||
Um9lWXhqRFFLTWdNaTR3Sm1acmY4N0l6WE1FSW54ZEtQcEE5RHBRRHcKcE5KYmp1
 | 
					UC80K1piWEdneVExSmQydHRqMFdTL1djd24wL2pDNFc3bjNxc3hZekkKTlI3Umh1
 | 
				
			||||||
WVdCVk0wMHZ2SCtUR0xKWU10N0xETXlXZmgxcmZZOFBXYWtBawotPiBlRm1gKGxU
 | 
					SmdBM0Ziak5GRm12K0pMckZ3UGZXZTNPMm5hZ3lTV0NFVlYwMAotPiBHLWdyZWFz
 | 
				
			||||||
LWdyZWFzZSAqXF8gOkU8Tm96IGA4IC1TCjY3NUgKLS0tIDhjaTNrbG1iQ05iTWRS
 | 
					ZSBddkFIRWdHIyBjOXwkT3MgJiBOcUkqRwp6VUMva2JWd0J5ZjBpemFFM2djTzNC
 | 
				
			||||||
UzIvNzA5TmVGS2ozZmYrYjlBY3J4Z1RRUGRNeWcKUTIEhWqr0fOODu86MDll7k3U
 | 
					RW5POHIzOUZFOG1zRElPMkZZZUxmbklpY1V2R3lqNUtOYnFlSUVMZXlrCnB6REdz
 | 
				
			||||||
ThgmS9nlcUY3fMgXzZLtpHIJ/4ZSI+miu8RmLMaeC61qv6xNThGdx+MvU4tMBWKA
 | 
					ZHFzbmRjMm5mM0RGU3NzeUl2bHBhTEx5MjhXRTJBLzJZRWgyUQotLS0gV1VlUkRD
 | 
				
			||||||
Hv3XGi2MYL1jdHh2KYg5PgdqchYuHrFuBPS7c/tQow==
 | 
					N1ZTZnMwTWN5SXEvQnJaK1NmcEUzMEJ6UVcvb2ptK3VYZU5zNAqgntLnLkQABERv
 | 
				
			||||||
 | 
					HpNr21t8+KR56PZ8nQS8xALzw/FzdexGvlt4Pzx6o0daBeh4aZx4mgcyG641PsRc
 | 
				
			||||||
 | 
					eDs4tJm8gmznr6y7B+WNC6WGrWPPIC3pHKU4g9PWzyEZcTEpL8Fp
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,82 +1,80 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBZVkFh
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBtVUdX
 | 
				
			||||||
RDNNZCtySlNQTTZFbzJvZmF2TEZKVUM5VjFjQWNSeHlNc1JNZ2hNClVac2pEdWdw
 | 
					WWlWOU5Pck0zSWFETUhMZVI5bjNUUk9pc0dRVC83TEJIN0V6aHlBCjJvWkxSaGNq
 | 
				
			||||||
OVpOTmhWWklVRDA3UzZWWk9QVG1ySUFmTzRSVlFReVdFVFEKLT4gWDI1NTE5IDVD
 | 
					WmxJSEhFekRLSE56K0pDTkxNRlJhOGZTWC9RdEZ4ZGJQNkkKLT4gWDI1NTE5IHNy
 | 
				
			||||||
eWN2S29aWVNVTTdldXFxZG1vWUNYK2RrajI0OGNGaklzdFByTzlPUkUKTmsvdTE3
 | 
					S2lZdjFYM1M0dksvZlZ1NkFENkhLdHFRVm1rM3B2YmJ3REZEa3poUk0KSURPMW9F
 | 
				
			||||||
ZFBvalZsdENxR0VnV3FVSnFxTitBRlFWR1BzcjJWd1h0U3hpYwotPiAyOkUlJC1n
 | 
					T0pWVHh5MnBjNThRcE9WY0E0Z3JtMko4eDFiS1k4L2RBa2wxNAotPiBgWn4tZ3Jl
 | 
				
			||||||
cmVhc2UgIWFOMiogVDc8IFZETk9BSDVTIHEKQ01rc1ZoNXQxUDdtWGRQUlRCV3k1
 | 
					YXNlIFdRamBzSyBlP1wKSHpqbmFWZGpJbkhyRENTZlZtdFgKLS0tIENud0RDdjRt
 | 
				
			||||||
djNZeEtOaUl6Tkl5TDA1S2ZXWTFQZEFiV2pWMDJpZ2dkYXdBOGhSTVA2ego4UnBz
 | 
					bFhpbVhQbkxXZXJRSHpDZWovUEowUWJxaUkwNGN2aVU3ZVUKlXMwhyxmFiFHHHDQ
 | 
				
			||||||
ZGhXcklMd0NVWlhsc0Voem1wUzMyREViUllCRAotLS0gMU5GQjdJaVdlUFJGMG82
 | 
					FDtswK4HmApIhnW3TORhJyKIG6WBKFE1wDN5cDLppbjLdWAZecQbw0Qe8UQP50CM
 | 
				
			||||||
YnZCUm05ak9qcmVyUVJSS0tHaWRRTld3ZkNPMArRgojrBQvlyjMhChn8jgUNDysj
 | 
					iSZOYSSpS4J6jo2kFCIQELXjXMi7YhmkIa+Svz7kcr+vVROOikBdTr37ZOXp51Dy
 | 
				
			||||||
9Nh3BVqf44fiUNMKARTrFTz3wVMlioo6MmKRzJ/yj0fWkZ2h80X68Nq3rQvy+0UK
 | 
					O+Ygl8rPaDkTV1elWCgwX/Y5KM9wvS/OEVBSKyc5vz83i0lsHMTOgb0QxMrqiAUC
 | 
				
			||||||
4PNPRbwY5ib0nf7n3itFKjehrYr8HnOjreQps4it52bT5re2TWIC9ogZhNKBLRvB
 | 
					cmYk7crzAXmKU8VeKw97dA0ZOrzdEh80M9JVpc6k3ydliXUO1b3seKlocB5cAtnE
 | 
				
			||||||
qv14HjcF5bGnia8TgSU/8nUZJuIaLwHvS5sc9GOtmV4lDwiSTEJQEtGh716Jzuvs
 | 
					9OcsJV2byI0dOvRp9IZLHv3EsHw3sa5MFlw60KBHYZE1NoN2Uo5EqBc/Iz/4T2Do
 | 
				
			||||||
XxQLPEVVufAjZUKLp+jWUhXGkvUEeY5bxE2aOLuB8kLfHPC/5p2rl/n2sW3oEDFn
 | 
					zpQ5YwK8d2fK1tMU/FH/RWxkCXOjiShKsJXSiccHkzXskHU4uP1Y7s+KtFYxAttD
 | 
				
			||||||
Fw+XcNnCHWBzk3DlzKZFXwIaZL6Ocqrt+p8CBpWoNhbssuKyOtEbWQOmJxX3UPMt
 | 
					IusDOGuvKKpRuYMjRQYSm6ZHDAZc9yZsPqlKmhYg7IWlCd9lTk8p4mGoAe5b37f4
 | 
				
			||||||
sBFNdKSKFhoBQ4ukqkKDhgcm0i+8wG4eBbNIMIDwzPBxK0QiVriwlPQHl7RS2M/J
 | 
					JwACx8asE3lZjNLo+1cwdjhARG535qmOt4i+e0t0x5XoUkenWhbq3Nr2x9fkzt0I
 | 
				
			||||||
LgGeS7qrKC3SgmLu57CdUVUlnogJ4oOg7FPh6x+jQBIIv7gtYCzJb040TUZWZWvi
 | 
					4S0l5IxnxXXO9Flc7g0E+9HNZXTixG7UvhTcLH0BcK2C9CZq8WQmYdLXcbQBJdq9
 | 
				
			||||||
cfKWBBwLqLa+7Y6kEhcosLUgw2c9Et5P4rvNjU598q7qrZq7uK6Mr+PMwD3Pd66O
 | 
					yfLKzEBdbzPT0qjMw7hua0ceBwc6SF4gzkRVwhSw2kVERPhto15Flr0ybpDIF+tI
 | 
				
			||||||
SQyT4nYhhXBnaIsLXZfima2nRzPocaBmfsuXQwlnLJC8JB6yzqEViK0xYKfl0fIi
 | 
					irSwhTwi9BKJn8XpzgErS9K/Y5Zd7GENY3BdZNzHH37VXK/cEyjWXYmW4sAL0QzQ
 | 
				
			||||||
jxuYBw/8Y+MWQhIkF1pP8z+Kw51QdK4CIV33mlLBJnGjlizewsjj04EIgpzQ0+3I
 | 
					BA/wujUhOjHrdYKb3QdVZJnym6ErOqzrg5EJ6eXI6nFLWer+2xDRouaXJsQplcyy
 | 
				
			||||||
ZRyee/SzFmGBBk/pMGN0DizA8LS9yZ9DRGrc13rYVUTN6G5xT5AT1eEtFbQ6DH/n
 | 
					5Hr+L/K84/1+s+0ecNqm2XCjgCge/9dFM8Xvb+cBo/yOL5J8Nynv55WfUb3sjVel
 | 
				
			||||||
q13Tur4QJ8AqJmwv1cnX+faH61dXahfbinveXWqB5S95/HE3OGnZfAiS5bs1jW4U
 | 
					pTXH33APtzX4wdqsZ3KlB+OgjW9fc4vI+rWyT+Ia1ZxfP3Q6sgznspaIM1BHRW3S
 | 
				
			||||||
D3BLaBiFMYD+ccPedg5MLXRgEryVaOWlQ5wuXxqmaCG0KS6YLxl8o0bRR3lKXNZP
 | 
					ZKTsH1wkSQKmLMZSUCNzpCmKY2bvZMQY4i8VP0GKbEqGjItknCPp4KM15QTOWgap
 | 
				
			||||||
B7Ye0Px69aYtOs58dTOq0Peu039Fi5iNC0beocdKOjig4tZ6p41uz0jPGMUoDebZ
 | 
					08T3+WX1uBaHITZKIOIbKfAUd3QAoKvHQBRZalhA+0+Rlq3tu/cEcsgyMnKppCuM
 | 
				
			||||||
MYHax+a7Qpi5M6ZVGVpF1ieW2hqnm0lfb18cEYHuXjoI/YlgVhFPCGSzHJpuNiDU
 | 
					my41LOgtjtGi3IRnKYDsVnvu72KsbWzBBn0d/J2ZejwLoAECJN5OaLpIpWCCwody
 | 
				
			||||||
qJSfOuD8HUB2iXFeEgAi+V3EKTsyjlS+R1zWxkr2awqAk7Uf3svLGWZNINHNoJRe
 | 
					bHWkCYF8eymXncuTbtF0EcGeu+sl+YaATwkEHmPC0Dy6S49BCCfWMK512JE+7WfV
 | 
				
			||||||
CPPANHzTSHlNPSelQ1CyOhl0W/eMCEJuJ9/6kZsmUC3zvzxEMGofG+Ub9RRBW/+/
 | 
					pxI2VZ2ncr8te4ki4iZPIncx0uYGTt7Q5WoMoBlave5AemYKr7MgAK9sZx+3VP0V
 | 
				
			||||||
TkrVvMrQv7/Va/4dxMPCqrdOQ+3/LkVzGX7qg6tQR76Su0q7aqh38Ki9qWY47bTm
 | 
					CXcLzQ9GznWxj30U5cro578/3DbvTRrvgD9kifTQZPDhLliqgc0Eiee+2O3LMVuS
 | 
				
			||||||
lq5I2EcQApt/O1cGQJTFowdXVJXx/qQv436p/jL1mymQ8241iQ6XX3DUjbnqdI33
 | 
					GBjeyUcIjF2tQ7C6AeZ/qjNZTQK6/zIjd6jwVwO8UDoxLZV4w8rCNEdu7zMUMYYy
 | 
				
			||||||
4XcPa/B7naRkgSG1Z55Vv+IIBOzcjzUMzeQVP/WM3SFRNYT79mJnV0SsKvUFtUOM
 | 
					nhLbrdAcNgBnDT2XRT+JXXZZ2YJmJFczd7tHPpmP8mAPXiypu+VSc4M+a/A+dGyo
 | 
				
			||||||
1OxMGEx+ZxfNIZqdp+qo0+uIU00ciokldh4URo9u8EIHjFVcV3Eyb7EbbCxzDiU9
 | 
					K8r2p47L6dNbMnJG/lke9V3NbK+5Cqg07KNkBEbFq9e9i3RyEs4KSq9SqqRGKYKt
 | 
				
			||||||
iwoAAaJjwBlyaRQFWYsKhY2J3NEay142WAyAiHmnNBNhZM9TKkCpjton4ehxeRUC
 | 
					uQ7wRu0u3O7vMsw8gagpSRXeVaEtxJTq2eA6eJWCj6l6ceZ+/nlNPMXudvbD1JlD
 | 
				
			||||||
hoXpzh4J2lMhdcmXXZ675C3MYiLDpajgLS1dwRp+mAUXwjvQG5rmJd7UWdgpbdpJ
 | 
					rt397ucz5ih5NpRFzTWG4iT91hXvZO5yhctCxBlmhLgsfoz9TK90fnmkeWMr/i76
 | 
				
			||||||
K6wABNkl601XgKv3/nV9touE0KQjHg1fzo9vzmf8zVEViTgXxH3NECZHctObwgoo
 | 
					cU+F+v1wYwiZ275occmyR3LxFBT2d8Isz4BbC/yFJ+afTMbAGM+WbUHeYSA/Pq7A
 | 
				
			||||||
SlbUOW8vihCi2HU9G3tqH7dwkUsgB2a22JFovgwwW8ePKJQpdvwAV/jyFMLL6jyj
 | 
					YgEhFSLULlM3ChmHm1otOMyyv6bbos5SvtegUtHewWZSx54ETN80kW9bsUBZgY9w
 | 
				
			||||||
6Tf0Gsc/Iut6Mh5TYiTWJdCzvEBjcybOVnppj2zR32/A/vAXUrJQaq0kwKkCwG+e
 | 
					XIOG3vW6dFVjpJpAGwcDG2XJpKs31F4eLnX0zq1PJXdp1UYo0H98U/CdP7OCfdT/
 | 
				
			||||||
TL0hAQuA2Su27qTR9Xy2QKpQ5NppRH7V9YxCpjGfcLbcCh7XH7AEZaYfrrX8NoP5
 | 
					AY6eKzdhEMTxEaWAfZvTdbX8p9shoVu1K5TEjQNTHTsIKoVnLbpjq5/iAwn30GIQ
 | 
				
			||||||
zPalFA+7E1IuDRtT29wFNRVb3lAet9t5q0LUHf3x+Qk23dQ7Mdq2JIf9RIo5xZ6X
 | 
					dQVBDsU2wTTsdi3HZKEqwbGW/iwqZEhfeTgIv0P5VgcnUa5uQvApxud0y+qf4M1A
 | 
				
			||||||
nsKa9eBQ0O5OAv1VGWVvbrVCMpmyiklYV2rcIT+dbrhrgiTu/BvODSvtmeANIkhC
 | 
					t6IOfzM7toUNsUGL/PQD7LcpJLwdKjFKPrQl4GyIplQCB1+bIU6JyE9Rr6hfeOTG
 | 
				
			||||||
uF112/+QW1UNPCENioYq9OWPcEwby+s9JkQf5nTub2o/0lTFKJxNgXa1QBcKKVyC
 | 
					pbbX1J7dfM/LN4yfdAdod+xTS5VU/4htKOzviZoVfHHoi5s6BuxT57BSseucJbX6
 | 
				
			||||||
9aTCRhcxXsfuR7YzbCXRcK2hUW203iS8+UgAfZBVe5GhskOd0ZR0WSkse+jGzPqI
 | 
					4wEUBk9wEzTrGRZSrUI9DHkmMTxJ3qORtt2P0ht9GVCFbtAg/Mgg3v1BGlQTTgtw
 | 
				
			||||||
tnH5F0yQgLn9emebpL6dNFUVvssjpiMlvkijXFJv1tWSKLb3TxJd2BE/w5Zj7Haz
 | 
					y6/iBgWxTO5OqiBW4EXQCFyfh85vPegvutX4o2oXU7Mz5QRITYDaObxMhyL32rBC
 | 
				
			||||||
iv7Wz6o5+bY4v2YL2Ev7hGzfSaef+ip7/BYZ9TGuzSoZEHMYa7dNT8kRR18IhfXv
 | 
					wkEf0euFCKabLeutQm6bh0W15IAW/a2SO2knXJmWuP9GRxfFqzF76ZmHWE+cswal
 | 
				
			||||||
Y3wa2xlOhB+WE3AjtYy1oTi2c6Vmd9UKASZy/Eb++j1MSPtxZQLNaj+svCmqqfvO
 | 
					/FXJ9BA/IEkbJr+kX87+RhgH5RgsmsFsDXY/jwgUoW4gZR78yB8bq/uQubIMhhAM
 | 
				
			||||||
/gElVfGlgkomYwc2EfJvR1lt9u9YGepxKrafPsgvjR6bYPwLF7eHKkKyEiqGCYnW
 | 
					HLDtYIaOT1Hwrf1v6IGDeFR31zrWudt3kHH6uZBAH77Y2O6C+TuN9a0IhHwLec2S
 | 
				
			||||||
mcNJz/B0egxhFjoGd0U17tNuZcYRD/Tsj9ugGF+4/q+IaEV2YzZTdGzupI3lW17o
 | 
					4AIVTZEm6ZT5o7xQTVzjaxLWAdXtENrW8rArf6TH+JIruznbaeuYT6aeY4KlWlYu
 | 
				
			||||||
Q4H+EksxkWYDr0WRlYKn7VT1gTThuggEz77JskjNP4jK29EOIEO9IqGMh39tXsud
 | 
					rVH/s1wBTWwhecdt9EHauLftK51Uy3GrZhQ1RTvb/DB/cbXM3yz7MbSsu7uqayiG
 | 
				
			||||||
mhL2Z6XMX6sgxSjSkYxLpFnS1mRZ6uQnSptxHTfnG6jYhq//MTjGX7xmYBj5EoTC
 | 
					g4+0at+1nk+4sFiM505FVtBVb6qL6HQIr+g65WcAnTUGj+DgYUBAmh38uu3jJbhd
 | 
				
			||||||
duHuaCqjRXc3yHWoNm8jepkpbe1PPbwEbL6RDK16G3g0WVREjZopj+66C2xlY8Bq
 | 
					TMq/LqoPVyXy1CizKPIcLXTEec7Bh6HwXkn5LMU1HPdrjk9OSwzS4HgcOVR6Blhj
 | 
				
			||||||
ZCmHhud22QHs+5r1LLSIynsUlGIOvq30DZ0F2/f9Gm7uayIYbp8gA4z7M7RjmHoZ
 | 
					fmoDMwuVkzyD0jJ1vRF+uH2krZu3NbBNA4W90XIpZy2FtyFePaTRJQuiZGXx9eGV
 | 
				
			||||||
+XHYSPc4kH4a3T9MucQQGzJMl1k/bifBAWLbu9uPcDUe7Cglfz0wHnPemOu8HZXY
 | 
					AlUv8e6SV47vctqRZA2pKSPrmYLOgeHTcB3YehiOghyXnVfC4vBCoaujK6ToQ8aP
 | 
				
			||||||
6qS1n6PAHyyGlqX/pNWxR2vQrHJRksdTCvjl4g6256PhaMDop3QAHuQj9meYKIqP
 | 
					i4R7Q/9g8xC6oZBtaBMoiVAkL6flDXanYcMQak5x/nPQvyyld+3gSqVVkta0uYg9
 | 
				
			||||||
MiZexiuOW3KjPJ30Gx1Q7PnUc+w3SjjsKaZEvRgeWKa37rvj1ICTnBQUPq2HV6y8
 | 
					1V54EEiB0TgviF7Gt+7/+UXXEx1dGygRzIV0LdX9dza9VarQmrN5JNhqPePzHiex
 | 
				
			||||||
zaGnJcfd0ENAmFnRaCIbdU6TRonnIAAuSfE2gtLni/PJbmUpznuq82W//kxvH1tR
 | 
					k5ITcrEWbRc59BTH54s3nYRmqH6V43g4IRmu8VKRZ1QQdl59TWkwZ9gjrw1qZObM
 | 
				
			||||||
oPx6LuM2+hRncMoyXUTWSUVO1DAUPXgZA+j7fkkwmosi14d/5xe3wO4U3dGZ6wAY
 | 
					5m9mSeHGd4Hs0h4kpzrhiq+p16q78SAifEIK8D/MKPisL+co3A2nkHPBlhKV3M4V
 | 
				
			||||||
D+zlzhq4d/4vIvLIL0NoBcp8yM+xWxPTtvj7HUJ7BOVV06ICnilUlv2wjR+dZLZK
 | 
					Md23894sXGjMUJUq7lIrfChBdolwLvOqOQmLkWasn+QQ2bSixc1C+AxypTbQNgTD
 | 
				
			||||||
DyjWhMoqk8r2TDZbAQr8MNX+sSlp1JxQEgBijpqBvRdF/ulqraF/GFDFRLcEi7D+
 | 
					I548k4nDAgvMsd6uyftUR0rjIe85N/xbgD4uEXUx9J/u8C49AprGoMdqe6q4GdTv
 | 
				
			||||||
AkHPg4TrmaNB5ixsj72j0xruFJxgQJGj8fwQtemJGu8QcuJbCvJ74TI3vu0Pac/C
 | 
					lwyKsZSPwUV989d6g2C0J8ptt0+5lB9f7H15Da/BemKUeccUZGAjVe55J6hXYkJD
 | 
				
			||||||
MRov1TAVJB7+iVvVNEgCMlzimJCSCUYh1Zgk5Ci2CDFMFRAEcGoHywIW6v5V8j5o
 | 
					xUbYq4yEL+6BcaIo/D7jRSJSXY2xbUgkise/99fH/rdOHZQDamvI+yh2yYXVbsGR
 | 
				
			||||||
v30mJKZCVFc4Yibivjj1aGhQVO72vgiog4L++i7CeXHIu6Fe1Jmlve5iuxrQA2aM
 | 
					bpd2qtc1OGGA3LRQjz68TS3LBq1iXcQXe+/B3ANus/d/YUGm/pjAb56k3+4z6b9U
 | 
				
			||||||
9vjCbFJIi8k5vQTVcKPRcsto7/qbyxvWvahKBBbHl53XnSb0WtLUyTEaXJ+0l5gy
 | 
					HsXKdEjZ+XCkjmlvlTuCGl0TL8TLn3kOcxJyrTG9MuJ6p55i+QM44ef1Dc2hrnt+
 | 
				
			||||||
Epxfl6ZRNkt+YBYBqCZL9aK6TNpCR+zTC7OhrKcZntqFYCeRB25YEfc1z0lTH4SE
 | 
					qVPQLxMQMQ++JOJvW0U4YYoA4eP+HggIx3rZ93Im8tnj07/bCtLkFfNvo0O42Opx
 | 
				
			||||||
TPymGSMOeUX8YEIr+XNYG0H/I7ZtEdNGBEXaUrC4YUNrvojpq3PS9bhfLhAf5D11
 | 
					Kxf8W3d67NyNkA1l3XL58m9/VdfBPjc44wwdMKBy6A4VhNmxvf7Z6A45sihmUAGy
 | 
				
			||||||
wmI2tS9cqxAuS2zkaBr9Qo5xNEVsyGNFd1K0q0JJosiMnVZDzOA4wJTYhOw5gwcW
 | 
					nCLO0dG9tIM8njEhaXJBcT3YHQKO2xxaHXWmvR5VssOhP4Ewnup2xJioiP3FweYJ
 | 
				
			||||||
T1Kh/LDvK4RE0CV0jRqN81YO8V6Jq+/c2kgtwTLzrx1GCcdHRsY2kPhCEWOTLKb8
 | 
					N4Yv3eVGHLYeDH77Yqq4R9q0He1R2iCwAzFlxOahtX03CANh+vUaKhruw7jNY+L2
 | 
				
			||||||
Jn5nyyvOOjMIkAEYYqoRRxl05UbNWNS9SuO2g9HF6JpNJmw0cmzT8erIIjVvaUs5
 | 
					WbrnNPYkjeiU/hFeVSBVgTeVkSQJPiQFK37E9NUo4T6dibGh9VT/5TEoskeUVmfU
 | 
				
			||||||
dd0Bd5EgkkLq3RMPNTiidQCyIy8QtoElmxYfM11mbf+JMgxsB3sDcRGN4lauUhho
 | 
					W17FzFwjBGQXaZzvChJFbKPbIE/j6ve7RrjdOBk6IBgi1LTib/rTOcGZbDhOTvIm
 | 
				
			||||||
JlayuFUfrQEwtHFwyULiJwUC55faVqOQzyvcQ8C9AJezDXS7//ku1kvEgbzK0nFm
 | 
					G+1ze435mQVoBK/1MRgpfE4cpssF2TTEeJqs6PfYbqpx/o7cwZG/At3Jra+nKNhq
 | 
				
			||||||
3bCCiuog7pG9XlldSReYvlJtnqTmp6E5+m9YaP+yB2E+swKBORHkbCfBu1CuX6R+
 | 
					WZs6TjIvNGvO7NUUZmfj2QPktLBRKADjym3YqJy4kGUQAZey5yeDWonMhEV9llAK
 | 
				
			||||||
aryBYIDeLaIiJs5GWJN//37TT0hVUCipY9QISfTiZ5tIy0aNKRu9syjWphcoTJuv
 | 
					LUC40BK6XY7ySw5vTmmGR6nnWo1ltT+71XDj3nZtfGF3TTCkNxZKlsX5HBhfXB/E
 | 
				
			||||||
YBaRxKNdZs81ppFTa3sXB824+QXwzRJJPjBndXOtyX/a2U68NK3dqau/A5190VAn
 | 
					+8PNg6Ova5jyH+IO9Lu7JLqYTh6St6NfVflD7i8ENFLf6X1CiJh6rRseb3TmM2ve
 | 
				
			||||||
bn7jnJ68rhcL9ewwydQRm72qwyxBbRHFXnEXpkJhzYRw6fosglqbOJMxFiy36HWD
 | 
					aj+LypLV8FJ1N7OklFseZy+gqZ7AYCknoOK3z20zL3KMilw7TwTwwfGe41qIhAHu
 | 
				
			||||||
RkVluvTInw8Em/DhhWgn+UrxLlQN6JnVdpkT9hwrlFWooiM56UKAPO2a1FM2XKXe
 | 
					LLa7dA0EB58T8isNdBp36H2+oQENGHAIi0kxF0HlE1x9NUoFXvoUhyVEGjEj2zcy
 | 
				
			||||||
TqsolY07uWnA+ouiljqIpsaFlVDBcz/sGZWqy4aKKPBTcZlreW88PMsS0c9nixVi
 | 
					Rqjb5iSCyELMRJ7qiKyD0e8auH2bQQeHoMmJlCk2E7BXTUUY67eJnNXNrD7ZQg/k
 | 
				
			||||||
nKnmI00HuzeL85zVHGo0IKYfktVVjuZNPzJ6+w18XpKIi8TxHpxELC9M2kVOCnuy
 | 
					Yt7OAinFP24nKn4SY2Bwm35JE60iHZ3USoYnrD4twPBbig62fUSYUqqDoNYc5L2g
 | 
				
			||||||
uwuntJlRty+GpXVvx2VLi1wBKyLpXUxhyg1tSi2sZyjIdVt4yEOKfajZYOp73JZx
 | 
					AtR5C2SbDOsEG7qbehziw8NLp7zbf/FAashRULc5GLTcFoC2YJHEawhb/lWjo1Az
 | 
				
			||||||
IcInD7Cby9olkMsa25YhloljY8YELfW8EWutF13m8tsjGP9c6aOuMIXhrrpwLgYy
 | 
					nLqXfTB7jXHVbqgjpghJ5vO7PZ+FGg8ylTdUC4aQ/lUWuSeJnjkHDkHFFIfNC4S5
 | 
				
			||||||
E27iFh9tHq0mjCMibwQnHld7Ccd4OqO4AKfPofHDxWoY9+ivArOBAXjsCxhxWWWp
 | 
					NYRpQIAYMdDRAP80tdAHeOG5BC1OoA51jBKqBi843tCxu8RUQxDlB5/3AYKB5ndC
 | 
				
			||||||
aLqLJz+JH+idcsVDlw8jJzFW6pQFbM3VxXObvCg9ou5+P+Pc5XYyALJzIlmoOrN+
 | 
					S3Pp6kYXW8wcFAFRluM+LCFzO9VFnZ8BEh5nDX4=
 | 
				
			||||||
ns5Z+U/2XKGyySQASUyFXUNml6csSrTd+ejz1QvEX9POU1nLmvS1+aojgnptgdpn
 | 
					 | 
				
			||||||
sAtksQHMt1Njo1oRug3+/0iC6XWEig==
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,35 +1,33 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyB3QTU1
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBqaFcw
 | 
				
			||||||
TEdvbFNaUmE4U1lCNzI1dlloVDBTNXdURjZ2akRMV0R6dm5ST0FNCk9YclRSakhT
 | 
					aURxK3cvaktEVkJIQ2dOOEtqbVVGRDN0SXpXdGI3NzhQV3FmaEJrCmVtclBDY2Zr
 | 
				
			||||||
NlV2UVJwak9Fa3dQNTNBK0xKWGlkNXdwZTBEMm4xZzc3azQKLT4gc3NoLWVkMjU1
 | 
					cVMvUld4dDNybnJ4bHZOODFpNGpJVXdRaDJKY1ZxMy8yMjQKLT4gc3NoLWVkMjU1
 | 
				
			||||||
MTkgakk4UkFnIGNBMHNrdG84cUQxd1lqQmJIczlScU1jNk52Y3BtR2tXeDNWdWRX
 | 
					MTkgakk4UkFnIEtDRTNkdi9VdGFnNkQvdE1UdHQyRmJXR1RtR21HTXMwa2hiK2xM
 | 
				
			||||||
cEFCR0UKVU5vem5MZUFPbGhoQzJTYnF4OTd3OW9jYTRkazdocVJkZ0pRRGNLek93
 | 
					Ym9xa2sKYTFVQmVCNmJId2pPQk4wd3g4N3pOc1lHcjg3YlBEa0FsQlVsb0RKRjYw
 | 
				
			||||||
cwotPiBzc2gtZWQyNTUxOSBnU3hQMFEgQ2RUaEUyV1ZGbGRtZnlIUEtTQXk5MUZF
 | 
					RQotPiBzc2gtZWQyNTUxOSBnU3hQMFEgOVM3K2NwalE0Vk1rbWdSL2srbXg2bkF2
 | 
				
			||||||
djYxZ0hBUThlV2tXTHNvdXpVSQpMdiswMy9QNUtCb1hkbGRqR0Nia3FXTzE1ajZL
 | 
					MTduekNpMFA1QkFBNHJidERpYwpCbWQreWk4cTllUnluWHZaMXZWREpqZnlwL1Ex
 | 
				
			||||||
UXljSTZqM2YvbzVuWUFzCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBYL1NrRjRaRnFn
 | 
					R3k0cWhHSGg2SkJPSkNZCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBwdS9CeklwWmpt
 | 
				
			||||||
RlNLdWJ3cThteDM3WmNaY210d3RmZzhCYmNpVXBwVGlVCjBkM0IzZC9zNjhmTTZV
 | 
					TkxWYnhTTjVxNVREOFBqQXhRWHlza3FLY202K0wxM1RNCi93YVFOTGJGNmYzZzhF
 | 
				
			||||||
R25ySkVoQWxQQ252WWFlWWZFMlc5dWtUN3VvVTgKLT4gWDI1NTE5IE8yUU1pWGFr
 | 
					WkpFMDd6V1JIcjR6ZXcwUys5UkE1ejdFOW91MWMKLT4gWDI1NTE5IEk0aGh0c09n
 | 
				
			||||||
NzUvZVpwalB6aklkWmJGWUQzTnJiRjNzdzY2MUp6MkY5M1UKR1VIWDVyTFpxem5F
 | 
					T3B0ZkNSc3NTa2doUGs2c0NKTTVMOENPRjJ6KzlodnBxR1EKUnB6azR1V3NHUnRR
 | 
				
			||||||
TmRNWE9zZStLanRTdlU5d0NOSEJKdWhDUjBCdy9vOAotPiBTJCd2NyFYey1ncmVh
 | 
					WmNrWHArZ2dmMUdEaGovYUdndDVNNlB2UW5VaVdnOAotPiAsLWdyZWFzZSAlUSA1
 | 
				
			||||||
c2UgfE4mYSBXfms0TC5FPiBiYmx8IGRFV35mciNoCjVZdHRiVUtMMWxEMlJ4b1F1
 | 
					WX0gJwpCMG1tNjBPMVJRMGRlQ25KLzJsblFzZkN2LzNDOGcwWEdSSXlBUjNwCi0t
 | 
				
			||||||
TGgxY01XTlZpTEtndkg0T0hRVjlqVUJGMUpSaE5tVlZWR3VGenpkUXY2eXJtbmkK
 | 
					LSAyY2hHNFNmWFBQWEsvb2hxTUxVUXdKL2p3ZkZWSHRDdFlkREJyaWJrVDg0Cis5
 | 
				
			||||||
ZCtqRVN4dnZENXdoYkpjNHRWYXkvN2laY1p4YjV0WQotLS0gOHlEVTVOSmlNemNQ
 | 
					gfdBAb92J5/DuoXUt8OirgM7bXucabAp8/U5Az0nmRkGawpSZidB9ecPYHfcdUGp
 | 
				
			||||||
TW5ISk1DeDlEM1RoQ2JtUFlyTXRKQjdnT0hiend2VQqrUFvr+76sKn0ldBmZMlEW
 | 
					VIv8roO6P0RbbfYXh3szT1YmEMyOXMHFM0+Yunq3u1ca1EHCZDV6Feb+i+lXIBJU
 | 
				
			||||||
U2k85DLo2KU+/+GtbkZwVXxxIZHMLpoJgghHk9ptdalUgLGcl0X15x9jVaw8aeta
 | 
					GST4oupwMET+ChVT1/yg7A9o4FY68+FgLjGwE1qeHN8gQr6aMz6/yml/z1WzBEXW
 | 
				
			||||||
hbeOHotRHY7bC3z0S74riTk3xDMR1eT0QGhDMWHjfo8SkCftOYBlFfhTftevdep3
 | 
					XEv5fVxGj39eBiq08Z/kCgt5zVDod8RxEq3S3kt1KX5JD+mpGYn2z5CMGhn7fclM
 | 
				
			||||||
pKMZsuQMwH9JzxgUfcxIcWE975cZzrEJ85nfWMGvdSjcg51KNxP/UUPRxDlcbCEf
 | 
					mj37LaVbcKfyVnwRlLPoN19NeqR+ltM3mu6ibjC7cOQ0E1D/zjQMIxtzNzmZRFgB
 | 
				
			||||||
9XX5apSzNsTI3ibGD1n6Qwq8bdVYDMHmy5pAhw4l8L+SdoU1tGdw7JOA16sMCJbx
 | 
					l/BEOsX25Zv5vJgLZBU9rMfybNVAjDroG5V1cCVDRR76TP6HVJIXSriyOW5xSFCy
 | 
				
			||||||
T4bV0ky/PGRonjJuCyDBj8oe9vMe1ZI1O/ITtktekS+wocxBs6QXlY7pIZMlGUn2
 | 
					Li/VyhWaUXRboGq0Nt4vXWuOTlU/tenlBnBc+d48x35VCExi9IEFpIHj1fUwM/0V
 | 
				
			||||||
6m59ZEEaf7R4/MdnmBDNDkQuyXaKc7SaTc6h5sKWzXdYScGUKvgUQ7U/WJ2ItUTC
 | 
					dgOfY2WRH9C2cObUc6W51FIARkp777uPXRbT4ZXRDjV18vb18CmwLQQwYupQYnZk
 | 
				
			||||||
N/Xq07GkZZMt5MYBlyEr+/mKWlcy+ylJPGb7EswvQWaHoeM1QF0XLZ1v+W/Xsso0
 | 
					c0hZHvoxDwg5QirWxPhuO3bWDqIvHiKy1LYgRrlvr4Wpcb1l0lAYSGX2r1+QVj8z
 | 
				
			||||||
seIoz+geSu9a02kwfsa8WvWXdIAT5X2pNGPClVNzjQ23pfQfQuW8ZQrGmIFR4g5A
 | 
					tA+zJcUaPkjUSpaqF4LNVWXrTWEN330gQrVk1knWqPl+hFPoyFEHP50PNYr3yxS0
 | 
				
			||||||
58T1K+vGLdShqqVGyJFMVrSuOzqX5FVmZalu7/++1IQfiRGUlrHKoPlKWnCfFEOu
 | 
					VxbSpg46cXyxi89ghwlXBqI4LRtWlheUoIOuNyLxvXZECwCI2kmt+XBFph5lbG7F
 | 
				
			||||||
AYjaPeEFX2ByxcqfMK1YVPvUufdISUQeaQOO7mXGE3FqB0oUqmRIUiWZATwhq3Pw
 | 
					UQaH+ve+trb3oYkkG8ZprCljUC7HvSyt31UIRF3l4sLsULQKHqWwVD/2M4B0N5wQ
 | 
				
			||||||
p5QdcySTnmMpD/w05hvwski77kCdmYuHlMlLZez/kfhTnIGXris+Vwi/V19bsZ8G
 | 
					IzIJkiuWBBE8IX/tI5vUlGx+QWSxmKdHD2mMb/GeMsbo7lOY51cWe8oxe9WcYPhB
 | 
				
			||||||
zwaZ/Xr6WNC+df5JqSfTGREnXZPFRDkaTt3ri5/eEm6BqliuYjGbuiKsDECi4+JX
 | 
					m4h1xPm4FLo0vHCnWIkXy2o8JYr6fmpjzslC++wYMEbIH3gRBKUVjgUGHywVIXSa
 | 
				
			||||||
bHpH6LBBoKQ6ms7jCAn0Ls4cUKF37PcjGAOuWnzCSBU+REht1EDfHzx4C7hNiP8X
 | 
					uwzRULUiD8uXFNT3cZ+YDnAvZkuYz528DBKjd5jNen4akah35wQ+oYoGuIhUKkGL
 | 
				
			||||||
87NjEqJbwE9lORho0hQJRTn8uriQcidlVoB3se2SYKbMy8UA4NNnxN9PTj0TuQjL
 | 
					K59+hTyctWyEGi+fCl1gah2JJ6aF1CXK69ON11YkCEVCI1SK1o1no/0NZj2XtepU
 | 
				
			||||||
OD3LtqHBElqNPbGNyyEAAJmMBmmkUvPPXlGQ0D99b1+jIdHzYSRtOLshBFykqWYQ
 | 
					MgXln0Pz+pOTZzcjCWhYTO/dNl+Xj6EeeSjjWHqDYg==
 | 
				
			||||||
LJD61duhGqcQqcLx4+JdQ+oVcfAI2nG7YINnHB0OmS2DOZvvwqQ7ASScSujUWIjA
 | 
					 | 
				
			||||||
LNQxu3ruMz+bw/G0tYZBBiE=
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,11 +1,12 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBEcDNm
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBvL0hp
 | 
				
			||||||
ajc3a0gwYmVSdkowak1aakJ3VWZ1Rk50S1JIS0ExVktVSW9OVWljCjJqbUEySlNK
 | 
					WUs1VWxPVlpydU01cjd3Qk9qd3hvWVdvK1VMaUZNT1YzQ1BjdWhvCmJlSDRDSFBj
 | 
				
			||||||
a0xyT3NPK1BBMjZzN0RrLzhwVitvS0pzQ25iSnJSc3FmM0EKLT4gWDI1NTE5IHk0
 | 
					ZGVmVGV3Vmp5YitGbm50aU56VDZCc1hTdjJmSGhEa2dvZWcKLT4gWDI1NTE5IEsy
 | 
				
			||||||
M2pkWHgyMHR1WHc5bE4xWTFDTndKdkhRdTg5bzZIWEU2cm02UDZBQjgKUUY3dS9p
 | 
					RHVVT1F5d0kxN2VBMG56NnJWYTlEeFFXaHg2VnNqdlJKTHhoR052akEKZjNObUtk
 | 
				
			||||||
U3h1L1ZvTkFPdURLZ2tSYXJXOGNZZ21KVGdIbXdhSUJrd2puYwotPiAoL0RtO0lH
 | 
					RCt4Q2l2R055TnJCSDBrY1lWaUZibk5iUDhnMlhvZkxRRkhpOAotPiB2LWdyZWFz
 | 
				
			||||||
OS1ncmVhc2UKVGthN0ZSU0ZFTTg5YW9UOXMwa3RnSzFlMjE2VTN3Ci0tLSBwMEMx
 | 
					ZSBMdUErIHQpI01mVENmICFrK2dRdjBbIFU5UyI+KjQjCitmdU4ySDhJMDRlbklD
 | 
				
			||||||
Q0tQckd3SzBwUUE4SndMV01kUjVrOTdDWmxlcWs2Zy9TZk5yMzhvCrBXyLBZGuSD
 | 
					aUcvREFqdVNtb1lFZWwxZWo5VXdNUGZQWGt6SVRKaUI4cTcrWEx3NThWZ3VORkor
 | 
				
			||||||
dJodNI13obTM3UvX6hSgQ8Su+J3fOKr5NibkhQ0Auvlr2tUXhhDm2WOUlHjqVTq+
 | 
					cy8KbG9EaGV1dGVDQQotLS0gQlFJdWpudnkrcmQvbEhpOUM5Y3RCWWRGMEQ2TUV5
 | 
				
			||||||
jWLSyhioDlIEyBgk8Zrl7KGeDzBi
 | 
					eTBFSnBkd0xnYjUrUQrxdaCf14h8hqRfdnMorggnbuCDMRHY7nAnGQ1ET4CBlCog
 | 
				
			||||||
 | 
					/Rp52aNZHfLh+BFFZazenI7qrvVvEaaB2ZVKa0Z/F8adsGHSGSwz+saqWw==
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,13 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBzaEo5
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrVktQ
 | 
				
			||||||
RzNndHBLMUl3Z2txdVZoOVJBbWsrTVJwY01WeHQ0VTBaSm5VclY0CnJLYStYNEI5
 | 
					Y05RdDFyeUhGNDBiK3VHNzlrMVhKWlBJQnhodkUvTTlINUZ5K1hVCjJ5bXo2cTd1
 | 
				
			||||||
VTN3dEQ0ZjBKaU1PZSt3d0lldkE5VC9wNHdWazNWV2F6WWMKLT4gWDI1NTE5IEJ5
 | 
					a3FCaHJTNVNaL1ZRcDhuTENuZVlhWlpJUUVndVErbDVoR2cKLT4gWDI1NTE5IEVj
 | 
				
			||||||
amlzTDhCOFF0TllPd2RsME5Cb1lRQUZPTGNvOEZnL1J2Wlpnb29GblUKT2t1NFZy
 | 
					VTErMFVTdHBoVmtMY2R5SmJSdHV0aTJ2SWZNc1hrN0h5S2dKUnFxRFUKTHpyaHV6
 | 
				
			||||||
blNZSHdxZjlHTlZmaTFYT0laQ1IwOCtDZ21vTjhxM0owdTAvawotPiBLYS1ncmVh
 | 
					WWFYME5xNndlSklvNU9GSEFrTFpnc1cya0NMQUlqc1Fhd0hNNAotPiBoRSMmKiNW
 | 
				
			||||||
c2UgRX0nVGtpSCUgNVNDWCVwIDBuPjM3MwplK2cwc2htQ2RLcFhUZ0RSc21uQlFV
 | 
					Pi1ncmVhc2UKZDQrM2piclMxdExSdUZqcmhVV3l1K3RHVFlOcFZzN1IycnU0d09k
 | 
				
			||||||
Y1QwSStOK3lKYmVVQ0J5RXA3Zytaa0JoMWtlWU9qMHBLNktFZWxtbFpDCnJyS0JJ
 | 
					V1dwREZDaEcreDQ0enJYd1FXMDd3d3BVNAowYlpwK1EKLS0tIEwrL09nY0FpSTlq
 | 
				
			||||||
WEcwbndYbERreFhLZlRyQ3E0czB5NkREancxZk5BTGdWRkR6N2NrZmFrbnhSYlZZ
 | 
					bFhQTUtHOWt2NWV0TDArRy9iaFRFTEIxbms4SmI0ejgKmJRGof5FAIPpGn+u6PDh
 | 
				
			||||||
NElHNEEKLS0tIGVLdXAxU0ZaZVkxaHV4dEZNNUVuc2J4N3VRMzZzTktSMDY3bDVB
 | 
					xSQMKrpFnGvjKs2FicG7K3C19YGVwvMds9XGYzLLdugvZgykzZhq13XK/mSk2b9r
 | 
				
			||||||
bWtmUVkKigIZ3J0s23vNzmbzJGjSMGBXK6o6xnsA9HXeQZ13VgKv5Qv+UHu+Z0g2
 | 
					9xkhAvCQ0p1ikQDyX6SuLwJzsJpa7V7wHbEF5HJXQ5NrJUOFwftzxSqYodtP29L4
 | 
				
			||||||
TeKdQSrHbDB3ydIxaiXsi2ivULdrIMCyd96rEJFxrkVuVqSZE0ehG5j+o8lKk4OU
 | 
					LiA8sxPzNeqhFYT/C8Ea4lDzgnXCjoWtMcZCpfWMMtOJh8fLLw==
 | 
				
			||||||
PDe70slbZrVYDSu+OOUOCVRSopZreCURlYn2Pc4rjvrMAn5r1r+/AxjZMdkmmQZ0
 | 
					 | 
				
			||||||
l0wMBTus5zZzKg==
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,15 +1,13 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBoZUI4
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA3enI5
 | 
				
			||||||
bEdWSW1pcDdMYVRJLzdQOWhsdTlZMmlyZjRVeEFwU3Z3NzVFa3lBCkxRZ1FYeU9D
 | 
					NkVZMkxncHRiSFkzRm9seGdwdGNPM2ZFckRoWkZFNlV3Rkl4U0UwClJ0bUZlUlFs
 | 
				
			||||||
L2dramp4WFFlREZ3NTFnWUs3clVEcnBhLzExclVac1M2SG8KLT4gWDI1NTE5IHVZ
 | 
					MVNsNmZ6aFFYRjJSQmNWdjJMc3F4cTNrejMyME1YRGdQVU0KLT4gWDI1NTE5IHlR
 | 
				
			||||||
bk9QYy94Tk50c1dVanNvNzhpYWNqeFMzVVR0eTQ5OXozMmp2VFlad2cKaEdvUnR5
 | 
					VlI3eGVMcS96a0ozWkx2b29wTWtIbFFCcDJEa0g4dWJvdnhGQWFwMUkKZjQ0MzlQ
 | 
				
			||||||
ZjhsQ1FRaittQXFkbnRZei85MmtWb3pXRVFsc0RzNzBPMXFMWQotPiAzSXJZb0RE
 | 
					VDlGdkdxNG91bDV2MFZXazM5SlIrUmduYTJacGtXQitnTXU4UQotPiBNQktGOG4t
 | 
				
			||||||
LWdyZWFzZSBudCBGIDklTWIjVnwgM3YvCjRVYUd2TForc0gycnRBR05MbU90QmNu
 | 
					Ky1ncmVhc2UgZzddIElDKW0KZTFiNlIvcEt6aHUvY3h5VFVtb29ZQ0RGODBtTUF1
 | 
				
			||||||
dXlmQVB2bnZyME5heXlyMUdGTmR6SVd5SHcrTThrZEJYRlpnUmdmWnkKU1lyNjQ3
 | 
					TS9Ta2lZZDJJUFNyOGp0aU9LCi0tLSAxa0ZNWnM2b2loNzNFMmd4U1V4NUFnZ2RO
 | 
				
			||||||
T0J6b3NPQ1FYZnhxTjFrYmN1UUJzMjEwcDBwSTJkTnlmeHl3WmFFTXB4eUVMWm9i
 | 
					SVRaUDVpNHVHMUFSczNOcVZzCiJKbkbVr3dPswaIeb/dlP5REMZW0NoxMluj8R73
 | 
				
			||||||
NExUZzM2SHlLLwpiZjQKLS0tIHdqakpMSUNOdnlBcVA4RGJHR2d5QnJNT2dVclZN
 | 
					AcCimbLRWY2KAOx5XU/ci2auvMqjlqMExlp608OwaGHcpmoijNZQsKgTAW8Z4z28
 | 
				
			||||||
djd4WXBLSUhORktzZ2sKzMjxqL3UPrtGmXDijdfu0AwxLJooK7ZKauYvXWSuZUrR
 | 
					9UbAMOmSWByLfgAzhoN4Xob5/40JjI2f3wFYwsAf0f/j6dLc2lmqxkhd+Zcj76Yj
 | 
				
			||||||
vl5i1QPMEEBYEl+NaZIFgxAFqWpAXHQ1VxSijMWxNjKUd1Chq0tbLrpbh9wXJflK
 | 
					t2WbVgPlBMqPQIoFd6TtwJweqzzGmLI=
 | 
				
			||||||
SW19Wyqc9eTb8BnFoOSYWpDvAs2Lbyr2kJkOj2TNrwMv8nDJdOB8XIPlV5drCj1q
 | 
					 | 
				
			||||||
Dx/1zWqm6NMYxsep6eZkv4AzxA==
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,13 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrd0pM
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA0N01m
 | 
				
			||||||
TGw1anJNaGoyQ3lMUis1cHVtRWFPcFFNZk9Cdm9TMEh1QTdKc25ZCm9VNzVQcUxE
 | 
					Z1RiUHFFbmlDVVgwTWQ5Nmw3WU1NckVFcWQ1SGVsQlZLdGIxSFJzCnZpL3dmRWdY
 | 
				
			||||||
Njh2Wi80RWszSU5NczRNcHpVYXpRMzJNcDRsdGxyWVZsUDgKLT4gWDI1NTE5IFpT
 | 
					UlVaOW0yT1ZmUXU0VkFHNmRzbFk4cEt3dW91MHdnR240eVEKLT4gWDI1NTE5IGtC
 | 
				
			||||||
MEJVUkcycVFJaVFOUURoL29VT3R0MVJCWW04NXVRVEpKY3hlY1lWRkEKcENya1Jx
 | 
					RTg1eThyRHlSZ0VsUEVzUm1EYVFIVHZZaHNvY21mOS9mTnlRbW03aEkKQjIraStT
 | 
				
			||||||
VnBCMVBrZkc4VDkvMnZoTllCL09vQ0VOZytuMnRvYVQxL2FldwotPiAzLWdyZWFz
 | 
					WE5sRUx3S29CcTRobHZVQXJDQTQ1YXg4Z2c4cS9zSVhVVElXcwotPiBoM09vUG0t
 | 
				
			||||||
ZSBCNX0gIiB7InIsfCAkOT9uM2UKUWpSYTZ1dUo3SHNaUlFibTl0UDhTaFh5Mk1n
 | 
					Z3JlYXNlIF4nRnwkeSEgKTRZIHIKT2FXTWZmbW9jSnkrYmp0WWVDVTZHdFFxcXJt
 | 
				
			||||||
bFp2cjM5RGhqU0s0Qm50Zk1pUVZmT0R6ZjBoUG1EUGlKbHFzVwozQ2t1cWVDVVAv
 | 
					Rkg3S08xVGZ0TVVjTHQwaExFbkh3WDB6bWJkVEFKYXpQUDEvSQpGNXY0ZS94SVY5
 | 
				
			||||||
Q21QTjF3NW5UdTBZRldnL0RmSlV3QndHcDB0d0lvZ1RHTTByS1ZwNkNVQnU3WmVn
 | 
					anViSzJ3NlNOUmp0eUliYms1Smd0RUVXVGhxdlV6TkFNVkpzcwotLS0gQnc2Y0ZS
 | 
				
			||||||
ZwotLS0gb0Fxb2FsYzgwRjJwSUF3ei9hZVR2Vk1ORDlIMWoyZ2RTd09hUmtvMWpD
 | 
					aGNtL2RwUjVxZE9uYlpBeVMwd2M4RTNsdW0wVWpDd2hLLzJSWQq07wZpB40EpZog
 | 
				
			||||||
cwrEjdaYfoGZ9i/S97xL9QvA/yii+sJLeuUzzv7a3DE661eQ5ezurV8Qz1tIhxWG
 | 
					fW3t5Uokt7EZL4V4RX9PFyd48SaEd/xR1FiEL7jg8IJp0dY7hdfnzObQbueCwUOi
 | 
				
			||||||
RsOppaaj1podFx3U1x7QQbLO6zQbJA458RMjYgc=
 | 
					lWOfF3n8XpzS8uo5TgLWLtY=
 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----END AGE ENCRYPTED FILE-----
 | 
				
			||||||
 
 | 
				
			|||||||
@@ -1,13 +1,12 @@
 | 
				
			|||||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
					-----BEGIN AGE ENCRYPTED FILE-----
 | 
				
			||||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBHNWg0
 | 
					YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA4bGQr
 | 
				
			||||||
WGRGZnlTdEhsRm96T0ZMOWx4UUxkTitJa3hMWDE1dVkreEtEa0RVClpvR2I5NGpz
 | 
					dzJZbU4reWI1Sk45QTR3UkRoc0NvaDBFcUwrVWlCYWUrcWtYZGpNCm1PWjVzRVlt
 | 
				
			||||||
aUF0N1VZU05oWXUzTEI1TVBLYlVVang3Zzgwbi9teDVlQlEKLT4gWDI1NTE5IG4v
 | 
					UDFKY2ZSZTg4S2pVZ0pDNzR1WklYQ3pEclJZLy9kKzdGTGsKLT4gWDI1NTE5IHFO
 | 
				
			||||||
OXRIbzhaZEdXc1pjTnRRWHVxc2ZTcmozSlJkY3lyOGtvd1BVeGprVUkKdUNqSW94
 | 
					TXVRK2d3azg2cHpRanhUNXp6YnRsZW1MUDJqc3l1bnNYNUhHaTIzMVkKWXp1M09H
 | 
				
			||||||
SUIyOWtsNU83cnVOTUxNR1BvWHJPczdzUWc4aGp1MjlpZm5ESQotPiA2KSV2PVx5
 | 
					TnJIazRmb0tOSnE1Q0E1dERiaHZCQkh2YzE1cS9zRUhwaEovMAotPiBzPj5nLWdy
 | 
				
			||||||
LWdyZWFzZSBqezVxOHc9biA+aD4tP20mXwpwRCtMUDhmcVhGNXpCZlFmSllpdDVp
 | 
					ZWFzZQozSThRWnJCcVFFRHpoSi9tZnZMdnJoRlFud2VISHBHSThMem9qZVVWdS9C
 | 
				
			||||||
SmFZelNhZnJlR25DS2l2MlQ3ZGFtdGxkZEdEWVNrRlk1VEZBRm9GMHBFCkVlQ1hp
 | 
					VFBDVEVzbUVCdFU2Qy9PaGdyc0FaCmk3UFZma2ZiR3hmWG1sa053bDBnY04yZ1VZ
 | 
				
			||||||
WnhOTGl2R2s5RDRKN0p5TmF6Y0cyN3ZlR2pDZlhMVjQ1c0FJN3hCbFEKLS0tIEFT
 | 
					TW9jZwotLS0gMDVSaE5aakxHenFPVXpXa1JxczlWQ2x2VGNuQzdwaWZFTTFTaUp6
 | 
				
			||||||
bjFiRStXMmJueHdsRm1nU084dDRpS0tBT21ENzZFclJXbE11NWJETm8KyMHU+tZY
 | 
					cnRmZwoomylfwjD5A3N21/mk1Wtt8f4bsK747iZz7KT34kqmoX597rbGYxyip5lg
 | 
				
			||||||
QELtZCbXKWnP8QC6V84JIFAxoRslACwsIJZpogcZO/IFIV2RGunGjCJk6QBmhOPV
 | 
					VLZV6CY4LLRjnnSKoC2hIXU0dgudAmvxhztuaQ42fOc=
 | 
				
			||||||
kJXRcGO/ndYjWfuU0U3+9HtPocnO
 | 
					 | 
				
			||||||
-----END AGE ENCRYPTED FILE-----
 | 
					-----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