Compare commits

...

88 Commits

Author SHA1 Message Date
820bb2de5b lib: River IP update
All checks were successful
CI / Check, build and cache nixfiles (push) Successful in 1h4m34s
Installer / Build installer (push) Successful in 5m54s
2025-01-01 19:14:04 +00:00
7d3ad52a44 devshell: Add git config safe.directory for build-n-switch
All checks were successful
CI / Check, build and cache nixfiles (push) Successful in 1h2m7s
2024-12-23 10:32:13 +00:00
2cdb98e898 nixos/common: Disable channels
All checks were successful
CI / Check, build and cache nixfiles (push) Successful in 53m0s
2024-12-12 12:38:01 +00:00
b717b1ceb4 nixos/gui: Add /dev/player0 VID
All checks were successful
CI / Check, build and cache nixfiles (push) Successful in 1h1m16s
2024-12-11 17:17:33 +00:00
f31ce61c2b Update borgthin
All checks were successful
CI / Check, build and cache nixfiles (push) Successful in 2h31m34s
2024-11-30 19:31:58 +00:00
aec22942f7 Update latest Linux kernel to 6.12 2024-11-30 19:31:43 +00:00
fc8676c3bb devshell: Remove deprecated Nix command stuff 2024-11-30 19:19:23 +00:00
2915e42a1d ci: Group CI jobs
Some checks failed
CI / Check, build and cache nixfiles (push) Failing after 33m39s
2024-11-30 18:05:22 +00:00
5783d3a51e Update nixpkgs-stable to 24.11 2024-11-30 17:45:59 +00:00
2fe94bba23 nixos/git: Add longer timeout for Gitea actions runner
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 2h29m25s
2024-11-27 12:29:04 +00:00
4b42960d26 home-manager/gui: Update alacritty import setting to new section
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 3h1m26s
2024-11-26 23:19:58 +00:00
56e9abf945 ci: Build and grab path for jobs in separate calls
Some checks failed
CI / Check, build and cache Nix flake (push) Has been cancelled
The old build-n-parse seemed to output null sometimes.....
2024-11-26 22:45:19 +00:00
4e2c2f92f0 nixos/middleman: Remove config for Matrix sliding sync proxy
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 6m29s
2024-11-26 22:15:53 +00:00
caa208b288 nixos/netboot: Use older version of iPXE for now
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 6m33s
2024-11-26 22:01:42 +00:00
9e6f885c17 ci: Tweak log messages 2024-11-26 22:00:17 +00:00
d8ca87bfd8 pkgs: Remove glfw-wayland-minecraft
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 6m15s
2024-11-26 21:23:50 +00:00
e9467e0cc7 ci: Build and cache CI jobs individually
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 6m27s
2024-11-26 12:37:47 +00:00
6c98ef8944 Revert "nixos/home/routing-common: Move Tailscale to home routers"
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 1h15m14s
This reverts commit 7c05b6158f.
2024-11-26 00:04:43 +00:00
18981e240b nixos/nvme: Update to libnvme v1.11.1 to fix LTS kernels 2024-11-25 23:58:15 +00:00
df7e5953eb Update nixpkgs-unstable (and other inputs)
Some checks failed
CI / Check, build and cache Nix flake (push) Has been cancelled
2024-11-25 23:10:24 +00:00
71d1c3f9c2 Ensure borgbackup cache / config is persisted
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 32m28s
2024-11-16 18:46:09 +00:00
1453a755c3 Add (now unused) Enshrouded server 2024-11-16 18:08:10 +00:00
970af805e9 home-manager/gui: Swap swaysome container binds
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 23m18s
2024-11-08 11:47:35 +00:00
383e9a9b1e home-manager/gui: Add swaysome
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 23m43s
2024-11-07 18:21:09 +00:00
26a16d0629 home-manager/gui: Disable ligatures in kitty
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 29m30s
2024-11-06 13:16:56 +00:00
208de7654e home-manager/gui: Use rofi-wayland 2024-11-06 13:16:51 +00:00
f577e7d58a nixos/routing-common: Increase bandwidth for CAKE
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 28m44s
2024-10-31 22:27:55 +00:00
6130ee73be nixos/tower: Add brightness keybinds
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 29m59s
2024-10-26 20:24:27 +01:00
5d827aa00c home-manager/gui: Add xdg-utils to home.packages 2024-10-26 18:32:24 +01:00
173ffc0044 home-manager/gui: Add "Activate Linux" watermark
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 30m5s
2024-10-16 11:32:14 +01:00
b113f2f48d home-manager/gui: Add Git LFS
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 28m47s
2024-09-04 21:53:26 +01:00
7c67eaff21 nixos/colony: Add qclk management container
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 34m42s
2024-09-01 19:22:03 +01:00
d1f1b84e82 Use fork of ragenix 2024-09-01 14:03:27 +01:00
e3cb2adbb6 nixos/castle: Add recursive-nix feature 2024-09-01 14:03:05 +01:00
736c406eb5 Update nixpkgs-mine for mautrix-whatsapp 0.10.9
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 27m54s
2024-08-26 11:59:28 +01:00
8e9b750ac8 nixos: Set up remote printing
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 27m42s
2024-08-20 10:36:21 +01:00
51c5578840 nixos/stream: Add OctoPrint
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 2m16s
2024-08-20 01:03:49 +01:00
e174af45f6 nixos/castle: Emulate ARM 2024-08-17 12:39:36 +01:00
198e7188bd home-manager/gui: Use upstream unstable nixpkgs' chromium
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 27m18s
2024-08-13 12:15:33 +01:00
571f8f1504 home-manager/gui: Add xournalpp
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 18m42s
2024-07-31 11:28:24 +01:00
64c3fe682c nixos/home/routing-common: Only run Tailscale on active router
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 26m33s
2024-07-31 10:20:19 +01:00
7c05b6158f nixos/home/routing-common: Move Tailscale to home routers
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 18m12s
2024-07-22 16:22:08 +01:00
c9ab90547f Fix installer workflow short rev
Some checks failed
Installer / Build installer (push) Successful in 4m23s
CI / Check, build and cache Nix flake (push) Has been cancelled
2024-07-21 13:01:03 +01:00
63d929c8e8 nixos: Include mutable flake in every system
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m41s
Installer / Build installer (push) Successful in 4m20s
2024-07-21 12:37:32 +01:00
bbb87a2d69 devshell: Add deploy-multi command
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m26s
2024-07-21 00:33:16 +01:00
e5d5847b89 nixos/middleman: Disable zstd in nginx for now
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 25m3s
2024-07-20 22:41:01 +01:00
9e7294e871 nixos/shill: Rename atticd mount to harmonia 2024-07-20 21:19:25 +01:00
69216c6b4c Use harmonia instead of attic for binary cache
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 2h1m7s
2024-07-20 19:04:51 +01:00
1ea172e690 nixos/vaultwarden: Use non-privileged port
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 18m41s
2024-07-19 18:06:14 +01:00
b7be45715e nixos/britway: Update headscale config
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 14m11s
2024-07-15 22:58:49 +01:00
3522a7078b Re-update nixpkgs 2024-07-15 22:58:42 +01:00
b44f0e74e8 Disable modrinth-app 2024-07-15 00:25:05 +01:00
7c57f00b27 nixos/britway: Update Headscale
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 2h14m36s
2024-07-14 22:04:03 +01:00
c9d36ec65b home-manager/gui: New cursor theme
Some checks failed
CI / Check, build and cache Nix flake (push) Has been cancelled
2024-07-14 21:49:37 +01:00
d8f97b9316 Update inputs 2024-07-14 21:21:43 +01:00
d5bb2f6787 nixos/routing-common: Start / stop radvd only for IPv6
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 16m56s
2024-07-11 00:16:33 +01:00
ced82fc002 Update river public IP
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m47s
2024-07-10 20:26:38 +01:00
3535d2fd90 nixos/shill: Use MemoryMax instead of MemoryMin
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m4s
2024-07-07 12:02:50 +01:00
4e207c3397 nixos/colony: Disable KSM for now 2024-07-07 11:57:45 +01:00
bc4e75a6a5 nixos/middleman: Fix Element config.json
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m37s
2024-07-05 16:30:34 +01:00
2ae922f3e8 home-manager/gui: Adjust brightness for wallpapers
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 17m51s
2024-07-04 18:07:41 +01:00
f263fdca3e nixos/castle: Add left monitor wallpaper
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 18m6s
2024-07-02 22:22:10 +01:00
1232e9cb30 Update nixpkgs
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 49m21s
2024-07-02 12:07:52 +01:00
fbb29162ca nixos/colony: Enable KSM 2024-07-01 14:43:07 +01:00
7ab57a12b7 Reduce core count for CI
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 1h27m30s
Installer / Build installer (push) Successful in 4m44s
2024-06-30 15:02:21 +01:00
4e947d4b1e nixos/unifi: Set up UniFi controller
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 40m53s
2024-06-30 12:21:21 +01:00
b68e82ae03 nixos: Move castle to home
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 42m12s
2024-06-30 04:01:56 +01:00
91489551b9 nixos: Working castle NVMe-oF root 2024-06-30 03:59:46 +01:00
86c99c2cbb nixos/build: Add Intel NIC drivers and increased timeout 2024-06-30 03:38:48 +01:00
7e2dfc21c6 nixos/sfh: Working containers
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 44m19s
2024-06-30 01:52:52 +01:00
9ac63220d5 nixos/installer: Add NFS client
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 42m53s
Installer / Build installer (push) Successful in 5m15s
2024-06-30 00:07:12 +01:00
ffa5d19854 home-manager/common: Add nix-tree package
Some checks failed
Installer / Build installer (push) Has been cancelled
CI / Check, build and cache Nix flake (push) Has been cancelled
2024-06-29 23:42:31 +01:00
19fb29213e nixos/netboot: Mount /boot via kernel command line 2024-06-29 23:41:01 +01:00
f9870abc9e Working "shill From Home" full network boot 2024-06-29 23:12:21 +01:00
84ca556c47 nixos: Initial netbooting installer
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 34m36s
Installer / Build installer (push) Successful in 4m34s
2024-06-24 00:42:26 +01:00
9f2651e352 nixos/installer: Disable GUI stuff 2024-06-23 19:00:29 +01:00
bce876ec42 Add release token to installer workflow
Some checks failed
CI / Check, build and cache Nix flake (push) Has been cancelled
Installer / Build installer (push) Successful in 6m0s
2024-06-22 16:24:30 +01:00
bc8adcecad Update river public IP 2024-06-22 15:26:48 +01:00
8878ce56c4 nixos/kelder: MTU fix + disable all local redirects
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 33m1s
2024-06-21 21:42:17 +01:00
dd9439b7fa nixos/shill: Add jam container
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 33m30s
2024-06-20 23:43:07 +01:00
bc9f266ef0 nixos/containers: Remove workaround for systemd-nspawn@ drop-in 2024-06-20 23:37:43 +01:00
1b083d298b nixos/castle: Re-add boardie
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 32m55s
2024-06-18 23:29:48 +01:00
83ba26735e nixos/colony: Add extra disk to darts VM
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 6m28s
2024-06-15 20:05:27 +01:00
50bd96ccdf nixos/chatterbox: Add ffmpeg to mautrix bridges
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 32m8s
2024-06-10 13:27:02 +01:00
a133cfb189 nixos/installer: Use my nixpkgs
All checks were successful
CI / Check, build and cache Nix flake (push) Successful in 33m39s
2024-06-09 01:49:18 +01:00
051e68254e nixos/chatterbox: Add Instagram bridge 2024-06-09 01:46:00 +01:00
3fa8ab43ef nixos/chatterbox: Add Messenger bridge 2024-06-08 23:08:27 +01:00
c6720f87c1 nixos/chatterbox: Add WhatsApp bridge 2024-06-08 22:16:02 +01:00
140 changed files with 3593 additions and 1657 deletions

View File

@@ -6,11 +6,11 @@ on:
jobs: jobs:
check: check:
name: Check, build and cache Nix flake name: Check, build and cache nixfiles
runs-on: ubuntu-22.04 runs-on: ubuntu-22.04
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: cachix/install-nix-action@v23 - uses: cachix/install-nix-action@v27
with: with:
# Gitea will supply a token in GITHUB_TOKEN, which this action will # Gitea will supply a token in GITHUB_TOKEN, which this action will
# try to pass to Nix when downloading from GitHub # try to pass to Nix when downloading from GitHub
@@ -18,22 +18,30 @@ jobs:
extra_nix_config: | extra_nix_config: |
# Make sure we're using sandbox # Make sure we're using sandbox
sandbox-fallback = false sandbox-fallback = false
# Big C++ projects fill up memory...
cores = 6
extra-substituters = https://nix-cache.nul.ie/main extra-substituters = https://nix-cache.nul.ie
extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8= extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
- name: Set up attic
run: |
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}"
- name: Check flake - name: Check flake
run: nix flake check run: nix flake check --no-build
- name: Build the world
- name: Build (and cache) the world
id: build id: build
env:
HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }}
run: | run: |
path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out) nix eval --json --apply "builtins.attrNames" .#ci.x86_64-linux | jq -cr '.[]' | while read job; do
echo "path=$path" >> "$GITHUB_OUTPUT" echo "::group::Build $job"
- name: Push to cache nix build --no-link .#ci.x86_64-linux."$job"
run: | echo "::endgroup::"
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
push main ${{ steps.build.outputs.path }} echo "::group::Cache $job"
ci/push-to-cache.sh "$(nix eval --raw .#ci.x86_64-linux."$job")"
echo "::endgroup::"
done
echo "Building and caching CI derivation"
nix build --no-link .#ciDrv.x86_64-linux
UPDATE_PROFILE=1 ci/push-to-cache.sh "$(nix eval --raw .#ciDrv.x86_64-linux)"

View File

@@ -14,22 +14,20 @@ jobs:
uses: https://github.com/actions/setup-go@v4 uses: https://github.com/actions/setup-go@v4
with: with:
go-version: '>=1.20.1' go-version: '>=1.20.1'
- uses: cachix/install-nix-action@v23 - uses: cachix/install-nix-action@v27
with: with:
github_access_token: ${{ secrets.GH_PULL_TOKEN }} github_access_token: ${{ secrets.GH_PULL_TOKEN }}
extra_nix_config: | extra_nix_config: |
# Make sure we're using sandbox # Make sure we're using sandbox
sandbox-fallback = false sandbox-fallback = false
extra-substituters = https://nix-cache.nul.ie/main extra-substituters = https://nix-cache.nul.ie
extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8= extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
- name: Set up attic
- name: Set up vars
id: setup id: setup
run: | run: |
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}"
echo "short_rev=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT" echo "short_rev=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
- name: Build installer ISO - name: Build installer ISO
run: | run: |
nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso
@@ -39,12 +37,13 @@ jobs:
run: | run: |
nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive
ln -s "$(readlink result)" \ ln -s "$(readlink result)" \
jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst
- name: Create release - name: Create release
uses: https://gitea.com/actions/release-action@main uses: https://gitea.com/actions/release-action@main
with: with:
title: Latest installer title: Latest installer
api_key: '${{ secrets.RELEASE_TOKEN }}'
files: | files: |
jackos-installer-${{ steps.setup.outputs.short_rev }}.iso jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst

1
.keys/harmonia.pub Normal file
View File

@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXRXkYnBf2opIjN+bXE7HmhUpa4hyXJUGmBT+MRccT4 harmonia

1
ci/known_hosts Normal file
View File

@@ -0,0 +1 @@
object-ctr.ams1.int.nul.ie ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdHbZErWLmTPO/aEWB1Fup/aGMf31Un5Wk66FJwTz/8

31
ci/push-to-cache.sh Executable file
View File

@@ -0,0 +1,31 @@
#!/bin/sh
set -e
REMOTE_STORE=/var/lib/harmonia
SSH_HOST="harmonia@object-ctr.ams1.int.nul.ie"
SSH_KEY=/tmp/harmonia.key
STORE_URI="ssh-ng://$SSH_HOST?ssh-key=$SSH_KEY&remote-store=$REMOTE_STORE"
remote_cmd() {
ssh -i "$SSH_KEY" "$SSH_HOST" env HOME=/run/harmonia NIX_REMOTE="$REMOTE_STORE" "$@"
}
umask_old=$(umask)
umask 0066
echo "$HARMONIA_SSH_KEY" | base64 -d > "$SSH_KEY"
umask $umask_old
mkdir -p ~/.ssh
cp ci/known_hosts ~/.ssh/
path="$1"
echo "Pushing $path to cache..."
nix copy --no-check-sigs --to "$STORE_URI" "$path"
if [ -n "$UPDATE_PROFILE" ]; then
echo "Updating profile..."
remote_cmd nix-env -p "$REMOTE_STORE"/nix/var/nix/profiles/nixfiles --set "$path"
echo "Collecting garbage..."
remote_cmd nix-collect-garbage --delete-older-than 60d
fi

View File

@@ -77,7 +77,12 @@ in
name = "build-n-switch"; name = "build-n-switch";
category = "tasks"; category = "tasks";
help = "Shortcut to nixos-rebuild for this flake"; help = "Shortcut to nixos-rebuild for this flake";
command = ''doas nixos-rebuild --flake . "$@"''; command = ''
# HACK: Upstream changes in Git + Nix makes this necessary
# https://github.com/NixOS/nix/issues/10202
doas git config --global --add safe.directory "$PWD"
doas nixos-rebuild --flake . "$@"
'';
} }
{ {
name = "run-vm"; name = "run-vm";
@@ -106,8 +111,8 @@ in
{ {
name = "build-netboot"; name = "build-netboot";
category = "tasks"; category = "tasks";
help = "Build NixOS configuration as netboot archive"; help = "Build NixOS configuration as netboot tree";
command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootArchive"''; command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootTree"'';
} }
{ {
name = "build-home"; name = "build-home";
@@ -115,29 +120,17 @@ in
help = "Build home-manager configuration"; help = "Build home-manager configuration";
command = ''nix build "''${@:2}" ".#homeConfigurations.\"$1\".activationPackage"''; command = ''nix build "''${@:2}" ".#homeConfigurations.\"$1\".activationPackage"'';
} }
{
name = "update-inputs";
category = "tasks";
help = "Update flake inputs";
command = ''
args=()
for f in "$@"; do
args+=(--update-input "$f")
done
nix flake lock "''${args[@]}"
'';
}
{ {
name = "update-nixpkgs"; name = "update-nixpkgs";
category = "tasks"; category = "tasks";
help = "Update nixpkgs flake inputs"; help = "Update nixpkgs flake inputs";
command = ''update-inputs nixpkgs-{unstable,stable,mine,mine-stable}''; command = ''nix flake update nixpkgs-{unstable,stable,mine,mine-stable}'';
} }
{ {
name = "update-home-manager"; name = "update-home-manager";
category = "tasks"; category = "tasks";
help = "Update home-manager flake inputs"; help = "Update home-manager flake inputs";
command = ''update-inputs home-manager-{unstable,stable}''; command = ''nix flake update home-manager-{unstable,stable}'';
} }
{ {
name = "update-installer"; name = "update-installer";
@@ -145,5 +138,15 @@ in
help = "Update installer tag (to trigger new release)"; help = "Update installer tag (to trigger new release)";
command = ''git tag -f installer && git push -f origin installer''; command = ''git tag -f installer && git push -f origin installer'';
} }
{
name = "deploy-multi";
category = "tasks";
help = "Deploy multiple flakes at once";
command = ''
for f in $@; do
deploy "$O" $f
done
'';
}
]; ];
} }

View File

@@ -11,7 +11,7 @@ in
NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf" NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf"
'' ''
experimental-features = nix-command flakes ca-derivations repl-flake experimental-features = nix-command flakes ca-derivations
connect-timeout = 5 connect-timeout = 5
fallback = true fallback = true
${lib.my.c.nix.cache.conf} ${lib.my.c.nix.cache.conf}
@@ -24,10 +24,10 @@ in
coreutils coreutils
nixVersions.stable nixVersions.stable
rage rage
wireguard-tools
(pkgs.writeShellScriptBin "deploy" '' (pkgs.writeShellScriptBin "deploy" ''
exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@" exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@"
'') '')
home-manager home-manager
attic-client
]; ];
} }

440
flake.lock generated
View File

@@ -8,14 +8,14 @@
"ragenix", "ragenix",
"nixpkgs" "nixpkgs"
], ],
"systems": "systems_6" "systems": "systems_7"
}, },
"locked": { "locked": {
"lastModified": 1707830867, "lastModified": 1723293904,
"narHash": "sha256-PAdwm5QqdlwIqGrfzzvzZubM+FXtilekQ/FA0cI49/o=", "narHash": "sha256-b+uqzj+Wa6xgMS9aNbX4I+sXeb5biPDi39VgvSFqFvU=",
"owner": "ryantm", "owner": "ryantm",
"repo": "agenix", "repo": "agenix",
"rev": "8cb01a0e717311680e0cbca06a76cbceba6f3ed6", "rev": "f6291c5935fdc4e0bef208cfc0dcab7e3f7a1c41",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -24,69 +24,43 @@
"type": "github" "type": "github"
} }
}, },
"attic": {
"inputs": {
"crane": "crane",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils",
"nixpkgs": [
"nixpkgs-unstable"
],
"nixpkgs-stable": [
"nixpkgs-stable"
]
},
"locked": {
"lastModified": 1711742460,
"narHash": "sha256-0O4v6e4a1toxXZ2gf5INhg4WPE5C5T+SVvsBt+45Mcc=",
"owner": "zhaofengli",
"repo": "attic",
"rev": "4dbdbee45728d8ce5788db6461aaaa89d98081f0",
"type": "github"
},
"original": {
"owner": "zhaofengli",
"repo": "attic",
"type": "github"
}
},
"boardie": { "boardie": {
"inputs": { "inputs": {
"devshell": "devshell", "devshell": "devshell",
"flake-utils": "flake-utils_3", "flake-utils": "flake-utils_2",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
], ],
"poetry2nix": "poetry2nix" "poetry2nix": "poetry2nix"
}, },
"locked": { "locked": {
"lastModified": 1682289679, "lastModified": 1718746012,
"narHash": "sha256-DbhSJ6y62VAO2VsJwoz3VsxCEP/4KMeFVs0wIz6Im04=", "narHash": "sha256-sp9vGl3vWXvD/C2JeMDi5nbW6CkKIC3Q2JMGKwexYEs=",
"owner": "devplayer0", "ref": "refs/heads/master",
"repo": "boardie", "rev": "ea24100bd4a914b9e044a2085a3785a6bd3a3833",
"rev": "e4b977f75bf7b4f656a691efca492ae057672a77", "revCount": 5,
"type": "github" "type": "git",
"url": "https://git.nul.ie/dev/boardie"
}, },
"original": { "original": {
"owner": "devplayer0", "type": "git",
"repo": "boardie", "url": "https://git.nul.ie/dev/boardie"
"type": "github"
} }
}, },
"borgthin": { "borgthin": {
"inputs": { "inputs": {
"devshell": "devshell_2", "devshell": "devshell_2",
"flake-utils": "flake-utils_6", "flake-utils": "flake-utils_5",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-mine" "nixpkgs-mine"
] ]
}, },
"locked": { "locked": {
"lastModified": 1692446555, "lastModified": 1732994213,
"narHash": "sha256-Uzl8TiGKVBCjwYhkprSwbcu8xlcQwnDNIqsk9rM+P9w=", "narHash": "sha256-3v8cTsPB+TIdWmc1gmRNd0Mi0elpfi39CXRsA/2x/Oo=",
"owner": "devplayer0", "owner": "devplayer0",
"repo": "borg", "repo": "borg",
"rev": "44a3dc19b014ebc8d33db0b3e145ed7bfc9a0cb7", "rev": "795f5009445987d42f32de1b49fdeb2d88326a64",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -96,39 +70,12 @@
} }
}, },
"crane": { "crane": {
"inputs": {
"nixpkgs": [
"attic",
"nixpkgs"
]
},
"locked": { "locked": {
"lastModified": 1702918879, "lastModified": 1725409566,
"narHash": "sha256-tWJqzajIvYcaRWxn+cLUB9L9Pv4dQ3Bfit/YjU5ze3g=", "narHash": "sha256-PrtLmqhM6UtJP7v7IGyzjBFhbG4eOAHT6LPYOFmYfbk=",
"owner": "ipetkov", "owner": "ipetkov",
"repo": "crane", "repo": "crane",
"rev": "7195c00c272fdd92fc74e7d5a0a2844b9fadb2fb", "rev": "7e4586bad4e3f8f97a9271def747cf58c4b68f3c",
"type": "github"
},
"original": {
"owner": "ipetkov",
"repo": "crane",
"type": "github"
}
},
"crane_2": {
"inputs": {
"nixpkgs": [
"ragenix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1708794349,
"narHash": "sha256-jX+B1VGHT0ruHHL5RwS8L21R6miBn4B6s9iVyUJsJJY=",
"owner": "ipetkov",
"repo": "crane",
"rev": "2c94ff9a6fbeb9f3ea0107f28688edbe9c81deaa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -162,18 +109,18 @@
}, },
"deploy-rs": { "deploy-rs": {
"inputs": { "inputs": {
"flake-compat": "flake-compat_2", "flake-compat": "flake-compat",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
], ],
"utils": "utils" "utils": "utils"
}, },
"locked": { "locked": {
"lastModified": 1715699772, "lastModified": 1727447169,
"narHash": "sha256-sKhqIgucN5sI/7UQgBwsonzR4fONjfMr9OcHK/vPits=", "narHash": "sha256-3KyjMPUKHkiWhwR91J1YchF6zb6gvckCAY1jOE+ne0U=",
"owner": "serokell", "owner": "serokell",
"repo": "deploy-rs", "repo": "deploy-rs",
"rev": "b3ea6f333f9057b77efd9091119ba67089399ced", "rev": "aa07eb05537d4cd025e2310397a6adcedfe72c76",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -184,15 +131,15 @@
}, },
"devshell": { "devshell": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2", "flake-utils": "flake-utils",
"nixpkgs": "nixpkgs" "nixpkgs": "nixpkgs"
}, },
"locked": { "locked": {
"lastModified": 1678957337, "lastModified": 1717408969,
"narHash": "sha256-Gw4nVbuKRdTwPngeOZQOzH/IFowmz4LryMPDiJN/ah4=", "narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
"owner": "numtide", "owner": "numtide",
"repo": "devshell", "repo": "devshell",
"rev": "3e0e60ab37cd0bf7ab59888f5c32499d851edb47", "rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -203,7 +150,7 @@
}, },
"devshell-tools": { "devshell-tools": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_11", "flake-utils": "flake-utils_9",
"nixpkgs": "nixpkgs_4" "nixpkgs": "nixpkgs_4"
}, },
"locked": { "locked": {
@@ -222,7 +169,7 @@
}, },
"devshell_2": { "devshell_2": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_5", "flake-utils": "flake-utils_4",
"nixpkgs": "nixpkgs_3" "nixpkgs": "nixpkgs_3"
}, },
"locked": { "locked": {
@@ -241,17 +188,16 @@
}, },
"devshell_3": { "devshell_3": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_7",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
] ]
}, },
"locked": { "locked": {
"lastModified": 1713532798, "lastModified": 1728330715,
"narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=", "narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
"owner": "numtide", "owner": "numtide",
"repo": "devshell", "repo": "devshell",
"rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40", "rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -261,22 +207,6 @@
} }
}, },
"flake-compat": { "flake-compat": {
"flake": false,
"locked": {
"lastModified": 1673956053,
"narHash": "sha256-4gtG9iQuiKITOjNQQeQIpoIB6b16fm+504Ch3sNKLd8=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "35bb57c0c8d8b62bbfd284272c928ceb64ddbde9",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"type": "github"
}
},
"flake-compat_2": {
"flake": false, "flake": false,
"locked": { "locked": {
"lastModified": 1696426674, "lastModified": 1696426674,
@@ -293,12 +223,15 @@
} }
}, },
"flake-utils": { "flake-utils": {
"inputs": {
"systems": "systems"
},
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1701680307,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f", "rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -309,7 +242,7 @@
}, },
"flake-utils_10": { "flake-utils_10": {
"inputs": { "inputs": {
"systems": "systems_7" "systems": "systems_10"
}, },
"locked": { "locked": {
"lastModified": 1705309234, "lastModified": 1705309234,
@@ -326,42 +259,6 @@
} }
}, },
"flake-utils_11": { "flake-utils_11": {
"inputs": {
"systems": "systems_8"
},
"locked": {
"lastModified": 1709126324,
"narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "d465f4819400de7c8d874d50b982301f28a84605",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_12": {
"inputs": {
"systems": "systems_9"
},
"locked": {
"lastModified": 1705309234,
"narHash": "sha256-uNRRNRKmJyCRC/8y1RqBkqWBLM034y4qN7EprSdmgyA=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ef2e671c3b0c19053962c07dbda38332dcebf26",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_13": {
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
@@ -377,12 +274,15 @@
} }
}, },
"flake-utils_2": { "flake-utils_2": {
"inputs": {
"systems": "systems_2"
},
"locked": { "locked": {
"lastModified": 1642700792, "lastModified": 1710146030,
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "846b2ae0fc4cc943637d3d1def4454213e203cba", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -393,14 +293,14 @@
}, },
"flake-utils_3": { "flake-utils_3": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems_3"
}, },
"locked": { "locked": {
"lastModified": 1681202837, "lastModified": 1710146030,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=", "narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401", "rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -410,24 +310,6 @@
} }
}, },
"flake-utils_4": { "flake-utils_4": {
"inputs": {
"systems": "systems_2"
},
"locked": {
"lastModified": 1681202837,
"narHash": "sha256-H+Rh19JDwRtpVPAWp64F+rlEtxUWBAQW28eAi3SRSzg=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "cfacdce06f30d2b68473a46042957675eebb3401",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_5": {
"locked": { "locked": {
"lastModified": 1642700792, "lastModified": 1642700792,
"narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=", "narHash": "sha256-XqHrk7hFb+zBvRg6Ghl+AZDq03ov6OshJLiSWOoX5es=",
@@ -442,7 +324,7 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_6": { "flake-utils_5": {
"locked": { "locked": {
"lastModified": 1667395993, "lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=", "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
@@ -457,16 +339,31 @@
"type": "github" "type": "github"
} }
}, },
"flake-utils_7": { "flake-utils_6": {
"inputs": { "inputs": {
"systems": "systems_4" "systems": "systems_6"
}, },
"locked": { "locked": {
"lastModified": 1701680307, "lastModified": 1731533236,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=", "narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725", "rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_7": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -477,7 +374,7 @@
}, },
"flake-utils_8": { "flake-utils_8": {
"inputs": { "inputs": {
"systems": "systems_5" "systems": "systems_8"
}, },
"locked": { "locked": {
"lastModified": 1710146030, "lastModified": 1710146030,
@@ -494,12 +391,15 @@
} }
}, },
"flake-utils_9": { "flake-utils_9": {
"inputs": {
"systems": "systems_9"
},
"locked": { "locked": {
"lastModified": 1659877975, "lastModified": 1709126324,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=", "narHash": "sha256-q6EQdSeUZOG26WelxqkmR7kArjgWCdw5sfJVHPH/7j8=",
"owner": "numtide", "owner": "numtide",
"repo": "flake-utils", "repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0", "rev": "d465f4819400de7c8d874d50b982301f28a84605",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -537,16 +437,16 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1716729592, "lastModified": 1732466619,
"narHash": "sha256-Y3bOjoh2cFBqZN0Jw1zUdyr7tjygyxl2bD/QY73GZP0=", "narHash": "sha256-T1e5oceypZu3Q8vzICjv1X/sGs9XfJRMW5OuXHgpB3c=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "2c78a57c544dd19b07442350727ced097e1aa6e6", "rev": "f3111f62a23451114433888902a55cf0692b408d",
"type": "github" "type": "github"
}, },
"original": { "original": {
"id": "home-manager", "id": "home-manager",
"ref": "release-23.11", "ref": "release-24.11",
"type": "indirect" "type": "indirect"
} }
}, },
@@ -557,11 +457,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1717097707, "lastModified": 1732884235,
"narHash": "sha256-HC5vJ3oYsjwsCaSbkIPv80e4ebJpNvFKQTBOGlHvjLs=", "narHash": "sha256-r8j6R3nrvwbT1aUp4EPQ1KC7gm0pu9VcV1aNaB+XG6Q=",
"owner": "nix-community", "owner": "nix-community",
"repo": "home-manager", "repo": "home-manager",
"rev": "0eb314b4f0ba337e88123e0b1e57ef58346aafd9", "rev": "819f682269f4e002884702b87e445c82840c68f2",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -571,11 +471,11 @@
}, },
"impermanence": { "impermanence": {
"locked": { "locked": {
"lastModified": 1708968331, "lastModified": 1731242966,
"narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=", "narHash": "sha256-B3C3JLbGw0FtLSWCjBxU961gLNv+BOOBC6WvstKLYMw=",
"owner": "nix-community", "owner": "nix-community",
"repo": "impermanence", "repo": "impermanence",
"rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30", "rev": "3ed3f0eaae9fcc0a8331e77e9319c8a4abd8a71a",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -584,9 +484,31 @@
"type": "github" "type": "github"
} }
}, },
"nix-github-actions": {
"inputs": {
"nixpkgs": [
"boardie",
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1703863825,
"narHash": "sha256-rXwqjtwiGKJheXB43ybM8NwWB8rO2dSRrEqes0S7F5Y=",
"owner": "nix-community",
"repo": "nix-github-actions",
"rev": "5163432afc817cf8bd1f031418d1869e4c9d5547",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nix-github-actions",
"type": "github"
}
},
"nixGL": { "nixGL": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_9", "flake-utils": "flake-utils_7",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
] ]
@@ -607,11 +529,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1677383253, "lastModified": 1704161960,
"narHash": "sha256-UfpzWfSxkfXHnb4boXZNaKsAcUrZT9Hw+tao1oZxd08=", "narHash": "sha256-QGua89Pmq+FBAro8NriTuoO/wNaUtugt29/qqA8zeeM=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "9952d6bc395f5841262b006fbace8dd7e143b634", "rev": "63143ac2c9186be6d9da6035fa22620018c85932",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -623,11 +545,11 @@
}, },
"nixpkgs-mine": { "nixpkgs-mine": {
"locked": { "locked": {
"lastModified": 1717628902, "lastModified": 1732985787,
"narHash": "sha256-qMAW+oKis3F8jXTjX9Ng02/LzZd+7YOK05Qa33h9yqY=", "narHash": "sha256-6rSJ9L4QywpHLi/xvpOHdTuPm6/eOJcXxnYzDbP3U1k=",
"owner": "devplayer0", "owner": "devplayer0",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "3e0ee08114e1563b1a0fd6a907563b5e86258fb4", "rev": "a28c46933ef5038fb7a2dd483b85152a539c7969",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -639,11 +561,11 @@
}, },
"nixpkgs-mine-stable": { "nixpkgs-mine-stable": {
"locked": { "locked": {
"lastModified": 1717245305, "lastModified": 1732985894,
"narHash": "sha256-LrIS3+Aa4F2VmuJPQOASRd3W+uToj878PoUKSLVw/vE=", "narHash": "sha256-YYuQQCcSF6KjgtAenZJiBmqt5jqP3UvYgC424VQ+22s=",
"owner": "devplayer0", "owner": "devplayer0",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "17a50249712512f600eced89bebcc3252b5f630f", "rev": "e0a3f4e2bbc5f7b681e344b389dcbab23f2e92a8",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -655,26 +577,26 @@
}, },
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1716991068, "lastModified": 1732824227,
"narHash": "sha256-Av0UWCCiIGJxsZ6TFc+OiKCJNqwoxMNVYDBChmhjNpo=", "narHash": "sha256-fYNXgpu1AEeLyd3fQt4Ym0tcVP7cdJ8wRoqJ+CtTRyY=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "25cf937a30bf0801447f6bf544fc7486c6309234", "rev": "c71ad5c34d51dcbda4c15f44ea4e4aa6bb6ac1e9",
"type": "github" "type": "github"
}, },
"original": { "original": {
"id": "nixpkgs", "id": "nixpkgs",
"ref": "nixos-23.11", "ref": "nixos-24.11",
"type": "indirect" "type": "indirect"
} }
}, },
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1716948383, "lastModified": 1732758367,
"narHash": "sha256-SzDKxseEcHR5KzPXLwsemyTR/kaM9whxeiJohbL04rs=", "narHash": "sha256-RzaI1RO0UXqLjydtz3GAXSTzHkpb/lLD1JD8a0W4Wpo=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "ad57eef4ef0659193044870c731987a6df5cf56b", "rev": "fa42b5a5f401aab8a32bd33c9a4de0738180dc59",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -685,15 +607,16 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1681756206, "lastModified": 1718632497,
"narHash": "sha256-7B2Jc1zosXvZJKlxTPBlGew0LeX/7cxguG/d3syc1JI=", "narHash": "sha256-YtlyfqOdYMuu7gumZtK0Kg7jr4OKfHUhJkZfNUryw68=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "6eceb07c28016ec50dd683fda94995702b67e855", "rev": "c58b4a9118498c1055c5908a5bbe666e56abe949",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "NixOS", "owner": "NixOS",
"ref": "nixos-unstable-small",
"repo": "nixpkgs", "repo": "nixpkgs",
"type": "github" "type": "github"
} }
@@ -748,15 +671,18 @@
}, },
"poetry2nix": { "poetry2nix": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_4", "flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_2" "nix-github-actions": "nix-github-actions",
"nixpkgs": "nixpkgs_2",
"systems": "systems_4",
"treefmt-nix": "treefmt-nix"
}, },
"locked": { "locked": {
"lastModified": 1681532901, "lastModified": 1718726452,
"narHash": "sha256-9ZN/gaCOlkx53km4J2QkLQh4bS+6UCBsjdi87kw6+jc=", "narHash": "sha256-w4hJSYvACz0i5XHtxc6XNyHwbxpisN13M2kA2Y7937o=",
"owner": "nix-community", "owner": "nix-community",
"repo": "poetry2nix", "repo": "poetry2nix",
"rev": "2e66fd2623eccb3086e52929c2cefd882faac8a8", "rev": "53e534a08c0cd2a9fa7587ed1c3e7f6aeb804a2c",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -768,35 +694,35 @@
"ragenix": { "ragenix": {
"inputs": { "inputs": {
"agenix": "agenix", "agenix": "agenix",
"crane": "crane_2", "crane": "crane",
"flake-utils": "flake-utils_10", "flake-utils": "flake-utils_8",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
], ],
"rust-overlay": "rust-overlay" "rust-overlay": "rust-overlay"
}, },
"locked": { "locked": {
"lastModified": 1709831932, "lastModified": 1731774781,
"narHash": "sha256-WsP8rOFa/SqYNbVtYJ/l2mWWOgyDTJFbITMV8tv0biI=", "narHash": "sha256-vwsUUYOIs8J6weeSK1n1mbZf8fgvygGUMsadx0JmG70=",
"owner": "yaxitech", "owner": "devplayer0",
"repo": "ragenix", "repo": "ragenix",
"rev": "06de099ef02840ec463419f12de73729d458e1eb", "rev": "ec4115da7b67c783b1091811e17dbcba50edd1c6",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "yaxitech", "owner": "devplayer0",
"ref": "add-rekey-one-flag",
"repo": "ragenix", "repo": "ragenix",
"type": "github" "type": "github"
} }
}, },
"root": { "root": {
"inputs": { "inputs": {
"attic": "attic",
"boardie": "boardie", "boardie": "boardie",
"borgthin": "borgthin", "borgthin": "borgthin",
"deploy-rs": "deploy-rs", "deploy-rs": "deploy-rs",
"devshell": "devshell_3", "devshell": "devshell_3",
"flake-utils": "flake-utils_8", "flake-utils": "flake-utils_6",
"home-manager-stable": "home-manager-stable", "home-manager-stable": "home-manager-stable",
"home-manager-unstable": "home-manager-unstable", "home-manager-unstable": "home-manager-unstable",
"impermanence": "impermanence", "impermanence": "impermanence",
@@ -811,21 +737,17 @@
}, },
"rust-overlay": { "rust-overlay": {
"inputs": { "inputs": {
"flake-utils": [
"ragenix",
"flake-utils"
],
"nixpkgs": [ "nixpkgs": [
"ragenix", "ragenix",
"nixpkgs" "nixpkgs"
] ]
}, },
"locked": { "locked": {
"lastModified": 1708740535, "lastModified": 1725675754,
"narHash": "sha256-NCTw235XwSDbeTAtAwg/hOeNOgwYhVq7JjDdbkOgBeA=", "narHash": "sha256-hXW3csqePOcF2e/PYnpXj72KEYyNj2HzTrVNmS/F7Ug=",
"owner": "oxalica", "owner": "oxalica",
"repo": "rust-overlay", "repo": "rust-overlay",
"rev": "9b24383d77f598716fa0cbb8b48c97249f5ee1af", "rev": "8cc45e678e914a16c8e224c3237fb07cf21e5e54",
"type": "github" "type": "github"
}, },
"original": { "original": {
@@ -836,7 +758,7 @@
}, },
"sbt": { "sbt": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_13", "flake-utils": "flake-utils_11",
"nixpkgs": "nixpkgs_5" "nixpkgs": "nixpkgs_5"
}, },
"locked": { "locked": {
@@ -856,22 +778,22 @@
"sharry": { "sharry": {
"inputs": { "inputs": {
"devshell-tools": "devshell-tools", "devshell-tools": "devshell-tools",
"flake-utils": "flake-utils_12", "flake-utils": "flake-utils_10",
"nixpkgs": [ "nixpkgs": [
"nixpkgs-unstable" "nixpkgs-unstable"
], ],
"sbt": "sbt" "sbt": "sbt"
}, },
"locked": { "locked": {
"lastModified": 1710796573, "lastModified": 1720592125,
"narHash": "sha256-23fLZFNacZU/skc8i7JExHfD//Mpkslhga6f5ATTqBA=", "narHash": "sha256-vR89LefkY8mBPWxDTQ8SNg6Z7/J6Yga80T4kSb6MNdk=",
"owner": "devplayer0", "owner": "eikek",
"repo": "sharry", "repo": "sharry",
"rev": "4e7a87880ba0807afd5d21706ce383b8b8727990", "rev": "604b20517150599cb05dbe178cd35cd10659aa4c",
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "devplayer0", "owner": "eikek",
"repo": "sharry", "repo": "sharry",
"type": "github" "type": "github"
} }
@@ -891,6 +813,21 @@
"type": "github" "type": "github"
} }
}, },
"systems_10": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
},
"systems_2": { "systems_2": {
"locked": { "locked": {
"lastModified": 1681028828, "lastModified": 1681028828,
@@ -931,9 +868,8 @@
"type": "github" "type": "github"
}, },
"original": { "original": {
"owner": "nix-systems", "id": "systems",
"repo": "default", "type": "indirect"
"type": "github"
} }
}, },
"systems_5": { "systems_5": {
@@ -1011,9 +947,31 @@
"type": "github" "type": "github"
} }
}, },
"treefmt-nix": {
"inputs": {
"nixpkgs": [
"boardie",
"poetry2nix",
"nixpkgs"
]
},
"locked": {
"lastModified": 1718522839,
"narHash": "sha256-ULzoKzEaBOiLRtjeY3YoGFJMwWSKRYOic6VNw2UyTls=",
"owner": "numtide",
"repo": "treefmt-nix",
"rev": "68eb1dc333ce82d0ab0c0357363ea17c31ea1f81",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "treefmt-nix",
"type": "github"
}
},
"utils": { "utils": {
"inputs": { "inputs": {
"systems": "systems_3" "systems": "systems_5"
}, },
"locked": { "locked": {
"lastModified": 1701680307, "lastModified": 1701680307,

View File

@@ -7,37 +7,34 @@
devshell.inputs.nixpkgs.follows = "nixpkgs-unstable"; devshell.inputs.nixpkgs.follows = "nixpkgs-unstable";
nixpkgs-unstable.url = "nixpkgs/nixos-unstable"; nixpkgs-unstable.url = "nixpkgs/nixos-unstable";
nixpkgs-stable.url = "nixpkgs/nixos-23.11"; nixpkgs-stable.url = "nixpkgs/nixos-24.11";
nixpkgs-mine.url = "github:devplayer0/nixpkgs/devplayer0"; nixpkgs-mine.url = "github:devplayer0/nixpkgs/devplayer0";
nixpkgs-mine-stable.url = "github:devplayer0/nixpkgs/devplayer0-stable"; nixpkgs-mine-stable.url = "github:devplayer0/nixpkgs/devplayer0-stable";
home-manager-unstable.url = "home-manager"; home-manager-unstable.url = "home-manager";
home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable"; home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";
home-manager-stable.url = "home-manager/release-23.11"; home-manager-stable.url = "home-manager/release-24.11";
home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable"; home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
# Stuff used by the flake for build / deployment # Stuff used by the flake for build / deployment
ragenix.url = "github:yaxitech/ragenix"; # ragenix.url = "github:yaxitech/ragenix";
ragenix.url = "github:devplayer0/ragenix/add-rekey-one-flag";
ragenix.inputs.nixpkgs.follows = "nixpkgs-unstable"; ragenix.inputs.nixpkgs.follows = "nixpkgs-unstable";
deploy-rs.url = "github:serokell/deploy-rs"; deploy-rs.url = "github:serokell/deploy-rs";
deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable"; deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable";
# Stuff used by systems # Stuff used by systems
impermanence.url = "github:nix-community/impermanence"; impermanence.url = "github:nix-community/impermanence";
boardie.url = "github:devplayer0/boardie"; boardie.url = "git+https://git.nul.ie/dev/boardie";
boardie.inputs.nixpkgs.follows = "nixpkgs-unstable"; boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
nixGL.url = "github:nix-community/nixGL"; nixGL.url = "github:nix-community/nixGL";
nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable"; nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
# Packages not in nixpkgs # Packages not in nixpkgs
# sharry.url = "github:eikek/sharry"; sharry.url = "github:eikek/sharry";
sharry.url = "github:devplayer0/sharry";
sharry.inputs.nixpkgs.follows = "nixpkgs-unstable"; sharry.inputs.nixpkgs.follows = "nixpkgs-unstable";
borgthin.url = "github:devplayer0/borg"; borgthin.url = "github:devplayer0/borg";
borgthin.inputs.nixpkgs.follows = "nixpkgs-mine"; borgthin.inputs.nixpkgs.follows = "nixpkgs-mine";
attic.url = "github:zhaofengli/attic";
attic.inputs.nixpkgs.follows = "nixpkgs-unstable";
attic.inputs.nixpkgs-stable.follows = "nixpkgs-stable";
}; };
outputs = outputs =
@@ -52,7 +49,7 @@
... ...
}: }:
let let
inherit (builtins) mapAttrs replaceStrings; inherit (builtins) mapAttrs replaceStrings elem;
inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules; inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules;
inherit (lib.flake) flattenTree eachDefaultSystem; inherit (lib.flake) flattenTree eachDefaultSystem;
inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay; inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay;
@@ -96,7 +93,6 @@
inputs.ragenix.overlays.default inputs.ragenix.overlays.default
inputs.deploy-rs.overlay inputs.deploy-rs.overlay
(flakePackageOverlay inputs.home-manager-unstable system) (flakePackageOverlay inputs.home-manager-unstable system)
inputs.attic.overlays.default
]; ];
})) }))
pkgsFlakes; pkgsFlakes;
@@ -108,6 +104,16 @@
pkgsLibOverlay pkgsLibOverlay
myPkgsOverlay myPkgsOverlay
]; ];
config = {
# RMS forgive me...
# Normally this is set modularly, but sometimes we need to use other pkgs
allowUnfreePredicate = p: elem (lib.getName p) [
"widevine-cdm"
"chromium-unwrapped"
"chromium"
];
};
})) }))
pkgsFlakes; pkgsFlakes;
@@ -116,9 +122,9 @@
nixos/installer.nix nixos/installer.nix
nixos/boxes/colony nixos/boxes/colony
nixos/boxes/tower nixos/boxes/tower
nixos/boxes/castle
nixos/boxes/home/stream.nix nixos/boxes/home/stream.nix
nixos/boxes/home/palace nixos/boxes/home/palace
nixos/boxes/home/castle
nixos/boxes/britway nixos/boxes/britway
nixos/boxes/kelder nixos/boxes/kelder
@@ -198,8 +204,9 @@
systems' = mapAttrs' (n: v: nameValuePair "system-${n}" v) systems; systems' = mapAttrs' (n: v: nameValuePair "system-${n}" v) systems;
packages' = mapAttrs' (n: v: nameValuePair "package-${n}" v) packages; packages' = mapAttrs' (n: v: nameValuePair "package-${n}" v) packages;
in in
pkgs.linkFarm "ci" (homes' // systems' // packages' // { homes' // systems' // packages' // {
inherit shell; inherit shell;
}); };
ciDrv = pkgs.linkFarm "ci" ci;
})); }));
} }

View File

@@ -199,17 +199,20 @@ in
file file
tree tree
pwgen pwgen
minicom
iperf3 iperf3
mosh mosh
wget wget
hyx
whois whois
ldns ldns
minicom
mtr mtr
hyx
ncdu ncdu
jq jq
yq-go yq-go
nix-tree
]; ];
sessionVariables = { sessionVariables = {

View File

@@ -1,6 +1,6 @@
{ lib, pkgs, config, ... }: { lib, pkgs', pkgs, config, ... }:
let let
inherit (lib) genAttrs mkIf mkMerge mkForce; inherit (lib) genAttrs mkIf mkMerge mkForce mapAttrs mkOptionDefault;
inherit (lib.my) mkBoolOpt'; inherit (lib.my) mkBoolOpt';
cfg = config.my.gui; cfg = config.my.gui;
@@ -39,10 +39,11 @@ in
{ {
home = { home = {
packages = with pkgs; [ packages = with pkgs; [
xdg-utils
font.package font.package
(nerdfonts.override { nerd-fonts.sauce-code-pro
fonts = [ "DroidSansMono" "SourceCodePro" ]; nerd-fonts.droid-sans-mono
})
noto-fonts-emoji noto-fonts-emoji
grim grim
@@ -62,6 +63,8 @@ in
neofetch neofetch
cmatrix cmatrix
doomsaver doomsaver
xournalpp
]; ];
}; };
@@ -76,7 +79,7 @@ in
alacritty = { alacritty = {
enable = true; enable = true;
settings = { settings = {
import = [ ./alacritty-xterm.toml ]; general.import = [ ./alacritty-xterm.toml ];
font = { font = {
size = font.size; size = font.size;
@@ -92,9 +95,10 @@ in
enable = true; enable = true;
inherit font; inherit font;
settings = { settings = {
background_opacity = "0.8"; background_opacity = "0.65";
tab_bar_edge = "top"; tab_bar_edge = "top";
shell_integration = "no-sudo"; shell_integration = "no-sudo";
font_features = "${font.name} -liga";
}; };
}; };
@@ -160,6 +164,19 @@ in
}; };
Install.RequiredBy = [ "sway-session.target" ]; Install.RequiredBy = [ "sway-session.target" ];
}; };
activate-linux = {
Unit = {
Description = "Linux activation watermark";
After = "graphical-session.target";
PartOf = "graphical-session.target";
};
Service = {
Type = "simple";
ExecStart = "${pkgs.activate-linux}/bin/activate-linux";
};
Install.RequiredBy = [ "graphical-session.target" ];
};
}; };
}; };
@@ -169,6 +186,7 @@ in
wl-clipboard wl-clipboard
wev wev
wdisplays wdisplays
swaysome
pavucontrol pavucontrol
libsecret libsecret
@@ -178,10 +196,11 @@ in
]; ];
pointerCursor = { pointerCursor = {
package = pkgs.vanilla-dmz; package = pkgs.posy-cursors;
name = "Vanilla-DMZ"; name = "Posy_Cursor";
size = 16; size = 32;
gtk.enable = true; gtk.enable = true;
x11.enable = true;
}; };
}; };
@@ -190,9 +209,36 @@ in
xsession.preferStatusNotifierItems = true; xsession.preferStatusNotifierItems = true;
wayland = { wayland = {
windowManager = { windowManager = {
sway = { sway =
let
cfg = config.wayland.windowManager.sway.config;
mod = cfg.modifier;
renameWs = pkgs.writeShellScript "sway-rename-ws" ''
focused_ws="$(swaymsg -t get_workspaces | jq ".[] | select(.focused)")"
focused_num="$(jq -r ".num" <<< "$focused_ws")"
focused_name="$(jq -r ".name" <<< "$focused_ws")"
placeholder="$(sed -E 's/[0-9]+: //' <<< "$focused_name")"
name="$(rofi -dmenu -p "rename ws $focused_num" -theme+entry+placeholder "\"$placeholder\"")"
if [ -n "$name" ]; then
swaymsg rename workspace "$focused_name" to "$focused_num: $name"
fi
'';
clearWsName = pkgs.writeShellScript "sway-clear-ws-name" ''
focused_ws="$(swaymsg -t get_workspaces | jq ".[] | select(.focused)")"
focused_num="$(jq -r ".num" <<< "$focused_ws")"
focused_name="$(jq -r ".name" <<< "$focused_ws")"
swaymsg rename workspace "$focused_name" to "$focused_num"
'';
in
{
enable = true; enable = true;
xwayland = true; xwayland = true;
extraConfigEarly = ''
set $mod ${mod}
'';
config = { config = {
input = { input = {
"type:touchpad" = { "type:touchpad" = {
@@ -207,31 +253,95 @@ in
modifier = "Mod4"; modifier = "Mod4";
terminal = "kitty"; terminal = "kitty";
keybindings = keybindings = mapAttrs (k: mkOptionDefault) {
let "${mod}+Left" = "focus left";
cfg = config.wayland.windowManager.sway.config; "${mod}+Down" = "focus down";
mod = cfg.modifier; "${mod}+Up" = "focus up";
in "${mod}+Right" = "focus right";
lib.mkOptionDefault {
"${mod}+d" = null;
"${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
"${mod}+x" = "exec ${cfg.menu}";
"${mod}+Shift+x" = "exec rofi -show drun";
"${mod}+q" = "kill";
"${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'";
"${mod}+Shift+d" = ''exec grim - | swappy -f -'';
"${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -'';
"${mod}+Shift+e" = "exec rofi -show emoji";
# Config for this doesn't seem to work :/
"${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"'';
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5"; "${mod}+Shift+Left" = "move left";
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; "${mod}+Shift+Down" = "move down";
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play"; "${mod}+Shift+Up" = "move up";
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause"; "${mod}+Shift+Right" = "move right";
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous"; "${mod}+b" = "splith";
}; "${mod}+v" = "splitv";
"${mod}+f" = "fullscreen toggle";
"${mod}+a" = "focus parent";
"${mod}+s" = "layout stacking";
"${mod}+w" = "layout tabbed";
"${mod}+e" = "layout toggle split";
"${mod}+Shift+space" = "floating toggle";
"${mod}+space" = "focus mode_toggle";
"${mod}+1" = "workspace number 1";
"${mod}+2" = "workspace number 2";
"${mod}+3" = "workspace number 3";
"${mod}+4" = "workspace number 4";
"${mod}+5" = "workspace number 5";
"${mod}+6" = "workspace number 6";
"${mod}+7" = "workspace number 7";
"${mod}+8" = "workspace number 8";
"${mod}+9" = "workspace number 9";
"${mod}+0" = "workspace number 10";
"${mod}+Shift+1" =
"move container to workspace number 1";
"${mod}+Shift+2" =
"move container to workspace number 2";
"${mod}+Shift+3" =
"move container to workspace number 3";
"${mod}+Shift+4" =
"move container to workspace number 4";
"${mod}+Shift+5" =
"move container to workspace number 5";
"${mod}+Shift+6" =
"move container to workspace number 6";
"${mod}+Shift+7" =
"move container to workspace number 7";
"${mod}+Shift+8" =
"move container to workspace number 8";
"${mod}+Shift+9" =
"move container to workspace number 9";
"${mod}+Shift+0" =
"move container to workspace number 10";
"${mod}+Shift+minus" = "move scratchpad";
"${mod}+minus" = "scratchpad show";
"${mod}+Return" = "exec ${cfg.terminal}";
"${mod}+r" = "mode resize";
"${mod}+d" = null;
"${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
"${mod}+q" = "kill";
"${mod}+Shift+c" = "reload";
"${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'";
# rofi
"${mod}+x" = "exec ${cfg.menu}";
"${mod}+Shift+x" = "exec rofi -show drun";
"${mod}+Shift+e" = "exec rofi -show emoji";
# Config for this doesn't seem to work :/
"${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"'';
"${mod}+Shift+r" = "exec ${renameWs}";
"${mod}+Shift+n" = "exec ${clearWsName}";
# Screenshots
"${mod}+Shift+d" = ''exec grim - | swappy -f -'';
"${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -'';
"XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
"XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5";
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play";
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause";
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
};
keycodebindings = { keycodebindings = {
# keycode for XF86AudioPlayPause (no sym for some reason) # keycode for XF86AudioPlayPause (no sym for some reason)
"172" = "exec ${pkgs.playerctl}/bin/playerctl play-pause"; "172" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
@@ -240,6 +350,9 @@ in
menu = "rofi -show run"; menu = "rofi -show run";
bars = mkForce [ ]; bars = mkForce [ ];
}; };
extraConfig = ''
include ${./swaysome.conf}
'';
swaynag = { swaynag = {
enable = true; enable = true;
@@ -290,6 +403,7 @@ in
diff-so-fancy.enable = true; diff-so-fancy.enable = true;
userEmail = "jackos1998@gmail.com"; userEmail = "jackos1998@gmail.com";
userName = "Jack O'Sullivan"; userName = "Jack O'Sullivan";
lfs.enable = true;
extraConfig = { extraConfig = {
pull.rebase = true; pull.rebase = true;
}; };
@@ -297,11 +411,13 @@ in
waybar = import ./waybar.nix { inherit lib pkgs config font; }; waybar = import ./waybar.nix { inherit lib pkgs config font; };
rofi = { rofi = {
package = pkgs.rofi-wayland;
enable = true; enable = true;
font = "${font.name} ${toString font.size}"; font = "${font.name} ${toString font.size}";
plugins = with pkgs; [ plugins = with pkgs; (map (p: p.override { rofi-unwrapped = rofi-wayland-unwrapped; }) [
rofi-calc rofi-calc
rofi-emoji ]) ++ [
rofi-emoji-wayland
]; ];
extraConfig = { extraConfig = {
modes = "window,run,ssh,filebrowser,calc,emoji"; modes = "window,run,ssh,filebrowser,calc,emoji";
@@ -316,7 +432,7 @@ in
chromium = { chromium = {
enable = true; enable = true;
package = (pkgs.chromium.override { enableWideVine = true; }).overrideAttrs (old: { package = (pkgs'.unstable.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
buildCommand = '' buildCommand = ''
${old.buildCommand} ${old.buildCommand}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 249 KiB

After

Width:  |  Height:  |  Size: 251 KiB

View File

@@ -0,0 +1,66 @@
# Use (un)bindcode or (un)bindsym, depending on what you used in your main sway config file.
# The `--no-warn` setting is only added to shortcuts that exist in the default config. You may want to add or remove
# that flag on some bindings depending on your config.
# Change focus between workspaces
bindsym $mod+Alt+1 exec "swaysome focus 1"
bindsym $mod+Alt+2 exec "swaysome focus 2"
bindsym $mod+Alt+3 exec "swaysome focus 3"
bindsym $mod+Alt+4 exec "swaysome focus 4"
bindsym $mod+Alt+5 exec "swaysome focus 5"
bindsym $mod+Alt+6 exec "swaysome focus 6"
bindsym $mod+Alt+7 exec "swaysome focus 7"
bindsym $mod+Alt+8 exec "swaysome focus 8"
bindsym $mod+Alt+9 exec "swaysome focus 9"
bindsym $mod+Alt+0 exec "swaysome focus 0"
# Focus workspace groups
bindsym --no-warn $mod+1 exec "swaysome focus-group 1"
bindsym --no-warn $mod+2 exec "swaysome focus-group 2"
bindsym --no-warn $mod+3 exec "swaysome focus-group 3"
bindsym --no-warn $mod+4 exec "swaysome focus-group 4"
bindsym --no-warn $mod+5 exec "swaysome focus-group 5"
bindsym --no-warn $mod+6 exec "swaysome focus-group 6"
bindsym --no-warn $mod+7 exec "swaysome focus-group 7"
bindsym --no-warn $mod+8 exec "swaysome focus-group 8"
bindsym --no-warn $mod+9 exec "swaysome focus-group 9"
bindsym --no-warn $mod+0 exec "swaysome focus-group 0"
# Move containers between workspaces
bindsym $mod+Alt+Shift+1 exec "swaysome move 1"
bindsym $mod+Alt+Shift+2 exec "swaysome move 2"
bindsym $mod+Alt+Shift+3 exec "swaysome move 3"
bindsym $mod+Alt+Shift+4 exec "swaysome move 4"
bindsym $mod+Alt+Shift+5 exec "swaysome move 5"
bindsym $mod+Alt+Shift+6 exec "swaysome move 6"
bindsym $mod+Alt+Shift+7 exec "swaysome move 7"
bindsym $mod+Alt+Shift+8 exec "swaysome move 8"
bindsym $mod+Alt+Shift+9 exec "swaysome move 9"
bindsym $mod+Alt+Shift+0 exec "swaysome move 0"
# Move containers to other workspace groups
bindsym --no-warn $mod+Shift+1 exec "swaysome move-to-group 1"
bindsym --no-warn $mod+Shift+2 exec "swaysome move-to-group 2"
bindsym --no-warn $mod+Shift+3 exec "swaysome move-to-group 3"
bindsym --no-warn $mod+Shift+4 exec "swaysome move-to-group 4"
bindsym --no-warn $mod+Shift+5 exec "swaysome move-to-group 5"
bindsym --no-warn $mod+Shift+6 exec "swaysome move-to-group 6"
bindsym --no-warn $mod+Shift+7 exec "swaysome move-to-group 7"
bindsym --no-warn $mod+Shift+8 exec "swaysome move-to-group 8"
bindsym --no-warn $mod+Shift+9 exec "swaysome move-to-group 9"
bindsym --no-warn $mod+Shift+0 exec "swaysome move-to-group 0"
# Move focused container to next output
bindsym $mod+Alt+Right exec "swaysome next-output"
# Move focused container to previous output
bindsym $mod+Alt+Left exec "swaysome prev-output"
# Move focused workspace group to next output
bindsym $mod+Shift+Alt+Right exec "swaysome workspace-group-next-output"
# Move focused workspace group to previous output
bindsym $mod+Shift+Alt+Left exec "swaysome workspace-group-prev-output"
# Init workspaces for every screen
exec "swaysome init 1"

View File

@@ -27,7 +27,7 @@ rec {
kernel = { kernel = {
lts = pkgs: pkgs.linuxKernel.packages.linux_6_6; lts = pkgs: pkgs.linuxKernel.packages.linux_6_6;
latest = pkgs: pkgs.linuxKernel.packages.linux_6_9; latest = pkgs: pkgs.linuxKernel.packages.linux_6_12;
}; };
nginx = rec { nginx = rec {
@@ -98,10 +98,10 @@ rec {
nix = { nix = {
cache = rec { cache = rec {
substituters = [ substituters = [
"https://nix-cache.${pubDomain}/main" "https://nix-cache.${pubDomain}"
]; ];
keys = [ keys = [
"main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=" "nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4="
]; ];
conf = '' conf = ''
extra-substituters = ${concatStringsSep " " substituters} extra-substituters = ${concatStringsSep " " substituters}
@@ -111,7 +111,7 @@ rec {
}; };
pubDomain = "nul.ie"; pubDomain = "nul.ie";
colony = { colony = rec {
domain = "ams1.int.${pubDomain}"; domain = "ams1.int.${pubDomain}";
pubV4 = "94.142.240.44"; pubV4 = "94.142.240.44";
prefixes = with lib.my.net.cidr; rec { prefixes = with lib.my.net.cidr; rec {
@@ -135,6 +135,9 @@ rec {
v4 = subnet 8 3 all.v4; v4 = subnet 8 3 all.v4;
v6 = subnet 4 3 all.v6; v6 = subnet 4 3 all.v6;
}; };
qclk = {
v4 = subnet 8 4 all.v4;
};
cust = { cust = {
v4 = subnet 8 100 all.v4; # single ip for routing only v4 = subnet 8 100 all.v4; # single ip for routing only
@@ -148,6 +151,10 @@ rec {
v4 = "94.142.242.255/32"; v4 = "94.142.242.255/32";
v6 = subnet 8 1 cust.v6; v6 = subnet 8 1 cust.v6;
}; };
jam = {
v4 = subnet 8 4 cust.v4;
v6 = subnet 8 2 cust.v6;
};
vip1 = "94.142.241.224/30"; vip1 = "94.142.241.224/30";
vip2 = "94.142.242.254/31"; vip2 = "94.142.242.254/31";
@@ -160,6 +167,16 @@ rec {
home.v6 = "2a0e:97c0:4d0::/48"; home.v6 = "2a0e:97c0:4d0::/48";
}; };
custRouting = with lib.my.net.cidr; {
mail-vm = host 1 prefixes.cust.v4;
darts-vm = host 2 prefixes.cust.v4;
jam-ctr = host 3 prefixes.cust.v4;
};
qclk = {
wgPort = 51821;
};
firewallForwards = aa: [ firewallForwards = aa: [
{ {
port = "http"; port = "http";
@@ -173,6 +190,7 @@ rec {
port = 8448; port = 8448;
dst = aa.middleman.internal.ipv4.address; dst = aa.middleman.internal.ipv4.address;
} }
{ {
port = 25565; port = 25565;
dst = aa.simpcraft-oci.internal.ipv4.address; dst = aa.simpcraft-oci.internal.ipv4.address;
@@ -181,6 +199,7 @@ rec {
port = 25566; port = 25566;
dst = aa.simpcraft-staging-oci.internal.ipv4.address; dst = aa.simpcraft-staging-oci.internal.ipv4.address;
} }
{ {
port = 25575; port = 25575;
dst = aa.simpcraft-oci.internal.ipv4.address; dst = aa.simpcraft-oci.internal.ipv4.address;
@@ -208,6 +227,23 @@ rec {
dst = aa.simpcraft-oci.internal.ipv4.address; dst = aa.simpcraft-oci.internal.ipv4.address;
proto = "udp"; proto = "udp";
} }
{
port = 15636;
dst = aa.enshrouded-oci.internal.ipv4.address;
proto = "udp";
}
{
port = 15637;
dst = aa.enshrouded-oci.internal.ipv4.address;
proto = "udp";
}
{
port = qclk.wgPort;
dst = aa.qclk.internal.ipv4.address;
proto = "udp";
}
]; ];
fstrimConfig = { fstrimConfig = {
@@ -231,7 +267,7 @@ rec {
"stream" "stream"
]; ];
routersPubV4 = [ routersPubV4 = [
"109.255.252.125" "109.255.31.155"
"109.255.252.63" "109.255.252.63"
]; ];
@@ -281,6 +317,8 @@ rec {
v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6; v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6;
}; };
}; };
roceBootModules = [ "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" ];
}; };
britway = { britway = {
@@ -331,6 +369,7 @@ rec {
}; };
domain = "hentai.engineer"; domain = "hentai.engineer";
ipv4MTU = 1460;
vpn = { vpn = {
port = 51820; port = 51820;
}; };
@@ -344,6 +383,7 @@ rec {
deploy = ../.keys/deploy.pub; deploy = ../.keys/deploy.pub;
rsyncNet = ../.keys/zh2855.rsync.net.pub; rsyncNet = ../.keys/zh2855.rsync.net.pub;
mailcowAcme = ../.keys/mailcow-acme.pub; mailcowAcme = ../.keys/mailcow-acme.pub;
harmonia = ../.keys/harmonia.pub;
}; };
sshHostKeys = { sshHostKeys = {
mail-vm = ../.keys/mail-vm-host.pub; mail-vm = ../.keys/mail-vm-host.pub;

View File

@@ -5,7 +5,7 @@ let
genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types
mkOption mkOverride mkForce mkIf mergeEqualOption optional mkOption mkOverride mkForce mkIf mergeEqualOption optional
showWarnings concatStringsSep flatten unique optionalAttrs showWarnings concatStringsSep flatten unique optionalAttrs
mkBefore; mkBefore toLower;
inherit (lib.flake) defaultSystems; inherit (lib.flake) defaultSystems;
in in
rec { rec {
@@ -248,10 +248,37 @@ rec {
in in
{ {
trivial = prev.trivial // { trivial = prev.trivial // {
release = "24.06:u-${prev.trivial.release}"; release = "24.12:u-${prev.trivial.release}";
codeName = "Carbrain"; codeName = "Epic";
revisionWithDefault = default: self.rev or default; revisionWithDefault = default: self.rev or default;
versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}"; versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}";
}; };
}; };
netbootKeaClientClasses = { tftpIP, hostname, systems }:
let
testIPXE = "substring(option[user-class].hex, 0, 4) == 'iPXE'";
in
(mapAttrsToList (name: mac: {
name = "nixos-${name}";
test = "(${testIPXE}) and (hexstring(pkt4.mac, ':') == '${toLower mac}')";
next-server = tftpIP;
server-hostname = hostname;
boot-file-name = "http://${hostname}/systems/${name}/menu.ipxe";
}) systems) ++ [
{
name = "ipxe";
test = testIPXE;
next-server = tftpIP;
server-hostname = hostname;
boot-file-name = "http://${hostname}/boot.ipxe";
}
{
name = "efi-x86_64";
test = "option[client-system].hex == 0x0007";
next-server = tftpIP;
server-hostname = hostname;
boot-file-name = "ipxe-x86_64.efi";
}
];
} }

View File

@@ -106,7 +106,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = lib.my.c.colony.prefixes.all.v4; Destination = lib.my.c.colony.prefixes.all.v4;
Gateway = allAssignments.estuary.as211024.ipv4.address; Gateway = allAssignments.estuary.as211024.ipv4.address;
@@ -123,7 +123,7 @@ in
Table = "ts-extra"; Table = "ts-extra";
} }
]; ];
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ routingPolicyRules = [
{ {
IncomingInterface = "tailscale0"; IncomingInterface = "tailscale0";
To = lib.my.c.colony.prefixes.all.v6; To = lib.my.c.colony.prefixes.all.v6;

View File

@@ -80,7 +80,7 @@ in
}; };
}; };
"ts.${pubDomain}" = { "hs.${pubDomain}" = {
locations."/" = { locations."/" = {
proxyPass = "http://localhost:${toString config.services.headscale.port}"; proxyPass = "http://localhost:${toString config.services.headscale.port}";
proxyWebsockets = true; proxyWebsockets = true;

View File

@@ -5,18 +5,20 @@ let
inherit (lib.my.c.britway) prefixes domain; inherit (lib.my.c.britway) prefixes domain;
# Can't use overrideAttrs because we need to override `vendorHash` within `buildGoModule` # Can't use overrideAttrs because we need to override `vendorHash` within `buildGoModule`
headscale = pkgs.headscale.override { headscale' = (pkgs.headscale.override {
buildGoModule = args: pkgs.buildGoModule (args // rec { buildGoModule = args: pkgs.buildGoModule (args // rec {
version = "0.23.0-alpha2"; version = "0.23.0-alpha12";
src = pkgs.fetchFromGitHub { src = pkgs.fetchFromGitHub {
owner = "juanfont"; owner = "juanfont";
repo = "headscale"; repo = "headscale";
rev = "v${version}"; rev = "v${version}";
hash = "sha256-sz+uQyyq/5YYDe5I44x5x2nvd48swAhNlInB8KZYvDo="; hash = "sha256-kZZK0cXnFARxblSMz01TDcBbTorkHGAwGpR+a4/mYfU=";
}; };
vendorHash = "sha256-u9AmJguQ5dnJpfhOeLN43apvMHuraOrJhvlEIp9RoIc="; patches = [];
vendorHash = "sha256-EorT2AVwA3usly/LcNor6r5UIhLCdj3L4O4ilgTIC2o=";
doCheck = false;
}); });
}; });
advRoutes = concatStringsSep "," [ advRoutes = concatStringsSep "," [
lib.my.c.home.prefixes.all.v4 lib.my.c.home.prefixes.all.v4
@@ -39,19 +41,20 @@ in
services = { services = {
headscale = { headscale = {
enable = true; enable = true;
package = headscale;
settings = { settings = {
disable_check_updates = true; disable_check_updates = true;
unix_socket_permission = "0770"; unix_socket_permission = "0770";
server_url = "https://ts.${pubDomain}"; server_url = "https://hs.${pubDomain}";
db_type = "sqlite3"; database = {
db_path = "/var/lib/headscale/db.sqlite3"; type = "sqlite3";
sqlite.path = "/var/lib/headscale/db.sqlite3";
};
noise.private_key_path = "/var/lib/headscale/noise_private.key"; noise.private_key_path = "/var/lib/headscale/noise_private.key";
ip_prefixes = with lib.my.c.tailscale.prefix; [ v4 v6 ]; prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; };
dns_config = { dns = {
# Use IPs that will route inside the VPN to prevent interception # Use IPs that will route inside the VPN to prevent interception
# (e.g. DNS rebinding filtering) # (e.g. DNS rebinding filtering)
restricted_nameservers = { nameservers.split = {
"${domain}" = pubNameservers; "${domain}" = pubNameservers;
"${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [ "${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [
ipv4.address ipv6.address ipv4.address ipv6.address
@@ -65,7 +68,6 @@ in
}; };
magic_dns = true; magic_dns = true;
base_domain = "ts.${pubDomain}"; base_domain = "ts.${pubDomain}";
override_local_dns = false;
}; };
oidc = { oidc = {
only_start_if_oidc_is_available = true; only_start_if_oidc_is_available = true;
@@ -85,7 +87,7 @@ in
interfaceName = "tailscale0"; interfaceName = "tailscale0";
extraUpFlags = [ extraUpFlags = [
"--operator=${config.my.user.config.name}" "--operator=${config.my.user.config.name}"
"--login-server=https://ts.nul.ie" "--login-server=https://hs.nul.ie"
"--netfilter-mode=off" "--netfilter-mode=off"
"--advertise-exit-node" "--advertise-exit-node"
"--advertise-routes=${advRoutes}" "--advertise-routes=${advRoutes}"

View File

@@ -1,7 +1,7 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c.colony) domain prefixes firewallForwards; inherit (lib.my.c.colony) domain prefixes custRouting firewallForwards;
in in
{ {
imports = [ ./vms ]; imports = [ ./vms ];
@@ -252,10 +252,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
ipv6PrefixConfig.Prefix = prefixes.vms.v6; Prefix = prefixes.vms.v6;
} }
]; ];
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = prefixes.ctrs.v4; Destination = prefixes.ctrs.v4;
Gateway = allAssignments.shill.routing.ipv4.address; Gateway = allAssignments.shill.routing.ipv4.address;
@@ -264,10 +264,12 @@ in
Destination = prefixes.ctrs.v6; Destination = prefixes.ctrs.v6;
Gateway = allAssignments.shill.internal.ipv6.address; Gateway = allAssignments.shill.internal.ipv6.address;
} }
{ {
Destination = allAssignments.shill.internal.ipv4.address; Destination = allAssignments.shill.internal.ipv4.address;
Gateway = allAssignments.shill.routing.ipv4.address; Gateway = allAssignments.shill.routing.ipv4.address;
} }
{ {
Destination = lib.my.c.tailscale.prefix.v4; Destination = lib.my.c.tailscale.prefix.v4;
Gateway = allAssignments.shill.routing.ipv4.address; Gateway = allAssignments.shill.routing.ipv4.address;
@@ -276,6 +278,15 @@ in
Destination = lib.my.c.tailscale.prefix.v6; Destination = lib.my.c.tailscale.prefix.v6;
Gateway = allAssignments.shill.internal.ipv6.address; Gateway = allAssignments.shill.internal.ipv6.address;
} }
{
Destination = prefixes.qclk.v4;
Gateway = allAssignments.shill.routing.ipv4.address;
}
{
Destination = prefixes.jam.v6;
Gateway = allAssignments.shill.internal.ipv6.address;
}
{ {
Destination = prefixes.oci.v4; Destination = prefixes.oci.v4;
@@ -307,7 +318,7 @@ in
"90-vm-mail" = { "90-vm-mail" = {
matchConfig.Name = "vm-mail"; matchConfig.Name = "vm-mail";
address = [ address = [
(net.cidr.subnet 8 1 prefixes.cust.v4) "${custRouting.mail-vm}/32"
prefixes.mail.v6 prefixes.mail.v6
]; ];
networkConfig = { networkConfig = {
@@ -316,10 +327,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
ipv6PrefixConfig.Prefix = prefixes.mail.v6; Prefix = prefixes.mail.v6;
} }
]; ];
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = prefixes.mail.v4; Destination = prefixes.mail.v4;
Scope = "link"; Scope = "link";
@@ -330,7 +341,7 @@ in
"90-vm-darts" = { "90-vm-darts" = {
matchConfig.Name = "vm-darts"; matchConfig.Name = "vm-darts";
address = [ address = [
(net.cidr.subnet 8 2 prefixes.cust.v4) "${custRouting.darts-vm}/32"
prefixes.darts.v6 prefixes.darts.v6
]; ];
networkConfig = { networkConfig = {
@@ -339,10 +350,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
ipv6PrefixConfig.Prefix = prefixes.darts.v6; Prefix = prefixes.darts.v6;
} }
]; ];
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = prefixes.darts.v4; Destination = prefixes.darts.v4;
Scope = "link"; Scope = "link";

View File

@@ -29,6 +29,9 @@
}; };
in in
{ {
# Kernel Same-Page Merging to attempt memory usage reduction
hardware.ksm.enable = false;
systemd = { systemd = {
network = { network = {
links = { links = {
@@ -130,7 +133,8 @@
(vm.lvmDisk "media") (vm.lvmDisk "media")
(vm.lvmDisk "minio") (vm.lvmDisk "minio")
(vm.lvmDisk "nix-atticd") (vm.lvmDisk "nix-cache")
(vm.lvmDisk "jam")
]); ]);
}; };
@@ -209,6 +213,7 @@
drives = [ drives = [
(mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ]) (mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ])
(vm.lvmDisk' "media" "darts-media") (vm.lvmDisk' "media" "darts-media")
(vm.lvmDisk' "ext" "darts-ext")
]; ];
}; };
}; };

View File

@@ -164,11 +164,9 @@ in
}; };
wireguardPeers = [ wireguardPeers = [
{ {
wireguardPeerConfig = { PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E=";
PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E="; AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ];
AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ]; PersistentKeepalive = 25;
PersistentKeepalive = 25;
};
} }
]; ];
}; };
@@ -278,47 +276,51 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
ipv6PrefixConfig.Prefix = prefixes.base.v6; Prefix = prefixes.base.v6;
} }
]; ];
routes = map (r: { routeConfig = r; }) (flatten routes = flatten ([
([ {
{ Destination = prefixes.vip1;
Destination = prefixes.vip1; Gateway = allAssignments.colony.routing.ipv4.address;
Gateway = allAssignments.colony.routing.ipv4.address; }
} {
{ Destination = prefixes.vip3;
Destination = prefixes.vip3; Gateway = allAssignments.colony.routing.ipv4.address;
Gateway = allAssignments.colony.routing.ipv4.address; }
} {
{ Destination = prefixes.darts.v4;
Destination = prefixes.darts.v4; Gateway = allAssignments.colony.routing.ipv4.address;
Gateway = allAssignments.colony.routing.ipv4.address; }
} {
{ Destination = prefixes.cust.v6;
Destination = prefixes.cust.v6; Gateway = allAssignments.colony.internal.ipv6.address;
Gateway = allAssignments.colony.internal.ipv6.address; }
}
{ {
Destination = lib.my.c.tailscale.prefix.v4; Destination = lib.my.c.tailscale.prefix.v4;
Gateway = allAssignments.colony.routing.ipv4.address; Gateway = allAssignments.colony.routing.ipv4.address;
} }
{ {
Destination = lib.my.c.tailscale.prefix.v6; Destination = lib.my.c.tailscale.prefix.v6;
Gateway = allAssignments.colony.internal.ipv6.address; Gateway = allAssignments.colony.internal.ipv6.address;
} }
] ++
(map (pName: [ {
{ Destination = prefixes.qclk.v4;
Gateway = allAssignments.colony.routing.ipv4.address; Gateway = allAssignments.colony.routing.ipv4.address;
Destination = prefixes."${pName}".v4; }
} ] ++
{ (map (pName: [
Destination = prefixes."${pName}".v6; {
Gateway = allAssignments.colony.internal.ipv6.address; Gateway = allAssignments.colony.routing.ipv4.address;
} Destination = prefixes."${pName}".v4;
]) [ "vms" "ctrs" "oci" ]))); }
{
Destination = prefixes."${pName}".v6;
Gateway = allAssignments.colony.internal.ipv6.address;
}
]) [ "vms" "ctrs" "oci" ]));
} }
]; ];
@@ -327,7 +329,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = lib.my.c.home.prefixes.all.v4; Destination = lib.my.c.home.prefixes.all.v4;
Gateway = lib.my.c.home.vips.as211024.v4; Gateway = lib.my.c.home.vips.as211024.v4;
@@ -339,10 +341,8 @@ in
matchConfig.Name = "kelder"; matchConfig.Name = "kelder";
routes = [ routes = [
{ {
routeConfig = { Destination = allAssignments.kelder.estuary.ipv4.address;
Destination = allAssignments.kelder.estuary.ipv4.address; Scope = "link";
Scope = "link";
};
} }
]; ];
}; };
@@ -394,6 +394,9 @@ in
# Safe enough to allow all SSH # Safe enough to allow all SSH
tcp dport ssh accept tcp dport ssh accept
# jam-ctr forwards
ip daddr ${aa.shill.internal.ipv4.address} tcp dport 60022 accept
ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept
${matchInet "tcp dport { http, https } accept" "git"} ${matchInet "tcp dport { http, https } accept" "git"}
ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport { 25565, 25575 } accept
@@ -404,6 +407,7 @@ in
ip6 daddr ${aa.valheim-oci.internal.ipv6.address} udp dport { 2456-2457 } accept 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.waffletail.internal.ipv6.address} udp dport 41641 accept
ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} udp dport 25565 accept ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} udp dport 25565 accept
ip6 daddr ${aa.enshrouded-oci.internal.ipv6.address} udp dport { 15636-15637 } accept
return return
} }
chain filter-routing { chain filter-routing {

View File

@@ -2,7 +2,7 @@
let let
inherit (builtins) attrNames; inherit (builtins) attrNames;
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c.colony) prefixes; inherit (lib.my.c.colony) prefixes custRouting;
authZones = attrNames config.my.pdns.auth.bind.zones; authZones = attrNames config.my.pdns.auth.bind.zones;
in in
@@ -153,6 +153,7 @@ in
simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address} simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address}
simpcraft-staging IN A ${assignments.internal.ipv4.address} simpcraft-staging IN A ${assignments.internal.ipv4.address}
simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address} simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address}
enshrouded IN A ${assignments.internal.ipv4.address}
mail-vm IN A ${net.cidr.host 0 prefixes.mail.v4} mail-vm IN A ${net.cidr.host 0 prefixes.mail.v4}
mail-vm IN AAAA ${net.cidr.host 1 prefixes.mail.v6} mail-vm IN AAAA ${net.cidr.host 1 prefixes.mail.v6}
@@ -162,6 +163,10 @@ in
andrey-cust IN A ${allAssignments.kelder.estuary.ipv4.address} andrey-cust IN A ${allAssignments.kelder.estuary.ipv4.address}
jam-cust IN A ${net.cidr.host 0 prefixes.jam.v4}
jam-fwd IN A ${allAssignments.shill.internal.ipv4.address}
jam-cust IN AAAA ${net.cidr.host 1 prefixes.jam.v6}
$TTL 3 $TTL 3
_acme-challenge IN LUA TXT @@FILE@@ _acme-challenge IN LUA TXT @@FILE@@

View File

@@ -35,6 +35,11 @@ in
]; ];
url = "https://git.${pubDomain}"; url = "https://git.${pubDomain}";
tokenFile = config.age.secrets."gitea/actions-runner.env".path; tokenFile = config.age.secrets."gitea/actions-runner.env".path;
settings = {
runner = {
timeout = "8h";
};
};
}; };
}; };
}; };

View File

@@ -0,0 +1,105 @@
{ lib, pkgs, assignments, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c.colony) prefixes custRouting;
in
{
fileSystems = {
"/mnt/jam" = {
device = "/dev/disk/by-label/jam";
fsType = "ext4";
};
"/var/lib/machines/jam" = {
device = "/mnt/jam";
options = [ "bind" ];
};
};
systemd = {
nspawn = {
jam = {
enable = true;
execConfig = {
Boot = true;
PrivateUsers = "pick";
LinkJournal = false;
};
networkConfig = {
Private = true;
VirtualEthernet = true;
};
};
};
network.networks = {
"50-ve-jam" = {
matchConfig = {
Kind = "veth";
Name = "ve-jam";
};
address = [
custRouting.jam-ctr
prefixes.jam.v6
];
networkConfig = {
IPv6AcceptRA = false;
IPv6SendRA = true;
};
ipv6Prefixes = [
{
Prefix = prefixes.jam.v6;
}
];
routes = [
{
Destination = prefixes.jam.v4;
Scope = "link";
}
];
};
};
services = {
"systemd-nspawn@jam" = {
overrideStrategy = "asDropin";
serviceConfig = {
CPUQuota = "400%";
MemoryHigh = "infinity";
MemoryMax = "4G";
};
wantedBy = [ "machines.target" ];
};
};
};
my = {
firewall =
let
jamIP = net.cidr.host 0 prefixes.jam.v4;
in
{
nat.forwardPorts."${assignments.internal.ipv4.address}" = [
{
port = 60022;
dst = jamIP;
dstPort = "ssh";
}
];
extraRules = ''
table inet filter {
chain forward {
iifname { ve-jam } oifname vms accept
iifname vms oifname { ve-jam } accept
}
}
table inet nat {
chain postrouting {
ip saddr ${jamIP} snat to ${assignments.internal.ipv4.address}
}
}
'';
};
};
}

View File

@@ -24,7 +24,7 @@ in
configuration = { lib, pkgs, config, assignments, allAssignments, ... }: configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
let let
inherit (lib) mkMerge mkIf mkForce; inherit (lib) genAttrs mkMerge mkIf mkForce;
inherit (lib.my) networkdAssignment; inherit (lib.my) networkdAssignment;
in in
{ {
@@ -45,9 +45,22 @@ in
owner = "matrix-synapse"; owner = "matrix-synapse";
group = "matrix-synapse"; group = "matrix-synapse";
}; };
"chatterbox/syncv3.env" = { "chatterbox/doublepuppet.yaml" = {
owner = "matrix-syncv3"; owner = "matrix-synapse";
group = "matrix-syncv3"; group = "matrix-synapse";
};
"chatterbox/mautrix-whatsapp.env" = {
owner = "mautrix-whatsapp";
group = "mautrix-whatsapp";
};
"chatterbox/mautrix-messenger.env" = {
owner = "mautrix-meta-messenger";
group = "mautrix-meta";
};
"chatterbox/mautrix-instagram.env" = {
owner = "mautrix-meta-instagram";
group = "mautrix-meta";
}; };
}; };
}; };
@@ -59,29 +72,24 @@ in
users = with lib.my.c.ids; { users = with lib.my.c.ids; {
users = { users = {
matrix-syncv3 = { matrix-synapse.extraGroups = [
isSystemUser = true; "mautrix-whatsapp"
uid = uids.matrix-syncv3; ];
group = "matrix-syncv3";
};
};
groups = {
matrix-syncv3.gid = gids.matrix-syncv3;
}; };
groups = { };
}; };
systemd = { systemd = {
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal; network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
services = { services = { } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: {
matrix-sliding-sync.serviceConfig = { # ffmpeg needed to convert GIFs to video
# Needs to be able to read its secrets path = with pkgs; [ ffmpeg ];
DynamicUser = mkForce false; }));
User = "matrix-syncv3";
Group = "matrix-syncv3";
};
};
}; };
# TODO/FIXME: https://github.com/NixOS/nixpkgs/issues/336052
nixpkgs.config.permittedInsecurePackages = [ "olm-3.2.16" ];
services = { services = {
netdata.enable = true; netdata.enable = true;
matrix-synapse = { matrix-synapse = {
@@ -168,19 +176,11 @@ in
app_service_config_files = [ app_service_config_files = [
"/var/lib/heisenbridge/registration.yml" "/var/lib/heisenbridge/registration.yml"
config.age.secrets."chatterbox/doublepuppet.yaml".path
]; ];
}; };
}; };
matrix-sliding-sync = {
enable = true;
createDatabase = false;
environmentFile = config.age.secrets."chatterbox/syncv3.env".path;
settings = {
SYNCV3_BINDADDR = "[::]:8009";
SYNCV3_SERVER = "http://localhost:8008";
};
};
heisenbridge = { heisenbridge = {
enable = true; enable = true;
@@ -195,6 +195,144 @@ in
]; ];
}; };
}; };
mautrix-whatsapp = {
enable = true;
environmentFile = config.age.secrets."chatterbox/mautrix-whatsapp.env".path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = "nul.ie";
};
appservice = {
database = {
type = "postgres";
uri = "$MAU_WAPP_PSQL_URI";
};
id = "whatsapp2";
bot = {
username = "whatsapp2";
displayname = "WhatsApp Bridge Bot";
};
};
bridge = {
username_template = "wapp2_{{.}}";
displayname_template = "{{or .BusinessName .PushName .JID}} (WA)";
personal_filtering_spaces = true;
delivery_receipts = true;
allow_user_invite = true;
url_previews = true;
command_prefix = "!wa";
login_shared_secret_map."nul.ie" = "$MAU_WAPP_DOUBLE_PUPPET_TOKEN";
encryption = {
allow = true;
default = true;
require = true;
};
permissions = {
"@dev:nul.ie" = "admin";
};
};
};
};
mautrix-meta.instances = {
messenger = {
enable = true;
registerToSynapse = true;
dataDir = "mautrix-messenger";
environmentFile = config.age.secrets."chatterbox/mautrix-messenger.env".path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = "nul.ie";
};
appservice = {
database = {
type = "postgres";
uri = "$MAU_FBM_PSQL_URI";
};
id = "fbm2";
bot = {
username = "messenger2";
displayname = "Messenger Bridge Bot";
avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak";
};
};
network = {
mode = "messenger";
displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FBM)'';
};
bridge = {
username_template = "fbm2_{{.}}";
personal_filtering_spaces = true;
delivery_receipts = true;
management_room_text.welcome = "Hello, I'm a Messenger bridge bot.";
command_prefix = "!fbm";
login_shared_secret_map."nul.ie" = "$MAU_FBM_DOUBLE_PUPPET_TOKEN";
backfill = {
history_fetch_pages = 5;
};
encryption = {
allow = true;
default = true;
require = true;
};
permissions = {
"@dev:nul.ie" = "admin";
};
};
};
};
instagram = {
enable = true;
registerToSynapse = true;
dataDir = "mautrix-instagram";
environmentFile = config.age.secrets."chatterbox/mautrix-instagram.env".path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = "nul.ie";
};
appservice = {
database = {
type = "postgres";
uri = "$MAU_IG_PSQL_URI";
};
id = "instagram";
bot = {
username = "instagram";
displayname = "Instagram Bridge Bot";
avatar = "mxc://maunium.net/JxjlbZUlCPULEeHZSwleUXQv";
};
};
network = {
mode = "instagram";
displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (IG)'';
};
bridge = {
username_template = "ig_{{.}}";
personal_filtering_spaces = true;
delivery_receipts = true;
management_room_text.welcome = "Hello, I'm an Instagram bridge bot.";
command_prefix = "!ig";
login_shared_secret_map."nul.ie" = "$MAU_IG_DOUBLE_PUPPET_TOKEN";
backfill = {
history_fetch_pages = 5;
};
encryption = {
allow = true;
default = true;
require = true;
};
permissions = {
"@dev:nul.ie" = "admin";
};
};
};
};
};
}; };
} }
(mkIf config.my.build.isDevVM { (mkIf config.my.build.isDevVM {

View File

@@ -8,5 +8,6 @@
./object.nix ./object.nix
./toot.nix ./toot.nix
./waffletail.nix ./waffletail.nix
./qclk
]; ];
} }

View File

@@ -94,6 +94,14 @@ in
}; };
}; };
nixpkgs.config.permittedInsecurePackages = [
# FIXME: This is needed for Sonarr
"aspnetcore-runtime-wrapped-6.0.36"
"aspnetcore-runtime-6.0.36"
"dotnet-sdk-wrapped-6.0.428"
"dotnet-sdk-6.0.428"
];
services = { services = {
netdata.enable = true; netdata.enable = true;

View File

@@ -71,14 +71,12 @@ in
RouteTable = routeTable; RouteTable = routeTable;
}; };
wireguardPeers = [ wireguardPeers = [
# AirVPN NL
{ {
# AirVPN NL Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637";
wireguardPeerConfig = { PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637"; PresharedKeyFile = config.age.secrets."${pskFile}".path;
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; AllowedIPs = [ "0.0.0.0/0" "::/0" ];
PresharedKeyFile = config.age.secrets."${pskFile}".path;
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
};
} }
]; ];
}; };
@@ -94,7 +92,7 @@ in
matchConfig.Name = "vpn"; matchConfig.Name = "vpn";
address = [ "10.182.97.37/32" "fd7d:76ee:e68f:a993:735d:ef5e:6907:b122/128" ]; address = [ "10.182.97.37/32" "fd7d:76ee:e68f:a993:735d:ef5e:6907:b122/128" ];
dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ]; dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ];
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ routingPolicyRules = [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;

View File

@@ -239,6 +239,9 @@ in
]; ];
recommendedTlsSettings = true; recommendedTlsSettings = true;
recommendedBrotliSettings = true;
# Uh so nginx is hanging with zstd enabled... maybe let's not for now
# recommendedZstdSettings = true;
clientMaxBodySize = "0"; clientMaxBodySize = "0";
serverTokens = true; serverTokens = true;
resolver = { resolver = {

View File

@@ -2,7 +2,7 @@
let let
inherit (builtins) mapAttrs toJSON; inherit (builtins) mapAttrs toJSON;
inherit (lib) mkMerge mkDefault genAttrs flatten concatStringsSep; inherit (lib) mkMerge mkDefault genAttrs flatten concatStringsSep;
inherit (lib.my.c) pubDomain; inherit (lib.my.c) pubDomain home;
inherit (lib.my.c.nginx) proxyHeaders; inherit (lib.my.c.nginx) proxyHeaders;
inherit (config.networking) domain; inherit (config.networking) domain;
@@ -35,7 +35,6 @@ let
# For clients # For clients
(mkWellKnown "matrix/client" (toJSON { (mkWellKnown "matrix/client" (toJSON {
"m.homeserver".base_url = "https://matrix.nul.ie"; "m.homeserver".base_url = "https://matrix.nul.ie";
"org.matrix.msc3575.proxy".url = "https://matrix-syncv3.nul.ie";
})) }))
]; ];
}; };
@@ -145,7 +144,7 @@ in
"pass.${pubDomain}" = "pass.${pubDomain}" =
let let
upstream = "http://vaultwarden-ctr.${domain}"; upstream = "http://vaultwarden-ctr.${domain}:8080";
in in
{ {
locations = { locations = {
@@ -182,10 +181,6 @@ in
]; ];
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"matrix-syncv3.${pubDomain}" = {
locations."/".proxyPass = "http://chatterbox-ctr.${domain}:8009";
useACMEHost = pubDomain;
};
"element.${pubDomain}" = "element.${pubDomain}" =
let let
@@ -206,7 +201,8 @@ in
# Currently it seems like single quotes aren't escaped like they should be... # Currently it seems like single quotes aren't escaped like they should be...
conf = { conf = {
brand = "/dev/player0 Matrix"; brand = "/dev/player0 Matrix";
showLabsSettings = true; show_labs_settings = true;
default_country_code = "IE";
disable_guests = true; disable_guests = true;
default_server_config = { default_server_config = {
"m.homeserver" = { "m.homeserver" = {
@@ -214,9 +210,8 @@ in
server_name = "nul.ie"; server_name = "nul.ie";
}; };
}; };
roomDirectory.servers = [ room_directory.servers = [
"nul.ie" "nul.ie"
"netsoc.ie"
"matrix.org" "matrix.org"
]; ];
}; };
@@ -396,6 +391,28 @@ in
}; };
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"pront.${pubDomain}" = mkMerge [
{
locations."/" = mkMerge [
{
proxyPass = "http://stream-hi.${home.domain}:5000";
proxyWebsockets = true;
extraConfig = proxyHeaders;
}
(ssoLoc "generic")
];
locations."~* ^/webcam/(.*)" = mkMerge [
{
proxyPass = "http://stream-hi.${home.domain}:5050/$1$is_args$args";
extraConfig = proxyHeaders;
}
(ssoLoc "generic")
];
useACMEHost = pubDomain;
}
(ssoServer "generic")
];
}; };
minio = minio =
@@ -407,10 +424,13 @@ in
ignore_invalid_headers off; ignore_invalid_headers off;
''; '';
nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar\.\S+)$''; nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar.*|serve\/.+)$'';
nixCacheHeaders = '' nixCacheHeaders = ''
add_header Cache-Control $nix_cache_control; add_header Cache-Control $nix_cache_control;
add_header Expires $nix_expires; add_header Expires $nix_expires;
brotli on;
brotli_types application/x-nix-archive;
''; '';
in in
{ {
@@ -452,9 +472,11 @@ in
"nix-cache.${pubDomain}" = { "nix-cache.${pubDomain}" = {
locations = { locations = {
"/".proxyPass = "http://${host}:8069"; "/" = {
proxyPass = "http://${host}:5000";
};
"~ ${nixCacheableRegex}" = { "~ ${nixCacheableRegex}" = {
proxyPass = "http://${host}:8069"; proxyPass = "http://${host}:5000";
extraConfig = nixCacheHeaders; extraConfig = nixCacheHeaders;
}; };
}; };

View File

@@ -31,6 +31,13 @@ in
{ {
config = mkMerge [ config = mkMerge [
{ {
fileSystems = {
"/var/lib/harmonia" = {
device = "/mnt/nix-cache";
options = [ "bind" ];
};
};
my = { my = {
deploy.enable = false; deploy.enable = false;
server.enable = true; server.enable = true;
@@ -48,6 +55,7 @@ in
group = config.my.user.config.group; group = config.my.user.config.group;
}; };
"object/atticd.env" = {}; "object/atticd.env" = {};
"nix-cache.key" = {};
"object/hedgedoc.env" = {}; "object/hedgedoc.env" = {};
"object/wastebin.env" = {}; "object/wastebin.env" = {};
}; };
@@ -58,6 +66,7 @@ in
9000 9001 9000 9001
config.services.sharry.config.bind.port config.services.sharry.config.bind.port
8069 8069
5000
config.services.hedgedoc.settings.port config.services.hedgedoc.settings.port
8088 8088
]; ];
@@ -68,14 +77,26 @@ in
}; };
}; };
users = with lib.my.c.ids; let inherit (config.services.atticd) user group; in { users = with lib.my.c.ids; mkMerge [
users."${user}" = { (let inherit (config.services.atticd) user group; in {
isSystemUser = true; users."${user}" = {
uid = uids.atticd; isSystemUser = true;
group = group; uid = uids.atticd;
}; group = group;
groups."${user}".gid = gids.atticd; };
}; groups."${user}".gid = gids.atticd;
})
{
users = {
harmonia = {
shell = pkgs.bashInteractive;
openssh.authorizedKeys.keyFiles = [
lib.my.c.sshKeyFiles.harmonia
];
};
};
}
];
systemd = { systemd = {
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal; network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
@@ -93,7 +114,9 @@ in
MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie"; MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie";
}; };
}; };
sharry = awaitPostgres; sharry = awaitPostgres;
atticd = mkMerge [ atticd = mkMerge [
awaitPostgres awaitPostgres
{ {
@@ -104,6 +127,15 @@ in
}; };
} }
]; ];
harmonia = {
environment.NIX_REMOTE = "/var/lib/harmonia";
preStart = ''
${config.nix.package}/bin/nix store ping
'';
serviceConfig = {
StateDirectory = "harmonia";
};
};
}; };
}; };
@@ -183,8 +215,8 @@ in
}; };
atticd = { atticd = {
enable = true; enable = false;
credentialsFile = config.age.secrets."object/atticd.env".path; environmentFile = config.age.secrets."object/atticd.env".path;
settings = { settings = {
listen = "[::]:8069"; listen = "[::]:8069";
allowed-hosts = [ "nix-cache.${pubDomain}" ]; allowed-hosts = [ "nix-cache.${pubDomain}" ];
@@ -203,6 +235,14 @@ in
}; };
}; };
harmonia = {
enable = true;
signKeyPaths = [ config.age.secrets."nix-cache.key".path ];
settings = {
priority = 30;
};
};
hedgedoc = { hedgedoc = {
enable = true; enable = true;
environmentFile = config.age.secrets."object/hedgedoc.env".path; environmentFile = config.age.secrets."object/hedgedoc.env".path;

View File

@@ -0,0 +1,115 @@
{ lib, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c.colony) domain prefixes qclk;
in
{
nixos.systems.qclk = { config, ... }: {
system = "x86_64-linux";
nixpkgs = "mine";
rendered = config.configuration.config.my.asContainer;
assignments = {
internal = {
name = "qclk-ctr";
inherit domain;
ipv4.address = net.cidr.host 10 prefixes.ctrs.v4;
ipv6 = {
iid = "::a";
address = net.cidr.host 10 prefixes.ctrs.v6;
};
};
qclk = {
ipv4 = {
address = net.cidr.host 1 prefixes.qclk.v4;
gateway = null;
};
};
};
configuration = { lib, pkgs, config, assignments, ... }:
let
inherit (lib) concatStringsSep mkMerge mkIf mkForce;
inherit (lib.my) networkdAssignment;
apiPort = 8080;
instances = [
{
host = 2;
wgKey = "D7z1FhcdxpnrGCE0wBW5PZb5BKuhCu6tcZ/5ZaYxdwQ=";
}
];
ipFor = i: net.cidr.host i.host prefixes.qclk.v4;
in
{
config = {
environment = {
systemPackages = with pkgs; [
wireguard-tools
];
};
my = {
deploy.enable = false;
server.enable = true;
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIC1kcfvahYmSk8IJKaUIcGkhxf/8Yse2XnU7Qqgcglyq";
files = {
"qclk/wg.key" = {
group = "systemd-network";
mode = "440";
};
};
};
firewall = {
udp.allowed = [ qclk.wgPort ];
extraRules = ''
table inet filter {
chain input {
iifname management tcp dport ${toString apiPort} accept
}
chain forward {
iifname host0 oifname management ip saddr { ${concatStringsSep ", " lib.my.c.as211024.trusted.v4} } accept
}
}
table inet nat {
chain postrouting {
iifname host0 oifname management snat ip to ${assignments.qclk.ipv4.address}
}
}
'';
};
};
systemd = {
network = {
netdevs."30-management" = {
netdevConfig = {
Name = "management";
Kind = "wireguard";
};
wireguardConfig = {
PrivateKeyFile = config.age.secrets."qclk/wg.key".path;
ListenPort = qclk.wgPort;
};
wireguardPeers = map (i: {
PublicKey = i.wgKey;
AllowedIPs = [ (ipFor i) ];
}) instances;
};
networks = {
"30-container-host0" = networkdAssignment "host0" assignments.internal;
"30-management" = networkdAssignment "management" assignments.qclk;
};
};
};
services = { };
};
};
};
}

View File

@@ -83,7 +83,7 @@ in
DOMAIN = "https://pass.${lib.my.c.pubDomain}"; DOMAIN = "https://pass.${lib.my.c.pubDomain}";
ROCKET_ADDRESS = "::"; ROCKET_ADDRESS = "::";
ROCKET_PORT = 80; ROCKET_PORT = 8080;
SMTP_HOST = "mail.nul.ie"; SMTP_HOST = "mail.nul.ie";
SMTP_FROM = "pass@nul.ie"; SMTP_FROM = "pass@nul.ie";
@@ -99,6 +99,8 @@ in
}; };
borgbackup.jobs.vaultwarden = { borgbackup.jobs.vaultwarden = {
readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ];
paths = [ vwData ]; paths = [ vwData ];
repo = "zh2855@zh2855.rsync.net:borg/vaultwarden2"; repo = "zh2855@zh2855.rsync.net:borg/vaultwarden2";
doInit = true; doInit = true;

View File

@@ -86,7 +86,7 @@ in
interfaceName = "tailscale0"; interfaceName = "tailscale0";
extraUpFlags = [ extraUpFlags = [
"--operator=${config.my.user.config.name}" "--operator=${config.my.user.config.name}"
"--login-server=https://ts.nul.ie" "--login-server=https://hs.nul.ie"
"--netfilter-mode=off" "--netfilter-mode=off"
"--advertise-exit-node" "--advertise-exit-node"
"--advertise-routes=${advRoutes}" "--advertise-routes=${advRoutes}"

View File

@@ -49,7 +49,11 @@ in
inherit (lib.my) networkdAssignment; inherit (lib.my) networkdAssignment;
in in
{ {
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ]; imports = [
"${modulesPath}/profiles/qemu-guest.nix"
./containers-ext.nix
];
config = mkMerge [ config = mkMerge [
{ {
@@ -90,8 +94,8 @@ in
device = "/dev/disk/by-label/minio"; device = "/dev/disk/by-label/minio";
fsType = "xfs"; fsType = "xfs";
}; };
"/mnt/atticd" = { "/mnt/nix-cache" = {
device = "/dev/disk/by-label/atticd"; device = "/dev/disk/by-label/nix-cache";
fsType = "ext4"; fsType = "ext4";
}; };
}; };
@@ -136,10 +140,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
ipv6PrefixConfig.Prefix = prefixes.ctrs.v6; Prefix = prefixes.ctrs.v6;
} }
]; ];
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = lib.my.c.tailscale.prefix.v4; Destination = lib.my.c.tailscale.prefix.v4;
Gateway = allAssignments.waffletail.internal.ipv4.address; Gateway = allAssignments.waffletail.internal.ipv4.address;
@@ -148,6 +152,11 @@ in
Destination = lib.my.c.tailscale.prefix.v6; Destination = lib.my.c.tailscale.prefix.v6;
Gateway = allAssignments.waffletail.internal.ipv6.address; Gateway = allAssignments.waffletail.internal.ipv6.address;
} }
{
Destination = prefixes.qclk.v4;
Gateway = allAssignments.qclk.internal.ipv4.address;
}
]; ];
} }
]; ];
@@ -202,11 +211,12 @@ in
object = { object = {
bindMounts = { bindMounts = {
"/mnt/minio".readOnly = false; "/mnt/minio".readOnly = false;
"/mnt/atticd".readOnly = false; "/mnt/nix-cache".readOnly = false;
}; };
}; };
toot = {}; toot = {};
waffletail = {}; waffletail = {};
qclk = {};
}; };
in in
mkMerge [ mkMerge [

View File

@@ -52,6 +52,7 @@ in
valheim-oci = 2; valheim-oci = 2;
simpcraft-oci = 3; simpcraft-oci = 3;
simpcraft-staging-oci = 4; simpcraft-staging-oci = 4;
enshrouded-oci = 5;
}; };
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }: configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
@@ -66,6 +67,7 @@ in
./valheim.nix ./valheim.nix
./minecraft ./minecraft
# ./enshrouded.nix
]; ];
config = mkMerge [ config = mkMerge [

View File

@@ -0,0 +1,35 @@
{ lib, config, allAssignments, ... }:
let
inherit (lib) concatStringsSep;
inherit (lib.my) dockerNetAssignment;
in
{
config = {
virtualisation.oci-containers.containers = {
enshrouded = {
image = "sknnr/enshrouded-dedicated-server@sha256:f163e8ba9caa2115d8a0a7b16c3696968242fb6fba82706d9a77a882df083497";
environment = {
SERVER_NAME = "UWUshrouded";
# SERVER_IP = "::"; # no IPv6?? :(
TZ = "Europe/Dublin";
};
environmentFiles = [ config.age.secrets."whale2/enshrouded.env".path ];
volumes = [
"enshrouded:/home/steam/enshrouded/savegame"
];
extraOptions = [
''--network=colony:${dockerNetAssignment allAssignments "enshrouded-oci"}''
];
};
};
my = {
secrets.files = {
"whale2/enshrouded.env" = {};
};
};
};
}

View File

@@ -123,6 +123,7 @@ in
within = "12H"; within = "12H";
hourly = 48; hourly = 48;
}; };
readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ];
# Avoid Minecraft poking the files while we back up # Avoid Minecraft poking the files while we back up
preHook = rconCommand "save-off"; preHook = rconCommand "save-off";

View File

@@ -1,7 +1,8 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c.home) domain vlans prefixes; inherit (lib.my.c) networkd;
inherit (lib.my.c.home) domain vlans prefixes vips roceBootModules;
in in
{ {
nixos.systems.castle = { nixos.systems.castle = {
@@ -15,7 +16,7 @@ in
ipv4 = { ipv4 = {
address = net.cidr.host 40 prefixes.hi.v4; address = net.cidr.host 40 prefixes.hi.v4;
mask = 22; mask = 22;
gateway = null; gateway = vips.hi.v4;
}; };
ipv6 = { ipv6 = {
iid = "::3:1"; iid = "::3:1";
@@ -35,7 +36,7 @@ in
cpu = { cpu = {
amd.updateMicrocode = true; amd.updateMicrocode = true;
}; };
opengl.extraPackages = with pkgs; [ graphics.extraPackages = with pkgs; [
intel-media-driver intel-media-driver
]; ];
bluetooth.enable = true; bluetooth.enable = true;
@@ -47,7 +48,7 @@ in
timeout = 10; timeout = 10;
}; };
kernelPackages = lib.my.c.kernel.latest pkgs; kernelPackages = lib.my.c.kernel.latest pkgs;
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-amd" "dm-snapshot" ];
kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ]; kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ];
kernelPatches = [ kernelPatches = [
# { # {
@@ -57,27 +58,40 @@ in
# } # }
]; ];
initrd = { initrd = {
availableKernelModules = [ "thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" ]; availableKernelModules = [
"thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod"
"8021q"
] ++ roceBootModules;
systemd.network = {
netdevs = mkVLAN "lan-hi" vlans.hi;
networks = {
"10-et100g" = {
matchConfig.Name = "et100g";
vlan = [ "lan-hi" ];
linkConfig.RequiredForOnline = "no";
networkConfig = networkd.noL3;
};
"20-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
};
};
}; };
binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
}; };
fileSystems = { fileSystems = {
"/boot" = {
device = "/dev/disk/by-partuuid/8ce4248a-3ee4-f44f-801f-064a628b4d6e";
fsType = "vfat";
};
"/nix" = { "/nix" = {
device = "/dev/disk/by-partuuid/2da23a1d-2daf-d943-b91e-fc175f3dad07"; device = "/dev/nvmeof/nix";
fsType = "ext4"; fsType = "ext4";
}; };
"/persist" = { "/persist" = {
device = "/dev/disk/by-partuuid/f4c80d4f-a022-e941-b5d1-fe2e65e444b9"; device = "/dev/nvmeof/persist";
fsType = "ext4"; fsType = "ext4";
neededForBoot = true; neededForBoot = true;
}; };
"/home" = { "/home" = {
device = "/dev/disk/by-partuuid/992a93cf-6c9c-324b-b0ce-f8eb2d1ce10d"; device = "/dev/nvmeof/home";
fsType = "ext4"; fsType = "ext4";
}; };
}; };
@@ -120,7 +134,7 @@ in
virtualisation.libvirtd.enable = true; virtualisation.libvirtd.enable = true;
networking = { networking = {
domain = "h.${lib.my.c.pubDomain}"; inherit domain;
firewall.enable = false; firewall.enable = false;
}; };
@@ -140,11 +154,14 @@ in
nix = { nix = {
gc.automatic = false; gc.automatic = false;
settings = {
experimental-features = [ "recursive-nix" ];
system-features = [ "nixos-test" "benchmark" "big-parallel" "kvm" "recursive-nix" ];
};
}; };
systemd = { systemd = {
network = { network = {
wait-online.enable = false;
netdevs = mkMerge [ netdevs = mkMerge [
(mkVLAN "lan-hi" vlans.hi) (mkVLAN "lan-hi" vlans.hi)
]; ];
@@ -161,29 +178,20 @@ in
matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a"; matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a";
linkConfig = { linkConfig = {
Name = "et100g"; Name = "et100g";
MTUBytes = "9000"; MTUBytes = toString lib.my.c.home.hiMTU;
}; };
}; };
}; };
networks = { networks = {
"50-lan" = { "30-et100g" = {
matchConfig.Name = "et2.5g";
DHCP = "no";
address = [ "10.16.7.1/16" ];
};
"50-et100g" = {
matchConfig.Name = "et100g"; matchConfig.Name = "et100g";
vlan = [ "lan-hi" ]; vlan = [ "lan-hi" ];
networkConfig.IPv6AcceptRA = false; networkConfig.IPv6AcceptRA = false;
}; };
"60-lan-hi" = mkMerge [ "40-lan-hi" = mkMerge [
(networkdAssignment "lan-hi" assignments.hi) (networkdAssignment "lan-hi" assignments.hi)
{ # So we don't drop the IP we use to connect to NVMe-oF!
DHCP = "yes"; { networkConfig.KeepConfiguration = "static"; }
matchConfig.Name = "lan-hi";
linkConfig.MTUBytes = "9000";
}
]; ];
}; };
}; };
@@ -203,10 +211,7 @@ in
packages = with pkgs; [ packages = with pkgs; [
jacktrip jacktrip
qpwgraph qpwgraph
# TODO: seems to be borked (infinite recursion???) boardie
# (writeShellScriptBin "boardie" ''
# exec pw-jack ${boardie}/bin/boardie "$@"
# '')
]; ];
}; };
@@ -220,6 +225,7 @@ in
HDMI-A-1 = { HDMI-A-1 = {
transform = "270"; transform = "270";
position = "0 0"; position = "0 0";
bg = "${./his-team-player.jpg} fill";
}; };
DP-1 = { DP-1 = {
mode = "2560x1440@170Hz"; mode = "2560x1440@170Hz";
@@ -241,11 +247,19 @@ in
}; };
#deploy.generate.system.mode = "boot"; #deploy.generate.system.mode = "boot";
deploy.node.hostname = "castle.box.${config.networking.domain}";
secrets = { secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlVuTzKObeaUuPocCF41IO/8X+443lzUJLuCIclt2vr"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlVuTzKObeaUuPocCF41IO/8X+443lzUJLuCIclt2vr";
}; };
nvme.uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b"; netboot.client = {
enable = true;
};
nvme = {
uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b";
boot = {
nqn = "nqn.2016-06.io.spdk:castle";
address = "192.168.68.80";
};
};
firewall = { firewall = {
enable = false; enable = false;

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 MiB

View File

@@ -94,7 +94,7 @@ in
extraOptions = [ "-A /var/log/smartd/" "--interval=600" ]; extraOptions = [ "-A /var/log/smartd/" "--interval=600" ];
}; };
udev.extraRules = '' udev.extraRules = ''
ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="3" ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="4"
''; '';
}; };
@@ -188,6 +188,13 @@ in
VLANId=${toString vlans.hi} VLANId=${toString vlans.hi}
LinkState=yes LinkState=yes
MACAddress=52:54:00:ac:15:a9 MACAddress=52:54:00:ac:15:a9
# sfh bridge
[SR-IOV]
VirtualFunction=3
VLANId=${toString vlans.hi}
LinkState=yes
MACAddress=52:54:00:90:34:95
''; '';
}; };
"60-lan-hi" = networkdAssignment "lan-hi" assignments.hi; "60-lan-hi" = networkdAssignment "lan-hi" assignments.hi;

View File

@@ -66,6 +66,7 @@ in
]; ];
services = { services = {
fstrim.enable = true;
netdata.enable = true; netdata.enable = true;
}; };

View File

@@ -129,6 +129,12 @@ in
hostnqn = hostnqn =
"nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b"; "nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b";
serial = "SPDK00000000000002"; serial = "SPDK00000000000002";
}) ++ (nvmfBdev {
bdev = "NVMeRaidp3";
nqn = "nqn.2016-06.io.spdk:sfh";
hostnqn =
"nqn.2014-08.org.nvmexpress:uuid:85d7df36-0de0-431b-b06e-51f7c0a455b4";
serial = "SPDK00000000000003";
}); });
}; };
}; };

View File

@@ -2,6 +2,7 @@
imports = [ imports = [
./cellar ./cellar
./river.nix ./river.nix
./sfh
]; ];
nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }: nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }:
@@ -57,11 +58,11 @@
systemd.services = systemd.services =
let let
awaitCellar = { awaitVM = system: {
after = [ "vm@cellar.service" ]; after = [ "vm@${system}.service" ];
bindsTo = [ "vm@cellar.service" ]; bindsTo = [ "vm@${system}.service" ];
preStart = '' preStart = ''
until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.cellar.hi.ipv4.address} 22; do until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.${system}.hi.ipv4.address} 22; do
sleep 1 sleep 1
done done
''; '';
@@ -81,13 +82,13 @@
vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device"; vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
in in
mkMerge [ mkMerge [
awaitCellar (awaitVM "cellar")
{ {
requires = [ vtapUnit ]; requires = [ vtapUnit ];
after = [ vtapUnit ]; after = [ vtapUnit ];
} }
]; ];
"vm@sfh" = awaitCellar; "vm@sfh" = (awaitVM "river");
}; };
my = { my = {
@@ -182,6 +183,10 @@
index = 0; index = 0;
hostBDF = "44:00.3"; hostBDF = "44:00.3";
}; };
et100g0vf3 = {
index = 1;
hostBDF = "44:00.4";
};
}; };
}; };
}; };

View File

@@ -10,18 +10,7 @@
let let
inherit (lib.my) networkdAssignment mkVLAN; inherit (lib.my) networkdAssignment mkVLAN;
inherit (lib.my.c) networkd; inherit (lib.my.c) networkd;
inherit (lib.my.c.home) vlans; inherit (lib.my.c.home) vlans domain prefixes roceBootModules;
lanLink = {
matchConfig = {
Driver = "mlx5_core";
PermanentMACAddress = "52:54:00:8a:8a:f2";
};
linkConfig = {
Name = "lan";
MTUBytes = toString lib.my.c.home.hiMTU;
};
};
in in
{ {
imports = [ imports = [
@@ -30,29 +19,17 @@
config = { config = {
boot = { boot = {
kernelModules = [ "kvm-intel" ]; kernelModules = [ "kvm-amd" ];
kernelParams = [ "console=ttyS0,115200n8" ]; kernelParams = [ "console=ttyS0,115200n8" ];
initrd = { initrd = {
availableKernelModules = [ availableKernelModules = [
"virtio_pci" "ahci" "sr_mod" "virtio_blk" "virtio_pci" "ahci" "sr_mod" "virtio_blk"
"ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" "8021q" "8021q"
"rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" ] ++ roceBootModules;
]; kernelModules = [ "dm-snapshot" ];
kernelModules = [ "dm-snapshot" "nvme-fabrics" ];
systemd = { systemd = {
extraBin = with pkgs; {
dmesg = "${util-linux}/bin/dmesg";
ip = "${iproute2}/bin/ip";
};
extraConfig = ''
DefaultTimeoutStartSec=50
DefaultDeviceTimeoutSec=50
'';
network = { network = {
enable = true; # Don't need to put the link config here, they're copied from main config
wait-online.enable = true;
links."10-lan" = lanLink;
netdevs = mkVLAN "lan-hi" vlans.hi; netdevs = mkVLAN "lan-hi" vlans.hi;
networks = { networks = {
"20-lan" = { "20-lan" = {
@@ -70,9 +47,6 @@
hardware = { hardware = {
enableRedistributableFirmware = true; enableRedistributableFirmware = true;
cpu = {
intel.updateMicrocode = true;
};
}; };
fileSystems = { fileSystems = {
@@ -96,6 +70,7 @@
boot.thin.enable = true; boot.thin.enable = true;
dmeventd.enable = true; dmeventd.enable = true;
}; };
fstrim.enable = true;
}; };
systemd.network = { systemd.network = {
@@ -114,7 +89,16 @@
}; };
}; };
"10-lan" = lanLink; "10-lan" = {
matchConfig = {
Driver = "mlx5_core";
PermanentMACAddress = "52:54:00:8a:8a:f2";
};
linkConfig = {
Name = "lan";
MTUBytes = toString lib.my.c.home.hiMTU;
};
};
}; };
# So we don't drop the IP we use to connect to NVMe-oF! # So we don't drop the IP we use to connect to NVMe-oF!
@@ -134,6 +118,14 @@
}; };
}; };
netboot.server = {
enable = true;
ip = assignments.lo.ipv4.address;
host = "boot.${domain}";
allowedPrefixes = with prefixes; [ hi.v4 hi.v6 lo.v4 lo.v6 ];
instances = [ "sfh" "castle" ];
};
deploy.node.hostname = "192.168.68.1"; deploy.node.hostname = "192.168.68.1";
}; };
}; };

View File

@@ -0,0 +1,5 @@
{
imports = [
./unifi.nix
];
}

View File

@@ -0,0 +1,65 @@
{ lib, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c.home) domain prefixes vips hiMTU;
in
{
nixos.systems.unifi = { config, ... }: {
system = "x86_64-linux";
nixpkgs = "mine";
rendered = config.configuration.config.my.asContainer;
assignments = {
hi = {
name = "unifi-ctr";
inherit domain;
mtu = hiMTU;
ipv4 = {
address = net.cidr.host 100 prefixes.hi.v4;
mask = 22;
gateway = vips.hi.v4;
};
ipv6 = {
iid = "::5:1";
address = net.cidr.host (65536*5+1) prefixes.hi.v6;
};
};
};
configuration = { lib, config, pkgs, assignments, ... }:
let
inherit (lib) mkMerge mkIf mkForce;
inherit (lib.my) networkdAssignment;
in
{
config = {
my = {
deploy.enable = false;
server.enable = true;
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKdgcziQki/RH7E+NH2bYnzSVKaJ27905Yo5TcOjSh/U";
files = { };
};
firewall = {
tcp.allowed = [ 8443 ];
};
};
systemd = {
network.networks."80-container-host0" = networkdAssignment "host0" assignments.hi;
};
services = {
unifi = {
enable = true;
openFirewall = true;
unifiPackage = pkgs.unifi8;
mongodbPackage = pkgs.mongodb-6_0;
};
};
};
};
};
}

View File

@@ -0,0 +1,157 @@
{ lib, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c.home) domain prefixes vips hiMTU roceBootModules;
in
{
imports = [ ./containers ];
config.nixos.systems.sfh = {
system = "x86_64-linux";
nixpkgs = "mine";
home-manager = "mine";
assignments = {
hi = {
inherit domain;
mtu = hiMTU;
ipv4 = {
address = net.cidr.host 81 prefixes.hi.v4;
mask = 22;
gateway = vips.hi.v4;
};
ipv6 = {
iid = "::4:2";
address = net.cidr.host (65536*4+2) prefixes.hi.v6;
};
};
};
configuration = { lib, modulesPath, pkgs, config, assignments, allAssignments, ... }:
let
inherit (lib) mapAttrs mkMerge;
inherit (lib.my) networkdAssignment;
inherit (lib.my.c) networkd;
inherit (lib.my.c.home) domain;
in
{
imports = [
"${modulesPath}/profiles/qemu-guest.nix"
];
config = {
boot = {
kernelModules = [ "kvm-amd" ];
kernelParams = [ "console=ttyS0,115200n8" ];
initrd = {
availableKernelModules = [
"virtio_pci" "ahci" "sr_mod" "virtio_blk"
] ++ roceBootModules;
kernelModules = [ "dm-snapshot" ];
systemd = {
network = {
networks = {
"20-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
};
};
};
};
};
hardware = {
enableRedistributableFirmware = true;
};
fileSystems = {
"/nix" = {
device = "/dev/main/nix";
fsType = "ext4";
};
"/persist" = {
device = "/dev/main/persist";
fsType = "ext4";
neededForBoot = true;
};
};
networking = { inherit domain; };
services = {
lvm = {
boot.thin.enable = true;
dmeventd.enable = true;
};
};
systemd.network = {
links = {
"10-lan-hi" = {
matchConfig = {
Driver = "mlx5_core";
PermanentMACAddress = "52:54:00:ac:15:a9";
};
linkConfig = {
Name = "lan-hi";
MTUBytes = toString lib.my.c.home.hiMTU;
};
};
"10-lan-hi-ctrs" = {
matchConfig = {
Driver = "mlx5_core";
PermanentMACAddress = "52:54:00:90:34:95";
};
linkConfig = {
Name = "lan-hi-ctrs";
MTUBytes = toString lib.my.c.home.hiMTU;
};
};
};
networks = {
"30-lan-hi" = mkMerge [
(networkdAssignment "lan-hi" assignments.hi)
# So we don't drop the IP we use to connect to NVMe-oF!
{ networkConfig.KeepConfiguration = "static"; }
];
"30-lan-hi-ctrs" = {
matchConfig.Name = "lan-hi-ctrs";
linkConfig.RequiredForOnline = "no";
networkConfig = networkd.noL3;
};
};
};
my = {
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAAaav5Se1E/AbqEXmADryVszYfNDscyP6jrWioN57R7";
};
server.enable = true;
netboot.client = {
enable = true;
};
nvme = {
uuid = "85d7df36-0de0-431b-b06e-51f7c0a455b4";
boot = {
nqn = "nqn.2016-06.io.spdk:sfh";
address = "192.168.68.80";
};
};
containers.instances =
let
instances = {
unifi = {};
};
in
mkMerge [
instances
(mapAttrs (n: i: {
networking.macVLAN = "lan-hi-ctrs";
}) instances)
];
};
};
};
};
}

View File

@@ -148,9 +148,11 @@ in
}; };
}; };
}; };
nginx.enable = true;
}; };
networking.domain = "h.${pubDomain}"; networking = { inherit domain; };
systemd.services = systemd.services =
let let
@@ -225,7 +227,7 @@ in
networkConfig = networkd.noL3; networkConfig = networkd.noL3;
extraConfig = '' extraConfig = ''
[CAKE] [CAKE]
Bandwidth=235M Bandwidth=490M
RTTSec=50ms RTTSec=50ms
PriorityQueueingPreset=besteffort PriorityQueueingPreset=besteffort
# DOCSIS preset # DOCSIS preset
@@ -249,7 +251,7 @@ in
extraConfig = '' extraConfig = ''
[CAKE] [CAKE]
Parent=root Parent=root
Bandwidth=24M Bandwidth=48M
RTTSec=50ms RTTSec=50ms
''; '';
} }
@@ -274,7 +276,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = lib.my.c.colony.prefixes.all.v4; Destination = lib.my.c.colony.prefixes.all.v4;
Gateway = allAssignments.estuary.as211024.ipv4.address; Gateway = allAssignments.estuary.as211024.ipv4.address;
@@ -299,7 +301,7 @@ in
{ {
"60-lan-hi" = { "60-lan-hi" = {
routes = map (r: { routeConfig = r; }) [ routes = [
{ {
Destination = elemAt routersPubV4 otherIndex; Destination = elemAt routersPubV4 otherIndex;
Gateway = net.cidr.host (otherIndex + 1) prefixes.hi.v4; Gateway = net.cidr.host (otherIndex + 1) prefixes.hi.v4;

View File

@@ -170,8 +170,9 @@ in
hostname = "${otherName}.${config.networking.domain}"; hostname = "${otherName}.${config.networking.domain}";
server = net.cidr.host (otherIndex + 1) prefixes.hi.v4; server = net.cidr.host (otherIndex + 1) prefixes.hi.v4;
}} }}
${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6} ${elemAt routers 0} IN AAAA ${allAssignments."${elemAt routers 0}".as211024.ipv6.address}
${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6} ${elemAt routers 1} IN AAAA ${allAssignments."${elemAt routers 1}".as211024.ipv6.address}
boot IN CNAME river-hi.${config.networking.domain}.
@ IN NS ns1 @ IN NS ns1
@ IN NS ns2 @ IN NS ns2
@@ -198,7 +199,7 @@ in
shytzel IN A ${net.cidr.host 12 prefixes.core.v4} shytzel IN A ${net.cidr.host 12 prefixes.core.v4}
wave IN A ${net.cidr.host 12 prefixes.hi.v4} wave IN A ${net.cidr.host 12 prefixes.hi.v4}
wave IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6} ; wave IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
vibe IN A ${net.cidr.host 13 prefixes.hi.v4} vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6} vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6}

View File

@@ -1,7 +1,7 @@
index: { lib, pkgs, assignments, ... }: index: { lib, pkgs, config, assignments, allAssignments, ... }:
let let
inherit (lib) mkForce; inherit (lib) mkForce;
inherit (lib.my) net; inherit (lib.my) net netbootKeaClientClasses;
inherit (lib.my.c.home) domain prefixes vips hiMTU; inherit (lib.my.c.home) domain prefixes vips hiMTU;
dns-servers = [ dns-servers = [
@@ -63,6 +63,14 @@ in
always-send = true; always-send = true;
} }
]; ];
client-classes = netbootKeaClientClasses {
tftpIP = allAssignments.river.lo.ipv4.address;
hostname = "boot.${domain}";
systems = {
sfh = "52:54:00:a5:7e:93";
castle = "c8:7f:54:6e:17:0f";
};
};
subnet4 = [ subnet4 = [
{ {
id = 1; id = 1;

View File

@@ -36,10 +36,6 @@ let
virtualRouterId = routerId; virtualRouterId = routerId;
virtualIps = vrrpIPs family; virtualIps = vrrpIPs family;
trackScripts = [ "${family}Alive" ]; trackScripts = [ "${family}Alive" ];
extraConfig = ''
notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root
notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root
'';
}; };
in in
{ {
@@ -66,7 +62,12 @@ in
}; };
vrrpInstances = { vrrpInstances = {
v4 = mkVRRP "v4" 51; v4 = mkVRRP "v4" 51;
v6 = mkVRRP "v6" 52; v6 = (mkVRRP "v6" 52) // {
extraConfig = ''
notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root
notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root
'';
};
}; };
# Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken... # Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken...
# extraConfig = '' # extraConfig = ''

View File

@@ -43,6 +43,38 @@
}; };
}; };
services = {
mjpg-streamer = {
enable = true;
inputPlugin = "input_uvc.so";
outputPlugin = "output_http.so -w @www@ -n -p 5050";
};
octoprint = {
enable = true;
host = "::";
extraConfig = {
plugins = {
classicwebcam = {
snapshot = "/webcam/?action=snapshot";
stream = "/webcam/?action=stream";
streamRatio = "4:3";
};
};
serial = {
port = "/dev/ttyACM0";
baudrate = 115200;
};
temperature.profiles = [
{
bed = 60;
extruder = 215;
name = "PLA";
}
];
};
};
};
systemd.network = { systemd.network = {
netdevs = { netdevs = {
"25-lan" = { "25-lan" = {

View File

@@ -26,7 +26,7 @@ in
config = { config = {
# Hardware acceleration for Jellyfin # Hardware acceleration for Jellyfin
hardware.opengl = { hardware.graphics = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
vaapiIntel vaapiIntel
@@ -78,6 +78,14 @@ in
}; };
}; };
nixpkgs.config.permittedInsecurePackages = [
# FIXME: This is needed for Sonarr
"aspnetcore-runtime-wrapped-6.0.36"
"aspnetcore-runtime-6.0.36"
"dotnet-sdk-wrapped-6.0.428"
"dotnet-sdk-6.0.428"
];
services = { services = {
transmission = { transmission = {
enable = true; enable = true;

View File

@@ -2,6 +2,7 @@
let let
inherit (lib) mkMerge mkIf; inherit (lib) mkMerge mkIf;
inherit (lib.my) networkdAssignment; inherit (lib.my) networkdAssignment;
inherit (lib.my.c.kelder) ipv4MTU;
wg = { wg = {
keyFile = "kelder/acquisition/airvpn-privkey"; keyFile = "kelder/acquisition/airvpn-privkey";
@@ -72,14 +73,12 @@ in
RouteTable = routeTable; RouteTable = routeTable;
}; };
wireguardPeers = [ wireguardPeers = [
# AirVPN IE
{ {
# AirVPN IE Endpoint = "146.70.94.2:1637";
wireguardPeerConfig = { PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
Endpoint = "146.70.94.2:1637"; PresharedKeyFile = config.age.secrets."${pskFile}".path;
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; AllowedIPs = [ "0.0.0.0/0" "::/0" ];
PresharedKeyFile = config.age.secrets."${pskFile}".path;
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
};
} }
]; ];
}; };
@@ -89,13 +88,14 @@ in
(networkdAssignment "host0" assignments.internal) (networkdAssignment "host0" assignments.internal)
{ {
networkConfig.DNSDefaultRoute = false; networkConfig.DNSDefaultRoute = false;
linkConfig.MTUBytes = toString ipv4MTU;
} }
]; ];
"90-vpn" = with wg; { "90-vpn" = with wg; {
matchConfig.Name = "vpn"; matchConfig.Name = "vpn";
address = [ "10.161.170.28/32" "fd7d:76ee:e68f:a993:b12d:6d15:c80a:9516/128" ]; address = [ "10.161.170.28/32" "fd7d:76ee:e68f:a993:b12d:6d15:c80a:9516/128" ];
dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ]; dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ];
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ routingPolicyRules = [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;

View File

@@ -84,6 +84,7 @@ in
c c
]; ];
acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}"; acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}";
# This is kinda borked because Virgin Media filters DNS responses with local IPs...
localRedirect = to: '' localRedirect = to: ''
rewrite_by_lua_block { rewrite_by_lua_block {
if ngx.var.remote_addr == pub_ip then if ngx.var.remote_addr == pub_ip then
@@ -103,7 +104,7 @@ in
"monitor.${domain}" = withAuth { "monitor.${domain}" = withAuth {
serverAliases = [ "monitor-local.${domain}" ]; serverAliases = [ "monitor-local.${domain}" ];
extraConfig = localRedirect "monitor-local.${domain}"; # extraConfig = localRedirect "monitor-local.${domain}";
locations = { locations = {
"/" = { "/" = {
proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999"; proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999";
@@ -136,17 +137,17 @@ in
}; };
"torrents.${domain}" = withAuth { "torrents.${domain}" = withAuth {
serverAliases = [ "torrents-local.${domain}" ]; serverAliases = [ "torrents-local.${domain}" ];
extraConfig = localRedirect "torrents-local.${domain}"; # extraConfig = localRedirect "torrents-local.${domain}";
locations."/".proxyPass = "${acquisition}:9091"; locations."/".proxyPass = "${acquisition}:9091";
}; };
"jackett.${domain}" = withAuth { "jackett.${domain}" = withAuth {
serverAliases = [ "jackett-local.${domain}" ]; serverAliases = [ "jackett-local.${domain}" ];
extraConfig = localRedirect "jackett-local.${domain}"; # extraConfig = localRedirect "jackett-local.${domain}";
locations."/".proxyPass = "${acquisition}:9117"; locations."/".proxyPass = "${acquisition}:9117";
}; };
"radarr.${domain}" = withAuth { "radarr.${domain}" = withAuth {
serverAliases = [ "radarr-local.${domain}" ]; serverAliases = [ "radarr-local.${domain}" ];
extraConfig = localRedirect "radarr-local.${domain}"; # extraConfig = localRedirect "radarr-local.${domain}";
locations."/" = { locations."/" = {
proxyPass = "${acquisition}:7878"; proxyPass = "${acquisition}:7878";
proxyWebsockets = true; proxyWebsockets = true;
@@ -155,7 +156,7 @@ in
}; };
"sonarr.${domain}" = withAuth { "sonarr.${domain}" = withAuth {
serverAliases = [ "sonarr-local.${domain}" ]; serverAliases = [ "sonarr-local.${domain}" ];
extraConfig = localRedirect "sonarr-local.${domain}"; # extraConfig = localRedirect "sonarr-local.${domain}";
locations."/" = { locations."/" = {
proxyPass = "${acquisition}:8989"; proxyPass = "${acquisition}:8989";
proxyWebsockets = true; proxyWebsockets = true;

View File

@@ -1,7 +1,7 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c.kelder) domain prefixes; inherit (lib.my.c.kelder) domain prefixes ipv4MTU;
in in
{ {
imports = [ ./containers ]; imports = [ ./containers ];
@@ -121,8 +121,7 @@ in
samba = { samba = {
enable = true; enable = true;
enableNmbd = true; settings = {
shares = {
storage = { storage = {
path = "/mnt/storage"; path = "/mnt/storage";
browseable = "yes"; browseable = "yes";
@@ -131,6 +130,8 @@ in
"directory mask" = "0775"; "directory mask" = "0775";
}; };
}; };
nmbd.enable = true;
}; };
samba-wsdd.enable = true; samba-wsdd.enable = true;
@@ -180,12 +181,10 @@ in
}; };
wireguardPeers = [ wireguardPeers = [
{ {
wireguardPeerConfig = { PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU="; Endpoint = "${allAssignments.estuary.internal.ipv4.address}:${toString lib.my.c.kelder.vpn.port}";
Endpoint = "estuary-vm.${lib.my.c.colony.domain}:${toString lib.my.c.kelder.vpn.port}"; AllowedIPs = [ "0.0.0.0/0" ];
AllowedIPs = [ "0.0.0.0/0" ]; PersistentKeepalive = 25;
PersistentKeepalive = 25;
};
} }
]; ];
}; };
@@ -200,6 +199,7 @@ in
"50-lan" = { "50-lan" = {
matchConfig.Name = "et1g0"; matchConfig.Name = "et1g0";
DHCP = "yes"; DHCP = "yes";
linkConfig.MTUBytes = toString ipv4MTU;
}; };
"80-ctrs" = mkMerge [ "80-ctrs" = mkMerge [
(networkdAssignment "ctrs" assignments.ctrs) (networkdAssignment "ctrs" assignments.ctrs)
@@ -212,7 +212,7 @@ in
address = with assignments.estuary; [ address = with assignments.estuary; [
(with ipv4; "${address}/${toString mask}") (with ipv4; "${address}/${toString mask}")
]; ];
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [ routingPolicyRules = [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;
@@ -272,7 +272,7 @@ in
config.name = "kontent"; config.name = "kontent";
}; };
#deploy.node.hostname = "10.16.9.21"; # deploy.node.hostname = "192.168.0.69";
secrets = { secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi";
files = { files = {

View File

@@ -14,7 +14,7 @@
cpu = { cpu = {
intel.updateMicrocode = true; intel.updateMicrocode = true;
}; };
opengl.extraPackages = with pkgs; [ graphics.extraPackages = with pkgs; [
intel-media-driver intel-media-driver
]; ];
bluetooth.enable = true; bluetooth.enable = true;
@@ -177,7 +177,7 @@
programs = { programs = {
fish = { fish = {
shellAbbrs = { shellAbbrs = {
tsup = "doas tailscale up --login-server=https://ts.nul.ie --accept-routes"; tsup = "doas tailscale up --login-server=https://hs.nul.ie --accept-routes";
}; };
}; };
}; };

View File

@@ -35,7 +35,7 @@ let
system = null; system = null;
# Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports # Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports
specialArgs = { inherit inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; }; specialArgs = { inherit self inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; };
# `baseModules` informs the manual which modules to document # `baseModules` informs the manual which modules to document
baseModules = baseModules =

View File

@@ -1,7 +1,7 @@
{ {
nixos.systems.installer = { config, ... }: { nixos.systems.installer = { config, ... }: {
system = "x86_64-linux"; system = "x86_64-linux";
nixpkgs = "unstable"; nixpkgs = "mine";
docCustom = false; docCustom = false;
rendered = config.configuration.config.my.asISO; rendered = config.configuration.config.my.asISO;
@@ -52,6 +52,8 @@
home.shellAliases = { home.shellAliases = {
show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT"; show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT";
}; };
my.gui.enable = false;
}; };
services = { services = {
@@ -59,8 +61,8 @@
}; };
networking = { networking = {
# Will be set dynamically # Will be set dynamically, but need something to satisfy `/etc/os-release` stuff
hostName = ""; hostName = "installer";
useNetworkd = false; useNetworkd = false;
}; };
@@ -80,6 +82,8 @@
${pkgs.gawk}/bin/awk '{ print $1 }')" ${pkgs.gawk}/bin/awk '{ print $1 }')"
''; '';
boot.supportedFilesystems.nfs = true;
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
dhcpcd dhcpcd
lm_sensors lm_sensors

View File

@@ -20,5 +20,6 @@
nvme = ./nvme; nvme = ./nvme;
spdk = ./spdk.nix; spdk = ./spdk.nix;
librespeed = ./librespeed; librespeed = ./librespeed;
netboot = ./netboot;
}; };
} }

View File

@@ -1,6 +1,6 @@
{ lib, pkgs, extendModules, modulesPath, options, config, ... }: { lib, pkgs, extendModules, modulesPath, options, config, ... }:
let let
inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge flatten optional; inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge mkForce flatten optional;
inherit (lib.my) mkBoolOpt' dummyOption; inherit (lib.my) mkBoolOpt' dummyOption;
cfg = config.my.build; cfg = config.my.build;
@@ -43,15 +43,145 @@ let
modules = flatten [ modules = flatten [
"${modulesPath}/installer/netboot/netboot.nix" "${modulesPath}/installer/netboot/netboot.nix"
allHardware allHardware
];
};
asNetboot = extendModules {
modules = flatten [
allHardware
({ pkgs, config, ... }: { ({ pkgs, config, ... }: {
system.build.netbootArchive = pkgs.runCommand "netboot-${config.system.name}-archive.tar" { } '' boot = {
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.kernel}" \ loader.grub.enable = false;
-f "$out" "${config.system.boot.loader.kernelFile}" initrd = {
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootRamdisk}" \ kernelModules = [ "nbd" ];
-f "$out" initrd availableKernelModules = [ "igb" "igc" ];
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootIpxeScript}" \
-f "$out" netboot.ipxe systemd = {
''; storePaths = with pkgs; [
gnused
nbd
netcat
];
extraBin = with pkgs; {
dmesg = "${util-linux}/bin/dmesg";
ip = "${iproute2}/bin/ip";
nbd-client = "${nbd}/bin/nbd-client";
};
extraConfig = ''
DefaultTimeoutStartSec=20
DefaultDeviceTimeoutSec=20
'';
network = {
enable = true;
wait-online.enable = true;
networks."10-netboot" = {
matchConfig.Name = "et-boot";
DHCP = "yes";
};
};
services = {
nbd = {
description = "NBD Root FS";
script = ''
get_cmdline() {
${pkgs.gnused}/bin/sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
}
s="$(get_cmdline nbd_server)"
until ${pkgs.netcat}/bin/nc -zv "$s" 22; do
sleep 0.1
done
exec ${pkgs.nbd}/bin/nbd-client -systemd-mark -N "$(get_cmdline nbd_export)" "$s" /dev/nbd0
'';
unitConfig = {
IgnoreOnIsolate = "yes";
DefaultDependencies = "no";
};
serviceConfig = {
Type = "forking";
Restart = "on-failure";
RestartSec = 10;
};
wantedBy = [ "initrd-root-device.target" ];
};
};
};
};
postBootCommands = ''
# After booting, register the contents of the Nix store
# in the Nix database in the COW root.
${config.nix.package}/bin/nix-store --load-db < /nix-path-registration
# nixos-rebuild also requires a "system" profile and an
# /etc/NIXOS tag.
touch /etc/NIXOS
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
'';
};
programs.nbd.enable = true;
fileSystems = {
"/" = {
fsType = "ext4";
device = "/dev/nbd0";
noCheck = true;
autoResize = true;
};
};
networking.useNetworkd = mkForce true;
systemd = {
network.networks."10-boot" = {
matchConfig.Name = "et-boot";
DHCP = "yes";
networkConfig.KeepConfiguration = "yes";
};
};
system.build = {
rootImage = pkgs.callPackage "${modulesPath}/../lib/make-ext4-fs.nix" {
storePaths = [ config.system.build.toplevel ];
volumeLabel = "netboot-root";
};
netbootScript = pkgs.writeText "boot.ipxe" ''
#!ipxe
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ifname=et-boot:''${mac} nbd_server=''${next-server} ${toString config.boot.kernelParams} ''${cmdline}
initrd initrd
boot
'';
netbootTree = pkgs.linkFarm "netboot-${config.system.name}" [
{
name = config.system.boot.loader.kernelFile;
path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
}
{
name = "initrd";
path = "${config.system.build.initialRamdisk}/initrd";
}
{
name = "rootfs.ext4";
path = config.system.build.rootImage;
}
{
name = "boot.ipxe";
path = config.system.build.netbootScript;
}
];
netbootArchive = pkgs.runCommand "netboot-${config.system.name}.tar.zst" { } ''
export PATH=${pkgs.zstd}/bin:$PATH
${pkgs.gnutar}/bin/tar --dereference --zstd -cvC ${config.system.build.netbootTree} -f "$out" .
'';
};
}) })
]; ];
}; };
@@ -77,6 +207,7 @@ in
asISO = mkAsOpt asISO "a bootable .iso image"; asISO = mkAsOpt asISO "a bootable .iso image";
asContainer = mkAsOpt asContainer "a container"; asContainer = mkAsOpt asContainer "a container";
asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd"; asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
asNetboot = mkAsOpt asNetboot "a netboot-able kernel initrd, and iPXE script";
buildAs = options.system.build; buildAs = options.system.build;
}; };
@@ -110,7 +241,8 @@ in
iso = config.my.asISO.config.system.build.isoImage; iso = config.my.asISO.config.system.build.isoImage;
container = config.my.asContainer.config.system.build.toplevel; container = config.my.asContainer.config.system.build.toplevel;
kexecTree = config.my.asKexecTree.config.system.build.kexecTree; kexecTree = config.my.asKexecTree.config.system.build.kexecTree;
netbootArchive = config.my.asKexecTree.config.system.build.netbootArchive; netbootTree = config.my.asNetboot.config.system.build.netbootTree;
netbootArchive = config.my.asNetboot.config.system.build.netbootArchive;
}; };
}; };
}; };

View File

@@ -1,4 +1,4 @@
{ lib, pkgsFlake, pkgs, pkgs', inputs, config, ... }: { lib, pkgsFlake, pkgs, pkgs', self, inputs, config, ... }:
let let
inherit (lib) mkIf mkDefault mkMerge; inherit (lib) mkIf mkDefault mkMerge;
inherit (lib.my) mkDefault'; inherit (lib.my) mkDefault';
@@ -12,7 +12,6 @@ in
inputs.impermanence.nixosModule inputs.impermanence.nixosModule
inputs.ragenix.nixosModules.age inputs.ragenix.nixosModules.age
inputs.sharry.nixosModules.default inputs.sharry.nixosModules.default
inputs.attic.nixosModules.atticd
]; ];
config = mkMerge [ config = mkMerge [
@@ -41,6 +40,7 @@ in
nix = { nix = {
package = pkgs'.mine.nix; package = pkgs'.mine.nix;
channel.enable = false;
settings = with lib.my.c.nix; { settings = with lib.my.c.nix; {
trusted-users = [ "@wheel" ]; trusted-users = [ "@wheel" ];
experimental-features = [ "nix-command" "flakes" "ca-derivations" ]; experimental-features = [ "nix-command" "flakes" "ca-derivations" ];
@@ -127,6 +127,9 @@ in
}; };
}; };
environment.etc = {
"nixos/flake.nix".source = "/run/nixfiles/flake.nix";
};
environment.systemPackages = with pkgs; mkMerge [ environment.systemPackages = with pkgs; mkMerge [
[ [
bash-completion bash-completion
@@ -142,7 +145,10 @@ in
fish.enable = mkDefault true; fish.enable = mkDefault true;
# TODO: This is expecting to look up the channel for the database... # TODO: This is expecting to look up the channel for the database...
command-not-found.enable = mkDefault false; command-not-found.enable = mkDefault false;
vim.defaultEditor = true; vim = {
enable = true;
defaultEditor = true;
};
}; };
services = { services = {
@@ -209,14 +215,35 @@ in
# python.d plugin script does #!/usr/bin/env bash # python.d plugin script does #!/usr/bin/env bash
path = with pkgs; [ bash ]; path = with pkgs; [ bash ];
}; };
nixfiles-mutable = {
description = "Mutable nixfiles";
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
path = with pkgs; [ util-linux ];
script = ''
nixfilesDir="${self}"
mkdir -p /run/nixfiles{,/.rw,/.work}
mount -t overlay overlay -o lowerdir="$nixfilesDir",upperdir=/run/nixfiles/.rw,workdir=/run/nixfiles/.work /run/nixfiles
chmod -R u+w /run/nixfiles
'';
preStop = ''
umount /run/nixfiles
rm -rf /run/nixfiles
'';
wantedBy = [ "multi-user.target" ];
};
}; };
}; };
} }
(mkIf config.services.kmscon.enable { (mkIf config.services.kmscon.enable {
fonts.fonts = with pkgs; [ fonts.fonts = with pkgs; [
(nerdfonts.override { nerd-fonts.sauce-code-pro
fonts = [ "SourceCodePro" ];
})
]; ];
}) })
]; ];

View File

@@ -1,6 +1,6 @@
{ lib, pkgs, options, config, systems, ... }: { lib, pkgs, options, config, systems, ... }:
let let
inherit (builtins) attrNames attrValues all hashString toJSON; inherit (builtins) attrNames attrValues all hashString toJSON any;
inherit (lib) inherit (lib)
groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge; groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge;
inherit (lib.my) mkOpt' mkBoolOpt'; inherit (lib.my) mkOpt' mkBoolOpt';
@@ -98,6 +98,7 @@ let
}; };
networking = { networking = {
bridge = mkOpt' (nullOr str) null "Network bridge to connect to."; bridge = mkOpt' (nullOr str) null "Network bridge to connect to.";
macVLAN = mkOpt' (nullOr str) null "Network interface to make MACVLAN interface from.";
}; };
}; };
}; };
@@ -115,26 +116,19 @@ in
assertion = config.systemd.network.enable; assertion = config.systemd.network.enable;
message = "Containers currently require systemd-networkd!"; message = "Containers currently require systemd-networkd!";
} }
{
assertion = all (i: i.networking.bridge == null || i.networking.macVLAN == null) (attrValues cfg.instances);
message = "Only bridge OR MACVLAN can be set";
}
]; ];
# TODO: Better security # TODO: Better security
my.firewall.trustedInterfaces = my.firewall.trustedInterfaces =
mapAttrsToList mapAttrsToList
(n: _: "ve-${n}") (n: _: "ve-${n}")
(filterAttrs (_: c: c.networking.bridge == null) cfg.instances); (filterAttrs (_: c: c.networking.bridge == null && c.networking.macVLAN == null) cfg.instances);
systemd = mkMerge ([ systemd = mkMerge (mapAttrsToList (n: c: {
{
# By symlinking to the original systemd-nspawn@.service for every instance we force the unit generator to
# create overrides instead of replacing the unit entirely
packages = [
(pkgs.linkFarm "systemd-nspawn-containers" (map (n: {
name = "etc/systemd/system/systemd-nspawn@${n}.service";
path = "${pkgs.systemd}/example/systemd/system/systemd-nspawn@.service";
}) (attrNames cfg.instances)))
];
}
] ++ (mapAttrsToList (n: c: {
nspawn."${n}" = { nspawn."${n}" = {
execConfig = { execConfig = {
Boot = true; Boot = true;
@@ -165,6 +159,8 @@ in
}; };
networkConfig = if (c.networking.bridge != null) then { networkConfig = if (c.networking.bridge != null) then {
Bridge = c.networking.bridge; Bridge = c.networking.bridge;
} else if (c.networking.macVLAN != null) then {
MACVLAN = "${c.networking.macVLAN}:host0";
} else { } else {
VirtualEthernet = true; VirtualEthernet = true;
}; };
@@ -182,6 +178,9 @@ in
c.containerSystem; c.containerSystem;
in in
{ {
# To prevent creating a whole new unit file
overrideStrategy = "asDropin";
environment = { environment = {
# systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths # systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths
root = "/run/machines/${n}"; root = "/run/machines/${n}";
@@ -247,7 +246,7 @@ in
Bridge = c.networking.bridge; Bridge = c.networking.bridge;
}; };
}; };
}) cfg.instances)); }) cfg.instances);
}) })
# Inside container # Inside container

View File

@@ -12,7 +12,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
hardware = { hardware = {
opengl.enable = mkDefault true; graphics.enable = mkDefault true;
}; };
systemd = { systemd = {
@@ -53,6 +53,8 @@ in
SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel" SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
# FT # FT
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel" SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel"
# /dev/player0
SUBSYSTEM=="usb", ATTR{idVendor}=="6969", MODE="0664", GROUP="wheel"
''; '';
}; };
}; };

View File

@@ -44,10 +44,8 @@ let
toString (mesh.baseMTU - overhead); toString (mesh.baseMTU - overhead);
bridgeFDBs = mapAttrsToList (n: peer: { bridgeFDBs = mapAttrsToList (n: peer: {
bridgeFDBConfig = { MACAddress = "00:00:00:00:00:00";
MACAddress = "00:00:00:00:00:00"; Destination = peer.addr;
Destination = peer.addr;
};
}) otherPeers; }) otherPeers;
}; };
}; };

View File

@@ -0,0 +1,232 @@
{ lib, pkgs, config, ... }:
let
inherit (lib) mkMerge mkIf mkForce genAttrs concatMapStringsSep;
inherit (lib.my) mkOpt' mkBoolOpt';
cfg = config.my.netboot;
ipxe = pkgs.ipxe.overrideAttrs (o: rec {
version = "1.21.1-unstable-2024-06-27";
src = pkgs.fetchFromGitHub {
owner = "ipxe";
repo = "ipxe";
rev = "b66e27d9b29a172a097c737ab4d378d60fe01b05";
hash = "sha256-TKZ4WjNV2oZIYNefch7E7m1JpeoC/d7O1kofoNv8G40=";
};
});
tftpRoot = pkgs.linkFarm "tftp-root" [
{
name = "ipxe-x86_64.efi";
path = "${ipxe}/ipxe.efi";
}
];
menuFile = pkgs.runCommand "menu.ipxe" {
bootHost = cfg.server.host;
} ''
substituteAll ${./menu.ipxe} "$out"
'';
bootBuilder = pkgs.substituteAll {
src = ./netboot-loader-builder.py;
isExecutable = true;
inherit (pkgs) python3;
bootspecTools = pkgs.bootspec;
nix = config.nix.package.out;
inherit (config.system.nixos) distroName;
systemName = config.system.name;
inherit (cfg.client) configurationLimit;
checkMountpoints = pkgs.writeShellScript "check-mountpoints" ''
if ! ${pkgs.util-linuxMinimal}/bin/findmnt /boot > /dev/null; then
echo "/boot is not a mounted partition. Is the path configured correctly?" >&2
exit 1
fi
'';
};
in
{
options.my.netboot = with lib.types; {
client = {
enable = mkBoolOpt' false "Whether network booting should be enabled.";
configurationLimit = mkOpt' ints.unsigned 10 "Max generations to show in boot menu.";
};
server = {
enable = mkBoolOpt' false "Whether a netboot server should be enabled.";
ip = mkOpt' str null "IP clients should connect to via TFTP.";
host = mkOpt' str config.networking.fqdn "Hostname clients should connect to over HTTP / NFS.";
allowedPrefixes = mkOpt' (listOf str) null "Prefixes clients should be allowed to connect from (NFS).";
installer = {
storeSize = mkOpt' str "16GiB" "Total allowed writable size of store.";
};
instances = mkOpt' (listOf str) [ ] "Systems to hold boot files for.";
};
};
config = mkMerge [
(mkIf cfg.client.enable {
systemd = {
services = {
mount-boot = {
description = "Mount /boot";
after = [ "systemd-networkd-wait-online.service" ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
};
path = with pkgs; [ gnused ldns nfs-utils ];
script = ''
get_cmdline() {
sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
}
host="$(get_cmdline boothost)"
if [ -z "$host" ]; then
echo "boothost kernel parameter not found!" >&2
exit 1
fi
until [ -n "$(drill -Q $host)" ]; do
sleep 0.1
done
mkdir -p /boot
mount.nfs $host:/srv/netboot/systems/${config.system.name} /boot
'';
wantedBy = [ "remote-fs.target" ];
};
};
};
boot.supportedFilesystems.nfs = true;
boot.loader = {
grub.enable = false;
systemd-boot.enable = false;
};
system = {
build.installBootLoader = bootBuilder;
boot.loader.id = "ipxe-netboot";
};
})
(mkIf cfg.server.enable {
environment = {
etc = {
"netboot/menu.ipxe".source = menuFile;
"netboot/shell.efi".source = "${pkgs.edk2-uefi-shell}/shell.efi";
};
};
systemd = {
tmpfiles.settings."10-netboot" = genAttrs
(map (i: "/srv/netboot/systems/${i}") cfg.server.instances)
(p: {
d = {
user = "root";
group = "root";
mode = "0777";
};
});
services = {
netboot-update = {
description = "Update netboot images";
after = [ "systemd-networkd-wait-online.service" ];
serviceConfig.Type = "oneshot";
path = with pkgs; [
coreutils curl jq zstd gnutar
];
script = ''
update_nixos() {
latestShort="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/tags/installer \
| jq -r .commit.sha | cut -c -7)"
if [ -f nixos-installer/tag.txt ] && [ "$(< nixos-installer/tag.txt)" = "$latestShort" ]; then
echo "NixOS installer is up to date"
return
fi
echo "Updating NixOS installer to $latestShort"
mkdir -p nixos-installer
fname="jackos-installer-netboot-$latestShort.tar.zst"
downloadUrl="$(curl -s https://git.nul.ie/api/v1/repos/dev/nixfiles/releases/tags/installer | \
jq -r ".assets[] | select(.name == \"$fname\").browser_download_url")"
curl -Lo /tmp/nixos-installer-netboot.tar.zst "$downloadUrl"
tar -C nixos-installer --zstd -xf /tmp/nixos-installer-netboot.tar.zst
truncate -s "${cfg.server.installer.storeSize}" nixos-installer/rootfs.ext4
rm /tmp/nixos-installer-netboot.tar.zst
echo "$latestShort" > nixos-installer/tag.txt
}
mkdir -p /srv/netboot
cd /srv/netboot
ln -sf ${menuFile} boot.ipxe
ln -sf "${pkgs.edk2-uefi-shell}/shell.efi" "efi-shell-${config.nixpkgs.localSystem.linuxArch}.efi"
update_nixos
'';
startAt = "06:00";
wantedBy = [ "network-online.target" ];
};
nbd-server = {
serviceConfig = {
PrivateUsers = mkForce false;
CacheDirectory = "netboot";
};
};
};
};
services = {
atftpd = {
enable = true;
root = tftpRoot;
};
nginx = {
virtualHosts."${cfg.server.host}" = {
locations."/" = {
root = "/srv/netboot";
extraConfig = ''
autoindex on;
'';
};
};
};
nbd.server = {
enable = true;
extraOptions = {
allowlist = true;
};
exports = {
nixos-installer = {
path = "/srv/netboot/nixos-installer/rootfs.ext4";
extraOptions = {
copyonwrite = true;
cowdir = "/var/cache/netboot";
sparse_cow = true;
};
};
};
};
nfs = {
server = {
enable = true;
exports = ''
/srv/netboot/systems ${concatMapStringsSep " " (p: "${p}(rw,all_squash)") cfg.server.allowedPrefixes}
'';
};
};
};
my = {
tmproot.persistence.config.directories = [
"/srv/netboot"
{ directory = "/var/cache/netboot"; mode = "0700"; }
];
};
})
];
}

View File

@@ -0,0 +1,68 @@
#!ipxe
set server http://@bootHost@
# Figure out if client is 64-bit capable
cpuid --ext 29 && set arch x86_64 || set arch i386
isset ${menu-default} || set menu-default exit
:start
menu Welcome to /dev/player0's humble iPXE boot menu
item --gap -- Operating Systems
iseq ${arch} x86_64 &&
item --key n nixos NixOS installer
# iseq ${arch} x86_64 &&
# item --key a archlinux Arch Linux (archiso x86_64)
# iseq ${arch} x86_64 &&
# item --key p alpine Alpine Linux
item --gap -- Other Options
item --key e efi_shell UEFI Shell
item --key x xyz netboot.xyz
item --key c config iPXE settings
item --key s shell Drop to iPXE shell
item --key r reboot Reboot
item --key q exit Exit (and continue to next boot device)
choose --timeout 0 --default ${menu-default} selected || goto cancel
goto ${selected}
:cancel
echo You cancelled the menu, dropping you to an iPXE shell
:shell
echo Type 'exit' to go back to the menu
shell
set menu-default nixos
goto start
:failed
echo Booting failed, dropping to shell
goto shell
:reboot
reboot
:exit
exit
:config
config
set menu-default config
goto start
:efi_shell
chain ${server}/efi-shell-${arch}.efi || goto failed
:xyz
chain --autofree https://boot.netboot.xyz || goto failed
:nixos
set cmdline nbd_export=nixos-installer
chain ${server}/nixos-installer/boot.ipxe || goto failed
:archlinux
# set mirrorurl https://arch.nul.ie/
chain ${server}/arch.ipxe || goto failed
:alpine
chain ${server}/alpine.ipxe || goto failed

View File

@@ -0,0 +1,280 @@
#! @python3@/bin/python3 -B
# Based on `nixos/modules/system/boot/loader/systemd-boot/systemd-boot-builder.py`
import argparse
import datetime
import glob
import os
import os.path
import shutil
import subprocess
import sys
import json
from typing import NamedTuple, Dict, List
from dataclasses import dataclass
BOOT_MOUNT_POINT = '/boot'
STORE_DIR = 'nix'
# These values will be replaced with actual values during the package build
BOOTSPEC_TOOLS = '@bootspecTools@'
NIX = '@nix@'
DISTRO_NAME = '@distroName@'
SYSTEM_NAME = '@systemName@'
CONFIGURATION_LIMIT = int('@configurationLimit@')
CHECK_MOUNTPOINTS = "@checkMountpoints@"
@dataclass
class BootSpec:
init: str
initrd: str
kernel: str
kernelParams: List[str]
label: str
system: str
toplevel: str
specialisations: Dict[str, 'BootSpec']
sortKey: str
initrdSecrets: str | None = None
class SystemIdentifier(NamedTuple):
profile: str | None
generation: int
specialisation: str | None
def copy_if_not_exists(source: str, dest: str) -> None:
if not os.path.exists(dest):
shutil.copyfile(source, dest)
def generation_dir(profile: str | None, generation: int) -> str:
if profile:
return f'/nix/var/nix/profiles/system-profiles/{profile}-{generation}-link'
else:
return f'/nix/var/nix/profiles/system-{generation}-link'
def system_dir(i: SystemIdentifier) -> str:
d = generation_dir(i.profile, i.generation)
if i.specialisation:
return os.path.join(d, 'specialisation', i.specialisation)
else:
return d
def entry_key(i: SystemIdentifier) -> str:
pieces = [
'nixos',
i.profile or None,
'generation',
str(i.generation),
f'specialisation-{i.specialisation}' if i.specialisation else None,
]
return '-'.join(p for p in pieces if p)
def bootspec_from_json(bootspec_json: Dict) -> BootSpec:
specialisations = bootspec_json['org.nixos.specialisation.v1']
specialisations = {k: bootspec_from_json(v) for k, v in specialisations.items()}
systemdBootExtension = bootspec_json.get('org.nixos.systemd-boot', {})
sortKey = systemdBootExtension.get('sortKey', 'nixos')
return BootSpec(
**bootspec_json['org.nixos.bootspec.v1'],
specialisations=specialisations,
sortKey=sortKey
)
bootspecs = {}
def get_bootspec(profile: str | None, generation: int) -> BootSpec:
k = (profile, generation)
if k in bootspecs:
return bootspecs[k]
system_directory = system_dir(SystemIdentifier(profile, generation, None))
boot_json_path = os.path.realpath(f'{system_directory}/boot.json')
if os.path.isfile(boot_json_path):
boot_json_f = open(boot_json_path, 'r')
bootspec_json = json.load(boot_json_f)
else:
boot_json_str = subprocess.check_output([
f'{BOOTSPEC_TOOLS}/bin/synthesize',
'--version',
'1',
system_directory,
'/dev/stdout',
],
universal_newlines=True)
bootspec_json = json.loads(boot_json_str)
bs = bootspec_from_json(bootspec_json)
bootspecs[k] = bs
return bs
def copy_from_file(file: str, dry_run: bool = False) -> str:
store_file_path = os.path.realpath(file)
suffix = os.path.basename(store_file_path)
store_dir = os.path.basename(os.path.dirname(store_file_path))
dst_path = f'/{STORE_DIR}/{store_dir}-{suffix}'
if not dry_run:
copy_if_not_exists(store_file_path, f'{BOOT_MOUNT_POINT}{dst_path}')
return dst_path
MENU_ITEM = 'item {gen_key} {title} Generation {generation} {description}'
BOOT_ENTRY = ''':{gen_key}
kernel ${{server}}/systems/{system_name}{kernel} {kernel_params} boothost=${{boothost}}
initrd ${{server}}/systems/{system_name}{initrd}
boot
'''
def gen_entry(i: SystemIdentifier) -> (str, str):
bootspec = get_bootspec(i.profile, i.generation)
if i.specialisation:
bootspec = bootspec.specialisations[i.specialisation]
kernel = copy_from_file(bootspec.kernel)
initrd = copy_from_file(bootspec.initrd)
gen_key = entry_key(i)
title = '{name}{profile}{specialisation}'.format(
name=DISTRO_NAME,
profile=' [' + i.profile + ']' if i.profile else '',
specialisation=f' ({i.specialisation})' if i.specialisation else '')
kernel_params = f'init={bootspec.init} '
kernel_params = kernel_params + ' '.join(bootspec.kernelParams)
build_time = int(os.path.getctime(system_dir(i)))
build_date = datetime.datetime.fromtimestamp(build_time).strftime('%F')
return MENU_ITEM.format(
gen_key=gen_key,
title=title,
description=f'{bootspec.label}, built on {build_date}',
generation=i.generation,
), BOOT_ENTRY.format(
gen_key=gen_key,
generation=i.generation,
system_name=SYSTEM_NAME,
kernel=kernel,
kernel_params=kernel_params,
initrd=initrd,
)
def get_generations(profile: str | None = None) -> list[SystemIdentifier]:
gen_list = subprocess.check_output([
f'{NIX}/bin/nix-env',
'--list-generations',
'-p',
'/nix/var/nix/profiles/' + ('system-profiles/' + profile if profile else 'system')],
universal_newlines=True)
gen_lines = gen_list.split('\n')
gen_lines.pop()
configurationLimit = CONFIGURATION_LIMIT
configurations = [
SystemIdentifier(
profile=profile,
generation=int(line.split()[0]),
specialisation=None
)
for line in gen_lines
]
return configurations[-configurationLimit:]
def remove_old_files(gens: list[SystemIdentifier]) -> None:
known_paths = []
for gen in gens:
bootspec = get_bootspec(gen.profile, gen.generation)
known_paths.append(copy_from_file(bootspec.kernel, True))
known_paths.append(copy_from_file(bootspec.initrd, True))
for path in glob.iglob(f'{BOOT_MOUNT_POINT}/{STORE_DIR}/*'):
if not path in known_paths and not os.path.isdir(path):
os.unlink(path)
def get_profiles() -> list[str]:
if os.path.isdir('/nix/var/nix/profiles/system-profiles/'):
return [x
for x in os.listdir('/nix/var/nix/profiles/system-profiles/')
if not x.endswith('-link')]
else:
return []
MENU = '''#!ipxe
# Server hostname option
set boothost ${{66:string}}
set server http://${{boothost}}
:start
menu {distro} boot menu
item --gap -- Generations
{generation_items}
item --gap -- Other
item --key m main Main netboot menu
choose --timeout 5000 --default {menu_default} selected || goto cancel
goto ${{selected}}
:cancel
shell
goto start
:error
echo Booting failed, dropping to shell
shell
goto start
:main
chain ${{server}}/boot.ipxe || goto error
'''
def write_menu(gens: list[SystemIdentifier], default: SystemIdentifier) -> None:
gen_menu_items = []
gen_cmds = []
for g in gens:
bootspec = get_bootspec(g.profile, g.generation)
specialisations = [
SystemIdentifier(profile=g.profile, generation=g.generation, specialisation=s) for s in bootspec.specialisations]
for i in [g] + specialisations:
mi, cmds = gen_entry(i)
gen_menu_items.append(mi)
gen_cmds.append(cmds)
menu_file = f'{BOOT_MOUNT_POINT}/menu.ipxe'
with open(f'{menu_file}.tmp', 'w') as f:
f.write(MENU.format(
distro=DISTRO_NAME,
generation_items='\n'.join(gen_menu_items),
menu_default=entry_key(default),
))
print(file=f)
print('\n\n'.join(gen_cmds), file=f)
os.rename(f'{menu_file}.tmp', menu_file)
def install_bootloader(args: argparse.Namespace) -> None:
os.makedirs(f'{BOOT_MOUNT_POINT}/{STORE_DIR}', exist_ok=True)
gens = get_generations()
for profile in get_profiles():
gens += get_generations(profile)
gens = sorted(gens, key=lambda g: entry_key(g), reverse=True)
remove_old_files(gens)
for g in gens:
if os.path.dirname(get_bootspec(g.profile, g.generation).init) == os.path.realpath(args.default_config):
default = g
break
else:
assert False, 'No default generation found'
write_menu(gens, default)
def main() -> None:
parser = argparse.ArgumentParser(description=f'Update {DISTRO_NAME}-related netboot files')
parser.add_argument('default_config', metavar='DEFAULT-CONFIG', help=f'The default {DISTRO_NAME} config to boot')
args = parser.parse_args()
subprocess.check_call(CHECK_MOUNTPOINTS)
install_bootloader(args)
if __name__ == '__main__':
main()

View File

@@ -5,7 +5,15 @@ let
cfg = config.my.nvme; cfg = config.my.nvme;
nvme-cli = pkgs.nvme-cli.override { nvme-cli = pkgs.nvme-cli.override {
libnvme = pkgs.libnvme.overrideAttrs (o: { libnvme = pkgs.libnvme.overrideAttrs (o: rec {
# TODO: Remove when 1.11.1 releases (see https://github.com/linux-nvme/libnvme/pull/914)
version = "1.11.1";
src = pkgs.fetchFromGitHub {
owner = "linux-nvme";
repo = "libnvme";
rev = "v${version}";
hash = "sha256-CEGr7PDOVRi210XvICH8iLYDKn8S9bGruBO4tycvsT8=";
};
patches = (if (o ? patches) then o.patches else [ ]) ++ [ ./libnvme-hostconf.patch ]; patches = (if (o ? patches) then o.patches else [ ]) ++ [ ./libnvme-hostconf.patch ];
}); });
}; };
@@ -33,24 +41,43 @@ in
etc = etc ""; etc = etc "";
}; };
boot.initrd.systemd = mkIf (cfg.boot.nqn != null) { boot = mkIf (cfg.boot.nqn != null) {
contents = etc "/etc/"; initrd = {
extraBin.nvme = "${nvme-cli}/bin/nvme"; availableKernelModules = [ "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" ];
kernelModules = [ "nvme-fabrics" ];
systemd = {
contents = etc "/etc/";
extraBin = with pkgs; {
dmesg = "${util-linux}/bin/dmesg";
ip = "${iproute2}/bin/ip";
nvme = "${nvme-cli}/bin/nvme";
};
extraConfig = ''
DefaultTimeoutStartSec=20
DefaultDeviceTimeoutSec=20
'';
services.connect-nvme = { network = {
description = "Connect NVMe-oF"; enable = true;
before = [ "initrd-root-device.target" ]; wait-online.enable = true;
after = [ "systemd-networkd-wait-online.service" ]; };
requires = [ "systemd-networkd-wait-online.service" ];
serviceConfig = { services.connect-nvme = {
Type = "oneshot"; description = "Connect NVMe-oF";
ExecStart = "${nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn}"; before = [ "initrd-root-device.target" ];
Restart = "on-failure"; after = [ "systemd-networkd-wait-online.service" ];
RestartSec = 10; requires = [ "systemd-networkd-wait-online.service" ];
serviceConfig = {
Type = "oneshot";
ExecStart = "${nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn}";
Restart = "on-failure";
RestartSec = 10;
};
wantedBy = [ "initrd-root-device.target" ];
};
}; };
wantedBy = [ "initrd-root-device.target" ];
}; };
}; };
}; };

View File

@@ -2,7 +2,7 @@
let let
inherit (lib) inherit (lib)
optionalString concatStringsSep concatMap concatMapStringsSep mkIf mkDefault mkMerge mkForce mkVMOverride optionalString concatStringsSep concatMap concatMapStringsSep mkIf mkDefault mkMerge mkForce mkVMOverride
mkAliasDefinitions; mkAliasDefinitions mapAttrsToList filterAttrs;
inherit (lib.my) mkOpt' mkBoolOpt' mkVMOverride'; inherit (lib.my) mkOpt' mkBoolOpt' mkVMOverride';
cfg = config.my.tmproot; cfg = config.my.tmproot;
@@ -147,6 +147,15 @@ in
"/var/lib/systemd" "/var/lib/systemd"
{ directory = "/root/.cache/nix"; mode = "0700"; } { directory = "/root/.cache/nix"; mode = "0700"; }
# Including these unconditionally due to infinite recursion problems...
{
directory = "/etc/lvm/archive";
mode = "0700";
}
{
directory = "/etc/lvm/backup";
mode = "0700";
}
]; ];
files = [ files = [
"/etc/machine-id" "/etc/machine-id"
@@ -260,18 +269,6 @@ in
my.tmproot.persistence.config.files = my.tmproot.persistence.config.files =
concatMap (k: [ k.path "${k.path}.pub" ]) config.services.openssh.hostKeys; concatMap (k: [ k.path "${k.path}.pub" ]) config.services.openssh.hostKeys;
}) })
(mkIf config.services.lvm.enable {
my.tmproot.persistence.config.directories = [
{
directory = "/etc/lvm/archive";
mode = "0700";
}
{
directory = "/etc/lvm/backup";
mode = "0700";
}
];
})
(mkIf (config.security.acme.certs != { }) { (mkIf (config.security.acme.certs != { }) {
my.tmproot.persistence.config.directories = [ my.tmproot.persistence.config.directories = [
{ {
@@ -505,6 +502,55 @@ in
} }
]; ];
}) })
(mkIf config.services.mautrix-whatsapp.enable {
my.tmproot.persistence.config.directories = [
{
directory = "/var/lib/mautrix-whatsapp";
mode = "0750";
user = "mautrix-whatsapp";
group = "mautrix-whatsapp";
}
];
})
{
my.tmproot.persistence.config.directories = mapAttrsToList (n: i: {
directory = "/var/lib/${i.dataDir}";
mode = "0750";
user = "mautrix-meta-${n}";
group = "mautrix-meta";
}) (filterAttrs (_: i: i.enable) config.services.mautrix-meta.instances);
}
(mkIf config.services.unifi.enable {
my.tmproot.persistence.config.directories = [
{
directory = "/var/lib/unifi";
mode = "0750";
user = "unifi";
group = "unifi";
}
{
directory = "/var/cache/unifi";
mode = "0750";
user = "unifi";
group = "unifi";
}
];
})
(persistSimpleSvc "octoprint")
(mkIf (config.services.borgbackup.jobs != { }) {
my.tmproot.persistence.config.directories = [
"/var/lib/borgbackup"
"/var/cache/borgbackup"
];
services.borgbackup.package = pkgs.borgbackup.overrideAttrs (o: {
makeWrapperArgs = o.makeWrapperArgs ++ [
"--set-default BORG_BASE_DIR /var/lib/borgbackup"
"--set-default BORG_CONFIG_DIR /var/lib/borgbackup/config"
"--set-default BORG_CACHE_DIR /var/cache/borgbackup"
];
});
})
])) ]))
]); ]);

View File

@@ -82,6 +82,10 @@ in
# NOTE: As the "outermost" module is still being evaluated in NixOS land, special params (e.g. pkgs) won't be # NOTE: As the "outermost" module is still being evaluated in NixOS land, special params (e.g. pkgs) won't be
# passed to it # passed to it
home-manager.users.${user'.name} = mkAliasDefinitions options.my.user.homeConfig; home-manager.users.${user'.name} = mkAliasDefinitions options.my.user.homeConfig;
systemd.services.nixfiles-mutable.script = ''
chown -R ${user'.name} /run/nixfiles
'';
} }
(mkIf (cfg.passwordSecret != null) { (mkIf (cfg.passwordSecret != null) {
my = { my = {

View File

@@ -7,8 +7,7 @@ in
monocraft' = callPackage ./monocraft.nix { }; monocraft' = callPackage ./monocraft.nix { };
vfio-pci-bind = callPackage ./vfio-pci-bind.nix { }; vfio-pci-bind = callPackage ./vfio-pci-bind.nix { };
librespeed-go = callPackage ./librespeed-go.nix { }; librespeed-go = callPackage ./librespeed-go.nix { };
modrinth-app = callPackage ./modrinth-app { }; # modrinth-app = callPackage ./modrinth-app { };
glfw-minecraft = callPackage ./glfw-minecraft { };
chocolate-doom2xx = callPackage ./chocolate-doom2xx { }; chocolate-doom2xx = callPackage ./chocolate-doom2xx { };
windowtolayer = callPackage ./windowtolayer.nix { }; windowtolayer = callPackage ./windowtolayer.nix { };
swaylock-plugin = callPackage ./swaylock-plugin.nix { }; swaylock-plugin = callPackage ./swaylock-plugin.nix { };

View File

@@ -1,6 +0,0 @@
{ lib, glfw-wayland-minecraft, ... }:
glfw-wayland-minecraft.overrideAttrs (o: {
patches = [
./suppress-wayland-errors.patch
];
})

View File

@@ -1,43 +0,0 @@
diff --git a/src/wl_window.c b/src/wl_window.c
index 7c509896..db9a6451 100644
--- a/src/wl_window.c
+++ b/src/wl_window.c
@@ -2115,25 +2115,21 @@ void _glfwSetWindowTitleWayland(_GLFWwindow* window, const char* title)
void _glfwSetWindowIconWayland(_GLFWwindow* window,
int count, const GLFWimage* images)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the window icon");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window icon\n");
}
void _glfwGetWindowPosWayland(_GLFWwindow* window, int* xpos, int* ypos)
{
// A Wayland client is not aware of its position, so just warn and leave it
// as (0, 0)
-
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not provide the window position");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not provide the window position\n");
}
void _glfwSetWindowPosWayland(_GLFWwindow* window, int xpos, int ypos)
{
// A Wayland client can not set its position, so just warn
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the window position");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the window position\n");
}
void _glfwGetWindowSizeWayland(_GLFWwindow* window, int* width, int* height)
@@ -2359,8 +2355,7 @@ void _glfwRequestWindowAttentionWayland(_GLFWwindow* window)
void _glfwFocusWindowWayland(_GLFWwindow* window)
{
- _glfwInputError(GLFW_FEATURE_UNAVAILABLE,
- "Wayland: The platform does not support setting the input focus");
+ fprintf(stderr, "!!! Ignoring Error: Wayland: The platform does not support setting the input focus\n");
}
void _glfwSetWindowMonitorWayland(_GLFWwindow* window,

View File

@@ -1,10 +1,10 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBJYzdr YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBrMXND
b1d2aEtVd3lVb3NBamRwVFpTaTRjZFlCczk4MVIwQUoxWklwN0NrCmFFekpPYUlO Zm1ma0FoNE5lWTFNTGlyeUQzdUZxMkxyVlU0cWdrcTJEakhDVXg4ClkyczJDR1FL
YlgvVlQ2WDR6amZDN0ZSY0Q3WWtTME5pUmhQeks1c3dGOVUKLT4gWDI1NTE5IHVK eXE3QWFTM0wyeDNvL1gvcmx6eGE4elNuZW9wRHhJZ3Aya2cKLT4gWDI1NTE5IDhO
bUZvUVAvL0NmQzFkY3BuYm1wMjcwbFpLRUNpZjJCaW15SEVDUDV0REkKRXFMQ2d1 S2JWNDhlclpERFFUTktyUG5HbnNxcVQvWmphOGp1cmNpK0NGZWVTejQKN0dybHl5
NlFBejBvTlJrcUtCYWZxSDBkbmxIdExBNTU0aC8zRW5OVWllVQotPiBDLWdyZWFz eHhicFNpUHQ3WFZDQS90NG5VZW5zVm8rcUxCdkZkOFVqdVFzRQotPiBBLWdyZWFz
ZSBkeC4oTFUgO0FtJG9+RyB2IF1QXGhxVwpJS213MXBRMWY1cXlHZwotLS0gRUF2 ZSBaIDMiRCBYO1g6IF9EawpJZwotLS0geXhWb1FORm00RVJoMm4zQjhBT0hERyt3
ZkswNlhvcDhTc2tybCs1dldwa2l6SDZZVmNkNUNjNGlkV1ZVa09pOAp88dxHGxVU ekM1YXNzdTgzUTVMeHNsNDUwbwqSjgIVhg9bqtIydYC1FCA4ly2gurTcb1SUCMG8
vuFQO6JcroY9MF5Te/YV+wMc3hVxksibMnH1TWGh207prwcOWNOEz2iEkZY= XA9WAx1jv05xje+U97tRTTongJEW5vw=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,15 +1,17 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBLVlg2 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBjQmZr
ZUdtUlFUQXBLT3B5YmkycWJnMXJyKzltbyt6K2dJK1RBUm5ydWwwCmRUdjJFSEYz VDl4TVlzK0lCc0YwdFM3TEptU3Q3cWZ1d0FJQUI4Q1g1TVNyOENFCkU4NE5lYVhI
Wnp4cGtzTXZwc0s0SUJQUjRlOUJlQUoyQ3BETXZmY0ppWG8KLT4gWDI1NTE5IGR5 d3B0amFJT1A1RTRSaUdUSmZ1WmU1SkVhTU9sdFZJR0p6UXcKLT4gWDI1NTE5IG5O
QUJzeG1DQTRLUmRwNnNSRUJRSFFtUDl5VjB0clVLYUp3R1g4TEVKaTgKb09tVlhF RG1SQnZtSUk0SThNYkRpOHFPS29kbjdUenZyYjBBSTJKdXNUaGpYMG8KME8waXJ0
R0tmcmIxMHVHcG80RGxRTEhBcngvT3MrdnNPbmpCTlRyZW5xQQotPiA6RzEtZ3Jl NWR2NHoyUkN1UUJoaVRxYXVMZlNvTHZqRmYvS2h4QjZpZm5NZwotPiBPclJULlkt
YXNlCldSUlN2ejB0MGpyUHYzNS9OQmJTK3MvcXRDakdBVlhuUEt6SFE4QmhnWVN0 Z3JlYXNlIEVdKEBXIDUgXTBzIi58TwpweFJEcUFpR0x2WWhiVDlOTFArenhjNXBB
V1JMOE1oaEp5QQotLS0gYW1OMTcxNWJrUndmR2h0ZmRDWk5CYnJjc29pSERUMnNk dVo2d1JQWEJyVHlTRnUzdUlFUE45RWlLU3ZRS0c4UWs5Nm1qVHorCko1RVdqOVdz
d2VhTGdpOW4yUQrEeH2E9m0YycuW60QrdlRetO1kNU5FaKXRQt46iA9lACIWD4rC aVAwY09KOUx4WktIVFBQclFXdFJZMTNVWHNKcTZFbDU5Q0xLaExvNVdlZ0pTczUr
Cx6WxhCBgz3hvm9x6iuYiiQxZzgJNK7qXcV2MBeQdivazeEbC7blAKVPhwD/dl+b SkVDTzhDUysKCi0tLSA2VGJMM2lrNkViaU0wcnArSG9PemJrQ3lrUFNnRDRVeE1p
PzBDXRXG3c3jMjeZFT69fIBGJfZrrLGKpTALVE4dTVXmQmVVQDTp19IC+jUXHBti V3lxeG1iN3I4Ckf36lD/b7agsT0qW8eGDnxsVor8hEmLBSa35/eeAxqMd0xPvQko
Pj6Dpc7452s8zPkzZyRbasO9b4PYTwq8IHT6X7ITwbzZZm8gexDYe2SzRZ5VcPz3 REzIxPuEHRQM5dE4s4H/mySTC/AVsiwfcMrnOXInm4o3MNAC9PREcef4NBOP3IMl
El+yoULZ92WbXPSQIP/Slx4BEZjmsQS+sm0N8AnBRNZkWVbHPF9IZRg3VjDAn2i8 Mcoifar27EXs21XdXw/lLOVNDX7oDKZh1zXVX4lFTcRW0v8abbwchvuTiayKePMG
F3un5js= DrcyFsj4jiwpJ5MmY/Q+n0lZmoAlAJkeTHRUptJxGMq+pWVEGMa8p1vUdrVwWq7G
YYO5lPlms01BFJfUsysh07HY1HPkOyFHeEkviZtt4N8hopx0pP4fyAZYYdrBAIdt
CLpQFQ==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,13 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyAyMWox YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBETE9p
cEFDWWUrVzJSM1o2azJqei9HV2xFY25oQXV5SzM3akxEaUJiN1J3CjkrQVhjWHY5 VVVHeThGT3daNW1xZjBDblFwQWozQ2VSUmR3NlJVak12YXdWUDNNCitTWnBHd1Mv
Uk01eGp5Q0RKNVREVXJVZytndTM0SXNZSGIvUVp1TnRiNXMKLT4gWDI1NTE5IFZn L2ViUWJvR0dtckpTQnRNMWZtazZHQ0tON0RhM0Z3cTlYVUUKLT4gWDI1NTE5IGhV
WjAyR1RMajEyMnFSYnNGT2EyekROVWNoakFJQVZxaFc0YThOMHVyanMKWldrdlAv ZEFqcW9CcHUya0s5dmgxc1JqUWRicmpXTllIckxaWjhtYzMrOFp0R2MKNUcxVllk
cVg0OTFHL2loeGJ3RHA0MnlnckN3czF4RUgyc1NjYXVOSXF5cwotPiBvTFQtZ3Jl WWJ2cEkzdXdiVFNDQVN2cUVNRnlMQ1BZWEx0QTI2M0FKSHE1ZwotPiBHaCJASk9u
YXNlIDRsSDp6eikgT1ojIGEzOFZMIFc3MUZGCkttZ3ZLNGxucnlJc01kRXFZTGpC LWdyZWFzZSBsIFxuClVieGM0alFSdmttVjVsNDZIT2hjSTdWc1Z2VXRIUC9BbXNL
eCsvRzl5WnFUMUIyTWNVWGk4SjQyN3V0bXQ4VzFuM1RjSzVMcDJkaW1JYXMKQkE4 MXArcHI2eDM4QWwyeXhtMU41cEtLQ2tkVllJdjkKTjMvNENSNXd1UjV2bGQzbnJx
YWI1Mmg3MkpjdVpVYWJkczJQMnM1SVMvNkZhOXBDVEZPCi0tLSB3SVIyU3M5RHBE U3RubVRxQXVSSzJXbG5uQmcKLS0tIFFIeEVhR29qY3FBaUlJd1M4K3FvdDNybHZB
VFRtMFU4OUFLbkNjbkJmVmhlc2VsYzdsd0pFaFkrUmkwCs+h2KlXoyZ8U++A9wmV MmVMZGxyYUYxVDNydjZLbXMKiPpxBn4WtzaH2iTFfjayYgNFPa0Mi6tIH0LOqkAj
kh4N2YyI/a84yPGDNoFdSlXaU8jxUzolnadImXSXyB4CroqQLvGEbkZZlWqPLVfh RyHNF/6vgWlmnivbhP+74dVaqR8IwUdFQN7S8/fx7eW/7qvtlg==
Iav7Ja8=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -0,0 +1,33 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBSS3E0
YWsxbHZXQXo1R3BzL1BDdERxN3d2ek5acFZWK3F6andTeGVacVNVCnhPR3I4dXFV
dFd0N2lsTU5NOCtsM3Z1YUdIaER4YjlrdkNXT1g4dGZXNFkKLT4gWDI1NTE5IDBQ
cHBYSG04eHA1ZG9KN1Q5bFk0eXk0T0o4c2pLVUdNbEtWaDdwckdJVmcKd3lkZmVY
cDc3dGdXSWViNGlMVW9jZENUWXd5MVNheStiVU1adG5MNEpnNAotPiBfJWZ0eWtP
LWdyZWFzZSA/VGRDTT5kSCB4QH05QF96eyAtfUpxQ1ggZU5FQEhZbGMKa2xDUlMw
Wml2QldxcS96YXVJT0hPVStqelhmUEd4K2R3ZDM4Uk83MXV6VlVoKzRiMWhxVlJx
Ykg4ZTJ6SSswTQpTdjYzUkhMWjFwblhzRWV4bFZOVnRjRGMveDFaUTJWM3diK3lj
MUE3dFlhUEVENAotLS0gd2lKQ05PRUF1b1RzZEs0ckY0eFlPaFFBNHRQZ01rZzBV
SW01L0VzUUpYSQrJxWuL6pjjZs+hCS0f6DTNwW6HSD33bUwdBpyTCLeLMyDT646H
4pjAhrVjVH1kgBFmuCjTP+SrD2bie/WhkQPSYrG7qygcmXbdNXlJn1tluEedDLzK
djbOaSuohlgneGw9Z00Zkm8rz//2NSB89+WiWuT5/6Pm/d6763FteRI1LsPOyWx2
vmTZMIcuclmrGn611T1kKR87R5AkaZ6xyhkOrOvWrb7BktmA69Kd9r5fXyxnLRZD
W6vPm4EJLo0b1a4DWlnIvFTy5I6e2fFT9h2+rU1qITn5fwQD5aAYdL8W8ELIEJ98
zYNxpbepHY5fBpHOGvOKM4AAO/R2pjaDaK7DRIFhSx/1RJLJvigXFd7YKl0WWn3w
PGK/YxXnhtxnZngEPrnwf3JPj+zQ3RwKDx/v12s+KTbfQu6sGvw3MhDwYsFrRn+J
T/jqlcZ/RodnxDngMnJCzc+YPkCJ/yAiot1DthVdpW0mWFiPsZvzN3co7t+6nopR
WYnSjp5igjHbO/E3zXQ8qRlOvXSp6zspOIv9AETq49felAxXF7uz28lMnBeCReVq
4hzBII+wDTR1Y/itKcOGm5mTdyvLF4qKRZFJFiJ3ATGZDEYh2dCrO2juaL4VczCl
+qwt9gYF+pOgY4ekOtW6BpvOGZ591LHTMWoP52O0MnZADU8GHkh66AvMDemQGumj
7qI6kI49Rwr5CoDMds5XlUBKlzeLgZLSo46FJghWOOQaiFiXWVQ+jYZpZPkgGjkU
wDkrnbdglkdPO93bT2drkNbPWziHRkV505lGk1s4zCvsUPMH0D6KYkA6o/hCum4B
IK8Sj215CmjQv5LYBwzHTNRusksXDu/+Ud5FpKCNw34aKblLIEPJNSk1BWLwyLzM
oCNTiI490ZBh3vcnXpHZorS1Hxzb536SW03l0Z6q1Izn/vfzhZ7HbFY4qS9Qe+je
Cvx+upRzt+mIQt8edbhrC1twfo/6whuvpT1HqGQDUr62+4zqVJ3lbccmXRX6uOAq
sfK9if7qo0wkfWqa4RutO008ocVSKt0JjDOUpGHHP9Z95NRMyKJiOlv7dgVwWEid
J8YMxexAgkmjByzwt1CBC7XizEHl09ZyjJrzN420NMRzaG3C6PY82cnKdbXNfEM2
0dlN/xUTaOG1dAjdlgr2oMA5o0jFptr3hTFcoOQ/va1zkkNDHvfgjzri9HSID0bP
kE0Akj6H9457cyo+xI+gD+2CtJW37TR/A7GLrzc+BDdDNZWtJz8t7oU0STL38h0d
rfHgC8uFj7Ozh0nvsPbviwHCw6F+Z3lOT2qaFjzWKMuhnB8s3C//vmMFCfY2XglJ
Tmcz+A==
-----END AGE ENCRYPTED FILE-----

View File

@@ -0,0 +1,14 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBBTHhU
TVdvcWhvb0c3NjlTT1JBWlRaRXBYSlFySFJhQVZHRUsxcTFVT1ZzCmVaZW1ucTRG
MVN0VnZEWndlVS9iclNhRlB2dkZPT241dHRxcjBRc1BpVncKLT4gWDI1NTE5IGh1
aitYSmVudUZPS0FHbUliUjFCWXJaTWI1RzRlK1Q0ZlpQNmRwN0haemcKaHhQS1JO
UVYxYUU1OTR0dXJhTm1EMGdER0hYUXVRd2VmNURwTEdVV09tVQotPiAnbHAtZ3Jl
YXNlIH0gLCJ9IDwhIEB2QW0lfSkKMUJLd21ubDVQdWJOR1VvCi0tLSB3N2dJV2o1
WGF2TENYNE8vSzI2UzVPZW01RzRtK1VCaUVKemN1RzVhaGlvChPEVtylQsq+EWK4
X6HxFl3JY+M9clfpicNlSqUjPcB3roEMpD9BmGcG46nVSZVDguVjPzwTltAGE72Q
Q4RP8/yhssA2rrLEuWz+JKcaASF/yEmu9QBILrWBIWz0rQyHfTRvBC9d83MdHS5f
DQl1abC7Lv8imVm0pJ9vthvB56mXlGgm16fnsd/UhgMQSWZuVLSitaoDEFCz/LWi
QAUKYTRVL2UcomgHsQqMx+2g3HT0RYQu1Ud3M5rT9eMSSqPG7IzyjNA3HmH5dw/4
EdnilIaW7c6k1RAYMFY270E6qlxqdQ==
-----END AGE ENCRYPTED FILE-----

View File

@@ -0,0 +1,15 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB1QUhX
dTlNY3h2SElIMytCTGlmY2syMmlTL1VMeDFnanN2UE9QK3RvRlUwCkVMM3ZKMU52
ZmIrZ1VxUDNWZm1lU2MrWnpkUzBLcDB5cUFCSXZmQ3RXR0UKLT4gWDI1NTE5IE5W
cE5uSlpRd3dIRXEyRnpSZ0VHZ253OE1ZVTd1OTJQYkZVd1NRdnh2aE0KNTFTaHJM
OE9tc0VkMHFHUGN2dFZVSGFBdTh5Tzk0TGU4SWwzYTBOb3FtdwotPiB9WnwtZ3Jl
YXNlIHZVYHxaIEBSbmZ9XiAhfF52YCNwCld0K0RCTFlQamNLeitWM0kwUnVJdXFV
QjNFcEYxWFBkVjJ3QlAwTGVvTE1GTkxCTEdDcmlZMC9xbUcrSHp2V3cKdzJLb011
aEM3a0V4eXBTMjhnCi0tLSBOWHozZTRjRldrOXBmM05BZ1lPRDYwaDFCcHBPNHhQ
SzlaWGM2RXY1THI4Cj4RzG3G1yGkmDyqxCBciqMNPAQYge4mXOib7mqOuyIbkT+k
qrJ8fLnW7Jbnb7+Rzr7BAEC5/dpOfjkyY9JPeg0FRutlkKyPIhRMAEhSsNvUFzXg
uwNbnSBI+9Str6nTKI5c9IWT5eT/8zsKwtK1/pr39mApRY/y6NlA5X7ZRIFeku3K
6I/bCI5cT0qhIMJbF5D0KiCnMCnMdmRLrwLzM2zcJoisxRAvj4dNfLktsUQOauZ+
Gta96qQkAewvrdfz8Z4lTYJQmEqeOs1vTA6sAMf4iLp5EhPE0jN0n6D8v7Lq7+2b
-----END AGE ENCRYPTED FILE-----

View File

@@ -0,0 +1,14 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBJbWVs
bkt4a1RBaU14cjJzRm9KUGhydnZlWGU0NGVYK0NmWXRsclpjVUU0CmNiVDJTODFw
TnloNW1LMUliVmlnUGt0SFFzWmxVTWxZQ3crNWVHVy9IL0EKLT4gWDI1NTE5IDcw
TUQva3UxN3o1MXJ5QmVmQWVmeTFLejVwOVdQZks3a0dVQUJTdUdZdzgKajBFK2dX
R1NNR3l5d010MnJGUktNWldwVjY2cDIwbU1laEMwOWJITEg0NAotPiBeLS1ncmVh
c2UgJjhQIF0pcSB4Ci90SVhIZzRGVlcrd0hRCi0tLSBKdVgwZ0pidC93aEFscm9w
Mm5GbEc3RDdZRDRpeTdONHpWN0xHYXkvVU5zCjjFfwumbetHbq8MKrBIx18YXmny
z+0ifVbksJhYLYk7hViSUDy+F3RRad23dSPvDdd7JCEpj+2PvcezBLkwfUkFdQe7
uQhUJJ9c62oKSX7PMbQeW1tyX10SVkt/P20z6HPXvBlY715lsXspjZERi+DheZk0
ZDc3dPYMeyoAIWicf40ZxH8C6rWl5HOLIaTMbCOKwpD+wPjpzeZHat605YWReFxR
Yd3cKCRqSb2QdAdtZ0XUDSPl7HVwkw0xobCsvtPzmObA3YbLopBq7Dvrvh7XW5ns
BPlTaI8WnrI03CplGP00
-----END AGE ENCRYPTED FILE-----

View File

@@ -1,13 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USB2WFY2 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USAwa1k3
MzFnVFYvb0wzc3grRDBrUi9teW1tNmx5dVBIRVc5OUdlcjdvTDJFCmpJL2tlYXND S3dka3ZjcVdIQ2hSN0xsb0hTNEhneXFYS3BXNWZDVlBNc2toQ25vCldqSlMrT0hB
bVJKbzd2S3JkSFVMdG40MS84V0lPTVJSNHVBQlNXSkN1eTAKLT4gWDI1NTE5IFBM Rkg2aDZUYlY4U1E4Y2djMVdwT1VsbGdpUm12Z3gzditmMncKLT4gWDI1NTE5IG13
ZGo3L2VlNUZqOEE1UHBuMHdqc1pyYlQ3R29ucE9pajU0bHMzamlXRDAKcG1Qdmw2 YXF4WWdmNFRPR1JDWkk4OFZkSjdzRS9BbXVzSC9YNG5FRnpqUXJZVk0KV0tOSG9N
cUlncDFWNXBOWnpIeDNZSFA3d1E1bjNaVVpKU3lMRjRaSHNtMAotPiB2XUh8eF4t c2VVWE10WkxUZXpqZjBZZUQyWE14TUFsdStMeWVlcFdJaTRVUQotPiBWaHxWdCYt
Z3JlYXNlICUrO0cxIH4gaTRoIF81SEpTN0Q5CnpWdEZpb1hZa2t5YkE5RnJFMHVZ Z3JlYXNlIDYgdDsgcW97Ii5yIE95Clhqa3RVUmJENngwTDNoR3BCNjlaTkVYc2JR
WkhkQ2o0eWtyOE9ueDJkeGd2aUhmLzRUUGs1aUc1NURIOTYxczZhOEVmT0EKd2xk ZWQwb2FOVy9sc2d5MmtkeUhkajJBOFE3TWJTOWViWVlJSTkxWQotLS0gN01aNGdm
TXFHN051d25PQmtNUVZkVEFGUVliZjdmZDF3RWFkaEhNTzd3ZVd5N3dlNzQKLS0t VjR0ai96VzRqb3QzYU4yRzVCby8ycVhXVlpubVptam5mYldoOAoZnbsXB5we9BQ5
IGZDR1Mxd24zOW05bitzQnN5WWVOOGtCNEc5aXIraEF4eXFUQm5CZUdCV2MKd44C AXQ08mXmMxRMg9iH7qgyCVc1ywR/uo5Fcefhuw23TyluRkYt7tZ9yiuFJIx5Znsr
/Trgg0OEZ89/jqbj56z/Hia1Ka3ZsEv6bXPI/kcRvFDBFTgtvG3KWCgMBtTUHXzY QEqaBioL1UfePVyDLi8LcBvUgnnx5uN05hUvTOt6gqaE
TKBPoQqrUf7plH7a/mTx3KR+4Y+yF+1i86s7TzYjD8d1xfFH3BsVtg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,30 +1,28 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBuQjBY YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USBvdjZT
K1ZTUzR0SmFoYUZLdzUzNUt2M1B4RFdPZzFkcW8rMWJLUjVHOUN3Cjd3ZHdMSzdp WWFyNzdXVENweXlVT1kxNElaUDFUSG1DSGMybTZlN3VKVDNNMGdBCklDRk9oaXdT
OWswditVWUhYNjZCdjV6M1d6U3pNak5hUlZjTHNqSkZPSk0KLT4gWDI1NTE5IGNG MEhrR1VTcGE2NWwzdW9NQklwcGFsd1BWSXBpa1YzREdTUUUKLT4gWDI1NTE5IFN4
ZytHazJQWTExMjNkZWV2aDUwcnZjUGcwcXRkZWl0M0F2R2JpUVlJekUKWTFlbkEz Nlg1OXFNMjVzbDlRME01WW5iMTZvU05hUTExNnB4MFpUQ1QreXFXbmMKb3BzamRT
YlN6dkgrMmFFcmlZMjQ0b2oySjlEMC85cUF5QlA4NGF3blBKRQotPiA8M1hbWS1n OVM0TWZIdkJnYlByRjRQUXNtQWtXS1FXRVlFTkpSNHFVTWV3OAotPiBpQy1ncmVh
cmVhc2UgOmlZJFYmJgo3UExzUHhSVi9lbVRjNW4xTnVaUTVGSGVDNzRUNlJ2TnVu c2UgJT9RYi1YewpadEZzVUpqc3F4U09zUQotLS0gWkg5ZWlxYUJGMUVDd2o0TTJT
U0wrWU5kd3dyR2phcUNVUHJCYjdzeWhjNVFOV011CmZMOVN0WDk5eUg3ajhwbStQ OTk0WlJ2aE96Z3FGNmQrNEx6Z3N5UkRxbwrp1nF8mtgoTEYfQ/aE7KgzFOei1PVt
aHExT0EwblpreTBXVHh6Zk1HRkhzcmFQNnoyVUlaeStMUkgKLS0tIG1aY3Zadko3 cLAh3v7wo7C3lxhBOL0v8ToIAVgSoGP6cj9/4k7+9GngpOgot0IOdoXsThVdcg7w
V3pDMGswSDZCeit4SVhSRCsrZVRVZVkvQkNsQWN1MXFMUGcKcK74YULWqWw9VvkI soDjArsSWDYn6Th0yZf+trSXfA24BKIS5qQnAMT2ivQQtO9Kqxko2Zj6+wZO4LEj
NH38VHfDPW5ueSiyHHKn8MI9YosPr/TmkwgKd/DOIMVB74ahPalo1QUeg+eaBVnq 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 uQ==
nL0T8YXdGt8K01w+nt+j5bo5gFoRz5+1/ZZ9BgN2DOo4SClYnJWQ/x80X061yJ33
0SGv4eAC3vFi6xE=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,16 +0,0 @@
-----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpCM2U2USA3MEFh
YURySHY5RjVQa1c0QmMvTkZtZElNd1BIeDFpR1U1YXZ5dndnclUwClA2M0ZYMk90
RmlCZHVISkxZQTZXeEhZVUROSVRGRVg4TmZKZytSL05FcTgKLT4gWDI1NTE5IFY2
V2k3S0VQdGlQZ0hkU2ZoSWdOUG9rQ0p5Ukg3ZHU3MXVvNHlWYVN5VVUKcWtoWDJh
LzRwcktWUGQ1bnJvRzVBVlpHU3NhdzYwUDBPTmx3MFNrdWNQYwotPiBKQil6Km0t
Z3JlYXNlIFdlRTlUU2cgVlxLIzUgJlVyQiJ8Cng3NzF2b3d6MnlEdURQWHgrSFJv
Y1BMUkZyelJSdDJvUUUwY1k5R3ZBMnJaa1R4NWxlUll2azNseW5MQlpvVWUKYUdN
d1ZscXVxd1dxSGpzMjBYeWhhYyt5ZlNkSjhmV1ZTTDBTCi0tLSBBTG45VUJOSXZv
N3lYNVlyZldMVkpZdUMvS21NdSswVmU3VThZK2M2eis4CjwfWWJVR9Ty5dBXEr5s
U+QrifXvyMJJvqOKEfMYYomFLpt/VtbDAUwNlqLnFIk1VZ2xPUBisXPtReiCK3gq
P+i6bUONSmPYvmF82VgiuKDuz/kmWqVGg2iSBPIXAGLNIEojndQwmhnrsN9ex4Xy
lBHkvVsN8EamUJwZ+FEZe4+PjA5yEnANWpeTELOt2gA92/jwwnNIsr07eVTlkh8X
UmQ2owGwktXP7it6//NV3C7sAdazs2bX65WSnog2E8WPNAorKWI8RCYs33CshVFt
zzclZ4hRmlAmqMHYqFY=
-----END AGE ENCRYPTED FILE-----

View File

@@ -1,11 +1,13 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBoYlRq YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBmSkJo
ckk2c21uMVZSR05SdlJpck5MT0FZeUpLTmpTRVN2WDkxWWxmVTBvCjlHZWtEQ2Jh UzFYMVBiNTRBbnliRHh1OXBpME05dUpyYjg1ZVY4WStxRXg4VTF3CkpGQ0Fia1Ew
YUdybjJLWkNsZkxabTVIR0JnMno5YlMvVmhodDU1bktrSzgKLT4gWDI1NTE5IFZT RnBsLzNJZEZMaER0emt2TFVSWHBGcEo5MnYzVDlvOEFrUVkKLT4gWDI1NTE5IHh3
Um9lWXhqRFFLTWdNaTR3Sm1acmY4N0l6WE1FSW54ZEtQcEE5RHBRRHcKcE5KYmp1 UC80K1piWEdneVExSmQydHRqMFdTL1djd24wL2pDNFc3bjNxc3hZekkKTlI3Umh1
WVdCVk0wMHZ2SCtUR0xKWU10N0xETXlXZmgxcmZZOFBXYWtBawotPiBlRm1gKGxU SmdBM0Ziak5GRm12K0pMckZ3UGZXZTNPMm5hZ3lTV0NFVlYwMAotPiBHLWdyZWFz
LWdyZWFzZSAqXF8gOkU8Tm96IGA4IC1TCjY3NUgKLS0tIDhjaTNrbG1iQ05iTWRS ZSBddkFIRWdHIyBjOXwkT3MgJiBOcUkqRwp6VUMva2JWd0J5ZjBpemFFM2djTzNC
UzIvNzA5TmVGS2ozZmYrYjlBY3J4Z1RRUGRNeWcKUTIEhWqr0fOODu86MDll7k3U RW5POHIzOUZFOG1zRElPMkZZZUxmbklpY1V2R3lqNUtOYnFlSUVMZXlrCnB6REdz
ThgmS9nlcUY3fMgXzZLtpHIJ/4ZSI+miu8RmLMaeC61qv6xNThGdx+MvU4tMBWKA ZHFzbmRjMm5mM0RGU3NzeUl2bHBhTEx5MjhXRTJBLzJZRWgyUQotLS0gV1VlUkRD
Hv3XGi2MYL1jdHh2KYg5PgdqchYuHrFuBPS7c/tQow== N1ZTZnMwTWN5SXEvQnJaK1NmcEUzMEJ6UVcvb2ptK3VYZU5zNAqgntLnLkQABERv
HpNr21t8+KR56PZ8nQS8xALzw/FzdexGvlt4Pzx6o0daBeh4aZx4mgcyG641PsRc
eDs4tJm8gmznr6y7B+WNC6WGrWPPIC3pHKU4g9PWzyEZcTEpL8Fp
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,82 +1,80 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBZVkFh YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGo2N0ZYUSBtVUdX
RDNNZCtySlNQTTZFbzJvZmF2TEZKVUM5VjFjQWNSeHlNc1JNZ2hNClVac2pEdWdw WWlWOU5Pck0zSWFETUhMZVI5bjNUUk9pc0dRVC83TEJIN0V6aHlBCjJvWkxSaGNq
OVpOTmhWWklVRDA3UzZWWk9QVG1ySUFmTzRSVlFReVdFVFEKLT4gWDI1NTE5IDVD WmxJSEhFekRLSE56K0pDTkxNRlJhOGZTWC9RdEZ4ZGJQNkkKLT4gWDI1NTE5IHNy
eWN2S29aWVNVTTdldXFxZG1vWUNYK2RrajI0OGNGaklzdFByTzlPUkUKTmsvdTE3 S2lZdjFYM1M0dksvZlZ1NkFENkhLdHFRVm1rM3B2YmJ3REZEa3poUk0KSURPMW9F
ZFBvalZsdENxR0VnV3FVSnFxTitBRlFWR1BzcjJWd1h0U3hpYwotPiAyOkUlJC1n T0pWVHh5MnBjNThRcE9WY0E0Z3JtMko4eDFiS1k4L2RBa2wxNAotPiBgWn4tZ3Jl
cmVhc2UgIWFOMiogVDc8IFZETk9BSDVTIHEKQ01rc1ZoNXQxUDdtWGRQUlRCV3k1 YXNlIFdRamBzSyBlP1wKSHpqbmFWZGpJbkhyRENTZlZtdFgKLS0tIENud0RDdjRt
djNZeEtOaUl6Tkl5TDA1S2ZXWTFQZEFiV2pWMDJpZ2dkYXdBOGhSTVA2ego4UnBz bFhpbVhQbkxXZXJRSHpDZWovUEowUWJxaUkwNGN2aVU3ZVUKlXMwhyxmFiFHHHDQ
ZGhXcklMd0NVWlhsc0Voem1wUzMyREViUllCRAotLS0gMU5GQjdJaVdlUFJGMG82 FDtswK4HmApIhnW3TORhJyKIG6WBKFE1wDN5cDLppbjLdWAZecQbw0Qe8UQP50CM
YnZCUm05ak9qcmVyUVJSS0tHaWRRTld3ZkNPMArRgojrBQvlyjMhChn8jgUNDysj iSZOYSSpS4J6jo2kFCIQELXjXMi7YhmkIa+Svz7kcr+vVROOikBdTr37ZOXp51Dy
9Nh3BVqf44fiUNMKARTrFTz3wVMlioo6MmKRzJ/yj0fWkZ2h80X68Nq3rQvy+0UK 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 S3Pp6kYXW8wcFAFRluM+LCFzO9VFnZ8BEh5nDX4=
ns5Z+U/2XKGyySQASUyFXUNml6csSrTd+ejz1QvEX9POU1nLmvS1+aojgnptgdpn
sAtksQHMt1Njo1oRug3+/0iC6XWEig==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,35 +1,33 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyB3QTU1 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IERMTWVGZyBqaFcw
TEdvbFNaUmE4U1lCNzI1dlloVDBTNXdURjZ2akRMV0R6dm5ST0FNCk9YclRSakhT aURxK3cvaktEVkJIQ2dOOEtqbVVGRDN0SXpXdGI3NzhQV3FmaEJrCmVtclBDY2Zr
NlV2UVJwak9Fa3dQNTNBK0xKWGlkNXdwZTBEMm4xZzc3azQKLT4gc3NoLWVkMjU1 cVMvUld4dDNybnJ4bHZOODFpNGpJVXdRaDJKY1ZxMy8yMjQKLT4gc3NoLWVkMjU1
MTkgakk4UkFnIGNBMHNrdG84cUQxd1lqQmJIczlScU1jNk52Y3BtR2tXeDNWdWRX MTkgakk4UkFnIEtDRTNkdi9VdGFnNkQvdE1UdHQyRmJXR1RtR21HTXMwa2hiK2xM
cEFCR0UKVU5vem5MZUFPbGhoQzJTYnF4OTd3OW9jYTRkazdocVJkZ0pRRGNLek93 Ym9xa2sKYTFVQmVCNmJId2pPQk4wd3g4N3pOc1lHcjg3YlBEa0FsQlVsb0RKRjYw
cwotPiBzc2gtZWQyNTUxOSBnU3hQMFEgQ2RUaEUyV1ZGbGRtZnlIUEtTQXk5MUZF RQotPiBzc2gtZWQyNTUxOSBnU3hQMFEgOVM3K2NwalE0Vk1rbWdSL2srbXg2bkF2
djYxZ0hBUThlV2tXTHNvdXpVSQpMdiswMy9QNUtCb1hkbGRqR0Nia3FXTzE1ajZL MTduekNpMFA1QkFBNHJidERpYwpCbWQreWk4cTllUnluWHZaMXZWREpqZnlwL1Ex
UXljSTZqM2YvbzVuWUFzCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBYL1NrRjRaRnFn R3k0cWhHSGg2SkJPSkNZCi0+IHNzaC1lZDI1NTE5IFZGY3c1ZyBwdS9CeklwWmpt
RlNLdWJ3cThteDM3WmNaY210d3RmZzhCYmNpVXBwVGlVCjBkM0IzZC9zNjhmTTZV TkxWYnhTTjVxNVREOFBqQXhRWHlza3FLY202K0wxM1RNCi93YVFOTGJGNmYzZzhF
R25ySkVoQWxQQ252WWFlWWZFMlc5dWtUN3VvVTgKLT4gWDI1NTE5IE8yUU1pWGFr WkpFMDd6V1JIcjR6ZXcwUys5UkE1ejdFOW91MWMKLT4gWDI1NTE5IEk0aGh0c09n
NzUvZVpwalB6aklkWmJGWUQzTnJiRjNzdzY2MUp6MkY5M1UKR1VIWDVyTFpxem5F T3B0ZkNSc3NTa2doUGs2c0NKTTVMOENPRjJ6KzlodnBxR1EKUnB6azR1V3NHUnRR
TmRNWE9zZStLanRTdlU5d0NOSEJKdWhDUjBCdy9vOAotPiBTJCd2NyFYey1ncmVh WmNrWHArZ2dmMUdEaGovYUdndDVNNlB2UW5VaVdnOAotPiAsLWdyZWFzZSAlUSA1
c2UgfE4mYSBXfms0TC5FPiBiYmx8IGRFV35mciNoCjVZdHRiVUtMMWxEMlJ4b1F1 WX0gJwpCMG1tNjBPMVJRMGRlQ25KLzJsblFzZkN2LzNDOGcwWEdSSXlBUjNwCi0t
TGgxY01XTlZpTEtndkg0T0hRVjlqVUJGMUpSaE5tVlZWR3VGenpkUXY2eXJtbmkK LSAyY2hHNFNmWFBQWEsvb2hxTUxVUXdKL2p3ZkZWSHRDdFlkREJyaWJrVDg0Cis5
ZCtqRVN4dnZENXdoYkpjNHRWYXkvN2laY1p4YjV0WQotLS0gOHlEVTVOSmlNemNQ gfdBAb92J5/DuoXUt8OirgM7bXucabAp8/U5Az0nmRkGawpSZidB9ecPYHfcdUGp
TW5ISk1DeDlEM1RoQ2JtUFlyTXRKQjdnT0hiend2VQqrUFvr+76sKn0ldBmZMlEW VIv8roO6P0RbbfYXh3szT1YmEMyOXMHFM0+Yunq3u1ca1EHCZDV6Feb+i+lXIBJU
U2k85DLo2KU+/+GtbkZwVXxxIZHMLpoJgghHk9ptdalUgLGcl0X15x9jVaw8aeta GST4oupwMET+ChVT1/yg7A9o4FY68+FgLjGwE1qeHN8gQr6aMz6/yml/z1WzBEXW
hbeOHotRHY7bC3z0S74riTk3xDMR1eT0QGhDMWHjfo8SkCftOYBlFfhTftevdep3 XEv5fVxGj39eBiq08Z/kCgt5zVDod8RxEq3S3kt1KX5JD+mpGYn2z5CMGhn7fclM
pKMZsuQMwH9JzxgUfcxIcWE975cZzrEJ85nfWMGvdSjcg51KNxP/UUPRxDlcbCEf mj37LaVbcKfyVnwRlLPoN19NeqR+ltM3mu6ibjC7cOQ0E1D/zjQMIxtzNzmZRFgB
9XX5apSzNsTI3ibGD1n6Qwq8bdVYDMHmy5pAhw4l8L+SdoU1tGdw7JOA16sMCJbx l/BEOsX25Zv5vJgLZBU9rMfybNVAjDroG5V1cCVDRR76TP6HVJIXSriyOW5xSFCy
T4bV0ky/PGRonjJuCyDBj8oe9vMe1ZI1O/ITtktekS+wocxBs6QXlY7pIZMlGUn2 Li/VyhWaUXRboGq0Nt4vXWuOTlU/tenlBnBc+d48x35VCExi9IEFpIHj1fUwM/0V
6m59ZEEaf7R4/MdnmBDNDkQuyXaKc7SaTc6h5sKWzXdYScGUKvgUQ7U/WJ2ItUTC dgOfY2WRH9C2cObUc6W51FIARkp777uPXRbT4ZXRDjV18vb18CmwLQQwYupQYnZk
N/Xq07GkZZMt5MYBlyEr+/mKWlcy+ylJPGb7EswvQWaHoeM1QF0XLZ1v+W/Xsso0 c0hZHvoxDwg5QirWxPhuO3bWDqIvHiKy1LYgRrlvr4Wpcb1l0lAYSGX2r1+QVj8z
seIoz+geSu9a02kwfsa8WvWXdIAT5X2pNGPClVNzjQ23pfQfQuW8ZQrGmIFR4g5A tA+zJcUaPkjUSpaqF4LNVWXrTWEN330gQrVk1knWqPl+hFPoyFEHP50PNYr3yxS0
58T1K+vGLdShqqVGyJFMVrSuOzqX5FVmZalu7/++1IQfiRGUlrHKoPlKWnCfFEOu VxbSpg46cXyxi89ghwlXBqI4LRtWlheUoIOuNyLxvXZECwCI2kmt+XBFph5lbG7F
AYjaPeEFX2ByxcqfMK1YVPvUufdISUQeaQOO7mXGE3FqB0oUqmRIUiWZATwhq3Pw UQaH+ve+trb3oYkkG8ZprCljUC7HvSyt31UIRF3l4sLsULQKHqWwVD/2M4B0N5wQ
p5QdcySTnmMpD/w05hvwski77kCdmYuHlMlLZez/kfhTnIGXris+Vwi/V19bsZ8G IzIJkiuWBBE8IX/tI5vUlGx+QWSxmKdHD2mMb/GeMsbo7lOY51cWe8oxe9WcYPhB
zwaZ/Xr6WNC+df5JqSfTGREnXZPFRDkaTt3ri5/eEm6BqliuYjGbuiKsDECi4+JX m4h1xPm4FLo0vHCnWIkXy2o8JYr6fmpjzslC++wYMEbIH3gRBKUVjgUGHywVIXSa
bHpH6LBBoKQ6ms7jCAn0Ls4cUKF37PcjGAOuWnzCSBU+REht1EDfHzx4C7hNiP8X uwzRULUiD8uXFNT3cZ+YDnAvZkuYz528DBKjd5jNen4akah35wQ+oYoGuIhUKkGL
87NjEqJbwE9lORho0hQJRTn8uriQcidlVoB3se2SYKbMy8UA4NNnxN9PTj0TuQjL K59+hTyctWyEGi+fCl1gah2JJ6aF1CXK69ON11YkCEVCI1SK1o1no/0NZj2XtepU
OD3LtqHBElqNPbGNyyEAAJmMBmmkUvPPXlGQ0D99b1+jIdHzYSRtOLshBFykqWYQ MgXln0Pz+pOTZzcjCWhYTO/dNl+Xj6EeeSjjWHqDYg==
LJD61duhGqcQqcLx4+JdQ+oVcfAI2nG7YINnHB0OmS2DOZvvwqQ7ASScSujUWIjA
LNQxu3ruMz+bw/G0tYZBBiE=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,11 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBEcDNm YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBvL0hp
ajc3a0gwYmVSdkowak1aakJ3VWZ1Rk50S1JIS0ExVktVSW9OVWljCjJqbUEySlNK WUs1VWxPVlpydU01cjd3Qk9qd3hvWVdvK1VMaUZNT1YzQ1BjdWhvCmJlSDRDSFBj
a0xyT3NPK1BBMjZzN0RrLzhwVitvS0pzQ25iSnJSc3FmM0EKLT4gWDI1NTE5IHk0 ZGVmVGV3Vmp5YitGbm50aU56VDZCc1hTdjJmSGhEa2dvZWcKLT4gWDI1NTE5IEsy
M2pkWHgyMHR1WHc5bE4xWTFDTndKdkhRdTg5bzZIWEU2cm02UDZBQjgKUUY3dS9p RHVVT1F5d0kxN2VBMG56NnJWYTlEeFFXaHg2VnNqdlJKTHhoR052akEKZjNObUtk
U3h1L1ZvTkFPdURLZ2tSYXJXOGNZZ21KVGdIbXdhSUJrd2puYwotPiAoL0RtO0lH RCt4Q2l2R055TnJCSDBrY1lWaUZibk5iUDhnMlhvZkxRRkhpOAotPiB2LWdyZWFz
OS1ncmVhc2UKVGthN0ZSU0ZFTTg5YW9UOXMwa3RnSzFlMjE2VTN3Ci0tLSBwMEMx ZSBMdUErIHQpI01mVENmICFrK2dRdjBbIFU5UyI+KjQjCitmdU4ySDhJMDRlbklD
Q0tQckd3SzBwUUE4SndMV01kUjVrOTdDWmxlcWs2Zy9TZk5yMzhvCrBXyLBZGuSD aUcvREFqdVNtb1lFZWwxZWo5VXdNUGZQWGt6SVRKaUI4cTcrWEx3NThWZ3VORkor
dJodNI13obTM3UvX6hSgQ8Su+J3fOKr5NibkhQ0Auvlr2tUXhhDm2WOUlHjqVTq+ cy8KbG9EaGV1dGVDQQotLS0gQlFJdWpudnkrcmQvbEhpOUM5Y3RCWWRGMEQ2TUV5
jWLSyhioDlIEyBgk8Zrl7KGeDzBi eTBFSnBkd0xnYjUrUQrxdaCf14h8hqRfdnMorggnbuCDMRHY7nAnGQ1ET4CBlCog
/Rp52aNZHfLh+BFFZazenI7qrvVvEaaB2ZVKa0Z/F8adsGHSGSwz+saqWw==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,15 +1,13 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBzaEo5 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrVktQ
RzNndHBLMUl3Z2txdVZoOVJBbWsrTVJwY01WeHQ0VTBaSm5VclY0CnJLYStYNEI5 Y05RdDFyeUhGNDBiK3VHNzlrMVhKWlBJQnhodkUvTTlINUZ5K1hVCjJ5bXo2cTd1
VTN3dEQ0ZjBKaU1PZSt3d0lldkE5VC9wNHdWazNWV2F6WWMKLT4gWDI1NTE5IEJ5 a3FCaHJTNVNaL1ZRcDhuTENuZVlhWlpJUUVndVErbDVoR2cKLT4gWDI1NTE5IEVj
amlzTDhCOFF0TllPd2RsME5Cb1lRQUZPTGNvOEZnL1J2Wlpnb29GblUKT2t1NFZy VTErMFVTdHBoVmtMY2R5SmJSdHV0aTJ2SWZNc1hrN0h5S2dKUnFxRFUKTHpyaHV6
blNZSHdxZjlHTlZmaTFYT0laQ1IwOCtDZ21vTjhxM0owdTAvawotPiBLYS1ncmVh WWFYME5xNndlSklvNU9GSEFrTFpnc1cya0NMQUlqc1Fhd0hNNAotPiBoRSMmKiNW
c2UgRX0nVGtpSCUgNVNDWCVwIDBuPjM3MwplK2cwc2htQ2RLcFhUZ0RSc21uQlFV Pi1ncmVhc2UKZDQrM2piclMxdExSdUZqcmhVV3l1K3RHVFlOcFZzN1IycnU0d09k
Y1QwSStOK3lKYmVVQ0J5RXA3Zytaa0JoMWtlWU9qMHBLNktFZWxtbFpDCnJyS0JJ V1dwREZDaEcreDQ0enJYd1FXMDd3d3BVNAowYlpwK1EKLS0tIEwrL09nY0FpSTlq
WEcwbndYbERreFhLZlRyQ3E0czB5NkREancxZk5BTGdWRkR6N2NrZmFrbnhSYlZZ bFhQTUtHOWt2NWV0TDArRy9iaFRFTEIxbms4SmI0ejgKmJRGof5FAIPpGn+u6PDh
NElHNEEKLS0tIGVLdXAxU0ZaZVkxaHV4dEZNNUVuc2J4N3VRMzZzTktSMDY3bDVB xSQMKrpFnGvjKs2FicG7K3C19YGVwvMds9XGYzLLdugvZgykzZhq13XK/mSk2b9r
bWtmUVkKigIZ3J0s23vNzmbzJGjSMGBXK6o6xnsA9HXeQZ13VgKv5Qv+UHu+Z0g2 9xkhAvCQ0p1ikQDyX6SuLwJzsJpa7V7wHbEF5HJXQ5NrJUOFwftzxSqYodtP29L4
TeKdQSrHbDB3ydIxaiXsi2ivULdrIMCyd96rEJFxrkVuVqSZE0ehG5j+o8lKk4OU LiA8sxPzNeqhFYT/C8Ea4lDzgnXCjoWtMcZCpfWMMtOJh8fLLw==
PDe70slbZrVYDSu+OOUOCVRSopZreCURlYn2Pc4rjvrMAn5r1r+/AxjZMdkmmQZ0
l0wMBTus5zZzKg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,15 +1,13 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBoZUI4 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA3enI5
bEdWSW1pcDdMYVRJLzdQOWhsdTlZMmlyZjRVeEFwU3Z3NzVFa3lBCkxRZ1FYeU9D NkVZMkxncHRiSFkzRm9seGdwdGNPM2ZFckRoWkZFNlV3Rkl4U0UwClJ0bUZlUlFs
L2dramp4WFFlREZ3NTFnWUs3clVEcnBhLzExclVac1M2SG8KLT4gWDI1NTE5IHVZ MVNsNmZ6aFFYRjJSQmNWdjJMc3F4cTNrejMyME1YRGdQVU0KLT4gWDI1NTE5IHlR
bk9QYy94Tk50c1dVanNvNzhpYWNqeFMzVVR0eTQ5OXozMmp2VFlad2cKaEdvUnR5 VlI3eGVMcS96a0ozWkx2b29wTWtIbFFCcDJEa0g4dWJvdnhGQWFwMUkKZjQ0MzlQ
ZjhsQ1FRaittQXFkbnRZei85MmtWb3pXRVFsc0RzNzBPMXFMWQotPiAzSXJZb0RE VDlGdkdxNG91bDV2MFZXazM5SlIrUmduYTJacGtXQitnTXU4UQotPiBNQktGOG4t
LWdyZWFzZSBudCBGIDklTWIjVnwgM3YvCjRVYUd2TForc0gycnRBR05MbU90QmNu Ky1ncmVhc2UgZzddIElDKW0KZTFiNlIvcEt6aHUvY3h5VFVtb29ZQ0RGODBtTUF1
dXlmQVB2bnZyME5heXlyMUdGTmR6SVd5SHcrTThrZEJYRlpnUmdmWnkKU1lyNjQ3 TS9Ta2lZZDJJUFNyOGp0aU9LCi0tLSAxa0ZNWnM2b2loNzNFMmd4U1V4NUFnZ2RO
T0J6b3NPQ1FYZnhxTjFrYmN1UUJzMjEwcDBwSTJkTnlmeHl3WmFFTXB4eUVMWm9i SVRaUDVpNHVHMUFSczNOcVZzCiJKbkbVr3dPswaIeb/dlP5REMZW0NoxMluj8R73
NExUZzM2SHlLLwpiZjQKLS0tIHdqakpMSUNOdnlBcVA4RGJHR2d5QnJNT2dVclZN AcCimbLRWY2KAOx5XU/ci2auvMqjlqMExlp608OwaGHcpmoijNZQsKgTAW8Z4z28
djd4WXBLSUhORktzZ2sKzMjxqL3UPrtGmXDijdfu0AwxLJooK7ZKauYvXWSuZUrR 9UbAMOmSWByLfgAzhoN4Xob5/40JjI2f3wFYwsAf0f/j6dLc2lmqxkhd+Zcj76Yj
vl5i1QPMEEBYEl+NaZIFgxAFqWpAXHQ1VxSijMWxNjKUd1Chq0tbLrpbh9wXJflK t2WbVgPlBMqPQIoFd6TtwJweqzzGmLI=
SW19Wyqc9eTb8BnFoOSYWpDvAs2Lbyr2kJkOj2TNrwMv8nDJdOB8XIPlV5drCj1q
Dx/1zWqm6NMYxsep6eZkv4AzxA==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,13 +1,13 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBrd0pM YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA0N01m
TGw1anJNaGoyQ3lMUis1cHVtRWFPcFFNZk9Cdm9TMEh1QTdKc25ZCm9VNzVQcUxE Z1RiUHFFbmlDVVgwTWQ5Nmw3WU1NckVFcWQ1SGVsQlZLdGIxSFJzCnZpL3dmRWdY
Njh2Wi80RWszSU5NczRNcHpVYXpRMzJNcDRsdGxyWVZsUDgKLT4gWDI1NTE5IFpT UlVaOW0yT1ZmUXU0VkFHNmRzbFk4cEt3dW91MHdnR240eVEKLT4gWDI1NTE5IGtC
MEJVUkcycVFJaVFOUURoL29VT3R0MVJCWW04NXVRVEpKY3hlY1lWRkEKcENya1Jx RTg1eThyRHlSZ0VsUEVzUm1EYVFIVHZZaHNvY21mOS9mTnlRbW03aEkKQjIraStT
VnBCMVBrZkc4VDkvMnZoTllCL09vQ0VOZytuMnRvYVQxL2FldwotPiAzLWdyZWFz WE5sRUx3S29CcTRobHZVQXJDQTQ1YXg4Z2c4cS9zSVhVVElXcwotPiBoM09vUG0t
ZSBCNX0gIiB7InIsfCAkOT9uM2UKUWpSYTZ1dUo3SHNaUlFibTl0UDhTaFh5Mk1n Z3JlYXNlIF4nRnwkeSEgKTRZIHIKT2FXTWZmbW9jSnkrYmp0WWVDVTZHdFFxcXJt
bFp2cjM5RGhqU0s0Qm50Zk1pUVZmT0R6ZjBoUG1EUGlKbHFzVwozQ2t1cWVDVVAv Rkg3S08xVGZ0TVVjTHQwaExFbkh3WDB6bWJkVEFKYXpQUDEvSQpGNXY0ZS94SVY5
Q21QTjF3NW5UdTBZRldnL0RmSlV3QndHcDB0d0lvZ1RHTTByS1ZwNkNVQnU3WmVn anViSzJ3NlNOUmp0eUliYms1Smd0RUVXVGhxdlV6TkFNVkpzcwotLS0gQnc2Y0ZS
ZwotLS0gb0Fxb2FsYzgwRjJwSUF3ei9hZVR2Vk1ORDlIMWoyZ2RTd09hUmtvMWpD aGNtL2RwUjVxZE9uYlpBeVMwd2M4RTNsdW0wVWpDd2hLLzJSWQq07wZpB40EpZog
cwrEjdaYfoGZ9i/S97xL9QvA/yii+sJLeuUzzv7a3DE661eQ5ezurV8Qz1tIhxWG fW3t5Uokt7EZL4V4RX9PFyd48SaEd/xR1FiEL7jg8IJp0dY7hdfnzObQbueCwUOi
RsOppaaj1podFx3U1x7QQbLO6zQbJA458RMjYgc= lWOfF3n8XpzS8uo5TgLWLtY=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,13 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyBHNWg0 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IG44Q3BVdyA4bGQr
WGRGZnlTdEhsRm96T0ZMOWx4UUxkTitJa3hMWDE1dVkreEtEa0RVClpvR2I5NGpz dzJZbU4reWI1Sk45QTR3UkRoc0NvaDBFcUwrVWlCYWUrcWtYZGpNCm1PWjVzRVlt
aUF0N1VZU05oWXUzTEI1TVBLYlVVang3Zzgwbi9teDVlQlEKLT4gWDI1NTE5IG4v UDFKY2ZSZTg4S2pVZ0pDNzR1WklYQ3pEclJZLy9kKzdGTGsKLT4gWDI1NTE5IHFO
OXRIbzhaZEdXc1pjTnRRWHVxc2ZTcmozSlJkY3lyOGtvd1BVeGprVUkKdUNqSW94 TXVRK2d3azg2cHpRanhUNXp6YnRsZW1MUDJqc3l1bnNYNUhHaTIzMVkKWXp1M09H
SUIyOWtsNU83cnVOTUxNR1BvWHJPczdzUWc4aGp1MjlpZm5ESQotPiA2KSV2PVx5 TnJIazRmb0tOSnE1Q0E1dERiaHZCQkh2YzE1cS9zRUhwaEovMAotPiBzPj5nLWdy
LWdyZWFzZSBqezVxOHc9biA+aD4tP20mXwpwRCtMUDhmcVhGNXpCZlFmSllpdDVp ZWFzZQozSThRWnJCcVFFRHpoSi9tZnZMdnJoRlFud2VISHBHSThMem9qZVVWdS9C
SmFZelNhZnJlR25DS2l2MlQ3ZGFtdGxkZEdEWVNrRlk1VEZBRm9GMHBFCkVlQ1hp VFBDVEVzbUVCdFU2Qy9PaGdyc0FaCmk3UFZma2ZiR3hmWG1sa053bDBnY04yZ1VZ
WnhOTGl2R2s5RDRKN0p5TmF6Y0cyN3ZlR2pDZlhMVjQ1c0FJN3hCbFEKLS0tIEFT TW9jZwotLS0gMDVSaE5aakxHenFPVXpXa1JxczlWQ2x2VGNuQzdwaWZFTTFTaUp6
bjFiRStXMmJueHdsRm1nU084dDRpS0tBT21ENzZFclJXbE11NWJETm8KyMHU+tZY cnRmZwoomylfwjD5A3N21/mk1Wtt8f4bsK747iZz7KT34kqmoX597rbGYxyip5lg
QELtZCbXKWnP8QC6V84JIFAxoRslACwsIJZpogcZO/IFIV2RGunGjCJk6QBmhOPV VLZV6CY4LLRjnnSKoC2hIXU0dgudAmvxhztuaQ42fOc=
kJXRcGO/ndYjWfuU0U3+9HtPocnO
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,11 +1,13 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBOZ1RV YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBzc05k
VVpOZ0Jhd2x4YklMOHdkNkd0MEM4ekZiYXFKMjRIdXlZVDFkOTFZCkRreDZlK3Bo SWtwMW9tdzAvL1hYenU4Wm9MTGF5MDIzS1Q1eHR5TDNlRHkzWEVBCjBWa1IyaHFr
WmJ1MDBxSU5UYzRuUDMvdnpVc0prNFF4MjM0M1FaZmg4V1EKLT4gWDI1NTE5IEkz MW1Xb0dSU2tVTlhuT09rTUF1Tnp0Um1EdExGSjk0ejJJSDAKLT4gWDI1NTE5IG55
THNsVDVCbU9KYWpXL010OVRmNjBVVmVyVzhRZW5McVFJcnA3ZWJvZzQKOE1lQnVX M1RVRy9YK1dhZnRFMWdpakptVkNmaXJyOWJxSUlLcHV3a2NHa0N3RWcKQ00wUmhY
Nk1rWVAvS1lpbDEzb2ViUUE4RlB5NnJOZmNoUGdUMGNuMk1iMAotPiBuYVwtZ3Jl UExuTXZ0bWhjQllQOVB3WnAwbnk5WjlURDdpQ0pqNjVvMExjbwotPiBPfj14Slot
YXNlIHdYXzh3MSB0TyREIGpdTjheeQpJZ2pYUyt6UC9vVmRNZU1uaDdvR2ZUNG0K LWdyZWFzZSBEPyB1O3spbCBYPCx0b0RQIFtTUmJUOAovelJwVUZibjBibWp0MmZ6
LS0tIHNCRno2V21tZU9XV1UwR2IvZDdkWEMzZDI4V25Yb0lvdmJadXNEZFV6TEEK WFNVMDZkbFJOMExlaEFUbFBBWnROWVVtMkNvR29ham9pV1dHVDV6M1BVWjBldU1L
81uT8S3QJNe+mVadi/VpXSPEP0Ygzm0/+1pB5qqYlSQEWTHqS55gCyFCwu+sjaDq CkptRVEyWjNBc3dXdkFWN0NlTld4M3lnCi0tLSByMk13SzY1L3R0NlRCVG9lcVor
DpYTSm1JAk5ql9NRj4fJvCS53lJZ4zo+5c0iJKmuRg== NVVmT1hxdnpSL0QrU0k2RWxlRUY5SldvCiBWgIk3pt8hcWFRsH6oleoX56bT+nz8
BZx959QwOE0of9n8Prfnviq15L9Uan8yL/CadSS+0kyir8AHhl3sV/VLFe9nlZZ6
Zg81EdhQXSQ=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,11 +1,10 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBBOVJi YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyA3TXZY
SXdGVDlXWmVGZUM0OTJPUWFYem5qZzAwZWxhNzhpT2t1VjdZU0ZrCjYxWUE2VW5o OTBpcmd0WmplOWFEbmMwTjVidC9BSFh2OUVqZXo1bzRvcEFvS3hvCkx0NytPaE1Y
cGFLZ3g3Y3BpUWlWOUtUYTg4MGZXVHZvdVV3eU9iZW0ybE0KLT4gWDI1NTE5IDIw NDliWk93SnNxb3lOdlV6em04bllsVmZuVllwYnZ0SytLZlUKLT4gWDI1NTE5IHFu
QmxaWTY0WjJFZUd6TUxqaHhRelpRQ1hGZVBEcm43d3JYUVhpTWp4aGcKVzhJdFFu bTgzM1NLWXZmWFVqVTQ0em5XajVEbkQvV1JxSXp3anZFc3EzeTdHQVEKYTc3eTVv
SEhUUUZVNVk1N2tzekpzUS9RazRCcFBhb2xxbkhRNEwzVys5cwotPiBkeE19PHEm cUFyYjU0UGErc01GclRhU0xtUWNzQ1F1cm45d2NVdHdDNWNWOAotPiBvWFhMLWdy
LWdyZWFzZQpwR0xsb05JVlFXQTZZQkJSWHY0akNRdjh1eXFnbmFDWUlCM0xLWXBi ZWFzZSBQMV9mNiBrdzVuNSBOOSkKOU9BZE5WUzdIbncKLS0tIGplTzYyQVNBR1g2
QkVuanloRQotLS0gZTkrT212MXdsZy9Kb1AwMkFHU3VsTElweGNlYkZ2UWVXRzkr N3VUUHRCVjY4cjBGYTV4akpEbGNPUm9SRXhvUzRzcDQKhBEb7xKAjU3SMSgsVxBa
dnB0SHRnYwrveLSY6SdUDO+QH7WGniLIOPcECTQ7CiTj9lwD5Hm0rYLdvizolb33 8KA0Rh6lgJ0HOLgfBI8cZTzHcNXeIOgOTae1GmStyVjUkw==
CsGX/kSEI2bD
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,12 +1,11 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBrTW1E YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBsOXZu
ZDFSRXIwbXZXUlNJbHZCVjFzMzRxTmdtbDQ5eWVOWWp3SEdSUERrClVMeFRLOGUx WENWTnkzdzgxVDVFY3BXSTBOUGgwY2xyMm1EQklDTG45V3JraEZrCmk1TjFMbGg3
U0dmT2ZUUXlCSGhJdE5ibkZLMmZ2VmZFWU9PQXpGZFRPQkkKLT4gWDI1NTE5IDIw WHB5b2s2WEZjV0lIT2pGci9TbC8rbUY4eVhhZVFDdVpHWkUKLT4gWDI1NTE5IG0w
VXd5N2EwTVdhdkRYeVF3c201SnV3TmxnUGpOZWY5bFJaQWRWMWxQVmMKR2RNc2pE RGpobG1sNXFBOSttVUdEd0RjSHpORm5tTVBLSG5iMnlHeDd3MVJ6MjgKNktpT0N2
aUs4ZW1XSGU1RzM4bHZYQks2cHZWUkhZN1hob2d1QnM3cCtlMAotPiB0XENxMSct RDg5S3A4clR0RmltNmZ6bVdBYklONGwycU00ZnFQMTJmcEhpYwotPiA0bFlqMi1n
Z3JlYXNlIC5LIEIoJ1w6Ci93eE5lMUxDQjE3dWI4a05wUE5sV2dWN21ZN2lFRThv cmVhc2UgU3ZAOyArVndDWCB7RmZiIVd6YQp2dnlBOExZQ204TEpuVy9vOHVNc1ND
YVJGNXNWaEtmbjVMaXhnemVuTXhOMXFtNkQvbGNuS3oKalZ6bEtGdHcxYnZNb0Zy d3dQc0ZPTUJaWXJJVFFjRzhqMWt0UTBzMzZ5elhiRTd2dE1qRFpBa0EyCgotLS0g
YnlGTDdoVVdyeTJpYjJjZkc3alUyV2ZGa0taeEFIYTdiRnZmYmRjR3BzNUp2Ci0t K2FnWmJNampDL1hiR1diR1lKNEdtR1NGanhGZEtpVkN5Ynk4QnlLNDNzbwoKzCe8
LSBROCtSMzFNR3hTK1p5NVhGcFpqM0U0L0MwbWpzNUNTUWUyNEVXbzFFMGpjCnot S+esi+100HykYeL6bKhoa3tuo05x8qCn2d/fAehnJDecPEnpqYdDXWOWc/3x
A6mYbp+jhpoyjZidXQfzLVcu6y34WqAfJZsfT6l5SJONVfSvSw+iP7XXW2T5OnE=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,12 +1,12 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyA3dDEx YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IGpJOFJBZyBOd0ZS
SUw4QVh5T3QySHFFemo2N1JWTjNCSGRiS1lmRTkxVEQ3S1NKR2dNClZNM1Vwc3dF aUp4RW1DaWxTOUtrbEtUaGRyNVYyb2hXMWdmN1pqd2poSXM3ZFE4Cm0zMCszMGpK
elB0Unk1OWpUb1RQMVpSTUpJUDNrZzFMWkhKK0l1dXVBYlkKLT4gWDI1NTE5IGRF Tks2UjBFZnhGVnhWYnBEcDhYakE4Q1d0aythcnhTWHlxMUkKLT4gWDI1NTE5IFlI
TTZlMjdaamlwTUJzYlVkcVIxbmtybkFwakVtK2craXVBNVZraGZ1VlEKN2VvaU5r Vmw1eWxPRHg3REhrOXlORURiSzJJcXAzYTF1KzZLYXlNSGUyR2RTbTgKNS9nZGZT
VjNRS2I5WE9kVDhES2dWTUV2cEVJaXZxNzRUcFo5blhGTDBaawotPiAxXCJQemxa MkZIalVGc3dLMUN4VmtxZSt2NEV0ZTc4KzgzSTlXelNlNWR1cwotPiBIL09daUJh
dS1ncmVhc2UgcDphKHFVTGUgIUonYydBPgowQnc2Wk5yS0E1bVBCWmpOc25MWWs2 fi1ncmVhc2UgNmVkIwpOOFQrV2FNS1Y3RVUrQjB3cWJWZ2xBU1ZEUmg5UElMVEtC
UTR1dVlJbnNXYUVJSkx5bWFIcmtpT1lPSVE3b2Zpd0JaTGZWcEtjelFDCitQcy83 Yi9hR3dJWW9QZDl6UDNXSVVFMFBUTHVqY2lJL2IyCjRlNWd6b2RETXhGMUxiTnVR
bEVvM3FNTEhyWVVFS21tS0VQWG5OOHFza28KLS0tIEZZeUZwVGxUdEdtQTZuYk5K amtYCi0tLSByclhCU2VUK2lqTmdQRUhZUEdCV3RoYlpLRXVtUWZpT0R0WXBiaml6
SHJaUDhHZ0JqbGNFSjJCaVlQTVo0OStkMWcKz/w0SnoHxnw71gr5DbXgMl59Kgjy aUdJCnhOnafCdWyJ8JDkXonlnrNbq6oJfkwA9eaksl8otOfQ0pfplHq1/EMtNH3Q
SW4tzNGeRcX2j4YdRjr77TP5UAzpQE30tEcrtw== AWkX50A=
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,13 +1,14 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpOcUlvZyBNalB5 YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpOcUlvZyA5dnBy
RUZRNE1CTUJsbW1kSkxBSWVIcG1RUnBKd1gvcnRQVkZCUXFOQmhvClJUN2ltbnNk YkRENmpNaSt4Y3lOKzhkSm9DbUM5RjQySzZHWms4QXYxNXdLSjFzCkM4M2djbmxt
T1grdVJSTzIyNTBTTGVEckVGQXdYNHdwOU5NbW1md3lGM0kKLT4gc3NoLWVkMjU1 NG5lZlh6V3JNVVpaWjZHOHhadWRlWUl3L2xHK0Y0YjFCYncKLT4gc3NoLWVkMjU1
MTkgcytxUmZnIHZ4bFZSS0huWFBDbUhNcTd2MFhvV0lOY1l3d3ZXNU4vT3dwMmlI MTkgcytxUmZnIEU3TzM2cXBXVDZYVUN1Q0E0eGxyZVJQTm1sMTJtRnJ5dGNsMUcz
emhoV0kKcDF4M0FPK0JpclI5Q3Q5WGxpZWVYbHVWbkNWdTArclZsN09XK3VJSXc1 WTcvMGMKQkJaVDUwQXEwVWhHUW5IRW5veGIxLzRmUHpEay9LNU5QYjd4TkJDTmU5
awotPiBYMjU1MTkgRjRCNVZmcXVnQnJ4KzZoM1ZkdWxYUkJTM1JuK3ZlRWJYdkFR VQotPiBYMjU1MTkgNTVKMGZnV2ttMjArV1hYZUEwV1YyZVRMcmxuOFpZbXY5QlI5
WXpFSmR4NApTbU5qR3ZuN0ZmbzIvMTFsMkdNSGJXSVlrVmZPdnZvcHFiZW45SW9I UElFRld3RQp3OHA3czM3UnVMdlo1L09VQW1IMlBodCtueHE5RjV3cFllSGxndUdN
endJCi0+IDEoIjlcJi1ncmVhc2UgJUE4IWl5ODkgfGVdLihEfT4gWCAreSduPS4K Sm1RCi0+IE5YTiMray1ncmVhc2UgWEQzbDsgO1A7YCV8PjAgNTpiODp9IFVZCmJh
bkI2Wm9LRGJXdW11aDl2VgotLS0gTENqYjZEUUZaWVZEcWQvWW5yTzJEdHRLeDJm c2VsZFBZOVAxRHVQajlielI3WkFrVzRTSU1HOTMxZmcKLS0tIENiSUsxc3E5Q3I2
QUl5aytXdDE5QVMwVHZVSQo+aDbaGNOrz+hTSUQ4IAjDC9EfNwrlXDZtBqw8HkRv UlFvMGJBaFd1SUtad2dzVVB1bkcvQUU5OTdQYldNVlUKo5ZSBZdm7MMSTJrX7RdF
1/Rr737scjrM7Bgt9zuKn6CB0zdeHTW5u685V2hCW/3aTy1eppWMWj3r p3+z1XKPeVBpaQmH4593iCVgxF1OTv6bOL3vS0EwtduRT/htoBbXJmgUeUpTfEUo
IY3DkohGqSbCVg==
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

View File

@@ -1,16 +1,14 @@
-----BEGIN AGE ENCRYPTED FILE----- -----BEGIN AGE ENCRYPTED FILE-----
YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpOcUlvZyBFb2hL YWdlLWVuY3J5cHRpb24ub3JnL3YxCi0+IHNzaC1lZDI1NTE5IFpOcUlvZyBhd2dJ
MCt6c0I4Nm5SMFhEaWNZRTRtNkpYeVQvVGFVZzVqd0E3L2dZdzFBCiszUXZSVENo UllxNVZpK3M1R1FwYmM3OWs3VVpSZzhSeGVudnE0WFdlbDVET2p3Cm9BSy83SERa
cmxqdVFwMFA0elpFOGZoM3B6SW80MEhCNlJoRXV0WXpUeG8KLT4gc3NoLWVkMjU1 cHQ1a05kVnJiODIvdVE3eFZ5SGJ1VU9xQjd2RDVKLzg2eEEKLT4gc3NoLWVkMjU1
MTkgcytxUmZnIHQxR2MrakZmRFJMcjhabGFON2xQU2RBSDNvRCtuV3NwNGJ2bjZF MTkgcytxUmZnIE5hUVpyQ1h1Nm9EWmJ1cEZCK3hVTHcwV3hRQnRZTS9ucUptQS9h
b2lCQVUKcFNzM3paS1ZnWk8xY1VzVmdTWndMK0JCTU14bUJvM3E2bjR2TmlTY2tF Vmc4VWsKYzhGenphTjFSalY2blJzVUIwQmNkTnVhTjczWk1ka2d5eGlVcll0Z2dp
NAotPiBYMjU1MTkgY1MrT3ZkN1pUd0JVb0JWSDByNUNRd1NUd2ZiNVJrc0JCb0J5 QQotPiBYMjU1MTkgT1VnMFY2MHhYaVBRV0hVYU1STW5ETTZaZU5zUHJhMFJ1alJj
NENrU0MySQp0bFpwRXRZcHRVdnN3eitkNHlWc0c0a0NmUjVYSVFXSVNFVHI0b0ZB emVuQWozWQpHR1NQeDgzZDdGRVBGaEZ1bGl1bnBnZnFyM0NEL2E1eWx4cm1NbEsz
U3kwCi0+IHQmKm9ERFdfLWdyZWFzZSBJIFkvRG5JIC9ZI002bmkgNX1hQHcKc2l4 bnFNCi0+ICstZ3JlYXNlIEsofSRTLz8KQzZuTW5taUNCaWs2NHNFNHBoYkxhKzI3
S0N4YzgvK2xqZm1YVkl4ZlF1REVOTGRWOVZRQm80R2NnczlsdFlhTEd1RmVoNjZa ZWJGUWdmWExMbUtnalhHWWEyUjBTNzlhVFd0aUo4cU5xc2ZoeDVWTQoKLS0tIFJn
KzlkVXNpbGZsNTRybAp4RDlIWmRqR0t3VjF6WVlSeTJ4aGZBd1dDNEpMTUhZenZS SjJleTVGU1o3YXhQZ1dWZHFIVm9FSE80VWdyZTg5dmhLWlhINmVWTUEKD84LkcH4
WjZCK0FZcXJORkJwc1piS1FvSlkzc3R5T2s3Vk0KLS0tIDFPODlkZ1BSWEhHUHJK FE9srKKG3yPpq//XXR+dsm3bIUd5rYZazszxqV8XyNqKHD44azPYTqyXwfBWeEoV
QjdZOE1KcFNvcUYxYlFkL1FLNVJETTkySVNYRTgKOipmWGTV9SvGE4KVqgQqGw4e 2vn/iMIpyCCMlSUDzDsyNvrFX48s
CLP4PYlgdSmOATTIg32G/GVTM8NlvaII3q2GNS0Enx7Y8YwnwS2dGkYKVN3Da3b2
WJwMiBZRu/PC
-----END AGE ENCRYPTED FILE----- -----END AGE ENCRYPTED FILE-----

Some files were not shown because too many files have changed in this diff Show More