Compare commits

..

1 Commits

Author SHA1 Message Date
1e66a99352 Don't blindly trust as211024
Some checks failed
CI / Check, build and cache Nix flake (push) Failing after 2m4s
2023-12-20 22:59:51 +00:00
182 changed files with 3284 additions and 14596 deletions

2
.envrc
View File

@@ -1,2 +1,2 @@
watch_file devshell/{default,commands,install,vm-tasks}.nix nix_direnv_watch_file devshell/{default,commands,install,vm-tasks}.nix
use flake use flake

View File

@@ -6,11 +6,11 @@ on:
jobs: jobs:
check: check:
name: Check, build and cache nixfiles name: Check, build and cache Nix flake
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@v27 - uses: cachix/install-nix-action@v23
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,30 +18,22 @@ 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 extra-substituters = https://nix-cache.nul.ie/main
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=
- name: Set up attic
run: |
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}"
- name: Check flake - name: Check flake
run: nix flake check --no-build run: nix flake check
- name: Build the world
- name: Build (and cache) the world
id: build id: build
env:
HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }}
run: | run: |
nix eval --json --apply "builtins.attrNames" .#ci.x86_64-linux | jq -cr '.[]' | while read job; do path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out)
echo "::group::Build $job" echo "path=$path" >> "$GITHUB_OUTPUT"
nix build --no-link .#ci.x86_64-linux."$job" - name: Push to cache
echo "::endgroup::" run: |
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
echo "::group::Cache $job" push main ${{ steps.build.outputs.path }}
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,36 +14,37 @@ 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@v27 - uses: cachix/install-nix-action@v23
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 extra-substituters = https://nix-cache.nul.ie/main
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4= extra-trusted-public-keys = main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8=
- 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
ln -s "$(readlink result)"/iso/jackos-installer.iso \ ln -s "$(readlink result)"/iso/nixos-installer-devplayer0.iso \
jackos-installer-${{ steps.setup.outputs.short_rev }}.iso nixos-installer-devplayer0-${{ steps.setup.outputs.short_rev }}.iso
- name: Build installer netboot archive - name: Build installer netboot archive
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.zst nixos-installer-devplayer0-netboot-${{ steps.setup.outputs.short_rev }}.tar
- 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 nixos-installer-devplayer0-${{ steps.setup.outputs.short_rev }}.iso
jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst nixos-installer-devplayer0-netboot-${{ steps.setup.outputs.short_rev }}.tar

View File

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

View File

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

View File

@@ -1,31 +0,0 @@
#!/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

@@ -20,7 +20,7 @@ in
[ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1 [ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
mkdir -p "$(dirname "${homeFlake}")" mkdir -p "$(dirname "${homeFlake}")"
ln -sf "$(pwd)/flake.nix" "${homeFlake}" ln -s "$(pwd)/flake.nix" "${homeFlake}"
echo "Installed link to $(pwd)/flake.nix at ${homeFlake}" echo "Installed link to $(pwd)/flake.nix at ${homeFlake}"
''; '';
} }
@@ -52,7 +52,7 @@ in
name = "json2nix"; name = "json2nix";
category = "utilities"; category = "utilities";
help = "Convert JSON to formatted Nix"; help = "Convert JSON to formatted Nix";
command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt-rfc-style}/bin/nixfmt"; command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt}/bin/nixfmt";
} }
{ {
@@ -77,12 +77,7 @@ 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 = '' command = ''doas nixos-rebuild --flake . "$@"'';
# 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";
@@ -111,8 +106,8 @@ in
{ {
name = "build-netboot"; name = "build-netboot";
category = "tasks"; category = "tasks";
help = "Build NixOS configuration as netboot tree"; help = "Build NixOS configuration as netboot archive";
command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootTree"''; command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootArchive"'';
} }
{ {
name = "build-home"; name = "build-home";
@@ -120,17 +115,29 @@ 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 = ''nix flake update nixpkgs-{unstable,stable,mine,mine-stable}''; command = ''update-inputs 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 = ''nix flake update home-manager-{unstable,stable}''; command = ''update-inputs home-manager-{unstable,stable}'';
} }
{ {
name = "update-installer"; name = "update-installer";
@@ -138,15 +145,5 @@ 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 experimental-features = nix-command flakes ca-derivations repl-flake
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
]; ];
} }

726
flake.lock generated

File diff suppressed because it is too large Load Diff

View File

@@ -3,27 +3,21 @@
inputs = { inputs = {
flake-utils.url = "github:numtide/flake-utils"; flake-utils.url = "github:numtide/flake-utils";
# libnet.url = "github:reo101/nix-lib-net";
libnetRepo = {
url = "github:oddlama/nixos-extra-modules";
flake = false;
};
devshell.url = "github:numtide/devshell"; devshell.url = "github:numtide/devshell";
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-25.05"; nixpkgs-stable.url = "nixpkgs/nixos-23.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-25.05"; home-manager-stable.url = "home-manager/release-23.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";
@@ -32,17 +26,17 @@
impermanence.url = "github:nix-community/impermanence"; impermanence.url = "github:nix-community/impermanence";
boardie.url = "github:devplayer0/boardie"; boardie.url = "github:devplayer0/boardie";
boardie.inputs.nixpkgs.follows = "nixpkgs-unstable"; boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
nixGL.url = "github:nix-community/nixGL"; nixGL.url = "github:guibou/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.inputs.nixpkgs.follows = "nixpkgs-unstable"; sharry.inputs.nixpkgs.follows = "nixpkgs-unstable";
borgthin.url = "github:devplayer0/borg"; borgthin.url = "github:devplayer0/borg";
# TODO: Update borgthin so this works borgthin.inputs.nixpkgs.follows = "nixpkgs-mine";
# borgthin.inputs.nixpkgs.follows = "nixpkgs-mine"; attic.url = "github:zhaofengli/attic";
copyparty.url = "github:9001/copyparty"; attic.inputs.nixpkgs.follows = "nixpkgs-unstable";
copyparty.inputs.nixpkgs.follows = "nixpkgs-unstable"; attic.inputs.nixpkgs-stable.follows = "nixpkgs-stable";
}; };
outputs = outputs =
@@ -57,7 +51,7 @@
... ...
}: }:
let let
inherit (builtins) mapAttrs replaceStrings elem; inherit (builtins) mapAttrs replaceStrings;
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;
@@ -65,11 +59,11 @@
# Extend a lib with extras that _must not_ internally reference private nixpkgs. flake-utils doesn't, but many # Extend a lib with extras that _must not_ internally reference private nixpkgs. flake-utils doesn't, but many
# other flakes (e.g. home-manager) probably do internally. # other flakes (e.g. home-manager) probably do internally.
libOverlay = final: prev: { libOverlay = final: prev: {
my = import ./lib { inherit inputs; lib = final; }; my = import ./lib { lib = final; };
flake = flake-utils.lib; flake = flake-utils.lib;
}; };
pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; }; pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; };
myPkgsOverlay = final: prev: import ./pkgs { lib = final.lib; pkgs = prev; }; myPkgsOverlay = final: prev: import ./pkgs { lib = prev.lib; pkgs = prev; };
# Override the flake-level lib since we're going to use it for non-config specific stuff # Override the flake-level lib since we're going to use it for non-config specific stuff
pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) { pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) {
@@ -96,12 +90,12 @@
(_: path: mkDefaultSystemsPkgs path (system: { (_: path: mkDefaultSystemsPkgs path (system: {
overlays = [ overlays = [
pkgsLibOverlay pkgsLibOverlay
myPkgsOverlay myPkgsOverlay
inputs.devshell.overlays.default inputs.devshell.overlays.default
inputs.ragenix.overlays.default inputs.ragenix.overlays.default
inputs.deploy-rs.overlays.default inputs.deploy-rs.overlay
(flakePackageOverlay inputs.home-manager-unstable system) (flakePackageOverlay inputs.home-manager-unstable system)
inputs.attic.overlays.default
]; ];
})) }))
pkgsFlakes; pkgsFlakes;
@@ -111,19 +105,8 @@
(_: path: mkDefaultSystemsPkgs path (_: { (_: path: mkDefaultSystemsPkgs path (_: {
overlays = [ overlays = [
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;
@@ -132,11 +115,10 @@
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/britnet.nix
nixos/boxes/kelder nixos/boxes/kelder
# Homes # Homes
@@ -147,7 +129,7 @@
modules = [ modules = [
{ {
_module.args = { _module.args = {
inherit lib pkgsFlakes hmFlakes self inputs; inherit lib pkgsFlakes hmFlakes inputs;
pkgs' = configPkgs'; pkgs' = configPkgs';
}; };
@@ -167,7 +149,7 @@
# Platform independent stuff # Platform independent stuff
{ {
nixpkgs = pkgs'; nixpkgs = pkgs';
inherit inputs lib nixfiles; inherit lib nixfiles;
overlays.default = myPkgsOverlay; overlays.default = myPkgsOverlay;
@@ -215,9 +197,8 @@
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
homes' // systems' // packages' // { pkgs.linkFarm "ci" (homes' // systems' // packages' // {
inherit shell; inherit shell;
}; });
ciDrv = pkgs.linkFarm "ci" ci;
})); }));
} }

View File

@@ -66,7 +66,7 @@ in
lsd = { lsd = {
enable = mkDefault true; enable = mkDefault true;
enableFishIntegration = mkDefault true; enableAliases = mkDefault true;
}; };
starship = { starship = {
@@ -80,7 +80,6 @@ in
tmux = { tmux = {
enable = true; enable = true;
keyMode = "vi";
}; };
bash = { bash = {
@@ -132,8 +131,6 @@ in
ssh = { ssh = {
enable = mkDefault true; enable = mkDefault true;
# TODO: Set after 25.11 releases
# enableDefaultConfig = false;
matchBlocks = { matchBlocks = {
nix-dev-vm = { nix-dev-vm = {
user = "dev"; user = "dev";
@@ -201,20 +198,17 @@ 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 = {
@@ -228,8 +222,6 @@ in
# Note: If globalPkgs mode is on, then these will be overridden by the NixOS equivalents of these options # Note: If globalPkgs mode is on, then these will be overridden by the NixOS equivalents of these options
nixpkgs = { nixpkgs = {
overlays = [ overlays = [
inputs.libnet.overlays.default
inputs.deploy-rs.overlay inputs.deploy-rs.overlay
inputs.boardie.overlays.default inputs.boardie.overlays.default
inputs.nixGL.overlays.default inputs.nixGL.overlays.default

View File

@@ -1,28 +0,0 @@
# XTerm's default colors
# Default colors
[colors.primary]
background = '#000000'
foreground = '#ffffff'
# Normal colors
[colors.normal]
black = '#000000'
red = '#cd0000'
green = '#00cd00'
yellow = '#cdcd00'
blue = '#0000ee'
magenta = '#cd00cd'
cyan = '#00cdcd'
white = '#e5e5e5'
# Bright colors
[colors.bright]
black = '#7f7f7f'
red = '#ff0000'
green = '#00ff00'
yellow = '#ffff00'
blue = '#5c5cff'
magenta = '#ff00ff'
cyan = '#00ffff'
white = '#ffffff'

View File

@@ -1,8 +1,7 @@
{ lib, pkgs', pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
inherit (lib) genAttrs mkIf mkMerge mkForce mapAttrs mkOptionDefault; inherit (lib) genAttrs mkIf mkMerge mkForce;
inherit (lib.my) mkOpt' mkBoolOpt'; inherit (lib.my) mkBoolOpt';
inherit (lib.my.c) pubDomain;
cfg = config.my.gui; cfg = config.my.gui;
@@ -11,80 +10,33 @@ let
name = "Monocraft"; name = "Monocraft";
size = 10; size = 10;
}; };
doomWad = pkgs.fetchurl {
url = "https://distro.ibiblio.org/slitaz/sources/packages/d/doom1.wad";
hash = "sha256-HX1DvlAeZ9kn5BXguPPinDvzMHXoWXIYFvZSpSbKx3E=";
};
subwaySurfers = pkgs.fetchurl {
url = "https://p.${pubDomain}/video/subway-surfers-smol.mkv";
hash = "sha256-fMe7TDRNTymRHIJOi7qG3trzu4GP8a3gCDz+FMkX1dY=";
};
minecraftParkour = pkgs.fetchurl {
url = "https://p.${pubDomain}/video/minecraft-parkour-smol.mkv";
hash = "sha256-723pRm4AsIjY/WFUyAHzTJp+JvH4Pn5hvzF9wHTnOPA=";
};
genLipsum = pkgs.writeScript "lipsum" ''
#!${pkgs.python3.withPackages (ps: [ ps.python-lorem ])}/bin/python
import lorem
print(lorem.get_paragraph(count=5, sep='\n\n'))
'';
doomsaver' = brainrotTextCommand: pkgs.runCommand "doomsaver" {
inherit (pkgs) windowtolayer tmux terminaltexteffects;
chocoDoom = pkgs.chocolate-doom2xx;
ffmpeg = pkgs.ffmpeg-full;
python = pkgs.python3.withPackages (ps: [ ps.filelock ]);
inherit doomWad;
enojy = ./enojy.jpg;
inherit brainrotTextCommand subwaySurfers minecraftParkour;
} ''
mkdir -p "$out"/bin
substituteAll ${./screensaver.py} "$out"/bin/doomsaver
chmod +x "$out"/bin/doomsaver
'';
doomsaver = doomsaver' cfg.screensaver.brainrotTextCommand;
in in
{ {
options.my.gui = with lib.types; { options.my.gui = {
enable = mkBoolOpt' true "Enable settings and packages meant for graphical systems"; enable = mkBoolOpt' true "Enable settings and packages meant for graphical systems";
manageGraphical = mkBoolOpt' false "Configure the graphical session"; manageGraphical = mkBoolOpt' false "Configure the graphical session";
standalone = mkBoolOpt' false "Enable settings for fully Nix managed systems"; standalone = mkBoolOpt' false "Enable settings for fully Nix managed systems";
screensaver.brainrotTextCommand = mkOpt' (either path str) genLipsum "Command to generate brainrot text.";
}; };
config = mkIf cfg.enable (mkMerge [ config = mkIf cfg.enable (mkMerge [
{ {
home = { home = {
packages = with pkgs; [ packages = with pkgs; [
xdg-utils
font.package font.package
nerd-fonts.sauce-code-pro (nerdfonts.override {
nerd-fonts.droid-sans-mono fonts = [ "DroidSansMono" "SourceCodePro" ];
})
noto-fonts-emoji noto-fonts-emoji
grim grim
slurp slurp
swappy swappy
python3Packages.python-lsp-server python310Packages.python-lsp-server
nil # nix language server nil # nix language server
zls # zig language server zls # zig language server
rust-analyzer rust-analyzer
cowsay
fortune
jp2a
terminaltexteffects
screenfetch
neofetch neofetch
cmatrix
doomsaver
ffmpeg-full
xournalpp
]; ];
}; };
@@ -99,15 +51,7 @@ in
alacritty = { alacritty = {
enable = true; enable = true;
settings = { settings = {
general.import = [ ./alacritty-xterm.toml ]; font.normal.family = font.name;
font = {
size = font.size;
normal = {
family = font.name;
style = "Regular";
};
};
}; };
}; };
@@ -115,29 +59,9 @@ in
enable = true; enable = true;
inherit font; inherit font;
settings = { settings = {
background_opacity = "0.65"; background_opacity = "0.8";
tab_bar_edge = "top"; tab_bar_edge = "top";
shell_integration = "no-sudo"; shell_integration = "no-sudo";
font_features = "${font.name} -liga";
};
};
termite = {
enable = true;
font = "${font.name} ${toString font.size}";
backgroundColor = "rgba(0, 0, 0, 0.8)";
};
foot = {
enable = true;
settings = {
main = {
font = "${font.name}:size=${toString font.size}";
};
colors = {
alpha = 0.8;
background = "000000";
};
}; };
}; };
@@ -184,19 +108,6 @@ 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" ];
};
}; };
}; };
@@ -206,7 +117,6 @@ in
wl-clipboard wl-clipboard
wev wev
wdisplays wdisplays
swaysome
pavucontrol pavucontrol
libsecret libsecret
@@ -216,11 +126,10 @@ in
]; ];
pointerCursor = { pointerCursor = {
package = pkgs.posy-cursors; package = pkgs.vanilla-dmz;
name = "Posy_Cursor"; name = "Vanilla-DMZ";
size = 32; size = 16;
gtk.enable = true; gtk.enable = true;
x11.enable = true;
}; };
}; };
@@ -229,36 +138,9 @@ 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" = {
@@ -273,87 +155,23 @@ in
modifier = "Mod4"; modifier = "Mod4";
terminal = "kitty"; terminal = "kitty";
keybindings = mapAttrs (k: mkOptionDefault) { keybindings =
"${mod}+Left" = "focus left"; let
"${mod}+Down" = "focus down"; cfg = config.wayland.windowManager.sway.config;
"${mod}+Up" = "focus up"; mod = cfg.modifier;
"${mod}+Right" = "focus right"; in
lib.mkOptionDefault {
"${mod}+Shift+Left" = "move left";
"${mod}+Shift+Down" = "move down";
"${mod}+Shift+Up" = "move up";
"${mod}+Shift+Right" = "move right";
"${mod}+b" = "splith";
"${mod}+v" = "splitv";
"${mod}+f" = "fullscreen toggle";
"${mod}+a" = "focus parent";
"${mod}+s" = "layout stacking";
"${mod}+w" = "layout tabbed";
"${mod}+e" = "layout toggle split";
"${mod}+Shift+space" = "floating toggle";
"${mod}+space" = "focus mode_toggle";
"${mod}+1" = "workspace number 1";
"${mod}+2" = "workspace number 2";
"${mod}+3" = "workspace number 3";
"${mod}+4" = "workspace number 4";
"${mod}+5" = "workspace number 5";
"${mod}+6" = "workspace number 6";
"${mod}+7" = "workspace number 7";
"${mod}+8" = "workspace number 8";
"${mod}+9" = "workspace number 9";
"${mod}+0" = "workspace number 10";
"${mod}+Shift+1" =
"move container to workspace number 1";
"${mod}+Shift+2" =
"move container to workspace number 2";
"${mod}+Shift+3" =
"move container to workspace number 3";
"${mod}+Shift+4" =
"move container to workspace number 4";
"${mod}+Shift+5" =
"move container to workspace number 5";
"${mod}+Shift+6" =
"move container to workspace number 6";
"${mod}+Shift+7" =
"move container to workspace number 7";
"${mod}+Shift+8" =
"move container to workspace number 8";
"${mod}+Shift+9" =
"move container to workspace number 9";
"${mod}+Shift+0" =
"move container to workspace number 10";
"${mod}+Shift+minus" = "move scratchpad";
"${mod}+minus" = "scratchpad show";
"${mod}+Return" = "exec ${cfg.terminal}";
"${mod}+r" = "mode resize";
"${mod}+d" = null; "${mod}+d" = null;
"${mod}+l" = "exec ${doomsaver}/bin/doomsaver"; "${mod}+l" = "exec swaylock -i ${./lock.png} -s stretch";
"${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}+x" = "exec ${cfg.menu}";
"${mod}+Shift+x" = "exec rofi -show drun"; "${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"; "${mod}+Shift+e" = "exec rofi -show emoji";
# Config for this doesn't seem to work :/ # 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}+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"; "XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5"; "XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5";
@@ -370,9 +188,6 @@ in
menu = "rofi -show run"; menu = "rofi -show run";
bars = mkForce [ ]; bars = mkForce [ ];
}; };
extraConfig = ''
include ${./swaysome.conf}
'';
swaynag = { swaynag = {
enable = true; enable = true;
@@ -395,10 +210,17 @@ in
}; };
qt = { qt = {
enable = true; enable = true;
platformTheme.name = "gtk"; platformTheme = "gtk";
}; };
services = { services = {
swaync = {
enable = true;
settings = {
widgets = [ "title" "dnd" "mpris" "notifications" ];
};
};
playerctld.enable = true; playerctld.enable = true;
spotifyd = { spotifyd = {
enable = false; enable = false;
@@ -423,7 +245,6 @@ 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;
}; };
@@ -431,13 +252,11 @@ 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; (map (p: p.override { rofi-unwrapped = rofi-wayland-unwrapped; }) [ plugins = with pkgs; [
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";
@@ -452,7 +271,7 @@ in
chromium = { chromium = {
enable = true; enable = true;
package = (pkgs'.unstable.chromium.override { enableWideVine = true; }).overrideAttrs (old: { package = (pkgs.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
buildCommand = '' buildCommand = ''
${old.buildCommand} ${old.buildCommand}
@@ -478,15 +297,6 @@ in
] (_: "chromium-browser.desktop"); ] (_: "chromium-browser.desktop");
}; };
}; };
my = {
swaync = {
enable = true;
settings = {
widgets = [ "title" "dnd" "mpris" "notifications" ];
};
};
};
}) })
(mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) { (mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) {

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.4 KiB

View File

@@ -1,257 +0,0 @@
#!@python@/bin/python
import argparse
import json
import os
import random
import signal
import subprocess
import sys
import filelock
class Screensaver:
def __init__(self, cmd, env=None, weight=1):
self.cmd = cmd
self.weight = weight
if env is not None:
self.env = os.environ.copy()
for k, v in env.items():
self.env[k] = v
else:
self.env = None
self.proc = None
def start(self):
assert self.proc is None
self.proc = subprocess.Popen(self.cmd, env=self.env)
def wait(self):
assert self.proc is not None
self.proc.wait()
def stop(self, kill=False):
assert self.proc is not None
if kill:
self.proc.kill()
else:
self.proc.terminate()
class DoomSaver(Screensaver):
wad = '@doomWad@'
def __init__(self, demo_index, weight=1.5):
super().__init__(
['@chocoDoom@/bin/chocolate-doom',
'-iwad', self.wad,
'-demoloopi', str(demo_index)],
env={
'SDL_AUDIODRIVER': 'null',
'SDL_VIDEODRIVER': 'caca',
'CACA_DRIVER': 'ncurses',
},
weight=weight,
)
def stop(self):
super().stop(kill=True)
class TTESaver(Screensaver):
effects = (
'beams,binarypath,blackhole,bouncyballs,bubbles,burn,colorshift,crumble,'
'decrypt,errorcorrect,expand,fireworks,middleout,orbittingvolley,overflow,'
'pour,print,rain,randomsequence,rings,scattered,slice,slide,spotlights,'
'spray,swarm,synthgrid,unstable,vhstape,waves,wipe'
).split(',')
def __init__(self, cmd, env=None, weight=1):
super().__init__(cmd, env=env, weight=weight)
self.running = False
def start(self):
self.running = True
def wait(self):
while self.running:
effect_cmd = ['@terminaltexteffects@/bin/tte', random.choice(self.effects)]
print(f"$ {self.cmd} | {' '.join(effect_cmd)}")
content = subprocess.check_output(self.cmd, shell=True, env=self.env, stderr=subprocess.DEVNULL)
self.proc = subprocess.Popen(effect_cmd, stdin=subprocess.PIPE)
self.proc.stdin.write(content)
self.proc.stdin.close()
self.proc.wait()
def stop(self):
self.running = False
self.proc.terminate()
class FFmpegCACASaver(Screensaver):
@staticmethod
def command(video, size):
return ['@ffmpeg@/bin/ffmpeg', '-hide_banner', '-loglevel', 'error',
'-stream_loop', '-1', '-i', video,
'-pix_fmt', 'rgb24', '-window_size', f'{size}x{size}',
'-f', 'caca', '-']
def __init__(self, video, weight=2):
cols, lines = os.get_terminal_size()
# IDK if it's reasonable to do this as "1:1"
size = lines - 4
super().__init__(
self.command(video, size),
env={'CACA_DRIVER': 'ncurses'},
weight=weight,
)
def stop(self):
super().stop(kill=True)
class BrainrotStorySaver(Screensaver):
def __init__(self, video, text_command, weight=2):
cols, lines = os.get_terminal_size()
video_size = lines - 1
video_command = ' '.join(FFmpegCACASaver.command(video, video_size))
text_command = (
f'while true; do {text_command} | '
f'@terminaltexteffects@/bin/tte --wrap-text --canvas-width=80 --canvas-height={video_size//2} --anchor-canvas=c '
'print --final-gradient-stops=ffffff; clear; done' )
self.tmux_session = f'screensaver-{os.urandom(4).hex()}'
super().__init__(
['@tmux@/bin/tmux', 'new-session', '-s', self.tmux_session, '-n', 'brainrot',
text_command, ';', 'split-window', '-hbl', str(lines), video_command],
# ['sh', '-c', text_command],
env={
'CACA_DRIVER': 'ncurses',
'SHELL': '/bin/sh',
},
weight=weight,
)
def stop(self):
subprocess.check_call(['@tmux@/bin/tmux', 'kill-session', '-t', self.tmux_session])
class MultiSaver:
savers = [
DoomSaver(0),
DoomSaver(1),
DoomSaver(2),
Screensaver(['cmatrix']),
TTESaver('screenfetch -N'),
TTESaver('fortune | cowsay'),
TTESaver('top -bn1 | head -n50'),
TTESaver('ss -nltu'),
TTESaver('ss -ntu'),
TTESaver('jp2a --width=100 @enojy@'),
BrainrotStorySaver('@subwaySurfers@', '@brainrotTextCommand@'),
BrainrotStorySaver('@minecraftParkour@', '@brainrotTextCommand@'),
]
state_filename = 'screensaver.json'
def __init__(self, select=None):
self.state_path = os.path.join(f'/run/user/{os.geteuid()}', self.state_filename)
self.lock = filelock.FileLock(f'{self.state_path}.lock')
if select is not None:
assert select >= 0 and select < len(self.savers), 'Invalid screensaver index'
self.selected = self.savers[select]
else:
self.selected = None
self.cleaned_up = False
def select(self):
with self.lock:
if not os.path.exists(self.state_path):
state = {'instances': []}
else:
with open(self.state_path) as f:
state = json.load(f)
if self.selected is None:
available = set(range(len(self.savers)))
new_instances = []
for instance in state['instances']:
if not os.path.exists(f"/proc/{instance['pid']}"):
continue
new_instances.append(instance)
i = instance['saver']
assert i in available
available.remove(i)
assert available, 'No screensavers left'
available = list(available)
weights = []
for i in available:
weights.append(self.savers[i].weight)
selected_i = random.choices(available, weights=weights)[0]
new_instances.append({'pid': os.getpid(), 'saver': selected_i})
state['instances'] = new_instances
# print(f'Selected saver {selected_i}')
self.selected = self.savers[selected_i]
with open(self.state_path, 'w') as f:
json.dump(state, f)
def cleanup(self):
if self.cleaned_up:
return
self.cleaned_up = True
with self.lock:
with open(self.state_path) as f:
state = json.load(f)
for i, instance in enumerate(state['instances']):
if instance['pid'] == os.getpid():
del state['instances'][i]
with open(self.state_path, 'w') as f:
json.dump(state, f)
def run(self):
assert self.selected is not None
self.selected.start()
signal.signal(signal.SIGINT, self._sighandler)
signal.signal(signal.SIGTERM, self._sighandler)
signal.signal(signal.SIGHUP, self._sighandler)
self.selected.wait()
self.cleanup()
def stop(self):
assert self.selected is not None
print('Shutting down')
self.selected.stop()
self.cleanup()
def _sighandler(self, signum, frame):
self.stop()
def main():
parser = argparse.ArgumentParser(description='Wayland terminal-based lock screen')
parser.add_argument('-l', '--locker-cmd', default='swaylock-plugin', help='swaylock-plugin command to use')
parser.add_argument('-t', '--terminal', default='alacritty', help='Terminal emulator to use')
parser.add_argument('-i', '--instance', action='store_true', help='Run as instance')
parser.add_argument('-s', '--screensaver', type=int, help='Force use of specific screensaver')
args = parser.parse_args()
if not args.instance:
cmd = [
args.locker_cmd, '--command-each',
f'@windowtolayer@/bin/windowtolayer -- {args.terminal} -e {sys.argv[0]} --instance']
if args.screensaver is not None:
cmd[-1] += f' --screensaver {args.screensaver}'
subprocess.check_call(cmd)
return
ms = MultiSaver(select=args.screensaver)
ms.select()
ms.run()
if __name__ == '__main__':
main()

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 249 KiB

View File

@@ -1,66 +0,0 @@
# 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

@@ -146,9 +146,9 @@ in
dnd-none = ""; dnd-none = "";
}; };
return-type = "json"; return-type = "json";
exec = "${config.my.swaync.package}/bin/swaync-client -swb"; exec = "${config.services.swaync.package}/bin/swaync-client -swb";
on-click = "${config.my.swaync.package}/bin/swaync-client -t -sw"; on-click = "${config.services.swaync.package}/bin/swaync-client -t -sw";
on-click-right = "${config.my.swaync.package}/bin/swaync-client -d -sw"; on-click-right = "${config.services.swaync.package}/bin/swaync-client -d -sw";
escape = true; escape = true;
}; };
}; };

View File

@@ -19,10 +19,10 @@ let
}; };
}; };
cfg = config.my.swaync; cfg = config.services.swaync;
in in
{ {
options.my.swaync = with lib.types; { options.services.swaync = with lib.types; {
enable = mkEnableOption "Sway Notification Center"; enable = mkEnableOption "Sway Notification Center";
package = mkOption { package = mkOption {
type = package; type = package;

View File

@@ -11,9 +11,6 @@ rec {
jellyseerr = 402; jellyseerr = 402;
atticd = 403; atticd = 403;
kea = 404; kea = 404;
keepalived_script = 405;
photoprism = 406;
copyparty = 408;
}; };
gids = { gids = {
matrix-syncv3 = 400; matrix-syncv3 = 400;
@@ -21,16 +18,12 @@ rec {
jellyseerr = 402; jellyseerr = 402;
atticd = 403; atticd = 403;
kea = 404; kea = 404;
keepalived_script = 405;
photoprism = 406;
adbusers = 407;
copyparty = 408;
}; };
}; };
kernel = { kernel = {
lts = pkgs: pkgs.linuxKernel.packages.linux_6_12; lts = pkgs: pkgs.linuxKernel.packages.linux_6_1;
latest = pkgs: pkgs.linuxKernel.packages.linux_6_16; latest = pkgs: pkgs.linuxKernel.packages.linux_6_6;
}; };
nginx = rec { nginx = rec {
@@ -101,10 +94,10 @@ rec {
nix = { nix = {
cache = rec { cache = rec {
substituters = [ substituters = [
"https://nix-cache.${pubDomain}" "https://nix-cache.${pubDomain}/main"
]; ];
keys = [ keys = [
"nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=" "main:mMChkG8LwXrFirVfudqjSHasK1jV31OVElYD3eImYl8="
]; ];
conf = '' conf = ''
extra-substituters = ${concatStringsSep " " substituters} extra-substituters = ${concatStringsSep " " substituters}
@@ -114,7 +107,7 @@ rec {
}; };
pubDomain = "nul.ie"; pubDomain = "nul.ie";
colony = rec { colony = {
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 {
@@ -138,9 +131,6 @@ 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
@@ -154,10 +144,6 @@ 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";
@@ -170,16 +156,6 @@ 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";
@@ -194,29 +170,6 @@ rec {
dst = aa.middleman.internal.ipv4.address; dst = aa.middleman.internal.ipv4.address;
} }
{
port = 25565;
dst = aa.simpcraft-oci.internal.ipv4.address;
}
{
port = 25566;
dst = aa.simpcraft-staging-oci.internal.ipv4.address;
}
{
port = 25567;
dst = aa.kevcraft-oci.internal.ipv4.address;
}
{
port = 25568;
dst = aa.kinkcraft-oci.internal.ipv4.address;
}
# RCON... unsafe?
# {
# port = 25575;
# dst = aa.simpcraft-oci.internal.ipv4.address;
# }
{ {
port = 2456; port = 2456;
dst = aa.valheim-oci.internal.ipv4.address; dst = aa.valheim-oci.internal.ipv4.address;
@@ -233,39 +186,6 @@ rec {
dst = aa.waffletail.internal.ipv4.address; dst = aa.waffletail.internal.ipv4.address;
proto = "udp"; proto = "udp";
} }
{
port = 25565;
dst = aa.simpcraft-oci.internal.ipv4.address;
proto = "udp";
}
{
port = 25567;
dst = aa.kevcraft-oci.internal.ipv4.address;
proto = "udp";
}
{
port = 25568;
dst = aa.kinkcraft-oci.internal.ipv4.address;
proto = "udp";
}
{
port = 15636;
dst = aa.enshrouded-oci.internal.ipv4.address;
proto = "udp";
}
{
port = 15637;
dst = aa.enshrouded-oci.internal.ipv4.address;
proto = "udp";
}
{
port = qclk.wgPort;
dst = aa.qclk.internal.ipv4.address;
proto = "udp";
}
]; ];
fstrimConfig = { fstrimConfig = {
@@ -289,8 +209,8 @@ rec {
"stream" "stream"
]; ];
routersPubV4 = [ routersPubV4 = [
"109.255.108.88" "109.255.31.25"
"109.255.108.121" "109.255.252.63"
]; ];
prefixes = with lib.my.net.cidr; rec { prefixes = with lib.my.net.cidr; rec {
@@ -339,8 +259,6 @@ 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 = {
@@ -356,20 +274,6 @@ rec {
assignedV6 = "2001:19f0:7402:128b:5400:04ff:feac:6e06"; assignedV6 = "2001:19f0:7402:128b:5400:04ff:feac:6e06";
}; };
britnet = {
domain = "bhx1.int.${pubDomain}";
pubV4 = "77.74.199.67";
vpn = {
port = 51820;
};
prefixes = with lib.my.net.cidr; rec {
vpn = {
v4 = "10.200.0.0/24";
v6 = "fdfb:5ebf:6e84::/64";
};
};
};
tailscale = { tailscale = {
prefix = { prefix = {
v4 = "100.64.0.0/10"; v4 = "100.64.0.0/10";
@@ -380,13 +284,11 @@ rec {
as211024 = rec { as211024 = rec {
trusted = { trusted = {
v4 = [ v4 = [
colony.prefixes.as211024.v4
colony.prefixes.all.v4 colony.prefixes.all.v4
home.prefixes.all.v4 home.prefixes.all.v4
tailscale.prefix.v4 tailscale.prefix.v4
]; ];
v6 = [ v6 = [
colony.prefixes.as211024.v6
colony.prefixes.all.v6 colony.prefixes.all.v6
home.prefixes.all.v6 home.prefixes.all.v6
tailscale.prefix.v6 tailscale.prefix.v6
@@ -405,7 +307,6 @@ rec {
}; };
domain = "hentai.engineer"; domain = "hentai.engineer";
ipv4MTU = 1460;
vpn = { vpn = {
port = 51820; port = 51820;
}; };
@@ -419,7 +320,6 @@ 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

@@ -1,11 +1,10 @@
{ inputs, lib }: { lib }:
let let
inherit (builtins) length match elemAt filter replaceStrings substring; inherit (builtins) length match elemAt filter replaceStrings;
inherit (lib) inherit (lib)
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 toLower splitString last;
inherit (lib.flake) defaultSystems; inherit (lib.flake) defaultSystems;
in in
rec { rec {
@@ -23,7 +22,7 @@ rec {
attrsToNVList = mapAttrsToList nameValuePair; attrsToNVList = mapAttrsToList nameValuePair;
inherit ((import "${inputs.libnetRepo}/lib/netu.nix" { inherit lib; }).lib) net; inherit (import ./net.nix { inherit lib; }) net;
dns = import ./dns.nix { inherit lib; }; dns = import ./dns.nix { inherit lib; };
c = import ./constants.nix { inherit lib; }; c = import ./constants.nix { inherit lib; };
@@ -53,7 +52,7 @@ rec {
in mkApp "${app}/bin/${app.meta.mainProgram}"; in mkApp "${app}/bin/${app.meta.mainProgram}";
flakePackageOverlay' = flake: pkg: system: (final: prev: flakePackageOverlay' = flake: pkg: system: (final: prev:
let let
pkg' = if pkg != null then flake.packages.${system}.${pkg} else flake.packages.${system}.default; pkg' = if pkg != null then flake.packages.${system}.${pkg} else flake.defaultPackage.${system};
name = if pkg != null then pkg else pkg'.name; name = if pkg != null then pkg else pkg'.name;
in in
{ {
@@ -167,7 +166,7 @@ rec {
systemdAwaitPostgres = pkg: host: { systemdAwaitPostgres = pkg: host: {
after = [ "systemd-networkd-wait-online.service" ]; after = [ "systemd-networkd-wait-online.service" ];
preStart = mkBefore '' preStart = ''
until ${pkg}/bin/pg_isready -h ${host}; do until ${pkg}/bin/pg_isready -h ${host}; do
sleep 0.5 sleep 0.5
done done
@@ -240,46 +239,4 @@ rec {
filterOpts = filterAttrsRecursive (_: v: v != null); filterOpts = filterAttrsRecursive (_: v: v != null);
}; };
versionOverlay = { self, pkgsFlake }: final: prev:
let
date = substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101");
revCode = flake: flake.shortRev or "dirty";
in
{
trivial = prev.trivial // {
release = "25.09:u-${prev.trivial.release}";
codeName = "Giving";
revisionWithDefault = default: self.rev or default;
versionSuffix = ".${date}.${revCode self}:u-${revCode pkgsFlake}";
};
};
upstreamRelease = last (splitString "-" lib.trivial.release);
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";
}
];
} }

1322
lib/net.nix Normal file

File diff suppressed because it is too large Load Diff

View File

@@ -1,191 +0,0 @@
{ lib, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c) pubDomain;
inherit (lib.my.c.britnet) domain pubV4 prefixes;
in
{
nixos.systems.britnet = {
system = "x86_64-linux";
nixpkgs = "mine";
assignments = {
allhost = {
inherit domain;
ipv4 = {
address = pubV4;
mask = 24;
gateway = "77.74.199.1";
};
ipv6 = {
address = "2a12:ab46:5344:99::a";
gateway = "2a12:ab46:5344::1";
};
};
vpn = {
ipv4 = {
address = net.cidr.host 1 prefixes.vpn.v4;
gateway = null;
};
ipv6.address = net.cidr.host 1 prefixes.vpn.v6;
};
};
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
let
inherit (lib) mkMerge mkForce;
inherit (lib.my) networkdAssignment;
in
{
imports = [
"${modulesPath}/profiles/qemu-guest.nix"
];
config = mkMerge [
{
boot = {
initrd.availableKernelModules = [
"ata_piix" "uhci_hcd" "virtio_pci" "virtio_scsi" "ahci" "sr_mod" "virtio_blk"
];
loader = {
systemd-boot.enable = false;
grub = {
enable = true;
device = "/dev/vda";
};
};
};
fileSystems = {
"/boot" = {
device = "/dev/disk/by-uuid/457444a1-81dd-4934-960c-650ad16c92b5";
fsType = "ext4";
};
"/nix" = {
device = "/dev/disk/by-uuid/992c0c79-5be6-45b6-bc30-dc82e3ec082a";
fsType = "ext4";
};
"/persist" = {
device = "/dev/disk/by-uuid/f020a955-54d5-4098-98ba-d3615781d96a";
fsType = "ext4";
neededForBoot = true;
};
};
environment = {
systemPackages = with pkgs; [
wireguard-tools
];
};
services = {
iperf3 = {
enable = true;
openFirewall = true;
};
tailscale = {
enable = true;
authKeyFile = config.age.secrets."tailscale-auth.key".path;
openFirewall = true;
interfaceName = "tailscale0";
extraUpFlags = [
"--operator=${config.my.user.config.name}"
"--login-server=https://hs.nul.ie"
"--netfilter-mode=off"
"--advertise-exit-node"
"--accept-routes=false"
];
};
};
networking = { inherit domain; };
systemd.network = {
netdevs = {
"30-wg0" = {
netdevConfig = {
Name = "wg0";
Kind = "wireguard";
};
wireguardConfig = {
PrivateKeyFile = config.age.secrets."britnet/wg.key".path;
ListenPort = lib.my.c.britnet.vpn.port;
};
wireguardPeers = [
{
PublicKey = "EfPwREfZ/q3ogHXBIqFZh4k/1NRJRyq4gBkBXtegNkE=";
AllowedIPs = [
(net.cidr.host 10 prefixes.vpn.v4)
(net.cidr.host 10 prefixes.vpn.v6)
];
}
];
};
};
links = {
"10-veth0" = {
matchConfig.PermanentMACAddress = "00:db:d9:62:68:1a";
linkConfig.Name = "veth0";
};
};
networks = {
"20-veth0" = mkMerge [
(networkdAssignment "veth0" assignments.allhost)
{
dns = [ "1.1.1.1" "1.0.0.1" ];
routes = [
{
# Gateway is on a different network for some reason...
Destination = "2a12:ab46:5344::1";
Scope = "link";
}
];
}
];
"30-wg0" = mkMerge [
(networkdAssignment "wg0" assignments.vpn)
{
networkConfig.IPv6AcceptRA = mkForce false;
}
];
};
};
my = {
server.enable = true;
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIJIEx+1EC/lN6WKIaOB+O5LJgVHRK962YpZEPQg/m78O";
files = {
"tailscale-auth.key" = {};
"britnet/wg.key" = {
owner = "systemd-network";
};
};
};
firewall = {
udp.allowed = [ lib.my.c.britnet.vpn.port ];
trustedInterfaces = [ "tailscale0" ];
extraRules = ''
table inet filter {
chain forward {
iifname wg0 oifname veth0 accept
}
}
table inet nat {
chain postrouting {
iifname { tailscale0, wg0 } oifname veth0 snat ip to ${assignments.allhost.ipv4.address}
iifname { tailscale0, wg0 } oifname veth0 snat ip6 to ${assignments.allhost.ipv6.address}
}
}
'';
};
};
}
];
};
};
}

View File

@@ -11,24 +11,23 @@ in
config = { config = {
my = { my = {
secrets.files."britway/bgp-password-vultr.conf" = { secrets.files."britway/bgp-password-vultr.conf" = {
owner = "bird"; owner = "bird2";
group = "bird"; group = "bird2";
}; };
}; };
environment.etc."bird/vultr-password.conf".source = config.age.secrets."britway/bgp-password-vultr.conf".path; environment.etc."bird/vultr-password.conf".source = config.age.secrets."britway/bgp-password-vultr.conf".path;
systemd = { systemd = {
services.bird.after = [ "systemd-networkd-wait-online@veth0.service" ]; services.bird2.after = [ "systemd-networkd-wait-online@veth0.service" ];
network = { network = {
config.networkConfig.ManageForeignRoutes = false; config.networkConfig.ManageForeignRoutes = false;
}; };
}; };
services = { services = {
bird = { bird2 = {
enable = true; enable = true;
package = pkgs.bird2;
preCheckConfig = '' preCheckConfig = ''
echo '"dummy"' > vultr-password.conf echo '"dummy"' > vultr-password.conf
''; '';

View File

@@ -106,7 +106,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
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 = [ routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
{ {
IncomingInterface = "tailscale0"; IncomingInterface = "tailscale0";
To = lib.my.c.colony.prefixes.all.v6; To = lib.my.c.colony.prefixes.all.v6;
@@ -154,7 +154,7 @@ in
extraRules = '' extraRules = ''
table inet filter { table inet filter {
chain forward { chain forward {
${lib.my.c.as211024.nftTrust} ${lib.my.as211024.nftTrust}
oifname as211024 accept oifname as211024 accept
} }
} }

View File

@@ -80,7 +80,7 @@ in
}; };
}; };
"hs.${pubDomain}" = { "ts.${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

@@ -4,6 +4,20 @@ let
inherit (lib.my.c) pubDomain; inherit (lib.my.c) pubDomain;
inherit (lib.my.c.britway) prefixes domain; inherit (lib.my.c.britway) prefixes domain;
# Can't use overrideAttrs because we need to override `vendorHash` within `buildGoModule`
headscale = pkgs.headscale.override {
buildGoModule = args: pkgs.buildGoModule (args // rec {
version = "0.23.0-alpha2";
src = pkgs.fetchFromGitHub {
owner = "juanfont";
repo = "headscale";
rev = "v${version}";
hash = "sha256-sz+uQyyq/5YYDe5I44x5x2nvd48swAhNlInB8KZYvDo=";
};
vendorHash = "sha256-u9AmJguQ5dnJpfhOeLN43apvMHuraOrJhvlEIp9RoIc=";
});
};
advRoutes = concatStringsSep "," [ advRoutes = concatStringsSep "," [
lib.my.c.home.prefixes.all.v4 lib.my.c.home.prefixes.all.v4
lib.my.c.home.prefixes.all.v6 lib.my.c.home.prefixes.all.v6
@@ -25,34 +39,29 @@ 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://hs.${pubDomain}"; server_url = "https://ts.${pubDomain}";
database = { db_type = "sqlite3";
type = "sqlite3"; db_path = "/var/lib/headscale/db.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";
prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; }; ip_prefixes = with lib.my.c.tailscale.prefix; [ v4 v6 ];
dns = { dns_config = {
override_local_dns = false; restricted_nameservers = {
# Use IPs that will route inside the VPN to prevent interception
# (e.g. DNS rebinding filtering)
nameservers.split = {
"${domain}" = pubNameservers; "${domain}" = pubNameservers;
"${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [ "${lib.my.c.colony.domain}" = with allAssignments.estuary.internal; [
ipv4.address ipv6.address ipv4.address ipv6.address
]; ];
"${lib.my.c.home.domain}" = with allAssignments; [ "${lib.my.c.home.domain}" = lib.my.c.home.routersPubV4 ++ ([
river.hi.ipv4.address allAssignments.river.as211024.ipv6.address
river.hi.ipv6.address allAssignments.stream.as211024.ipv6.address
stream.hi.ipv4.address ]);
stream.hi.ipv6.address
];
}; };
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;
@@ -72,7 +81,7 @@ in
interfaceName = "tailscale0"; interfaceName = "tailscale0";
extraUpFlags = [ extraUpFlags = [
"--operator=${config.my.user.config.name}" "--operator=${config.my.user.config.name}"
"--login-server=https://hs.nul.ie" "--login-server=https://ts.nul.ie"
"--netfilter-mode=off" "--netfilter-mode=off"
"--advertise-exit-node" "--advertise-exit-node"
"--advertise-routes=${advRoutes}" "--advertise-routes=${advRoutes}"

View File

@@ -1,8 +1,7 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c) networkd; inherit (lib.my.c.home) domain vlans prefixes;
inherit (lib.my.c.home) domain vlans prefixes vips roceBootModules;
in in
{ {
nixos.systems.castle = { nixos.systems.castle = {
@@ -16,7 +15,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 = vips.hi.v4; gateway = null;
}; };
ipv6 = { ipv6 = {
iid = "::3:1"; iid = "::3:1";
@@ -36,7 +35,7 @@ in
cpu = { cpu = {
amd.updateMicrocode = true; amd.updateMicrocode = true;
}; };
graphics.extraPackages = with pkgs; [ opengl.extraPackages = with pkgs; [
intel-media-driver intel-media-driver
]; ];
bluetooth.enable = true; bluetooth.enable = true;
@@ -48,7 +47,7 @@ in
timeout = 10; timeout = 10;
}; };
kernelPackages = lib.my.c.kernel.latest pkgs; kernelPackages = lib.my.c.kernel.latest pkgs;
kernelModules = [ "kvm-amd" "dm-snapshot" ]; kernelModules = [ "kvm-amd" ];
kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ]; kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ];
kernelPatches = [ kernelPatches = [
# { # {
@@ -58,40 +57,27 @@ in
# } # }
]; ];
initrd = { initrd = {
availableKernelModules = [ availableKernelModules = [ "thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" ];
"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/nvmeof/nix"; device = "/dev/disk/by-partuuid/2da23a1d-2daf-d943-b91e-fc175f3dad07";
fsType = "ext4"; fsType = "ext4";
}; };
"/persist" = { "/persist" = {
device = "/dev/nvmeof/persist"; device = "/dev/disk/by-partuuid/f4c80d4f-a022-e941-b5d1-fe2e65e444b9";
fsType = "ext4"; fsType = "ext4";
neededForBoot = true; neededForBoot = true;
}; };
"/home" = { "/home" = {
device = "/dev/nvmeof/home"; device = "/dev/disk/by-partuuid/992a93cf-6c9c-324b-b0ce-f8eb2d1ce10d";
fsType = "ext4"; fsType = "ext4";
}; };
}; };
@@ -115,12 +101,6 @@ in
dnssec = "false"; dnssec = "false";
}; };
pipewire.extraConfig.pipewire = {
"10-buffer"."context.properties" = {
"default.clock.quantum" = 128;
"default.clock.max-quantum" = 128;
};
};
blueman.enable = true; blueman.enable = true;
}; };
@@ -134,7 +114,7 @@ in
virtualisation.libvirtd.enable = true; virtualisation.libvirtd.enable = true;
networking = { networking = {
inherit domain; domain = "h.${lib.my.c.pubDomain}";
firewall.enable = false; firewall.enable = false;
}; };
@@ -150,19 +130,23 @@ in
mstflint mstflint
qperf qperf
ethtool ethtool
android-tools
]; ];
environment.etc = {
"pipewire/pipewire.conf.d/sample-size.conf".text = ''
context.properties = {
default.clock.quantum = 128
default.clock.max-quantum = 128
}
'';
};
nix = { nix = {
gc.automatic = false; gc.automatic = false;
settings = {
experimental-features = [ "recursive-nix" ];
system-features = [ "nixos-test" "benchmark" "big-parallel" "kvm" "recursive-nix" ];
};
}; };
systemd = { systemd = {
network = { network = {
wait-online.enable = false;
netdevs = mkMerge [ netdevs = mkMerge [
(mkVLAN "lan-hi" vlans.hi) (mkVLAN "lan-hi" vlans.hi)
]; ];
@@ -179,20 +163,29 @@ in
matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a"; matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a";
linkConfig = { linkConfig = {
Name = "et100g"; Name = "et100g";
MTUBytes = toString lib.my.c.home.hiMTU; MTUBytes = "9000";
}; };
}; };
}; };
networks = { networks = {
"30-et100g" = { "50-lan" = {
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;
}; };
"40-lan-hi" = mkMerge [ "60-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! {
{ networkConfig.KeepConfiguration = "static"; } DHCP = "yes";
matchConfig.Name = "lan-hi";
linkConfig.MTUBytes = "9000";
}
]; ];
}; };
}; };
@@ -212,7 +205,10 @@ in
packages = with pkgs; [ packages = with pkgs; [
jacktrip jacktrip
qpwgraph qpwgraph
boardie # TODO: seems to be borked (infinite recursion???)
# (writeShellScriptBin "boardie" ''
# exec pw-jack ${boardie}/bin/boardie "$@"
# '')
]; ];
}; };
@@ -226,7 +222,6 @@ 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";
@@ -248,19 +243,11 @@ 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";
}; };
netboot.client = { nvme.uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b";
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;

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 custRouting firewallForwards; inherit (lib.my.c.colony) domain prefixes firewallForwards;
in in
{ {
imports = [ ./vms ]; imports = [ ./vms ];
@@ -60,27 +60,16 @@ in
kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: { kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
kernel = super.kernel.override { kernel = super.kernel.override {
structuredExtraConfig = with lib.kernel; { structuredExtraConfig = with lib.kernel; {
ACPI_APEI_PCIEAER = yes; #SOME_OPT = yes;
PCIEAER = yes; #A_MOD = module;
}; };
}; };
}); });
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-amd" ];
kernelParams = [ kernelParams = [ "amd_iommu=on" "console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0" ];
"amd_iommu=on"
"console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0"
"systemd.setenv=SYSTEMD_SULOGIN_FORCE=1"
];
initrd = { initrd = {
kernelModules = [ "dm-raid" ]; kernelModules = [ "dm-raid" ];
availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ]; availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
systemd = {
enable = true;
# Onlu activate volumes needed for boot to prevent thin check from getting killed while switching root
contents."/etc/lvm/lvm.conf".text = ''
activation/auto_activation_volume_list = [ "main/colony-nix" "main/colony-persist" ]
'';
};
}; };
}; };
@@ -148,15 +137,6 @@ in
services = { services = {
"serial-getty@ttyS0".enable = true; "serial-getty@ttyS0".enable = true;
"serial-getty@ttyS1".enable = true; "serial-getty@ttyS1".enable = true;
lvm-activate-main = {
description = "Activate remaining LVs";
unitConfig.DefaultDependencies = false;
serviceConfig = {
Type = "oneshot";
ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
};
wantedBy = [ "local-fs-pre.target" ];
};
rsync-lvm-meta = { rsync-lvm-meta = {
description = "rsync lvm metadata backups / archives to rsync.net"; description = "rsync lvm metadata backups / archives to rsync.net";
@@ -252,10 +232,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
Prefix = prefixes.vms.v6; ipv6PrefixConfig.Prefix = prefixes.vms.v6;
} }
]; ];
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
Destination = prefixes.ctrs.v4; Destination = prefixes.ctrs.v4;
Gateway = allAssignments.shill.routing.ipv4.address; Gateway = allAssignments.shill.routing.ipv4.address;
@@ -264,12 +244,10 @@ 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;
@@ -278,15 +256,6 @@ 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;
@@ -318,7 +287,7 @@ in
"90-vm-mail" = { "90-vm-mail" = {
matchConfig.Name = "vm-mail"; matchConfig.Name = "vm-mail";
address = [ address = [
"${custRouting.mail-vm}/32" (net.cidr.subnet 8 1 prefixes.cust.v4)
prefixes.mail.v6 prefixes.mail.v6
]; ];
networkConfig = { networkConfig = {
@@ -327,10 +296,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
Prefix = prefixes.mail.v6; ipv6PrefixConfig.Prefix = prefixes.mail.v6;
} }
]; ];
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
Destination = prefixes.mail.v4; Destination = prefixes.mail.v4;
Scope = "link"; Scope = "link";
@@ -341,7 +310,7 @@ in
"90-vm-darts" = { "90-vm-darts" = {
matchConfig.Name = "vm-darts"; matchConfig.Name = "vm-darts";
address = [ address = [
"${custRouting.darts-vm}/32" (net.cidr.subnet 8 2 prefixes.cust.v4)
prefixes.darts.v6 prefixes.darts.v6
]; ];
networkConfig = { networkConfig = {
@@ -350,10 +319,10 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
Prefix = prefixes.darts.v6; ipv6PrefixConfig.Prefix = prefixes.darts.v6;
} }
]; ];
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
Destination = prefixes.darts.v4; Destination = prefixes.darts.v4;
Scope = "link"; Scope = "link";

View File

@@ -29,9 +29,6 @@
}; };
in in
{ {
# Kernel Same-Page Merging to attempt memory usage reduction
hardware.ksm.enable = false;
systemd = { systemd = {
network = { network = {
links = { links = {
@@ -123,7 +120,7 @@
cpus = 12; cpus = 12;
threads = 2; threads = 2;
}; };
memory = 40960; memory = 49152;
networks.vms.mac = "52:54:00:27:3d:5c"; networks.vms.mac = "52:54:00:27:3d:5c";
cleanShutdown.timeout = 120; cleanShutdown.timeout = 120;
drives = [ ] ++ (optionals (!config.my.build.isDevVM) [ drives = [ ] ++ (optionals (!config.my.build.isDevVM) [
@@ -133,8 +130,7 @@
(vm.lvmDisk "media") (vm.lvmDisk "media")
(vm.lvmDisk "minio") (vm.lvmDisk "minio")
(vm.lvmDisk "nix-cache") (vm.lvmDisk "nix-atticd")
(vm.lvmDisk "jam")
]); ]);
}; };
@@ -164,7 +160,7 @@
cpus = 12; cpus = 12;
threads = 2; threads = 2;
}; };
memory = 40960; memory = 32768;
networks.vms.mac = "52:54:00:75:78:a8"; networks.vms.mac = "52:54:00:75:78:a8";
cleanShutdown.timeout = 120; cleanShutdown.timeout = 120;
drives = [ drives = [
@@ -185,7 +181,7 @@
cpus = 3; cpus = 3;
threads = 2; threads = 2;
}; };
memory = 6144; memory = 8192;
networks.public = { networks.public = {
bridge = null; bridge = null;
mac = "52:54:00:a8:d1:03"; mac = "52:54:00:a8:d1:03";
@@ -213,7 +209,6 @@
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

@@ -8,9 +8,8 @@ in
{ {
config = { config = {
services = { services = {
bird = { bird2 = {
enable = true; enable = true;
package = pkgs.bird2;
# TODO: Clean up and modularise # TODO: Clean up and modularise
config = '' config = ''
define OWNAS = 211024; define OWNAS = 211024;
@@ -251,87 +250,41 @@ in
neighbor 2001:7f8:10f::dc49:254 as 56393; neighbor 2001:7f8:10f::dc49:254 as 56393;
} }
protocol bgp ixp4_frysix_rs3 from ixp_bgp4 {
description "Frys-IX route server 3 (IPv4)";
neighbor 185.1.160.255 as 56393;
}
protocol bgp ixp6_frysix_rs3 from ixp_bgp6 {
description "Frys-IX route server 3 (IPv6)";
neighbor 2001:7f8:10f::dc49:1 as 56393;
}
protocol bgp ixp4_frysix_rs4 from ixp_bgp4 {
description "Frys-IX route server 4 (IPv4)";
neighbor 185.1.161.0 as 56393;
}
protocol bgp ixp6_frysix_rs4 from ixp_bgp6 {
description "Frys-IX route server 4 (IPv6)";
neighbor 2001:7f8:10f::dc49:2 as 56393;
}
protocol bgp peer4_frysix_luje from peer_bgp4 { protocol bgp peer4_frysix_luje from peer_bgp4 {
description "LUJE.net (on Frys-IX, IPv4)"; description "LUJE.net (on Frys-IX, IPv4)";
neighbor 185.1.160.152 as 212855; neighbor 185.1.203.152 as 212855;
} }
protocol bgp peer6_frysix_luje from peer_bgp6 { protocol bgp peer6_frysix_luje from peer_bgp6 {
description "LUJE.net (on Frys-IX, IPv6)"; description "LUJE.net (on Frys-IX, IPv6)";
neighbor 2001:7f8:10f::3:3f95:152 as 212855; neighbor 2001:7f8:10f::3:3f95:152 as 212855;
} }
protocol bgp peer4_frysix_he from peer_bgp4 { protocol bgp peer4_frysix_he from peer_bgp4 {
description "Hurricane Electric (on Frys-IX, IPv4)"; description "Hurricane Electric (on Frys-IX, IPv4)";
neighbor 185.1.160.154 as 6939; neighbor 185.1.203.154 as 6939;
} }
protocol bgp peer4_frysix_cloudflare from peer_bgp4 {
protocol bgp peer4_frysix_cloudflare1_old from peer_bgp4 { description "Cloudflare (on Frys-IX, IPv4)";
description "Cloudflare 1 (on Frys-IX, IPv4)";
neighbor 185.1.203.217 as 13335; neighbor 185.1.203.217 as 13335;
} }
protocol bgp peer4_frysix_cloudflare2_old from peer_bgp4 { protocol bgp peer6_frysix_cloudflare from peer_bgp6 {
description "Cloudflare 2 (on Frys-IX, IPv4)"; description "Cloudflare (on Frys-IX, IPv6)";
neighbor 185.1.203.109 as 13335;
}
protocol bgp peer4_frysix_cloudflare1 from peer_bgp4 {
description "Cloudflare 1 (on Frys-IX, IPv4)";
neighbor 185.1.160.217 as 13335;
}
protocol bgp peer4_frysix_cloudflare2 from peer_bgp4 {
description "Cloudflare 2 (on Frys-IX, IPv4)";
neighbor 185.1.160.109 as 13335;
}
protocol bgp peer6_frysix_cloudflare1 from peer_bgp6 {
description "Cloudflare 1 (on Frys-IX, IPv6)";
neighbor 2001:7f8:10f::3417:217 as 13335; neighbor 2001:7f8:10f::3417:217 as 13335;
} }
protocol bgp peer6_frysix_cloudflare2 from peer_bgp6 {
description "Cloudflare 2 (on Frys-IX, IPv6)";
neighbor 2001:7f8:10f::3417:109 as 13335;
}
protocol bgp peer4_frysix_jurrian from peer_bgp4 { protocol bgp peer4_frysix_jurrian from peer_bgp4 {
description "AS212635 aka jurrian (on Frys-IX, IPv4)"; description "AS212635 aka jurrian (on Frys-IX, IPv4)";
neighbor 185.1.160.134 as 212635; neighbor 185.1.203.134 as 212635;
} }
protocol bgp peer6_frysix_jurrian from peer_bgp6 { protocol bgp peer6_frysix_jurrian from peer_bgp6 {
description "AS212635 aka jurrian (on Frys-IX, IPv6)"; description "AS212635 aka jurrian (on Frys-IX, IPv6)";
neighbor 2001:7f8:10f::3:3e9b:134 as 212635; neighbor 2001:7f8:10f::3:3e9b:134 as 212635;
} }
protocol bgp peer4_frysix_meta1 from peer_bgp4 {
protocol bgp peer4_frysix_meta1_old from peer_bgp4 {
description "Meta 1 (on Frys-IX, IPv4)"; description "Meta 1 (on Frys-IX, IPv4)";
neighbor 185.1.203.225 as 32934; neighbor 185.1.203.225 as 32934;
} }
protocol bgp peer4_frysix_meta2_old from peer_bgp4 {
description "Meta 2 (on Frys-IX, IPv4)";
neighbor 185.1.203.226 as 32934;
}
protocol bgp peer4_frysix_meta1 from peer_bgp4 {
description "Meta 1 (on Frys-IX, IPv4)";
neighbor 185.1.160.225 as 32934;
}
protocol bgp peer4_frysix_meta2 from peer_bgp4 { protocol bgp peer4_frysix_meta2 from peer_bgp4 {
description "Meta 2 (on Frys-IX, IPv4)"; description "Meta 2 (on Frys-IX, IPv4)";
neighbor 185.1.160.226 as 32934; neighbor 185.1.203.226 as 32934;
} }
protocol bgp peer6_frysix_meta1 from peer_bgp6 { protocol bgp peer6_frysix_meta1 from peer_bgp6 {
description "Meta 1 (on Frys-IX, IPv6)"; description "Meta 1 (on Frys-IX, IPv6)";
@@ -364,36 +317,36 @@ in
ipv6 { preference (PREFIXP-1); }; ipv6 { preference (PREFIXP-1); };
} }
# protocol bgp peer4_nlix_cloudflare1 from peer_bgp4 { protocol bgp peer4_nlix_cloudflare1 from peer_bgp4 {
# description "Cloudflare NL-ix 1 (IPv4)"; description "Cloudflare NL-ix 1 (IPv4)";
# neighbor 193.239.117.14 as 13335; neighbor 193.239.117.14 as 13335;
# ipv4 { preference (PREFPEER-1); }; ipv4 { preference (PREFPEER-1); };
# } }
# protocol bgp peer4_nlix_cloudflare2 from peer_bgp4 { protocol bgp peer4_nlix_cloudflare2 from peer_bgp4 {
# description "Cloudflare NL-ix 2 (IPv4)"; description "Cloudflare NL-ix 2 (IPv4)";
# neighbor 193.239.117.114 as 13335; neighbor 193.239.117.114 as 13335;
# ipv4 { preference (PREFPEER-1); }; ipv4 { preference (PREFPEER-1); };
# } }
# protocol bgp peer4_nlix_cloudflare3 from peer_bgp4 { protocol bgp peer4_nlix_cloudflare3 from peer_bgp4 {
# description "Cloudflare NL-ix 3 (IPv4)"; description "Cloudflare NL-ix 3 (IPv4)";
# neighbor 193.239.118.138 as 13335; neighbor 193.239.118.138 as 13335;
# ipv4 { preference (PREFPEER-1); }; ipv4 { preference (PREFPEER-1); };
# } }
# protocol bgp peer6_nlix_cloudflare1 from peer_bgp6 { protocol bgp peer6_nlix_cloudflare1 from peer_bgp6 {
# description "Cloudflare NL-ix 1 (IPv6)"; description "Cloudflare NL-ix 1 (IPv6)";
# neighbor 2001:7f8:13::a501:3335:1 as 13335; neighbor 2001:7f8:13::a501:3335:1 as 13335;
# ipv6 { preference (PREFPEER-1); }; ipv6 { preference (PREFPEER-1); };
# } }
# protocol bgp peer6_nlix_cloudflare2 from peer_bgp6 { protocol bgp peer6_nlix_cloudflare2 from peer_bgp6 {
# description "Cloudflare NL-ix 2 (IPv6)"; description "Cloudflare NL-ix 2 (IPv6)";
# neighbor 2001:7f8:13::a501:3335:2 as 13335; neighbor 2001:7f8:13::a501:3335:2 as 13335;
# ipv6 { preference (PREFPEER-1); }; ipv6 { preference (PREFPEER-1); };
# } }
# protocol bgp peer6_nlix_cloudflare3 from peer_bgp6 { protocol bgp peer6_nlix_cloudflare3 from peer_bgp6 {
# description "Cloudflare NL-ix 3 (IPv6)"; description "Cloudflare NL-ix 3 (IPv6)";
# neighbor 2001:7f8:13::a501:3335:3 as 13335; neighbor 2001:7f8:13::a501:3335:3 as 13335;
# ipv6 { preference (PREFPEER-1); }; ipv6 { preference (PREFPEER-1); };
# } }
protocol bgp peer4_nlix_jurrian from peer_bgp4 { protocol bgp peer4_nlix_jurrian from peer_bgp4 {
description "AS212635 aka jurrian (on NL-ix, IPv4)"; description "AS212635 aka jurrian (on NL-ix, IPv4)";
neighbor 193.239.117.55 as 212635; neighbor 193.239.117.55 as 212635;

View File

@@ -9,7 +9,6 @@ in
vpns = { vpns = {
l2 = { l2 = {
as211024 = { as211024 = {
udpEncapsulation = true;
vni = 211024; vni = 211024;
security.enable = true; security.enable = true;
peers = { peers = {
@@ -164,9 +163,11 @@ in
}; };
wireguardPeers = [ wireguardPeers = [
{ {
wireguardPeerConfig = {
PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E="; PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E=";
AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ]; AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ];
PersistentKeepalive = 25; PersistentKeepalive = 25;
};
} }
]; ];
}; };
@@ -219,9 +220,6 @@ in
mkMerge mkMerge
[ [
(mkIXPConfig "frys-ix" "185.1.203.196/24" "2001:7f8:10f::3:3850:196/64") (mkIXPConfig "frys-ix" "185.1.203.196/24" "2001:7f8:10f::3:3850:196/64")
# FrysIX is migrating to a /23
{ "85-frys-ix".address = [ "185.1.160.196/23" ]; }
(mkIXPConfig "nl-ix" "193.239.116.145/22" "2001:7f8:13::a521:1024:1/64") (mkIXPConfig "nl-ix" "193.239.116.145/22" "2001:7f8:13::a521:1024:1/64")
(mkIXPConfig "fogixp" "185.1.147.159/24" "2001:7f8:ca:1::159/64") (mkIXPConfig "fogixp" "185.1.147.159/24" "2001:7f8:ca:1::159/64")
{ {
@@ -279,10 +277,11 @@ in
}; };
ipv6Prefixes = [ ipv6Prefixes = [
{ {
Prefix = prefixes.base.v6; ipv6PrefixConfig.Prefix = prefixes.base.v6;
} }
]; ];
routes = flatten ([ routes = map (r: { routeConfig = r; }) (flatten
([
{ {
Destination = prefixes.vip1; Destination = prefixes.vip1;
Gateway = allAssignments.colony.routing.ipv4.address; Gateway = allAssignments.colony.routing.ipv4.address;
@@ -308,11 +307,6 @@ in
Destination = lib.my.c.tailscale.prefix.v6; Destination = lib.my.c.tailscale.prefix.v6;
Gateway = allAssignments.colony.internal.ipv6.address; Gateway = allAssignments.colony.internal.ipv6.address;
} }
{
Destination = prefixes.qclk.v4;
Gateway = allAssignments.colony.routing.ipv4.address;
}
] ++ ] ++
(map (pName: [ (map (pName: [
{ {
@@ -323,7 +317,7 @@ in
Destination = prefixes."${pName}".v6; Destination = prefixes."${pName}".v6;
Gateway = allAssignments.colony.internal.ipv6.address; Gateway = allAssignments.colony.internal.ipv6.address;
} }
]) [ "vms" "ctrs" "oci" ])); ]) [ "vms" "ctrs" "oci" ])));
} }
]; ];
@@ -332,7 +326,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
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;
@@ -344,8 +338,10 @@ 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";
};
} }
]; ];
}; };
@@ -397,24 +393,12 @@ in
# Safe enough to allow all SSH # Safe enough to allow all SSH
tcp dport ssh accept tcp dport ssh accept
# jam-ctr forwards ${matchInet "tcp dport { http, https, 8448 } accept" "middleman"}
ip daddr ${aa.shill.internal.ipv4.address} tcp dport 60022 accept
ip6 daddr ${aa.middleman.internal.ipv6.address} tcp dport { http, https, 8448 } accept
${matchInet "tcp dport { http, https } accept" "git"}
ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} tcp dport 25565 accept
ip6 daddr ${aa.simpcraft-staging-oci.internal.ipv6.address} tcp dport 25565 accept
ip6 daddr ${aa.kevcraft-oci.internal.ipv6.address} tcp dport 25567 accept
ip6 daddr ${aa.kinkcraft-oci.internal.ipv6.address} tcp dport 25568 accept
return return
} }
chain routing-udp { chain routing-udp {
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.enshrouded-oci.internal.ipv6.address} udp dport { 15636-15637 } accept
ip6 daddr ${aa.kevcraft-oci.internal.ipv6.address} udp dport 25567 accept
ip6 daddr ${aa.kinkcraft-oci.internal.ipv6.address} udp dport 25568 accept
return return
} }
chain filter-routing { chain filter-routing {
@@ -445,6 +429,8 @@ in
table inet nat { table inet nat {
chain prerouting { chain prerouting {
${matchInet "meta l4proto { udp, tcp } th dport domain redirect to :5353" "estuary"} ${matchInet "meta l4proto { udp, tcp } th dport domain redirect to :5353" "estuary"}
ip daddr ${aa.git.internal.ipv4.address} tcp dport { http, https } dnat to ${aa.middleman.internal.ipv4.address}
ip6 daddr ${aa.git.internal.ipv6.address} tcp dport { http, https } dnat to ${aa.middleman.internal.ipv6.address}
} }
chain postrouting { chain postrouting {
ip saddr ${prefixes.all.v4} oifname != as211024 snat to ${assignments.internal.ipv4.address} ip saddr ${prefixes.all.v4} oifname != as211024 snat to ${assignments.internal.ipv4.address}

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 custRouting; inherit (lib.my.c.colony) prefixes;
authZones = attrNames config.my.pdns.auth.bind.zones; authZones = attrNames config.my.pdns.auth.bind.zones;
in in
@@ -14,7 +14,7 @@ in
owner = "pdns"; owner = "pdns";
group = "pdns"; group = "pdns";
}; };
"estuary/pdns/recursor.yml" = { "estuary/pdns/recursor.conf" = {
owner = "pdns-recursor"; owner = "pdns-recursor";
group = "pdns-recursor"; group = "pdns-recursor";
}; };
@@ -31,7 +31,7 @@ in
pdns.recursor = { pdns.recursor = {
enable = true; enable = true;
extraSettingsFile = config.age.secrets."estuary/pdns/recursor.yml".path; extraSettingsFile = config.age.secrets."estuary/pdns/recursor.conf".path;
}; };
}; };
@@ -44,37 +44,34 @@ in
}; };
pdns-recursor = { pdns-recursor = {
yaml-settings = { dns = {
incoming = { address = [
listen = [
"127.0.0.1" "::1" "127.0.0.1" "::1"
assignments.base.ipv4.address assignments.base.ipv6.address assignments.base.ipv4.address assignments.base.ipv6.address
]; ];
allow_from = [ allowFrom = [
"127.0.0.0/8" "::1/128" "127.0.0.0/8" "::1/128"
prefixes.all.v4 prefixes.all.v6 prefixes.all.v4 prefixes.all.v6
] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]); ];
# DNS NOTIFY messages override TTL
allow_notify_for = authZones;
allow_notify_from = [ "127.0.0.0/8" "::1/128" ];
}; };
outgoing = { settings = {
source_address = [ query-local-address = [
assignments.internal.ipv4.address assignments.internal.ipv4.address
assignments.internal.ipv6.address assignments.internal.ipv6.address
assignments.base.ipv6.address assignments.base.ipv6.address
]; ];
}; forward-zones = map (z: "${z}=127.0.0.1:5353") authZones;
recursor = { # DNS NOTIFY messages override TTL
forward_zones = map (z: { allow-notify-for = authZones;
zone = z; allow-notify-from = [ "127.0.0.0/8" "::1/128" ];
forwarders = [ "127.0.0.1:5353" ];
}) authZones;
lua_dns_script = pkgs.writeText "pdns-script.lua" '' webserver = true;
webserver-address = "::";
webserver-allow-from = [ "127.0.0.1" "::1" ];
lua-dns-script = pkgs.writeText "pdns-script.lua" ''
function preresolve(dq) function preresolve(dq)
if dq.qname:equal("nix-cache.nul.ie") then if dq.qname:equal("nix-cache.nul.ie") then
dq:addAnswer(pdns.CNAME, "http.${config.networking.domain}.") dq:addAnswer(pdns.CNAME, "http.${config.networking.domain}.")
@@ -87,13 +84,6 @@ in
end end
''; '';
}; };
webservice = {
webserver = true;
address = "::";
allow_from = [ "127.0.0.1" "::1" ];
};
};
}; };
}; };
@@ -155,19 +145,9 @@ in
http IN A ${assignments.internal.ipv4.address} http IN A ${assignments.internal.ipv4.address}
http IN AAAA ${allAssignments.middleman.internal.ipv6.address} http IN AAAA ${allAssignments.middleman.internal.ipv6.address}
librespeed IN CNAME http.${config.networking.domain}.
valheim IN A ${assignments.internal.ipv4.address} valheim IN A ${assignments.internal.ipv4.address}
valheim IN AAAA ${allAssignments.valheim-oci.internal.ipv6.address} valheim IN AAAA ${allAssignments.valheim-oci.internal.ipv6.address}
simpcraft IN A ${assignments.internal.ipv4.address}
simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address}
simpcraft-staging IN A ${assignments.internal.ipv4.address}
simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address}
enshrouded IN A ${assignments.internal.ipv4.address}
kevcraft IN A ${assignments.internal.ipv4.address}
kevcraft IN AAAA ${allAssignments.kevcraft-oci.internal.ipv6.address}
kinkcraft IN A ${assignments.internal.ipv4.address}
kinkcraft IN AAAA ${allAssignments.kinkcraft-oci.internal.ipv6.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}
@@ -177,10 +157,6 @@ 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

@@ -1,11 +1,8 @@
{ lib, ... }: { lib, ... }:
let let
inherit (builtins) mapAttrs;
inherit (lib) mkMerge mkDefault;
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c) pubDomain; inherit (lib.my.c) pubDomain;
inherit (lib.my.c.colony) domain prefixes firewallForwards; inherit (lib.my.c.colony) domain prefixes;
inherit (lib.my.c.nginx) baseHttpConfig proxyHeaders;
in in
{ {
nixos.systems.git = { nixos.systems.git = {
@@ -75,81 +72,9 @@ in
}; };
}; };
users = {
users = {
nginx.extraGroups = [ "acme" ];
};
};
security.acme = {
acceptTerms = true;
defaults = {
email = "dev@nul.ie";
server = "https://acme-v02.api.letsencrypt.org/directory";
reloadServices = [ "nginx" ];
dnsResolver = "8.8.8.8";
};
certs = {
"${pubDomain}" = {
extraDomainNames = [
"*.${pubDomain}"
];
dnsProvider = "cloudflare";
credentialsFile = config.age.secrets."middleman/cloudflare-credentials.conf".path;
};
};
};
services = { services = {
fstrim = lib.my.c.colony.fstrimConfig; fstrim = lib.my.c.colony.fstrimConfig;
netdata.enable = true; netdata.enable = true;
nginx = {
enable = true;
enableReload = true;
logError = "stderr info";
recommendedTlsSettings = true;
clientMaxBodySize = "0";
serverTokens = true;
sslDhparam = config.age.secrets."dhparams.pem".path;
# Based on recommended*Settings, but probably better to be explicit about these
appendHttpConfig = ''
${baseHttpConfig}
# caching
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=512m;
'';
virtualHosts =
let
hosts = {
"_" = {
default = true;
forceSSL = true;
onlySSL = false;
locations = {
"/".root = "${pkgs.nginx}/html";
};
};
"git.${pubDomain}" = {
locations."/".proxyPass = "http://localhost:3000";
};
};
defaultsFor = mapAttrs (n: _: {
onlySSL = mkDefault true;
useACMEHost = mkDefault pubDomain;
kTLS = mkDefault true;
http2 = mkDefault true;
});
in
mkMerge [
hosts
(defaultsFor hosts)
];
};
}; };
virtualisation = { virtualisation = {
@@ -179,25 +104,11 @@ in
}; };
my = { my = {
secrets = { secrets.key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+KINpHLMduBuW96JzfSRDLUzkI+XaCBghu5/wHiW5R";
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+KINpHLMduBuW96JzfSRDLUzkI+XaCBghu5/wHiW5R";
files = {
"dhparams.pem" = {
owner = "acme";
group = "acme";
mode = "440";
};
"middleman/cloudflare-credentials.conf" = {
owner = "acme";
group = "acme";
};
};
};
server.enable = true; server.enable = true;
firewall = { firewall = {
tcp.allowed = [ 19999 "http" "https" ]; tcp.allowed = [ 19999 ];
nat.forwardPorts."${allAssignments.estuary.internal.ipv4.address}" = firewallForwards allAssignments;
extraRules = '' extraRules = ''
table inet filter { table inet filter {
chain forward { chain forward {

View File

@@ -35,11 +35,6 @@ 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

@@ -26,6 +26,18 @@ in
systemd = { systemd = {
services = { services = {
# TODO: Figure out a way to do this properly... redirecting localhost is awkward...
local-http-forward = {
description = "Forward local HTTP connections";
serviceConfig.ExecStart = "${pkgs.socat}/bin/socat tcp-listen:80,fork tcp:${allAssignments.middleman.internal.ipv4.address}:80";
wantedBy = [ "multi-user.target" ];
};
local-https-forward = {
description = "Forward local HTTPS connections";
serviceConfig.ExecStart = "${pkgs.socat}/bin/socat tcp-listen:443,fork tcp:${allAssignments.middleman.internal.ipv4.address}:443";
wantedBy = [ "multi-user.target" ];
};
gitea = mkMerge [ gitea = mkMerge [
(lib.my.systemdAwaitPostgres pkgs.postgresql "colony-psql") (lib.my.systemdAwaitPostgres pkgs.postgresql "colony-psql")
{ {
@@ -129,6 +141,21 @@ in
"gitea/minio.txt" = ownedByGit; "gitea/minio.txt" = ownedByGit;
}; };
}; };
firewall.extraRules = ''
table inet filter {
chain input {
ip saddr ${prefixes.all.v4} tcp dport 3000 accept
ip6 saddr ${prefixes.all.v6} tcp dport 3000 accept
}
}
table inet nat {
chain prerouting {
ip daddr ${assignments.internal.ipv4.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv4.address}
ip6 daddr ${assignments.internal.ipv6.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv6.address}
}
}
'';
}; };
}; };
} }

View File

@@ -1,105 +0,0 @@
{ 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) genAttrs mkMerge mkIf mkForce; inherit (lib) mkMerge mkIf mkForce;
inherit (lib.my) networkdAssignment; inherit (lib.my) networkdAssignment;
in in
{ {
@@ -45,22 +45,9 @@ in
owner = "matrix-synapse"; owner = "matrix-synapse";
group = "matrix-synapse"; group = "matrix-synapse";
}; };
"chatterbox/doublepuppet.yaml" = { "chatterbox/syncv3.env" = {
owner = "matrix-synapse"; owner = "matrix-syncv3";
group = "matrix-synapse"; group = "matrix-syncv3";
};
"chatterbox/mautrix-whatsapp.env" = {
owner = "mautrix-whatsapp";
group = "mautrix-whatsapp";
};
"chatterbox/mautrix-messenger.env" = {
owner = "mautrix-meta-messenger";
group = "mautrix-meta";
};
"chatterbox/mautrix-instagram.env" = {
owner = "mautrix-meta-instagram";
group = "mautrix-meta";
}; };
}; };
}; };
@@ -72,23 +59,28 @@ in
users = with lib.my.c.ids; { users = with lib.my.c.ids; {
users = { users = {
matrix-synapse.extraGroups = [ matrix-syncv3 = {
"mautrix-whatsapp" isSystemUser = true;
]; 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 = { } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: { services = {
# ffmpeg needed to convert GIFs to video matrix-sliding-sync.serviceConfig = {
path = with pkgs; [ ffmpeg ]; # Needs to be able to read its secrets
})); 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;
@@ -176,10 +168,18 @@ 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
]; ];
}; };
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 = {
@@ -195,145 +195,6 @@ 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";
"@adzerq:nul.ie" = "user";
};
};
};
};
};
}; };
} }
(mkIf config.my.build.isDevVM { (mkIf config.my.build.isDevVM {

View File

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

View File

@@ -1,8 +1,6 @@
{ lib, ... }: { lib, ... }:
let let
inherit (lib) concatStringsSep;
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c) pubDomain;
inherit (lib.my.c.colony) domain prefixes; inherit (lib.my.c.colony) domain prefixes;
in in
{ {
@@ -23,7 +21,7 @@ in
}; };
}; };
configuration = { lib, pkgs, config, allAssignments, ... }: configuration = { lib, pkgs, config, ... }:
let let
inherit (lib) mkForce; inherit (lib) mkForce;
in in
@@ -37,19 +35,6 @@ in
secrets = { secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPUv1ntVrZv5ripsKpcOAnyDQX2PHjowzyhqWK10Ml53"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPUv1ntVrZv5ripsKpcOAnyDQX2PHjowzyhqWK10Ml53";
files = {
"jackflix/photoprism-pass.txt" = {};
"jackflix/copyparty-pass.txt" = {
owner = "copyparty";
group = "copyparty";
};
};
};
firewall = {
tcp.allowed = [
3923
];
}; };
}; };
@@ -65,21 +50,10 @@ in
uid = uids.jellyseerr; uid = uids.jellyseerr;
group = "jellyseerr"; group = "jellyseerr";
}; };
photoprism = {
isSystemUser = true;
uid = uids.photoprism;
group = "photoprism";
};
copyparty = {
uid = uids.copyparty;
extraGroups = [ "media" ];
};
}; };
groups = { groups = {
media.gid = 2000; media.gid = 2000;
jellyseerr.gid = gids.jellyseerr; jellyseerr.gid = gids.jellyseerr;
photoprism.gid = gids.photoprism;
copyparty.gid = gids.copyparty;
}; };
}; };
@@ -102,10 +76,6 @@ in
RootDirectoryStartOnly = lib.mkForce false; RootDirectoryStartOnly = lib.mkForce false;
RootDirectory = lib.mkForce ""; RootDirectory = lib.mkForce "";
}; };
photoprism.serviceConfig = {
# Needs to be able to access its data
DynamicUser = mkForce false;
};
}; };
}; };
@@ -138,7 +108,6 @@ in
}; };
}; };
flaresolverr.enable = true;
jackett.enable = true; jackett.enable = true;
radarr.enable = true; radarr.enable = true;
sonarr.enable = true; sonarr.enable = true;
@@ -148,68 +117,6 @@ in
}; };
jellyfin.enable = true; jellyfin.enable = true;
photoprism = {
enable = true;
address = "[::]";
port = 2342;
originalsPath = "/mnt/media/photoprism/originals";
importPath = "/mnt/media/photoprism/import";
passwordFile = config.age.secrets."jackflix/photoprism-pass.txt".path;
settings = {
PHOTOPRISM_AUTH_MODE = "password";
PHOTOPRISM_ADMIN_USER = "dev";
PHOTOPRISM_APP_NAME = "/dev/player0 Photos";
PHOTOPRISM_SITE_URL = "https://photos.${pubDomain}/";
PHOTOPRISM_SITE_TITLE = "/dev/player0 Photos";
PHOTOPRISM_TRUSTED_PROXY = concatStringsSep "," (with prefixes.ctrs; [ v4 v6 ]);
PHOTOPRISM_DATABASE_DRIVER = "sqlite";
};
};
copyparty = {
enable = true;
package = pkgs.copyparty.override {
withMagic = true;
};
settings = {
name = "dev-stuff";
no-reload = true;
j = 8; # cores
http-only = true;
xff-src =
with allAssignments.middleman.internal;
[ "${ipv4.address}/32" prefixes.ctrs.v6 ];
rproxy = 1; # get if from x-forwarded-for
magic = true; # enable checking file magic on upload
hist = "/var/cache/copyparty";
shr = "/share"; # enable share creation
ed = true; # enable dotfiles
chmod-f = 664;
chmod-d = 775;
e2dsa = true; # file indexing
e2t = true; # metadata indexing
og-ua = "(Discord|Twitter|Slack)bot"; # embeds
theme = 6;
};
accounts.dev.passwordFile = config.age.secrets."jackflix/copyparty-pass.txt".path;
volumes = {
"/" = {
path = "/mnt/media/public";
access = {
A = "dev";
"r." = "*";
};
flags = {
shr_who = "no"; # no reason to have shares here
};
};
"/priv" = {
path = "/mnt/media/stuff";
access.A = "dev"; # dev has admin access
};
};
};
}; };
}; };
}; };

View File

@@ -37,7 +37,7 @@ in
tcp dport ${toString transmissionPeerPort} accept tcp dport ${toString transmissionPeerPort} accept
iifname vpn return iifname vpn return
tcp dport { 19999, 9091, 9117, 7878, 8989, 8096, 2342 } accept tcp dport { 19999, 9091, 9117, 7878, 8989, 8096 } accept
return return
} }
chain input { chain input {
@@ -71,12 +71,14 @@ in
RouteTable = routeTable; RouteTable = routeTable;
}; };
wireguardPeers = [ wireguardPeers = [
# AirVPN NL
{ {
# AirVPN NL
wireguardPeerConfig = {
Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637"; Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637";
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
PresharedKeyFile = config.age.secrets."${pskFile}".path; PresharedKeyFile = config.age.secrets."${pskFile}".path;
AllowedIPs = [ "0.0.0.0/0" "::/0" ]; AllowedIPs = [ "0.0.0.0/0" "::/0" ];
};
} }
]; ];
}; };
@@ -92,7 +94,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 = [ routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;

View File

@@ -66,7 +66,6 @@ in
owner = "nginx"; owner = "nginx";
group = "nginx"; group = "nginx";
}; };
"librespeed.toml" = { };
}; };
}; };
@@ -123,19 +122,6 @@ in
baseURL = "https://sso.${pubDomain}"; baseURL = "https://sso.${pubDomain}";
}; };
}; };
librespeed = {
frontend.servers = [
{
name = "Amsterdam, Netherlands";
server = "//librespeed.${domain}";
}
];
backend = {
enable = true;
extraSettingsFile = config.age.secrets."librespeed.toml".path;
};
};
}; };
users = { users = {
@@ -239,9 +225,6 @@ 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 = {
@@ -251,9 +234,6 @@ in
proxyResolveWhileRunning = true; proxyResolveWhileRunning = true;
sslDhparam = config.age.secrets."dhparams.pem".path; sslDhparam = config.age.secrets."dhparams.pem".path;
appendConfig = ''
worker_processes auto;
'';
# Based on recommended*Settings, but probably better to be explicit about these # Based on recommended*Settings, but probably better to be explicit about these
appendHttpConfig = '' appendHttpConfig = ''
${baseHttpConfig} ${baseHttpConfig}

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 home; inherit (lib.my.c) pubDomain;
inherit (lib.my.c.nginx) proxyHeaders; inherit (lib.my.c.nginx) proxyHeaders;
inherit (config.networking) domain; inherit (config.networking) domain;
@@ -35,6 +35,7 @@ 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";
})) }))
]; ];
}; };
@@ -49,7 +50,6 @@ let
"/.well-known/webfinger".return = "301 https://toot.nul.ie$request_uri"; "/.well-known/webfinger".return = "301 https://toot.nul.ie$request_uri";
"/.well-known/nodeinfo".return = "301 https://toot.nul.ie$request_uri"; "/.well-known/nodeinfo".return = "301 https://toot.nul.ie$request_uri";
"/.well-known/host-meta".return = "301 https://toot.nul.ie$request_uri"; "/.well-known/host-meta".return = "301 https://toot.nul.ie$request_uri";
"/.well-known/atproto-did".return = "301 https://pds.nul.ie$request_uri";
}; };
in in
{ {
@@ -80,10 +80,6 @@ in
sha256 = "018wh6ps19n7323fi44njzj9yd4wqslc90dykbwfyscv7bgxhlar"; sha256 = "018wh6ps19n7323fi44njzj9yd4wqslc90dykbwfyscv7bgxhlar";
}; };
} }
{
name = "ssh.pub";
path = lib.my.c.sshKeyFiles.me;
}
]; ];
} }
wellKnown wellKnown
@@ -149,7 +145,7 @@ in
"pass.${pubDomain}" = "pass.${pubDomain}" =
let let
upstream = "http://vaultwarden-ctr.${domain}:8080"; upstream = "http://vaultwarden-ctr.${domain}";
in in
{ {
locations = { locations = {
@@ -186,6 +182,10 @@ in
]; ];
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"matrix-syncv3.${pubDomain}" = {
locations."/".proxyPass = "http://chatterbox-ctr.${domain}:8009";
useACMEHost = pubDomain;
};
"element.${pubDomain}" = "element.${pubDomain}" =
let let
@@ -206,8 +206,7 @@ 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";
show_labs_settings = true; showLabsSettings = true;
default_country_code = "IE";
disable_guests = true; disable_guests = true;
default_server_config = { default_server_config = {
"m.homeserver" = { "m.homeserver" = {
@@ -215,8 +214,9 @@ in
server_name = "nul.ie"; server_name = "nul.ie";
}; };
}; };
room_directory.servers = [ roomDirectory.servers = [
"nul.ie" "nul.ie"
"netsoc.ie"
"matrix.org" "matrix.org"
]; ];
}; };
@@ -327,15 +327,6 @@ in
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"pds.nul.ie" = {
locations."/" = {
proxyPass = "http://toot-ctr.${domain}:3000";
proxyWebsockets = true;
extraConfig = proxyHeaders;
};
useACMEHost = pubDomain;
};
"share.${pubDomain}" = { "share.${pubDomain}" = {
locations."/" = { locations."/" = {
proxyPass = "http://object-ctr.${domain}:9090"; proxyPass = "http://object-ctr.${domain}:9090";
@@ -347,16 +338,8 @@ in
"stuff.${pubDomain}" = { "stuff.${pubDomain}" = {
locations."/" = { locations."/" = {
proxyPass = "http://jackflix-ctr.${domain}:3923"; basicAuthFile = config.age.secrets."middleman/htpasswd".path;
}; root = "/mnt/media/stuff";
useACMEHost = pubDomain;
};
"public.${pubDomain}" = {
onlySSL = false;
addSSL = true;
serverAliases = [ "p.${pubDomain}" ];
locations."/" = {
root = "/mnt/media/public";
extraConfig = '' extraConfig = ''
fancyindex on; fancyindex on;
fancyindex_show_dotfiles on; fancyindex_show_dotfiles on;
@@ -365,76 +348,8 @@ in
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"mc-map.${pubDomain}" = { "git.${pubDomain}" = {
locations."/".proxyPass = "http://simpcraft-oci.${domain}:8100"; locations."/".proxyPass = "http://git-vm.${domain}:3000";
useACMEHost = pubDomain;
};
"mc-rail.${pubDomain}" = {
locations."/".proxyPass = "http://simpcraft-oci.${domain}:3876";
useACMEHost = pubDomain;
};
"mc-map-kink.${pubDomain}" = {
locations."/".proxyPass = "http://kinkcraft-oci.${domain}:8100";
useACMEHost = pubDomain;
};
"librespeed.${domain}" = {
locations."/".proxyPass = "http://localhost:8989";
};
"speed.${pubDomain}" = {
locations."/".proxyPass = "http://localhost:8989";
useACMEHost = pubDomain;
};
"md.${pubDomain}" = {
locations."/" = {
proxyPass = "http://object-ctr.${domain}:3000";
proxyWebsockets = true;
extraConfig = proxyHeaders;
};
useACMEHost = pubDomain;
};
"pb.${pubDomain}" = {
locations."/".proxyPass = "http://object-ctr.${domain}:8088";
useACMEHost = pubDomain;
};
"photos.${pubDomain}" = {
locations."/" = {
proxyPass = "http://jackflix-ctr.${domain}:2342";
proxyWebsockets = true;
extraConfig = proxyHeaders;
};
useACMEHost = pubDomain;
};
"pront.${pubDomain}" = mkMerge [
{
locations."/" = mkMerge [
{
proxyPass = "http://stream-hi.${home.domain}:5000";
proxyWebsockets = true;
extraConfig = proxyHeaders;
}
(ssoLoc "generic")
];
locations."~* ^/webcam/(.*)" = mkMerge [
{
proxyPass = "http://stream-hi.${home.domain}:5050/$1$is_args$args";
extraConfig = proxyHeaders;
}
(ssoLoc "generic")
];
useACMEHost = pubDomain;
}
(ssoServer "generic")
];
"hass.${pubDomain}" = {
locations."/" = {
proxyPass = "http://hass-ctr.${home.domain}:8123";
proxyWebsockets = true;
extraConfig = proxyHeaders;
};
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
}; };
@@ -448,13 +363,10 @@ in
ignore_invalid_headers off; ignore_invalid_headers off;
''; '';
nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar.*|serve\/.+)$''; nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar\.\S+)$'';
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
{ {
@@ -475,32 +387,15 @@ in
"s3.${pubDomain}" = { "s3.${pubDomain}" = {
serverAliases = [ "*.s3.${pubDomain}" ]; serverAliases = [ "*.s3.${pubDomain}" ];
inherit extraConfig; inherit extraConfig;
locations = { locations."/".proxyPass = s3Upstream;
"/".proxyPass = s3Upstream;
"/gitea/packages/" = {
proxyPass = s3Upstream;
# HACK: Docker images need the MIME type to be correct for the manifest but Gitea
# doesn't tell S3... By hiding the header we can use add_header to set Content-Type
# (normally can't be set directly)
extraConfig = ''
proxy_hide_header Content-Type;
add_header Content-Type $upstream_http_content_type always;
if ($args ~ "response-content-disposition=.+filename%3D%22manifest\.json%22") {
add_header Content-Type "application/vnd.docker.distribution.manifest.v2+json";
}
'';
};
};
useACMEHost = pubDomain; useACMEHost = pubDomain;
}; };
"nix-cache.${pubDomain}" = { "nix-cache.${pubDomain}" = {
locations = { locations = {
"/" = { "/".proxyPass = "http://${host}:8069";
proxyPass = "http://${host}:5000";
};
"~ ${nixCacheableRegex}" = { "~ ${nixCacheableRegex}" = {
proxyPass = "http://${host}:5000"; proxyPass = "http://${host}:8069";
extraConfig = nixCacheHeaders; extraConfig = nixCacheHeaders;
}; };
}; };

View File

@@ -31,13 +31,6 @@ 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;
@@ -55,21 +48,11 @@ 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/wastebin.env" = {};
}; };
}; };
firewall = { firewall = {
tcp.allowed = [ tcp.allowed = [ 9000 9001 config.services.sharry.config.bind.port 8069 ];
9000 9001
config.services.sharry.config.bind.port
8069
5000
config.services.hedgedoc.settings.port
8088
];
}; };
user.homeConfig = { user.homeConfig = {
@@ -77,26 +60,14 @@ in
}; };
}; };
users = with lib.my.c.ids; mkMerge [ users = with lib.my.c.ids; let inherit (config.services.atticd) user group; in {
(let inherit (config.services.atticd) user group; in {
users."${user}" = { users."${user}" = {
isSystemUser = true; isSystemUser = true;
uid = uids.atticd; uid = uids.atticd;
group = group; group = group;
}; };
groups."${user}".gid = gids.atticd; groups."${user}".gid = gids.atticd;
})
{
users = {
harmonia = {
shell = pkgs.bashInteractive;
openssh.authorizedKeys.keyFiles = [
lib.my.c.sshKeyFiles.harmonia
];
}; };
};
}
];
systemd = { systemd = {
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal; network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
@@ -114,9 +85,7 @@ 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
{ {
@@ -127,15 +96,6 @@ in
}; };
} }
]; ];
harmonia = {
environment.NIX_REMOTE = "/var/lib/harmonia";
preStart = ''
${config.nix.package}/bin/nix store ping
'';
serviceConfig = {
StateDirectory = "harmonia";
};
};
}; };
}; };
@@ -215,8 +175,8 @@ in
}; };
atticd = { atticd = {
enable = false; enable = true;
environmentFile = config.age.secrets."object/atticd.env".path; credentialsFile = config.age.secrets."object/atticd.env".path;
settings = { settings = {
listen = "[::]:8069"; listen = "[::]:8069";
allowed-hosts = [ "nix-cache.${pubDomain}" ]; allowed-hosts = [ "nix-cache.${pubDomain}" ];
@@ -234,43 +194,6 @@ in
}; };
}; };
}; };
harmonia = {
enable = true;
signKeyPaths = [ config.age.secrets."nix-cache.key".path ];
settings = {
priority = 30;
};
};
hedgedoc = {
enable = true;
environmentFile = config.age.secrets."object/hedgedoc.env".path;
settings = {
domain = "md.${pubDomain}";
protocolUseSSL = true;
db = {
dialect = "postgresql";
username = "hedgedoc";
database = "hedgedoc";
host = "colony-psql";
};
host = "::";
allowAnonymous = false;
allowAnonymousEdits = true;
email = true;
allowEmailRegister = false;
};
};
wastebin = {
enable = true;
settings = {
WASTEBIN_MAX_BODY_SIZE = 67108864; # 16 MiB
WASTEBIN_PASSWORD_SALT = "TeGhaemeer0Siez3";
};
secretFile = config.age.secrets."object/wastebin.env".path;
};
}; };
} }
(mkIf config.my.build.isDevVM { (mkIf config.my.build.isDevVM {

View File

@@ -1,115 +0,0 @@
{ 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

@@ -26,8 +26,6 @@ in
let let
inherit (lib) mkMerge mkIf genAttrs; inherit (lib) mkMerge mkIf genAttrs;
inherit (lib.my) networkdAssignment systemdAwaitPostgres; inherit (lib.my) networkdAssignment systemdAwaitPostgres;
pdsPort = 3000;
in in
{ {
config = mkMerge [ config = mkMerge [
@@ -38,7 +36,7 @@ in
secrets = { secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSslLkDe54AKYzxdtKD70zcU72W0EpYsfbdJ6UFq0QK"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSslLkDe54AKYzxdtKD70zcU72W0EpYsfbdJ6UFq0QK";
files = (genAttrs files = genAttrs
(map (f: "toot/${f}") [ (map (f: "toot/${f}") [
"postgres-password.txt" "postgres-password.txt"
"secret-key.txt" "secret-key.txt"
@@ -50,12 +48,7 @@ in
(_: with config.services.mastodon; { (_: with config.services.mastodon; {
owner = user; owner = user;
inherit group; inherit group;
})) // { });
"toot/pds.env" = {
owner = "pds";
group = "pds";
};
};
}; };
firewall = { firewall = {
@@ -63,7 +56,6 @@ in
19999 19999
"http" "http"
pdsPort
]; ];
}; };
}; };
@@ -87,7 +79,7 @@ in
netdata.enable = true; netdata.enable = true;
mastodon = mkMerge [ mastodon = mkMerge [
rec { rec {
enable = false; enable = true;
localDomain = extraConfig.WEB_DOMAIN; # for nginx config localDomain = extraConfig.WEB_DOMAIN; # for nginx config
extraConfig = { extraConfig = {
LOCAL_DOMAIN = "nul.ie"; LOCAL_DOMAIN = "nul.ie";
@@ -95,9 +87,7 @@ in
}; };
secretKeyBaseFile = config.age.secrets."toot/secret-key.txt".path; secretKeyBaseFile = config.age.secrets."toot/secret-key.txt".path;
# TODO: This was removed at some point. otpSecretFile = config.age.secrets."toot/otp-secret.txt".path;
# If we want to bring Mastodon back, this will probably need to be addressd.
# otpSecretFile = config.age.secrets."toot/otp-secret.txt".path;
vapidPrivateKeyFile = config.age.secrets."toot/vapid-key.txt".path; vapidPrivateKeyFile = config.age.secrets."toot/vapid-key.txt".path;
vapidPublicKeyFile = toString (pkgs.writeText vapidPublicKeyFile = toString (pkgs.writeText
"vapid-pubkey.txt" "vapid-pubkey.txt"
@@ -165,32 +155,6 @@ in
}; };
}; };
}; };
bluesky-pds = {
enable = true;
environmentFiles = [ config.age.secrets."toot/pds.env".path ];
settings = {
PDS_HOSTNAME = "pds.nul.ie";
PDS_PORT = pdsPort;
PDS_BLOBSTORE_DISK_LOCATION = null;
PDS_BLOBSTORE_S3_BUCKET = "pds";
PDS_BLOBSTORE_S3_ENDPOINT = "https://s3.nul.ie/";
PDS_BLOBSTORE_S3_REGION = "eu-central-1";
PDS_BLOBSTORE_S3_ACCESS_KEY_ID = "pds";
PDS_BLOB_UPLOAD_LIMIT = "52428800";
PDS_EMAIL_FROM_ADDRESS = "pds@nul.ie";
PDS_DID_PLC_URL = "https://plc.directory";
PDS_INVITE_REQUIRED = 1;
PDS_BSKY_APP_VIEW_URL = "https://api.bsky.app";
PDS_BSKY_APP_VIEW_DID = "did:web:api.bsky.app";
PDS_REPORT_SERVICE_URL = "https://mod.bsky.app";
PDS_REPORT_SERVICE_DID = "did:plc:ar7c4by46qjdydhdevvrndac";
PDS_CRAWLERS = "https://bsky.network";
};
};
}; };
} }
(mkIf config.my.build.isDevVM { (mkIf config.my.build.isDevVM {

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 = 8080; ROCKET_PORT = 80;
SMTP_HOST = "mail.nul.ie"; SMTP_HOST = "mail.nul.ie";
SMTP_FROM = "pass@nul.ie"; SMTP_FROM = "pass@nul.ie";
@@ -99,8 +99,6 @@ 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://hs.nul.ie" "--login-server=https://ts.nul.ie"
"--netfilter-mode=off" "--netfilter-mode=off"
"--advertise-exit-node" "--advertise-exit-node"
"--advertise-routes=${advRoutes}" "--advertise-routes=${advRoutes}"

View File

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

View File

@@ -50,11 +50,6 @@ in
}; };
}) { }) {
valheim-oci = 2; valheim-oci = 2;
simpcraft-oci = 3;
simpcraft-staging-oci = 4;
enshrouded-oci = 5;
kevcraft-oci = 6;
kinkcraft-oci = 7;
}; };
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }: configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
@@ -68,8 +63,6 @@ in
"${modulesPath}/profiles/qemu-guest.nix" "${modulesPath}/profiles/qemu-guest.nix"
./valheim.nix ./valheim.nix
./minecraft
# ./enshrouded.nix
]; ];
config = mkMerge [ config = mkMerge [
@@ -112,31 +105,46 @@ in
oci-containers = { oci-containers = {
backend = "podman"; backend = "podman";
}; };
containers.containersConf.settings.network = { # NixOS has switched to using netavark, which is native to podman. It's currently missing an option to
network_backend = "netavark"; # disable iptables rules generation, which is very annoying.
firewall_driver = "none"; containers.containersConf.settings.network.network_backend = mkForce "cni";
};
}; };
environment = { environment = {
etc = { etc = {
"containers/networks/colony.json".text = toJSON { "cni/net.d/90-colony.conflist".text = toJSON {
cniVersion = "0.4.0";
name = "colony"; name = "colony";
id = "0000000000000000000000000000000000000000000000000000000000000001"; plugins = [
driver = "bridge"; {
network_interface = "oci"; type = "bridge";
ipv6_enabled = true; bridge = "oci";
internal = false; isGateway = true;
dns_enabled = false; ipMasq = false;
subnets = [ hairpinMode = true;
ipam = {
type = "host-local";
routes = [
{ dst = "0.0.0.0/0"; }
{ dst = "::/0"; }
];
ranges = [
[
{ {
subnet = prefixes.oci.v4; subnet = prefixes.oci.v4;
gateway = net.cidr.host 1 prefixes.oci.v4; gateway = net.cidr.host 1 prefixes.oci.v4;
} }
]
[
{ {
subnet = prefixes.oci.v6; subnet = prefixes.oci.v6;
gateway = net.cidr.host 1 prefixes.oci.v6; gateway = net.cidr.host 1 prefixes.oci.v6;
} }
]
];
};
capabilities.ips = true;
}
]; ];
}; };
}; };

View File

@@ -1,35 +0,0 @@
{ 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

@@ -1,228 +0,0 @@
{ lib, pkgs, config, allAssignments, ... }:
let
inherit (lib) concatStringsSep;
inherit (lib.my) dockerNetAssignment;
# devplayer0
op = "6d7d971b-ce10-435b-85c5-c99c0d8d288c";
kev = "703b378a-09f9-4c1d-9876-1c9305728c49";
whitelist = concatStringsSep "," [
op
"dcd2ecb9-2b5e-49cb-9d4f-f5a76162df56" # Elderlypug
"fcb26db2-c3ce-41aa-b588-efec79d37a8a" # Jesthral_
"1d366062-12c0-4e29-aba7-6ab5d8c6bb05" # shr3kas0ras
kev
"f105bbe6-eda6-4a13-a8cf-894e77cab77b" # Adzerq
"1fc94979-41fb-497a-81e9-34ae24ca537a" # johnnyscrims
"d53c91df-b6e6-4463-b106-e8427d7a8d01" # BossLonus
"f439f64d-91c9-4c74-9ce5-df4d24cd8e05" # hynge_
"d6ec4c91-5da2-44eb-b89d-71dc8fe017a0" # Eefah98
"096a7348-fabe-4b2d-93fc-fd1fd5608fb0" # ToTheMoonStar
];
fastback = {
gitConfig = pkgs.writeText "git-config" ''
[user]
email = "simpcraft@nul.ie"
name = "Simpcraft bot"
'';
};
in
{
config = {
virtualisation.oci-containers.containers = {
simpcraft = {
image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
environment = {
TYPE = "MODRINTH";
EULA = "true";
ENABLE_QUERY = "true";
ENABLE_RCON = "true";
MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t §4§k-----";
ICON = "/ext/icon.png";
EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
WHITELIST = whitelist;
EXISTING_OPS_FILE = "SYNCHRONIZE";
OPS = op;
DIFFICULTY = "normal";
SPAWN_PROTECTION = "0";
VIEW_DISTANCE = "20";
MAX_MEMORY = "8G";
MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/NGutsQSd/Simpcraft-0.2.1.mrpack";
TZ = "Europe/Dublin";
};
environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
volumes = [
"minecraft_data:/data"
"${./icon.png}:/ext/icon.png:ro"
"${fastback.gitConfig}:/data/.config/git/config:ro"
];
extraOptions = [
''--network=colony:${dockerNetAssignment allAssignments "simpcraft-oci"}''
];
};
# simpcraft-staging = {
# image = "git.nul.ie/dev/craftblock:2024.1.0-java17-alpine";
# environment = {
# TYPE = "MODRINTH";
# EULA = "true";
# ENABLE_QUERY = "true";
# ENABLE_RCON = "true";
# MOTD = "§4§k----- §9S§ai§bm§cp§dc§er§fa§6f§5t [staging] §4§k-----";
# ICON = "/ext/icon.png";
# EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
# WHITELIST = whitelist;
# EXISTING_OPS_FILE = "SYNCHRONIZE";
# OPS = op;
# DIFFICULTY = "normal";
# SPAWN_PROTECTION = "0";
# VIEW_DISTANCE = "20";
# MAX_MEMORY = "4G";
# MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/Ym3sIi6H/Simpcraft-0.2.0.mrpack";
# TZ = "Europe/Dublin";
# };
# environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
# volumes = [
# "minecraft_staging_data:/data"
# "${./icon.png}:/ext/icon.png:ro"
# ];
# extraOptions = [
# ''--network=colony:${dockerNetAssignment allAssignments "simpcraft-staging-oci"}''
# ];
# };
kevcraft = {
# 2025.2.1-java21-alpine
image = "itzg/minecraft-server@sha256:57e319c15e9fee63f61029a65a33acc3de85118b21a2b4bb29f351cf4a915027";
environment = {
TYPE = "VANILLA";
VERSION = "1.20.1";
SERVER_PORT = "25567";
QUERY_PORT = "25567";
EULA = "true";
ENABLE_QUERY = "true";
ENABLE_RCON = "true";
MOTD = "§4§k----- §9K§ae§bv§cc§dr§ea§ff§6t §4§k-----";
ICON = "/ext/icon.png";
EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
WHITELIST = whitelist;
EXISTING_OPS_FILE = "SYNCHRONIZE";
OPS = concatStringsSep "," [ op kev ];
DIFFICULTY = "normal";
SPAWN_PROTECTION = "0";
# VIEW_DISTANCE = "20";
MAX_MEMORY = "4G";
TZ = "Europe/Dublin";
};
environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
volumes = [
"kevcraft_data:/data"
"${./kev.png}:/ext/icon.png:ro"
];
extraOptions = [
''--network=colony:${dockerNetAssignment allAssignments "kevcraft-oci"}''
];
};
kinkcraft = {
# 2025.5.1-java21-alpine
image = "itzg/minecraft-server@sha256:de26c7128e3935f3be48fd30283f0b5a6da1b3d9f1a10c9f92502ee1ba072f7b";
environment = {
TYPE = "MODRINTH";
SERVER_PORT = "25568";
QUERY_PORT = "25568";
EULA = "true";
ENABLE_QUERY = "true";
ENABLE_RCON = "true";
MOTD = "§4§k----- §9K§ai§bn§ck§dc§er§fa§6f§5t §4§k-----";
ICON = "/ext/icon.png";
EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
WHITELIST = whitelist;
EXISTING_OPS_FILE = "SYNCHRONIZE";
OPS = op;
DIFFICULTY = "normal";
SPAWN_PROTECTION = "0";
VIEW_DISTANCE = "20";
MAX_MEMORY = "6G";
MODRINTH_MODPACK = "https://cdn.modrinth.com/data/CIYf3Hk8/versions/NGutsQSd/Simpcraft-0.2.1.mrpack";
TZ = "Europe/Dublin";
};
environmentFiles = [ config.age.secrets."whale2/simpcraft.env".path ];
volumes = [
"kinkcraft_data:/data"
"${./icon.png}:/ext/icon.png:ro"
];
extraOptions = [
''--network=colony:${dockerNetAssignment allAssignments "kinkcraft-oci"}''
];
};
};
services = {
borgbackup.jobs.simpcraft =
let
rconCommand = cmd: ''${pkgs.mcrcon}/bin/mcrcon -H simpcraft-oci -p "$RCON_PASSWORD" "${cmd}"'';
in
{
paths = [ "/var/lib/containers/storage/volumes/minecraft_data/_data/world" ];
repo = "/var/lib/containers/backup/simpcraft";
doInit = true;
encryption.mode = "none";
compression = "zstd,10";
# every ~15 minutes offset from 5 minute intervals (Minecraft seems to save at precise times?)
startAt = "*:03,17,33,47";
prune.keep = {
within = "12H";
hourly = 48;
};
readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ];
# Avoid Minecraft poking the files while we back up
preHook = rconCommand "save-off";
postHook = rconCommand "save-on";
};
};
systemd = {
services = {
borgbackup-job-simpcraft.serviceConfig.EnvironmentFile = [ config.age.secrets."whale2/simpcraft.env".path ];
};
};
my = {
secrets.files = {
"whale2/simpcraft.env" = {};
};
};
};
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.4 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

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}="4" ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="2"
''; '';
}; };
@@ -110,7 +110,7 @@ in
hwloc hwloc
]; ];
networking = { inherit domain; }; networking.domain = "h.${pubDomain}";
systemd = { systemd = {
tmpfiles.rules = [ tmpfiles.rules = [
@@ -144,13 +144,6 @@ in
netdevs = mkMerge [ netdevs = mkMerge [
(mkVLAN "lan-hi" vlans.hi) (mkVLAN "lan-hi" vlans.hi)
(mkVLAN "lan-lo-phy" vlans.lo)
{
"25-lan-lo".netdevConfig = {
Name = "lan-lo";
Kind = "bridge";
};
}
]; ];
networks = { networks = {
@@ -158,7 +151,6 @@ in
(networkdAssignment "lan-core" assignments.core) (networkdAssignment "lan-core" assignments.core)
{ {
matchConfig.Name = "lan-core"; matchConfig.Name = "lan-core";
vlan = [ "lan-lo-phy" ];
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
} }
]; ];
@@ -181,35 +173,9 @@ in
VirtualFunction=1 VirtualFunction=1
LinkState=yes LinkState=yes
MACAddress=52:54:00:8a:8a:f2 MACAddress=52:54:00:8a:8a:f2
# sfh
[SR-IOV]
VirtualFunction=2
VLANId=${toString vlans.hi}
LinkState=yes
MACAddress=52:54:00:ac:15:a9
# 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;
"50-lan-lo-phy" = {
matchConfig.Name = "lan-lo-phy";
networkConfig = {
Bridge = "lan-lo";
} // networkd.noL3;
};
"60-lan-lo" = {
matchConfig.Name = "lan-lo";
linkConfig.RequiredForOnline = "no";
networkConfig = networkd.noL3;
};
}; };
}; };
}; };

View File

@@ -58,15 +58,12 @@ in
}; };
}; };
networking = { inherit domain; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
pciutils pciutils
partclone partclone
]; ];
services = { services = {
fstrim.enable = true;
netdata.enable = true; netdata.enable = true;
}; };

View File

@@ -129,12 +129,6 @@ 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,7 +2,6 @@
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, ... }:
@@ -56,19 +55,7 @@
}; };
}; };
systemd.services = systemd.services = {
let
awaitVM = system: {
after = [ "vm@${system}.service" ];
bindsTo = [ "vm@${system}.service" ];
preStart = ''
until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.${system}.hi.ipv4.address} 22; do
sleep 1
done
'';
};
in
{
"vm@cellar" = { "vm@cellar" = {
serviceConfig = { serviceConfig = {
CPUAffinity = "numa"; CPUAffinity = "numa";
@@ -76,19 +63,20 @@
NUMAMask = "1"; NUMAMask = "1";
}; };
}; };
"vm@river" = "vm@river" =
let let
vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device"; vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
in in
mkMerge [
(awaitVM "cellar")
{ {
requires = [ vtapUnit ]; requires = [ vtapUnit ];
after = [ vtapUnit ]; after = [ vtapUnit "vm@cellar.service" ];
} bindsTo = [ "vm@cellar.service" ];
]; preStart = ''
"vm@sfh" = (awaitVM "river"); until ${pkgs.netcat}/bin/nc -w1 -z ${allAssignments.cellar.hi.ipv4.address} 22; do
sleep 1
done
'';
};
}; };
my = { my = {
@@ -140,7 +128,7 @@
threads = 2; threads = 2;
}; };
memory = 4096; memory = 4096;
cleanShutdown.timeout = 60; cleanShutdown.timeout = 120;
networks = { networks = {
et1g0 = { et1g0 = {
ifname = "vm-et1g0"; ifname = "vm-et1g0";
@@ -162,40 +150,6 @@
}; };
}; };
}; };
sfh = {
uuid = "82ec149d-577c-421a-93e2-a9307c756cd8";
cpu = "host,topoext";
smp = {
cpus = 8;
threads = 2;
};
memory = 32768;
cleanShutdown.timeout = 120;
networks.netboot = {
bridge = "lan-lo";
waitOnline = "carrier";
mac = "52:54:00:a5:7e:93";
extraOptions.bootindex = 1;
};
hostDevices = {
et100g0vf2 = {
index = 0;
hostBDF = "44:00.3";
};
et100g0vf3 = {
index = 1;
hostBDF = "44:00.4";
};
};
qemuFlags = [
"device qemu-xhci,id=xhci"
# Front-right port?
"device usb-host,hostbus=1,hostport=4"
# Front-left port
"device usb-host,hostbus=1,hostport=3"
];
};
}; };
}; };
}; };

View File

@@ -10,7 +10,18 @@
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 domain prefixes roceBootModules; inherit (lib.my.c.home) vlans;
lanLink = {
matchConfig = {
Driver = "mlx5_core";
PermanentMACAddress = "52:54:00:8a:8a:f2";
};
linkConfig = {
Name = "lan";
MTUBytes = toString lib.my.c.home.hiMTU;
};
};
in in
{ {
imports = [ imports = [
@@ -19,17 +30,29 @@
config = { config = {
boot = { boot = {
kernelModules = [ "kvm-amd" ]; kernelModules = [ "kvm-intel" ];
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"
"8021q" "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" "8021q"
] ++ roceBootModules; "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma"
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 = {
# Don't need to put the link config here, they're copied from main config enable = true;
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" = {
@@ -47,6 +70,9 @@
hardware = { hardware = {
enableRedistributableFirmware = true; enableRedistributableFirmware = true;
cpu = {
intel.updateMicrocode = true;
};
}; };
fileSystems = { fileSystems = {
@@ -70,7 +96,6 @@
boot.thin.enable = true; boot.thin.enable = true;
dmeventd.enable = true; dmeventd.enable = true;
}; };
fstrim.enable = true;
}; };
systemd.network = { systemd.network = {
@@ -89,16 +114,7 @@
}; };
}; };
"10-lan" = { "10-lan" = lanLink;
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!
@@ -118,14 +134,6 @@
}; };
}; };
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

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

View File

@@ -1,262 +0,0 @@
{ lib, ... }:
let
inherit (lib.my) net;
inherit (lib.my.c) pubDomain;
inherit (lib.my.c.home) domain prefixes vips hiMTU;
in
{
nixos.systems.hass = { config, ... }: {
system = "x86_64-linux";
nixpkgs = "mine";
rendered = config.configuration.config.my.asContainer;
assignments = {
hi = {
name = "hass-ctr";
altNames = [ "frigate" ];
inherit domain;
mtu = hiMTU;
ipv4 = {
address = net.cidr.host 103 prefixes.hi.v4;
mask = 22;
gateway = vips.hi.v4;
};
ipv6 = {
iid = "::5:3";
address = net.cidr.host (65536*5+3) prefixes.hi.v6;
};
};
lo = {
name = "hass-ctr-lo";
inherit domain;
mtu = 1500;
ipv4 = {
address = net.cidr.host 103 prefixes.lo.v4;
mask = 21;
gateway = null;
};
ipv6 = {
iid = "::5:3";
address = net.cidr.host (65536*5+3) prefixes.lo.v6;
};
};
};
configuration = { lib, config, pkgs, assignments, allAssignments, ... }:
let
inherit (lib) mkMerge mkIf mkForce;
inherit (lib.my) networkdAssignment;
hassCli = pkgs.writeShellScriptBin "hass-cli" ''
export HASS_SERVER="http://localhost:${toString config.services.home-assistant.config.http.server_port}"
export HASS_TOKEN="$(< ${config.age.secrets."hass/cli-token.txt".path})"
exec ${pkgs.home-assistant-cli}/bin/hass-cli "$@"
'';
in
{
config = {
my = {
deploy.enable = false;
server.enable = true;
secrets = {
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIGpYX2WbYwUqHp8bFFf0eHFrqrR8xp8IheguA054F8V4";
files = {
"hass/cli-token.txt" = {
owner = config.my.user.config.name;
};
};
};
firewall = {
tcp.allowed = [ "http" 1883 ];
};
};
environment = {
systemPackages = with pkgs; [
usbutils
hassCli
];
};
systemd = {
network.networks = {
"80-container-host0" = networkdAssignment "host0" assignments.hi;
"80-container-lan-lo" = networkdAssignment "lan-lo" assignments.lo;
};
};
services = {
mosquitto = {
enable = true;
listeners = [
{
omitPasswordAuth = true;
settings = {
allow_anonymous = true;
};
}
];
};
go2rtc = {
enable = true;
settings = {
streams = {
reolink_living_room = [
# "http://reolink-living-room.${domain}/flv?port=1935&app=bcs&stream=channel0_main.bcs&user=admin#video=copy#audio=copy#audio=opus"
"rtsp://admin:@reolink-living-room:554/h264Preview_01_main"
];
webcam_office = [
"ffmpeg:device?video=/dev/video0&video_size=1024x576#video=h264"
];
};
};
};
frigate = {
enable = true;
hostname = "frigate.${domain}";
settings = {
mqtt = {
enabled = true;
host = "localhost";
topic_prefix = "frigate";
};
cameras = {
reolink_living_room = {
ffmpeg.inputs = [
{
path = "rtsp://127.0.0.1:8554/reolink_living_room";
input_args = "preset-rtsp-restream";
roles = [ "record" "detect" ];
}
];
detect = {
enabled = false;
};
record = {
enabled = true;
retain.days = 1;
};
};
webcam_office = {
ffmpeg.inputs = [
{
path = "rtsp://127.0.0.1:8554/webcam_office";
input_args = "preset-rtsp-restream";
roles = [ "record" "detect" ];
}
];
detect.enabled = false;
record = {
enabled = true;
retain.days = 1;
};
};
};
};
};
home-assistant =
let
cfg = config.services.home-assistant;
pyirishrail = ps: ps.buildPythonPackage rec {
pname = "pyirishrail";
version = "0.0.2";
src = pkgs.fetchFromGitHub {
owner = "ttroy50";
repo = "pyirishrail";
tag = version;
hash = "sha256-NgARqhcXP0lgGpgBRiNtQaSn9JcRNtCcZPljcL7t3Xc=";
};
dependencies = with ps; [
requests
];
pyproject = true;
build-system = [ ps.setuptools ];
};
in
{
enable = true;
extraComponents = [
"default_config"
"esphome"
"google_translate"
"met"
"zha"
"denonavr"
"webostv"
"androidtv_remote"
"heos"
"mqtt"
"wled"
];
extraPackages = python3Packages: with python3Packages; [
zlib-ng
isal
gtts
(pyirishrail python3Packages)
];
customComponents = with pkgs.home-assistant-custom-components; [
alarmo
frigate
];
configWritable = false;
openFirewall = true;
config = {
default_config = {};
homeassistant = {
name = "Home";
unit_system = "metric";
currency = "EUR";
country = "IE";
time_zone = "Europe/Dublin";
external_url = "https://hass.${pubDomain}";
internal_url = "http://hass-ctr.${domain}:${toString cfg.config.http.server_port}";
};
http = {
use_x_forwarded_for = true;
trusted_proxies = with allAssignments.middleman.internal; [
ipv4.address
ipv6.address
];
ip_ban_enabled = false;
};
automation = "!include automations.yaml";
script = "!include scripts.yaml";
scene = "!include scenes.yaml";
sensor = [
{
platform = "irish_rail_transport";
name = "To Work from Home";
station = "Glenageary";
stops_at = "Dublin Connolly";
direction = "Northbound";
}
{
platform = "irish_rail_transport";
name = "To Home from Work";
station = "Dublin Connolly";
stops_at = "Glenageary";
direction = "Southbound";
}
];
};
};
};
};
};
};
}

View File

@@ -1,65 +0,0 @@
{ 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.unifi;
mongodbPackage = pkgs.mongodb-7_0;
};
};
};
};
};
}

View File

@@ -1,200 +0,0 @@
{ 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 mkForce;
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;
};
};
environment = {
systemPackages = with pkgs; [
usbutils
];
};
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;
};
};
"10-lan-lo-ctrs" = {
matchConfig = {
Driver = "virtio_net";
PermanentMACAddress = "52:54:00:a5:7e:93";
};
linkConfig.Name = "lan-lo-ctrs";
};
};
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;
};
"30-lan-lo-ctrs" = {
matchConfig.Name = "lan-lo-ctrs";
linkConfig.RequiredForOnline = "no";
networkConfig = networkd.noL3;
};
};
};
systemd.nspawn = {
hass = {
networkConfig = {
MACVLAN = mkForce "lan-hi-ctrs:host0 lan-lo-ctrs:lan-lo";
};
};
};
systemd.services = {
"systemd-nspawn@hass".serviceConfig.DeviceAllow = [
"char-ttyUSB rw"
"char-video4linux rw"
];
};
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 = {};
hass = {
bindMounts = {
"/dev/bus/usb/001/002".readOnly = false;
"/dev/video0".readOnly = false;
"/dev/serial/by-id/usb-Nabu_Casa_Home_Assistant_Connect_ZBT-1_ce549704fe38ef11a2c2e5d154516304-if00-port0" = {
readOnly = false;
mountPoint = "/dev/ttyUSB0";
};
};
};
};
in
mkMerge [
instances
(mapAttrs (n: i: {
networking.macVLAN = "lan-hi-ctrs";
}) instances)
];
};
};
};
};
}

View File

@@ -141,40 +141,26 @@ in
onState = [ "configured" ]; onState = [ "configured" ];
script = '' script = ''
#!${pkgs.runtimeShell} #!${pkgs.runtimeShell}
if [ "$IFACE" = "wan-ifb" ]; then if [ $IFACE = "wan-ifb" ]; then
${pkgs.iproute2}/bin/tc filter add dev wan parent ffff: matchall action mirred egress redirect dev "$IFACE" ${pkgs.iproute2}/bin/tc filter add dev wan parent ffff: matchall action mirred egress redirect dev $IFACE
fi fi
''; '';
}; };
}; };
}; };
nginx.enable = true;
}; };
networking = { inherit domain; }; networking.domain = "h.${pubDomain}";
systemd.services = systemd.services = {
ipsec =
let let
waitOnline = "systemd-networkd-wait-online@wan.service"; waitOnline = "systemd-networkd-wait-online@wan.service";
in in
{ {
ipsec = {
after = [ waitOnline ]; after = [ waitOnline ];
requires = [ waitOnline ]; requires = [ waitOnline ];
}; };
ipv6-clear-default-route = {
description = "Clear IPv6 RA default route";
after = [ waitOnline ];
requires = [ waitOnline ];
script = ''
# Seems like we can sometimes pick up a default route somehow...
${pkgs.iproute2}/bin/ip -6 route del default via fe80::1 || true
'';
serviceConfig.Type = "oneshot";
wantedBy = [ "multi-user.target" ];
};
}; };
systemd.network = { systemd.network = {
@@ -227,8 +213,8 @@ in
networkConfig = networkd.noL3; networkConfig = networkd.noL3;
extraConfig = '' extraConfig = ''
[CAKE] [CAKE]
Bandwidth=490M Bandwidth=235M
RTTSec=50ms RTTSec=10ms
PriorityQueueingPreset=besteffort PriorityQueueingPreset=besteffort
# DOCSIS preset # DOCSIS preset
OverheadBytes=18 OverheadBytes=18
@@ -251,8 +237,8 @@ in
extraConfig = '' extraConfig = ''
[CAKE] [CAKE]
Parent=root Parent=root
Bandwidth=48M Bandwidth=24M
RTTSec=50ms RTTSec=1ms
''; '';
} }
]; ];
@@ -276,7 +262,7 @@ in
{ {
matchConfig.Name = "as211024"; matchConfig.Name = "as211024";
networkConfig.IPv6AcceptRA = mkForce false; networkConfig.IPv6AcceptRA = mkForce false;
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
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;
@@ -301,7 +287,7 @@ in
{ {
"60-lan-hi" = { "60-lan-hi" = {
routes = [ routes = map (r: { routeConfig = r; }) [
{ {
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;
@@ -339,7 +325,6 @@ in
'' ''
table inet filter { table inet filter {
chain input { chain input {
${lib.my.c.as211024.nftTrust}
iifname base meta l4proto { udp, tcp } th dport domain accept iifname base meta l4proto { udp, tcp } th dport domain accept
iifname lan-core meta l4proto vrrp accept iifname lan-core meta l4proto vrrp accept
} }
@@ -372,16 +357,6 @@ in
return return
} }
chain forward-early {
type filter hook forward priority -1; policy accept;
# MSS clamping to workaround IPv6 PMTUD being broken...
tcp flags syn tcp option maxseg size set rt mtu counter
# More Disney+ discrimination...
# TODO: This prefix could change (random AWS block)
ip6 daddr 2600:9000:2245::/48 drop
}
chain forward { chain forward {
${lib.my.c.as211024.nftTrust} ${lib.my.c.as211024.nftTrust}
iifname lan-untrusted jump filter-untrusted iifname lan-untrusted jump filter-untrusted

View File

@@ -1,74 +0,0 @@
# Blocklist for LG WebOS Services (US)
ad.lgappstv.com
ibis.lgappstv.com
info.lgsmartad.com
lgtvsdp.com
ngfts.lge.com
rdx2.lgtvsdp.com
smartshare.lgtvsdp.com
lgappstv.com
us.ad.lgsmartad.com
us.ibs.lgappstv.com
us.info.lgsmartad.com
us.lgtvsdp.com
# Community Contributions
lgad.cjpowercast.com
edgesuite.net
yumenetworks.com
smartclip.net
smartclip.com
# Non-US Entries
rdx2.lgtvsdp.com
info.lgsmartad.com
ibs.lgappstv.com
lgtvsdp.com
lgappstv.com
smartshare.lgtvsdp.com
# Full Block for Europe and Other Regions
de.ad.lgsmartad.com
de.emp.lgsmartplatform.com
de.ibs.lgappstv.com
de.info.lgsmartad.com
de.lgeapi.com
de.lgtvsdp.com
de.rdx2.lgtvsdp.com
eu.ad.lgsmartad.com
eu.ibs.lgappstv.com
eu.info.lgsmartad.com
app-lgwebos.pluto.tv
it.lgtvsdp.com
it.lgeapi.com
it.emp.lgsmartplatform.com
# LG ThinQ Services
eic.common.lgthinq.com
eic.iotservice.lgthinq.com
eic.service.lgthinq.com
eic.ngfts.lge.com
eic.svc-lgthinq-com.aws-thinq-prd.net
eic.cdpsvc.lgtvcommon.com
eic.cdpbeacon.lgtvcommon.com
eic.cdplauncher.lgtvcommon.com
eic.homeprv.lgtvcommon.com
eic.lgtviot.com
eic.nudge.lgtvcommon.com
eic.rdl.lgtvcommon.com
eic.recommend.lgtvcommon.com
eic.service.lgtvcommon.com
gb-lgeapi-com.esi-prd.net
gb.lgeapi.com
lgtvonline.lge.com
lg-channelplus-de-beacons.xumo.com
lg-channelplus-de-mds.xumo.com
lg-channelplus-eu-beacons.xumo.com
lg-channelplus-eu-mds.xumo.com
kr-op-v2.lgthinqhome.com
ngfts.lge.com
noti.lgthinq.com
objectcontent.lgthinq.com
# Update Server Block
#snu.lge.com

View File

@@ -2,7 +2,6 @@ index: { lib, pkgs, config, assignments, allAssignments, ... }:
let let
inherit (builtins) attrNames elemAt; inherit (builtins) attrNames elemAt;
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c) pubDomain;
inherit (lib.my.c.home) prefixes vips routers; inherit (lib.my.c.home) prefixes vips routers;
name = elemAt routers index; name = elemAt routers index;
@@ -19,121 +18,54 @@ in
owner = "pdns"; owner = "pdns";
group = "pdns"; group = "pdns";
}; };
"home/pdns/recursor.yml" = { "home/pdns/recursor.conf" = {
owner = "pdns-recursor"; owner = "pdns-recursor";
group = "pdns-recursor"; group = "pdns-recursor";
}; };
"home/ddclient-cloudflare.key" = {};
}; };
pdns.recursor = { pdns.recursor = {
enable = true; enable = true;
extraSettingsFile = config.age.secrets."home/pdns/recursor.yml".path; extraSettingsFile = config.age.secrets."home/pdns/recursor.conf".path;
}; };
}; };
services = { services = {
pdns-recursor = { pdns-recursor = {
yaml-settings = { dns = {
incoming = { address = [
listen = [
"127.0.0.1" "::1" "127.0.0.1" "::1"
assignments.hi.ipv4.address assignments.hi.ipv6.address assignments.hi.ipv4.address assignments.hi.ipv6.address
assignments.lo.ipv4.address assignments.lo.ipv6.address assignments.lo.ipv4.address assignments.lo.ipv6.address
]; ];
allow_from = [ allowFrom = [
"127.0.0.0/8" "::1/128" "127.0.0.0/8" "::1/128"
prefixes.hi.v4 prefixes.hi.v6 prefixes.hi.v4 prefixes.hi.v6
prefixes.lo.v4 prefixes.lo.v6 prefixes.lo.v4 prefixes.lo.v6
] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]); ];
};
settings = {
query-local-address = [
"0.0.0.0"
"::"
];
forward-zones = map (z: "${z}=127.0.0.1:5353") authZones;
# DNS NOTIFY messages override TTL # DNS NOTIFY messages override TTL
allow_notify_for = authZones; allow-notify-for = authZones;
allow_notify_from = [ "127.0.0.0/8" "::1/128" ]; allow-notify-from = [ "127.0.0.0/8" "::1/128" ];
};
outgoing = {
source_address = [ "0.0.0.0" "::" ];
};
recursor = {
forward_zones = map (z: {
zone = z;
forwarders = [ "127.0.0.1:5353" ];
}) authZones;
lua_dns_script = pkgs.writeText "pdns-script.lua" ''
blocklist = newDS()
function preresolve(dq)
local name = dq.qname:toString()
-- Disney+ doesn't like our IP space...
if dq.qtype == pdns.AAAA and (string.find(name, "disneyplus") or string.find(name, "disney-plus") or string.find(name , "disney.api")) then
dq.rcode = 0
return true
end
if blocklist:check(dq.qname) then
if dq.qtype == pdns.A then
dq:addAnswer(dq.qtype, "127.0.0.1")
elseif dq.qtype == pdns.AAAA then
dq:addAnswer(dq.qtype, "::1")
end
return true
end
return false
end
for line in io.lines("${./dns-blocklist.txt}") do
entry = line:gsub("%s+", "")
if entry ~= "" and string.sub(entry, 1, 1) ~= "#" then
blocklist:add(entry)
end
end
'';
};
webservice = {
webserver = true; webserver = true;
address = "::"; webserver-address = "::";
allow_from = [ "127.0.0.1" "::1" ]; webserver-allow-from = [ "127.0.0.1" "::1" ];
};
}; };
}; };
}; };
systemd = { systemd.services = {
services = {
# Add AF_NETLINK to allow pulling IP from network interfaces # Add AF_NETLINK to allow pulling IP from network interfaces
pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK"; pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
ddns-update = {
description = "DNS update script";
after = [ "network.target" ];
path = [
(pkgs.python3.withPackages (ps: [ ps.cloudflare ]))
pkgs.ldns
];
serviceConfig = {
Type = "oneshot";
ExecStart =
''${./dns_update.py} -k ${config.age.secrets."home/ddclient-cloudflare.key".path} '' +
''${pubDomain} ns${toString (index + 1)}.${config.networking.domain}'';
};
wantedBy = [ "multi-user.target" ];
};
};
timers = {
ddns-update = {
description = "Periodically update DNS";
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "5min";
OnUnitInactiveSec = "5min";
};
};
};
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@@ -196,9 +128,8 @@ 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 ${allAssignments."${elemAt routers 0}".as211024.ipv6.address} ${elemAt routers 0} IN AAAA ${net.cidr.host 1 prefixes.hi.v6}
${elemAt routers 1} IN AAAA ${allAssignments."${elemAt routers 1}".as211024.ipv6.address} ${elemAt routers 1} IN AAAA ${net.cidr.host 2 prefixes.hi.v6}
boot IN CNAME river-hi.${config.networking.domain}.
@ IN NS ns1 @ IN NS ns1
@ IN NS ns2 @ IN NS ns2
@@ -222,19 +153,9 @@ in
dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4} dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6} dave-lo IN AAAA ${net.cidr.host (65536+2) prefixes.lo.v6}
shytzel IN A ${net.cidr.host 12 prefixes.core.v4}
wave IN A ${net.cidr.host 12 prefixes.hi.v4}
; wave IN AAAA ${net.cidr.host (65536+3) prefixes.hi.v6}
vibe IN A ${net.cidr.host 13 prefixes.hi.v4}
vibe IN AAAA ${net.cidr.host (65536+4) prefixes.hi.v6}
ups IN A ${net.cidr.host 20 prefixes.lo.v4} ups IN A ${net.cidr.host 20 prefixes.lo.v4}
palace-kvm IN A ${net.cidr.host 21 prefixes.lo.v4} palace-kvm IN A ${net.cidr.host 21 prefixes.lo.v4}
reolink-living-room IN A ${net.cidr.host 45 prefixes.lo.v4}
nixlight IN A ${net.cidr.host 46 prefixes.lo.v4}
${lib.my.dns.fwdRecords { ${lib.my.dns.fwdRecords {
inherit allAssignments names; inherit allAssignments names;
domain = config.networking.domain; domain = config.networking.domain;

View File

@@ -1,40 +0,0 @@
#!/usr/bin/env python3
import argparse
import subprocess
import cloudflare
def main():
parser = argparse.ArgumentParser(description='Cloudflare DNS update script')
parser.add_argument('-k', '--api-token-file', help='Cloudflare API token file')
parser.add_argument('zone', help='Cloudflare Zone')
parser.add_argument('record', help='Cloudflare record name')
args = parser.parse_args()
address = subprocess.check_output(
['drill', '-Q', '-p5353', '@127.0.0.1', args.record, 'A'],
encoding='utf8').strip()
cf_token = None
if args.api_token_file:
with open(args.api_token_file) as f:
cf_token = f.readline().strip()
cf = cloudflare.Cloudflare(api_token=cf_token)
zones = list(cf.zones.list(name=args.zone))
assert zones, f'Zone {args.zone} not found'
assert len(zones) == 1, f'More than one zone found for {args.zone}'
zone = zones[0]
records = list(cf.dns.records.list(zone_id=zone.id, name=args.record, type='A'))
assert records, f'Record {args.record} not found in zone {args.zone}'
assert len(records) == 1, f'More than one record found for {args.record}'
record = records[0]
print(f'Updating {args.record} -> {address}')
cf.dns.records.edit(
zone_id=zone.id, dns_record_id=record.id,
type='A', content=address)
if __name__ == '__main__':
main()

View File

@@ -1,7 +1,7 @@
index: { lib, pkgs, config, assignments, allAssignments, ... }: index: { lib, pkgs, assignments, ... }:
let let
inherit (lib) mkForce; inherit (lib) mkForce;
inherit (lib.my) net netbootKeaClientClasses; inherit (lib.my) net;
inherit (lib.my.c.home) domain prefixes vips hiMTU; inherit (lib.my.c.home) domain prefixes vips hiMTU;
dns-servers = [ dns-servers = [
@@ -26,11 +26,7 @@ in
}; };
systemd.services = { systemd.services = {
kea-dhcp4-server.serviceConfig = { kea-dhcp4-server.serviceConfig.DynamicUser = mkForce false;
# Sometimes interfaces might not be ready in time and Kea doesn't like that
Restart = "on-failure";
DynamicUser = mkForce false;
};
kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false; kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false;
}; };
@@ -59,18 +55,10 @@ in
} }
{ {
name = "domain-search"; name = "domain-search";
data = "${domain}, dyn.${domain}, ${lib.my.c.colony.domain}, ${lib.my.c.britway.domain}"; data = "${domain}, dyn.${domain}";
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;
@@ -132,37 +120,6 @@ in
hw-address = "24:8a:07:a8:fe:3a"; hw-address = "24:8a:07:a8:fe:3a";
ip-address = net.cidr.host 40 prefixes.lo.v4; ip-address = net.cidr.host 40 prefixes.lo.v4;
} }
{
# avr
hw-address = "8c:a9:6f:30:03:6b";
ip-address = net.cidr.host 41 prefixes.lo.v4;
}
{
# tv
hw-address = "00:a1:59:b8:4d:86";
ip-address = net.cidr.host 42 prefixes.lo.v4;
}
{
# android tv
hw-address = "b8:7b:d4:95:c6:74";
ip-address = net.cidr.host 43 prefixes.lo.v4;
}
{
# hass-panel
hw-address = "80:30:49:cd:d7:51";
ip-address = net.cidr.host 44 prefixes.lo.v4;
}
{
# reolink-living-room
hw-address = "ec:71:db:30:69:a4";
ip-address = net.cidr.host 45 prefixes.lo.v4;
}
{
# nixlight
hw-address = "00:4b:12:3b:d3:14";
ip-address = net.cidr.host 46 prefixes.lo.v4;
}
]; ];
} }
]; ];

View File

@@ -1,83 +1,52 @@
index: { lib, pkgs, config, ... }: index: { lib, pkgs, config, ... }:
let let
inherit (builtins) attrNames concatMap length; inherit (builtins) attrNames concatMap;
inherit (lib) optional concatMapStringsSep; inherit (lib) optional;
inherit (lib.my) net; inherit (lib.my) net;
inherit (lib.my.c.home) prefixes vips; inherit (lib.my.c.home) prefixes vips;
pingScriptFor = name: ips:
let
script' = pkgs.writeShellScript
"keepalived-ping-${name}"
(concatMapStringsSep " || " (ip: "${pkgs.iputils}/bin/ping -qnc 1 -W 1 ${ip}") ips);
in
{
script = toString script';
interval = 1;
timeout = (length ips) + 1;
rise = 3;
fall = 3;
};
vlanIface = vlan: if vlan == "as211024" then vlan else "lan-${vlan}"; vlanIface = vlan: if vlan == "as211024" then vlan else "lan-${vlan}";
vrrpIPs = family: concatMap (vlan: (optional (family == "v6") { vrrpIPs = family: concatMap (vlan: [
addr = "fe80::1/64";
dev = vlanIface vlan;
}) ++ [
{ {
addr = "${vips.${vlan}.${family}}/${toString (net.cidr.length prefixes.${vlan}.${family})}"; addr = "${vips.${vlan}.${family}}/${toString (net.cidr.length prefixes.${vlan}.${family})}";
dev = vlanIface vlan; dev = vlanIface vlan;
} }
]) (attrNames vips); ] ++ (optional (family == "v6") {
addr = "fe80::1/64";
dev = vlanIface vlan;
})) (attrNames vips);
mkVRRP = family: routerId: { mkVRRP = family: routerId: {
state = if index == 0 then "MASTER" else "BACKUP"; state = if index == 0 then "MASTER" else "BACKUP";
interface = "lan-core"; interface = "lan-core";
priority = 255 - index; priority = 255 - index;
virtualRouterId = routerId; virtualRouterId = routerId;
virtualIps = vrrpIPs family; virtualIps = vrrpIPs family;
trackScripts = [ "${family}Alive" ]; extraConfig = ''
notify_master "${config.systemd.package}/bin/systemctl start radvd.service"
notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service"
'';
}; };
in in
{ {
users = with lib.my.c.ids; {
users.keepalived_script = {
uid = uids.keepalived_script;
isSystemUser = true;
group = "keepalived_script";
};
groups.keepalived_script.gid = gids.keepalived_script;
};
services = { services = {
keepalived = { keepalived = {
enable = true; enable = true;
enableScriptSecurity = true;
extraGlobalDefs = '' extraGlobalDefs = ''
vrrp_version 3 vrrp_version 3
nftables keepalived nftables keepalived
''; '';
vrrpScripts = {
v4Alive = pingScriptFor "v4" [ "1.1.1.1" "8.8.8.8" "216.218.236.2" ];
v6Alive = pingScriptFor "v6" [ "2606:4700:4700::1111" "2001:4860:4860::8888" "2600::" ];
};
vrrpInstances = { vrrpInstances = {
v4 = mkVRRP "v4" 51; v4 = mkVRRP "v4" 51;
v6 = (mkVRRP "v6" 52) // { v6 = mkVRRP "v6" 52;
};
extraConfig = '' extraConfig = ''
notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root vrrp_sync_group main {
notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root group {
v4
v6
}
}
''; '';
}; };
}; };
# Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken...
# extraConfig = ''
# vrrp_sync_group main {
# group {
# v4
# v6
# }
# }
# '';
};
};
} }

View File

@@ -24,8 +24,8 @@ in
onState = [ "routable" ]; onState = [ "routable" ];
script = '' script = ''
#!${pkgs.runtimeShell} #!${pkgs.runtimeShell}
if [ "$IFACE" = "lan" ]; then if [ $IFACE = "lan" ]; then
${mstpd}/sbin/mstpctl setforcevers "$IFACE" rstp ${mstpd}/sbin/mstpctl setforcevers $IFACE rstp
fi fi
''; '';
}; };

View File

@@ -11,7 +11,7 @@ let
AdvLinkMTU ${toString prefixes."${name}".mtu}; AdvLinkMTU ${toString prefixes."${name}".mtu};
prefix ${prefixes."${name}".v6} {}; prefix ${prefixes."${name}".v6} {};
RDNSS ${net.cidr.host 1 prefixes."${name}".v6} ${net.cidr.host 2 prefixes."${name}".v6} {}; RDNSS ${net.cidr.host 1 prefixes."${name}".v6} ${net.cidr.host 2 prefixes."${name}".v6} {};
DNSSL ${domain} dyn.${domain} ${lib.my.c.colony.domain} ${lib.my.c.britway.domain} {}; DNSSL ${domain} dyn.${domain} {};
}; };
''; '';
in in

View File

@@ -43,38 +43,6 @@
}; };
}; };
services = {
mjpg-streamer = {
enable = false;
inputPlugin = "input_uvc.so";
outputPlugin = "output_http.so -w @www@ -n -p 5050";
};
octoprint = {
enable = false;
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" = {
@@ -155,7 +123,7 @@
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb"; key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb";
}; };
server.enable = true; server.enable = true;
# deploy.node.hostname = "192.168.68.2"; deploy.node.hostname = "192.168.68.2";
}; };
}; };
}; };

View File

@@ -26,7 +26,7 @@ in
config = { config = {
# Hardware acceleration for Jellyfin # Hardware acceleration for Jellyfin
hardware.graphics = { hardware.opengl = {
enable = true; enable = true;
extraPackages = with pkgs; [ extraPackages = with pkgs; [
vaapiIntel vaapiIntel
@@ -65,27 +65,13 @@ in
systemd = { systemd = {
services = { services = {
jackett.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ]; jackett.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ]; transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
# https://github.com/NixOS/nixpkgs/issues/258793#issuecomment-1748168206
transmission.serviceConfig = {
RootDirectoryStartOnly = lib.mkForce false;
RootDirectory = lib.mkForce "";
};
radarr.serviceConfig.UMask = "0002"; radarr.serviceConfig.UMask = "0002";
sonarr.serviceConfig.UMask = "0002"; sonarr.serviceConfig.UMask = "0002";
}; };
}; };
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,7 +2,6 @@
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";
@@ -73,12 +72,14 @@ in
RouteTable = routeTable; RouteTable = routeTable;
}; };
wireguardPeers = [ wireguardPeers = [
# AirVPN IE
{ {
# AirVPN IE
wireguardPeerConfig = {
Endpoint = "146.70.94.2:1637"; Endpoint = "146.70.94.2:1637";
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk="; PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
PresharedKeyFile = config.age.secrets."${pskFile}".path; PresharedKeyFile = config.age.secrets."${pskFile}".path;
AllowedIPs = [ "0.0.0.0/0" "::/0" ]; AllowedIPs = [ "0.0.0.0/0" "::/0" ];
};
} }
]; ];
}; };
@@ -88,14 +89,13 @@ 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 = [ routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;

View File

@@ -92,19 +92,17 @@ in
nextcloud = { nextcloud = {
enable = true; enable = true;
# TODO: Might need to do some bullshit to go from Nextcloud 28 (?) to 30 package = pkgs.nextcloud27;
package = pkgs.nextcloud30;
datadir = "/mnt/storage/nextcloud"; datadir = "/mnt/storage/nextcloud";
hostName = "cloud.${domain}"; hostName = "cloud.${domain}";
https = true; https = true;
config = { config = {
extraTrustedDomains = [ "cloud-local.${domain}" ];
adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path; adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path;
dbtype = "sqlite"; defaultPhoneRegion = "IE";
}; };
settings = { extraOptions = {
updatechecker = false; updatechecker = false;
trusted_domains = [ "cloud-local.${domain}" ];
default_phone_region = "IE";
}; };
}; };
}; };

View File

@@ -84,7 +84,6 @@ 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
@@ -104,7 +103,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";
@@ -137,17 +136,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;
@@ -156,7 +155,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 ipv4MTU; inherit (lib.my.c.kelder) domain prefixes;
in in
{ {
imports = [ ./containers ]; imports = [ ./containers ];
@@ -121,7 +121,8 @@ in
samba = { samba = {
enable = true; enable = true;
settings = { enableNmbd = true;
shares = {
storage = { storage = {
path = "/mnt/storage"; path = "/mnt/storage";
browseable = "yes"; browseable = "yes";
@@ -130,20 +131,16 @@ in
"directory mask" = "0775"; "directory mask" = "0775";
}; };
}; };
nmbd.enable = true;
}; };
samba-wsdd.enable = true; samba-wsdd.enable = true;
minecraft-server = { minecraft-server = {
enable = false; enable = true;
package = pkgs.minecraftServers.vanilla-1-20; package = pkgs.minecraftServers.vanilla-1-19;
declarative = true; declarative = true;
eula = true; eula = true;
whitelist = { whitelist = {
devplayer0 = "6d7d971b-ce10-435b-85c5-c99c0d8d288c"; devplayer0 = "6d7d971b-ce10-435b-85c5-c99c0d8d288c";
Elderlypug = "dcd2ecb9-2b5e-49cb-9d4f-f5a76162df56";
shr3kas0ras = "1d366062-12c0-4e29-aba7-6ab5d8c6bb05";
}; };
serverProperties = { serverProperties = {
motd = "Simpcraft"; motd = "Simpcraft";
@@ -181,10 +178,12 @@ 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;
};
} }
]; ];
}; };
@@ -199,7 +198,6 @@ 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 +210,7 @@ in
address = with assignments.estuary; [ address = with assignments.estuary; [
(with ipv4; "${address}/${toString mask}") (with ipv4; "${address}/${toString mask}")
]; ];
routingPolicyRules = [ routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
{ {
Family = "both"; Family = "both";
SuppressPrefixLength = 0; SuppressPrefixLength = 0;
@@ -272,7 +270,7 @@ in
config.name = "kontent"; config.name = "kontent";
}; };
# deploy.node.hostname = "192.168.0.69"; #deploy.node.hostname = "10.16.9.21";
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;
}; };
graphics.extraPackages = with pkgs; [ opengl.extraPackages = with pkgs; [
intel-media-driver intel-media-driver
]; ];
bluetooth.enable = true; bluetooth.enable = true;
@@ -116,10 +116,6 @@
programs = { programs = {
steam.enable = true; steam.enable = true;
wireshark = {
enable = true;
package = pkgs.wireshark-qt;
};
}; };
networking = { networking = {
@@ -129,9 +125,10 @@
wifi = { wifi = {
backend = "wpa_supplicant"; backend = "wpa_supplicant";
}; };
settings = { extraConfig = ''
main.no-auto-default = "*"; [main]
}; no-auto-default=*
'';
}; };
}; };
@@ -174,14 +171,6 @@
packages = with pkgs; [ ]; packages = with pkgs; [ ];
}; };
programs = {
fish = {
shellAbbrs = {
tsup = "doas tailscale up --login-server=https://hs.nul.ie --accept-routes";
};
};
};
services = { services = {
blueman-applet.enable = true; blueman-applet.enable = true;
}; };

View File

@@ -1,4 +1,4 @@
{ self, lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }: { lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
let let
inherit (builtins) attrValues mapAttrs; inherit (builtins) attrValues mapAttrs;
inherit (lib) inherit (lib)
@@ -23,19 +23,15 @@ let
pkgs = pkgs'.${config'.nixpkgs}.${config'.system}; pkgs = pkgs'.${config'.nixpkgs}.${config'.system};
allPkgs = mapAttrs (_: p: p.${config'.system}) pkgs'; allPkgs = mapAttrs (_: p: p.${config'.system}) pkgs';
modules' = [ hmFlakes.${config'.home-manager}.nixosModules.default ] ++ (attrValues cfg.modules); modules' = [ hmFlakes.${config'.home-manager}.nixosModule ] ++ (attrValues cfg.modules);
in in
# Import eval-config ourselves since the flake now force-sets lib pkgsFlake.lib.nixosSystem {
import "${pkgsFlake}/nixos/lib/eval-config.nix" {
# Gotta override lib here unforunately, eval-config.nix likes to import its own (unextended) lib. We explicitly # Gotta override lib here unforunately, eval-config.nix likes to import its own (unextended) lib. We explicitly
# don't pass pkgs so that it'll be imported with modularly applied config and overlays. # don't pass pkgs so that it'll be imported with modularly applied config and overlays.
lib = pkgs.lib.extend (lib.my.versionOverlay { inherit self pkgsFlake; }); lib = pkgs.lib;
# Set to null since we pass modularly
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 self inputs pkgsFlakes pkgsFlake allAssignments; inherit (cfg) systems; }; specialArgs = { inherit 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 =
@@ -55,7 +51,7 @@ let
pkgs' = allPkgs; pkgs' = allPkgs;
}; };
system = { inherit name; }; system.name = name;
networking = { networking = {
domain = let d = config'.assignments.internal.domain or null; in mkIf (d != null) (mkDefault' d); domain = let d = config'.assignments.internal.domain or null; in mkIf (d != null) (mkDefault' d);
hostName = mkDefault (config'.assignments.internal.name or name); hostName = mkDefault (config'.assignments.internal.name or name);
@@ -90,8 +86,6 @@ let
pkgsPath = toString pkgsFlakes.${config'.hmNixpkgs}; pkgsPath = toString pkgsFlakes.${config'.hmNixpkgs};
pkgs' = allPkgs; pkgs' = allPkgs;
}; };
home.enableNixpkgsReleaseCheck = false;
} }
(homeStateVersion config'.home-manager) (homeStateVersion config'.home-manager)
]; ];
@@ -135,7 +129,6 @@ let
ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6."; ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6.";
baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with."; baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with.";
l3Overhead = mkOpt' ints.unsigned 40 "Overhead of L3 header (to calculate MTU)."; l3Overhead = mkOpt' ints.unsigned 40 "Overhead of L3 header (to calculate MTU).";
udpEncapsulation = mkBoolOpt' false "Whether to encapsulate ESP frames in UDP.";
firewall = mkBoolOpt' true "Whether to generate firewall rules."; firewall = mkBoolOpt' true "Whether to generate firewall rules.";
vni = mkOpt' ints.unsigned 1 "VXLAN VNI."; vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers."; peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";

View File

@@ -1,7 +1,7 @@
{ {
nixos.systems.installer = { config, ... }: { nixos.systems.installer = { config, ... }: {
system = "x86_64-linux"; system = "x86_64-linux";
nixpkgs = "mine"; nixpkgs = "unstable";
docCustom = false; docCustom = false;
rendered = config.configuration.config.my.asISO; rendered = config.configuration.config.my.asISO;
@@ -31,11 +31,8 @@
server.enable = true; server.enable = true;
}; };
image = {
baseName = "jackos-installer";
};
isoImage = { isoImage = {
volumeID = "jackos-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}"; isoBaseName = "nixos-installer-devplayer0";
edition = "devplayer0"; edition = "devplayer0";
appendToMenuLabel = " /dev/player0 Installer"; appendToMenuLabel = " /dev/player0 Installer";
}; };
@@ -54,8 +51,6 @@
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 = {
@@ -63,8 +58,8 @@
}; };
networking = { networking = {
# Will be set dynamically, but need something to satisfy `/etc/os-release` stuff # Will be set dynamically
hostName = "installer"; hostName = "";
useNetworkd = false; useNetworkd = false;
}; };
@@ -84,8 +79,6 @@
${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

@@ -14,12 +14,10 @@
network = ./network.nix; network = ./network.nix;
pdns = ./pdns.nix; pdns = ./pdns.nix;
nginx-sso = ./nginx-sso.nix; nginx-sso = ./nginx-sso.nix;
gui = ./gui; gui = ./gui.nix;
l2mesh = ./l2mesh.nix; l2mesh = ./l2mesh.nix;
borgthin = ./borgthin.nix; borgthin = ./borgthin.nix;
nvme = ./nvme; nvme = ./nvme;
spdk = ./spdk.nix; spdk = ./spdk.nix;
librespeed = ./librespeed;
netboot = ./netboot;
}; };
} }

View File

@@ -1,4 +1,4 @@
{ inputs, lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
inherit (builtins) substring match; inherit (builtins) substring match;
inherit (lib) inherit (lib)
@@ -127,9 +127,7 @@ in
enable = mkBoolOpt' false "Whether to enable borgthin jobs"; enable = mkBoolOpt' false "Whether to enable borgthin jobs";
lvmPackage = mkOpt' package pkgs.lvm2 "Packge containing LVM tools"; lvmPackage = mkOpt' package pkgs.lvm2 "Packge containing LVM tools";
thinToolsPackage = mkOpt' package pkgs.thin-provisioning-tools "Package containing thin-provisioning-tools"; thinToolsPackage = mkOpt' package pkgs.thin-provisioning-tools "Package containing thin-provisioning-tools";
# Really we should use the version from the overlay, but the package is quite far behind... package = mkOpt' package pkgs.borgthin "borgthin package";
# Not bothering to update until Borg 2.0 releases
package = mkOpt' package inputs.borgthin.packages.${config.nixpkgs.system}.borgthin "borgthin package";
jobs = mkOpt' (attrsOf jobType) { } "borgthin jobs"; jobs = mkOpt' (attrsOf jobType) { } "borgthin jobs";
}; };

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 mkForce flatten optional; inherit (lib) recursiveUpdate mkOption mkDefault mkIf mkMerge flatten optional;
inherit (lib.my) mkBoolOpt' dummyOption; inherit (lib.my) mkBoolOpt' dummyOption;
cfg = config.my.build; cfg = config.my.build;
@@ -43,145 +43,15 @@ 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, ... }: {
boot = { system.build.netbootArchive = pkgs.runCommand "netboot-${config.system.name}-archive.tar" { } ''
loader.grub.enable = false; ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.kernel}" \
initrd = { -f "$out" "${config.system.boot.loader.kernelFile}"
kernelModules = [ "nbd" ]; ${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootRamdisk}" \
availableKernelModules = [ "igb" "igc" ]; -f "$out" initrd
${pkgs.gnutar}/bin/tar -rvC "${config.system.build.netbootIpxeScript}" \
systemd = { -f "$out" netboot.ipxe
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" .
'';
};
}) })
]; ];
}; };
@@ -207,7 +77,6 @@ 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;
}; };
@@ -221,9 +90,8 @@ in
memorySize = dummyOption; memorySize = dummyOption;
qemu.options = dummyOption; qemu.options = dummyOption;
}; };
image.baseName = dummyOption;
isoImage = { isoImage = {
volumeID = dummyOption; isoBaseName = dummyOption;
edition = dummyOption; edition = dummyOption;
appendToMenuLabel = dummyOption; appendToMenuLabel = dummyOption;
}; };
@@ -241,8 +109,7 @@ 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;
netbootTree = config.my.asNetboot.config.system.build.netbootTree; netbootArchive = config.my.asKexecTree.config.system.build.netbootArchive;
netbootArchive = config.my.asNetboot.config.system.build.netbootArchive;
}; };
}; };
}; };

View File

@@ -1,7 +1,7 @@
{ lib, pkgsFlake, pkgs, pkgs', self, inputs, config, ... }: { lib, pkgs, pkgs', inputs, config, ... }:
let let
inherit (lib) mkIf mkDefault mkMerge; inherit (lib) mkIf mkDefault mkMerge;
inherit (lib.my) mkDefault'; inherit (lib.my) mkBoolOpt' dummyOption;
in in
{ {
options = with lib.types; { options = with lib.types; {
@@ -12,7 +12,7 @@ in
inputs.impermanence.nixosModule inputs.impermanence.nixosModule
inputs.ragenix.nixosModules.age inputs.ragenix.nixosModules.age
inputs.sharry.nixosModules.default inputs.sharry.nixosModules.default
inputs.copyparty.nixosModules.default inputs.attic.nixosModules.atticd
]; ];
config = mkMerge [ config = mkMerge [
@@ -41,7 +41,6 @@ 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" ];
@@ -54,7 +53,7 @@ in
pkgs = { pkgs = {
to = { to = {
type = "path"; type = "path";
path = "${pkgsFlake}"; path = "${pkgs.path}";
}; };
exact = true; exact = true;
}; };
@@ -66,12 +65,10 @@ in
}; };
nixpkgs = { nixpkgs = {
overlays = [ overlays = [
inputs.deploy-rs.overlays.default inputs.deploy-rs.overlay
inputs.sharry.overlays.default inputs.sharry.overlays.default
# TODO: Re-enable when borgthin is updated inputs.borgthin.overlays.default
# inputs.borgthin.overlays.default
inputs.boardie.overlays.default inputs.boardie.overlays.default
inputs.copyparty.overlays.default
]; ];
config = { config = {
allowUnfree = true; allowUnfree = true;
@@ -124,15 +121,7 @@ in
services.lvm.enable = mkDefault true; services.lvm.enable = mkDefault true;
}; };
}; };
system = {
nixos = {
distroName = mkDefault' "JackOS";
};
};
environment.etc = {
"nixos/flake.nix".source = "/run/nixfiles/flake.nix";
};
environment.systemPackages = with pkgs; mkMerge [ environment.systemPackages = with pkgs; mkMerge [
[ [
bash-completion bash-completion
@@ -148,10 +137,7 @@ 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 = { vim.defaultEditor = true;
enable = true;
defaultEditor = true;
};
}; };
services = { services = {
@@ -165,7 +151,6 @@ in
font-name=SauceCodePro Nerd Font Mono font-name=SauceCodePro Nerd Font Mono
''; '';
}; };
getty.greetingLine = mkDefault' ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>'';
openssh = { openssh = {
enable = mkDefault true; enable = mkDefault true;
@@ -218,35 +203,14 @@ 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; [
nerd-fonts.sauce-code-pro (nerdfonts.override {
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 any; inherit (builtins) attrNames attrValues all hashString toJSON;
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';
@@ -15,7 +15,6 @@ let
passAsFile = [ "code" ]; passAsFile = [ "code" ];
code = '' code = ''
#include <stdio.h> #include <stdio.h>
#include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <unistd.h> #include <unistd.h>
#include <systemd/sd-daemon.h> #include <systemd/sd-daemon.h>
@@ -99,7 +98,6 @@ 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.";
}; };
}; };
}; };
@@ -117,19 +115,26 @@ 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 && c.networking.macVLAN == null) cfg.instances); (filterAttrs (_: c: c.networking.bridge == null) cfg.instances);
systemd = mkMerge (mapAttrsToList (n: c: { systemd = mkMerge ([
{
# By symlinking to the original systemd-nspawn@.service for every instance we force the unit generator to
# create overrides instead of replacing the unit entirely
packages = [
(pkgs.linkFarm "systemd-nspawn-containers" (map (n: {
name = "etc/systemd/system/systemd-nspawn@${n}.service";
path = "${pkgs.systemd}/example/systemd/system/systemd-nspawn@.service";
}) (attrNames cfg.instances)))
];
}
] ++ (mapAttrsToList (n: c: {
nspawn."${n}" = { nspawn."${n}" = {
execConfig = { execConfig = {
Boot = true; Boot = true;
@@ -160,8 +165,6 @@ 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;
}; };
@@ -179,9 +182,6 @@ 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 +247,7 @@ in
Bridge = c.networking.bridge; Bridge = c.networking.bridge;
}; };
}; };
}) cfg.instances); }) cfg.instances));
}) })
# Inside container # Inside container

View File

@@ -15,20 +15,16 @@ let
# Based on https://github.com/serokell/deploy-rs/blob/master/flake.nix # Based on https://github.com/serokell/deploy-rs/blob/master/flake.nix
nixosActivate = cfg': base: (pkgs.deploy-rs.lib.activate.custom // { nixosActivate = cfg': base: (pkgs.deploy-rs.lib.activate.custom // {
dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate"; dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate";
boot = '' boot = "$PROFILE/bin/switch-to-configuration boot";
$PROFILE/bin/switch-to-configuration boot
${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
'';
}) base.config.system.build.toplevel '' }) base.config.system.build.toplevel ''
# work around https://github.com/NixOS/nixpkgs/issues/73404 # work around https://github.com/NixOS/nixpkgs/issues/73404
cd /tmp cd /tmp
"$PROFILE"/bin/switch-to-configuration switch "$PROFILE"/bin/switch-to-configuration ${cfg'.mode}
# https://github.com/serokell/deploy-rs/issues/31 # https://github.com/serokell/deploy-rs/issues/31
${with base.config.boot.loader; ${with base.config.boot.loader;
optionalString systemd-boot.enable optionalString ((cfg'.mode == "switch" || cfg'.mode == "boot") && systemd-boot.enable)
"sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"} "sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"}
${keepGensSnippet "$PROFILE" cfg'.keepGenerations} ${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
@@ -63,11 +59,7 @@ let
{ {
name = "container-${n}"; name = "container-${n}";
value = { value = {
path = (pkgs.deploy-rs.lib.activate.custom // { path = pkgs.deploy-rs.lib.activate.custom ctrConfig.my.buildAs.container ''
boot = ''
echo "Next systemd-nspawn@${n}.service restart / reload will load config"
'';
}) ctrConfig.my.buildAs.container ''
source ${systemdUtil}/bin/systemd-util.sh source ${systemdUtil}/bin/systemd-util.sh
${if c.hotReload then '' ${if c.hotReload then ''
if (! systemctl show -p ActiveState systemd-nspawn@${n} | grep -q "ActiveState=active") || \ if (! systemctl show -p ActiveState systemd-nspawn@${n} | grep -q "ActiveState=active") || \

View File

@@ -222,7 +222,7 @@ in
"iifname ${cfg.nat.externalInterface} jump filter-iif-port-forwards"} "iifname ${cfg.nat.externalInterface} jump filter-iif-port-forwards"}
${optionalString ${optionalString
dipForward dipForward
(concatMapStringsSep "\n " (ip: "jump ${natFilterChain ip}") (attrNames cfg.nat.forwardPorts))} (concatMapStringsSep "\n " (ip: "${ipK ip} daddr ${ip} jump ${natFilterChain ip}") (attrNames cfg.nat.forwardPorts))}
} }
} }

View File

@@ -4,12 +4,6 @@ let
inherit (lib.my) mkBoolOpt'; inherit (lib.my) mkBoolOpt';
cfg = config.my.gui; cfg = config.my.gui;
androidUdevRules = pkgs.runCommand "udev-rules-android" {
rulesFile = ./android-udev.rules;
} ''
install -D "$rulesFile" "$out"/lib/udev/rules.d/51-android.rules
'';
in in
{ {
options.my.gui = with lib.types; { options.my.gui = with lib.types; {
@@ -18,7 +12,7 @@ in
config = mkIf cfg.enable { config = mkIf cfg.enable {
hardware = { hardware = {
graphics.enable = mkDefault true; opengl.enable = mkDefault true;
}; };
systemd = { systemd = {
@@ -29,19 +23,13 @@ in
security = { security = {
polkit.enable = true; polkit.enable = true;
pam.services.swaylock-plugin = {}; pam.services.swaylock = {};
};
users = {
groups = {
adbusers.gid = lib.my.c.ids.gids.adbusers;
};
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
# for pw-jack # for pw-jack
pipewire.jack pipewire.jack
swaylock-plugin swaylock
]; ];
services = { services = {
pipewire = { pipewire = {
@@ -56,21 +44,13 @@ in
gnome = { gnome = {
gnome-keyring.enable = true; gnome-keyring.enable = true;
}; };
udisks2.enable = true;
udev = { udev = {
packages = [
androidUdevRules
];
extraRules = '' extraRules = ''
# Nvidia # Nvidia
SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel" SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
# Nintendo # Nintendo
SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel" SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
# FT
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel"
# /dev/player0
SUBSYSTEM=="usb", ATTR{idVendor}=="6969", MODE="0664", GROUP="wheel"
''; '';
}; };
}; };
@@ -104,13 +84,5 @@ in
]; ];
}; };
}; };
my = {
user = {
config = {
extraGroups = [ "adbusers" ];
};
};
};
}; };
} }

File diff suppressed because it is too large Load Diff

View File

@@ -36,16 +36,18 @@ let
espOverhead = espOverhead =
if (!mesh.security.enable) then 0 if (!mesh.security.enable) then 0
else else
# UDP encap + SPI + seq + IV + pad / header + ICV # SPI + seq + IV + pad / header + ICV
(if mesh.udpEncapsulation then 8 else 0) + 4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16; 4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16;
# UDP + VXLAN + Ethernet + L3 (IPv4/IPv6) # UDP + VXLAN + Ethernet + L3 (IPv4/IPv6)
overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead; overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead;
in in
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;
}; };
}; };
@@ -60,12 +62,8 @@ let
chain l2mesh-${name} { chain l2mesh-${name} {
${optionalString mesh.security.enable '' ${optionalString mesh.security.enable ''
udp dport isakmp accept udp dport isakmp accept
${if mesh.udpEncapsulation then ''
udp dport ipsec-nat-t accept
'' else ''
meta l4proto esp accept meta l4proto esp accept
''} ''}
''}
${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)} ${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)}
return return
} }
@@ -96,7 +94,6 @@ let
esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"} esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"}
ikev2=yes ikev2=yes
modecfgpull=no modecfgpull=no
encapsulation=${if mesh.udpEncapsulation then "yes" else "no"}
''; '';
}) })
otherPeers); otherPeers);

View File

@@ -1,76 +0,0 @@
{ lib, pkgs, config, ... }:
let
inherit (builtins) toJSON;
inherit (lib) mkOption mkMerge mkIf mkDefault;
inherit (lib.my) mkOpt' mkBoolOpt';
cfg = config.my.librespeed;
serversConf = map (s: s // {
dlURL = "backend/garbage";
ulURL = "backend/empty";
pingURL = "backend/empty";
getIpURL = "backend/getIP";
}) cfg.frontend.servers;
frontendTree = pkgs.runCommand "librespeed-frontend" {
speedtestServers = toJSON serversConf;
} ''
mkdir "$out"
cp "${pkgs.librespeed-go}"/assets/* "$out"/
substitute ${./index.html} "$out"/index.html --subst-var speedtestServers
'';
backendConf = pkgs.writers.writeTOML "librespeed.toml" cfg.backend.settings;
generateBackendSettings = base: dst: if (cfg.backend.extraSettingsFile != null) then ''
oldUmask="$(umask)"
umask 006
cat "${base}" "${cfg.backend.extraSettingsFile}" > "${dst}"
umask "$oldUmask"
'' else ''
cp "${base}" "${dst}"
'';
in
{
options.my.librespeed = with lib.types; {
frontend = {
servers = mkOpt' (listOf (attrsOf unspecified)) { } "Server configs.";
webroot = mkOption {
description = "Frontend webroot.";
type = package;
readOnly = true;
};
};
backend = {
enable = mkBoolOpt' false "Whether to enable librespeed backend.";
settings = mkOpt' (attrsOf unspecified) { } "Backend settings.";
extraSettingsFile = mkOpt' (nullOr str) null "Extra settings file.";
};
};
config = mkMerge [
(mkIf (cfg.frontend.servers != { }) {
my.librespeed.frontend.webroot = frontendTree;
})
(mkIf cfg.backend.enable {
my.librespeed.backend.settings = {
assets_path = frontendTree;
database_type = mkDefault "bolt";
database_file = mkDefault "/var/lib/librespeed-go/speedtest.db";
};
systemd.services.librespeed = {
description = "LibreSpeed Go backend";
wants = [ "network-online.target" ];
after = [ "network-online.target" ];
preStart = generateBackendSettings backendConf "/run/librespeed-go/settings.toml";
serviceConfig = {
ExecStart = "${pkgs.librespeed-go}/bin/speedtest -c /run/librespeed-go/settings.toml";
RuntimeDirectory = "librespeed-go";
StateDirectory = "librespeed-go";
};
wantedBy = [ "multi-user.target" ];
};
})
];
}

View File

@@ -1,491 +0,0 @@
<!DOCTYPE html>
<html>
<head>
<link rel="shortcut icon" href="favicon.ico">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no, user-scalable=no" />
<meta charset="UTF-8" />
<script type="text/javascript" src="speedtest.js"></script>
<script type="text/javascript">
function I(i){return document.getElementById(i);}
//LIST OF TEST SERVERS. See documentation for details if needed
var SPEEDTEST_SERVERS=@speedtestServers@;
// var SPEEDTEST_SERVERS=[
// { //this server doesn't actually exist, remove it
// name:"Example Server 1", //user friendly name for the server
// server:"//test1.mydomain.com/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
// dlURL:"backend/garbage.php", //path to download test on this server (garbage.php or replacement)
// ulURL:"backend/empty.php", //path to upload test on this server (empty.php or replacement)
// pingURL:"backend/empty.php", //path to ping/jitter test on this server (empty.php or replacement)
// getIpURL:"backend/getIP.php" //path to getIP on this server (getIP.php or replacement)
// },
// { //this server doesn't actually exist, remove it
// name:"Example Server 2", //user friendly name for the server
// server:"//test2.example.com/", //URL to the server. // at the beginning will be replaced with http:// or https:// automatically
// dlURL:"garbage.php", //path to download test on this server (garbage.php or replacement)
// ulURL:"empty.php", //path to upload test on this server (empty.php or replacement)
// pingURL:"empty.php", //path to ping/jitter test on this server (empty.php or replacement)
// getIpURL:"getIP.php" //path to getIP on this server (getIP.php or replacement)
// }
// //add other servers here, comma separated
// ];
//INITIALIZE SPEEDTEST
var s=new Speedtest(); //create speed test object
s.setParameter("telemetry_level","basic"); //enable telemetry
//SERVER AUTO SELECTION
function initServers(){
var noServersAvailable=function(){
I("message").innerHTML="No servers available";
}
var runServerSelect=function(){
s.selectServer(function(server){
if(server!=null){ //at least 1 server is available
I("loading").className="hidden"; //hide loading message
//populate server list for manual selection
for(var i=0;i<SPEEDTEST_SERVERS.length;i++){
if(SPEEDTEST_SERVERS[i].pingT==-1) continue;
var option=document.createElement("option");
option.value=i;
option.textContent=SPEEDTEST_SERVERS[i].name;
if(SPEEDTEST_SERVERS[i]===server) option.selected=true;
I("server").appendChild(option);
}
//show test UI
I("testWrapper").className="visible";
initUI();
}else{ //no servers are available, the test cannot proceed
noServersAvailable();
}
});
}
if(typeof SPEEDTEST_SERVERS === "string"){
//need to fetch list of servers from specified URL
s.loadServerList(SPEEDTEST_SERVERS,function(servers){
if(servers==null){ //failed to load server list
noServersAvailable();
}else{ //server list loaded
SPEEDTEST_SERVERS=servers;
runServerSelect();
}
});
}else{
//hardcoded server list
s.addTestPoints(SPEEDTEST_SERVERS);
runServerSelect();
}
}
var meterBk=/Trident.*rv:(\d+\.\d+)/i.test(navigator.userAgent)?"#EAEAEA":"#80808040";
var dlColor="#6060AA",
ulColor="#616161";
var progColor=meterBk;
//CODE FOR GAUGES
function drawMeter(c,amount,bk,fg,progress,prog){
var ctx=c.getContext("2d");
var dp=window.devicePixelRatio||1;
var cw=c.clientWidth*dp, ch=c.clientHeight*dp;
var sizScale=ch*0.0055;
if(c.width==cw&&c.height==ch){
ctx.clearRect(0,0,cw,ch);
}else{
c.width=cw;
c.height=ch;
}
ctx.beginPath();
ctx.strokeStyle=bk;
ctx.lineWidth=12*sizScale;
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,Math.PI*0.1);
ctx.stroke();
ctx.beginPath();
ctx.strokeStyle=fg;
ctx.lineWidth=12*sizScale;
ctx.arc(c.width/2,c.height-58*sizScale,c.height/1.8-ctx.lineWidth,-Math.PI*1.1,amount*Math.PI*1.2-Math.PI*1.1);
ctx.stroke();
if(typeof progress !== "undefined"){
ctx.fillStyle=prog;
ctx.fillRect(c.width*0.3,c.height-16*sizScale,c.width*0.4*progress,4*sizScale);
}
}
function mbpsToAmount(s){
return 1-(1/(Math.pow(1.3,Math.sqrt(s))));
}
function format(d){
d=Number(d);
if(d<10) return d.toFixed(2);
if(d<100) return d.toFixed(1);
return d.toFixed(0);
}
//UI CODE
var uiData=null;
function startStop(){
if(s.getState()==3){
//speed test is running, abort
s.abort();
data=null;
I("startStopBtn").className="";
I("server").disabled=false;
initUI();
}else{
//test is not running, begin
I("startStopBtn").className="running";
I("shareArea").style.display="none";
I("server").disabled=true;
s.onupdate=function(data){
uiData=data;
};
s.onend=function(aborted){
I("startStopBtn").className="";
I("server").disabled=false;
updateUI(true);
if(!aborted){
//if testId is present, show sharing panel, otherwise do nothing
try{
var testId=uiData.testId;
if(testId!=null){
var shareURL=window.location.href.substring(0,window.location.href.lastIndexOf("/"))+"/results/?id="+testId;
I("resultsImg").src=shareURL;
I("resultsURL").value=shareURL;
I("testId").innerHTML=testId;
I("shareArea").style.display="";
}
}catch(e){}
}
};
s.start();
}
}
//this function reads the data sent back by the test and updates the UI
function updateUI(forced){
if(!forced&&s.getState()!=3) return;
if(uiData==null) return;
var status=uiData.testState;
I("ip").textContent=uiData.clientIp;
I("dlText").textContent=(status==1&&uiData.dlStatus==0)?"...":format(uiData.dlStatus);
drawMeter(I("dlMeter"),mbpsToAmount(Number(uiData.dlStatus*(status==1?oscillate():1))),meterBk,dlColor,Number(uiData.dlProgress),progColor);
I("ulText").textContent=(status==3&&uiData.ulStatus==0)?"...":format(uiData.ulStatus);
drawMeter(I("ulMeter"),mbpsToAmount(Number(uiData.ulStatus*(status==3?oscillate():1))),meterBk,ulColor,Number(uiData.ulProgress),progColor);
I("pingText").textContent=format(uiData.pingStatus);
I("jitText").textContent=format(uiData.jitterStatus);
}
function oscillate(){
return 1+0.02*Math.sin(Date.now()/100);
}
//update the UI every frame
window.requestAnimationFrame=window.requestAnimationFrame||window.webkitRequestAnimationFrame||window.mozRequestAnimationFrame||window.msRequestAnimationFrame||(function(callback,element){setTimeout(callback,1000/60);});
function frame(){
requestAnimationFrame(frame);
updateUI();
}
frame(); //start frame loop
//function to (re)initialize UI
function initUI(){
drawMeter(I("dlMeter"),0,meterBk,dlColor,0);
drawMeter(I("ulMeter"),0,meterBk,ulColor,0);
I("dlText").textContent="";
I("ulText").textContent="";
I("pingText").textContent="";
I("jitText").textContent="";
I("ip").textContent="";
}
</script>
<style type="text/css">
html,body{
border:none; padding:0; margin:0;
background:#FFFFFF;
color:#202020;
}
body{
text-align:center;
font-family:"Roboto",sans-serif;
}
h1{
color:#404040;
}
#loading{
background-color:#FFFFFF;
color:#404040;
text-align:center;
}
span.loadCircle{
display:inline-block;
width:2em;
height:2em;
vertical-align:middle;
background:url('data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAMAAAD04JH5AAAAP1BMVEUAAAB2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZ2dnZyFzwnAAAAFHRSTlMAEvRFvX406baecwbf0casimhSHyiwmqgAAADpSURBVHja7dbJbQMxAENRahnN5lkc//5rDRAkDeRgHszXgACJoKiIiIiIiIiIiIiIiIiIiIj4HHspsrpAVhdVVguzrA4OWc10WcEqpwKbnBo0OU1Q5NSpsoJFTgOecrrdEag85DRgktNqfoEdTjnd7hrEHMEJvmRUYJbTYk5Agy6nau6Abp5Cm7mDBtRdPi9gyKdU7w4p1fsLvyqs8hl4z9/w3n/Hmr9WoQ65lAU4d7lMYOz//QboRR5jBZibLMZdAR6O/Vfa1PlxNr3XdS3HzK/HVPRu/KnLs8iAOh993VpRRERERMT/fAN60wwWaVyWwAAAAABJRU5ErkJggg==');
background-size:2em 2em;
margin-right:0.5em;
animation: spin 0.6s linear infinite;
}
@keyframes spin{
0%{transform:rotate(0deg);}
100%{transform:rotate(359deg);}
}
#startStopBtn{
display:inline-block;
margin:0 auto;
color:#6060AA;
background-color:rgba(0,0,0,0);
border:0.15em solid #6060FF;
border-radius:0.3em;
transition:all 0.3s;
box-sizing:border-box;
width:8em; height:3em;
line-height:2.7em;
cursor:pointer;
box-shadow: 0 0 0 rgba(0,0,0,0.1), inset 0 0 0 rgba(0,0,0,0.1);
}
#startStopBtn:hover{
box-shadow: 0 0 2em rgba(0,0,0,0.1), inset 0 0 1em rgba(0,0,0,0.1);
}
#startStopBtn.running{
background-color:#FF3030;
border-color:#FF6060;
color:#FFFFFF;
}
#startStopBtn:before{
content:"Start";
}
#startStopBtn.running:before{
content:"Abort";
}
#serverArea{
margin-top:1em;
}
#server{
font-size:1em;
padding:0.2em;
}
#test{
margin-top:2em;
margin-bottom:12em;
}
div.testArea{
display:inline-block;
width:16em;
height:12.5em;
position:relative;
box-sizing:border-box;
}
div.testArea2{
display:inline-block;
width:14em;
height:7em;
position:relative;
box-sizing:border-box;
text-align:center;
}
div.testArea div.testName{
position:absolute;
top:0.1em; left:0;
width:100%;
font-size:1.4em;
z-index:9;
}
div.testArea2 div.testName{
display:block;
text-align:center;
font-size:1.4em;
}
div.testArea div.meterText{
position:absolute;
bottom:1.55em; left:0;
width:100%;
font-size:2.5em;
z-index:9;
}
div.testArea2 div.meterText{
display:inline-block;
font-size:2.5em;
}
div.meterText:empty:before{
content:"0.00";
}
div.testArea div.unit{
position:absolute;
bottom:2em; left:0;
width:100%;
z-index:9;
}
div.testArea2 div.unit{
display:inline-block;
}
div.testArea canvas{
position:absolute;
top:0; left:0; width:100%; height:100%;
z-index:1;
}
div.testGroup{
display:block;
margin: 0 auto;
}
#shareArea{
width:95%;
max-width:40em;
margin:0 auto;
margin-top:2em;
}
#shareArea > *{
display:block;
width:100%;
height:auto;
margin: 0.25em 0;
}
#privacyPolicy{
position:fixed;
top:2em;
bottom:2em;
left:2em;
right:2em;
overflow-y:auto;
width:auto;
height:auto;
box-shadow:0 0 3em 1em #000000;
z-index:999999;
text-align:left;
background-color:#FFFFFF;
padding:1em;
}
a.privacy{
text-align:center;
font-size:0.8em;
color:#808080;
padding: 0 3em;
}
div.closePrivacyPolicy {
width: 100%;
text-align: center;
}
div.closePrivacyPolicy a.privacy {
padding: 1em 3em;
}
@media all and (max-width:40em){
body{
font-size:0.8em;
}
}
div.visible{
animation: fadeIn 0.4s;
display:block;
}
div.hidden{
animation: fadeOut 0.4s;
display:none;
}
@keyframes fadeIn{
0%{
opacity:0;
}
100%{
opacity:1;
}
}
@keyframes fadeOut{
0%{
display:block;
opacity:1;
}
100%{
display:block;
opacity:0;
}
}
</style>
<title>/dev/player0's speedtest</title>
</head>
<body onload="initServers()">
<h1>/dev/player0's speedtest</h1>
<div id="loading" class="visible">
<p id="message"><span class="loadCircle"></span>Selecting a server...</p>
</div>
<div id="testWrapper" class="hidden">
<div id="startStopBtn" onclick="startStop()"></div><br/>
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display=''">Privacy</a>
<div id="serverArea">
Server: <select id="server" onchange="s.setSelectedServer(SPEEDTEST_SERVERS[this.value])"></select>
</div>
<div id="test">
<div class="testGroup">
<div class="testArea2">
<div class="testName">Ping</div>
<div id="pingText" class="meterText" style="color:#AA6060"></div>
<div class="unit">ms</div>
</div>
<div class="testArea2">
<div class="testName">Jitter</div>
<div id="jitText" class="meterText" style="color:#AA6060"></div>
<div class="unit">ms</div>
</div>
</div>
<div class="testGroup">
<div class="testArea">
<div class="testName">Download</div>
<canvas id="dlMeter" class="meter"></canvas>
<div id="dlText" class="meterText"></div>
<div class="unit">Mbit/s</div>
</div>
<div class="testArea">
<div class="testName">Upload</div>
<canvas id="ulMeter" class="meter"></canvas>
<div id="ulText" class="meterText"></div>
<div class="unit">Mbit/s</div>
</div>
</div>
<div id="ipArea">
<span id="ip"></span>
</div>
<div id="shareArea" style="display:none">
<h3>Share results</h3>
<p>Test ID: <span id="testId"></span></p>
<input type="text" value="" id="resultsURL" readonly="readonly" onclick="this.select();this.focus();this.select();document.execCommand('copy');alert('Link copied')"/>
<img src="" id="resultsImg" />
</div>
</div>
<a href="https://github.com/librespeed/speedtest">Source code</a>
</div>
<div id="privacyPolicy" style="display:none">
<h2>Privacy Policy</h2>
<p>This HTML5 speed test server is configured with telemetry enabled.</p>
<h4>What data we collect</h4>
<p>
At the end of the test, the following data is collected and stored:
<ul>
<li>Test ID</li>
<li>Time of testing</li>
<li>Test results (download and upload speed, ping and jitter)</li>
<li>IP address</li>
<li>ISP information</li>
<li>Approximate location (inferred from IP address, not GPS)</li>
<li>User agent and browser locale</li>
<li>Test log (contains no personal information)</li>
</ul>
</p>
<h4>How we use the data</h4>
<p>
Data collected through this service is used to:
<ul>
<li>Allow sharing of test results (sharable image for forums, etc.)</li>
<li>To improve the service offered to you (for instance, to detect problems on our side)</li>
</ul>
No personal information is disclosed to third parties.
</p>
<h4>Your consent</h4>
<p>
By starting the test, you consent to the terms of this privacy policy.
</p>
<h4>Data removal</h4>
<p>
If you want to have your information deleted, you need to provide either the ID of the test or your IP address. This is the only way to identify your data, without this information we won't be able to comply with your request.<br/><br/>
Contact this email address for all deletion requests: <a href="mailto:dev@nul.ie">dev@nul.ie</a>.
</p>
<br/><br/>
<div class="closePrivacyPolicy">
<a class="privacy" href="#" onclick="I('privacyPolicy').style.display='none'">Close</a>
</div>
<br/>
</div>
</body>
</html>

View File

@@ -1,238 +0,0 @@
{ lib, pkgs, config, ... }:
let
inherit (lib) mkMerge mkIf mkForce genAttrs concatMapStringsSep;
inherit (lib.my) mkOpt' mkBoolOpt';
cfg = config.my.netboot;
# Newer releases don't boot on desktop?
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=";
};
# This upstream patch (in newer versions) is needed for newer GCC
patches = (if (o ? patches) then o.patches else []) ++ [ ./fix-uninitialised-var.patch ];
});
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.replaceVarsWith {
src = ./netboot-loader-builder.py;
isExecutable = true;
replacements = {
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

@@ -1,48 +0,0 @@
From 7f75d320f6d8ac7ec5185b2145da87f698aec273 Mon Sep 17 00:00:00 2001
From: Michael Brown <mcb30@ipxe.org>
Date: Mon, 2 Sep 2024 12:24:57 +0100
Subject: [PATCH] [etherfabric] Fix use of uninitialised variable in
falcon_xaui_link_ok()
The link status check in falcon_xaui_link_ok() reads from the
FCN_XX_CORE_STAT_REG_MAC register only on production hardware (where
the FPGA version reads as zero), but modifies the value and writes
back to this register unconditionally. This triggers an uninitialised
variable warning on newer versions of gcc.
Fix by assuming that the register exists only on production hardware,
and so moving the "modify-write" portion of the "read-modify-write"
operation to also be covered by the same conditional check.
Signed-off-by: Michael Brown <mcb30@ipxe.org>
---
src/drivers/net/etherfabric.c | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/src/drivers/net/etherfabric.c b/src/drivers/net/etherfabric.c
index b40596beae7..be30b71f79f 100644
--- a/src/drivers/net/etherfabric.c
+++ b/src/drivers/net/etherfabric.c
@@ -2225,13 +2225,16 @@ falcon_xaui_link_ok ( struct efab_nic *efab )
sync = ( sync == FCN_XX_SYNC_STAT_DECODE_SYNCED );
link_ok = align_done && sync;
- }
- /* Clear link status ready for next read */
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET, FCN_XX_COMMA_DET_RESET );
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR, FCN_XX_CHARERR_RESET);
- EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR, FCN_XX_DISPERR_RESET);
- falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ /* Clear link status ready for next read */
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_COMMA_DET,
+ FCN_XX_COMMA_DET_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_CHARERR,
+ FCN_XX_CHARERR_RESET );
+ EFAB_SET_DWORD_FIELD ( reg, FCN_XX_DISPERR,
+ FCN_XX_DISPERR_RESET );
+ falcon_xmac_writel ( efab, &reg, FCN_XX_CORE_STAT_REG_MAC );
+ }
has_phyxs = ( efab->phy_op->mmds & ( 1 << MDIO_MMD_PHYXS ) );
if ( link_ok && has_phyxs ) {

View File

@@ -1,68 +0,0 @@
#!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

@@ -1,280 +0,0 @@
#! @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

@@ -1,6 +1,6 @@
{ lib, pkgs, config, ... }: { lib, pkgs, config, ... }:
let let
inherit (lib) flatten optional mkIf mkDefault mkMerge versionAtLeast; inherit (lib) flatten optional mkIf mkDefault mkMerge;
in in
{ {
config = mkMerge [ config = mkMerge [
@@ -12,6 +12,14 @@ in
useNetworkd = mkDefault true; useNetworkd = mkDefault true;
}; };
systemd = {
additionalUpstreamSystemUnits = [
# TODO: NixOS has its own version of this, but with `network` instead of `networkd`. Is this just a typo? It
# hasn't been updated in 2 years...
"systemd-networkd-wait-online@.service"
];
};
services.resolved = { services.resolved = {
domains = [ config.networking.domain ]; domains = [ config.networking.domain ];
# Explicitly unset fallback DNS (Nix module will not allow for a blank config) # Explicitly unset fallback DNS (Nix module will not allow for a blank config)

View File

@@ -4,6 +4,11 @@ let
inherit (lib.my) mkOpt'; inherit (lib.my) mkOpt';
cfg = config.my.nvme; cfg = config.my.nvme;
nvme-cli = pkgs.nvme-cli.override {
libnvme = pkgs.libnvme.overrideAttrs (o: {
patches = o.patches ++ [ ./libnvme-hostconf.patch ];
});
};
hostNQN = "nqn.2014-08.org.nvmexpress:uuid:${cfg.uuid}"; hostNQN = "nqn.2014-08.org.nvmexpress:uuid:${cfg.uuid}";
etc = prefix: { etc = prefix: {
@@ -23,27 +28,14 @@ in
config = mkIf (cfg.uuid != null) { config = mkIf (cfg.uuid != null) {
environment = { environment = {
systemPackages = [ systemPackages = [
pkgs.nvme-cli nvme-cli
]; ];
etc = etc ""; etc = etc "";
}; };
boot = mkIf (cfg.boot.nqn != null) { boot.initrd.systemd = mkIf (cfg.boot.nqn != null) {
initrd = {
availableKernelModules = [ "rdma_cm" "iw_cm" "ib_cm" "nvme_core" "nvme_rdma" ];
kernelModules = [ "nvme-fabrics" ];
systemd = {
contents = etc "/etc/"; contents = etc "/etc/";
extraBin = with pkgs; { extraBin.nvme = "${nvme-cli}/bin/nvme";
dmesg = "${util-linux}/bin/dmesg";
ip = "${iproute2}/bin/ip";
nvme = "${nvme-cli}/bin/nvme";
};
network = {
enable = true;
wait-online.enable = true;
};
services.connect-nvme = { services.connect-nvme = {
description = "Connect NVMe-oF"; description = "Connect NVMe-oF";
@@ -53,26 +45,13 @@ in
serviceConfig = { serviceConfig = {
Type = "oneshot"; Type = "oneshot";
ExecStart = "${pkgs.nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn} -q ${hostNQN}"; ExecStart = "${nvme-cli}/bin/nvme connect -t rdma -a ${cfg.boot.address} -n ${cfg.boot.nqn}";
Restart = "on-failure"; Restart = "on-failure";
RestartSec = 10; RestartSec = 10;
}; };
wantedBy = [ "initrd-root-device.target" ]; wantedBy = [ "initrd-root-device.target" ];
}; };
# TODO: Remove when 25.11 releases
} // (if (lib.versionAtLeast lib.my.upstreamRelease "25.11") then {
settings.Manager = {
DefaultTimeoutStartSec = 20;
DefaultDeviceTimeoutSec = 20;
};
} else {
extraConfig = ''
DefaultTimeoutStartSec=20
DefaultDeviceTimeoutSec=20
'';
});
};
}; };
}; };
} }

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