Compare commits
	
		
			1 Commits
		
	
	
		
			fastback-s
			...
			1e66a99352
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| 1e66a99352 | 
							
								
								
									
										2
									
								
								.envrc
									
									
									
									
									
								
							
							
						
						
									
										2
									
								
								.envrc
									
									
									
									
									
								
							@@ -1,2 +1,2 @@
 | 
			
		||||
watch_file devshell/{default,commands,install,vm-tasks}.nix
 | 
			
		||||
nix_direnv_watch_file devshell/{default,commands,install,vm-tasks}.nix
 | 
			
		||||
use flake
 | 
			
		||||
 
 | 
			
		||||
@@ -33,18 +33,18 @@ jobs:
 | 
			
		||||
      - name: Build installer ISO
 | 
			
		||||
        run: |
 | 
			
		||||
          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso
 | 
			
		||||
          ln -s "$(readlink result)"/iso/jackos-installer.iso \
 | 
			
		||||
            jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
 | 
			
		||||
          ln -s "$(readlink result)"/iso/nixos-installer-devplayer0.iso \
 | 
			
		||||
            nixos-installer-devplayer0-${{ steps.setup.outputs.short_rev }}.iso
 | 
			
		||||
      - name: Build installer netboot archive
 | 
			
		||||
        run: |
 | 
			
		||||
          nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive
 | 
			
		||||
          ln -s "$(readlink result)" \
 | 
			
		||||
            jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
			
		||||
            nixos-installer-devplayer0-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
			
		||||
 | 
			
		||||
      - name: Create release
 | 
			
		||||
        uses: https://gitea.com/actions/release-action@main
 | 
			
		||||
        with:
 | 
			
		||||
          title: Latest installer
 | 
			
		||||
          files: |
 | 
			
		||||
            jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
 | 
			
		||||
            jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
			
		||||
            nixos-installer-devplayer0-${{ steps.setup.outputs.short_rev }}.iso
 | 
			
		||||
            nixos-installer-devplayer0-netboot-${{ steps.setup.outputs.short_rev }}.tar
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										152
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										152
									
								
								flake.lock
									
									
									
										generated
									
									
									
								
							@@ -35,11 +35,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1702969472,
 | 
			
		||||
        "narHash": "sha256-IJP9sC+/gLUdWhm6TsnWpw6A1zQWUfn53ym63KeLXvU=",
 | 
			
		||||
        "lastModified": 1698258239,
 | 
			
		||||
        "narHash": "sha256-qnhoYYIJ0L/P7H/f56lQUEvpzNlXh4sxuHpRERV+B44=",
 | 
			
		||||
        "owner": "zhaofengli",
 | 
			
		||||
        "repo": "attic",
 | 
			
		||||
        "rev": "bdafd64910bb2b861cf90fa15f1fc93318b6fbf6",
 | 
			
		||||
        "rev": "e9918bc6be268da6fa97af6ced15193d8a0421c0",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -95,17 +95,26 @@
 | 
			
		||||
    },
 | 
			
		||||
    "crane": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-compat": [
 | 
			
		||||
          "attic",
 | 
			
		||||
          "flake-compat"
 | 
			
		||||
        ],
 | 
			
		||||
        "flake-utils": [
 | 
			
		||||
          "attic",
 | 
			
		||||
          "flake-utils"
 | 
			
		||||
        ],
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "attic",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
        ],
 | 
			
		||||
        "rust-overlay": "rust-overlay"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1702918879,
 | 
			
		||||
        "narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=",
 | 
			
		||||
        "lastModified": 1677892403,
 | 
			
		||||
        "narHash": "sha256-/Wi0L1spSWLFj+UQxN3j0mPYMoc7ZoAujpUF/juFVII=",
 | 
			
		||||
        "owner": "ipetkov",
 | 
			
		||||
        "repo": "crane",
 | 
			
		||||
        "rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb",
 | 
			
		||||
        "rev": "105e27adb70a9890986b6d543a67761cbc1964a2",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -176,11 +185,11 @@
 | 
			
		||||
        "utils": "utils"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703087360,
 | 
			
		||||
        "narHash": "sha256-0VUbWBW8VyiDRuimMuLsEO4elGuUw/nc2WDeuO1eN1M=",
 | 
			
		||||
        "lastModified": 1698921442,
 | 
			
		||||
        "narHash": "sha256-7KmvhQ7FuXlT/wG4zjTssap6maVqeAMBdtel+VjClSM=",
 | 
			
		||||
        "owner": "serokell",
 | 
			
		||||
        "repo": "deploy-rs",
 | 
			
		||||
        "rev": "b709d63debafce9f5645a5ba550c9e0983b3d1f7",
 | 
			
		||||
        "rev": "660180bbbeae7d60dad5a92b30858306945fd427",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -232,14 +241,14 @@
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ],
 | 
			
		||||
        "systems": "systems_4"
 | 
			
		||||
        "systems": "systems_3"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701787589,
 | 
			
		||||
        "narHash": "sha256-ce+oQR4Zq9VOsLoh9bZT8Ip9PaMLcjjBUHVPzW5d7Cw=",
 | 
			
		||||
        "lastModified": 1698410321,
 | 
			
		||||
        "narHash": "sha256-MphuSlgpmKwtJncGMohryHiK55J1n6WzVQ/OAfmfoMc=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "devshell",
 | 
			
		||||
        "rev": "44ddedcbcfc2d52a76b64fb6122f209881bd3e1e",
 | 
			
		||||
        "rev": "1aed986e3c81a4f6698e85a7452cbfcc4b31a36e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -267,11 +276,11 @@
 | 
			
		||||
    "flake-compat_2": {
 | 
			
		||||
      "flake": false,
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1696426674,
 | 
			
		||||
        "narHash": "sha256-kvjfFW7WAETZlt09AgDn1MrtKzP7t90Vf7vypd3OL1U=",
 | 
			
		||||
        "lastModified": 1668681692,
 | 
			
		||||
        "narHash": "sha256-Ht91NGdewz8IQLtWZ9LCeNXMSXHUss+9COoqu6JLmXU=",
 | 
			
		||||
        "owner": "edolstra",
 | 
			
		||||
        "repo": "flake-compat",
 | 
			
		||||
        "rev": "0f9255e01c2351cc7d116c072cb317785dd33b33",
 | 
			
		||||
        "rev": "009399224d5e398d03b22badca40a37ac85412a1",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -409,14 +418,14 @@
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_7": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_5"
 | 
			
		||||
        "systems": "systems_4"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701680307,
 | 
			
		||||
        "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
 | 
			
		||||
        "lastModified": 1694529238,
 | 
			
		||||
        "narHash": "sha256-zsNZZGTGnMOf9YpHKJqMSsa0dXbfmxeoJ7xHlrt+xmY=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
 | 
			
		||||
        "rev": "ff7b65b44d01cf9ba6a71320833626af21126384",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -442,7 +451,7 @@
 | 
			
		||||
    },
 | 
			
		||||
    "flake-utils_9": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_6"
 | 
			
		||||
        "systems": "systems_5"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681202837,
 | 
			
		||||
@@ -465,11 +474,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703367386,
 | 
			
		||||
        "narHash": "sha256-FMbm48UGrBfOWGt8+opuS+uLBLQlRfhiYXhHNcYMS5k=",
 | 
			
		||||
        "lastModified": 1700814205,
 | 
			
		||||
        "narHash": "sha256-lWqDPKHRbQfi+zNIivf031BUeyciVOtwCwTjyrhDB5g=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "rev": "d5824a76bc6bb93d1dce9ebbbcb09a9b6abcc224",
 | 
			
		||||
        "rev": "aeb2232d7a32530d3448318790534d196bf9427a",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -485,11 +494,11 @@
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703754036,
 | 
			
		||||
        "narHash": "sha256-JpJdcj9Tg4lMuYikXDpajA8wOp+rHyn9RD2rKBEM4cQ=",
 | 
			
		||||
        "lastModified": 1701433070,
 | 
			
		||||
        "narHash": "sha256-Gf9JStfENaUQ7YWFz3V7x/srIwr4nlnVteqaAxtwpgM=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "home-manager",
 | 
			
		||||
        "rev": "c24c298562fe41b39909f632c5a7151bbf6b4628",
 | 
			
		||||
        "rev": "4a8545f5e737a6338814a4676dc8e18c7f43fc57",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -499,11 +508,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "impermanence": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703656108,
 | 
			
		||||
        "narHash": "sha256-hCSUqdFJKHHbER8Cenf5JRzjMlBjIdwdftGQsO0xoJs=",
 | 
			
		||||
        "lastModified": 1697303681,
 | 
			
		||||
        "narHash": "sha256-caJ0rXeagaih+xTgRduYtYKL1rZ9ylh06CIrt1w5B4g=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "repo": "impermanence",
 | 
			
		||||
        "rev": "033643a45a4a920660ef91caa391fbffb14da466",
 | 
			
		||||
        "rev": "0f317c2e9e56550ce12323eb39302d251618f5b5",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -522,13 +531,13 @@
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1685908677,
 | 
			
		||||
        "narHash": "sha256-E4zUPEUFyVWjVm45zICaHRpfGepfkE9Z2OECV9HXfA4=",
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "owner": "guibou",
 | 
			
		||||
        "repo": "nixGL",
 | 
			
		||||
        "rev": "489d6b095ab9d289fe11af0219a9ff00fe87c7c5",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-community",
 | 
			
		||||
        "owner": "guibou",
 | 
			
		||||
        "repo": "nixGL",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
@@ -551,11 +560,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-mine": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703756459,
 | 
			
		||||
        "narHash": "sha256-ztEMyPQZh3Pb+LOoWl5lbIK2LenP59sOUBC86CDmLio=",
 | 
			
		||||
        "lastModified": 1701607327,
 | 
			
		||||
        "narHash": "sha256-pHX6S1mrUSFVq6v0HiZuShfXLL01wiWvgivCabX2x+M=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "e80160eb2ac3a7111d07cc43a15c16b9edca01ea",
 | 
			
		||||
        "rev": "c8af66cb9046a65cbab33563f804b7bad46173af",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -567,11 +576,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-mine-stable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703756491,
 | 
			
		||||
        "narHash": "sha256-9VL34e0gzomwqRnryRn23V2ImYcaZIQdp7CsWg5TmlE=",
 | 
			
		||||
        "lastModified": 1701607437,
 | 
			
		||||
        "narHash": "sha256-ozMDOyJtxr/CznI6lrwtt9JkU32Y2cLr2B4vlW85Tfw=",
 | 
			
		||||
        "owner": "devplayer0",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "36611f5f7cfd401f51ad4ca76fd6ee85a714bb74",
 | 
			
		||||
        "rev": "67ef05e2dd98d1fd856028eba1bb4edb847f6c6e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -583,11 +592,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-stable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703467016,
 | 
			
		||||
        "narHash": "sha256-/5A/dNPhbQx/Oa2d+Get174eNI3LERQ7u6WTWOlR1eQ=",
 | 
			
		||||
        "lastModified": 1701389149,
 | 
			
		||||
        "narHash": "sha256-rU1suTIEd5DGCaAXKW6yHoCfR1mnYjOXQFOaH7M23js=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "d02d818f22c777aa4e854efc3242ec451e5d462a",
 | 
			
		||||
        "rev": "5de0b32be6e85dc1a9404c75131316e4ffbc634c",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -598,11 +607,11 @@
 | 
			
		||||
    },
 | 
			
		||||
    "nixpkgs-unstable": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1703438236,
 | 
			
		||||
        "narHash": "sha256-aqVBq1u09yFhL7bj1/xyUeJjzr92fXVvQSSEx6AdB1M=",
 | 
			
		||||
        "lastModified": 1701253981,
 | 
			
		||||
        "narHash": "sha256-ztaDIyZ7HrTAfEEUt9AtTDNoCYxUdSd6NrRHaYOIxtk=",
 | 
			
		||||
        "owner": "NixOS",
 | 
			
		||||
        "repo": "nixpkgs",
 | 
			
		||||
        "rev": "5f64a12a728902226210bf01d25ec6cbb9d9265b",
 | 
			
		||||
        "rev": "e92039b55bcd58469325ded85d4f58dd5a4eaf58",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
@@ -669,7 +678,7 @@
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "nixpkgs-unstable"
 | 
			
		||||
        ],
 | 
			
		||||
        "rust-overlay": "rust-overlay"
 | 
			
		||||
        "rust-overlay": "rust-overlay_2"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1682237245,
 | 
			
		||||
@@ -706,6 +715,33 @@
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "rust-overlay": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": [
 | 
			
		||||
          "attic",
 | 
			
		||||
          "crane",
 | 
			
		||||
          "flake-utils"
 | 
			
		||||
        ],
 | 
			
		||||
        "nixpkgs": [
 | 
			
		||||
          "attic",
 | 
			
		||||
          "crane",
 | 
			
		||||
          "nixpkgs"
 | 
			
		||||
        ]
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1675391458,
 | 
			
		||||
        "narHash": "sha256-ukDKZw922BnK5ohL9LhwtaDAdCsJL7L6ScNEyF1lO9w=",
 | 
			
		||||
        "owner": "oxalica",
 | 
			
		||||
        "repo": "rust-overlay",
 | 
			
		||||
        "rev": "383a4acfd11d778d5c2efcf28376cbd845eeaedf",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "oxalica",
 | 
			
		||||
        "repo": "rust-overlay",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "rust-overlay_2": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "flake-utils": [
 | 
			
		||||
          "ragenix",
 | 
			
		||||
@@ -826,31 +862,13 @@
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "systems_6": {
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1681028828,
 | 
			
		||||
        "narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
        "owner": "nix-systems",
 | 
			
		||||
        "repo": "default",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      }
 | 
			
		||||
    },
 | 
			
		||||
    "utils": {
 | 
			
		||||
      "inputs": {
 | 
			
		||||
        "systems": "systems_3"
 | 
			
		||||
      },
 | 
			
		||||
      "locked": {
 | 
			
		||||
        "lastModified": 1701680307,
 | 
			
		||||
        "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
 | 
			
		||||
        "lastModified": 1667395993,
 | 
			
		||||
        "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
 | 
			
		||||
        "owner": "numtide",
 | 
			
		||||
        "repo": "flake-utils",
 | 
			
		||||
        "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
 | 
			
		||||
        "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
 | 
			
		||||
        "type": "github"
 | 
			
		||||
      },
 | 
			
		||||
      "original": {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,7 +26,7 @@
 | 
			
		||||
    impermanence.url = "github:nix-community/impermanence";
 | 
			
		||||
    boardie.url = "github:devplayer0/boardie";
 | 
			
		||||
    boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
			
		||||
    nixGL.url = "github:nix-community/nixGL";
 | 
			
		||||
    nixGL.url = "github:guibou/nixGL";
 | 
			
		||||
    nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
 | 
			
		||||
 | 
			
		||||
    # Packages not in nixpkgs
 | 
			
		||||
@@ -63,7 +63,7 @@
 | 
			
		||||
        flake = flake-utils.lib;
 | 
			
		||||
      };
 | 
			
		||||
      pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; };
 | 
			
		||||
      myPkgsOverlay = final: prev: import ./pkgs { lib = final.lib; pkgs = prev; };
 | 
			
		||||
      myPkgsOverlay = final: prev: import ./pkgs { lib = prev.lib; pkgs = prev; };
 | 
			
		||||
 | 
			
		||||
      # Override the flake-level lib since we're going to use it for non-config specific stuff
 | 
			
		||||
      pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) {
 | 
			
		||||
@@ -129,7 +129,7 @@
 | 
			
		||||
        modules = [
 | 
			
		||||
          {
 | 
			
		||||
            _module.args = {
 | 
			
		||||
              inherit lib pkgsFlakes hmFlakes self inputs;
 | 
			
		||||
              inherit lib pkgsFlakes hmFlakes inputs;
 | 
			
		||||
              pkgs' = configPkgs';
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -80,7 +80,6 @@ in
 | 
			
		||||
 | 
			
		||||
        tmux = {
 | 
			
		||||
          enable = true;
 | 
			
		||||
          keyMode = "vi";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        bash = {
 | 
			
		||||
 
 | 
			
		||||
@@ -169,18 +169,6 @@ rec {
 | 
			
		||||
        port = 8448;
 | 
			
		||||
        dst = aa.middleman.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
      {
 | 
			
		||||
        port = 25565;
 | 
			
		||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
      {
 | 
			
		||||
        port = 25566;
 | 
			
		||||
        dst = aa.simpcraft-staging-oci.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
      {
 | 
			
		||||
        port = 25575;
 | 
			
		||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      {
 | 
			
		||||
        port = 2456;
 | 
			
		||||
@@ -198,12 +186,6 @@ rec {
 | 
			
		||||
        dst = aa.waffletail.internal.ipv4.address;
 | 
			
		||||
        proto = "udp";
 | 
			
		||||
      }
 | 
			
		||||
 | 
			
		||||
      {
 | 
			
		||||
        port = 25565;
 | 
			
		||||
        dst = aa.simpcraft-oci.internal.ipv4.address;
 | 
			
		||||
        proto = "udp";
 | 
			
		||||
      }
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    fstrimConfig = {
 | 
			
		||||
@@ -227,7 +209,7 @@ rec {
 | 
			
		||||
      "stream"
 | 
			
		||||
    ];
 | 
			
		||||
    routersPubV4 = [
 | 
			
		||||
      "109.255.1.246"
 | 
			
		||||
      "109.255.31.25"
 | 
			
		||||
      "109.255.252.63"
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
@@ -302,13 +284,11 @@ rec {
 | 
			
		||||
  as211024 = rec {
 | 
			
		||||
    trusted = {
 | 
			
		||||
      v4 = [
 | 
			
		||||
        colony.prefixes.as211024.v4
 | 
			
		||||
        colony.prefixes.all.v4
 | 
			
		||||
        home.prefixes.all.v4
 | 
			
		||||
        tailscale.prefix.v4
 | 
			
		||||
      ];
 | 
			
		||||
      v6 = [
 | 
			
		||||
        colony.prefixes.as211024.v6
 | 
			
		||||
        colony.prefixes.all.v6
 | 
			
		||||
        home.prefixes.all.v6
 | 
			
		||||
        tailscale.prefix.v6
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,10 @@
 | 
			
		||||
{ lib }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) length match elemAt filter replaceStrings substring;
 | 
			
		||||
  inherit (builtins) length match elemAt filter replaceStrings;
 | 
			
		||||
  inherit (lib)
 | 
			
		||||
    genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types
 | 
			
		||||
    mkOption mkOverride mkForce mkIf mergeEqualOption optional
 | 
			
		||||
    showWarnings concatStringsSep flatten unique optionalAttrs
 | 
			
		||||
    mkBefore;
 | 
			
		||||
    showWarnings concatStringsSep flatten unique optionalAttrs;
 | 
			
		||||
  inherit (lib.flake) defaultSystems;
 | 
			
		||||
in
 | 
			
		||||
rec {
 | 
			
		||||
@@ -167,7 +166,7 @@ rec {
 | 
			
		||||
 | 
			
		||||
  systemdAwaitPostgres = pkg: host: {
 | 
			
		||||
    after = [ "systemd-networkd-wait-online.service" ];
 | 
			
		||||
    preStart = mkBefore ''
 | 
			
		||||
    preStart = ''
 | 
			
		||||
      until ${pkg}/bin/pg_isready -h ${host}; do
 | 
			
		||||
        sleep 0.5
 | 
			
		||||
      done
 | 
			
		||||
@@ -240,18 +239,4 @@ rec {
 | 
			
		||||
 | 
			
		||||
    filterOpts = filterAttrsRecursive (_: v: v != null);
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  versionOverlay = { self, pkgsFlake }: final: prev:
 | 
			
		||||
  let
 | 
			
		||||
    date = substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101");
 | 
			
		||||
    revCode = flake: flake.shortRev or "dirty";
 | 
			
		||||
  in
 | 
			
		||||
  {
 | 
			
		||||
    trivial = prev.trivial // {
 | 
			
		||||
      release = "23.12:u-${prev.trivial.release}";
 | 
			
		||||
      codeName = "Amogus";
 | 
			
		||||
      revisionWithDefault = default: self.rev or default;
 | 
			
		||||
      versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}";
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -154,7 +154,7 @@ in
 | 
			
		||||
                extraRules = ''
 | 
			
		||||
                  table inet filter {
 | 
			
		||||
                    chain forward {
 | 
			
		||||
                      ${lib.my.c.as211024.nftTrust}
 | 
			
		||||
                      ${lib.my.as211024.nftTrust}
 | 
			
		||||
                      oifname as211024 accept
 | 
			
		||||
                    }
 | 
			
		||||
                  }
 | 
			
		||||
 
 | 
			
		||||
@@ -49,19 +49,15 @@ in
 | 
			
		||||
          noise.private_key_path = "/var/lib/headscale/noise_private.key";
 | 
			
		||||
          ip_prefixes = with lib.my.c.tailscale.prefix; [ v4 v6 ];
 | 
			
		||||
          dns_config = {
 | 
			
		||||
            # Use IPs that will route inside the VPN to prevent interception
 | 
			
		||||
            # (e.g. DNS rebinding filtering)
 | 
			
		||||
            restricted_nameservers = {
 | 
			
		||||
              "${domain}" = pubNameservers;
 | 
			
		||||
              "${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [
 | 
			
		||||
              "${lib.my.c.colony.domain}" = with allAssignments.estuary.internal; [
 | 
			
		||||
                ipv4.address ipv6.address
 | 
			
		||||
              ];
 | 
			
		||||
              "${lib.my.c.home.domain}" = with allAssignments; [
 | 
			
		||||
                river.hi.ipv4.address
 | 
			
		||||
                river.hi.ipv6.address
 | 
			
		||||
                stream.hi.ipv4.address
 | 
			
		||||
                stream.hi.ipv6.address
 | 
			
		||||
              ];
 | 
			
		||||
              "${lib.my.c.home.domain}" = lib.my.c.home.routersPubV4 ++ ([
 | 
			
		||||
                allAssignments.river.as211024.ipv6.address
 | 
			
		||||
                allAssignments.stream.as211024.ipv6.address
 | 
			
		||||
              ]);
 | 
			
		||||
            };
 | 
			
		||||
            magic_dns = true;
 | 
			
		||||
            base_domain = "ts.${pubDomain}";
 | 
			
		||||
 
 | 
			
		||||
@@ -66,21 +66,10 @@ in
 | 
			
		||||
            };
 | 
			
		||||
          });
 | 
			
		||||
          kernelModules = [ "kvm-amd" ];
 | 
			
		||||
          kernelParams = [
 | 
			
		||||
            "amd_iommu=on"
 | 
			
		||||
            "console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0"
 | 
			
		||||
            "systemd.setenv=SYSTEMD_SULOGIN_FORCE=1"
 | 
			
		||||
          ];
 | 
			
		||||
          kernelParams = [ "amd_iommu=on" "console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0" ];
 | 
			
		||||
          initrd = {
 | 
			
		||||
            kernelModules = [ "dm-raid" ];
 | 
			
		||||
            availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
 | 
			
		||||
            systemd = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              # Onlu activate volumes needed for boot to prevent thin check from getting killed while switching root
 | 
			
		||||
              contents."/etc/lvm/lvm.conf".text = ''
 | 
			
		||||
                activation/auto_activation_volume_list = [ "main/colony-nix" "main/colony-persist" ]
 | 
			
		||||
              '';
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -148,15 +137,6 @@ in
 | 
			
		||||
          services = {
 | 
			
		||||
            "serial-getty@ttyS0".enable = true;
 | 
			
		||||
            "serial-getty@ttyS1".enable = true;
 | 
			
		||||
            lvm-activate-main = {
 | 
			
		||||
              description = "Activate remaining LVs";
 | 
			
		||||
              before = [ "local-fs-pre.target" ];
 | 
			
		||||
              serviceConfig = {
 | 
			
		||||
                Type = "oneshot";
 | 
			
		||||
                ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
 | 
			
		||||
              };
 | 
			
		||||
              wantedBy = [ "sysinit.target" ];
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            rsync-lvm-meta = {
 | 
			
		||||
              description = "rsync lvm metadata backups / archives to rsync.net";
 | 
			
		||||
 
 | 
			
		||||
@@ -120,7 +120,7 @@
 | 
			
		||||
              cpus = 12;
 | 
			
		||||
              threads = 2;
 | 
			
		||||
            };
 | 
			
		||||
            memory = 40960;
 | 
			
		||||
            memory = 49152;
 | 
			
		||||
            networks.vms.mac = "52:54:00:27:3d:5c";
 | 
			
		||||
            cleanShutdown.timeout = 120;
 | 
			
		||||
            drives = [ ] ++ (optionals (!config.my.build.isDevVM) [
 | 
			
		||||
@@ -160,7 +160,7 @@
 | 
			
		||||
              cpus = 12;
 | 
			
		||||
              threads = 2;
 | 
			
		||||
            };
 | 
			
		||||
            memory = 40960;
 | 
			
		||||
            memory = 32768;
 | 
			
		||||
            networks.vms.mac = "52:54:00:75:78:a8";
 | 
			
		||||
            cleanShutdown.timeout = 120;
 | 
			
		||||
            drives = [
 | 
			
		||||
@@ -181,7 +181,7 @@
 | 
			
		||||
              cpus = 3;
 | 
			
		||||
              threads = 2;
 | 
			
		||||
            };
 | 
			
		||||
            memory = 6144;
 | 
			
		||||
            memory = 8192;
 | 
			
		||||
            networks.public = {
 | 
			
		||||
              bridge = null;
 | 
			
		||||
              mac = "52:54:00:a8:d1:03";
 | 
			
		||||
 
 | 
			
		||||
@@ -393,16 +393,12 @@ in
 | 
			
		||||
                      # Safe enough to allow all SSH
 | 
			
		||||
                      tcp dport ssh accept
 | 
			
		||||
 | 
			
		||||
                      ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept
 | 
			
		||||
                      ${matchInet "tcp dport { http, https } accept" "git"}
 | 
			
		||||
                      ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept
 | 
			
		||||
                      ip6 daddr ${aa.simpcraft-staging-oci.internal.ipv6.address} tcp dport 25565 accept
 | 
			
		||||
                      ${matchInet "tcp dport { http, https, 8448 } accept" "middleman"}
 | 
			
		||||
                      return
 | 
			
		||||
                    }
 | 
			
		||||
                    chain routing-udp {
 | 
			
		||||
                      ip6 daddr ${aa.valheim-oci.internal.ipv6.address} udp dport { 2456-2457 } accept
 | 
			
		||||
                      ip6 daddr ${aa.waffletail.internal.ipv6.address} udp dport 41641 accept
 | 
			
		||||
                      ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} udp dport 25565 accept
 | 
			
		||||
                      return
 | 
			
		||||
                    }
 | 
			
		||||
                    chain filter-routing {
 | 
			
		||||
@@ -433,6 +429,8 @@ in
 | 
			
		||||
                  table inet nat {
 | 
			
		||||
                    chain prerouting {
 | 
			
		||||
                      ${matchInet "meta l4proto { udp, tcp } th dport domain redirect to :5353" "estuary"}
 | 
			
		||||
                      ip daddr ${aa.git.internal.ipv4.address} tcp dport { http, https } dnat to ${aa.middleman.internal.ipv4.address}
 | 
			
		||||
                      ip6 daddr ${aa.git.internal.ipv6.address} tcp dport { http, https } dnat to ${aa.middleman.internal.ipv6.address}
 | 
			
		||||
                    }
 | 
			
		||||
                    chain postrouting {
 | 
			
		||||
                      ip saddr ${prefixes.all.v4} oifname != as211024 snat to ${assignments.internal.ipv4.address}
 | 
			
		||||
 
 | 
			
		||||
@@ -52,7 +52,7 @@ in
 | 
			
		||||
          allowFrom = [
 | 
			
		||||
            "127.0.0.0/8" "::1/128"
 | 
			
		||||
            prefixes.all.v4 prefixes.all.v6
 | 
			
		||||
          ] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]);
 | 
			
		||||
          ];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        settings = {
 | 
			
		||||
@@ -145,14 +145,9 @@ in
 | 
			
		||||
 | 
			
		||||
            http IN A ${assignments.internal.ipv4.address}
 | 
			
		||||
            http IN AAAA ${allAssignments.middleman.internal.ipv6.address}
 | 
			
		||||
            librespeed IN CNAME http.${config.networking.domain}.
 | 
			
		||||
 | 
			
		||||
            valheim IN A ${assignments.internal.ipv4.address}
 | 
			
		||||
            valheim IN AAAA ${allAssignments.valheim-oci.internal.ipv6.address}
 | 
			
		||||
            simpcraft IN A ${assignments.internal.ipv4.address}
 | 
			
		||||
            simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address}
 | 
			
		||||
            simpcraft-staging IN A ${assignments.internal.ipv4.address}
 | 
			
		||||
            simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address}
 | 
			
		||||
 | 
			
		||||
            mail-vm IN A ${net.cidr.host 0 prefixes.mail.v4}
 | 
			
		||||
            mail-vm IN AAAA ${net.cidr.host 1 prefixes.mail.v6}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,11 +1,8 @@
 | 
			
		||||
{ lib, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) mapAttrs;
 | 
			
		||||
  inherit (lib) mkMerge mkDefault;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c) pubDomain;
 | 
			
		||||
  inherit (lib.my.c.colony) domain prefixes;
 | 
			
		||||
  inherit (lib.my.c.nginx) baseHttpConfig proxyHeaders;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  nixos.systems.git = {
 | 
			
		||||
@@ -75,109 +72,9 @@ in
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            users = {
 | 
			
		||||
              users = {
 | 
			
		||||
                nginx.extraGroups = [ "acme" ];
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            security.acme = {
 | 
			
		||||
              acceptTerms = true;
 | 
			
		||||
              defaults = {
 | 
			
		||||
                email = "dev@nul.ie";
 | 
			
		||||
                server = "https://acme-v02.api.letsencrypt.org/directory";
 | 
			
		||||
                reloadServices = [ "nginx" ];
 | 
			
		||||
                dnsResolver = "8.8.8.8";
 | 
			
		||||
              };
 | 
			
		||||
              certs = {
 | 
			
		||||
                "${pubDomain}" = {
 | 
			
		||||
                  extraDomainNames = [
 | 
			
		||||
                    "*.${pubDomain}"
 | 
			
		||||
                  ];
 | 
			
		||||
                  dnsProvider = "cloudflare";
 | 
			
		||||
                  credentialsFile = config.age.secrets."middleman/cloudflare-credentials.conf".path;
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            services = {
 | 
			
		||||
              fstrim = lib.my.c.colony.fstrimConfig;
 | 
			
		||||
              # Hacks for Jsch (Minecraft FastBack) to work
 | 
			
		||||
              openssh = {
 | 
			
		||||
                hostKeys = [
 | 
			
		||||
                  {
 | 
			
		||||
                    bits = 4096;
 | 
			
		||||
                    path = "/etc/ssh/ssh_host_rsa_key";
 | 
			
		||||
                    type = "rsa";
 | 
			
		||||
                  }
 | 
			
		||||
                  {
 | 
			
		||||
                    path = "/etc/ssh/ssh_host_ed25519_key";
 | 
			
		||||
                    type = "ed25519";
 | 
			
		||||
                  }
 | 
			
		||||
 | 
			
		||||
                  {
 | 
			
		||||
                    type = "ecdsa-sha2-nistp256";
 | 
			
		||||
                    path = "/etc/ssh/ssh_host_ecdsa_key";
 | 
			
		||||
                  }
 | 
			
		||||
                ];
 | 
			
		||||
                settings = {
 | 
			
		||||
                  Macs = [
 | 
			
		||||
                    "hmac-sha2-512-etm@openssh.com"
 | 
			
		||||
                    "hmac-sha2-256-etm@openssh.com"
 | 
			
		||||
                    "umac-128-etm@openssh.com"
 | 
			
		||||
 | 
			
		||||
                    "hmac-sha2-256"
 | 
			
		||||
                  ];
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
              netdata.enable = true;
 | 
			
		||||
              nginx = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                enableReload = true;
 | 
			
		||||
 | 
			
		||||
                logError = "stderr info";
 | 
			
		||||
                recommendedTlsSettings = true;
 | 
			
		||||
                clientMaxBodySize = "0";
 | 
			
		||||
                serverTokens = true;
 | 
			
		||||
                sslDhparam = config.age.secrets."dhparams.pem".path;
 | 
			
		||||
 | 
			
		||||
                # Based on recommended*Settings, but probably better to be explicit about these
 | 
			
		||||
                appendHttpConfig = ''
 | 
			
		||||
                  ${baseHttpConfig}
 | 
			
		||||
 | 
			
		||||
                  # caching
 | 
			
		||||
                  proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=512m;
 | 
			
		||||
                '';
 | 
			
		||||
 | 
			
		||||
                virtualHosts =
 | 
			
		||||
                let
 | 
			
		||||
                  hosts = {
 | 
			
		||||
                    "_" = {
 | 
			
		||||
                      default = true;
 | 
			
		||||
                      forceSSL = true;
 | 
			
		||||
                      onlySSL = false;
 | 
			
		||||
                      locations = {
 | 
			
		||||
                        "/".root = "${pkgs.nginx}/html";
 | 
			
		||||
                      };
 | 
			
		||||
                    };
 | 
			
		||||
 | 
			
		||||
                    "git.${pubDomain}" = {
 | 
			
		||||
                      locations."/".proxyPass = "http://localhost:3000";
 | 
			
		||||
                    };
 | 
			
		||||
                  };
 | 
			
		||||
 | 
			
		||||
                  defaultsFor = mapAttrs (n: _: {
 | 
			
		||||
                    onlySSL = mkDefault true;
 | 
			
		||||
                    useACMEHost = mkDefault pubDomain;
 | 
			
		||||
                    kTLS = mkDefault true;
 | 
			
		||||
                    http2 = mkDefault true;
 | 
			
		||||
                  });
 | 
			
		||||
                in
 | 
			
		||||
                mkMerge [
 | 
			
		||||
                  hosts
 | 
			
		||||
                  (defaultsFor hosts)
 | 
			
		||||
                ];
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            virtualisation = {
 | 
			
		||||
@@ -207,24 +104,11 @@ in
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            my = {
 | 
			
		||||
              secrets = {
 | 
			
		||||
                key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+KINpHLMduBuW96JzfSRDLUzkI+XaCBghu5/wHiW5R";
 | 
			
		||||
                files = {
 | 
			
		||||
                  "dhparams.pem" = {
 | 
			
		||||
                    owner = "acme";
 | 
			
		||||
                    group = "acme";
 | 
			
		||||
                    mode = "440";
 | 
			
		||||
                  };
 | 
			
		||||
                  "middleman/cloudflare-credentials.conf" = {
 | 
			
		||||
                    owner = "acme";
 | 
			
		||||
                    group = "acme";
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
              secrets.key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+KINpHLMduBuW96JzfSRDLUzkI+XaCBghu5/wHiW5R";
 | 
			
		||||
              server.enable = true;
 | 
			
		||||
 | 
			
		||||
              firewall = {
 | 
			
		||||
                tcp.allowed = [ 19999 "http" "https" ];
 | 
			
		||||
                tcp.allowed = [ 19999 ];
 | 
			
		||||
                extraRules = ''
 | 
			
		||||
                  table inet filter {
 | 
			
		||||
                    chain forward {
 | 
			
		||||
 
 | 
			
		||||
@@ -26,6 +26,18 @@ in
 | 
			
		||||
 | 
			
		||||
    systemd = {
 | 
			
		||||
      services = {
 | 
			
		||||
        # TODO: Figure out a way to do this properly... redirecting localhost is awkward...
 | 
			
		||||
        local-http-forward = {
 | 
			
		||||
          description = "Forward local HTTP connections";
 | 
			
		||||
          serviceConfig.ExecStart = "${pkgs.socat}/bin/socat tcp-listen:80,fork tcp:${allAssignments.middleman.internal.ipv4.address}:80";
 | 
			
		||||
          wantedBy = [ "multi-user.target" ];
 | 
			
		||||
        };
 | 
			
		||||
        local-https-forward = {
 | 
			
		||||
          description = "Forward local HTTPS connections";
 | 
			
		||||
          serviceConfig.ExecStart = "${pkgs.socat}/bin/socat tcp-listen:443,fork tcp:${allAssignments.middleman.internal.ipv4.address}:443";
 | 
			
		||||
          wantedBy = [ "multi-user.target" ];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        gitea = mkMerge [
 | 
			
		||||
          (lib.my.systemdAwaitPostgres pkgs.postgresql "colony-psql")
 | 
			
		||||
          {
 | 
			
		||||
@@ -129,6 +141,21 @@ in
 | 
			
		||||
          "gitea/minio.txt" = ownedByGit;
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      firewall.extraRules = ''
 | 
			
		||||
        table inet filter {
 | 
			
		||||
          chain input {
 | 
			
		||||
            ip saddr ${prefixes.all.v4} tcp dport 3000 accept
 | 
			
		||||
            ip6 saddr ${prefixes.all.v6} tcp dport 3000 accept
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
        table inet nat {
 | 
			
		||||
          chain prerouting {
 | 
			
		||||
            ip daddr ${assignments.internal.ipv4.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv4.address}
 | 
			
		||||
            ip6 daddr ${assignments.internal.ipv6.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv6.address}
 | 
			
		||||
          }
 | 
			
		||||
        }
 | 
			
		||||
      '';
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -66,7 +66,6 @@ in
 | 
			
		||||
                  owner = "nginx";
 | 
			
		||||
                  group = "nginx";
 | 
			
		||||
                };
 | 
			
		||||
                "librespeed.toml" = { };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
@@ -123,19 +122,6 @@ in
 | 
			
		||||
                baseURL = "https://sso.${pubDomain}";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            librespeed = {
 | 
			
		||||
              frontend.servers = [
 | 
			
		||||
                {
 | 
			
		||||
                  name = "Amsterdam, Netherlands";
 | 
			
		||||
                  server = "//librespeed.${domain}";
 | 
			
		||||
                }
 | 
			
		||||
              ];
 | 
			
		||||
              backend = {
 | 
			
		||||
                enable = true;
 | 
			
		||||
                extraSettingsFile = config.age.secrets."librespeed.toml".path;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          users = {
 | 
			
		||||
 
 | 
			
		||||
@@ -347,41 +347,9 @@ in
 | 
			
		||||
        };
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
      "public.${pubDomain}" = {
 | 
			
		||||
        serverAliases = [ "p.${pubDomain}" ];
 | 
			
		||||
        locations."/" = {
 | 
			
		||||
          root = "/mnt/media/public";
 | 
			
		||||
          extraConfig = ''
 | 
			
		||||
            fancyindex on;
 | 
			
		||||
            fancyindex_show_dotfiles on;
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      "mc-map.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://simpcraft-oci.${domain}:8100";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
      "mc-rail.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://simpcraft-staging-oci.${domain}:3876";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      "librespeed.${domain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://localhost:8989";
 | 
			
		||||
      };
 | 
			
		||||
      "speed.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://localhost:8989";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      "md.${pubDomain}" = {
 | 
			
		||||
        locations."/" = {
 | 
			
		||||
          proxyPass = "http://object-ctr.${domain}:3000";
 | 
			
		||||
          proxyWebsockets = true;
 | 
			
		||||
          extraConfig = proxyHeaders;
 | 
			
		||||
        };
 | 
			
		||||
      "git.${pubDomain}" = {
 | 
			
		||||
        locations."/".proxyPass = "http://git-vm.${domain}:3000";
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
@@ -419,22 +387,7 @@ in
 | 
			
		||||
      "s3.${pubDomain}" = {
 | 
			
		||||
        serverAliases = [ "*.s3.${pubDomain}" ];
 | 
			
		||||
        inherit extraConfig;
 | 
			
		||||
        locations = {
 | 
			
		||||
          "/".proxyPass = s3Upstream;
 | 
			
		||||
          "/gitea/packages/" = {
 | 
			
		||||
            proxyPass = s3Upstream;
 | 
			
		||||
            # HACK: Docker images need the MIME type to be correct for the manifest but Gitea
 | 
			
		||||
            # doesn't tell S3... By hiding the header we can use add_header to set Content-Type
 | 
			
		||||
            # (normally can't be set directly)
 | 
			
		||||
            extraConfig = ''
 | 
			
		||||
              proxy_hide_header Content-Type;
 | 
			
		||||
              add_header Content-Type $upstream_http_content_type always;
 | 
			
		||||
              if ($args ~ "response-content-disposition=.+filename%3D%22manifest\.json%22") {
 | 
			
		||||
                add_header Content-Type "application/vnd.docker.distribution.manifest.v2+json";
 | 
			
		||||
              }
 | 
			
		||||
            '';
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
        locations."/".proxyPass = s3Upstream;
 | 
			
		||||
        useACMEHost = pubDomain;
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -48,17 +48,11 @@ in
 | 
			
		||||
                  group = config.my.user.config.group;
 | 
			
		||||
                };
 | 
			
		||||
                "object/atticd.env" = {};
 | 
			
		||||
                "object/hedgedoc.env" = {};
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            firewall = {
 | 
			
		||||
              tcp.allowed = [
 | 
			
		||||
                9000 9001
 | 
			
		||||
                config.services.sharry.config.bind.port
 | 
			
		||||
                8069
 | 
			
		||||
                config.services.hedgedoc.settings.port
 | 
			
		||||
              ];
 | 
			
		||||
              tcp.allowed = [ 9000 9001 config.services.sharry.config.bind.port 8069 ];
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            user.homeConfig = {
 | 
			
		||||
@@ -200,26 +194,6 @@ in
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            hedgedoc = {
 | 
			
		||||
              enable = true;
 | 
			
		||||
              environmentFile = config.age.secrets."object/hedgedoc.env".path;
 | 
			
		||||
              settings = {
 | 
			
		||||
                domain = "md.${pubDomain}";
 | 
			
		||||
                protocolUseSSL = true;
 | 
			
		||||
                db = {
 | 
			
		||||
                  dialect = "postgresql";
 | 
			
		||||
                  username = "hedgedoc";
 | 
			
		||||
                  database = "hedgedoc";
 | 
			
		||||
                  host = "colony-psql";
 | 
			
		||||
                };
 | 
			
		||||
                host = "::";
 | 
			
		||||
                allowAnonymous = false;
 | 
			
		||||
                allowAnonymousEdits = true;
 | 
			
		||||
                email = true;
 | 
			
		||||
                allowEmailRegister = false;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        }
 | 
			
		||||
        (mkIf config.my.build.isDevVM {
 | 
			
		||||
 
 | 
			
		||||
@@ -50,8 +50,6 @@ in
 | 
			
		||||
      };
 | 
			
		||||
    }) {
 | 
			
		||||
      valheim-oci = 2;
 | 
			
		||||
      simpcraft-oci = 3;
 | 
			
		||||
      simpcraft-staging-oci = 4;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
 | 
			
		||||
@@ -65,7 +63,6 @@ in
 | 
			
		||||
          "${modulesPath}/profiles/qemu-guest.nix"
 | 
			
		||||
 | 
			
		||||
          ./valheim.nix
 | 
			
		||||
          ./minecraft
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        config = mkMerge [
 | 
			
		||||
 
 | 
			
		||||
@@ -1,121 +0,0 @@
 | 
			
		||||
{ lib, pkgs, config, allAssignments, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) concatStringsSep;
 | 
			
		||||
  inherit (lib.my) dockerNetAssignment;
 | 
			
		||||
 | 
			
		||||
  # devplayer0
 | 
			
		||||
  op = "6d7d971b-ce10-435b-85c5-c99c0d8d288c";
 | 
			
		||||
  whitelist = concatStringsSep "," [
 | 
			
		||||
    op
 | 
			
		||||
    "dcd2ecb9-2b5e-49cb-9d4f-f5a76162df56" # Elderlypug
 | 
			
		||||
    "fcb26db2-c3ce-41aa-b588-efec79d37a8a" # Jesthral_
 | 
			
		||||
    "1d366062-12c0-4e29-aba7-6ab5d8c6bb05" # shr3kas0ras
 | 
			
		||||
    "703b378a-09f9-4c1d-9876-1c9305728c49" # OROURKEIRE
 | 
			
		||||
    "f105bbe6-eda6-4a13-a8cf-894e77cab77b" # Adzerq
 | 
			
		||||
    "1fc94979-41fb-497a-81e9-34ae24ca537a" # johnnyscrims
 | 
			
		||||
    "d53c91df-b6e6-4463-b106-e8427d7a8d01" # BossLonus
 | 
			
		||||
    "f439f64d-91c9-4c74-9ce5-df4d24cd8e05" # hynge_
 | 
			
		||||
    "d6ec4c91-5da2-44eb-b89d-71dc8fe017a0" # Eefah98
 | 
			
		||||
    "096a7348-fabe-4b2d-93fc-fd1fd5608fb0" # ToTheMoonStar
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  fastback = {
 | 
			
		||||
    gitConfig = pkgs.writeText "git-config" ''
 | 
			
		||||
      [user]
 | 
			
		||||
      	email = "simpcraft@nul.ie"
 | 
			
		||||
      	name = "Simpcraft bot"
 | 
			
		||||
    '';
 | 
			
		||||
    knownHosts = pkgs.writeText "known_hosts" ''
 | 
			
		||||
      git.nul.ie ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBD023ECzYmLeXIpcGVaciPjq6UN/Sjmsys5HP/Nei5GkrUZqPa3OJ2uSXKLUSKGYdeNhxaFTPJe8Yx3TsZxMme8=
 | 
			
		||||
    '';
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  config = {
 | 
			
		||||
    virtualisation.oci-containers.containers = {
 | 
			
		||||
      simpcraft = {
 | 
			
		||||
        image = "ghcr.io/itzg/minecraft-server:2023.12.2-java17-alpine";
 | 
			
		||||
 | 
			
		||||
        environment = {
 | 
			
		||||
          TYPE = "MODRINTH";
 | 
			
		||||
 | 
			
		||||
          EULA = "true";
 | 
			
		||||
          ENABLE_QUERY = "true";
 | 
			
		||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t §4§k-----";
 | 
			
		||||
          ICON = "/ext/icon.png";
 | 
			
		||||
 | 
			
		||||
          EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
			
		||||
          WHITELIST = whitelist;
 | 
			
		||||
          EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
			
		||||
          OPS = op;
 | 
			
		||||
          DIFFICULTY = "normal";
 | 
			
		||||
          SPAWN_PROTECTION = "0";
 | 
			
		||||
          VIEW_DISTANCE = "20";
 | 
			
		||||
 | 
			
		||||
          MAX_MEMORY = "6G";
 | 
			
		||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/cdj2bSKg/Simpcraft-0.1.2.mrpack";
 | 
			
		||||
 | 
			
		||||
          TZ = "Europe/Dublin";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        volumes = [
 | 
			
		||||
          "minecraft_data:/data"
 | 
			
		||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        extraOptions = [
 | 
			
		||||
          ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-oci"}''
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      simpcraft-staging = {
 | 
			
		||||
        image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
 | 
			
		||||
 | 
			
		||||
        environment = {
 | 
			
		||||
          TYPE = "MODRINTH";
 | 
			
		||||
 | 
			
		||||
          EULA = "true";
 | 
			
		||||
          ENABLE_QUERY = "true";
 | 
			
		||||
          ENABLE_RCON = "true";
 | 
			
		||||
          MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
 | 
			
		||||
          ICON = "/ext/icon.png";
 | 
			
		||||
 | 
			
		||||
          EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
 | 
			
		||||
          WHITELIST = whitelist;
 | 
			
		||||
          EXISTING_OPS_FILE = "SYNCHRONIZE";
 | 
			
		||||
          OPS = op;
 | 
			
		||||
          DIFFICULTY = "normal";
 | 
			
		||||
          SPAWN_PROTECTION = "0";
 | 
			
		||||
          VIEW_DISTANCE = "20";
 | 
			
		||||
 | 
			
		||||
          MAX_MEMORY = "4G";
 | 
			
		||||
          MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
 | 
			
		||||
 | 
			
		||||
          TZ = "Europe/Dublin";
 | 
			
		||||
        };
 | 
			
		||||
        environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
 | 
			
		||||
 | 
			
		||||
        volumes = [
 | 
			
		||||
          "minecraft_staging_data:/data"
 | 
			
		||||
          "${./icon.png}:/ext/icon.png:ro"
 | 
			
		||||
          "${fastback.gitConfig}:/data/.config/git/config:ro"
 | 
			
		||||
          "${fastback.knownHosts}:/data/.ssh/known_hosts:ro"
 | 
			
		||||
          "${config.age.secrets."whale2/simpcraft-git.key".path}:/data/.ssh/id_rsa"
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        extraOptions = [
 | 
			
		||||
          ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
 | 
			
		||||
        ];
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    my = {
 | 
			
		||||
      secrets.files = {
 | 
			
		||||
        "whale2/simpcraft.env" = {};
 | 
			
		||||
        "whale2/simpcraft-git.key" = {
 | 
			
		||||
          owner = "1000";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
										
											Binary file not shown.
										
									
								
							| 
		 Before Width: | Height: | Size: 5.4 KiB  | 
@@ -94,7 +94,7 @@ in
 | 
			
		||||
            extraOptions = [ "-A /var/log/smartd/" "--interval=600" ];
 | 
			
		||||
          };
 | 
			
		||||
          udev.extraRules = ''
 | 
			
		||||
            ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="3"
 | 
			
		||||
            ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="2"
 | 
			
		||||
          '';
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
@@ -110,7 +110,7 @@ in
 | 
			
		||||
          hwloc
 | 
			
		||||
        ];
 | 
			
		||||
 | 
			
		||||
        networking = { inherit domain; };
 | 
			
		||||
        networking.domain = "h.${pubDomain}";
 | 
			
		||||
 | 
			
		||||
        systemd = {
 | 
			
		||||
          tmpfiles.rules = [
 | 
			
		||||
@@ -144,13 +144,6 @@ in
 | 
			
		||||
 | 
			
		||||
            netdevs = mkMerge [
 | 
			
		||||
              (mkVLAN "lan-hi" vlans.hi)
 | 
			
		||||
              (mkVLAN "lan-lo-phy" vlans.lo)
 | 
			
		||||
              {
 | 
			
		||||
                "25-lan-lo".netdevConfig = {
 | 
			
		||||
                  Name = "lan-lo";
 | 
			
		||||
                  Kind = "bridge";
 | 
			
		||||
                };
 | 
			
		||||
              }
 | 
			
		||||
            ];
 | 
			
		||||
 | 
			
		||||
            networks = {
 | 
			
		||||
@@ -158,7 +151,6 @@ in
 | 
			
		||||
                (networkdAssignment "lan-core" assignments.core)
 | 
			
		||||
                {
 | 
			
		||||
                  matchConfig.Name = "lan-core";
 | 
			
		||||
                  vlan = [ "lan-lo-phy" ];
 | 
			
		||||
                  networkConfig.IPv6AcceptRA = mkForce false;
 | 
			
		||||
                }
 | 
			
		||||
              ];
 | 
			
		||||
@@ -181,28 +173,9 @@ in
 | 
			
		||||
                  VirtualFunction=1
 | 
			
		||||
                  LinkState=yes
 | 
			
		||||
                  MACAddress=52:54:00:8a:8a:f2
 | 
			
		||||
 | 
			
		||||
                  # sfh
 | 
			
		||||
                  [SR-IOV]
 | 
			
		||||
                  VirtualFunction=2
 | 
			
		||||
                  VLANId=${toString vlans.hi}
 | 
			
		||||
                  LinkState=yes
 | 
			
		||||
                  MACAddress=52:54:00:ac:15:a9
 | 
			
		||||
                '';
 | 
			
		||||
              };
 | 
			
		||||
              "60-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
 | 
			
		||||
 | 
			
		||||
              "50-lan-lo-phy" = {
 | 
			
		||||
                matchConfig.Name = "lan-lo-phy";
 | 
			
		||||
                networkConfig = {
 | 
			
		||||
                  Bridge = "lan-lo";
 | 
			
		||||
                } // networkd.noL3;
 | 
			
		||||
              };
 | 
			
		||||
              "60-lan-lo" = {
 | 
			
		||||
                matchConfig.Name = "lan-lo";
 | 
			
		||||
                linkConfig.RequiredForOnline = "no";
 | 
			
		||||
                networkConfig = networkd.noL3;
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 
 | 
			
		||||
@@ -58,8 +58,6 @@ in
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
            networking = { inherit domain; };
 | 
			
		||||
 | 
			
		||||
            environment.systemPackages = with pkgs; [
 | 
			
		||||
              pciutils
 | 
			
		||||
              partclone
 | 
			
		||||
 
 | 
			
		||||
@@ -55,19 +55,7 @@
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    systemd.services =
 | 
			
		||||
    let
 | 
			
		||||
      awaitCellar = {
 | 
			
		||||
        after = [ "vm@cellar.service" ];
 | 
			
		||||
        bindsTo = [ "vm@cellar.service" ];
 | 
			
		||||
        preStart = ''
 | 
			
		||||
          until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.cellar.hi.ipv4.address} 22; do
 | 
			
		||||
            sleep 1
 | 
			
		||||
          done
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
    in
 | 
			
		||||
    {
 | 
			
		||||
    systemd.services = {
 | 
			
		||||
      "vm@cellar" = {
 | 
			
		||||
        serviceConfig = {
 | 
			
		||||
          CPUAffinity = "numa";
 | 
			
		||||
@@ -75,19 +63,20 @@
 | 
			
		||||
          NUMAMask = "1";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      "vm@river" =
 | 
			
		||||
      let
 | 
			
		||||
        vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
 | 
			
		||||
      in
 | 
			
		||||
      mkMerge [
 | 
			
		||||
        awaitCellar
 | 
			
		||||
        {
 | 
			
		||||
          requires = [ vtapUnit ];
 | 
			
		||||
          after = [ vtapUnit ];
 | 
			
		||||
        }
 | 
			
		||||
      ];
 | 
			
		||||
      "vm@sfh" = awaitCellar;
 | 
			
		||||
      {
 | 
			
		||||
        requires = [ vtapUnit ];
 | 
			
		||||
        after = [ vtapUnit "vm@cellar.service" ];
 | 
			
		||||
        bindsTo = [ "vm@cellar.service" ];
 | 
			
		||||
        preStart = ''
 | 
			
		||||
          until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.cellar.hi.ipv4.address} 22; do
 | 
			
		||||
            sleep 1
 | 
			
		||||
          done
 | 
			
		||||
        '';
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    my = {
 | 
			
		||||
@@ -139,7 +128,7 @@
 | 
			
		||||
              threads = 2;
 | 
			
		||||
            };
 | 
			
		||||
            memory = 4096;
 | 
			
		||||
            cleanShutdown.timeout = 60;
 | 
			
		||||
            cleanShutdown.timeout = 120;
 | 
			
		||||
            networks = {
 | 
			
		||||
              et1g0 = {
 | 
			
		||||
                ifname = "vm-et1g0";
 | 
			
		||||
@@ -161,29 +150,6 @@
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          sfh = {
 | 
			
		||||
            uuid = "82ec149d-577c-421a-93e2-a9307c756cd8";
 | 
			
		||||
            cpu = "host,topoext";
 | 
			
		||||
            smp = {
 | 
			
		||||
              cpus = 8;
 | 
			
		||||
              threads = 2;
 | 
			
		||||
            };
 | 
			
		||||
            memory = 32768;
 | 
			
		||||
            cleanShutdown.timeout = 120;
 | 
			
		||||
            networks.netboot = {
 | 
			
		||||
              bridge = "lan-lo";
 | 
			
		||||
              waitOnline = "carrier";
 | 
			
		||||
              mac = "52:54:00:a5:7e:93";
 | 
			
		||||
              extraOptions.bootindex = 1;
 | 
			
		||||
            };
 | 
			
		||||
            hostDevices = {
 | 
			
		||||
              et100g0vf2 = {
 | 
			
		||||
                index = 0;
 | 
			
		||||
                hostBDF = "44:00.3";
 | 
			
		||||
              };
 | 
			
		||||
            };
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -325,7 +325,6 @@ in
 | 
			
		||||
              ''
 | 
			
		||||
                table inet filter {
 | 
			
		||||
                  chain input {
 | 
			
		||||
                    ${lib.my.c.as211024.nftTrust}
 | 
			
		||||
                    iifname base meta l4proto { udp, tcp } th dport domain accept
 | 
			
		||||
                    iifname lan-core meta l4proto vrrp accept
 | 
			
		||||
                  }
 | 
			
		||||
 
 | 
			
		||||
@@ -2,7 +2,6 @@ index: { lib, pkgs, config, assignments, allAssignments, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) attrNames elemAt;
 | 
			
		||||
  inherit (lib.my) net;
 | 
			
		||||
  inherit (lib.my.c) pubDomain;
 | 
			
		||||
  inherit (lib.my.c.home) prefixes vips routers;
 | 
			
		||||
 | 
			
		||||
  name = elemAt routers index;
 | 
			
		||||
@@ -23,7 +22,6 @@ in
 | 
			
		||||
          owner = "pdns-recursor";
 | 
			
		||||
          group = "pdns-recursor";
 | 
			
		||||
        };
 | 
			
		||||
        "home/ddclient-cloudflare.key" = {};
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      pdns.recursor = {
 | 
			
		||||
@@ -44,7 +42,7 @@ in
 | 
			
		||||
            "127.0.0.0/8" "::1/128"
 | 
			
		||||
            prefixes.hi.v4 prefixes.hi.v6
 | 
			
		||||
            prefixes.lo.v4 prefixes.lo.v6
 | 
			
		||||
          ] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]);
 | 
			
		||||
          ];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        settings = {
 | 
			
		||||
@@ -65,36 +63,9 @@ in
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    systemd = {
 | 
			
		||||
      services = {
 | 
			
		||||
        # Add AF_NETLINK to allow pulling IP from network interfaces
 | 
			
		||||
        pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
 | 
			
		||||
        ddns-update = {
 | 
			
		||||
          description = "DNS update script";
 | 
			
		||||
          after = [ "network.target" ];
 | 
			
		||||
          path = [
 | 
			
		||||
            (pkgs.python3.withPackages (ps: [ ps.cloudflare ]))
 | 
			
		||||
            pkgs.ldns
 | 
			
		||||
          ];
 | 
			
		||||
          serviceConfig = {
 | 
			
		||||
            Type = "oneshot";
 | 
			
		||||
            ExecStart =
 | 
			
		||||
              ''${./dns_update.py} -k ${config.age.secrets."home/ddclient-cloudflare.key".path} '' +
 | 
			
		||||
              ''${pubDomain} ns${toString (index + 1)}.${config.networking.domain}'';
 | 
			
		||||
          };
 | 
			
		||||
          wantedBy = [ "multi-user.target" ];
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      timers = {
 | 
			
		||||
        ddns-update = {
 | 
			
		||||
          description = "Periodically update DNS";
 | 
			
		||||
          wantedBy = [ "timers.target" ];
 | 
			
		||||
          timerConfig = {
 | 
			
		||||
            OnBootSec = "5min";
 | 
			
		||||
            OnUnitInactiveSec = "5min";
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
    systemd.services = {
 | 
			
		||||
      # Add AF_NETLINK to allow pulling IP from network interfaces
 | 
			
		||||
      pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    environment.systemPackages = with pkgs; [
 | 
			
		||||
@@ -182,11 +153,6 @@ in
 | 
			
		||||
            dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
 | 
			
		||||
            dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6}
 | 
			
		||||
 | 
			
		||||
            ;ap0 IN A ${net.cidr.host 12 prefixes.hi.v4}
 | 
			
		||||
            ;ap0 IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
 | 
			
		||||
            vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
 | 
			
		||||
            vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6}
 | 
			
		||||
 | 
			
		||||
            ups IN A ${net.cidr.host 20 prefixes.lo.v4}
 | 
			
		||||
            palace-kvm IN A ${net.cidr.host 21 prefixes.lo.v4}
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,35 +0,0 @@
 | 
			
		||||
#!/usr/bin/env python3
 | 
			
		||||
import argparse
 | 
			
		||||
import subprocess
 | 
			
		||||
 | 
			
		||||
import CloudFlare
 | 
			
		||||
 | 
			
		||||
def main():
 | 
			
		||||
    parser = argparse.ArgumentParser(description='Cloudflare DNS update script')
 | 
			
		||||
    parser.add_argument('-k', '--api-token-file', help='Cloudflare API token file')
 | 
			
		||||
    parser.add_argument('zone', help='Cloudflare Zone')
 | 
			
		||||
    parser.add_argument('record', help='Cloudflare record name')
 | 
			
		||||
    args = parser.parse_args()
 | 
			
		||||
 | 
			
		||||
    address = subprocess.check_output(
 | 
			
		||||
        ['drill', '-Q', '-p5353', '@127.0.0.1', args.record, 'A'],
 | 
			
		||||
        encoding='utf8').strip()
 | 
			
		||||
 | 
			
		||||
    cf_token = None
 | 
			
		||||
    if args.api_token_file:
 | 
			
		||||
        with open(args.api_token_file) as f:
 | 
			
		||||
            cf_token = f.readline().strip()
 | 
			
		||||
 | 
			
		||||
    cf = CloudFlare.CloudFlare(token=cf_token)
 | 
			
		||||
    zones = cf.zones.get(params={'name': args.zone})
 | 
			
		||||
    assert zones, f'Zone {args.zone} not found'
 | 
			
		||||
    records = cf.zones.dns_records.get(zones[0]['id'], params={'name': args.record})
 | 
			
		||||
    assert records, f'Record {args.record} not found in zone {args.zone}'
 | 
			
		||||
 | 
			
		||||
    print(f'Updating {args.record} -> {address}')
 | 
			
		||||
    cf.zones.dns_records.patch(
 | 
			
		||||
        zones[0]['id'], records[0]['id'],
 | 
			
		||||
        data={'type': 'A', 'name': args.record, 'content': address})
 | 
			
		||||
 | 
			
		||||
if __name__ == '__main__':
 | 
			
		||||
    main()
 | 
			
		||||
@@ -55,7 +55,7 @@ in
 | 
			
		||||
            }
 | 
			
		||||
            {
 | 
			
		||||
              name = "domain-search";
 | 
			
		||||
              data = "${domain}, dyn.${domain}, ${lib.my.c.colony.domain}, ${lib.my.c.britway.domain}";
 | 
			
		||||
              data = "${domain}, dyn.${domain}";
 | 
			
		||||
              always-send = true;
 | 
			
		||||
            }
 | 
			
		||||
          ];
 | 
			
		||||
 
 | 
			
		||||
@@ -11,7 +11,7 @@ let
 | 
			
		||||
      AdvLinkMTU ${toString prefixes."${name}".mtu};
 | 
			
		||||
      prefix ${prefixes."${name}".v6} {};
 | 
			
		||||
      RDNSS ${net.cidr.host 1 prefixes."${name}".v6} ${net.cidr.host 2 prefixes."${name}".v6} {};
 | 
			
		||||
      DNSSL ${domain} dyn.${domain} ${lib.my.c.colony.domain} ${lib.my.c.britway.domain} {};
 | 
			
		||||
      DNSSL ${domain} dyn.${domain} {};
 | 
			
		||||
     };
 | 
			
		||||
  '';
 | 
			
		||||
in
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,7 @@ in
 | 
			
		||||
 | 
			
		||||
          nextcloud = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            package = pkgs.nextcloud28;
 | 
			
		||||
            package = pkgs.nextcloud27;
 | 
			
		||||
            datadir = "/mnt/storage/nextcloud";
 | 
			
		||||
            hostName = "cloud.${domain}";
 | 
			
		||||
            https = true;
 | 
			
		||||
 
 | 
			
		||||
@@ -135,14 +135,12 @@ in
 | 
			
		||||
            samba-wsdd.enable = true;
 | 
			
		||||
 | 
			
		||||
            minecraft-server = {
 | 
			
		||||
              enable = false;
 | 
			
		||||
              package = pkgs.minecraftServers.vanilla-1-20;
 | 
			
		||||
              enable = true;
 | 
			
		||||
              package = pkgs.minecraftServers.vanilla-1-19;
 | 
			
		||||
              declarative = true;
 | 
			
		||||
              eula = true;
 | 
			
		||||
              whitelist = {
 | 
			
		||||
                devplayer0 = "6d7d971b-ce10-435b-85c5-c99c0d8d288c";
 | 
			
		||||
                Elderlypug = "dcd2ecb9-2b5e-49cb-9d4f-f5a76162df56";
 | 
			
		||||
                shr3kas0ras = "1d366062-12c0-4e29-aba7-6ab5d8c6bb05";
 | 
			
		||||
              };
 | 
			
		||||
              serverProperties = {
 | 
			
		||||
                motd = "Simpcraft";
 | 
			
		||||
 
 | 
			
		||||
@@ -116,10 +116,6 @@
 | 
			
		||||
 | 
			
		||||
        programs = {
 | 
			
		||||
          steam.enable = true;
 | 
			
		||||
          wireshark = {
 | 
			
		||||
            enable = true;
 | 
			
		||||
            package = pkgs.wireshark-qt;
 | 
			
		||||
          };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        networking = {
 | 
			
		||||
@@ -175,14 +171,6 @@
 | 
			
		||||
                packages = with pkgs; [ ];
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              programs = {
 | 
			
		||||
                fish = {
 | 
			
		||||
                  shellAbbrs = {
 | 
			
		||||
                    tsup = "doas tailscale up --login-server=https://ts.nul.ie --accept-routes";
 | 
			
		||||
                  };
 | 
			
		||||
                };
 | 
			
		||||
              };
 | 
			
		||||
 | 
			
		||||
              services = {
 | 
			
		||||
                blueman-applet.enable = true;
 | 
			
		||||
              };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,4 +1,4 @@
 | 
			
		||||
{ self, lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
 | 
			
		||||
{ lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) attrValues mapAttrs;
 | 
			
		||||
  inherit (lib)
 | 
			
		||||
@@ -25,14 +25,10 @@ let
 | 
			
		||||
 | 
			
		||||
      modules' = [ hmFlakes.${config'.home-manager}.nixosModule ] ++ (attrValues cfg.modules);
 | 
			
		||||
    in
 | 
			
		||||
    # Import eval-config ourselves since the flake now force-sets lib
 | 
			
		||||
    import "${pkgsFlake}/nixos/lib/eval-config.nix" {
 | 
			
		||||
    pkgsFlake.lib.nixosSystem {
 | 
			
		||||
      # Gotta override lib here unforunately, eval-config.nix likes to import its own (unextended) lib. We explicitly
 | 
			
		||||
      # don't pass pkgs so that it'll be imported with modularly applied config and overlays.
 | 
			
		||||
      lib = pkgs.lib.extend (lib.my.versionOverlay { inherit self pkgsFlake; });
 | 
			
		||||
 | 
			
		||||
      # Set to null since we pass modularly
 | 
			
		||||
      system = null;
 | 
			
		||||
      lib = pkgs.lib;
 | 
			
		||||
 | 
			
		||||
      # Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports
 | 
			
		||||
      specialArgs = { inherit inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; };
 | 
			
		||||
@@ -55,7 +51,7 @@ let
 | 
			
		||||
            pkgs' = allPkgs;
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          system = { inherit name; };
 | 
			
		||||
          system.name = name;
 | 
			
		||||
          networking = {
 | 
			
		||||
            domain = let d = config'.assignments.internal.domain or null; in mkIf (d != null) (mkDefault' d);
 | 
			
		||||
            hostName = mkDefault (config'.assignments.internal.name or name);
 | 
			
		||||
@@ -90,8 +86,6 @@ let
 | 
			
		||||
                  pkgsPath = toString pkgsFlakes.${config'.hmNixpkgs};
 | 
			
		||||
                  pkgs' = allPkgs;
 | 
			
		||||
                };
 | 
			
		||||
 | 
			
		||||
                home.enableNixpkgsReleaseCheck = false;
 | 
			
		||||
              }
 | 
			
		||||
              (homeStateVersion config'.home-manager)
 | 
			
		||||
            ];
 | 
			
		||||
 
 | 
			
		||||
@@ -32,8 +32,7 @@
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          isoImage = {
 | 
			
		||||
            isoBaseName = "jackos-installer";
 | 
			
		||||
            volumeID = "jackos-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
 | 
			
		||||
            isoBaseName = "nixos-installer-devplayer0";
 | 
			
		||||
            edition = "devplayer0";
 | 
			
		||||
            appendToMenuLabel = " /dev/player0 Installer";
 | 
			
		||||
          };
 | 
			
		||||
 
 | 
			
		||||
@@ -19,6 +19,5 @@
 | 
			
		||||
    borgthin = ./borgthin.nix;
 | 
			
		||||
    nvme = ./nvme;
 | 
			
		||||
    spdk = ./spdk.nix;
 | 
			
		||||
    librespeed = ./librespeed;
 | 
			
		||||
  };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -92,7 +92,6 @@ in
 | 
			
		||||
    };
 | 
			
		||||
    isoImage = {
 | 
			
		||||
      isoBaseName = dummyOption;
 | 
			
		||||
      volumeID = dummyOption;
 | 
			
		||||
      edition = dummyOption;
 | 
			
		||||
      appendToMenuLabel = dummyOption;
 | 
			
		||||
    };
 | 
			
		||||
 
 | 
			
		||||
@@ -1,7 +1,7 @@
 | 
			
		||||
{ lib, pkgs, pkgs', inputs, config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (lib) mkIf mkDefault mkMerge;
 | 
			
		||||
  inherit (lib.my) mkDefault';
 | 
			
		||||
  inherit (lib.my) mkBoolOpt' dummyOption;
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  options = with lib.types; {
 | 
			
		||||
@@ -121,11 +121,6 @@ in
 | 
			
		||||
          services.lvm.enable = mkDefault true;
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
      system = {
 | 
			
		||||
        nixos = {
 | 
			
		||||
          distroName = mkDefault' "JackOS";
 | 
			
		||||
        };
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      environment.systemPackages = with pkgs; mkMerge [
 | 
			
		||||
        [
 | 
			
		||||
@@ -156,7 +151,6 @@ in
 | 
			
		||||
              font-name=SauceCodePro Nerd Font Mono
 | 
			
		||||
            '';
 | 
			
		||||
        };
 | 
			
		||||
        getty.greetingLine = mkDefault' ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>'';
 | 
			
		||||
 | 
			
		||||
        openssh = {
 | 
			
		||||
          enable = mkDefault true;
 | 
			
		||||
 
 | 
			
		||||
@@ -15,20 +15,16 @@ let
 | 
			
		||||
  # Based on https://github.com/serokell/deploy-rs/blob/master/flake.nix
 | 
			
		||||
  nixosActivate = cfg': base: (pkgs.deploy-rs.lib.activate.custom // {
 | 
			
		||||
    dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate";
 | 
			
		||||
    boot = ''
 | 
			
		||||
      $PROFILE/bin/switch-to-configuration boot
 | 
			
		||||
 | 
			
		||||
      ${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
 | 
			
		||||
    '';
 | 
			
		||||
    boot = "$PROFILE/bin/switch-to-configuration boot";
 | 
			
		||||
  }) base.config.system.build.toplevel ''
 | 
			
		||||
    # work around https://github.com/NixOS/nixpkgs/issues/73404
 | 
			
		||||
    cd /tmp
 | 
			
		||||
 | 
			
		||||
    "$PROFILE"/bin/switch-to-configuration switch
 | 
			
		||||
    "$PROFILE"/bin/switch-to-configuration ${cfg'.mode}
 | 
			
		||||
 | 
			
		||||
    # https://github.com/serokell/deploy-rs/issues/31
 | 
			
		||||
    ${with base.config.boot.loader;
 | 
			
		||||
    optionalString systemd-boot.enable
 | 
			
		||||
    optionalString ((cfg'.mode == "switch" || cfg'.mode == "boot") && systemd-boot.enable)
 | 
			
		||||
    "sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"}
 | 
			
		||||
 | 
			
		||||
    ${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
 | 
			
		||||
@@ -63,11 +59,7 @@ let
 | 
			
		||||
  {
 | 
			
		||||
    name = "container-${n}";
 | 
			
		||||
    value = {
 | 
			
		||||
      path = (pkgs.deploy-rs.lib.activate.custom // {
 | 
			
		||||
        boot = ''
 | 
			
		||||
          echo "Next systemd-nspawn@${n}.service restart / reload will load config"
 | 
			
		||||
        '';
 | 
			
		||||
      }) ctrConfig.my.buildAs.container ''
 | 
			
		||||
      path = pkgs.deploy-rs.lib.activate.custom ctrConfig.my.buildAs.container ''
 | 
			
		||||
        source ${systemdUtil}/bin/systemd-util.sh
 | 
			
		||||
        ${if c.hotReload then ''
 | 
			
		||||
          if (! systemctl show -p ActiveState systemd-nspawn@${n} | grep -q "ActiveState=active") || \
 | 
			
		||||
 
 | 
			
		||||
@@ -222,7 +222,7 @@ in
 | 
			
		||||
                "iifname ${cfg.nat.externalInterface} jump filter-iif-port-forwards"}
 | 
			
		||||
              ${optionalString
 | 
			
		||||
                dipForward
 | 
			
		||||
                (concatMapStringsSep "\n    " (ip: "jump ${natFilterChain ip}") (attrNames cfg.nat.forwardPorts))}
 | 
			
		||||
                (concatMapStringsSep "\n    " (ip: "${ipK ip} daddr ${ip} jump ${natFilterChain ip}") (attrNames cfg.nat.forwardPorts))}
 | 
			
		||||
            }
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -1,76 +0,0 @@
 | 
			
		||||
{ lib, pkgs, config, ... }:
 | 
			
		||||
let
 | 
			
		||||
  inherit (builtins) toJSON;
 | 
			
		||||
  inherit (lib) mkOption mkMerge mkIf mkDefault;
 | 
			
		||||
  inherit (lib.my) mkOpt' mkBoolOpt';
 | 
			
		||||
 | 
			
		||||
  cfg = config.my.librespeed;
 | 
			
		||||
 | 
			
		||||
  serversConf = map (s: s // {
 | 
			
		||||
    dlURL = "backend/garbage";
 | 
			
		||||
    ulURL = "backend/empty";
 | 
			
		||||
    pingURL = "backend/empty";
 | 
			
		||||
    getIpURL = "backend/getIP";
 | 
			
		||||
  }) cfg.frontend.servers;
 | 
			
		||||
  frontendTree = pkgs.runCommand "librespeed-frontend" {
 | 
			
		||||
    speedtestServers = toJSON serversConf;
 | 
			
		||||
  } ''
 | 
			
		||||
    mkdir "$out"
 | 
			
		||||
    cp "${pkgs.librespeed-go}"/assets/* "$out"/
 | 
			
		||||
    substitute ${./index.html} "$out"/index.html --subst-var speedtestServers
 | 
			
		||||
  '';
 | 
			
		||||
 | 
			
		||||
  backendConf = pkgs.writers.writeTOML "librespeed.toml" cfg.backend.settings;
 | 
			
		||||
  generateBackendSettings = base: dst: if (cfg.backend.extraSettingsFile != null) then ''
 | 
			
		||||
    oldUmask="$(umask)"
 | 
			
		||||
    umask 006
 | 
			
		||||
    cat "${base}" "${cfg.backend.extraSettingsFile}" > "${dst}"
 | 
			
		||||
    umask "$oldUmask"
 | 
			
		||||
  '' else ''
 | 
			
		||||
    cp "${base}" "${dst}"
 | 
			
		||||
  '';
 | 
			
		||||
in
 | 
			
		||||
{
 | 
			
		||||
  options.my.librespeed = with lib.types; {
 | 
			
		||||
    frontend = {
 | 
			
		||||
      servers = mkOpt' (listOf (attrsOf unspecified)) { } "Server configs.";
 | 
			
		||||
      webroot = mkOption {
 | 
			
		||||
        description = "Frontend webroot.";
 | 
			
		||||
        type = package;
 | 
			
		||||
        readOnly = true;
 | 
			
		||||
      };
 | 
			
		||||
    };
 | 
			
		||||
    backend = {
 | 
			
		||||
      enable = mkBoolOpt' false "Whether to enable librespeed backend.";
 | 
			
		||||
      settings = mkOpt' (attrsOf unspecified) { } "Backend settings.";
 | 
			
		||||
      extraSettingsFile = mkOpt' (nullOr str) null "Extra settings file.";
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  config = mkMerge [
 | 
			
		||||
    (mkIf (cfg.frontend.servers != { }) {
 | 
			
		||||
      my.librespeed.frontend.webroot = frontendTree;
 | 
			
		||||
    })
 | 
			
		||||
    (mkIf cfg.backend.enable {
 | 
			
		||||
      my.librespeed.backend.settings = {
 | 
			
		||||
        assets_path = frontendTree;
 | 
			
		||||
        database_type = mkDefault "bolt";
 | 
			
		||||
        database_file = mkDefault "/var/lib/librespeed-go/speedtest.db";
 | 
			
		||||
      };
 | 
			
		||||
 | 
			
		||||
      systemd.services.librespeed = {
 | 
			
		||||
        description = "LibreSpeed Go backend";
 | 
			
		||||
        wants = [ "network-online.target" ];
 | 
			
		||||
        after = [ "network-online.target" ];
 | 
			
		||||
 | 
			
		||||
        preStart = generateBackendSettings backendConf "/run/librespeed-go/settings.toml";
 | 
			
		||||
        serviceConfig = {
 | 
			
		||||
          ExecStart = "${pkgs.librespeed-go}/bin/speedtest -c /run/librespeed-go/settings.toml";
 | 
			
		||||
          RuntimeDirectory = "librespeed-go";
 | 
			
		||||
          StateDirectory = "librespeed-go";
 | 
			
		||||
        };
 | 
			
		||||
        wantedBy = [ "multi-user.target" ];
 | 
			
		||||
      };
 | 
			
		||||
    })
 | 
			
		||||
  ];
 | 
			
		||||
}
 | 
			
		||||
@@ -1,491 +0,0 @@
 | 
			
		||||
<!DOCTYPE html>
 | 
			
		||||
<html>
 | 
			
		||||
<head>
 | 
			
		||||
<link rel="shortcut icon" href="favicon.ico">
 | 
			
		||||
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
 | 
			
		||||
<meta charset="UTF-8" />
 | 
			
		||||
<script type="text/javascript" src="speedtest.js"></script>
 | 
			
		||||
<script type="text/javascript">
 | 
			
		||||
function I(i){return document.getElementById(i);}
 | 
			
		||||
 | 
			
		||||
//LIST OF TEST SERVERS. See documentation for details if needed
 | 
			
		||||
var SPEEDTEST_SERVERS=@speedtestServers@;
 | 
			
		||||
// var SPEEDTEST_SERVERS=[
 | 
			
		||||
// 	{	//this server doesn't actually exist, remove it
 | 
			
		||||
// 		name:"Example Server 1", //user friendly name for the server
 | 
			
		||||
// 		server:"//test1.mydomain.com/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
 | 
			
		||||
// 		dlURL:"backend/garbage.php",  //path to download test on this server (garbage.php or replacement)
 | 
			
		||||
// 		ulURL:"backend/empty.php",  //path to upload test on this server (empty.php or replacement)
 | 
			
		||||
// 		pingURL:"backend/empty.php",  //path to ping/jitter test on this server (empty.php or replacement)
 | 
			
		||||
// 		getIpURL:"backend/getIP.php"  //path to getIP on this server (getIP.php or replacement)
 | 
			
		||||
// 	},
 | 
			
		||||
// 	{	//this server doesn't actually exist, remove it
 | 
			
		||||
// 		name:"Example Server 2", //user friendly name for the server
 | 
			
		||||
// 		server:"//test2.example.com/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
 | 
			
		||||
// 		dlURL:"garbage.php",  //path to download test on this server (garbage.php or replacement)
 | 
			
		||||
// 		ulURL:"empty.php",  //path to upload test on this server (empty.php or replacement)
 | 
			
		||||
// 		pingURL:"empty.php",  //path to ping/jitter test on this server (empty.php or replacement)
 | 
			
		||||
// 		getIpURL:"getIP.php"  //path to getIP on this server (getIP.php or replacement)
 | 
			
		||||
// 	}
 | 
			
		||||
// 	//add other servers here, comma separated
 | 
			
		||||
// ];
 | 
			
		||||
 | 
			
		||||
//INITIALIZE SPEEDTEST
 | 
			
		||||
var s=new Speedtest(); //create speed test object
 | 
			
		||||
s.setParameter("telemetry_level","basic"); //enable telemetry
 | 
			
		||||
 | 
			
		||||
//SERVER AUTO SELECTION
 | 
			
		||||
function initServers(){
 | 
			
		||||
    var noServersAvailable=function(){
 | 
			
		||||
        I("message").innerHTML="No servers available";
 | 
			
		||||
    }
 | 
			
		||||
    var runServerSelect=function(){
 | 
			
		||||
        s.selectServer(function(server){
 | 
			
		||||
            if(server!=null){ //at least 1 server is available
 | 
			
		||||
                I("loading").className="hidden"; //hide loading message
 | 
			
		||||
                //populate server list for manual selection
 | 
			
		||||
                for(var i=0;i<SPEEDTEST_SERVERS.length;i++){
 | 
			
		||||
                    if(SPEEDTEST_SERVERS[i].pingT==-1) continue;
 | 
			
		||||
                    var option=document.createElement("option");
 | 
			
		||||
                    option.value=i;
 | 
			
		||||
                    option.textContent=SPEEDTEST_SERVERS[i].name;
 | 
			
		||||
                    if(SPEEDTEST_SERVERS[i]===server) option.selected=true;
 | 
			
		||||
                    I("server").appendChild(option);
 | 
			
		||||
                }
 | 
			
		||||
                //show test UI
 | 
			
		||||
                I("testWrapper").className="visible";
 | 
			
		||||
                initUI();
 | 
			
		||||
            }else{ //no servers are available, the test cannot proceed
 | 
			
		||||
                noServersAvailable();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
    if(typeof SPEEDTEST_SERVERS === "string"){
 | 
			
		||||
        //need to fetch list of servers from specified URL
 | 
			
		||||
        s.loadServerList(SPEEDTEST_SERVERS,function(servers){
 | 
			
		||||
            if(servers==null){ //failed to load server list
 | 
			
		||||
                noServersAvailable();
 | 
			
		||||
            }else{ //server list loaded
 | 
			
		||||
                SPEEDTEST_SERVERS=servers;
 | 
			
		||||
                runServerSelect();
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
    }else{
 | 
			
		||||
        //hardcoded server list
 | 
			
		||||
        s.addTestPoints(SPEEDTEST_SERVERS);
 | 
			
		||||
        runServerSelect();
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var meterBk=/Trident.*rv:(\d+\.\d+)/i.test(navigator.userAgent)?"#EAEAEA":"#80808040";
 | 
			
		||||
var dlColor="#6060AA",
 | 
			
		||||
	ulColor="#616161";
 | 
			
		||||
var progColor=meterBk;
 | 
			
		||||
 | 
			
		||||
//CODE FOR GAUGES
 | 
			
		||||
function drawMeter(c,amount,bk,fg,progress,prog){
 | 
			
		||||
	var ctx=c.getContext("2d");
 | 
			
		||||
	var dp=window.devicePixelRatio||1;
 | 
			
		||||
	var cw=c.clientWidth*dp, ch=c.clientHeight*dp;
 | 
			
		||||
	var sizScale=ch*0.0055;
 | 
			
		||||
	if(c.width==cw&&c.height==ch){
 | 
			
		||||
		ctx.clearRect(0,0,cw,ch);
 | 
			
		||||
	}else{
 | 
			
		||||
		c.width=cw;
 | 
			
		||||
		c.height=ch;
 | 
			
		||||
	}
 | 
			
		||||
	ctx.beginPath();
 | 
			
		||||
	ctx.strokeStyle=bk;
 | 
			
		||||
	ctx.lineWidth=12*sizScale;
 | 
			
		||||
	ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,Math.PI*0.1);
 | 
			
		||||
	ctx.stroke();
 | 
			
		||||
	ctx.beginPath();
 | 
			
		||||
	ctx.strokeStyle=fg;
 | 
			
		||||
	ctx.lineWidth=12*sizScale;
 | 
			
		||||
	ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,amount*Math.PI*1.2-Math.PI*1.1);
 | 
			
		||||
	ctx.stroke();
 | 
			
		||||
	if(typeof progress !== "undefined"){
 | 
			
		||||
		ctx.fillStyle=prog;
 | 
			
		||||
		ctx.fillRect(c.width*0.3,c.height-16*sizScale,c.width*0.4*progress,4*sizScale);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
function mbpsToAmount(s){
 | 
			
		||||
	return 1-(1/(Math.pow(1.3,Math.sqrt(s))));
 | 
			
		||||
}
 | 
			
		||||
function format(d){
 | 
			
		||||
    d=Number(d);
 | 
			
		||||
    if(d<10) return d.toFixed(2);
 | 
			
		||||
    if(d<100) return d.toFixed(1);
 | 
			
		||||
    return d.toFixed(0);
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
//UI CODE
 | 
			
		||||
var uiData=null;
 | 
			
		||||
function startStop(){
 | 
			
		||||
    if(s.getState()==3){
 | 
			
		||||
		//speed test is running, abort
 | 
			
		||||
		s.abort();
 | 
			
		||||
		data=null;
 | 
			
		||||
		I("startStopBtn").className="";
 | 
			
		||||
		I("server").disabled=false;
 | 
			
		||||
		initUI();
 | 
			
		||||
	}else{
 | 
			
		||||
		//test is not running, begin
 | 
			
		||||
		I("startStopBtn").className="running";
 | 
			
		||||
		I("shareArea").style.display="none";
 | 
			
		||||
		I("server").disabled=true;
 | 
			
		||||
		s.onupdate=function(data){
 | 
			
		||||
            uiData=data;
 | 
			
		||||
		};
 | 
			
		||||
		s.onend=function(aborted){
 | 
			
		||||
            I("startStopBtn").className="";
 | 
			
		||||
            I("server").disabled=false;
 | 
			
		||||
            updateUI(true);
 | 
			
		||||
            if(!aborted){
 | 
			
		||||
                //if testId is present, show sharing panel, otherwise do nothing
 | 
			
		||||
                try{
 | 
			
		||||
                    var testId=uiData.testId;
 | 
			
		||||
                    if(testId!=null){
 | 
			
		||||
                        var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
 | 
			
		||||
                        I("resultsImg").src=shareURL;
 | 
			
		||||
                        I("resultsURL").value=shareURL;
 | 
			
		||||
                        I("testId").innerHTML=testId;
 | 
			
		||||
                        I("shareArea").style.display="";
 | 
			
		||||
                    }
 | 
			
		||||
                }catch(e){}
 | 
			
		||||
            }
 | 
			
		||||
		};
 | 
			
		||||
		s.start();
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
//this function reads the data sent back by the test and updates the UI
 | 
			
		||||
function updateUI(forced){
 | 
			
		||||
	if(!forced&&s.getState()!=3) return;
 | 
			
		||||
	if(uiData==null) return;
 | 
			
		||||
	var status=uiData.testState;
 | 
			
		||||
	I("ip").textContent=uiData.clientIp;
 | 
			
		||||
	I("dlText").textContent=(status==1&&uiData.dlStatus==0)?"...":format(uiData.dlStatus);
 | 
			
		||||
	drawMeter(I("dlMeter"),mbpsToAmount(Number(uiData.dlStatus*(status==1?oscillate():1))),meterBk,dlColor,Number(uiData.dlProgress),progColor);
 | 
			
		||||
	I("ulText").textContent=(status==3&&uiData.ulStatus==0)?"...":format(uiData.ulStatus);
 | 
			
		||||
	drawMeter(I("ulMeter"),mbpsToAmount(Number(uiData.ulStatus*(status==3?oscillate():1))),meterBk,ulColor,Number(uiData.ulProgress),progColor);
 | 
			
		||||
	I("pingText").textContent=format(uiData.pingStatus);
 | 
			
		||||
	I("jitText").textContent=format(uiData.jitterStatus);
 | 
			
		||||
}
 | 
			
		||||
function oscillate(){
 | 
			
		||||
	return 1+0.02*Math.sin(Date.now()/100);
 | 
			
		||||
}
 | 
			
		||||
//update the UI every frame
 | 
			
		||||
window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||(function(callback,element){setTimeout(callback,1000/60);});
 | 
			
		||||
function frame(){
 | 
			
		||||
	requestAnimationFrame(frame);
 | 
			
		||||
	updateUI();
 | 
			
		||||
}
 | 
			
		||||
frame(); //start frame loop
 | 
			
		||||
//function to (re)initialize UI
 | 
			
		||||
function initUI(){
 | 
			
		||||
	drawMeter(I("dlMeter"),0,meterBk,dlColor,0);
 | 
			
		||||
	drawMeter(I("ulMeter"),0,meterBk,ulColor,0);
 | 
			
		||||
	I("dlText").textContent="";
 | 
			
		||||
	I("ulText").textContent="";
 | 
			
		||||
	I("pingText").textContent="";
 | 
			
		||||
	I("jitText").textContent="";
 | 
			
		||||
	I("ip").textContent="";
 | 
			
		||||
}
 | 
			
		||||
</script>
 | 
			
		||||
<style type="text/css">
 | 
			
		||||
	html,body{
 | 
			
		||||
		border:none; padding:0; margin:0;
 | 
			
		||||
		background:#FFFFFF;
 | 
			
		||||
		color:#202020;
 | 
			
		||||
	}
 | 
			
		||||
	body{
 | 
			
		||||
		text-align:center;
 | 
			
		||||
		font-family:"Roboto",sans-serif;
 | 
			
		||||
	}
 | 
			
		||||
	h1{
 | 
			
		||||
		color:#404040;
 | 
			
		||||
	}
 | 
			
		||||
	#loading{
 | 
			
		||||
		background-color:#FFFFFF;
 | 
			
		||||
		color:#404040;
 | 
			
		||||
		text-align:center;
 | 
			
		||||
	}
 | 
			
		||||
	span.loadCircle{
 | 
			
		||||
		display:inline-block;
 | 
			
		||||
		width:2em;
 | 
			
		||||
		height:2em;
 | 
			
		||||
		vertical-align:middle;
 | 
			
		||||
		background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAP1BMVEUAAAB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZyFzwnAAAAFHRSTlMAEvRFvX406baecwbf0casimhSHyiwmqgAAADpSURBVHja7dbJbQMxAENRahnN5lkc//5rDRAkDeRgHszXgACJoKiIiIiIiIiIiIiIiIiIiIj4HHspsrpAVhdVVguzrA4OWc10WcEqpwKbnBo0OU1Q5NSpsoJFTgOecrrdEag85DRgktNqfoEdTjnd7hrEHMEJvmRUYJbTYk5Agy6nau6Abp5Cm7mDBtRdPi9gyKdU7w4p1fsLvyqs8hl4z9/w3n/Hmr9WoQ65lAU4d7lMYOz//QboRR5jBZibLMZdAR6O/Vfa1PlxNr3XdS3HzK/HVPRu/KnLs8iAOh993VpRRERERMT/fAN60wwWaVyWwAAAAABJRU5ErkJggg==');
 | 
			
		||||
		background-size:2em 2em;
 | 
			
		||||
		margin-right:0.5em;
 | 
			
		||||
		animation: spin 0.6s linear infinite;
 | 
			
		||||
	}
 | 
			
		||||
	@keyframes spin{
 | 
			
		||||
		0%{transform:rotate(0deg);}
 | 
			
		||||
		100%{transform:rotate(359deg);}
 | 
			
		||||
	}
 | 
			
		||||
	#startStopBtn{
 | 
			
		||||
		display:inline-block;
 | 
			
		||||
		margin:0 auto;
 | 
			
		||||
		color:#6060AA;
 | 
			
		||||
		background-color:rgba(0,0,0,0);
 | 
			
		||||
		border:0.15em solid #6060FF;
 | 
			
		||||
		border-radius:0.3em;
 | 
			
		||||
		transition:all 0.3s;
 | 
			
		||||
		box-sizing:border-box;
 | 
			
		||||
		width:8em; height:3em;
 | 
			
		||||
		line-height:2.7em;
 | 
			
		||||
		cursor:pointer;
 | 
			
		||||
		box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
 | 
			
		||||
	}
 | 
			
		||||
	#startStopBtn:hover{
 | 
			
		||||
		box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
 | 
			
		||||
	}
 | 
			
		||||
	#startStopBtn.running{
 | 
			
		||||
		background-color:#FF3030;
 | 
			
		||||
		border-color:#FF6060;
 | 
			
		||||
		color:#FFFFFF;
 | 
			
		||||
	}
 | 
			
		||||
	#startStopBtn:before{
 | 
			
		||||
		content:"Start";
 | 
			
		||||
	}
 | 
			
		||||
	#startStopBtn.running:before{
 | 
			
		||||
		content:"Abort";
 | 
			
		||||
	}
 | 
			
		||||
	#serverArea{
 | 
			
		||||
		margin-top:1em;
 | 
			
		||||
	}
 | 
			
		||||
	#server{
 | 
			
		||||
		font-size:1em;
 | 
			
		||||
		padding:0.2em;
 | 
			
		||||
	}
 | 
			
		||||
	#test{
 | 
			
		||||
		margin-top:2em;
 | 
			
		||||
		margin-bottom:12em;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea{
 | 
			
		||||
		display:inline-block;
 | 
			
		||||
		width:16em;
 | 
			
		||||
		height:12.5em;
 | 
			
		||||
		position:relative;
 | 
			
		||||
		box-sizing:border-box;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea2{
 | 
			
		||||
		display:inline-block;
 | 
			
		||||
		width:14em;
 | 
			
		||||
		height:7em;
 | 
			
		||||
		position:relative;
 | 
			
		||||
		box-sizing:border-box;
 | 
			
		||||
		text-align:center;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea div.testName{
 | 
			
		||||
		position:absolute;
 | 
			
		||||
		top:0.1em; left:0;
 | 
			
		||||
		width:100%;
 | 
			
		||||
		font-size:1.4em;
 | 
			
		||||
		z-index:9;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea2 div.testName{
 | 
			
		||||
        display:block;
 | 
			
		||||
        text-align:center;
 | 
			
		||||
        font-size:1.4em;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea div.meterText{
 | 
			
		||||
		position:absolute;
 | 
			
		||||
		bottom:1.55em; left:0;
 | 
			
		||||
		width:100%;
 | 
			
		||||
		font-size:2.5em;
 | 
			
		||||
		z-index:9;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea2 div.meterText{
 | 
			
		||||
        display:inline-block;
 | 
			
		||||
        font-size:2.5em;
 | 
			
		||||
	}
 | 
			
		||||
	div.meterText:empty:before{
 | 
			
		||||
		content:"0.00";
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea div.unit{
 | 
			
		||||
		position:absolute;
 | 
			
		||||
		bottom:2em; left:0;
 | 
			
		||||
		width:100%;
 | 
			
		||||
		z-index:9;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea2 div.unit{
 | 
			
		||||
		display:inline-block;
 | 
			
		||||
	}
 | 
			
		||||
	div.testArea canvas{
 | 
			
		||||
		position:absolute;
 | 
			
		||||
		top:0; left:0; width:100%; height:100%;
 | 
			
		||||
		z-index:1;
 | 
			
		||||
	}
 | 
			
		||||
	div.testGroup{
 | 
			
		||||
		display:block;
 | 
			
		||||
        margin: 0 auto;
 | 
			
		||||
	}
 | 
			
		||||
	#shareArea{
 | 
			
		||||
		width:95%;
 | 
			
		||||
		max-width:40em;
 | 
			
		||||
		margin:0 auto;
 | 
			
		||||
		margin-top:2em;
 | 
			
		||||
	}
 | 
			
		||||
	#shareArea > *{
 | 
			
		||||
		display:block;
 | 
			
		||||
		width:100%;
 | 
			
		||||
		height:auto;
 | 
			
		||||
		margin: 0.25em 0;
 | 
			
		||||
	}
 | 
			
		||||
	#privacyPolicy{
 | 
			
		||||
        position:fixed;
 | 
			
		||||
        top:2em;
 | 
			
		||||
        bottom:2em;
 | 
			
		||||
        left:2em;
 | 
			
		||||
        right:2em;
 | 
			
		||||
        overflow-y:auto;
 | 
			
		||||
        width:auto;
 | 
			
		||||
        height:auto;
 | 
			
		||||
        box-shadow:0 0 3em 1em #000000;
 | 
			
		||||
        z-index:999999;
 | 
			
		||||
        text-align:left;
 | 
			
		||||
        background-color:#FFFFFF;
 | 
			
		||||
        padding:1em;
 | 
			
		||||
	}
 | 
			
		||||
	a.privacy{
 | 
			
		||||
        text-align:center;
 | 
			
		||||
        font-size:0.8em;
 | 
			
		||||
        color:#808080;
 | 
			
		||||
        padding: 0 3em;
 | 
			
		||||
	}
 | 
			
		||||
    div.closePrivacyPolicy {
 | 
			
		||||
        width: 100%;
 | 
			
		||||
        text-align: center;
 | 
			
		||||
    }
 | 
			
		||||
    div.closePrivacyPolicy a.privacy {
 | 
			
		||||
        padding: 1em 3em;
 | 
			
		||||
    }
 | 
			
		||||
	@media all and (max-width:40em){
 | 
			
		||||
		body{
 | 
			
		||||
			font-size:0.8em;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	div.visible{
 | 
			
		||||
		animation: fadeIn 0.4s;
 | 
			
		||||
		display:block;
 | 
			
		||||
	}
 | 
			
		||||
	div.hidden{
 | 
			
		||||
		animation: fadeOut 0.4s;
 | 
			
		||||
		display:none;
 | 
			
		||||
	}
 | 
			
		||||
	@keyframes fadeIn{
 | 
			
		||||
		0%{
 | 
			
		||||
			opacity:0;
 | 
			
		||||
		}
 | 
			
		||||
		100%{
 | 
			
		||||
			opacity:1;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	@keyframes fadeOut{
 | 
			
		||||
		0%{
 | 
			
		||||
			display:block;
 | 
			
		||||
			opacity:1;
 | 
			
		||||
		}
 | 
			
		||||
		100%{
 | 
			
		||||
			display:block;
 | 
			
		||||
			opacity:0;
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
</style>
 | 
			
		||||
<title>/dev/player0's speedtest</title>
 | 
			
		||||
</head>
 | 
			
		||||
<body onload="initServers()">
 | 
			
		||||
<h1>/dev/player0's speedtest</h1>
 | 
			
		||||
<div id="loading" class="visible">
 | 
			
		||||
	<p id="message"><span class="loadCircle"></span>Selecting a server...</p>
 | 
			
		||||
</div>
 | 
			
		||||
<div id="testWrapper" class="hidden">
 | 
			
		||||
	<div id="startStopBtn" onclick="startStop()"></div><br/>
 | 
			
		||||
	<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
 | 
			
		||||
	<div id="serverArea">
 | 
			
		||||
		Server: <select id="server" onchange="s.setSelectedServer(SPEEDTEST_SERVERS[this.value])"></select>
 | 
			
		||||
	</div>
 | 
			
		||||
	<div id="test">
 | 
			
		||||
		<div class="testGroup">
 | 
			
		||||
            <div class="testArea2">
 | 
			
		||||
				<div class="testName">Ping</div>
 | 
			
		||||
				<div id="pingText" class="meterText" style="color:#AA6060"></div>
 | 
			
		||||
				<div class="unit">ms</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="testArea2">
 | 
			
		||||
				<div class="testName">Jitter</div>
 | 
			
		||||
				<div id="jitText" class="meterText" style="color:#AA6060"></div>
 | 
			
		||||
				<div class="unit">ms</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div class="testGroup">
 | 
			
		||||
			<div class="testArea">
 | 
			
		||||
				<div class="testName">Download</div>
 | 
			
		||||
				<canvas id="dlMeter" class="meter"></canvas>
 | 
			
		||||
				<div id="dlText" class="meterText"></div>
 | 
			
		||||
				<div class="unit">Mbit/s</div>
 | 
			
		||||
			</div>
 | 
			
		||||
			<div class="testArea">
 | 
			
		||||
				<div class="testName">Upload</div>
 | 
			
		||||
				<canvas id="ulMeter" class="meter"></canvas>
 | 
			
		||||
				<div id="ulText" class="meterText"></div>
 | 
			
		||||
				<div class="unit">Mbit/s</div>
 | 
			
		||||
			</div>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div id="ipArea">
 | 
			
		||||
			<span id="ip"></span>
 | 
			
		||||
		</div>
 | 
			
		||||
		<div id="shareArea" style="display:none">
 | 
			
		||||
			<h3>Share results</h3>
 | 
			
		||||
			<p>Test ID: <span id="testId"></span></p>
 | 
			
		||||
			<input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
 | 
			
		||||
			<img src="" id="resultsImg" />
 | 
			
		||||
		</div>
 | 
			
		||||
	</div>
 | 
			
		||||
	<a href="https://github.com/librespeed/speedtest">Source code</a>
 | 
			
		||||
</div>
 | 
			
		||||
<div id="privacyPolicy" style="display:none">
 | 
			
		||||
    <h2>Privacy Policy</h2>
 | 
			
		||||
    <p>This HTML5 speed test server is configured with telemetry enabled.</p>
 | 
			
		||||
    <h4>What data we collect</h4>
 | 
			
		||||
    <p>
 | 
			
		||||
        At the end of the test, the following data is collected and stored:
 | 
			
		||||
        <ul>
 | 
			
		||||
            <li>Test ID</li>
 | 
			
		||||
            <li>Time of testing</li>
 | 
			
		||||
            <li>Test results (download and upload speed, ping and jitter)</li>
 | 
			
		||||
            <li>IP address</li>
 | 
			
		||||
            <li>ISP information</li>
 | 
			
		||||
            <li>Approximate location (inferred from IP address, not GPS)</li>
 | 
			
		||||
            <li>User agent and browser locale</li>
 | 
			
		||||
            <li>Test log (contains no personal information)</li>
 | 
			
		||||
        </ul>
 | 
			
		||||
    </p>
 | 
			
		||||
    <h4>How we use the data</h4>
 | 
			
		||||
    <p>
 | 
			
		||||
        Data collected through this service is used to:
 | 
			
		||||
        <ul>
 | 
			
		||||
            <li>Allow sharing of test results (sharable image for forums, etc.)</li>
 | 
			
		||||
            <li>To improve the service offered to you (for instance, to detect problems on our side)</li>
 | 
			
		||||
        </ul>
 | 
			
		||||
        No personal information is disclosed to third parties.
 | 
			
		||||
    </p>
 | 
			
		||||
    <h4>Your consent</h4>
 | 
			
		||||
    <p>
 | 
			
		||||
        By starting the test, you consent to the terms of this privacy policy.
 | 
			
		||||
    </p>
 | 
			
		||||
    <h4>Data removal</h4>
 | 
			
		||||
    <p>
 | 
			
		||||
        If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.<br/><br/>
 | 
			
		||||
        Contact this email address for all deletion requests: <a href="mailto:dev@nul.ie">dev@nul.ie</a>.
 | 
			
		||||
    </p>
 | 
			
		||||
    <br/><br/>
 | 
			
		||||
    <div class="closePrivacyPolicy">
 | 
			
		||||
        <a class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a>
 | 
			
		||||
    </div>
 | 
			
		||||
    <br/>
 | 
			
		||||
</div>
 | 
			
		||||
</body>
 | 
			
		||||
</html>
 | 
			
		||||
@@ -480,18 +480,6 @@ in
 | 
			
		||||
      (mkIf config.services.tailscale.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [ "/var/lib/tailscale" ];
 | 
			
		||||
      })
 | 
			
		||||
      (mkIf config.my.librespeed.backend.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [ "/var/lib/librespeed-go" ];
 | 
			
		||||
      })
 | 
			
		||||
      (mkIf config.services.hedgedoc.enable {
 | 
			
		||||
        my.tmproot.persistence.config.directories = [
 | 
			
		||||
          {
 | 
			
		||||
            directory = "/var/lib/hedgedoc";
 | 
			
		||||
            user = "hedgedoc";
 | 
			
		||||
            group = "hedgedoc";
 | 
			
		||||
          }
 | 
			
		||||
        ];
 | 
			
		||||
      })
 | 
			
		||||
    ]))
 | 
			
		||||
  ]);
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -116,7 +116,7 @@ let
 | 
			
		||||
        });
 | 
			
		||||
        default = { };
 | 
			
		||||
      };
 | 
			
		||||
      drives = mkOpt' (listOf (submodule driveOpts)) [ ] "Drives to attach to VM.";
 | 
			
		||||
      drives = mkOpt' (listOf (submodule driveOpts)) { } "Drives to attach to VM.";
 | 
			
		||||
      hostDevices = mkOpt' (attrsOf (submodule hostDevOpts)) { } "Host PCI devices to pass to the VM.";
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
@@ -126,8 +126,8 @@ let
 | 
			
		||||
      (map
 | 
			
		||||
        (i: mapAttrsToList (name: c: c // { inherit name; }) i.hostDevices)
 | 
			
		||||
        (attrValues cfg.instances));
 | 
			
		||||
  anyVfioDevs = any (d: d.bindVFIO);
 | 
			
		||||
  vfioHostDevs = filter (d: d.bindVFIO);
 | 
			
		||||
  anyVfioDevs = any (d: d.bindVFIO) allHostDevs;
 | 
			
		||||
  vfioHostDevs = filter (d: d.bindVFIO) allHostDevs;
 | 
			
		||||
 | 
			
		||||
  mkQemuScript = n: i:
 | 
			
		||||
  let
 | 
			
		||||
@@ -204,7 +204,7 @@ in
 | 
			
		||||
    services.udev = {
 | 
			
		||||
      packages =
 | 
			
		||||
        optionals
 | 
			
		||||
          (anyVfioDevs allHostDevs)
 | 
			
		||||
          anyVfioDevs
 | 
			
		||||
          [
 | 
			
		||||
            pkgs.vfio-pci-bind
 | 
			
		||||
            (pkgs.writeTextDir
 | 
			
		||||
@@ -212,7 +212,7 @@ in
 | 
			
		||||
              (concatMapStringsSep
 | 
			
		||||
                "\n"
 | 
			
		||||
                (d: ''ACTION=="add", SUBSYSTEM=="pci", KERNEL=="0000:${d.hostBDF}", TAG="vfio-pci-bind"'')
 | 
			
		||||
                (vfioHostDevs allHostDevs)))
 | 
			
		||||
                vfioHostDevs))
 | 
			
		||||
          ];
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
@@ -261,15 +261,12 @@ in
 | 
			
		||||
          };
 | 
			
		||||
 | 
			
		||||
          preStart =
 | 
			
		||||
          let
 | 
			
		||||
            hostDevs = attrValues i.hostDevices;
 | 
			
		||||
          in
 | 
			
		||||
            ''
 | 
			
		||||
              if [ ! -e "$STATE_DIRECTORY"/ovmf_vars.bin ]; then
 | 
			
		||||
                cp "${cfg.ovmfPackage.fd}"/FV/OVMF_VARS.fd "$STATE_DIRECTORY"/ovmf_vars.bin
 | 
			
		||||
              fi
 | 
			
		||||
 | 
			
		||||
              ${optionalString (anyVfioDevs hostDevs) ''
 | 
			
		||||
              ${optionalString anyVfioDevs ''
 | 
			
		||||
                iommu_group() {
 | 
			
		||||
                  g=/sys/bus/pci/devices/0000:$1/iommu_group
 | 
			
		||||
                  until [ -e $g ]; do
 | 
			
		||||
@@ -283,7 +280,7 @@ in
 | 
			
		||||
                  done
 | 
			
		||||
                }
 | 
			
		||||
 | 
			
		||||
                ${concatMapStringsSep "\n" (d: "wait_vfio ${d.hostBDF}") (vfioHostDevs hostDevs) }
 | 
			
		||||
                ${concatMapStringsSep "\n" (d: "wait_vfio ${d.hostBDF}") vfioHostDevs}
 | 
			
		||||
              ''}
 | 
			
		||||
            '';
 | 
			
		||||
          script = mkQemuScript n i;
 | 
			
		||||
 
 | 
			
		||||
@@ -6,6 +6,4 @@ in
 | 
			
		||||
  # yeah turns out this is in nixpkgs now... we'll leave it as a sample i guess lol
 | 
			
		||||
  monocraft' = callPackage ./monocraft.nix { };
 | 
			
		||||
  vfio-pci-bind = callPackage ./vfio-pci-bind.nix { };
 | 
			
		||||
  librespeed-go = callPackage ./librespeed-go.nix { };
 | 
			
		||||
  modrinth-app = callPackage ./modrinth-app { };
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -1,26 +0,0 @@
 | 
			
		||||
{ lib, fetchFromGitHub, buildGoModule, ... }:
 | 
			
		||||
let
 | 
			
		||||
  webSrc = fetchFromGitHub {
 | 
			
		||||
    owner = "librespeed";
 | 
			
		||||
    repo = "speedtest";
 | 
			
		||||
    rev = "5.3.0";
 | 
			
		||||
    hash = "sha256-OgKGLQcfWX/sBLzaHI6TcJHxX1Wol6K7obLf0+CHrC8=";
 | 
			
		||||
  };
 | 
			
		||||
in
 | 
			
		||||
buildGoModule rec {
 | 
			
		||||
  pname = "librespeed-go";
 | 
			
		||||
  version = "1.1.5";
 | 
			
		||||
 | 
			
		||||
  src = fetchFromGitHub {
 | 
			
		||||
    owner = "librespeed";
 | 
			
		||||
    repo = "speedtest-go";
 | 
			
		||||
    rev = "v${version}";
 | 
			
		||||
    hash = "sha256-ywGrodl/mj/WB25F0TKVvaV0PV4lgc+KEj0x/ix9HT8=";
 | 
			
		||||
  };
 | 
			
		||||
  vendorHash = "sha256-ev5TEv8u+tx7xIvNaK8b5iq2XXF6I37Fnrr8mb+N2WM=";
 | 
			
		||||
 | 
			
		||||
  postInstall = ''
 | 
			
		||||
    mkdir -p "$out"/assets
 | 
			
		||||
    cp "${webSrc}"/{speedtest.js,speedtest_worker.js,favicon.ico} "$out"/assets/
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										6239
									
								
								pkgs/modrinth-app/Cargo.lock
									
									
									
										generated
									
									
									
								
							
							
						
						
									
										6239
									
								
								pkgs/modrinth-app/Cargo.lock
									
									
									
										generated
									
									
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							@@ -1,97 +0,0 @@
 | 
			
		||||
{ lib
 | 
			
		||||
, fetchFromGitHub
 | 
			
		||||
, rustPlatform
 | 
			
		||||
, pkg-config
 | 
			
		||||
, openssl
 | 
			
		||||
, libsoup
 | 
			
		||||
, dbus
 | 
			
		||||
, glib
 | 
			
		||||
, glib-networking
 | 
			
		||||
, gtk3
 | 
			
		||||
, webkitgtk
 | 
			
		||||
, libayatana-appindicator
 | 
			
		||||
, librsvg
 | 
			
		||||
, wrapGAppsHook
 | 
			
		||||
, stdenvNoCC
 | 
			
		||||
, jq
 | 
			
		||||
, moreutils
 | 
			
		||||
, nodePackages
 | 
			
		||||
, cacert
 | 
			
		||||
}:
 | 
			
		||||
rustPlatform.buildRustPackage rec {
 | 
			
		||||
  pname = "modrinth-app";
 | 
			
		||||
  version = "0.6.3";
 | 
			
		||||
 | 
			
		||||
  src = fetchFromGitHub {
 | 
			
		||||
    owner = "modrinth";
 | 
			
		||||
    repo = "theseus";
 | 
			
		||||
    rev = "v${version}";
 | 
			
		||||
    hash = "sha256-gFQXcTqHgSKfne6+v837ENXYYiEYu/Yks9TpnfBCPnA=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  cargoLock = {
 | 
			
		||||
    lockFile = ./Cargo.lock;
 | 
			
		||||
    outputHashes = {
 | 
			
		||||
      "tauri-plugin-single-instance-0.0.0" = "sha256-G4h2OXKPpZMmradutdUWxGG5axL9XMz2ACAe8AQ40eg=";
 | 
			
		||||
    };
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  nativeBuildInputs = [
 | 
			
		||||
    pkg-config
 | 
			
		||||
    nodePackages.pnpm
 | 
			
		||||
    wrapGAppsHook
 | 
			
		||||
  ];
 | 
			
		||||
  buildInputs = [
 | 
			
		||||
    openssl
 | 
			
		||||
    libsoup
 | 
			
		||||
    dbus
 | 
			
		||||
    glib
 | 
			
		||||
    glib-networking
 | 
			
		||||
    gtk3
 | 
			
		||||
    webkitgtk
 | 
			
		||||
    libayatana-appindicator
 | 
			
		||||
    librsvg
 | 
			
		||||
  ];
 | 
			
		||||
 | 
			
		||||
  pnpm-deps = stdenvNoCC.mkDerivation {
 | 
			
		||||
    pname = "${pname}-pnpm-deps";
 | 
			
		||||
    inherit src version;
 | 
			
		||||
 | 
			
		||||
    sourceRoot = "${src.name}/theseus_gui";
 | 
			
		||||
 | 
			
		||||
    nativeBuildInputs = [
 | 
			
		||||
      jq
 | 
			
		||||
      moreutils
 | 
			
		||||
      nodePackages.pnpm
 | 
			
		||||
      cacert
 | 
			
		||||
    ];
 | 
			
		||||
 | 
			
		||||
    installPhase = ''
 | 
			
		||||
      export HOME=$(mktemp -d)
 | 
			
		||||
      pnpm config set store-dir $out
 | 
			
		||||
      pnpm install --ignore-scripts
 | 
			
		||||
 | 
			
		||||
      # Remove timestamp and sort the json files
 | 
			
		||||
      rm -rf $out/v3/tmp
 | 
			
		||||
      for f in $(find $out -name "*.json"); do
 | 
			
		||||
        sed -i -E -e 's/"checkedAt":[0-9]+,//g' $f
 | 
			
		||||
        jq --sort-keys . $f | sponge $f
 | 
			
		||||
      done
 | 
			
		||||
    '';
 | 
			
		||||
 | 
			
		||||
    dontFixup = true;
 | 
			
		||||
    outputHashMode = "recursive";
 | 
			
		||||
    outputHash = "sha256-9HtTdIotG3sNIlWhd76v7Ia6P69ufp/FFqZfINXSkVc=";
 | 
			
		||||
  };
 | 
			
		||||
 | 
			
		||||
  preBuild = ''
 | 
			
		||||
    cd theseus_gui
 | 
			
		||||
    export HOME=$(mktemp -d)
 | 
			
		||||
    pnpm config set store-dir ${pnpm-deps}
 | 
			
		||||
    pnpm install --ignore-scripts --offline
 | 
			
		||||
    chmod -R +w node_modules
 | 
			
		||||
    pnpm rebuild
 | 
			
		||||
    pnpm build
 | 
			
		||||
    cd ..
 | 
			
		||||
  '';
 | 
			
		||||
}
 | 
			
		||||
@@ -1,35 +1,30 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyB3QTU1
 | 
			
		||||
TEdvbFNaUmE4U1lCNzI1dlloVDBTNXdURjZ2akRMV0R6dm5ST0FNCk9YclRSakhT
 | 
			
		||||
NlV2UVJwak9Fa3dQNTNBK0xKWGlkNXdwZTBEMm4xZzc3azQKLT4gc3NoLWVkMjU1
 | 
			
		||||
MTkgakk4UkFnIGNBMHNrdG84cUQxd1lqQmJIczlScU1jNk52Y3BtR2tXeDNWdWRX
 | 
			
		||||
cEFCR0UKVU5vem5MZUFPbGhoQzJTYnF4OTd3OW9jYTRkazdocVJkZ0pRRGNLek93
 | 
			
		||||
cwotPiBzc2gtZWQyNTUxOSBnU3hQMFEgQ2RUaEUyV1ZGbGRtZnlIUEtTQXk5MUZF
 | 
			
		||||
djYxZ0hBUThlV2tXTHNvdXpVSQpMdiswMy9QNUtCb1hkbGRqR0Nia3FXTzE1ajZL
 | 
			
		||||
UXljSTZqM2YvbzVuWUFzCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBYL1NrRjRaRnFn
 | 
			
		||||
RlNLdWJ3cThteDM3WmNaY210d3RmZzhCYmNpVXBwVGlVCjBkM0IzZC9zNjhmTTZV
 | 
			
		||||
R25ySkVoQWxQQ252WWFlWWZFMlc5dWtUN3VvVTgKLT4gWDI1NTE5IE8yUU1pWGFr
 | 
			
		||||
NzUvZVpwalB6aklkWmJGWUQzTnJiRjNzdzY2MUp6MkY5M1UKR1VIWDVyTFpxem5F
 | 
			
		||||
TmRNWE9zZStLanRTdlU5d0NOSEJKdWhDUjBCdy9vOAotPiBTJCd2NyFYey1ncmVh
 | 
			
		||||
c2UgfE4mYSBXfms0TC5FPiBiYmx8IGRFV35mciNoCjVZdHRiVUtMMWxEMlJ4b1F1
 | 
			
		||||
TGgxY01XTlZpTEtndkg0T0hRVjlqVUJGMUpSaE5tVlZWR3VGenpkUXY2eXJtbmkK
 | 
			
		||||
ZCtqRVN4dnZENXdoYkpjNHRWYXkvN2laY1p4YjV0WQotLS0gOHlEVTVOSmlNemNQ
 | 
			
		||||
TW5ISk1DeDlEM1RoQ2JtUFlyTXRKQjdnT0hiend2VQqrUFvr+76sKn0ldBmZMlEW
 | 
			
		||||
U2k85DLo2KU+/+GtbkZwVXxxIZHMLpoJgghHk9ptdalUgLGcl0X15x9jVaw8aeta
 | 
			
		||||
hbeOHotRHY7bC3z0S74riTk3xDMR1eT0QGhDMWHjfo8SkCftOYBlFfhTftevdep3
 | 
			
		||||
pKMZsuQMwH9JzxgUfcxIcWE975cZzrEJ85nfWMGvdSjcg51KNxP/UUPRxDlcbCEf
 | 
			
		||||
9XX5apSzNsTI3ibGD1n6Qwq8bdVYDMHmy5pAhw4l8L+SdoU1tGdw7JOA16sMCJbx
 | 
			
		||||
T4bV0ky/PGRonjJuCyDBj8oe9vMe1ZI1O/ITtktekS+wocxBs6QXlY7pIZMlGUn2
 | 
			
		||||
6m59ZEEaf7R4/MdnmBDNDkQuyXaKc7SaTc6h5sKWzXdYScGUKvgUQ7U/WJ2ItUTC
 | 
			
		||||
N/Xq07GkZZMt5MYBlyEr+/mKWlcy+ylJPGb7EswvQWaHoeM1QF0XLZ1v+W/Xsso0
 | 
			
		||||
seIoz+geSu9a02kwfsa8WvWXdIAT5X2pNGPClVNzjQ23pfQfQuW8ZQrGmIFR4g5A
 | 
			
		||||
58T1K+vGLdShqqVGyJFMVrSuOzqX5FVmZalu7/++1IQfiRGUlrHKoPlKWnCfFEOu
 | 
			
		||||
AYjaPeEFX2ByxcqfMK1YVPvUufdISUQeaQOO7mXGE3FqB0oUqmRIUiWZATwhq3Pw
 | 
			
		||||
p5QdcySTnmMpD/w05hvwski77kCdmYuHlMlLZez/kfhTnIGXris+Vwi/V19bsZ8G
 | 
			
		||||
zwaZ/Xr6WNC+df5JqSfTGREnXZPFRDkaTt3ri5/eEm6BqliuYjGbuiKsDECi4+JX
 | 
			
		||||
bHpH6LBBoKQ6ms7jCAn0Ls4cUKF37PcjGAOuWnzCSBU+REht1EDfHzx4C7hNiP8X
 | 
			
		||||
87NjEqJbwE9lORho0hQJRTn8uriQcidlVoB3se2SYKbMy8UA4NNnxN9PTj0TuQjL
 | 
			
		||||
OD3LtqHBElqNPbGNyyEAAJmMBmmkUvPPXlGQ0D99b1+jIdHzYSRtOLshBFykqWYQ
 | 
			
		||||
LJD61duhGqcQqcLx4+JdQ+oVcfAI2nG7YINnHB0OmS2DOZvvwqQ7ASScSujUWIjA
 | 
			
		||||
LNQxu3ruMz+bw/G0tYZBBiE=
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBMQkxo
 | 
			
		||||
YUpuOW5hSFdZYzhBaU5oeFZPRlVoMmNWMEVhQ1VVclJwT2dtdEV3CmIyYStQeFMr
 | 
			
		||||
VkI3UjhSVFA1eDRZWXBjVXVxamx3ZDFaOTF0YS9ZVVk1eFEKLT4gc3NoLWVkMjU1
 | 
			
		||||
MTkgZ1N4UDBRIEdReTZqdlZkSloyTTV6ZFl1QU1hbU53QlVpM3dFVUlNM25MRFhm
 | 
			
		||||
Uk96eHcKbWFOYytZbHd1d21xN2JEdE9xQlU2MDQ1dVNvQmlEQ1dCdDJUdXdNSURG
 | 
			
		||||
awotPiBzc2gtZWQyNTUxOSBWRmN3NWcgTURZWU01WS8wZnA0ZXh5L2h3ZHhPUUcy
 | 
			
		||||
NEhPUDdUcjVRZjRDUWlJRWJCZwpNakpPdFprVUxoWG1ESi9uZWFxV3RDbEJrbUc5
 | 
			
		||||
Q2NsVmx5UnhBclhHSjlZCi0+IFgyNTUxOSArS3JYaklMR3RtSEVhbU5OR2EyY0s4
 | 
			
		||||
OW12V09mZGVYYzdtbEdWL1NTdjJFCmU3c25iNG53d21pTHQvTW1TM2hDcG1xZkZq
 | 
			
		||||
M2R3QkZyMnMweFdTeVNFLzAKLT4gMz4sWF5JLWdyZWFzZQpmOU9PTTFieDQvbVhL
 | 
			
		||||
ZwotLS0gd0R2OHhrekNrWndZQVR4TTg1L21TM09hUWFzU3lLKzg4QXdHbWRhUWFE
 | 
			
		||||
dwoRz4OWxG6yPNFZtBgIuHT8fNp9LRfE7KoD4HcpZtnSIIhgjfs6Bw1KTJtDMRM/
 | 
			
		||||
EbfhxdRuiRs9GES5RQw1n5+kFjZxD9X2ExbnsOhoqc9fY5w/BWcg467ExIt1svDh
 | 
			
		||||
wwXGKxsf7upC0NsvywpArY+FeAslYdpfsbwE7TlmnHSG4ZfvJq42RsMiz2VsoKxl
 | 
			
		||||
vgdK97lKWUD9xoWM1KJ0ujej8srRWjQQrWo3m28avgUr7LUHPYNbXcOALn60jsKE
 | 
			
		||||
N4pBf9pTO5DD6RHTltpXVPyNU6tewUXbyAFWYEPTF5c18Gsl1sjWxKX9mEHcK9VG
 | 
			
		||||
hK+5Bg1ygBJ3Rz0o9IROw/cnE8ukHvutZFzSg/d4VOoRvKxhBCxQfr/dy12e33RN
 | 
			
		||||
i3jkTqR8Op3279q5Fpi3Z3Ca23Ts32omRRKHt1wQWg9LnI7MonngJpSV1mWk6Lln
 | 
			
		||||
RfSxmMtE2DZ64FUCngV17nPXsNqsJxL/edecRaSYFuHWUSEaJvYxHbRN3/QZgKEi
 | 
			
		||||
PKUJ7n4hlVrHM9Dk1ktvgVUhf9bucywMiJZUE5bxP6iIlcdTJQsAbd3FzqM+KUD2
 | 
			
		||||
FNEOY28RWPCBhbHtRK8w6a0hSfH3x6/1yBbVWrF7RyJayV6tSUyPMoSKobqSVgZ5
 | 
			
		||||
LMZXaZXfvznBdmRHVyZjVtQM+SKcvY7+jguNCHWOltoCOosT1pdN6XWYyi8piNgQ
 | 
			
		||||
3nQDScaiEb61z7juzBlwsbFZ1xVRyMYrNeeg3y9JKjJEImxUae59ieSy+JLkIBYC
 | 
			
		||||
LtEwCmyvtcxyRtj1uki2DXtnbPP54vA0BIF0g0bw3FCNcjDslt7ruPN6YWPQjWOY
 | 
			
		||||
nCeONk9/JoA0ejG8AHK26W/YlvelQVF+qQJv/ODTdQIjjpM/6ftQZrb++m5hIQHD
 | 
			
		||||
p8pCNgta3bXYz58XyeM2WPqBKgU/OAC24AeOLgiTW8PdlTPy31Ylb/wNtsUFYqSW
 | 
			
		||||
2cPM/hM7Qjq+OAuuhgf2cOxRsx6cX1y9BnWJVRDUwwBTDjVsF+It8AK6RJ9CUL/p
 | 
			
		||||
gRI16087ZRMsfYi0qolVX80IQnJnTl6K8hjWhhc0KAUXZSc=
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
 
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpOcUlvZyBNalB5
 | 
			
		||||
RUZRNE1CTUJsbW1kSkxBSWVIcG1RUnBKd1gvcnRQVkZCUXFOQmhvClJUN2ltbnNk
 | 
			
		||||
T1grdVJSTzIyNTBTTGVEckVGQXdYNHdwOU5NbW1md3lGM0kKLT4gc3NoLWVkMjU1
 | 
			
		||||
MTkgcytxUmZnIHZ4bFZSS0huWFBDbUhNcTd2MFhvV0lOY1l3d3ZXNU4vT3dwMmlI
 | 
			
		||||
emhoV0kKcDF4M0FPK0JpclI5Q3Q5WGxpZWVYbHVWbkNWdTArclZsN09XK3VJSXc1
 | 
			
		||||
awotPiBYMjU1MTkgRjRCNVZmcXVnQnJ4KzZoM1ZkdWxYUkJTM1JuK3ZlRWJYdkFR
 | 
			
		||||
WXpFSmR4NApTbU5qR3ZuN0ZmbzIvMTFsMkdNSGJXSVlrVmZPdnZvcHFiZW45SW9I
 | 
			
		||||
endJCi0+IDEoIjlcJi1ncmVhc2UgJUE4IWl5ODkgfGVdLihEfT4gWCAreSduPS4K
 | 
			
		||||
bkI2Wm9LRGJXdW11aDl2VgotLS0gTENqYjZEUUZaWVZEcWQvWW5yTzJEdHRLeDJm
 | 
			
		||||
QUl5aytXdDE5QVMwVHZVSQo+aDbaGNOrz+hTSUQ4IAjDC9EfNwrlXDZtBqw8HkRv
 | 
			
		||||
1/Rr737scjrM7Bgt9zuKn6CB0zdeHTW5u685V2hCW/3aTy1eppWMWj3r
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
@@ -1,13 +0,0 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyA4N0Qw
 | 
			
		||||
bFd4Q01yb3M3M05Ua1BPZjNsK2cwYlBuSUM3TXRaa2hPU2wxb1hzCnhoTzNMYVNT
 | 
			
		||||
bjRUTzFJdjdZVG1IVWJNa29PNjVVQ2NWbFdnNWNjcDk1bk0KLT4gWDI1NTE5IGVu
 | 
			
		||||
d2x5N21ZaW5MeHBzWkw5QnV0SUNiZTJBVlhXOFZacUFJVktNQXI4MTgKYmxQYmlC
 | 
			
		||||
YXJvYjhKbWVZWGRPWWh0eTlIZTJPSFZTZmt4UHJ1M2thNHRCMAotPiBvPls2N3ct
 | 
			
		||||
Z3JlYXNlIGowLGEgUFNKKWljTX4gInUKMkFwNGRiZUJCbUZhN2Z3YnZnZ3Nna0tD
 | 
			
		||||
UCtrODlldWZ0Rk5INmxTd0tmTGx1NS8rQUtTdVFwSVROcjVqeUJaWAplNWd3SUR5
 | 
			
		||||
MjRzeXlyemtka2EwdVZDTkowTk5NMk1rdUxCdkR5ZUJOCi0tLSA4bWVKMXFTalg4
 | 
			
		||||
ODFIN0hsTS9lekdWZVI2VTNKYlE3UzhXNk5nM1ZCMlowCn3ZLml2b8qDs+A2W8Nn
 | 
			
		||||
YGCfDV+aes39ef/2wu6EMISradXZQrzhSj8JHn7HqsarqSQmOhYP5juawEFxAuZJ
 | 
			
		||||
kUc=
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
@@ -1,19 +1,17 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyA2NGhR
 | 
			
		||||
aGJ3RjRaTjlFeUtWa1FZbmdQcGJmbVdxNVkveURqbmdwL2x1RGpVCnY5eTFZRjV3
 | 
			
		||||
QVNMZ2xGMHVBek1BaklxUUtiRU5pTU9kWFk1VHhGNE81SFUKLT4gc3NoLWVkMjU1
 | 
			
		||||
MTkgVkZjdzVnIElYUmkwbUFPeEExZnJGVWwvUFZsRTdhYkJsSC9CM3hMbGtuSVFs
 | 
			
		||||
UGJXQkUKQnc4MGNMM0JZcC9FeG5HeHpLUVFlNE9xelo4Qk1mam5WNlBITnF3WnJs
 | 
			
		||||
WQotPiBYMjU1MTkgVkpmUVdBY1p2UDdLcFpXVnJOZGUyZ1VXNVYrUmxkZlpqazRn
 | 
			
		||||
cVlLYkt5YwpZSUtIN0RwSEdOSUFYQ0Zsc1NzeUhiQ2Q0T296dmZ3UW5hY1Y1MEJn
 | 
			
		||||
MzF3Ci0+ICV5Qy1ncmVhc2UgXSggRWprMCBuCkdKVldUMHozVXlqTVNrUVdyUVd0
 | 
			
		||||
MFdSN0dPSVdnT3hMN2NNYVBRSGZnV2k2cVp4NGdjMHBHS0xadC96YmNObEIKUWVH
 | 
			
		||||
YWk1Q2tuQUpsV01JWVozbG4rd0ZiN1JHOHRFYVFIenVxOFhXRndrN09lODkvaVhB
 | 
			
		||||
eDBoVmxvbU1FbWJrCi0tLSBSeU5TaVZUbmdwdmh1TDVzb0s1eDFvNkVrK1dqTmZG
 | 
			
		||||
cDJobU1DZkdHRWhnCvEtMAlEC+BPPYX1YvvcmvRjeOgbuuxzjkGjuB+tT1pBKfYR
 | 
			
		||||
9gsHtkPWibhCk546Q1w+fY4StxKmaoxPddBjeQNXh9W6cCQ/vSmxAFya3w5SEtPd
 | 
			
		||||
QjozqEVsiwBmBrZgt0UJ96e5hmhmD6zU7fp/RhpFpZv1JrEkhYEz8+jk5Ai96mSg
 | 
			
		||||
0pKDAU8xtCnyBBaPiaj2jU/6kiKoGaVXCEuIv0uayRhRp0wap/kf+ToHA/oXVXbl
 | 
			
		||||
TZsalOEKH38udhBJiMjRgemqyHQEEpjmYIMWdiTvH6PGZ0yp/09iiEyBCMwzcJAk
 | 
			
		||||
nr8HyZKcuzswBcVjRak/raM9lAbpdWWktHxAZa67wsCH017FDrN9e15B2MI8
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBVMkFi
 | 
			
		||||
Zkd0SHI1L2M0YTNKU1RXVnFZYlB6T1hFK1B5RWwxYlpkSU9ZVlFRCmRPdWVyNkJ5
 | 
			
		||||
VGw0K3ZBeW9mYmVteEt6aW9BaCtiTzhpb0lxdDZMTkJ6NFUKLT4gWDI1NTE5IGlW
 | 
			
		||||
UCtQeXg0bXZNMTlBQUVvTXBScDFRcHFSMzVBd2x5ZDJuVTg2cGx0MXMKTFNDbkN4
 | 
			
		||||
SDlEcG9BOCt3Nk1yNENxKy9EU1dXVC9yalJ0ekRmc2FvQldmZwotPiA3JzZefHFp
 | 
			
		||||
LWdyZWFzZSAlQjUmCmV0dUJQU01RdlZraVdPNFN2YzE2Y3d6eW00RmlZd3Y0eVdu
 | 
			
		||||
bHUyVDlCb3dsZSszOFhNb1BIUGZUK2hqaFNkV3oKZDRZMU9UbUZUSURkakNvYU9N
 | 
			
		||||
WHJRVVhFT1VUczljZlpiVEZ4bSs0NGhYM0k3N0F5UEVWRXd1blFXZwotLS0gWTIv
 | 
			
		||||
NXVUb1RQL2ZhajFnSlJuaVp5c1hOUENnTkloOFJ3ZkFTY3pvdktCOAoFB6muUkj5
 | 
			
		||||
xjLe5AQ9bHB2f8DL1U0ijCeHPMHv7fk41jpNAGc0KMxpNboGXxROEu2ZsLN2WJOm
 | 
			
		||||
z7LEGHh6bSGP/sBgJnnUMWdsaqToa/JK3d07LzZMevlNxAXOpe/SE3rAEFUnbPKr
 | 
			
		||||
UuNYoO2FmyDCAhmdB+HAhb1JUDmmGWEVftrwoCeRg97RE5Rgh/+GT6QJcAct6e3+
 | 
			
		||||
QrJqZ9045L644rDqhMHGHAWTjsLX9s8i10WNhFS4x5J5+C9u32eC2xZ/ZjMj4vHU
 | 
			
		||||
xkNg/HCL6iDnm/jlSfmrbuTWu70IofWz9gPZy++/Gbf8uM7cICWXU1ujCI+4TIQm
 | 
			
		||||
we8GEP0lO4wrGYnzXgXs5cT0V0dV4Jn5
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
 
 | 
			
		||||
@@ -1,14 +0,0 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGhrYnR2ZyA3MjM3
 | 
			
		||||
dytZeGQ1VmFtdmtEdFlQWG9zMzZLY3psY1NBaVloeUh2VG4xbVVrCjdua1BHajdT
 | 
			
		||||
WEpvdTRoTVdTUGpqTzhQWXpEMkxEVzBwQkwwZ21qNkdMVkEKLT4gWDI1NTE5IG9x
 | 
			
		||||
d0ViazRzcG1qSDNFR29GcFJtMWxabWRqdnBjQUZBWklyNUZvdjBmMlkKcWhDUGxu
 | 
			
		||||
YTZUbEhtMW5pajdpQXYrdEp4NllXRkQ0NWRhc2p5Y1Vub2VjTQotPiBMSTgtZ3Jl
 | 
			
		||||
YXNlIHQ3Ngo3enhCRVhiV3N0TlkzdHNMMHJTZ3F5ckc0UUlUa3hCVEZQdTUxaW9p
 | 
			
		||||
R2hJRmlxWTZPU2VVbEpvZDZpKzN2NXh0CndxRVM4ZkEKLS0tIHMyTEZJUVRGWlB0
 | 
			
		||||
bS9hbjduWWJuVW5KVXpnYlRkMFdCK052RkUvSEdMV1kK4fjaE0yBZXu55Kn1j/yG
 | 
			
		||||
PRwEhA9QyNbas21qCikGh8RxCUfoobhlKHpYxyvOMenhv0+8gb3ceXzSUR/3a98Y
 | 
			
		||||
orARTVFlOvVZolCwoyC86kUExIBubJxO3EpH2UxrvQoCOrAf5XdD+qzt/G71wpYk
 | 
			
		||||
jGUknUWUyPbj9HWoVo2aRmC//bCnena9DUVicAXbDwqr5/KCHHFlkT9UI5Vqvgfw
 | 
			
		||||
rPpyZ+De
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
@@ -1,64 +0,0 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IC9FSlh2ZyB2T0Ft
 | 
			
		||||
R1o5bEVYRzk3VnpzRDAzK3kzTlNuSTdPVkkrT0l5RjFYT1RuZm5vCjYxN1A1ZFU5
 | 
			
		||||
TEE5R01RcnQ2T1k4NXZuc25RTUlvc3NBNnAwemE4YXp2NUUKLT4gWDI1NTE5IGk3
 | 
			
		||||
M2lSMXhDWjEvVVBtZnFJdmlnT25OZ1NlOGJwVWo2Qm84L2UxRGxlbU0KaFNzR0sy
 | 
			
		||||
clllVC9QSHU2ZDEvQW1KTDlXYlF4aDdUNW5RampTbGtsaHZCUQotPiA4XHJETy1n
 | 
			
		||||
cmVhc2UgM1xTMnYmIHJqbEogKgpoVWg1V1ZubElOZVNhazNzdGRrS0tyZFZKNWlo
 | 
			
		||||
YW80Ci0tLSBZZXdFT25VVTRnaE5jNnpyaU5OTUdXeE1FZ3djRmpKMG9hdDdodUIw
 | 
			
		||||
Z25JCmaCCdtWJR+6PZbGMCKLAYmG2j/YxlrZzAjLR6g3KFQjDhJA6zTCDy8UHQyH
 | 
			
		||||
7A0+1Ozu5RBt0kVJiejX+osYYBhFHMEqBJnuB79lmrAg/Pyss3396b1C9hMCZqdo
 | 
			
		||||
mkt0knv8wWSI78eMP9DtUQXK0NW4rDf2Wyis9/U4IImlVk5QgkcR1mheF1bgyJt0
 | 
			
		||||
t8rr4UBpT8EU85aSGhXC45IkVtAtgA3hsNcptwwcyJT9Hz9obYUnov6tlwD6p4oJ
 | 
			
		||||
8tvpTC5p212LBvndr6dvsg3zwlqFfVbkDgsidnIpTTaxqbFi2nHl0F67Ofu17J/l
 | 
			
		||||
AWj/5SeiK7k8vDQt+TSTuAF3tuhYvSBYVT/7EHCFzLAnNj/TJFWZf//gH7S/byZW
 | 
			
		||||
1XbEqOaUK1mzOESLbwR61hDNfRRRrr85CTx/n8KXvJFzQ+mi1hHJmEbrGzd2tObm
 | 
			
		||||
EmCCzcCsupjgFH/exS/o83lleR5zN/BW96Sjh12MbE3OuMjcjZJ7noDv6q9p0gmq
 | 
			
		||||
hHMmocC53xxOB00dlUBLmheo6aGyfF+XE7m5FYHVjlIdu2ol43BGGF1Wv13xJ+w+
 | 
			
		||||
G5cI+jahrkRpmIk2sLeV+BoCMnEYjOnFc24uya9km0Vz7fo92tK037+kdaFUXjvX
 | 
			
		||||
JmWkbbcSb8YcgKzZLhFJiscY+P0xN2hmoai0fNC48Oneu0GqQdftfjiQYJMhp18o
 | 
			
		||||
T3IERTLt/JoNIhqZrssg0lKHyt6N47S2A6/X2cT6eMgRrRn43KthPjsmGhRjdFDT
 | 
			
		||||
qCuUJJl1L9NX4EqZjXHBZo/bjsbErx2XixN1YbXGnLwN4yUEjE2A/hMbWumzZxp+
 | 
			
		||||
ATJgbTYuzim6lachbXsrf4f9sRjDjufMR+evD4lMTmFx+Mg6edBJN6Z2lvLyxJh4
 | 
			
		||||
qtw0Uejxn5mYPX1otpTa5tTD5ZSGvMXikDO05ItVcfWKQ7Uohck9cRRbNoJn+dlL
 | 
			
		||||
8UuNwmXixH7CkC11w51HTM7HkDW3G3aRTftN2mdfEC2Qr1aGKM+tqLEddja+vDPJ
 | 
			
		||||
9Ty8m9nXC5armWO9ewNji4oBEmi0QQK5kasLdQfPBMFupL1a0H2FxtucW2BVW5/K
 | 
			
		||||
RQTgJ6ACitcd36+FWtof3HoKyOBqoezguh6P5ImvKgz3mGcq/2AdosgSZ82m4eZp
 | 
			
		||||
Ug2KAEgZkR8mdNLujJHD7TZyW2FFq9DAF0Qshg7eD2cK4QA1BdpOrMUTKS5yCHFb
 | 
			
		||||
wXJWefnUK5Z9fvGeIN3L4bBjzYBwBfqopBmfDguGx3P7o3Zk42mJ5Z53NTqW0HaF
 | 
			
		||||
CN805HzFmNFt9/WV5I4jzVlVgNeep7b3wnH3pLITfz2FpDYU0/URuUNV/th2nJ2+
 | 
			
		||||
qH0tTbl1sql/i+kPGHQbyuCbM4IsFo6dZMgCGaovv9jmbJuS3ZmrRQhE/8CUMK6V
 | 
			
		||||
YsKi7Heyeza4HDzh9tlddNG+jwkT9/pIWvXChGa3JPokDtJrOoa7P6dV78opfGcT
 | 
			
		||||
XJFQbOm0KIH0rISbuWV7I4XEmkEim5TtmaGmsC8NIqgsY7Wjv0pap6vevevU6ImF
 | 
			
		||||
w7pxeU0J+5Npm88B+Nyd95Shy/pjRou31W7qTpE95/z89tLKmN3EKL1iDOWhWdCW
 | 
			
		||||
VsFS0XC1x7LIpnCXKf1QbnxmQzndSH/oMXmWetCUQ9RPbp8BpiIi+aULe6wzArPb
 | 
			
		||||
0Kxs+EEKMhswp4wbZNCmC5X3RRmm4CrmPryb4+rMqWhhTRXri2QvfuOb3IyM46wa
 | 
			
		||||
vKZJsCwlb7/2KR+DTwGJDcV9ArX85Yxb6lhHyQqMyHfL8XmnctmejVA+aacWc+dl
 | 
			
		||||
2YAwoUo/NnZ28GVjZsImt8ltJlcc8bIW8GwXqqOKPyqdShU6ExxdFRLUhq7o82uK
 | 
			
		||||
1oDtxyqI77IbVgQMlrdqL9XRuM3OvGt3rjg51EpDVqY/PUDrFuBkk0eQDNVjaI9e
 | 
			
		||||
k5vbMCTjECdiEjQq+ZJsSeVfnEs3pJVqD+vtSIMC2oodxPc2rClrRuhHaCzvUVP0
 | 
			
		||||
7LR/2PZlIHzkbwy5sT9W8HOPV3PO/4jPwKRtZQvz8kFiEh2gj8ZfRDELVAV6BOKd
 | 
			
		||||
kLrGAEs+dmFOkwfzH7/Mb3hakHe7wqVjSBB4yZqd87zxYK91b8D4io7CemDUidiO
 | 
			
		||||
5+6ms829MCro5+ZmS0+ALnc2LTnFWc/bS0TkOdTtwpfCCF/9gbSea85PwDNaB8Vl
 | 
			
		||||
M41t15H3oXwjYIwpxvVN/1AWUn3NjbYE7a4ndLccJs//Wyj6nmmnIYc5H5r/BeTD
 | 
			
		||||
cHnue35twb4LmiL0MubjQNIyCHdnupCauorfZI6G3yLMXo9Y+Kf8FtkBEZdgD3TB
 | 
			
		||||
DC6264ZOkjEtBfYQ2gj2MXDsKGYVRuz7xn80NnvRr0O/KRpN7h8WNw2qmYKMt9Uk
 | 
			
		||||
qBgEIe5vyVcAl5cbEcZCQxMKGK6WY96IYmgCV30Bv61hUx9fn6Wc+86o00N/LJY/
 | 
			
		||||
O4e8QnRwVntY4IS6hYz3W1BjdzPAB9Bsz33UCznEyreaetRQlOTgg+sEZb1/EbsD
 | 
			
		||||
Ia5dDIjmxBc8Lpf3xLTHZkUYKZt4RlNdKCOhn8Ka+0bfpaW3AVWvEolgDl+e66E0
 | 
			
		||||
Mk2FzJy5w/+Rgav+Btf1Ol038OcvY2V/5KRcqXK244LIRpHfAd26eXx95DsN5vzc
 | 
			
		||||
Ulkt5aWt4awfxnz1SRUZChdoctJlOuiT/pH8S76FpeY+HXbD3vmTW25jHKXq0qqu
 | 
			
		||||
9HEuMRbNLcRcIrXoxpI7nfvfLOmtrEkHH+vVQdLauIGOUQKgaKc5PvvOU0ARerUn
 | 
			
		||||
1wbu8dSJvrzH2LYKhLZIYONmNaRLLlrGolw+vII3MvZYFTst6TyyXLcVwWcacL/9
 | 
			
		||||
k694FKX3TH5Rtbf3SjpJCNhiez/kWcDuWJ4k5hwfpU0MTQPYJRHrrWbHNrq7T0Iv
 | 
			
		||||
M40eTeN4mGn0ldcrkMObmMwMWEnPbmNPCsd4RnRG3jsf81UBFTZmMBe6oqW04OI0
 | 
			
		||||
u8h9Afhv9JZNx41FHY06WQUWk29Bo++0mWUiRJcDvDFFlnWlied8Fp9iU6ijJjp+
 | 
			
		||||
Fma/e3jc88/1rX8FKvYX5d6KEz+VmVW6PWLI2oQz5ydm7zDzJJ9zwzVrBpg3B6hX
 | 
			
		||||
m5Q/BfNdAKck4PB9rGfqs+/lPDNgHN7iUVPB95wYf1/jNAqY/I+OT36Hl1LFuSF8
 | 
			
		||||
kvOpb4w87BSTFIYBXBQff8xCwyhPHnyuQcSa7qgJDKdUqqMIG9sauzO+a316ZhqG
 | 
			
		||||
6LW2eEw1ZLuNl3Tk2ix3WhZWu42pf/uDGTu3DXJC05hGg1KuyvGWDGsIkI6yfNYg
 | 
			
		||||
MaHwIg6U+m1+Gva1rcv74vSH0OH4LIcco0F0V8wDA2IdbvPTduNIb4OheWPvReZy
 | 
			
		||||
zZZ12JjLSkKZI/qH1kGQTN6GN+NaUdtkr1ElX4H6IRue28Jtrm7pi39WO3J6/xZv
 | 
			
		||||
SC80sm3k/emvQ/1RiQbXXjxl3Ma+zcGFqkB93OaG+TbGiNRL5KkXWpP1fDF8zOKV
 | 
			
		||||
UkPletJkwnR6wsdEjd6q1ysRTHiDVf1uuSmdGep18QnRqQ==
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
@@ -1,10 +0,0 @@
 | 
			
		||||
-----BEGIN AGE ENCRYPTED FILE-----
 | 
			
		||||
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IC9FSlh2ZyBEb2hB
 | 
			
		||||
cnZBRFZ5OFlvR1ZtSm4zWG1MMjFhQ0VONkk4M2hPQmlaV0tkS21vCm9pWTA4UGtE
 | 
			
		||||
dXd4SnFCd3JMeGg3c0ZXZm5Fc1hWdkhxbEQzYVZyMHkyM00KLT4gWDI1NTE5IEwr
 | 
			
		||||
MXpubG9nMk1wNFczQ2dUY0NSKzZoR3ZkQlBkbEtOclg3YklWeEYwR1kKZE8wTFND
 | 
			
		||||
eDgrbDhNL0ZYYVNCSGRSN1dNSHlmdEVFSnVENnFMVjlOL3k3UQotPiBpNUpIRC1n
 | 
			
		||||
cmVhc2UKV0JWMGdmZldNUyswR2tLdUVFRQotLS0gK0E3VFRlVXZqSDQ0ZDBvdjdl
 | 
			
		||||
YU1UQkltNUw5ZndVTU1kbVZ6bDlCQjU3NAp0czfiB+B6CH87gdHFh4i6ssbAtjEC
 | 
			
		||||
RnlqGXKkw3Lxa66DU0KYewcXcnTQZQSXbaVHin1KXndG7F0Jvz0po70=
 | 
			
		||||
-----END AGE ENCRYPTED FILE-----
 | 
			
		||||
		Reference in New Issue
	
	Block a user