Compare commits
1 Commits
master
...
731cfce080
| Author | SHA1 | Date | |
|---|---|---|---|
| 731cfce080 |
2
.envrc
@@ -1,2 +1,2 @@
|
||||
watch_file devshell/{default,commands,install,vm-tasks}.nix
|
||||
nix_direnv_watch_file devshell/{default,commands,install,vm-tasks}.nix
|
||||
use flake
|
||||
|
||||
@@ -6,11 +6,13 @@ on:
|
||||
|
||||
jobs:
|
||||
check:
|
||||
name: Check, build and cache nixfiles
|
||||
name: Check, build and cache Nix flake
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: cachix/install-nix-action@v27
|
||||
- name: Install jq
|
||||
run: apt-get update -y && apt-get install -y jq
|
||||
- uses: cachix/install-nix-action@v23
|
||||
with:
|
||||
# Gitea will supply a token in GITHUB_TOKEN, which this action will
|
||||
# try to pass to Nix when downloading from GitHub
|
||||
@@ -18,30 +20,21 @@ jobs:
|
||||
extra_nix_config: |
|
||||
# Make sure we're using sandbox
|
||||
sandbox-fallback = false
|
||||
# Big C++ projects fill up memory...
|
||||
cores = 6
|
||||
|
||||
extra-substituters = https://nix-cache.nul.ie
|
||||
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
|
||||
|
||||
- name: Check flake
|
||||
run: nix flake check --no-build
|
||||
|
||||
- name: Build (and cache) the world
|
||||
id: build
|
||||
env:
|
||||
HARMONIA_SSH_KEY: ${{ secrets.HARMONIA_SSH_KEY }}
|
||||
extra-substituters = https://nix-cache.nul.ie/main
|
||||
extra-trusted-public-keys = main:a2CtSxCXCXKabLa6IYQWzy3rdYjOwg9Ccm4ayahFjDI=
|
||||
- name: Set up attic
|
||||
run: |
|
||||
nix eval --json --apply "builtins.attrNames" .#ci.x86_64-linux | jq -cr '.[]' | while read job; do
|
||||
echo "::group::Build $job"
|
||||
nix build --no-link .#ci.x86_64-linux."$job"
|
||||
echo "::endgroup::"
|
||||
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
|
||||
login --set-default colony https://nix-cache.nul.ie "${{ secrets.NIX_CACHE_TOKEN }}"
|
||||
|
||||
echo "::group::Cache $job"
|
||||
ci/push-to-cache.sh "$(nix eval --raw .#ci.x86_64-linux."$job")"
|
||||
echo "::endgroup::"
|
||||
done
|
||||
- name: Check and build flake
|
||||
id: build
|
||||
run: |
|
||||
# nix flake check
|
||||
|
||||
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)"
|
||||
path=$(nix build --no-link .#ci.x86_64-linux --json | jq -r .[0].outputs.out)
|
||||
echo "path=$path" >> "$GITHUB_OUTPUT"
|
||||
- name: Push to cache
|
||||
run: |
|
||||
nix run .#nixpkgs.mine.x86_64-linux.attic-client -- \
|
||||
push main ${{ steps.build.outputs.path }}
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
name: Installer
|
||||
|
||||
on:
|
||||
push:
|
||||
tags: [installer]
|
||||
|
||||
jobs:
|
||||
installer:
|
||||
name: Build installer
|
||||
runs-on: ubuntu-22.04
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up Go
|
||||
uses: https://github.com/actions/setup-go@v4
|
||||
with:
|
||||
go-version: '>=1.20.1'
|
||||
- uses: cachix/install-nix-action@v27
|
||||
with:
|
||||
github_access_token: ${{ secrets.GH_PULL_TOKEN }}
|
||||
extra_nix_config: |
|
||||
# Make sure we're using sandbox
|
||||
sandbox-fallback = false
|
||||
|
||||
extra-substituters = https://nix-cache.nul.ie
|
||||
extra-trusted-public-keys = nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4=
|
||||
|
||||
- name: Set up vars
|
||||
id: setup
|
||||
run: |
|
||||
echo "short_rev=$(git rev-parse --short HEAD)" >> "$GITHUB_OUTPUT"
|
||||
- name: Build installer ISO
|
||||
run: |
|
||||
nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.iso
|
||||
ln -s "$(readlink result)"/iso/jackos-installer.iso \
|
||||
jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
|
||||
- name: Build installer netboot archive
|
||||
run: |
|
||||
nix build .#nixfiles.config.nixos.systems.installer.configuration.config.my.buildAs.netbootArchive
|
||||
ln -s "$(readlink result)" \
|
||||
jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst
|
||||
|
||||
- name: Create release
|
||||
uses: https://gitea.com/actions/release-action@main
|
||||
with:
|
||||
title: Latest installer
|
||||
api_key: '${{ secrets.RELEASE_TOKEN }}'
|
||||
files: |
|
||||
jackos-installer-${{ steps.setup.outputs.short_rev }}.iso
|
||||
jackos-installer-netboot-${{ steps.setup.outputs.short_rev }}.tar.zst
|
||||
1
.keys/ci.pub
Normal file
@@ -0,0 +1 @@
|
||||
age1ythn9runhsvwmszqfy69zetc422hug39ta4g236tue6f5qf65y0q4qg7xx
|
||||
@@ -1 +0,0 @@
|
||||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIKXRXkYnBf2opIjN+bXE7HmhUpa4hyXJUGmBT+MRccT4 harmonia
|
||||
@@ -1 +0,0 @@
|
||||
object-ctr.ams1.int.nul.ie ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdHbZErWLmTPO/aEWB1Fup/aGMf31Un5Wk66FJwTz/8
|
||||
@@ -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
|
||||
@@ -47,8 +47,8 @@ in
|
||||
(nodesFor homes)
|
||||
);
|
||||
|
||||
autoRollback = false;
|
||||
magicRollback = false;
|
||||
autoRollback = true;
|
||||
magicRollback = true;
|
||||
};
|
||||
|
||||
# Filter out null values so deploy merges overriding options correctly
|
||||
|
||||
@@ -20,7 +20,7 @@ in
|
||||
[ -e "${homeFlake}" ] && echo "${homeFlake} already exists" && exit 1
|
||||
|
||||
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}"
|
||||
'';
|
||||
}
|
||||
@@ -48,12 +48,6 @@ in
|
||||
help = "Print the ed25519 pubkey for a host";
|
||||
command = "${pkgs.openssh}/bin/ssh-keyscan -t ed25519 \"$1\" 2> /dev/null | awk '{ print $2 \" \" $3 }'";
|
||||
}
|
||||
{
|
||||
name = "json2nix";
|
||||
category = "utilities";
|
||||
help = "Convert JSON to formatted Nix";
|
||||
command = "nix eval --impure --expr 'builtins.fromJSON (builtins.readFile /dev/stdin)' | ${pkgs.nixfmt}/bin/nixfmt";
|
||||
}
|
||||
|
||||
{
|
||||
name = "fmt";
|
||||
@@ -77,12 +71,7 @@ in
|
||||
name = "build-n-switch";
|
||||
category = "tasks";
|
||||
help = "Shortcut to nixos-rebuild for this flake";
|
||||
command = ''
|
||||
# HACK: Upstream changes in Git + Nix makes this necessary
|
||||
# https://github.com/NixOS/nix/issues/10202
|
||||
doas git config --global --add safe.directory "$PWD"
|
||||
doas nixos-rebuild --flake . "$@"
|
||||
'';
|
||||
command = ''doas nixos-rebuild --flake . "$@"'';
|
||||
}
|
||||
{
|
||||
name = "run-vm";
|
||||
@@ -102,51 +91,35 @@ in
|
||||
help = "Build NixOS configuration into an ISO";
|
||||
command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.iso"'';
|
||||
}
|
||||
{
|
||||
name = "build-kexec";
|
||||
category = "tasks";
|
||||
help = "Build NixOS configuration as kexec tree";
|
||||
command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.kexecTree"'';
|
||||
}
|
||||
{
|
||||
name = "build-netboot";
|
||||
category = "tasks";
|
||||
help = "Build NixOS configuration as netboot tree";
|
||||
command = ''nix build "''${@:2}" ".#nixfiles.config.nixos.systems.\"$1\".configuration.config.my.buildAs.netbootTree"'';
|
||||
}
|
||||
{
|
||||
name = "build-home";
|
||||
category = "tasks";
|
||||
help = "Build home-manager configuration";
|
||||
command = ''nix build "''${@:2}" ".#homeConfigurations.\"$1\".activationPackage"'';
|
||||
}
|
||||
{
|
||||
name = "update-inputs";
|
||||
category = "tasks";
|
||||
help = "Update flake inputs";
|
||||
command = ''
|
||||
args=()
|
||||
for f in "$@"; do
|
||||
args+=(--update-input "$f")
|
||||
done
|
||||
nix flake lock "''${args[@]}"
|
||||
'';
|
||||
}
|
||||
{
|
||||
name = "update-nixpkgs";
|
||||
category = "tasks";
|
||||
help = "Update nixpkgs flake inputs";
|
||||
command = ''nix flake update nixpkgs-{unstable,stable,mine,mine-stable}'';
|
||||
command = ''update-inputs nixpkgs-{unstable,stable,mine,mine-stable}'';
|
||||
}
|
||||
{
|
||||
name = "update-home-manager";
|
||||
category = "tasks";
|
||||
help = "Update home-manager flake inputs";
|
||||
command = ''nix flake update home-manager-{unstable,stable}'';
|
||||
}
|
||||
{
|
||||
name = "update-installer";
|
||||
category = "tasks";
|
||||
help = "Update installer tag (to trigger new release)";
|
||||
command = ''git tag -f installer && git push -f origin installer'';
|
||||
}
|
||||
{
|
||||
name = "deploy-multi";
|
||||
category = "tasks";
|
||||
help = "Deploy multiple flakes at once";
|
||||
command = ''
|
||||
for f in $@; do
|
||||
deploy "$O" $f
|
||||
done
|
||||
'';
|
||||
command = ''update-inputs home-manager-{unstable,stable}'';
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib) concatStringsSep;
|
||||
inherit (lib.my) attrsToNVList;
|
||||
in
|
||||
{
|
||||
@@ -11,10 +12,10 @@ in
|
||||
|
||||
NIX_USER_CONF_FILES = toString (pkgs.writeText "nix.conf"
|
||||
''
|
||||
experimental-features = nix-command flakes ca-derivations
|
||||
connect-timeout = 5
|
||||
fallback = true
|
||||
${lib.my.c.nix.cache.conf}
|
||||
experimental-features = nix-command flakes ca-derivations repl-flake
|
||||
#substituters = https://nix-cache.nul.ie https://cache.nixos.org
|
||||
substituters = https://cache.nixos.org
|
||||
trusted-public-keys = ${concatStringsSep " " lib.my.c.nix.cacheKeys}
|
||||
'');
|
||||
|
||||
INSTALLER_SSH_OPTS = "-i .keys/deploy.key";
|
||||
@@ -24,10 +25,8 @@ in
|
||||
coreutils
|
||||
nixVersions.stable
|
||||
rage
|
||||
wireguard-tools
|
||||
(pkgs.writeShellScriptBin "deploy" ''
|
||||
exec ${deploy-rs.deploy-rs}/bin/deploy --skip-checks "$@"
|
||||
'')
|
||||
deploy-rs.deploy-rs
|
||||
home-manager
|
||||
attic-client
|
||||
];
|
||||
}
|
||||
|
||||
806
flake.lock
generated
92
flake.nix
@@ -3,50 +3,40 @@
|
||||
|
||||
inputs = {
|
||||
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.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
nixpkgs-unstable.url = "nixpkgs/nixos-unstable";
|
||||
nixpkgs-stable.url = "nixpkgs/nixos-25.11";
|
||||
nixpkgs-stable.url = "nixpkgs/nixos-23.05";
|
||||
nixpkgs-mine.url = "github:devplayer0/nixpkgs/devplayer0";
|
||||
nixpkgs-mine-stable.url = "github:devplayer0/nixpkgs/devplayer0-stable";
|
||||
|
||||
home-manager-unstable.url = "home-manager";
|
||||
home-manager-unstable.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
home-manager-stable.url = "home-manager/release-25.11";
|
||||
home-manager-stable.url = "home-manager/release-23.05";
|
||||
home-manager-stable.inputs.nixpkgs.follows = "nixpkgs-stable";
|
||||
|
||||
# Stuff used by the flake for build / deployment
|
||||
# ragenix.url = "github:yaxitech/ragenix";
|
||||
ragenix.url = "github:devplayer0/ragenix/add-rekey-one-flag";
|
||||
ragenix.url = "github:yaxitech/ragenix";
|
||||
ragenix.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
deploy-rs.url = "github:serokell/deploy-rs";
|
||||
deploy-rs.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
# Stuff used by systems
|
||||
impermanence.url = "github:nix-community/impermanence";
|
||||
impermanence.inputs.home-manager.follows = "home-manager-unstable";
|
||||
boardie.url = "github:devplayer0/boardie";
|
||||
boardie.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
nixGL.url = "github:nix-community/nixGL";
|
||||
nixGL.url = "github:guibou/nixGL";
|
||||
nixGL.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
harmonia.url = "github:nix-community/harmonia";
|
||||
# harmonia.url = "github:devplayer0/harmonia/cache-config-daemon-store";
|
||||
harmonia.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
|
||||
# Packages not in nixpkgs
|
||||
sharry.url = "github:eikek/sharry";
|
||||
sharry.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
borgthin.url = "github:devplayer0/borg";
|
||||
# TODO: Update borgthin so this works
|
||||
# borgthin.inputs.nixpkgs.follows = "nixpkgs-mine";
|
||||
copyparty.url = "github:9001/copyparty";
|
||||
copyparty.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
borgthin.inputs.nixpkgs.follows = "nixpkgs-mine";
|
||||
attic.url = "github:zhaofengli/attic";
|
||||
attic.inputs.nixpkgs.follows = "nixpkgs-unstable";
|
||||
attic.inputs.nixpkgs-stable.follows = "nixpkgs-stable";
|
||||
};
|
||||
|
||||
outputs =
|
||||
@@ -61,7 +51,7 @@
|
||||
...
|
||||
}:
|
||||
let
|
||||
inherit (builtins) mapAttrs replaceStrings elem;
|
||||
inherit (builtins) mapAttrs replaceStrings;
|
||||
inherit (lib) mapAttrs' filterAttrs nameValuePair recurseIntoAttrs evalModules;
|
||||
inherit (lib.flake) flattenTree eachDefaultSystem;
|
||||
inherit (lib.my) mkDefaultSystemsPkgs flakePackageOverlay;
|
||||
@@ -69,11 +59,11 @@
|
||||
# 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.
|
||||
libOverlay = final: prev: {
|
||||
my = import ./lib { inherit inputs; lib = final; };
|
||||
my = import ./lib { lib = final; };
|
||||
flake = flake-utils.lib;
|
||||
};
|
||||
pkgsLibOverlay = final: prev: { lib = prev.lib.extend libOverlay; };
|
||||
myPkgsOverlay = final: prev: import ./pkgs { lib = final.lib; pkgs = prev; };
|
||||
myPkgsOverlay = final: prev: import ./pkgs { lib = prev.lib; pkgs = prev; };
|
||||
|
||||
# Override the flake-level lib since we're going to use it for non-config specific stuff
|
||||
pkgsFlakes = mapAttrs (_: pkgsFlake: pkgsFlake // { lib = pkgsFlake.lib.extend libOverlay; }) {
|
||||
@@ -100,12 +90,12 @@
|
||||
(_: path: mkDefaultSystemsPkgs path (system: {
|
||||
overlays = [
|
||||
pkgsLibOverlay
|
||||
|
||||
myPkgsOverlay
|
||||
inputs.devshell.overlays.default
|
||||
inputs.ragenix.overlays.default
|
||||
inputs.deploy-rs.overlays.default
|
||||
inputs.deploy-rs.overlay
|
||||
(flakePackageOverlay inputs.home-manager-unstable system)
|
||||
inputs.attic.overlays.default
|
||||
];
|
||||
}))
|
||||
pkgsFlakes;
|
||||
@@ -115,19 +105,8 @@
|
||||
(_: path: mkDefaultSystemsPkgs path (_: {
|
||||
overlays = [
|
||||
pkgsLibOverlay
|
||||
|
||||
myPkgsOverlay
|
||||
];
|
||||
|
||||
config = {
|
||||
# RMS forgive me...
|
||||
# Normally this is set modularly, but sometimes we need to use other pkgs
|
||||
allowUnfreePredicate = p: elem (lib.getName p) [
|
||||
"widevine-cdm"
|
||||
"chromium-unwrapped"
|
||||
"chromium"
|
||||
];
|
||||
};
|
||||
}))
|
||||
pkgsFlakes;
|
||||
|
||||
@@ -136,22 +115,19 @@
|
||||
nixos/installer.nix
|
||||
nixos/boxes/colony
|
||||
nixos/boxes/tower
|
||||
nixos/boxes/home/stream.nix
|
||||
nixos/boxes/home/palace
|
||||
nixos/boxes/home/castle
|
||||
nixos/boxes/britway
|
||||
nixos/boxes/britnet.nix
|
||||
nixos/boxes/castle
|
||||
nixos/boxes/kelder
|
||||
|
||||
# Homes
|
||||
# home-manager/configs/macsimum.nix
|
||||
# home-manager/configs/castle.nix
|
||||
home-manager/configs/macsimum.nix
|
||||
];
|
||||
|
||||
nixfiles = evalModules {
|
||||
modules = [
|
||||
{
|
||||
_module.args = {
|
||||
inherit lib pkgsFlakes hmFlakes self inputs;
|
||||
inherit lib pkgsFlakes hmFlakes inputs;
|
||||
pkgs' = configPkgs';
|
||||
};
|
||||
|
||||
@@ -171,7 +147,7 @@
|
||||
# Platform independent stuff
|
||||
{
|
||||
nixpkgs = pkgs';
|
||||
inherit inputs lib nixfiles;
|
||||
inherit lib nixfiles;
|
||||
|
||||
overlays.default = myPkgsOverlay;
|
||||
|
||||
@@ -189,39 +165,35 @@
|
||||
lib = pkgs.lib;
|
||||
|
||||
filterSystem = filterAttrs (_: c: c.config.nixpkgs.system == system);
|
||||
homes =
|
||||
homes' =
|
||||
mapAttrs
|
||||
(_: h: h.activationPackage)
|
||||
(filterSystem self.homeConfigurations);
|
||||
systems =
|
||||
systems' =
|
||||
mapAttrs
|
||||
(_: h: h.config.system.build.toplevel)
|
||||
(filterSystem self.nixosConfigurations);
|
||||
shell = pkgs.devshell.mkShell ./devshell;
|
||||
in
|
||||
# Stuff for each platform
|
||||
rec {
|
||||
{
|
||||
checks = flattenTree {
|
||||
homeConfigurations = recurseIntoAttrs homes;
|
||||
homeConfigurations = recurseIntoAttrs homes';
|
||||
deploy = recurseIntoAttrs (pkgs.deploy-rs.lib.deployChecks self.deploy);
|
||||
};
|
||||
|
||||
ci =
|
||||
let
|
||||
homes =
|
||||
mapAttrs'
|
||||
(n: v: nameValuePair ''home-${replaceStrings ["@"] ["-at-"] n}'' v)
|
||||
homes';
|
||||
systems = mapAttrs' (n: v: nameValuePair "system-${n}" v) systems';
|
||||
in
|
||||
pkgs.linkFarm "ci" (homes // systems);
|
||||
|
||||
packages = flattenTree (import ./pkgs { inherit lib pkgs; });
|
||||
|
||||
devShells.default = shell;
|
||||
|
||||
ci =
|
||||
let
|
||||
homes' =
|
||||
mapAttrs'
|
||||
(n: v: nameValuePair ''home-${replaceStrings ["@"] ["-at-"] n}'' v)
|
||||
homes;
|
||||
systems' = mapAttrs' (n: v: nameValuePair "system-${n}" v) systems;
|
||||
packages' = mapAttrs' (n: v: nameValuePair "package-${n}" v) packages;
|
||||
in
|
||||
homes' // systems' // packages' // {
|
||||
inherit shell;
|
||||
};
|
||||
ciDrv = pkgs.linkFarm "ci" ci;
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -47,14 +47,9 @@ in
|
||||
|
||||
nix = {
|
||||
package = mkIf (!(versionAtLeast config.home.stateVersion "22.11")) pkgs.nix;
|
||||
settings = with lib.my.c.nix; {
|
||||
settings = {
|
||||
experimental-features = [ "nix-command" "flakes" "ca-derivations" ];
|
||||
max-jobs = mkDefault "auto";
|
||||
|
||||
extra-substituters = cache.substituters;
|
||||
extra-trusted-public-keys = cache.keys;
|
||||
connect-timeout = 5;
|
||||
fallback = true;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -66,7 +61,7 @@ in
|
||||
|
||||
lsd = {
|
||||
enable = mkDefault true;
|
||||
enableFishIntegration = mkDefault true;
|
||||
enableAliases = mkDefault true;
|
||||
};
|
||||
|
||||
starship = {
|
||||
@@ -80,7 +75,6 @@ in
|
||||
|
||||
tmux = {
|
||||
enable = true;
|
||||
keyMode = "vi";
|
||||
};
|
||||
|
||||
bash = {
|
||||
@@ -132,7 +126,6 @@ in
|
||||
|
||||
ssh = {
|
||||
enable = mkDefault true;
|
||||
enableDefaultConfig = false;
|
||||
matchBlocks = {
|
||||
nix-dev-vm = {
|
||||
user = "dev";
|
||||
@@ -158,14 +151,13 @@ in
|
||||
host = "cube spoon napalm gandalf saruman";
|
||||
user = "root";
|
||||
};
|
||||
|
||||
"*" = {
|
||||
identityFile = [
|
||||
"~/.ssh/id_rsa"
|
||||
"~/.ssh/borg"
|
||||
];
|
||||
};
|
||||
};
|
||||
extraConfig =
|
||||
''
|
||||
IdentityFile ~/.ssh/id_rsa
|
||||
IdentityFile ~/.ssh/netsoc
|
||||
IdentityFile ~/.ssh/borg
|
||||
'';
|
||||
};
|
||||
|
||||
direnv = {
|
||||
@@ -201,20 +193,17 @@ in
|
||||
file
|
||||
tree
|
||||
pwgen
|
||||
|
||||
minicom
|
||||
iperf3
|
||||
mosh
|
||||
wget
|
||||
hyx
|
||||
whois
|
||||
ldns
|
||||
minicom
|
||||
mtr
|
||||
|
||||
hyx
|
||||
ncdu
|
||||
jq
|
||||
yq-go
|
||||
nix-tree
|
||||
];
|
||||
|
||||
sessionVariables = {
|
||||
@@ -228,7 +217,7 @@ in
|
||||
# Note: If globalPkgs mode is on, then these will be overridden by the NixOS equivalents of these options
|
||||
nixpkgs = {
|
||||
overlays = [
|
||||
inputs.deploy-rs.overlays.default
|
||||
inputs.deploy-rs.overlay
|
||||
inputs.boardie.overlays.default
|
||||
inputs.nixGL.overlays.default
|
||||
];
|
||||
@@ -246,6 +235,13 @@ in
|
||||
exact = true;
|
||||
};
|
||||
};
|
||||
settings = {
|
||||
substituters = [
|
||||
#"https://nix-cache.nul.ie"
|
||||
"https://cache.nixos.org"
|
||||
];
|
||||
trusted-public-keys = lib.my.c.nix.cacheKeys;
|
||||
};
|
||||
};
|
||||
})
|
||||
(mkIf config.my.isStandalone {
|
||||
|
||||
@@ -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'
|
||||
@@ -1,8 +1,7 @@
|
||||
{ lib, pkgs', pkgs, config, ... }:
|
||||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (lib) genAttrs mkIf mkMerge mkForce mapAttrs mkOptionDefault;
|
||||
inherit (lib.my) mkOpt' mkBoolOpt';
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib) genAttrs mkIf mkMerge mkForce;
|
||||
inherit (lib.my) mkBoolOpt';
|
||||
|
||||
cfg = config.my.gui;
|
||||
|
||||
@@ -11,80 +10,33 @@ let
|
||||
name = "Monocraft";
|
||||
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
|
||||
{
|
||||
options.my.gui = with lib.types; {
|
||||
options.my.gui = {
|
||||
enable = mkBoolOpt' true "Enable settings and packages meant for graphical systems";
|
||||
manageGraphical = mkBoolOpt' false "Configure the graphical session";
|
||||
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 [
|
||||
{
|
||||
home = {
|
||||
packages = with pkgs; [
|
||||
xdg-utils
|
||||
|
||||
font.package
|
||||
nerd-fonts.sauce-code-pro
|
||||
nerd-fonts.droid-sans-mono
|
||||
noto-fonts-color-emoji
|
||||
(nerdfonts.override {
|
||||
fonts = [ "DroidSansMono" "SourceCodePro" ];
|
||||
})
|
||||
noto-fonts-emoji
|
||||
|
||||
grim
|
||||
slurp
|
||||
swappy
|
||||
|
||||
python3Packages.python-lsp-server
|
||||
python310Packages.python-lsp-server
|
||||
nil # nix language server
|
||||
zls # zig language server
|
||||
rust-analyzer
|
||||
|
||||
cowsay
|
||||
fortune
|
||||
jp2a
|
||||
terminaltexteffects
|
||||
screenfetch
|
||||
neofetch
|
||||
cmatrix
|
||||
doomsaver
|
||||
|
||||
ffmpeg-full
|
||||
xournalpp
|
||||
];
|
||||
};
|
||||
|
||||
@@ -99,15 +51,7 @@ in
|
||||
alacritty = {
|
||||
enable = true;
|
||||
settings = {
|
||||
general.import = [ ./alacritty-xterm.toml ];
|
||||
|
||||
font = {
|
||||
size = font.size;
|
||||
normal = {
|
||||
family = font.name;
|
||||
style = "Regular";
|
||||
};
|
||||
};
|
||||
font.normal.family = font.name;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -115,29 +59,8 @@ in
|
||||
enable = true;
|
||||
inherit font;
|
||||
settings = {
|
||||
background_opacity = "0.65";
|
||||
background_opacity = "0.8";
|
||||
tab_bar_edge = "top";
|
||||
shell_integration = "no-sudo";
|
||||
font_features = "${font.name} -liga";
|
||||
};
|
||||
};
|
||||
|
||||
termite = {
|
||||
enable = true;
|
||||
font = "${font.name} ${toString font.size}";
|
||||
backgroundColor = "rgba(0, 0, 0, 0.8)";
|
||||
};
|
||||
|
||||
foot = {
|
||||
enable = true;
|
||||
settings = {
|
||||
main = {
|
||||
font = "${font.name}:size=${toString font.size}";
|
||||
};
|
||||
colors = {
|
||||
alpha = 0.8;
|
||||
background = "000000";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -184,19 +107,6 @@ in
|
||||
};
|
||||
Install.RequiredBy = [ "sway-session.target" ];
|
||||
};
|
||||
|
||||
activate-linux = {
|
||||
Unit = {
|
||||
Description = "Linux activation watermark";
|
||||
After = "graphical-session.target";
|
||||
PartOf = "graphical-session.target";
|
||||
};
|
||||
Service = {
|
||||
Type = "simple";
|
||||
ExecStart = "${pkgs.activate-linux}/bin/activate-linux";
|
||||
};
|
||||
Install.RequiredBy = [ "graphical-session.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -206,7 +116,6 @@ in
|
||||
wl-clipboard
|
||||
wev
|
||||
wdisplays
|
||||
swaysome
|
||||
|
||||
pavucontrol
|
||||
libsecret
|
||||
@@ -216,11 +125,10 @@ in
|
||||
];
|
||||
|
||||
pointerCursor = {
|
||||
package = pkgs.posy-cursors;
|
||||
name = "Posy_Cursor";
|
||||
size = 32;
|
||||
package = pkgs.vanilla-dmz;
|
||||
name = "Vanilla-DMZ";
|
||||
size = 16;
|
||||
gtk.enable = true;
|
||||
x11.enable = true;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -229,36 +137,9 @@ in
|
||||
xsession.preferStatusNotifierItems = true;
|
||||
wayland = {
|
||||
windowManager = {
|
||||
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
|
||||
{
|
||||
sway = {
|
||||
enable = true;
|
||||
xwayland = true;
|
||||
extraConfigEarly = ''
|
||||
set $mod ${mod}
|
||||
'';
|
||||
config = {
|
||||
input = {
|
||||
"type:touchpad" = {
|
||||
@@ -273,95 +154,31 @@ in
|
||||
|
||||
modifier = "Mod4";
|
||||
terminal = "kitty";
|
||||
keybindings = mapAttrs (k: mkOptionDefault) {
|
||||
"${mod}+Left" = "focus left";
|
||||
"${mod}+Down" = "focus down";
|
||||
"${mod}+Up" = "focus up";
|
||||
"${mod}+Right" = "focus right";
|
||||
keybindings =
|
||||
let
|
||||
cfg = config.wayland.windowManager.sway.config;
|
||||
mod = cfg.modifier;
|
||||
in
|
||||
lib.mkOptionDefault {
|
||||
"${mod}+d" = null;
|
||||
"${mod}+l" = "exec swaylock -i ${./lock.png} -s stretch";
|
||||
"${mod}+x" = "exec ${cfg.menu}";
|
||||
"${mod}+Shift+x" = "exec rofi -show drun";
|
||||
"${mod}+q" = "kill";
|
||||
"${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'";
|
||||
"${mod}+Shift+d" = ''exec grim - | swappy -f -'';
|
||||
"${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -'';
|
||||
"${mod}+Shift+e" = "exec rofi -show emoji";
|
||||
# Config for this doesn't seem to work :/
|
||||
"${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"'';
|
||||
|
||||
"${mod}+Shift+Left" = "move left";
|
||||
"${mod}+Shift+Down" = "move down";
|
||||
"${mod}+Shift+Up" = "move up";
|
||||
"${mod}+Shift+Right" = "move right";
|
||||
|
||||
"${mod}+b" = "splith";
|
||||
"${mod}+v" = "splitv";
|
||||
"${mod}+f" = "fullscreen toggle";
|
||||
"${mod}+a" = "focus parent";
|
||||
|
||||
"${mod}+s" = "layout stacking";
|
||||
"${mod}+w" = "layout tabbed";
|
||||
"${mod}+e" = "layout toggle split";
|
||||
|
||||
"${mod}+Shift+space" = "floating toggle";
|
||||
"${mod}+space" = "focus mode_toggle";
|
||||
|
||||
"${mod}+1" = "workspace number 1";
|
||||
"${mod}+2" = "workspace number 2";
|
||||
"${mod}+3" = "workspace number 3";
|
||||
"${mod}+4" = "workspace number 4";
|
||||
"${mod}+5" = "workspace number 5";
|
||||
"${mod}+6" = "workspace number 6";
|
||||
"${mod}+7" = "workspace number 7";
|
||||
"${mod}+8" = "workspace number 8";
|
||||
"${mod}+9" = "workspace number 9";
|
||||
"${mod}+0" = "workspace number 10";
|
||||
|
||||
"${mod}+Shift+1" =
|
||||
"move container to workspace number 1";
|
||||
"${mod}+Shift+2" =
|
||||
"move container to workspace number 2";
|
||||
"${mod}+Shift+3" =
|
||||
"move container to workspace number 3";
|
||||
"${mod}+Shift+4" =
|
||||
"move container to workspace number 4";
|
||||
"${mod}+Shift+5" =
|
||||
"move container to workspace number 5";
|
||||
"${mod}+Shift+6" =
|
||||
"move container to workspace number 6";
|
||||
"${mod}+Shift+7" =
|
||||
"move container to workspace number 7";
|
||||
"${mod}+Shift+8" =
|
||||
"move container to workspace number 8";
|
||||
"${mod}+Shift+9" =
|
||||
"move container to workspace number 9";
|
||||
"${mod}+Shift+0" =
|
||||
"move container to workspace number 10";
|
||||
|
||||
"${mod}+Shift+minus" = "move scratchpad";
|
||||
"${mod}+minus" = "scratchpad show";
|
||||
|
||||
"${mod}+Return" = "exec ${cfg.terminal}";
|
||||
"${mod}+r" = "mode resize";
|
||||
"${mod}+d" = null;
|
||||
"${mod}+l" = "exec ${doomsaver}/bin/doomsaver";
|
||||
"${mod}+q" = "kill";
|
||||
"${mod}+Shift+c" = "reload";
|
||||
"${mod}+Shift+q" = "exec swaynag -t warning -m 'bruh you really wanna kill sway?' -b 'ye' 'systemctl --user stop graphical-session.target && swaymsg exit'";
|
||||
|
||||
# rofi
|
||||
"${mod}+x" = "exec ${cfg.menu}";
|
||||
"${mod}+Shift+x" = "exec rofi -show drun";
|
||||
"${mod}+Shift+e" = "exec rofi -show emoji";
|
||||
# Config for this doesn't seem to work :/
|
||||
"${mod}+c" = ''exec rofi -show calc -calc-command "echo -n '{result}' | ${pkgs.wl-clipboard}/bin/wl-copy"'';
|
||||
"${mod}+Shift+r" = "exec ${renameWs}";
|
||||
"${mod}+Shift+n" = "exec ${clearWsName}";
|
||||
|
||||
# Screenshots
|
||||
"${mod}+Shift+d" = ''exec grim - | swappy -f -'';
|
||||
"${mod}+Shift+s" = ''exec grim -g "$(slurp)" - | swappy -f -'';
|
||||
|
||||
"XF86MonBrightnessDown" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set 5%-";
|
||||
"XF86MonBrightnessUp" = "exec ${pkgs.brightnessctl}/bin/brightnessctl set +5%";
|
||||
|
||||
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
|
||||
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5";
|
||||
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play";
|
||||
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause";
|
||||
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
|
||||
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
|
||||
};
|
||||
"XF86AudioRaiseVolume" = "exec ${pkgs.pamixer}/bin/pamixer -i 5";
|
||||
"XF86AudioLowerVolume" = "exec ${pkgs.pamixer}/bin/pamixer -d 5";
|
||||
"XF86AudioPlay" = "exec ${pkgs.playerctl}/bin/playerctl play";
|
||||
"XF86AudioPause" = "exec ${pkgs.playerctl}/bin/playerctl pause";
|
||||
"XF86AudioNext" = "exec ${pkgs.playerctl}/bin/playerctl next";
|
||||
"XF86AudioPrev" = "exec ${pkgs.playerctl}/bin/playerctl previous";
|
||||
};
|
||||
keycodebindings = {
|
||||
# keycode for XF86AudioPlayPause (no sym for some reason)
|
||||
"172" = "exec ${pkgs.playerctl}/bin/playerctl play-pause";
|
||||
@@ -370,9 +187,6 @@ in
|
||||
menu = "rofi -show run";
|
||||
bars = mkForce [ ];
|
||||
};
|
||||
extraConfig = ''
|
||||
include ${./swaysome.conf}
|
||||
'';
|
||||
|
||||
swaynag = {
|
||||
enable = true;
|
||||
@@ -395,10 +209,17 @@ in
|
||||
};
|
||||
qt = {
|
||||
enable = true;
|
||||
platformTheme.name = "gtk";
|
||||
platformTheme = "gtk";
|
||||
};
|
||||
|
||||
services = {
|
||||
swaync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
widgets = [ "title" "dnd" "mpris" "notifications" ];
|
||||
};
|
||||
};
|
||||
|
||||
playerctld.enable = true;
|
||||
spotifyd = {
|
||||
enable = false;
|
||||
@@ -420,16 +241,13 @@ in
|
||||
programs = {
|
||||
git = {
|
||||
enable = true;
|
||||
settings = {
|
||||
user = {
|
||||
email = "jackos1998@gmail.com";
|
||||
name = "Jack O'Sullivan";
|
||||
};
|
||||
diff-so-fancy.enable = true;
|
||||
userEmail = "jackos1998@gmail.com";
|
||||
userName = "Jack O'Sullivan";
|
||||
extraConfig = {
|
||||
pull.rebase = true;
|
||||
};
|
||||
lfs.enable = true;
|
||||
};
|
||||
diff-so-fancy.enable = true;
|
||||
|
||||
waybar = import ./waybar.nix { inherit lib pkgs config font; };
|
||||
rofi = {
|
||||
@@ -452,7 +270,7 @@ in
|
||||
|
||||
chromium = {
|
||||
enable = true;
|
||||
package = (pkgs'.unstable.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
|
||||
package = (pkgs.chromium.override { enableWideVine = true; }).overrideAttrs (old: {
|
||||
buildCommand = ''
|
||||
${old.buildCommand}
|
||||
|
||||
@@ -478,15 +296,6 @@ in
|
||||
] (_: "chromium-browser.desktop");
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
swaync = {
|
||||
enable = true;
|
||||
settings = {
|
||||
widgets = [ "title" "dnd" "mpris" "notifications" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
})
|
||||
|
||||
(mkIf (cfg.standalone && !pkgs.stdenv.isDarwin) {
|
||||
|
||||
|
Before Width: | Height: | Size: 7.4 KiB |
@@ -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()
|
||||
|
Before Width: | Height: | Size: 251 KiB After Width: | Height: | Size: 249 KiB |
@@ -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"
|
||||
|
||||
@@ -146,9 +146,9 @@ in
|
||||
dnd-none = "";
|
||||
};
|
||||
return-type = "json";
|
||||
exec = "${config.my.swaync.package}/bin/swaync-client -swb";
|
||||
on-click = "${config.my.swaync.package}/bin/swaync-client -t -sw";
|
||||
on-click-right = "${config.my.swaync.package}/bin/swaync-client -d -sw";
|
||||
exec = "${config.services.swaync.package}/bin/swaync-client -swb";
|
||||
on-click = "${config.services.swaync.package}/bin/swaync-client -t -sw";
|
||||
on-click-right = "${config.services.swaync.package}/bin/swaync-client -d -sw";
|
||||
escape = true;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -19,10 +19,10 @@ let
|
||||
};
|
||||
};
|
||||
|
||||
cfg = config.my.swaync;
|
||||
cfg = config.services.swaync;
|
||||
in
|
||||
{
|
||||
options.my.swaync = with lib.types; {
|
||||
options.services.swaync = with lib.types; {
|
||||
enable = mkEnableOption "Sway Notification Center";
|
||||
package = mkOption {
|
||||
type = package;
|
||||
@@ -70,17 +70,13 @@ in
|
||||
"swaync/config.json" = mkIf (cfg.settings != { }) {
|
||||
source = configSource;
|
||||
onChange = ''
|
||||
if ${pkgs.systemd}/bin/systemctl --user is-active --quiet swaync; then
|
||||
${cfg.package}/bin/swaync-client --reload-config
|
||||
fi
|
||||
${cfg.package}/bin/swaync-client --reload-config
|
||||
'';
|
||||
};
|
||||
"swaync/style.css" = mkIf (cfg.style != null) {
|
||||
source = styleSource;
|
||||
onChange = ''
|
||||
if ${pkgs.systemd}/bin/systemctl --user is-active --quiet swaync; then
|
||||
${cfg.package}/bin/swaync-client --reload-css
|
||||
fi
|
||||
${cfg.package}/bin/swaync-client --reload-css
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,39 +1,19 @@
|
||||
{ lib }:
|
||||
let
|
||||
inherit (lib) concatStringsSep;
|
||||
in
|
||||
rec {
|
||||
{ lib }: rec {
|
||||
# See https://github.com/NixOS/nixpkgs/blob/master/nixos/modules/misc/ids.nix
|
||||
ids = {
|
||||
uids = {
|
||||
matrix-syncv3 = 400;
|
||||
gitea-runner = 401;
|
||||
jellyseerr = 402;
|
||||
atticd = 403;
|
||||
kea = 404;
|
||||
keepalived_script = 405;
|
||||
photoprism = 406;
|
||||
copyparty = 408;
|
||||
};
|
||||
gids = {
|
||||
matrix-syncv3 = 400;
|
||||
gitea-runner = 401;
|
||||
jellyseerr = 402;
|
||||
atticd = 403;
|
||||
kea = 404;
|
||||
keepalived_script = 405;
|
||||
photoprism = 406;
|
||||
adbusers = 407;
|
||||
copyparty = 408;
|
||||
};
|
||||
};
|
||||
|
||||
kernel = {
|
||||
lts = pkgs: pkgs.linuxKernel.packages.linux_6_12;
|
||||
latest = pkgs: pkgs.linuxKernel.packages.linux_6_18;
|
||||
};
|
||||
|
||||
nginx = rec {
|
||||
nginx = {
|
||||
proxyHeaders = ''
|
||||
# Setting any proxy_header in a child (e.g. location) will nuke the parents...
|
||||
proxy_set_header X-Origin-URI $request_uri;
|
||||
@@ -47,76 +27,18 @@ rec {
|
||||
proxy_set_header X-Forwarded-Protocol $scheme;
|
||||
proxy_set_header X-Scheme $scheme;
|
||||
'';
|
||||
baseHttpConfig = ''
|
||||
# NixOS provides a logrotate config that auto-compresses :)
|
||||
log_format main
|
||||
'$remote_addr - $remote_user [$time_local] $scheme "$host" "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
# optimisation
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
# gzip
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 5;
|
||||
gzip_types
|
||||
application/atom+xml
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/xml+rss
|
||||
image/svg+xml
|
||||
text/css
|
||||
text/javascript
|
||||
text/plain
|
||||
text/xml;
|
||||
gzip_vary on;
|
||||
|
||||
# proxying
|
||||
proxy_buffering off;
|
||||
proxy_redirect off;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
${proxyHeaders}
|
||||
'';
|
||||
};
|
||||
|
||||
networkd = {
|
||||
noL3 = {
|
||||
LinkLocalAddressing = "no";
|
||||
DHCP = "no";
|
||||
LLDP = false;
|
||||
EmitLLDP = false;
|
||||
IPv6AcceptRA = false;
|
||||
};
|
||||
};
|
||||
|
||||
nix = {
|
||||
cache = rec {
|
||||
substituters = [
|
||||
"https://nix-cache.${pubDomain}"
|
||||
];
|
||||
keys = [
|
||||
"nix-cache.nul.ie-1:BzH5yMfF4HbzY1C977XzOxoPhEc9Zbu39ftPkUbH+m4="
|
||||
];
|
||||
conf = ''
|
||||
extra-substituters = ${concatStringsSep " " substituters}
|
||||
extra-trusted-public-keys = ${concatStringsSep " " keys}
|
||||
'';
|
||||
};
|
||||
cacheKeys = [
|
||||
"nix-cache.nul.ie-1:XofkqdHQSGFoPjB6aRohQbCU2ILKFqhNjWfoOdQgF5Y="
|
||||
"cache.nixos.org-1:6NCHdD59X431o0gWypbMrAURkbJ16ZPMQFGspcDShjY="
|
||||
];
|
||||
};
|
||||
|
||||
pubDomain = "nul.ie";
|
||||
colony = rec {
|
||||
colony = {
|
||||
domain = "ams1.int.${pubDomain}";
|
||||
pubV4 = "94.142.240.44";
|
||||
prefixes = with lib.my.net.cidr; rec {
|
||||
all = {
|
||||
v4 = "10.100.0.0/16";
|
||||
@@ -138,19 +60,6 @@ rec {
|
||||
v4 = subnet 8 3 all.v4;
|
||||
v6 = subnet 4 3 all.v6;
|
||||
};
|
||||
qclk = {
|
||||
v4 = subnet 8 4 all.v4;
|
||||
};
|
||||
|
||||
p2pTunnels = {
|
||||
v4 = subnet 8 5 all.v4;
|
||||
};
|
||||
hillcrest = {
|
||||
v4 = subnet 6 0 p2pTunnels.v4;
|
||||
};
|
||||
john-valorant = {
|
||||
v4 = subnet 6 1 p2pTunnels.v4;
|
||||
};
|
||||
|
||||
cust = {
|
||||
v4 = subnet 8 100 all.v4; # single ip for routing only
|
||||
@@ -164,270 +73,16 @@ rec {
|
||||
v4 = "94.142.242.255/32";
|
||||
v6 = subnet 8 1 cust.v6;
|
||||
};
|
||||
jam = {
|
||||
v4 = subnet 8 4 cust.v4;
|
||||
v6 = subnet 8 2 cust.v6;
|
||||
};
|
||||
|
||||
vip1 = "94.142.241.224/30";
|
||||
vip2 = "94.142.242.254/31";
|
||||
vip3 = "94.142.241.117/32";
|
||||
|
||||
as211024 = {
|
||||
v4 = subnet 8 50 all.v4;
|
||||
v6 = "2a0e:97c0:4df::/64";
|
||||
};
|
||||
home.v6 = "2a0e:97c0:4d0::/48";
|
||||
};
|
||||
|
||||
custRouting = with lib.my.net.cidr; {
|
||||
mail-vm = host 1 prefixes.cust.v4;
|
||||
darts-vm = host 2 prefixes.cust.v4;
|
||||
jam-ctr = host 3 prefixes.cust.v4;
|
||||
};
|
||||
|
||||
qclk = {
|
||||
wgPort = 51821;
|
||||
};
|
||||
|
||||
firewallForwards = aa: [
|
||||
{
|
||||
port = "http";
|
||||
dst = aa.middleman.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = "https";
|
||||
dst = aa.middleman.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 8448;
|
||||
dst = aa.middleman.internal.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
port = 25565;
|
||||
dst = aa.simpcraft-oci.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 25566;
|
||||
dst = aa.simpcraft-staging-oci.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 25567;
|
||||
dst = aa.kevcraft-oci.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 25568;
|
||||
dst = aa.kinkcraft-oci.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 25569;
|
||||
dst = aa.graeme-oci.internal.ipv4.address;
|
||||
}
|
||||
|
||||
# RCON... unsafe?
|
||||
# {
|
||||
# port = 25575;
|
||||
# dst = aa.simpcraft-oci.internal.ipv4.address;
|
||||
# }
|
||||
|
||||
{
|
||||
port = 7777;
|
||||
dst = aa.gam.internal.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
port = 2456;
|
||||
dst = aa.valheim-oci.internal.ipv4.address;
|
||||
proto = "udp";
|
||||
}
|
||||
{
|
||||
port = 2457;
|
||||
dst = aa.valheim-oci.internal.ipv4.address;
|
||||
proto = "udp";
|
||||
}
|
||||
|
||||
{
|
||||
port = 41641;
|
||||
dst = aa.waffletail.internal.ipv4.address;
|
||||
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 = 25569;
|
||||
dst = aa.graeme-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";
|
||||
}
|
||||
|
||||
{
|
||||
port = 7777;
|
||||
dst = aa.gam.internal.ipv4.address;
|
||||
proto = "udp";
|
||||
}
|
||||
];
|
||||
|
||||
fstrimConfig = {
|
||||
enable = true;
|
||||
# backup happens at 05:00
|
||||
interval = "04:45";
|
||||
};
|
||||
};
|
||||
|
||||
home = rec {
|
||||
domain = "h.${pubDomain}";
|
||||
vlans = {
|
||||
hi = 100;
|
||||
lo = 110;
|
||||
untrusted = 120;
|
||||
wan = 130;
|
||||
};
|
||||
hiMTU = 9000;
|
||||
routers = [
|
||||
"river"
|
||||
"stream"
|
||||
];
|
||||
routersPubV4 = [
|
||||
"109.255.108.88"
|
||||
"109.255.108.121"
|
||||
];
|
||||
|
||||
prefixes = with lib.my.net.cidr; rec {
|
||||
modem = {
|
||||
v4 = "192.168.0.0/24";
|
||||
};
|
||||
all = {
|
||||
v4 = "192.168.64.0/18";
|
||||
v6 = "2a0e:97c0:4d0::/60";
|
||||
};
|
||||
core = {
|
||||
v4 = subnet 6 0 all.v4;
|
||||
};
|
||||
hi = {
|
||||
v4 = subnet 4 1 all.v4;
|
||||
v6 = subnet 4 1 all.v6;
|
||||
mtu = hiMTU;
|
||||
};
|
||||
lo = {
|
||||
v4 = subnet 3 1 all.v4;
|
||||
v6 = subnet 4 2 all.v6;
|
||||
mtu = 1500;
|
||||
};
|
||||
untrusted = {
|
||||
v4 = subnet 6 16 all.v4;
|
||||
v6 = subnet 4 3 all.v6;
|
||||
mtu = 1500;
|
||||
};
|
||||
inherit (colony.prefixes) as211024;
|
||||
};
|
||||
vips = with lib.my.net.cidr; {
|
||||
hi = {
|
||||
v4 = host (4*256-2) prefixes.hi.v4;
|
||||
v6 = host 65535 prefixes.hi.v6;
|
||||
};
|
||||
lo = {
|
||||
v4 = host (8*256-2) prefixes.lo.v4;
|
||||
v6 = host 65535 prefixes.lo.v6;
|
||||
};
|
||||
untrusted = {
|
||||
v4 = host 254 prefixes.untrusted.v4;
|
||||
v6 = host 65535 prefixes.untrusted.v6;
|
||||
};
|
||||
as211024 = {
|
||||
v4 = host 4 prefixes.as211024.v4;
|
||||
v6 = host ((1*65536*65536*65536) + 65535) prefixes.as211024.v6;
|
||||
};
|
||||
};
|
||||
|
||||
roceBootModules = [ "ib_core" "ib_uverbs" "mlx5_core" "mlx5_ib" ];
|
||||
};
|
||||
|
||||
britway = {
|
||||
domain = "lon1.int.${pubDomain}";
|
||||
pubV4 = "45.76.141.188";
|
||||
prefixes = {
|
||||
vultr = {
|
||||
v6 = "2001:19f0:7402:128b::/64";
|
||||
};
|
||||
inherit (colony.prefixes) as211024;
|
||||
};
|
||||
# Need to use this IP as the source address for BGP
|
||||
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 = {
|
||||
prefix = {
|
||||
v4 = "100.64.0.0/10";
|
||||
v6 = "fd7a:115c:a1e0::/48";
|
||||
};
|
||||
};
|
||||
|
||||
as211024 = rec {
|
||||
trusted = {
|
||||
v4 = [
|
||||
colony.prefixes.as211024.v4
|
||||
colony.prefixes.all.v4
|
||||
home.prefixes.all.v4
|
||||
tailscale.prefix.v4
|
||||
];
|
||||
v6 = [
|
||||
colony.prefixes.as211024.v6
|
||||
colony.prefixes.all.v6
|
||||
home.prefixes.all.v6
|
||||
tailscale.prefix.v6
|
||||
];
|
||||
};
|
||||
nftTrust = ''
|
||||
iifname as211024 ip saddr { ${concatStringsSep ", " trusted.v4} } accept
|
||||
iifname as211024 ip6 saddr { ${concatStringsSep ", " trusted.v6} } accept
|
||||
'';
|
||||
};
|
||||
|
||||
kelder = {
|
||||
groups = {
|
||||
storage = 2000;
|
||||
@@ -435,7 +90,6 @@ rec {
|
||||
};
|
||||
|
||||
domain = "hentai.engineer";
|
||||
ipv4MTU = 1460;
|
||||
vpn = {
|
||||
port = 51820;
|
||||
};
|
||||
@@ -444,21 +98,11 @@ rec {
|
||||
ctrs.v4 = subnet 4 0 all.v4;
|
||||
};
|
||||
};
|
||||
|
||||
hillcrest = {
|
||||
vpn.port = 51822;
|
||||
};
|
||||
|
||||
john-valorant = {
|
||||
vpn.port = 51823;
|
||||
};
|
||||
|
||||
sshKeyFiles = {
|
||||
me = ../.keys/me.pub;
|
||||
deploy = ../.keys/deploy.pub;
|
||||
rsyncNet = ../.keys/zh2855.rsync.net.pub;
|
||||
mailcowAcme = ../.keys/mailcow-acme.pub;
|
||||
harmonia = ../.keys/harmonia.pub;
|
||||
};
|
||||
sshHostKeys = {
|
||||
mail-vm = ../.keys/mail-vm-host.pub;
|
||||
|
||||
106
lib/default.nix
@@ -1,29 +1,16 @@
|
||||
{ inputs, lib }:
|
||||
{ lib }:
|
||||
let
|
||||
inherit (builtins) length match elemAt filter replaceStrings substring;
|
||||
inherit (builtins) length match elemAt filter;
|
||||
inherit (lib)
|
||||
genAttrs mapAttrsToList filterAttrsRecursive nameValuePair types
|
||||
mkOption mkOverride mkForce mkIf mergeEqualOption optional
|
||||
showWarnings concatStringsSep flatten unique optionalAttrs
|
||||
mkBefore toLower splitString last;
|
||||
showWarnings concatStringsSep flatten unique;
|
||||
inherit (lib.flake) defaultSystems;
|
||||
in
|
||||
rec {
|
||||
pow =
|
||||
let
|
||||
pow' = base: exponent: value:
|
||||
# FIXME: It will silently overflow on values > 2**62 :(
|
||||
# The value will become negative or zero in this case
|
||||
if exponent == 0
|
||||
then 1
|
||||
else if exponent <= 1
|
||||
then value
|
||||
else (pow' base (exponent - 1) (value * base));
|
||||
in base: exponent: pow' base exponent base;
|
||||
|
||||
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; };
|
||||
c = import ./constants.nix { inherit lib; };
|
||||
|
||||
@@ -42,8 +29,6 @@ rec {
|
||||
ports = checked (elemAt m 1);
|
||||
};
|
||||
|
||||
netBroadcast = net': net.cidr.host ((pow 2 (net.cidr.size net')) - 1) net';
|
||||
|
||||
mkDefaultSystemsPkgs = path: args': genAttrs defaultSystems (system: import path ((args' system) // { inherit system; }));
|
||||
mkApp = program: { type = "app"; inherit program; };
|
||||
mkShellApp = pkgs: name: text: mkApp (pkgs.writeShellScript name text).outPath;
|
||||
@@ -53,7 +38,7 @@ rec {
|
||||
in mkApp "${app}/bin/${app.meta.mainProgram}";
|
||||
flakePackageOverlay' = flake: pkg: system: (final: prev:
|
||||
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;
|
||||
in
|
||||
{
|
||||
@@ -124,21 +109,6 @@ rec {
|
||||
home-manager = mkOpt' (enum [ "unstable" "stable" "mine" "mine-stable" ]) "unstable" "Branch of home-manager to use.";
|
||||
};
|
||||
|
||||
nft = rec {
|
||||
ipEscape = replaceStrings ["." ":"] ["-" "-"];
|
||||
natFilterChain = ip: "filter-fwd-${ipEscape ip}";
|
||||
dnatChain = ip: "fwd-${ipEscape ip}";
|
||||
};
|
||||
|
||||
mkVLAN = name: vid: {
|
||||
"25-${name}" = {
|
||||
netdevConfig = {
|
||||
Name = name;
|
||||
Kind = "vlan";
|
||||
};
|
||||
vlanConfig.Id = vid;
|
||||
};
|
||||
};
|
||||
networkdAssignment = iface: a: {
|
||||
matchConfig.Name = iface;
|
||||
address =
|
||||
@@ -153,9 +123,6 @@ rec {
|
||||
LLDP = true;
|
||||
EmitLLDP = "customer-bridge";
|
||||
};
|
||||
linkConfig = optionalAttrs (a.mtu != null) {
|
||||
MTUBytes = toString a.mtu;
|
||||
};
|
||||
ipv6AcceptRAConfig = {
|
||||
Token = mkIf (a.ipv6.iid != null) "static:${a.ipv6.iid}";
|
||||
UseDNS = true;
|
||||
@@ -167,32 +134,13 @@ rec {
|
||||
|
||||
systemdAwaitPostgres = pkg: host: {
|
||||
after = [ "systemd-networkd-wait-online.service" ];
|
||||
preStart = mkBefore ''
|
||||
preStart = ''
|
||||
until ${pkg}/bin/pg_isready -h ${host}; do
|
||||
sleep 0.5
|
||||
done
|
||||
'';
|
||||
};
|
||||
|
||||
vm = rec {
|
||||
lvmDisk' = name: lv: {
|
||||
inherit name;
|
||||
backend = {
|
||||
driver = "host_device";
|
||||
filename = "/dev/main/${lv}";
|
||||
# It appears this needs to be set on the backend _and_ the format
|
||||
discard = "unmap";
|
||||
};
|
||||
format = {
|
||||
driver = "raw";
|
||||
discard = "unmap";
|
||||
};
|
||||
frontend = "virtio-blk";
|
||||
};
|
||||
lvmDisk = lv: lvmDisk' lv lv;
|
||||
disk = vm: lv: lvmDisk' lv "vm-${vm}-${lv}";
|
||||
};
|
||||
|
||||
deploy-rs =
|
||||
with types;
|
||||
let
|
||||
@@ -240,46 +188,4 @@ rec {
|
||||
|
||||
filterOpts = filterAttrsRecursive (_: v: v != null);
|
||||
};
|
||||
|
||||
versionOverlay = { self, pkgsFlake }: final: prev:
|
||||
let
|
||||
date = substring 0 8 (self.lastModifiedDate or self.lastModified or "19700101");
|
||||
revCode = flake: flake.shortRev or "dirty";
|
||||
in
|
||||
{
|
||||
trivial = prev.trivial // {
|
||||
release = "25.11:u-${prev.trivial.release}";
|
||||
codeName = "Hooray";
|
||||
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";
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
31
lib/dns.nix
@@ -67,35 +67,4 @@ rec {
|
||||
(a.ipv6.address != null && a.ipv6.genPTR)
|
||||
''@@PTR:${a.ipv6.address}:${toString ndots}@@ IN PTR ${a.name}.${domain}.'';
|
||||
};
|
||||
|
||||
ifaceA = { pkgs, iface, skipBroadcasts ? [] }:
|
||||
let
|
||||
extraFilters = concatMapStringsSep " " (b: ''and .broadcast != \"${b}\"'') skipBroadcasts;
|
||||
script = pkgs.writeText "if-${iface}-a.lua" ''
|
||||
local proc = io.popen("${pkgs.iproute2}/bin/ip -j addr show dev ${iface} | ${pkgs.jq}/bin/jq -r '.[0].addr_info[] | select(.family == \"inet\" and .scope == \"global\" ${extraFilters}).local'", "r")
|
||||
assert(proc, "failed to popen")
|
||||
|
||||
local addr_line = proc:read("*l")
|
||||
assert(proc:close(), "command failed")
|
||||
assert(addr_line, "no output from command")
|
||||
|
||||
return addr_line
|
||||
'';
|
||||
in
|
||||
''A "dofile('${script}')"'';
|
||||
|
||||
lookupIP = { pkgs, hostname, server, type ? "A" }:
|
||||
let
|
||||
script = pkgs.writeScript "drill-${hostname}-${server}.lua" ''
|
||||
local proc = io.popen("${pkgs.ldns}/bin/drill -Q @${server} ${hostname} ${type}", "r")
|
||||
assert(proc, "failed to popen")
|
||||
|
||||
local addr_line = proc:read("*l")
|
||||
assert(proc:close(), "command failed")
|
||||
assert(addr_line, "no output from command")
|
||||
|
||||
return addr_line
|
||||
'';
|
||||
in
|
||||
''${type} "dofile('${script}')"'';
|
||||
}
|
||||
|
||||
1322
lib/net.nix
Normal 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}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,198 +0,0 @@
|
||||
{ lib, pkgs, config, assignments, ... }:
|
||||
let
|
||||
inherit (lib.my.c.britway) assignedV6;
|
||||
|
||||
securebitSpace = "2a0e:97c0:4d0::/44";
|
||||
intnet6 = "2a0e:97c0:4df::/48";
|
||||
amsnet6 = "2a0e:97c0:4d2::/48";
|
||||
homenet6 = "2a0e:97c0:4d0::/48";
|
||||
in
|
||||
{
|
||||
config = {
|
||||
my = {
|
||||
secrets.files."britway/bgp-password-vultr.conf" = {
|
||||
owner = "bird";
|
||||
group = "bird";
|
||||
};
|
||||
};
|
||||
|
||||
environment.etc."bird/vultr-password.conf".source = config.age.secrets."britway/bgp-password-vultr.conf".path;
|
||||
|
||||
systemd = {
|
||||
services.bird.after = [ "systemd-networkd-wait-online@veth0.service" ];
|
||||
network = {
|
||||
config.networkConfig.ManageForeignRoutes = false;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
bird = {
|
||||
enable = true;
|
||||
package = pkgs.bird2;
|
||||
preCheckConfig = ''
|
||||
echo '"dummy"' > vultr-password.conf
|
||||
'';
|
||||
# TODO: Clean up and modularise
|
||||
config = ''
|
||||
define OWNAS = 211024;
|
||||
|
||||
define OWNIP4 = ${assignments.vultr.ipv4.address};
|
||||
define OWNNETSET4 = [ ${assignments.vultr.ipv4.address}/32 ];
|
||||
|
||||
define INTNET6 = ${intnet6};
|
||||
define AMSNET6 = ${amsnet6};
|
||||
define HOMENET6 = ${homenet6};
|
||||
|
||||
define OWNIP6 = ${assignments.vultr.ipv6.address};
|
||||
define OWNNETSET6 = [ ${intnet6}, ${amsnet6}, ${homenet6} ];
|
||||
#define TRANSSET6 = [ ::1/128 ];
|
||||
|
||||
define DUB1IP6 = ${lib.my.c.home.vips.as211024.v6};
|
||||
|
||||
define PREFIXP = 110;
|
||||
define PREFPEER = 120;
|
||||
|
||||
filter bgp_import {
|
||||
if net !~ OWNNETSET4 && net !~ OWNNETSET6 then accept; else reject;
|
||||
}
|
||||
filter bgp_export {
|
||||
if net ~ OWNNETSET4 || net ~ OWNNETSET6 then accept; else reject;
|
||||
}
|
||||
|
||||
router id from "veth0";
|
||||
|
||||
protocol device {}
|
||||
protocol direct {
|
||||
interface "veth0";
|
||||
ipv4;
|
||||
ipv6;
|
||||
}
|
||||
protocol static static4 {
|
||||
ipv4 {
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
protocol static static6 {
|
||||
# Special case: We have to do the routing on behalf of this _internal_ next-hop
|
||||
route INTNET6 via "as211024";
|
||||
route HOMENET6 via DUB1IP6;
|
||||
|
||||
ipv6 {
|
||||
import all;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
|
||||
protocol kernel kernel4 {
|
||||
ipv4 {
|
||||
import none;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
protocol kernel kernel6 {
|
||||
ipv6 {
|
||||
import none;
|
||||
export filter {
|
||||
if net = HOMENET6 then accept;
|
||||
reject;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
protocol bgp bgptools {
|
||||
local as OWNAS;
|
||||
multihop;
|
||||
description "bgp.tools monitoring";
|
||||
neighbor 2a0c:2f07:9459::b11 as 212232;
|
||||
source address OWNIP6;
|
||||
ipv4 {
|
||||
import none;
|
||||
export all;
|
||||
add paths tx;
|
||||
};
|
||||
ipv6 {
|
||||
import none;
|
||||
export all;
|
||||
add paths tx;
|
||||
};
|
||||
}
|
||||
|
||||
template bgp base_bgp4 {
|
||||
local as OWNAS;
|
||||
direct;
|
||||
allow local as;
|
||||
ipv4 {
|
||||
import keep filtered;
|
||||
export none;
|
||||
};
|
||||
}
|
||||
|
||||
template bgp upstream_bgp4 from base_bgp4 {
|
||||
ipv4 {
|
||||
#import none;
|
||||
import filter bgp_import;
|
||||
};
|
||||
}
|
||||
template bgp peer_bgp4 from base_bgp4 {
|
||||
ipv4 {
|
||||
import filter bgp_import;
|
||||
preference PREFPEER;
|
||||
};
|
||||
}
|
||||
template bgp ixp_bgp4 from base_bgp4 {
|
||||
ipv4 {
|
||||
import filter bgp_import;
|
||||
preference PREFIXP;
|
||||
};
|
||||
}
|
||||
|
||||
template bgp base_bgp6 {
|
||||
local ${assignedV6} as OWNAS;
|
||||
direct;
|
||||
# So we can see routes we announce from other routers
|
||||
allow local as;
|
||||
ipv6 {
|
||||
import keep filtered;
|
||||
export filter bgp_export;
|
||||
};
|
||||
}
|
||||
|
||||
template bgp upstream_bgp6 from base_bgp6 {
|
||||
ipv6 {
|
||||
#import none;
|
||||
import filter bgp_import;
|
||||
};
|
||||
}
|
||||
template bgp peer_bgp6 from base_bgp6 {
|
||||
ipv6 {
|
||||
import filter bgp_import;
|
||||
preference PREFPEER;
|
||||
};
|
||||
}
|
||||
template bgp ixp_bgp6 from base_bgp6 {
|
||||
ipv6 {
|
||||
import filter bgp_import;
|
||||
preference PREFIXP;
|
||||
};
|
||||
}
|
||||
|
||||
protocol bgp upstream4_vultr from upstream_bgp4 {
|
||||
description "Vultr transit (IPv4)";
|
||||
neighbor 169.254.169.254 as 64515;
|
||||
multihop 2;
|
||||
password
|
||||
include "vultr-password.conf";;
|
||||
}
|
||||
protocol bgp upstream6_vultr from upstream_bgp6 {
|
||||
description "Vultr transit (IPv6)";
|
||||
neighbor 2001:19f0:ffff::1 as 64515;
|
||||
multihop 2;
|
||||
password
|
||||
include "vultr-password.conf";;
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,174 +0,0 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.britway) prefixes domain pubV4 assignedV6;
|
||||
in
|
||||
{
|
||||
nixos.systems.britway = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
|
||||
assignments = {
|
||||
vultr = {
|
||||
inherit domain;
|
||||
ipv4 = {
|
||||
address = pubV4;
|
||||
mask = 23;
|
||||
gateway = "45.76.140.1";
|
||||
};
|
||||
ipv6 = {
|
||||
iid = "::1";
|
||||
address = "2001:19f0:7402:128b::1";
|
||||
};
|
||||
};
|
||||
as211024 = {
|
||||
ipv4 = {
|
||||
address = net.cidr.host 5 prefixes.as211024.v4;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6.address = net.cidr.host ((2*65536*65536*65536) + 1) prefixes.as211024.v6;
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/profiles/qemu-guest.nix"
|
||||
./bgp.nix
|
||||
./nginx.nix
|
||||
./tailscale.nix
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
boot = {
|
||||
initrd.availableKernelModules = [ "ata_piix" "uhci_hcd" "sr_mod" ];
|
||||
loader = {
|
||||
systemd-boot.enable = false;
|
||||
grub = {
|
||||
enable = true;
|
||||
device = "/dev/vda";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/c557ef12-da44-41d1-84f5-d32a711feefd";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-partuuid/d42d0853-b054-4104-8afd-6d36287c7ca3";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/disk/by-partuuid/f14fbcf4-5242-456b-a4db-ef15d053d62e";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
iperf3 = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking = { inherit domain; };
|
||||
|
||||
systemd.network = {
|
||||
config = {
|
||||
routeTables.ts-extra = 1337;
|
||||
};
|
||||
|
||||
links = {
|
||||
"10-veth0" = {
|
||||
matchConfig.PermanentMACAddress = "56:00:04:ac:6e:06";
|
||||
linkConfig.Name = "veth0";
|
||||
};
|
||||
};
|
||||
|
||||
networks = {
|
||||
"20-veth0" = mkMerge [
|
||||
(networkdAssignment "veth0" assignments.vultr)
|
||||
{
|
||||
address = [ "${assignedV6}/64" ];
|
||||
}
|
||||
];
|
||||
"90-l2mesh-as211024" = mkMerge [
|
||||
(networkdAssignment "as211024" assignments.as211024)
|
||||
{
|
||||
matchConfig.Name = "as211024";
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
routes = [
|
||||
{
|
||||
Destination = lib.my.c.colony.prefixes.all.v4;
|
||||
Gateway = allAssignments.estuary.as211024.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = lib.my.c.home.prefixes.all.v4;
|
||||
Gateway = lib.my.c.home.vips.as211024.v4;
|
||||
}
|
||||
|
||||
{
|
||||
# Just when routing traffic from Tailscale nodes, otherwise use WAN
|
||||
Destination = lib.my.c.colony.prefixes.all.v6;
|
||||
Gateway = allAssignments.estuary.as211024.ipv6.address;
|
||||
Table = "ts-extra";
|
||||
}
|
||||
];
|
||||
routingPolicyRules = [
|
||||
{
|
||||
IncomingInterface = "tailscale0";
|
||||
To = lib.my.c.colony.prefixes.all.v6;
|
||||
Table = "ts-extra";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
server.enable = true;
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAmXC9egI46Qtaiifhq2I+rv2s1yPyzTlO4BHzUb+3Su";
|
||||
files = {
|
||||
"l2mesh/as211024.key" = {};
|
||||
};
|
||||
};
|
||||
vpns = {
|
||||
l2.pskFiles = {
|
||||
as211024 = config.age.secrets."l2mesh/as211024.key".path;
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
trustedInterfaces = [ "tailscale0" ];
|
||||
extraRules = ''
|
||||
table inet filter {
|
||||
chain forward {
|
||||
${lib.my.c.as211024.nftTrust}
|
||||
oifname as211024 accept
|
||||
}
|
||||
}
|
||||
table inet nat {
|
||||
chain postrouting {
|
||||
iifname tailscale0 oifname veth0 snat ip to ${assignments.vultr.ipv4.address}
|
||||
iifname tailscale0 oifname veth0 snat ip6 to ${assignments.as211024.ipv6.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,109 +0,0 @@
|
||||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (builtins) mapAttrs;
|
||||
inherit (lib) mkMerge mkDefault;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.nginx) baseHttpConfig proxyHeaders;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
my = {
|
||||
secrets.files = {
|
||||
"dhparams.pem" = {
|
||||
owner = "acme";
|
||||
group = "acme";
|
||||
mode = "440";
|
||||
};
|
||||
"britway/cloudflare-credentials.conf" = {
|
||||
owner = "acme";
|
||||
group = "acme";
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [ "http" "https" ];
|
||||
};
|
||||
};
|
||||
|
||||
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."britway/cloudflare-credentials.conf".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
nginx = {
|
||||
enable = true;
|
||||
enableReload = true;
|
||||
|
||||
logError = "stderr info";
|
||||
recommendedTlsSettings = true;
|
||||
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";
|
||||
};
|
||||
};
|
||||
|
||||
"hs.${pubDomain}" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://localhost:${toString config.services.headscale.port}";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
defaultsFor = mapAttrs (n: _: {
|
||||
onlySSL = mkDefault true;
|
||||
useACMEHost = mkDefault pubDomain;
|
||||
kTLS = mkDefault true;
|
||||
http2 = mkDefault true;
|
||||
});
|
||||
in
|
||||
mkMerge [
|
||||
hosts
|
||||
(defaultsFor hosts)
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,97 +0,0 @@
|
||||
{ lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) concatStringsSep;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.britway) prefixes domain;
|
||||
|
||||
advRoutes = concatStringsSep "," [
|
||||
lib.my.c.home.prefixes.all.v4
|
||||
lib.my.c.home.prefixes.all.v6
|
||||
];
|
||||
pubNameservers = [
|
||||
"1.1.1.1"
|
||||
"1.0.0.1"
|
||||
"2606:4700:4700::1111"
|
||||
"2606:4700:4700::1001"
|
||||
];
|
||||
in
|
||||
{
|
||||
config = {
|
||||
environment.systemPackages = [
|
||||
# For CLI
|
||||
config.services.headscale.package
|
||||
];
|
||||
|
||||
services = {
|
||||
headscale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
disable_check_updates = true;
|
||||
unix_socket_permission = "0770";
|
||||
server_url = "https://hs.${pubDomain}";
|
||||
database = {
|
||||
type = "sqlite3";
|
||||
sqlite.path = "/var/lib/headscale/db.sqlite3";
|
||||
};
|
||||
noise.private_key_path = "/var/lib/headscale/noise_private.key";
|
||||
prefixes = with lib.my.c.tailscale.prefix; { inherit v4 v6; };
|
||||
dns = {
|
||||
override_local_dns = false;
|
||||
# Use IPs that will route inside the VPN to prevent interception
|
||||
# (e.g. DNS rebinding filtering)
|
||||
nameservers.split = {
|
||||
"${domain}" = pubNameservers;
|
||||
"${lib.my.c.colony.domain}" = with allAssignments.estuary.base; [
|
||||
ipv4.address ipv6.address
|
||||
];
|
||||
"${lib.my.c.home.domain}" = with allAssignments; [
|
||||
river.hi.ipv4.address
|
||||
river.hi.ipv6.address
|
||||
stream.hi.ipv4.address
|
||||
stream.hi.ipv6.address
|
||||
];
|
||||
};
|
||||
magic_dns = true;
|
||||
base_domain = "ts.${pubDomain}";
|
||||
};
|
||||
oidc = {
|
||||
only_start_if_oidc_is_available = true;
|
||||
issuer = "https://accounts.google.com";
|
||||
client_id = "545475967061-l45cln081mp8t4li2c34v7t7b8la6f4f.apps.googleusercontent.com";
|
||||
client_secret_path = config.age.secrets."britway/oidc-secret.txt".path;
|
||||
scope = [ "openid" "profile" "email" ];
|
||||
allowed_users = [ "jackos1998@gmail.com" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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"
|
||||
"--advertise-routes=${advRoutes}"
|
||||
"--accept-routes=false"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
files = {
|
||||
"britway/oidc-secret.txt" = {
|
||||
owner = "headscale";
|
||||
group = "headscale";
|
||||
mode = "440";
|
||||
};
|
||||
"tailscale-auth.key" = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,34 +1,12 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) networkd;
|
||||
inherit (lib.my.c.home) domain vlans prefixes vips roceBootModules;
|
||||
in
|
||||
{
|
||||
{ lib, ... }: {
|
||||
nixos.systems.castle = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
home-manager = "mine";
|
||||
|
||||
assignments = {
|
||||
hi = {
|
||||
inherit domain;
|
||||
ipv4 = {
|
||||
address = net.cidr.host 40 prefixes.hi.v4;
|
||||
mask = 22;
|
||||
gateway = vips.hi.v4;
|
||||
};
|
||||
ipv6 = {
|
||||
iid = "::3:1";
|
||||
address = net.cidr.host (65536*3+1) prefixes.hi.v6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, systems, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkIf mkMerge mkForce;
|
||||
inherit (lib.my) mkVLAN networkdAssignment;
|
||||
in
|
||||
{
|
||||
hardware = {
|
||||
@@ -36,7 +14,7 @@ in
|
||||
cpu = {
|
||||
amd.updateMicrocode = true;
|
||||
};
|
||||
graphics.extraPackages = with pkgs; [
|
||||
opengl.extraPackages = with pkgs; [
|
||||
intel-media-driver
|
||||
];
|
||||
bluetooth.enable = true;
|
||||
@@ -47,8 +25,8 @@ in
|
||||
efi.canTouchEfiVariables = false;
|
||||
timeout = 10;
|
||||
};
|
||||
kernelPackages = lib.my.c.kernel.latest pkgs;
|
||||
kernelModules = [ "kvm-amd" "dm-snapshot" ];
|
||||
kernelPackages = pkgs.linuxKernel.packages.linux_6_5;
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
kernelParams = [ "amd_iommu=on" "amd_pstate=passive" ];
|
||||
kernelPatches = [
|
||||
# {
|
||||
@@ -58,40 +36,27 @@ in
|
||||
# }
|
||||
];
|
||||
initrd = {
|
||||
availableKernelModules = [
|
||||
"thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod"
|
||||
"8021q"
|
||||
] ++ roceBootModules;
|
||||
systemd.network = {
|
||||
netdevs = mkVLAN "lan-hi" vlans.hi;
|
||||
networks = {
|
||||
"10-et100g" = {
|
||||
matchConfig.Name = "et100g";
|
||||
vlan = [ "lan-hi" ];
|
||||
linkConfig.RequiredForOnline = "no";
|
||||
networkConfig = networkd.noL3;
|
||||
};
|
||||
"20-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
|
||||
};
|
||||
};
|
||||
availableKernelModules = [ "thunderbolt" "xhci_pci" "nvme" "ahci" "usbhid" "usb_storage" "sd_mod" ];
|
||||
};
|
||||
|
||||
binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/8ce4248a-3ee4-f44f-801f-064a628b4d6e";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/nvmeof/nix";
|
||||
device = "/dev/disk/by-partuuid/2da23a1d-2daf-d943-b91e-fc175f3dad07";
|
||||
fsType = "ext4";
|
||||
};
|
||||
|
||||
"/persist" = {
|
||||
device = "/dev/nvmeof/persist";
|
||||
device = "/dev/disk/by-partuuid/f4c80d4f-a022-e941-b5d1-fe2e65e444b9";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
|
||||
"/home" = {
|
||||
device = "/dev/nvmeof/home";
|
||||
device = "/dev/disk/by-partuuid/992a93cf-6c9c-324b-b0ce-f8eb2d1ce10d";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
@@ -109,29 +74,17 @@ in
|
||||
};
|
||||
fstrim.enable = true;
|
||||
|
||||
resolved.settings.Resolve.LLMNR = mkForce true;
|
||||
|
||||
pipewire.extraConfig.pipewire = {
|
||||
"10-buffer"."context.properties" = {
|
||||
"default.clock.quantum" = 128;
|
||||
"default.clock.max-quantum" = 128;
|
||||
};
|
||||
};
|
||||
blueman.enable = true;
|
||||
avahi.enable = true;
|
||||
};
|
||||
|
||||
programs = {
|
||||
virt-manager.enable = true;
|
||||
wireshark = {
|
||||
resolved = {
|
||||
enable = true;
|
||||
package = pkgs.wireshark-qt;
|
||||
extraConfig = mkForce "";
|
||||
dnssec = "false";
|
||||
};
|
||||
|
||||
blueman.enable = true;
|
||||
};
|
||||
virtualisation.libvirtd.enable = true;
|
||||
|
||||
networking = {
|
||||
inherit domain;
|
||||
domain = "h.${lib.my.c.pubDomain}";
|
||||
firewall.enable = false;
|
||||
};
|
||||
|
||||
@@ -147,23 +100,23 @@ in
|
||||
mstflint
|
||||
qperf
|
||||
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 = {
|
||||
gc.automatic = false;
|
||||
settings = {
|
||||
experimental-features = [ "recursive-nix" ];
|
||||
system-features = [ "nixos-test" "benchmark" "big-parallel" "kvm" "recursive-nix" ];
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
network = {
|
||||
netdevs = mkMerge [
|
||||
(mkVLAN "lan-hi" vlans.hi)
|
||||
(mkVLAN "lan-lo" vlans.lo)
|
||||
];
|
||||
wait-online.enable = false;
|
||||
links = {
|
||||
"10-et2.5g" = {
|
||||
matchConfig.MACAddress = "c8:7f:54:6e:17:0f";
|
||||
@@ -174,39 +127,14 @@ in
|
||||
linkConfig.Name = "et10g";
|
||||
};
|
||||
"12-et100g" = {
|
||||
matchConfig.PermanentMACAddress = "24:8a:07:a8:fe:3a";
|
||||
linkConfig = {
|
||||
Name = "et100g";
|
||||
MTUBytes = toString lib.my.c.home.hiMTU;
|
||||
};
|
||||
matchConfig.MACAddress = "24:8a:07:a8:fe:3a";
|
||||
linkConfig.Name = "et100g";
|
||||
};
|
||||
};
|
||||
networks = {
|
||||
"30-et100g" = {
|
||||
matchConfig.Name = "et100g";
|
||||
vlan = [ "lan-hi" "lan-lo" ];
|
||||
networkConfig.IPv6AcceptRA = false;
|
||||
};
|
||||
"40-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"; }
|
||||
];
|
||||
"45-lan-lo" = {
|
||||
matchConfig.Name = "lan-lo";
|
||||
networkConfig = {
|
||||
DHCP = "ipv4";
|
||||
IPv6AcceptRA = true;
|
||||
UseDomains = false;
|
||||
};
|
||||
dhcpV4Config = {
|
||||
UseDNS = false;
|
||||
UseGateway = false;
|
||||
};
|
||||
ipv6AcceptRAConfig = {
|
||||
UseDNS = false;
|
||||
UseGateway = false;
|
||||
};
|
||||
"50-lan" = {
|
||||
matchConfig.Name = "et2.5g";
|
||||
DHCP = "yes";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -226,7 +154,10 @@ in
|
||||
packages = with pkgs; [
|
||||
jacktrip
|
||||
qpwgraph
|
||||
boardie
|
||||
# TODO: seems to be borked (infinite recursion???)
|
||||
# (writeShellScriptBin "boardie" ''
|
||||
# exec pw-jack ${boardie}/bin/boardie "$@"
|
||||
# '')
|
||||
];
|
||||
};
|
||||
|
||||
@@ -240,7 +171,6 @@ in
|
||||
HDMI-A-1 = {
|
||||
transform = "270";
|
||||
position = "0 0";
|
||||
bg = "${./his-team-player.jpg} fill";
|
||||
};
|
||||
DP-1 = {
|
||||
mode = "2560x1440@170Hz";
|
||||
@@ -262,19 +192,10 @@ in
|
||||
};
|
||||
|
||||
#deploy.generate.system.mode = "boot";
|
||||
deploy.node.hostname = "castle.box.${config.networking.domain}";
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIMlVuTzKObeaUuPocCF41IO/8X+443lzUJLuCIclt2vr";
|
||||
};
|
||||
netboot.client = {
|
||||
enable = true;
|
||||
};
|
||||
nvme = {
|
||||
uuid = "2230b066-a674-4f45-a1dc-f7727b3a9e7b";
|
||||
boot = {
|
||||
nqn = "nqn.2016-06.io.spdk:castle";
|
||||
address = "192.168.68.80";
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
enable = false;
|
||||
@@ -1,7 +1,7 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.colony) domain prefixes custRouting firewallForwards;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
imports = [ ./vms ];
|
||||
@@ -57,30 +57,19 @@ in
|
||||
};
|
||||
|
||||
boot = {
|
||||
kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
|
||||
kernelPackages = pkgs.linuxKernel.packages.linux_6_1.extend (self: super: {
|
||||
kernel = super.kernel.override {
|
||||
structuredExtraConfig = with lib.kernel; {
|
||||
ACPI_APEI_PCIEAER = yes;
|
||||
PCIEAER = yes;
|
||||
#SOME_OPT = yes;
|
||||
#A_MOD = module;
|
||||
};
|
||||
};
|
||||
});
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
kernelParams = [
|
||||
"amd_iommu=on"
|
||||
"console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0"
|
||||
"systemd.setenv=SYSTEMD_SULOGIN_FORCE=1"
|
||||
];
|
||||
kernelParams = [ "amd_iommu=on" "console=ttyS0,115200n8" "console=ttyS1,115200n8" "console=tty0" ];
|
||||
initrd = {
|
||||
kernelModules = [ "dm-raid" ];
|
||||
availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
|
||||
systemd = {
|
||||
enable = true;
|
||||
# Onlu activate volumes needed for boot to prevent thin check from getting killed while switching root
|
||||
contents."/etc/lvm/lvm.conf".text = ''
|
||||
activation/auto_activation_volume_list = [ "main/colony-nix" "main/colony-persist" ]
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -148,15 +137,6 @@ in
|
||||
services = {
|
||||
"serial-getty@ttyS0".enable = true;
|
||||
"serial-getty@ttyS1".enable = true;
|
||||
lvm-activate-main = {
|
||||
description = "Activate remaining LVs";
|
||||
unitConfig.DefaultDependencies = false;
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart = "${pkgs.lvm2.bin}/bin/vgchange -aay main";
|
||||
};
|
||||
wantedBy = [ "local-fs-pre.target" ];
|
||||
};
|
||||
|
||||
rsync-lvm-meta = {
|
||||
description = "rsync lvm metadata backups / archives to rsync.net";
|
||||
@@ -252,10 +232,10 @@ in
|
||||
};
|
||||
ipv6Prefixes = [
|
||||
{
|
||||
Prefix = prefixes.vms.v6;
|
||||
ipv6PrefixConfig.Prefix = prefixes.vms.v6;
|
||||
}
|
||||
];
|
||||
routes = [
|
||||
routes = map (r: { routeConfig = r; }) [
|
||||
{
|
||||
Destination = prefixes.ctrs.v4;
|
||||
Gateway = allAssignments.shill.routing.ipv4.address;
|
||||
@@ -264,30 +244,11 @@ in
|
||||
Destination = prefixes.ctrs.v6;
|
||||
Gateway = allAssignments.shill.internal.ipv6.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = allAssignments.shill.internal.ipv4.address;
|
||||
Gateway = allAssignments.shill.routing.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v4;
|
||||
Gateway = allAssignments.shill.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v6;
|
||||
Gateway = allAssignments.shill.internal.ipv6.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.qclk.v4;
|
||||
Gateway = allAssignments.shill.routing.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = prefixes.jam.v6;
|
||||
Gateway = allAssignments.shill.internal.ipv6.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = prefixes.oci.v4;
|
||||
Gateway = allAssignments.whale2.routing.ipv4.address;
|
||||
@@ -300,11 +261,6 @@ in
|
||||
Destination = allAssignments.whale2.internal.ipv4.address;
|
||||
Gateway = allAssignments.whale2.routing.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = allAssignments.git.internal.ipv4.address;
|
||||
Gateway = allAssignments.git.routing.ipv4.address;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
@@ -318,7 +274,7 @@ in
|
||||
"90-vm-mail" = {
|
||||
matchConfig.Name = "vm-mail";
|
||||
address = [
|
||||
"${custRouting.mail-vm}/32"
|
||||
(net.cidr.subnet 8 1 prefixes.cust.v4)
|
||||
prefixes.mail.v6
|
||||
];
|
||||
networkConfig = {
|
||||
@@ -327,10 +283,10 @@ in
|
||||
};
|
||||
ipv6Prefixes = [
|
||||
{
|
||||
Prefix = prefixes.mail.v6;
|
||||
ipv6PrefixConfig.Prefix = prefixes.mail.v6;
|
||||
}
|
||||
];
|
||||
routes = [
|
||||
routes = map (r: { routeConfig = r; }) [
|
||||
{
|
||||
Destination = prefixes.mail.v4;
|
||||
Scope = "link";
|
||||
@@ -341,7 +297,7 @@ in
|
||||
"90-vm-darts" = {
|
||||
matchConfig.Name = "vm-darts";
|
||||
address = [
|
||||
"${custRouting.darts-vm}/32"
|
||||
(net.cidr.subnet 8 2 prefixes.cust.v4)
|
||||
prefixes.darts.v6
|
||||
];
|
||||
networkConfig = {
|
||||
@@ -350,10 +306,10 @@ in
|
||||
};
|
||||
ipv6Prefixes = [
|
||||
{
|
||||
Prefix = prefixes.darts.v6;
|
||||
ipv6PrefixConfig.Prefix = prefixes.darts.v6;
|
||||
}
|
||||
];
|
||||
routes = [
|
||||
routes = map (r: { routeConfig = r; }) [
|
||||
{
|
||||
Destination = prefixes.darts.v4;
|
||||
Scope = "link";
|
||||
@@ -390,7 +346,6 @@ in
|
||||
|
||||
firewall = {
|
||||
trustedInterfaces = [ "vms" ];
|
||||
nat.forwardPorts."${allAssignments.estuary.internal.ipv4.address}" = firewallForwards allAssignments;
|
||||
extraRules = ''
|
||||
define cust = { vm-mail, vm-darts }
|
||||
table inet filter {
|
||||
@@ -417,7 +372,6 @@ in
|
||||
"vm-estuary-persist"
|
||||
"vm-whale2-persist"
|
||||
"vm-mail-data"
|
||||
"vm-git-persist"
|
||||
"git"
|
||||
];
|
||||
compression = "zstd,5";
|
||||
|
||||
@@ -3,22 +3,37 @@
|
||||
./estuary
|
||||
./shill
|
||||
./whale2
|
||||
./git
|
||||
];
|
||||
|
||||
nixos.systems.colony.configuration = { lib, pkgs, config, systems, ... }:
|
||||
let
|
||||
inherit (lib) mkIf mkMerge optionals;
|
||||
inherit (lib.my) vm;
|
||||
|
||||
lvmDisk' = name: lv: {
|
||||
inherit name;
|
||||
backend = {
|
||||
driver = "host_device";
|
||||
filename = "/dev/main/${lv}";
|
||||
# It appears this needs to be set on the backend _and_ the format
|
||||
discard = "unmap";
|
||||
};
|
||||
format = {
|
||||
driver = "raw";
|
||||
discard = "unmap";
|
||||
};
|
||||
frontend = "virtio-blk";
|
||||
};
|
||||
lvmDisk = lv: lvmDisk' lv lv;
|
||||
vmLVM = vm: lv: lvmDisk' lv "vm-${vm}-${lv}";
|
||||
|
||||
installerDisk = {
|
||||
name = "installer";
|
||||
backend = {
|
||||
driver = "file";
|
||||
#filename = "${systems.installer.configuration.config.my.buildAs.iso}/iso/nixos-installer-devplayer0.iso";
|
||||
filename = "/persist/home/dev/nixos-installer-devplayer0-b4d0d9a.iso";
|
||||
#filename = "/persist/home/dev/nixos-installer-devplayer0.iso";
|
||||
#filename = "/persist/home/dev/debian-12.1.0-amd64-netinst.iso";
|
||||
# filename = "/persist/home/dev/ubuntu-22.04.3-live-server-amd64.iso";
|
||||
filename = "/persist/home/dev/ubuntu-22.04.3-live-server-amd64.iso";
|
||||
read-only = "on";
|
||||
};
|
||||
format.driver = "raw";
|
||||
@@ -29,9 +44,6 @@
|
||||
};
|
||||
in
|
||||
{
|
||||
# Kernel Same-Page Merging to attempt memory usage reduction
|
||||
hardware.ksm.enable = false;
|
||||
|
||||
systemd = {
|
||||
network = {
|
||||
links = {
|
||||
@@ -104,9 +116,9 @@
|
||||
};
|
||||
};
|
||||
drives = [ ] ++ (optionals (!config.my.build.isDevVM) [
|
||||
(mkMerge [ (vm.disk "estuary" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "estuary" "nix")
|
||||
(vm.disk "estuary" "persist")
|
||||
(mkMerge [ (vmLVM "estuary" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vmLVM "estuary" "nix")
|
||||
(vmLVM "estuary" "persist")
|
||||
]);
|
||||
hostDevices = {
|
||||
net-wan0 = {
|
||||
@@ -123,18 +135,17 @@
|
||||
cpus = 12;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 40960;
|
||||
memory = 65536;
|
||||
networks.vms.mac = "52:54:00:27:3d:5c";
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [ ] ++ (optionals (!config.my.build.isDevVM) [
|
||||
(mkMerge [ (vm.disk "shill" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "shill" "nix")
|
||||
(vm.disk "shill" "persist")
|
||||
(mkMerge [ (vmLVM "shill" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vmLVM "shill" "nix")
|
||||
(vmLVM "shill" "persist")
|
||||
|
||||
(vm.lvmDisk "media")
|
||||
(vm.lvmDisk "minio")
|
||||
(vm.lvmDisk "nix-cache")
|
||||
(vm.lvmDisk "jam")
|
||||
(lvmDisk "media")
|
||||
(lvmDisk "minio")
|
||||
(lvmDisk "git")
|
||||
]);
|
||||
};
|
||||
|
||||
@@ -145,39 +156,19 @@
|
||||
cpus = 8;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 16384;
|
||||
memory = 32768;
|
||||
networks.vms.mac = "52:54:00:d5:d9:c6";
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [ ] ++ (optionals (!config.my.build.isDevVM) [
|
||||
(mkMerge [ (vm.disk "whale2" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "whale2" "nix")
|
||||
(vm.disk "whale2" "persist")
|
||||
(mkMerge [ (vmLVM "whale2" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vmLVM "whale2" "nix")
|
||||
(vmLVM "whale2" "persist")
|
||||
|
||||
(vm.lvmDisk "oci")
|
||||
(lvmDisk "oci")
|
||||
(lvmDisk "gitea-actions-cache")
|
||||
]);
|
||||
};
|
||||
|
||||
git = {
|
||||
uuid = "c0659fdc-3356-4717-a6a1-5f289ef03c4a";
|
||||
cpu = "host,topoext";
|
||||
smp = {
|
||||
cpus = 12;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 40960;
|
||||
networks.vms.mac = "52:54:00:75:78:a8";
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [
|
||||
(mkMerge [ (vm.disk "git" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "git" "nix")
|
||||
(vm.disk "git" "persist")
|
||||
(vm.disk "git" "oci")
|
||||
|
||||
(vm.lvmDisk "git")
|
||||
(vm.lvmDisk "gitea-actions-cache")
|
||||
];
|
||||
};
|
||||
|
||||
mail = {
|
||||
uuid = "fd95fe0f-c204-4dd5-b16f-2b808e14a43a";
|
||||
cpu = "host,topoext";
|
||||
@@ -185,15 +176,15 @@
|
||||
cpus = 3;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 6144;
|
||||
memory = 8192;
|
||||
networks.public = {
|
||||
bridge = null;
|
||||
mac = "52:54:00:a8:d1:03";
|
||||
};
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [
|
||||
(mkMerge [ (vm.disk "mail" "root") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "mail" "data")
|
||||
(mkMerge [ (vmLVM "mail" "root") { frontendOpts.bootindex = 0; } ])
|
||||
(vmLVM "mail" "data")
|
||||
];
|
||||
};
|
||||
|
||||
@@ -211,9 +202,8 @@
|
||||
};
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [
|
||||
(mkMerge [ (vm.disk "darts" "root") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.lvmDisk' "media" "darts-media")
|
||||
(vm.lvmDisk' "ext" "darts-ext")
|
||||
(mkMerge [ (vmLVM "darts" "root") { frontendOpts.bootindex = 0; } ])
|
||||
(lvmDisk' "media" "darts-media")
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
@@ -8,32 +8,28 @@ in
|
||||
{
|
||||
config = {
|
||||
services = {
|
||||
bird = {
|
||||
bird2 = {
|
||||
enable = true;
|
||||
package = pkgs.bird2;
|
||||
# TODO: Clean up and modularise
|
||||
config = ''
|
||||
define OWNAS = 211024;
|
||||
|
||||
define CCVIP1 = ${lib.my.c.colony.prefixes.vip1};
|
||||
define CCVIP2 = ${lib.my.c.colony.prefixes.vip2};
|
||||
define CCVIP3 = ${lib.my.c.colony.prefixes.vip3};
|
||||
|
||||
define OWNIP4 = ${assignments.internal.ipv4.address};
|
||||
define OWNNETSET4 = [ ${assignments.internal.ipv4.address}/32 ];
|
||||
define CCNETSET4 = [ ${lib.my.c.colony.prefixes.vip1}, ${lib.my.c.colony.prefixes.vip2}, ${lib.my.c.colony.prefixes.vip3} ];
|
||||
define CCNETSET4 = [ ${lib.my.c.colony.prefixes.vip1}, ${lib.my.c.colony.prefixes.vip2} ];
|
||||
|
||||
define INTNET6 = ${intnet6};
|
||||
define AMSNET6 = ${amsnet6};
|
||||
define HOMENET6 = ${homenet6};
|
||||
|
||||
define OWNIP6 = ${assignments.base.ipv6.address};
|
||||
# we have issues with sending ICMPv6 too big back on the wrong interface right now...
|
||||
define OWNNETSET6 = [ ${intnet6}, ${amsnet6} ];
|
||||
define CCNETSET6 = [ ];
|
||||
define OWNNETSET6 = [ ${intnet6}, ${amsnet6}, ${homenet6} ];
|
||||
#define TRANSSET6 = [ ::1/128 ];
|
||||
|
||||
define DUB1IP6 = ${lib.my.c.home.vips.as211024.v6};
|
||||
define DUB1IP6 = 2a0e:97c0:4df:0:2::1;
|
||||
|
||||
define PREFIXP = 110;
|
||||
define PREFPEER = 120;
|
||||
@@ -45,7 +41,7 @@ in
|
||||
if net ~ OWNNETSET4 || net ~ OWNNETSET6 then accept; else reject;
|
||||
}
|
||||
filter bgp_export_cc {
|
||||
if net ~ OWNNETSET4 || net ~ OWNNETSET6 || net ~ CCNETSET4 || net ~ CCNETSET6 then accept; else reject;
|
||||
if net ~ OWNNETSET4 || net ~ OWNNETSET6 || net ~ CCNETSET4 then accept; else reject;
|
||||
}
|
||||
|
||||
router id from "wan";
|
||||
@@ -59,7 +55,6 @@ in
|
||||
protocol static static4 {
|
||||
route CCVIP1 via "base";
|
||||
route CCVIP2 via "base";
|
||||
route CCVIP3 via "base";
|
||||
|
||||
ipv4 {
|
||||
import all;
|
||||
@@ -191,12 +186,10 @@ in
|
||||
protocol bgp upstream6_coloclue_eun2 from upstream_bgp6 {
|
||||
description "ColoClue euNetworks 2 (IPv6)";
|
||||
neighbor 2a02:898:0:20::e2 as 8283;
|
||||
ipv6 { export filter bgp_export_cc; };
|
||||
}
|
||||
protocol bgp upstream6_coloclue_eun3 from upstream_bgp6 {
|
||||
description "ColoClue euNetworks 3 (IPv6)";
|
||||
neighbor 2a02:898:0:20::e1 as 8283;
|
||||
ipv6 { export filter bgp_export_cc; };
|
||||
}
|
||||
|
||||
protocol bgp upstream6_ifog from upstream_bgp6 {
|
||||
@@ -209,15 +202,14 @@ in
|
||||
neighbor 2001:7f8:10f::1b1b:154 as 6939;
|
||||
}
|
||||
|
||||
# Not working so well lately...
|
||||
# protocol bgp upstream4_fogixp_efero from upstream_bgp4 {
|
||||
# description "efero transit (on FogIXP, IPv4)";
|
||||
# neighbor 185.1.147.107 as 208431;
|
||||
# }
|
||||
# protocol bgp upstream6_fogixp_efero from upstream_bgp6 {
|
||||
# description "efero transit (on FogIXP, IPv6)";
|
||||
# neighbor 2001:7f8:ca:1::107 as 208431;
|
||||
# }
|
||||
protocol bgp upstream4_fogixp_efero from upstream_bgp4 {
|
||||
description "efero transit (on FogIXP, IPv4)";
|
||||
neighbor 185.1.147.107 as 208431;
|
||||
}
|
||||
protocol bgp upstream6_fogixp_efero from upstream_bgp6 {
|
||||
description "efero transit (on FogIXP, IPv6)";
|
||||
neighbor 2001:7f8:ca:1::107 as 208431;
|
||||
}
|
||||
|
||||
protocol bgp peer4_cc_luje from peer_bgp4 {
|
||||
description "LUJE.net (on ColoClue, IPv4)";
|
||||
@@ -233,71 +225,59 @@ in
|
||||
neighbor 2a07:cd40:1::9 as 202413;
|
||||
}
|
||||
|
||||
protocol bgp ixp4_frysix_rs3 from ixp_bgp4 {
|
||||
description "Frys-IX route server 3 (IPv4)";
|
||||
neighbor 185.1.160.255 as 56393;
|
||||
protocol bgp ixp4_frysix_rs1 from ixp_bgp4 {
|
||||
description "Frys-IX route server 1 (IPv4)";
|
||||
neighbor 185.1.203.253 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 ixp6_frysix_rs1 from ixp_bgp6 {
|
||||
description "Frys-IX route server 1 (IPv6)";
|
||||
neighbor 2001:7f8:10f::dc49:253 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 ixp4_frysix_rs2 from ixp_bgp4 {
|
||||
description "Frys-IX route server 2 (IPv4)";
|
||||
neighbor 185.1.203.254 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 ixp6_frysix_rs2 from ixp_bgp6 {
|
||||
description "Frys-IX route server 2 (IPv6)";
|
||||
neighbor 2001:7f8:10f::dc49:254 as 56393;
|
||||
}
|
||||
|
||||
protocol bgp peer4_frysix_luje from peer_bgp4 {
|
||||
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 {
|
||||
description "LUJE.net (on Frys-IX, IPv6)";
|
||||
neighbor 2001:7f8:10f::3:3f95:152 as 212855;
|
||||
}
|
||||
|
||||
protocol bgp peer4_frysix_he from peer_bgp4 {
|
||||
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_cloudflare1 from peer_bgp4 {
|
||||
description "Cloudflare 1 (on Frys-IX, IPv4)";
|
||||
neighbor 185.1.160.217 as 13335;
|
||||
protocol bgp peer4_frysix_cloudflare from peer_bgp4 {
|
||||
description "Cloudflare (on Frys-IX, IPv4)";
|
||||
neighbor 185.1.203.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)";
|
||||
protocol bgp peer6_frysix_cloudflare from peer_bgp6 {
|
||||
description "Cloudflare (on Frys-IX, IPv6)";
|
||||
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 {
|
||||
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 {
|
||||
description "AS212635 aka jurrian (on Frys-IX, IPv6)";
|
||||
neighbor 2001:7f8:10f::3:3e9b:134 as 212635;
|
||||
}
|
||||
|
||||
protocol bgp peer4_frysix_meta1 from peer_bgp4 {
|
||||
description "Meta 1 (on Frys-IX, IPv4)";
|
||||
neighbor 185.1.160.225 as 32934;
|
||||
neighbor 185.1.203.225 as 32934;
|
||||
}
|
||||
protocol bgp peer4_frysix_meta2 from peer_bgp4 {
|
||||
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 {
|
||||
description "Meta 1 (on Frys-IX, IPv6)";
|
||||
@@ -330,36 +310,36 @@ in
|
||||
ipv6 { preference (PREFIXP-1); };
|
||||
}
|
||||
|
||||
# protocol bgp peer4_nlix_cloudflare1 from peer_bgp4 {
|
||||
# description "Cloudflare NL-ix 1 (IPv4)";
|
||||
# neighbor 193.239.117.14 as 13335;
|
||||
# ipv4 { preference (PREFPEER-1); };
|
||||
# }
|
||||
# protocol bgp peer4_nlix_cloudflare2 from peer_bgp4 {
|
||||
# description "Cloudflare NL-ix 2 (IPv4)";
|
||||
# neighbor 193.239.117.114 as 13335;
|
||||
# ipv4 { preference (PREFPEER-1); };
|
||||
# }
|
||||
# protocol bgp peer4_nlix_cloudflare3 from peer_bgp4 {
|
||||
# description "Cloudflare NL-ix 3 (IPv4)";
|
||||
# neighbor 193.239.118.138 as 13335;
|
||||
# ipv4 { preference (PREFPEER-1); };
|
||||
# }
|
||||
# protocol bgp peer6_nlix_cloudflare1 from peer_bgp6 {
|
||||
# description "Cloudflare NL-ix 1 (IPv6)";
|
||||
# neighbor 2001:7f8:13::a501:3335:1 as 13335;
|
||||
# ipv6 { preference (PREFPEER-1); };
|
||||
# }
|
||||
# protocol bgp peer6_nlix_cloudflare2 from peer_bgp6 {
|
||||
# description "Cloudflare NL-ix 2 (IPv6)";
|
||||
# neighbor 2001:7f8:13::a501:3335:2 as 13335;
|
||||
# ipv6 { preference (PREFPEER-1); };
|
||||
# }
|
||||
# protocol bgp peer6_nlix_cloudflare3 from peer_bgp6 {
|
||||
# description "Cloudflare NL-ix 3 (IPv6)";
|
||||
# neighbor 2001:7f8:13::a501:3335:3 as 13335;
|
||||
# ipv6 { preference (PREFPEER-1); };
|
||||
# }
|
||||
protocol bgp peer4_nlix_cloudflare1 from peer_bgp4 {
|
||||
description "Cloudflare NL-ix 1 (IPv4)";
|
||||
neighbor 193.239.117.14 as 13335;
|
||||
ipv4 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer4_nlix_cloudflare2 from peer_bgp4 {
|
||||
description "Cloudflare NL-ix 2 (IPv4)";
|
||||
neighbor 193.239.117.114 as 13335;
|
||||
ipv4 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer4_nlix_cloudflare3 from peer_bgp4 {
|
||||
description "Cloudflare NL-ix 3 (IPv4)";
|
||||
neighbor 193.239.118.138 as 13335;
|
||||
ipv4 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer6_nlix_cloudflare1 from peer_bgp6 {
|
||||
description "Cloudflare NL-ix 1 (IPv6)";
|
||||
neighbor 2001:7f8:13::a501:3335:1 as 13335;
|
||||
ipv6 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer6_nlix_cloudflare2 from peer_bgp6 {
|
||||
description "Cloudflare NL-ix 2 (IPv6)";
|
||||
neighbor 2001:7f8:13::a501:3335:2 as 13335;
|
||||
ipv6 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer6_nlix_cloudflare3 from peer_bgp6 {
|
||||
description "Cloudflare NL-ix 3 (IPv6)";
|
||||
neighbor 2001:7f8:13::a501:3335:3 as 13335;
|
||||
ipv6 { preference (PREFPEER-1); };
|
||||
}
|
||||
protocol bgp peer4_nlix_jurrian from peer_bgp4 {
|
||||
description "AS212635 aka jurrian (on NL-ix, IPv4)";
|
||||
neighbor 193.239.117.55 as 212635;
|
||||
|
||||
@@ -1,22 +1,19 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (builtins) elemAt;
|
||||
inherit (lib.my) net mkVLAN;
|
||||
inherit (lib.my.c.colony) pubV4 domain prefixes firewallForwards;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
|
||||
pubV4 = "94.142.240.44";
|
||||
in
|
||||
{
|
||||
nixos = {
|
||||
vpns = {
|
||||
l2 = {
|
||||
as211024 = {
|
||||
udpEncapsulation = true;
|
||||
vni = 211024;
|
||||
security.enable = true;
|
||||
peers = {
|
||||
estuary.addr = pubV4;
|
||||
river.addr = elemAt lib.my.c.home.routersPubV4 0;
|
||||
stream.addr = elemAt lib.my.c.home.routersPubV4 1;
|
||||
britway.addr = lib.my.c.britway.pubV4;
|
||||
home.addr = "188.141.75.2";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -56,10 +53,10 @@ in
|
||||
};
|
||||
as211024 = {
|
||||
ipv4 = {
|
||||
address = net.cidr.host 1 prefixes.as211024.v4;
|
||||
address = "10.255.3.1";
|
||||
gateway = null;
|
||||
};
|
||||
ipv6.address = net.cidr.host 1 prefixes.as211024.v6;
|
||||
ipv6.address = "2a0e:97c0:4df:0:3::1";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -67,7 +64,6 @@ in
|
||||
let
|
||||
inherit (lib) flatten mkIf mkMerge mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
inherit (lib.my.c) networkd;
|
||||
in
|
||||
{
|
||||
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ./dns.nix ./bgp.nix ];
|
||||
@@ -94,7 +90,6 @@ in
|
||||
environment = {
|
||||
systemPackages = with pkgs; [
|
||||
ethtool
|
||||
conntrack-tools
|
||||
wireguard-tools
|
||||
];
|
||||
};
|
||||
@@ -104,9 +99,11 @@ in
|
||||
lvm = {
|
||||
dmeventd.enable = true;
|
||||
};
|
||||
resolved.settings.Resolve = {
|
||||
LLMNR = false;
|
||||
MulticastDNS = false;
|
||||
resolved = {
|
||||
llmnr = "false";
|
||||
extraConfig = ''
|
||||
MulticastDNS=false
|
||||
'';
|
||||
};
|
||||
netdata.enable = true;
|
||||
|
||||
@@ -117,19 +114,34 @@ in
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services =
|
||||
let
|
||||
waitOnline = "systemd-networkd-wait-online@wan.service";
|
||||
in
|
||||
{
|
||||
bird2 = {
|
||||
services = {
|
||||
# Use this as a way to make sure the router always knows we're here (NDP seems kindy funky)
|
||||
ipv6-neigh-keepalive =
|
||||
let
|
||||
waitOnline = "systemd-networkd-wait-online@wan.service";
|
||||
in
|
||||
{
|
||||
description = "Frequent ICMP6 neighbour solicitations";
|
||||
enable = false;
|
||||
requires = [ waitOnline ];
|
||||
after = [ waitOnline ];
|
||||
script = ''
|
||||
while true; do
|
||||
${pkgs.ndisc6}/bin/ndisc6 ${assignments.internal.ipv6.gateway} wan
|
||||
sleep 10
|
||||
done
|
||||
'';
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
|
||||
bird2 =
|
||||
let
|
||||
waitOnline = "systemd-networkd-wait-online@wan.service";
|
||||
in
|
||||
{
|
||||
after = [ waitOnline ];
|
||||
# requires = [ waitOnline ];
|
||||
};
|
||||
ipsec = {
|
||||
after = [ waitOnline ];
|
||||
requires = [ waitOnline ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -142,7 +154,19 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
netdevs = mkMerge [
|
||||
netdevs =
|
||||
let
|
||||
mkVLAN = name: vid: {
|
||||
"25-${name}" = {
|
||||
netdevConfig = {
|
||||
Name = name;
|
||||
Kind = "vlan";
|
||||
};
|
||||
vlanConfig.Id = vid;
|
||||
};
|
||||
};
|
||||
in
|
||||
mkMerge [
|
||||
(mkVLAN "ifog" 409)
|
||||
|
||||
(mkVLAN "frys-ix" 701)
|
||||
@@ -162,47 +186,11 @@ in
|
||||
};
|
||||
wireguardPeers = [
|
||||
{
|
||||
PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E=";
|
||||
AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ];
|
||||
PersistentKeepalive = 25;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
{
|
||||
"30-hillcrest" = {
|
||||
netdevConfig = {
|
||||
Name = "hillcrest";
|
||||
Kind = "wireguard";
|
||||
};
|
||||
wireguardConfig = {
|
||||
PrivateKeyFile = config.age.secrets."estuary/hillcrest-wg.key".path;
|
||||
ListenPort = lib.my.c.hillcrest.vpn.port;
|
||||
};
|
||||
wireguardPeers = [
|
||||
{
|
||||
PublicKey = "+67Ks+ZRk1ssNCfg5BFKmIE9NtLasAxRE6XMqufx5GY=";
|
||||
AllowedIPs = [ (net.cidr.host 2 prefixes.hillcrest.v4) ];
|
||||
PersistentKeepalive = 25;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
{
|
||||
"30-john-valorant" = {
|
||||
netdevConfig = {
|
||||
Name = "john-valorant";
|
||||
Kind = "wireguard";
|
||||
};
|
||||
wireguardConfig = {
|
||||
PrivateKeyFile = config.age.secrets."estuary/john-valorant-wg.key".path;
|
||||
ListenPort = lib.my.c.john-valorant.vpn.port;
|
||||
};
|
||||
wireguardPeers = [
|
||||
{
|
||||
PublicKey = "xyqKF0yOAv1bObN1paL2vATFh77pdFfvN+JmuAxaTCk=";
|
||||
AllowedIPs = [ (net.cidr.host 2 prefixes.john-valorant.v4) ];
|
||||
PersistentKeepalive = 25;
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = "7N9YdQaCMWWIwAnW37vrthm9ZpbnG4Lx3gheHeRYz2E=";
|
||||
AllowedIPs = [ allAssignments.kelder.estuary.ipv4.address ];
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -254,7 +242,7 @@ in
|
||||
in
|
||||
mkMerge
|
||||
[
|
||||
(mkIXPConfig "frys-ix" "185.1.160.196/23" "2001:7f8:10f::3:3850:196/64")
|
||||
(mkIXPConfig "frys-ix" "185.1.203.196/24" "2001:7f8:10f::3:3850:196/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")
|
||||
{
|
||||
@@ -283,7 +271,13 @@ in
|
||||
Kind = "vlan";
|
||||
};
|
||||
vlan = [ "frys-ix" "nl-ix" "fogixp" "ifog-transit" ];
|
||||
networkConfig = networkd.noL3;
|
||||
networkConfig = {
|
||||
LinkLocalAddressing = "no";
|
||||
DHCP = "no";
|
||||
LLDP = false;
|
||||
EmitLLDP = false;
|
||||
IPv6AcceptRA = false;
|
||||
};
|
||||
};
|
||||
"85-ifog-transit" = {
|
||||
matchConfig.Name = "ifog-transit";
|
||||
@@ -312,93 +306,53 @@ in
|
||||
};
|
||||
ipv6Prefixes = [
|
||||
{
|
||||
Prefix = prefixes.base.v6;
|
||||
ipv6PrefixConfig.Prefix = prefixes.base.v6;
|
||||
}
|
||||
];
|
||||
routes = flatten ([
|
||||
{
|
||||
Destination = prefixes.vip1;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.vip3;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.darts.v4;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.cust.v6;
|
||||
Gateway = allAssignments.colony.internal.ipv6.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v4;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v6;
|
||||
Gateway = allAssignments.colony.internal.ipv6.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = prefixes.qclk.v4;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
] ++
|
||||
(map (pName: [
|
||||
{
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
Destination = prefixes."${pName}".v4;
|
||||
}
|
||||
{
|
||||
Destination = prefixes."${pName}".v6;
|
||||
Gateway = allAssignments.colony.internal.ipv6.address;
|
||||
}
|
||||
]) [ "vms" "ctrs" "oci" ]));
|
||||
routes = map (r: { routeConfig = r; }) (flatten
|
||||
([
|
||||
{
|
||||
Destination = prefixes.vip1;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.darts.v4;
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = prefixes.cust.v6;
|
||||
Gateway = allAssignments.colony.internal.ipv6.address;
|
||||
}
|
||||
] ++
|
||||
(map (pName: [
|
||||
{
|
||||
Gateway = allAssignments.colony.routing.ipv4.address;
|
||||
Destination = prefixes."${pName}".v4;
|
||||
}
|
||||
{
|
||||
Destination = prefixes."${pName}".v6;
|
||||
Gateway = allAssignments.colony.internal.ipv6.address;
|
||||
}
|
||||
]) [ "vms" "ctrs" "oci" ])));
|
||||
}
|
||||
];
|
||||
|
||||
"90-l2mesh-as211024" = mkMerge [
|
||||
(networkdAssignment "as211024" assignments.as211024)
|
||||
{
|
||||
matchConfig.Name = "as211024";
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
routes = [
|
||||
{
|
||||
Destination = lib.my.c.home.prefixes.all.v4;
|
||||
Gateway = lib.my.c.home.vips.as211024.v4;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
"90-l2mesh-as211024" = {
|
||||
matchConfig.Name = "as211024";
|
||||
address = with assignments.as211024; [
|
||||
(with ipv4; "${address}/${toString mask}")
|
||||
(with ipv6; "${address}/${toString mask}")
|
||||
];
|
||||
networkConfig.IPv6AcceptRA = false;
|
||||
};
|
||||
"95-kelder" = {
|
||||
matchConfig.Name = "kelder";
|
||||
routes = [
|
||||
{
|
||||
Destination = allAssignments.kelder.estuary.ipv4.address;
|
||||
Scope = "link";
|
||||
}
|
||||
];
|
||||
};
|
||||
"95-hillcrest" = {
|
||||
matchConfig.Name = "hillcrest";
|
||||
address = [ "${net.cidr.host 1 prefixes.hillcrest.v4}/32" ];
|
||||
routes = [
|
||||
{
|
||||
Destination = net.cidr.host 2 prefixes.hillcrest.v4;
|
||||
Scope = "link";
|
||||
}
|
||||
];
|
||||
};
|
||||
"95-john-valorant" = {
|
||||
matchConfig.Name = "john-valorant";
|
||||
address = [ "${net.cidr.host 1 prefixes.john-valorant.v4}/32" ];
|
||||
routes = [
|
||||
{
|
||||
Destination = net.cidr.host 2 prefixes.john-valorant.v4;
|
||||
Scope = "link";
|
||||
routeConfig = {
|
||||
Destination = allAssignments.kelder.estuary.ipv4.address;
|
||||
Scope = "link";
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -412,35 +366,43 @@ in
|
||||
"estuary/kelder-wg.key" = {
|
||||
owner = "systemd-network";
|
||||
};
|
||||
"estuary/hillcrest-wg.key" = {
|
||||
owner = "systemd-network";
|
||||
};
|
||||
"estuary/john-valorant-wg.key" = {
|
||||
owner = "systemd-network";
|
||||
};
|
||||
"l2mesh/as211024.key" = {};
|
||||
};
|
||||
};
|
||||
server.enable = true;
|
||||
|
||||
vpns = {
|
||||
l2.pskFiles = {
|
||||
as211024 = config.age.secrets."l2mesh/as211024.key".path;
|
||||
};
|
||||
};
|
||||
firewall = {
|
||||
udp.allowed = [
|
||||
5353
|
||||
|
||||
lib.my.c.kelder.vpn.port
|
||||
lib.my.c.hillcrest.vpn.port
|
||||
lib.my.c.john-valorant.vpn.port
|
||||
];
|
||||
trustedInterfaces = [ "as211024" ];
|
||||
udp.allowed = [ 5353 lib.my.c.kelder.vpn.port ];
|
||||
tcp.allowed = [ 5353 "bgp" ];
|
||||
nat = {
|
||||
enable = true;
|
||||
externalInterface = "wan";
|
||||
forwardPorts."${assignments.internal.ipv4.address}" = firewallForwards allAssignments;
|
||||
externalIP = assignments.internal.ipv4.address;
|
||||
forwardPorts = [
|
||||
{
|
||||
port = "http";
|
||||
dst = allAssignments.middleman.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = "https";
|
||||
dst = allAssignments.middleman.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
port = 8448;
|
||||
dst = allAssignments.middleman.internal.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
port = 2456;
|
||||
dst = allAssignments.valheim-oci.internal.ipv4.address;
|
||||
proto = "udp";
|
||||
}
|
||||
{
|
||||
port = 2457;
|
||||
dst = allAssignments.valheim-oci.internal.ipv4.address;
|
||||
proto = "udp";
|
||||
}
|
||||
];
|
||||
};
|
||||
extraRules =
|
||||
let
|
||||
@@ -462,28 +424,12 @@ in
|
||||
# Safe enough to allow all SSH
|
||||
tcp dport ssh accept
|
||||
|
||||
# jam-ctr forwards
|
||||
ip daddr ${aa.shill.internal.ipv4.address} tcp dport 60022 accept
|
||||
${matchInet "tcp dport { http, https, 8448 } accept" "middleman"}
|
||||
${matchInet "udp dport { 2456-2457 } accept" "valheim-oci"}
|
||||
|
||||
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
|
||||
ip6 daddr ${aa.graeme-oci.internal.ipv6.address} tcp dport 25569 accept
|
||||
ip6 daddr ${aa.gam.internal.ipv6.address} tcp dport 7777 accept
|
||||
return
|
||||
}
|
||||
chain routing-udp {
|
||||
ip6 daddr ${aa.valheim-oci.internal.ipv6.address} udp dport { 2456-2457 } accept
|
||||
ip6 daddr ${aa.waffletail.internal.ipv6.address} udp dport 41641 accept
|
||||
ip6 daddr ${aa.simpcraft-oci.internal.ipv6.address} udp dport 25565 accept
|
||||
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
|
||||
ip6 daddr ${aa.graeme-oci.internal.ipv6.address} udp dport 25569 accept
|
||||
ip6 daddr ${aa.gam.internal.ipv6.address} udp dport 7777 accept
|
||||
return
|
||||
}
|
||||
chain filter-routing {
|
||||
@@ -500,11 +446,10 @@ in
|
||||
}
|
||||
|
||||
chain forward {
|
||||
${lib.my.c.as211024.nftTrust}
|
||||
iifname { wan, as211024, $ixps } oifname base jump filter-routing
|
||||
iifname { wan, $ixps } oifname base jump filter-routing
|
||||
oifname $ixps jump ixp
|
||||
iifname base oifname { base, wan, $ixps } accept
|
||||
oifname { as211024, kelder, hillcrest, john-valorant } accept
|
||||
iifname base oifname { wan, $ixps } accept
|
||||
oifname { as211024, kelder } accept
|
||||
}
|
||||
chain output {
|
||||
oifname ifog ether type != vlan reject
|
||||
@@ -514,11 +459,11 @@ in
|
||||
table inet nat {
|
||||
chain prerouting {
|
||||
${matchInet "meta l4proto { udp, tcp } th dport domain redirect to :5353" "estuary"}
|
||||
ip daddr ${allAssignments.shill.internal.ipv4.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv4.address}
|
||||
ip6 daddr ${allAssignments.shill.internal.ipv6.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv6.address}
|
||||
}
|
||||
chain postrouting {
|
||||
oifname hillcrest snat ip to ${net.cidr.host 1 prefixes.hillcrest.v4}
|
||||
oifname john-valorant snat ip to ${net.cidr.host 1 prefixes.john-valorant.v4}
|
||||
ip saddr ${prefixes.all.v4} oifname != as211024 snat to ${assignments.internal.ipv4.address}
|
||||
ip saddr ${prefixes.all.v4} snat to ${assignments.internal.ipv4.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let
|
||||
inherit (builtins) attrNames;
|
||||
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;
|
||||
in
|
||||
@@ -14,7 +14,7 @@ in
|
||||
owner = "pdns";
|
||||
group = "pdns";
|
||||
};
|
||||
"estuary/pdns/recursor.yml" = {
|
||||
"estuary/pdns/recursor.conf" = {
|
||||
owner = "pdns-recursor";
|
||||
group = "pdns-recursor";
|
||||
};
|
||||
@@ -31,7 +31,7 @@ in
|
||||
|
||||
pdns.recursor = {
|
||||
enable = true;
|
||||
extraSettingsFile = config.age.secrets."estuary/pdns/recursor.yml".path;
|
||||
extraSettingsFile = config.age.secrets."estuary/pdns/recursor.conf".path;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -44,55 +44,45 @@ in
|
||||
};
|
||||
|
||||
pdns-recursor = {
|
||||
yaml-settings = {
|
||||
incoming = {
|
||||
listen = [
|
||||
"127.0.0.1" "::1"
|
||||
assignments.base.ipv4.address assignments.base.ipv6.address
|
||||
];
|
||||
allow_from = [
|
||||
"127.0.0.0/8" "::1/128"
|
||||
prefixes.all.v4 prefixes.all.v6
|
||||
] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]);
|
||||
dns = {
|
||||
address = [
|
||||
"127.0.0.1" "::1"
|
||||
assignments.base.ipv4.address assignments.base.ipv6.address
|
||||
];
|
||||
allowFrom = [
|
||||
"127.0.0.0/8" "::1/128"
|
||||
prefixes.all.v4 prefixes.all.v6
|
||||
];
|
||||
};
|
||||
|
||||
# DNS NOTIFY messages override TTL
|
||||
allow_notify_for = authZones;
|
||||
allow_notify_from = [ "127.0.0.0/8" "::1/128" ];
|
||||
};
|
||||
settings = {
|
||||
query-local-address = [
|
||||
assignments.internal.ipv4.address
|
||||
assignments.internal.ipv6.address
|
||||
assignments.base.ipv6.address
|
||||
];
|
||||
forward-zones = map (z: "${z}=127.0.0.1:5353") authZones;
|
||||
|
||||
outgoing = {
|
||||
source_address = [
|
||||
assignments.internal.ipv4.address
|
||||
assignments.internal.ipv6.address
|
||||
assignments.base.ipv6.address
|
||||
];
|
||||
};
|
||||
# DNS NOTIFY messages override TTL
|
||||
allow-notify-for = authZones;
|
||||
allow-notify-from = [ "127.0.0.0/8" "::1/128" ];
|
||||
|
||||
recursor = {
|
||||
forward_zones = map (z: {
|
||||
zone = z;
|
||||
forwarders = [ "127.0.0.1:5353" ];
|
||||
}) authZones;
|
||||
webserver = true;
|
||||
webserver-address = "::";
|
||||
webserver-allow-from = [ "127.0.0.1" "::1" ];
|
||||
|
||||
lua_dns_script = pkgs.writeText "pdns-script.lua" ''
|
||||
function preresolve(dq)
|
||||
if dq.qname:equal("nix-cache.nul.ie") then
|
||||
dq:addAnswer(pdns.CNAME, "http.${config.networking.domain}.")
|
||||
dq.rcode = 0
|
||||
dq.followupFunction = "followCNAMERecords"
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
lua-dns-script = pkgs.writeText "pdns-script.lua" ''
|
||||
function preresolve(dq)
|
||||
if dq.qname:equal("nix-cache.nul.ie") then
|
||||
dq:addAnswer(pdns.CNAME, "http.${config.networking.domain}.")
|
||||
dq.rcode = 0
|
||||
dq.followupFunction = "followCNAMERecords"
|
||||
return true
|
||||
end
|
||||
'';
|
||||
};
|
||||
|
||||
webservice = {
|
||||
webserver = true;
|
||||
address = "::";
|
||||
allow_from = [ "127.0.0.1" "::1" ];
|
||||
};
|
||||
return false
|
||||
end
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -155,23 +145,9 @@ in
|
||||
|
||||
http IN A ${assignments.internal.ipv4.address}
|
||||
http IN AAAA ${allAssignments.middleman.internal.ipv6.address}
|
||||
librespeed IN CNAME http.${config.networking.domain}.
|
||||
|
||||
valheim IN A ${assignments.internal.ipv4.address}
|
||||
valheim IN AAAA ${allAssignments.valheim-oci.internal.ipv6.address}
|
||||
simpcraft IN A ${assignments.internal.ipv4.address}
|
||||
simpcraft IN AAAA ${allAssignments.simpcraft-oci.internal.ipv6.address}
|
||||
simpcraft-staging IN A ${assignments.internal.ipv4.address}
|
||||
simpcraft-staging IN AAAA ${allAssignments.simpcraft-staging-oci.internal.ipv6.address}
|
||||
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}
|
||||
graeme IN A ${assignments.internal.ipv4.address}
|
||||
graeme IN AAAA ${allAssignments.graeme-oci.internal.ipv6.address}
|
||||
terraria IN A ${assignments.internal.ipv4.address}
|
||||
terraria IN AAAA ${allAssignments.gam.internal.ipv6.address}
|
||||
|
||||
mail-vm IN A ${net.cidr.host 0 prefixes.mail.v4}
|
||||
mail-vm IN AAAA ${net.cidr.host 1 prefixes.mail.v6}
|
||||
@@ -181,13 +157,6 @@ in
|
||||
|
||||
andrey-cust IN A ${allAssignments.kelder.estuary.ipv4.address}
|
||||
|
||||
jam-cust IN A ${net.cidr.host 0 prefixes.jam.v4}
|
||||
jam-fwd IN A ${allAssignments.shill.internal.ipv4.address}
|
||||
jam-cust IN AAAA ${net.cidr.host 1 prefixes.jam.v6}
|
||||
|
||||
hillcrest-tun IN A ${net.cidr.host 2 prefixes.hillcrest.v4}
|
||||
john-valorant-tun IN A ${net.cidr.host 2 prefixes.john-valorant.v4}
|
||||
|
||||
$TTL 3
|
||||
_acme-challenge IN LUA TXT @@FILE@@
|
||||
|
||||
|
||||
@@ -1,214 +0,0 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (builtins) mapAttrs;
|
||||
inherit (lib) mkMerge mkDefault;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.colony) domain prefixes firewallForwards;
|
||||
inherit (lib.my.c.nginx) baseHttpConfig proxyHeaders;
|
||||
in
|
||||
{
|
||||
nixos.systems.git = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
|
||||
assignments = {
|
||||
routing = {
|
||||
name = "git-vm-routing";
|
||||
inherit domain;
|
||||
ipv4.address = net.cidr.host 4 prefixes.vms.v4;
|
||||
};
|
||||
internal = {
|
||||
name = "git-vm";
|
||||
inherit domain;
|
||||
ipv4 = {
|
||||
address = net.cidr.host 0 prefixes.vip3;
|
||||
mask = 32;
|
||||
gateway = null;
|
||||
genPTR = false;
|
||||
};
|
||||
ipv6 = {
|
||||
iid = "::4";
|
||||
address = net.cidr.host 4 prefixes.vms.v6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/profiles/qemu-guest.nix"
|
||||
|
||||
./gitea.nix
|
||||
./gitea-actions.nix
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
boot = {
|
||||
kernelParams = [ "console=ttyS0,115200n8" ];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-label/ESP";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-label/nix";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/disk/by-label/persist";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
|
||||
"/var/lib/containers" = {
|
||||
device = "/dev/disk/by-label/oci";
|
||||
fsType = "xfs";
|
||||
options = [ "pquota" ];
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
users = {
|
||||
nginx.extraGroups = [ "acme" ];
|
||||
};
|
||||
};
|
||||
|
||||
security.acme = {
|
||||
acceptTerms = true;
|
||||
defaults = {
|
||||
email = "dev@nul.ie";
|
||||
server = "https://acme-v02.api.letsencrypt.org/directory";
|
||||
reloadServices = [ "nginx" ];
|
||||
dnsResolver = "8.8.8.8";
|
||||
};
|
||||
certs = {
|
||||
"${pubDomain}" = {
|
||||
extraDomainNames = [
|
||||
"*.${pubDomain}"
|
||||
];
|
||||
dnsProvider = "cloudflare";
|
||||
credentialsFile = config.age.secrets."middleman/cloudflare-credentials.conf".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
fstrim = lib.my.c.colony.fstrimConfig;
|
||||
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 = {
|
||||
podman = {
|
||||
enable = true;
|
||||
};
|
||||
oci-containers = {
|
||||
backend = "podman";
|
||||
};
|
||||
containers.containersConf.settings.network.default_subnet = "10.88.0.0/16";
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
links = {
|
||||
"10-vms" = {
|
||||
matchConfig.MACAddress = "52:54:00:75:78:a8";
|
||||
linkConfig.Name = "vms";
|
||||
};
|
||||
};
|
||||
|
||||
networks = {
|
||||
"80-vms" = mkMerge [
|
||||
(networkdAssignment "vms" assignments.routing)
|
||||
(networkdAssignment "vms" assignments.internal)
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP+KINpHLMduBuW96JzfSRDLUzkI+XaCBghu5/wHiW5R";
|
||||
files = {
|
||||
"dhparams.pem" = {
|
||||
owner = "acme";
|
||||
group = "acme";
|
||||
mode = "440";
|
||||
};
|
||||
"middleman/cloudflare-credentials.conf" = {
|
||||
owner = "acme";
|
||||
group = "acme";
|
||||
};
|
||||
};
|
||||
};
|
||||
server.enable = true;
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [ 19999 "http" "https" ];
|
||||
nat.forwardPorts."${allAssignments.estuary.internal.ipv4.address}" = firewallForwards allAssignments;
|
||||
extraRules = ''
|
||||
table inet filter {
|
||||
chain forward {
|
||||
ip saddr 10.88.0.0/16 accept
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -24,7 +24,7 @@ in
|
||||
|
||||
configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) genAttrs mkMerge mkIf mkForce;
|
||||
inherit (lib) mkMerge mkIf mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
@@ -45,22 +45,9 @@ in
|
||||
owner = "matrix-synapse";
|
||||
group = "matrix-synapse";
|
||||
};
|
||||
"chatterbox/doublepuppet.yaml" = {
|
||||
owner = "matrix-synapse";
|
||||
group = "matrix-synapse";
|
||||
};
|
||||
|
||||
"chatterbox/mautrix-whatsapp.env" = {
|
||||
owner = "mautrix-whatsapp";
|
||||
group = "mautrix-whatsapp";
|
||||
};
|
||||
"chatterbox/mautrix-messenger.env" = {
|
||||
owner = "mautrix-meta-messenger";
|
||||
group = "mautrix-meta";
|
||||
};
|
||||
"chatterbox/mautrix-instagram.env" = {
|
||||
owner = "mautrix-meta-instagram";
|
||||
group = "mautrix-meta";
|
||||
"chatterbox/syncv3.env" = {
|
||||
owner = "matrix-syncv3";
|
||||
group = "matrix-syncv3";
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -72,24 +59,29 @@ in
|
||||
|
||||
users = with lib.my.c.ids; {
|
||||
users = {
|
||||
matrix-synapse.extraGroups = [
|
||||
"mautrix-whatsapp"
|
||||
];
|
||||
matrix-syncv3 = {
|
||||
isSystemUser = true;
|
||||
uid = uids.matrix-syncv3;
|
||||
group = "matrix-syncv3";
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
matrix-syncv3.gid = gids.matrix-syncv3;
|
||||
};
|
||||
groups = { };
|
||||
};
|
||||
|
||||
systemd = {
|
||||
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
|
||||
services = { } // (genAttrs [ "mautrix-whatsapp" "mautrix-meta-messenger" "mautrix-meta-instagram" ] (_: {
|
||||
# ffmpeg needed to convert GIFs to video
|
||||
path = with pkgs; [ ffmpeg ];
|
||||
}));
|
||||
services = {
|
||||
matrix-sliding-sync.serviceConfig = {
|
||||
# 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 = {
|
||||
netdata.enable = true;
|
||||
matrix-synapse = {
|
||||
@@ -176,10 +168,18 @@ in
|
||||
|
||||
app_service_config_files = [
|
||||
"/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 = {
|
||||
@@ -195,179 +195,6 @@ in
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
mautrix-whatsapp = {
|
||||
enable = true;
|
||||
package = pkgs.mautrix-whatsapp.overrideAttrs (o: {
|
||||
# TODO: Remove when upgrading nixpkgs
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "mautrix";
|
||||
repo = "whatsapp";
|
||||
tag = "v0.2511.0";
|
||||
hash = "sha256-0Jpod9/mZ9eGFvPxki6Yz0KL1XQ4HTtZ7Zv7WvamuC0=";
|
||||
};
|
||||
vendorHash = "sha256-n25j2uM3e5/5PYs2jwH+iclaU/p/MhctCAhPninz2HI=";
|
||||
});
|
||||
environmentFile = config.age.secrets."chatterbox/mautrix-whatsapp.env".path;
|
||||
settings = {
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "$MAU_WAPP_PSQL_URI";
|
||||
};
|
||||
homeserver = {
|
||||
address = "http://localhost:8008";
|
||||
domain = "nul.ie";
|
||||
};
|
||||
appservice = {
|
||||
id = "whatsapp2";
|
||||
bot = {
|
||||
username = "whatsapp2";
|
||||
displayname = "WhatsApp Bridge Bot";
|
||||
};
|
||||
username_template = "wapp2_{{.}}";
|
||||
};
|
||||
bridge = {
|
||||
personal_filtering_spaces = true;
|
||||
command_prefix = "!wa";
|
||||
permissions = {
|
||||
"@dev:nul.ie" = "admin";
|
||||
};
|
||||
};
|
||||
double_puppet = {
|
||||
secrets."nul.ie" = "$MAU_WAPP_DOUBLE_PUPPET_TOKEN";
|
||||
};
|
||||
encryption = {
|
||||
allow = true;
|
||||
default = true;
|
||||
require = true;
|
||||
pickle_key = "maunium.net/go/mautrix-whatsapp";
|
||||
};
|
||||
matrix = {
|
||||
delivery_receipts = true;
|
||||
};
|
||||
network = {
|
||||
displayname_template = ''{{or .BusinessName .PushName .FullName .Phone "Unknown user"}} (WA)'';
|
||||
url_previews = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# TODO: Remove when upgrading nixpkgs
|
||||
mautrix-meta.package = pkgs.mautrix-meta.overrideAttrs (o: {
|
||||
src = pkgs.fetchFromGitHub {
|
||||
owner = "mautrix";
|
||||
repo = "meta";
|
||||
rev = "v0.2511.0";
|
||||
hash = "sha256-Ke5b1Q1QIB2u5fbDmhvwe/HaZX1oycNSIor/9gdmdWA=";
|
||||
};
|
||||
vendorHash = "sha256-vbXV9xa0Q+Sml21QQZ3YUmPzXgrIZRJx0tQx0O4JcHs=";
|
||||
});
|
||||
mautrix-meta.instances = {
|
||||
messenger = {
|
||||
enable = true;
|
||||
registerToSynapse = true;
|
||||
dataDir = "mautrix-messenger";
|
||||
environmentFile = config.age.secrets."chatterbox/mautrix-messenger.env".path;
|
||||
settings = {
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "$MAU_FBM_PSQL_URI";
|
||||
};
|
||||
homeserver = {
|
||||
address = "http://localhost:8008";
|
||||
domain = "nul.ie";
|
||||
};
|
||||
appservice = {
|
||||
id = "fbm2";
|
||||
bot = {
|
||||
username = "messenger2";
|
||||
displayname = "Messenger Bridge Bot";
|
||||
avatar = "mxc://maunium.net/ygtkteZsXnGJLJHRchUwYWak";
|
||||
};
|
||||
username_template = "fbm2_{{.}}";
|
||||
};
|
||||
network = {
|
||||
mode = "messenger";
|
||||
displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (FBM)'';
|
||||
};
|
||||
bridge = {
|
||||
personal_filtering_spaces = true;
|
||||
# management_room_text.welcome = "Hello, I'm a Messenger bridge bot.";
|
||||
command_prefix = "!fbm";
|
||||
backfill = {
|
||||
enabled = true;
|
||||
};
|
||||
permissions = {
|
||||
"@dev:nul.ie" = "admin";
|
||||
};
|
||||
};
|
||||
double_puppet = {
|
||||
secrets."nul.ie" = "$MAU_FBM_DOUBLE_PUPPET_TOKEN";
|
||||
};
|
||||
encryption = {
|
||||
allow = true;
|
||||
default = true;
|
||||
require = true;
|
||||
};
|
||||
matrix = {
|
||||
delivery_receipts = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
instagram = {
|
||||
enable = true;
|
||||
registerToSynapse = true;
|
||||
dataDir = "mautrix-instagram";
|
||||
environmentFile = config.age.secrets."chatterbox/mautrix-instagram.env".path;
|
||||
settings = {
|
||||
database = {
|
||||
type = "postgres";
|
||||
uri = "$MAU_IG_PSQL_URI";
|
||||
};
|
||||
homeserver = {
|
||||
address = "http://localhost:8008";
|
||||
domain = "nul.ie";
|
||||
};
|
||||
appservice = {
|
||||
id = "instagram";
|
||||
bot = {
|
||||
username = "instagram";
|
||||
displayname = "Instagram Bridge Bot";
|
||||
avatar = "mxc://maunium.net/JxjlbZUlCPULEeHZSwleUXQv";
|
||||
};
|
||||
username_template = "ig_{{.}}";
|
||||
};
|
||||
network = {
|
||||
mode = "instagram";
|
||||
displayname_template = ''{{or .DisplayName .Username "Unknown user"}} (IG)'';
|
||||
};
|
||||
bridge = {
|
||||
personal_filtering_spaces = true;
|
||||
# management_room_text.welcome = "Hello, I'm an Instagram bridge bot.";
|
||||
command_prefix = "!ig";
|
||||
backfill = {
|
||||
enabled = true;
|
||||
};
|
||||
permissions = {
|
||||
"@dev:nul.ie" = "admin";
|
||||
"@adzerq:nul.ie" = "user";
|
||||
};
|
||||
};
|
||||
double_puppet = {
|
||||
secrets."nul.ie" = "$MAU_IG_DOUBLE_PUPPET_TOKEN";
|
||||
};
|
||||
encryption = {
|
||||
allow = true;
|
||||
default = true;
|
||||
require = true;
|
||||
};
|
||||
matrix = {
|
||||
delivery_receipts = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
(mkIf config.my.build.isDevVM {
|
||||
|
||||
@@ -7,8 +7,5 @@
|
||||
./jackflix
|
||||
./object.nix
|
||||
./toot.nix
|
||||
./waffletail.nix
|
||||
./qclk
|
||||
./gam.nix
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1,72 +0,0 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
nixos.systems.gam = { config, ... }: {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
rendered = config.configuration.config.my.asContainer;
|
||||
|
||||
assignments = {
|
||||
internal = {
|
||||
name = "gam-ctr";
|
||||
inherit domain;
|
||||
ipv4.address = net.cidr.host 11 prefixes.ctrs.v4;
|
||||
ipv6 = {
|
||||
iid = "::11";
|
||||
address = net.cidr.host 11 prefixes.ctrs.v6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge mkIf mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
config = mkMerge [
|
||||
{
|
||||
my = {
|
||||
deploy.enable = false;
|
||||
server.enable = true;
|
||||
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIAvDlH3nT1kve741gBluYmn5KQs8yz7FAEt8qLt+f0K6";
|
||||
files = {
|
||||
"gam/terraria.conf" = {
|
||||
owner = "terraria";
|
||||
group = "terraria";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
|
||||
};
|
||||
|
||||
services = {
|
||||
terraria = {
|
||||
enable = true;
|
||||
noUPnP = true;
|
||||
messageOfTheDay = "sup gamers";
|
||||
autoCreatedWorldSize = "large";
|
||||
worldPath = "/var/lib/terraria/NotWorld.wld";
|
||||
configFile = config.age.secrets."gam/terraria.conf".path;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
(mkIf config.my.build.isDevVM {
|
||||
virtualisation = {
|
||||
forwardPorts = [ ];
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,6 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) concatStringsSep;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
@@ -23,7 +21,7 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, config, allAssignments, ... }:
|
||||
configuration = { lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (lib) mkForce;
|
||||
in
|
||||
@@ -37,19 +35,6 @@ in
|
||||
|
||||
secrets = {
|
||||
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;
|
||||
group = "jellyseerr";
|
||||
};
|
||||
photoprism = {
|
||||
isSystemUser = true;
|
||||
uid = uids.photoprism;
|
||||
group = "photoprism";
|
||||
};
|
||||
copyparty = {
|
||||
uid = uids.copyparty;
|
||||
extraGroups = [ "media" ];
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
media.gid = 2000;
|
||||
jellyseerr.gid = gids.jellyseerr;
|
||||
photoprism.gid = gids.photoprism;
|
||||
copyparty.gid = gids.copyparty;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -89,9 +63,7 @@ in
|
||||
transmission.bindsTo = [ "systemd-networkd-wait-online@vpn.service" ];
|
||||
|
||||
radarr.serviceConfig.UMask = "0002";
|
||||
radarr.path = with pkgs; [ ffmpeg ];
|
||||
sonarr.serviceConfig.UMask = "0002";
|
||||
sonarr.path = with pkgs; [ ffmpeg ];
|
||||
jellyseerr.serviceConfig = {
|
||||
# Needs to be able to read its secrets
|
||||
DynamicUser = mkForce false;
|
||||
@@ -104,10 +76,6 @@ in
|
||||
RootDirectoryStartOnly = lib.mkForce false;
|
||||
RootDirectory = lib.mkForce "";
|
||||
};
|
||||
photoprism.serviceConfig = {
|
||||
# Needs to be able to access its data
|
||||
DynamicUser = mkForce false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -116,7 +84,6 @@ in
|
||||
|
||||
transmission = {
|
||||
enable = true;
|
||||
package = pkgs.transmission_4;
|
||||
downloadDirPermissions = null;
|
||||
performanceNetParameters = true;
|
||||
settings = {
|
||||
@@ -141,7 +108,6 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
flaresolverr.enable = true;
|
||||
jackett.enable = true;
|
||||
radarr.enable = true;
|
||||
sonarr.enable = true;
|
||||
@@ -151,68 +117,6 @@ in
|
||||
};
|
||||
|
||||
jellyfin.enable = true;
|
||||
|
||||
photoprism = {
|
||||
enable = true;
|
||||
address = "[::]";
|
||||
port = 2342;
|
||||
originalsPath = "/mnt/media/photoprism/originals";
|
||||
importPath = "/mnt/media/photoprism/import";
|
||||
passwordFile = config.age.secrets."jackflix/photoprism-pass.txt".path;
|
||||
settings = {
|
||||
PHOTOPRISM_AUTH_MODE = "password";
|
||||
PHOTOPRISM_ADMIN_USER = "dev";
|
||||
PHOTOPRISM_APP_NAME = "/dev/player0 Photos";
|
||||
PHOTOPRISM_SITE_URL = "https://photos.${pubDomain}/";
|
||||
PHOTOPRISM_SITE_TITLE = "/dev/player0 Photos";
|
||||
PHOTOPRISM_TRUSTED_PROXY = concatStringsSep "," (with prefixes.ctrs; [ v4 v6 ]);
|
||||
PHOTOPRISM_DATABASE_DRIVER = "sqlite";
|
||||
};
|
||||
};
|
||||
|
||||
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
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -37,7 +37,7 @@ in
|
||||
tcp dport ${toString transmissionPeerPort} accept
|
||||
iifname vpn return
|
||||
|
||||
tcp dport { 19999, 9091, 9117, 7878, 8989, 8096, 2342 } accept
|
||||
tcp dport { 19999, 9091, 9117, 7878, 8989, 8096 } accept
|
||||
return
|
||||
}
|
||||
chain input {
|
||||
@@ -71,12 +71,14 @@ in
|
||||
RouteTable = routeTable;
|
||||
};
|
||||
wireguardPeers = [
|
||||
# AirVPN NL
|
||||
{
|
||||
Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637";
|
||||
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
|
||||
PresharedKeyFile = config.age.secrets."${pskFile}".path;
|
||||
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||
# AirVPN NL
|
||||
wireguardPeerConfig = {
|
||||
Endpoint = "2a00:1678:1337:2329:e5f:35d4:4404:ef9f:1637";
|
||||
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
|
||||
PresharedKeyFile = config.age.secrets."${pskFile}".path;
|
||||
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -92,7 +94,7 @@ in
|
||||
matchConfig.Name = "vpn";
|
||||
address = [ "10.182.97.37/32" "fd7d:76ee:e68f:a993:735d:ef5e:6907:b122/128" ];
|
||||
dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ];
|
||||
routingPolicyRules = [
|
||||
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
|
||||
{
|
||||
Family = "both";
|
||||
SuppressPrefixLength = 0;
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.nginx) baseHttpConfig;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
@@ -66,19 +65,11 @@ in
|
||||
owner = "nginx";
|
||||
group = "nginx";
|
||||
};
|
||||
"librespeed.toml" = { };
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [ "http" "https" 8448 ];
|
||||
extraRules = ''
|
||||
table inet nat {
|
||||
chain postrouting {
|
||||
oifname host0 snat ip6 to ${assignments.internal.ipv6.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
nginx-sso = {
|
||||
@@ -130,19 +121,6 @@ in
|
||||
baseURL = "https://sso.${pubDomain}";
|
||||
};
|
||||
};
|
||||
|
||||
librespeed = {
|
||||
frontend.servers = [
|
||||
{
|
||||
name = "Amsterdam, Netherlands";
|
||||
server = "//librespeed.${domain}";
|
||||
}
|
||||
];
|
||||
backend = {
|
||||
enable = true;
|
||||
extraSettingsFile = config.age.secrets."librespeed.toml".path;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users = {
|
||||
@@ -153,10 +131,6 @@ in
|
||||
|
||||
systemd = {
|
||||
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
|
||||
services = {
|
||||
# HACK: nginx seems to get stuck not being able to DNS early...
|
||||
nginx = lib.my.systemdAwaitPostgres pkgs.postgresql "colony-psql";
|
||||
};
|
||||
};
|
||||
|
||||
security = {
|
||||
@@ -246,9 +220,6 @@ in
|
||||
];
|
||||
|
||||
recommendedTlsSettings = true;
|
||||
recommendedBrotliSettings = true;
|
||||
# Uh so nginx is hanging with zstd enabled... maybe let's not for now
|
||||
# recommendedZstdSettings = true;
|
||||
clientMaxBodySize = "0";
|
||||
serverTokens = true;
|
||||
resolver = {
|
||||
@@ -258,14 +229,45 @@ in
|
||||
proxyResolveWhileRunning = true;
|
||||
sslDhparam = config.age.secrets."dhparams.pem".path;
|
||||
|
||||
appendConfig = ''
|
||||
worker_processes auto;
|
||||
'';
|
||||
# Based on recommended*Settings, but probably better to be explicit about these
|
||||
appendHttpConfig = ''
|
||||
${baseHttpConfig}
|
||||
# NixOS provides a logrotate config that auto-compresses :)
|
||||
log_format main
|
||||
'$remote_addr - $remote_user [$time_local] $scheme "$host" "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
resolver_timeout 5s;
|
||||
# optimisation
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
# gzip
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 5;
|
||||
gzip_types
|
||||
application/atom+xml
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/xml+rss
|
||||
image/svg+xml
|
||||
text/css
|
||||
text/javascript
|
||||
text/plain
|
||||
text/xml;
|
||||
gzip_vary on;
|
||||
|
||||
# proxying
|
||||
proxy_buffering off;
|
||||
proxy_redirect off;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
${lib.my.c.nginx.proxyHeaders}
|
||||
|
||||
# caching
|
||||
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=4g;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let
|
||||
inherit (builtins) mapAttrs toJSON;
|
||||
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 (config.networking) domain;
|
||||
|
||||
@@ -35,6 +35,7 @@ let
|
||||
# For clients
|
||||
(mkWellKnown "matrix/client" (toJSON {
|
||||
"m.homeserver".base_url = "https://matrix.nul.ie";
|
||||
"org.matrix.msc3575.proxy".url = "https://matrix-syncv3.nul.ie";
|
||||
}))
|
||||
];
|
||||
};
|
||||
@@ -49,7 +50,6 @@ let
|
||||
"/.well-known/webfinger".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/atproto-did".return = "301 https://pds.nul.ie$request_uri";
|
||||
};
|
||||
in
|
||||
{
|
||||
@@ -80,10 +80,6 @@ in
|
||||
sha256 = "018wh6ps19n7323fi44njzj9yd4wqslc90dykbwfyscv7bgxhlar";
|
||||
};
|
||||
}
|
||||
{
|
||||
name = "ssh.pub";
|
||||
path = lib.my.c.sshKeyFiles.me;
|
||||
}
|
||||
];
|
||||
}
|
||||
wellKnown
|
||||
@@ -149,7 +145,7 @@ in
|
||||
|
||||
"pass.${pubDomain}" =
|
||||
let
|
||||
upstream = "http://vaultwarden-ctr.${domain}:8080";
|
||||
upstream = "http://vaultwarden-ctr.${domain}";
|
||||
in
|
||||
{
|
||||
locations = {
|
||||
@@ -186,6 +182,10 @@ in
|
||||
];
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
"matrix-syncv3.${pubDomain}" = {
|
||||
locations."/".proxyPass = "http://chatterbox-ctr.${domain}:8009";
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
|
||||
"element.${pubDomain}" =
|
||||
let
|
||||
@@ -206,8 +206,7 @@ in
|
||||
# Currently it seems like single quotes aren't escaped like they should be...
|
||||
conf = {
|
||||
brand = "/dev/player0 Matrix";
|
||||
show_labs_settings = true;
|
||||
default_country_code = "IE";
|
||||
showLabsSettings = true;
|
||||
disable_guests = true;
|
||||
default_server_config = {
|
||||
"m.homeserver" = {
|
||||
@@ -215,8 +214,9 @@ in
|
||||
server_name = "nul.ie";
|
||||
};
|
||||
};
|
||||
room_directory.servers = [
|
||||
roomDirectory.servers = [
|
||||
"nul.ie"
|
||||
"netsoc.ie"
|
||||
"matrix.org"
|
||||
];
|
||||
};
|
||||
@@ -318,21 +318,59 @@ in
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
|
||||
"toot.nul.ie" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://toot-ctr.${domain}:80";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = proxyHeaders;
|
||||
"toot.nul.ie" =
|
||||
let
|
||||
mkAssetLoc = name: {
|
||||
tryFiles = "$uri =404";
|
||||
extraConfig = ''
|
||||
add_header Cache-Control "public, max-age=2419200, must-revalidate";
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubpubDomains";
|
||||
'';
|
||||
};
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
in
|
||||
{
|
||||
root = "${pkgs.mastodon}/public";
|
||||
locations = mkMerge [
|
||||
(genAttrs [
|
||||
"= /sw.js"
|
||||
"~ ^/assets/"
|
||||
"~ ^/avatars/"
|
||||
"~ ^/emoji/"
|
||||
"~ ^/headers/"
|
||||
"~ ^/packs/"
|
||||
"~ ^/shortcuts/"
|
||||
"~ ^/sounds/"
|
||||
] mkAssetLoc)
|
||||
{
|
||||
"/".tryFiles = "$uri @proxy";
|
||||
|
||||
"pds.nul.ie" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://toot-ctr.${domain}:3000";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = proxyHeaders;
|
||||
};
|
||||
"^~ /api/v1/streaming" = {
|
||||
proxyPass = "http://toot-ctr.${domain}:55000";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
${proxyHeaders}
|
||||
proxy_set_header Proxy "";
|
||||
|
||||
add_header Strict-Transport-Security "max-age=63072000; includeSubdomains";
|
||||
'';
|
||||
};
|
||||
"@proxy" = {
|
||||
proxyPass = "http://toot-ctr.${domain}:55001";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = ''
|
||||
${proxyHeaders}
|
||||
proxy_set_header Proxy "";
|
||||
proxy_pass_header Server;
|
||||
|
||||
proxy_cache CACHE;
|
||||
proxy_cache_valid 200 7d;
|
||||
proxy_cache_valid 410 24h;
|
||||
proxy_cache_use_stale error timeout updating http_500 http_502 http_503 http_504;
|
||||
add_header X-Cached $upstream_cache_status;
|
||||
'';
|
||||
};
|
||||
}
|
||||
];
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
|
||||
@@ -347,16 +385,8 @@ in
|
||||
|
||||
"stuff.${pubDomain}" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://jackflix-ctr.${domain}:3923";
|
||||
};
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
"public.${pubDomain}" = {
|
||||
onlySSL = false;
|
||||
addSSL = true;
|
||||
serverAliases = [ "p.${pubDomain}" ];
|
||||
locations."/" = {
|
||||
root = "/mnt/media/public";
|
||||
basicAuthFile = config.age.secrets."middleman/htpasswd".path;
|
||||
root = "/mnt/media/stuff";
|
||||
extraConfig = ''
|
||||
fancyindex on;
|
||||
fancyindex_show_dotfiles on;
|
||||
@@ -365,84 +395,8 @@ in
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
|
||||
"mc-map.${pubDomain}" = {
|
||||
locations."/".proxyPass = "http://simpcraft-oci.${domain}:8100";
|
||||
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;
|
||||
};
|
||||
"hass-john.${pubDomain}" = {
|
||||
locations."/" = {
|
||||
proxyPass = "http://john-valorant-tun.${domain}:8123";
|
||||
proxyWebsockets = true;
|
||||
extraConfig = proxyHeaders;
|
||||
};
|
||||
"git.${pubDomain}" = {
|
||||
locations."/".proxyPass = "http://shill-vm.${domain}:3000";
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
};
|
||||
@@ -456,13 +410,11 @@ in
|
||||
ignore_invalid_headers off;
|
||||
'';
|
||||
|
||||
nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar.*|serve\/.+)$'';
|
||||
nixCacheableRegex = ''^\/(\S+\.narinfo|nar\/\S+\.nar\.\S+)$'';
|
||||
nixCacheHeaders = ''
|
||||
proxy_hide_header "X-Amz-Request-Id";
|
||||
add_header Cache-Control $nix_cache_control;
|
||||
add_header Expires $nix_expires;
|
||||
|
||||
brotli on;
|
||||
brotli_types application/x-nix-archive;
|
||||
'';
|
||||
in
|
||||
{
|
||||
@@ -483,36 +435,20 @@ in
|
||||
"s3.${pubDomain}" = {
|
||||
serverAliases = [ "*.s3.${pubDomain}" ];
|
||||
inherit extraConfig;
|
||||
locations = {
|
||||
"/".proxyPass = s3Upstream;
|
||||
"/gitea/packages/" = {
|
||||
proxyPass = s3Upstream;
|
||||
# HACK: Docker images need the MIME type to be correct for the manifest but Gitea
|
||||
# doesn't tell S3... By hiding the header we can use add_header to set Content-Type
|
||||
# (normally can't be set directly)
|
||||
extraConfig = ''
|
||||
proxy_hide_header Content-Type;
|
||||
add_header Content-Type $upstream_http_content_type always;
|
||||
if ($args ~ "response-content-disposition=.+filename%3D%22manifest\.json%22") {
|
||||
add_header Content-Type "application/vnd.docker.distribution.manifest.v2+json";
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
locations."/".proxyPass = s3Upstream;
|
||||
useACMEHost = pubDomain;
|
||||
};
|
||||
|
||||
"nix-cache.${pubDomain}" = {
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://${host}:5000";
|
||||
};
|
||||
"/".proxyPass = "http://${host}:8069";
|
||||
"~ ${nixCacheableRegex}" = {
|
||||
proxyPass = "http://${host}:5000";
|
||||
proxyPass = "http://${host}:8069";
|
||||
extraConfig = nixCacheHeaders;
|
||||
};
|
||||
};
|
||||
useACMEHost = pubDomain;
|
||||
onlySSL = false;
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
@@ -31,13 +31,6 @@ in
|
||||
{
|
||||
config = mkMerge [
|
||||
{
|
||||
fileSystems = {
|
||||
"/var/lib/harmonia" = {
|
||||
device = "/mnt/nix-cache";
|
||||
options = [ "bind" ];
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
deploy.enable = false;
|
||||
server.enable = true;
|
||||
@@ -55,21 +48,11 @@ in
|
||||
group = config.my.user.config.group;
|
||||
};
|
||||
"object/atticd.env" = {};
|
||||
"nix-cache.key" = {};
|
||||
"object/hedgedoc.env" = {};
|
||||
"object/wastebin.env" = {};
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [
|
||||
9000 9001
|
||||
config.services.sharry.config.bind.port
|
||||
8069
|
||||
5000
|
||||
config.services.hedgedoc.settings.port
|
||||
8088
|
||||
];
|
||||
tcp.allowed = [ 9000 9001 config.services.sharry.config.bind.port 8069 ];
|
||||
};
|
||||
|
||||
user.homeConfig = {
|
||||
@@ -77,40 +60,9 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
users = with lib.my.c.ids; mkMerge [
|
||||
(let inherit (config.services.atticd) user group; in {
|
||||
users."${user}" = {
|
||||
isSystemUser = true;
|
||||
uid = uids.atticd;
|
||||
group = group;
|
||||
};
|
||||
groups."${user}".gid = gids.atticd;
|
||||
})
|
||||
{
|
||||
users = {
|
||||
harmonia = {
|
||||
isSystemUser = true;
|
||||
group = "harmonia";
|
||||
shell = pkgs.bashInteractive;
|
||||
openssh.authorizedKeys.keyFiles = [
|
||||
lib.my.c.sshKeyFiles.harmonia
|
||||
];
|
||||
};
|
||||
};
|
||||
groups = {
|
||||
harmonia = { };
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
systemd = {
|
||||
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
|
||||
|
||||
services =
|
||||
let
|
||||
awaitPostgres = systemdAwaitPostgres pkgs.postgresql "colony-psql";
|
||||
in
|
||||
{
|
||||
services = {
|
||||
minio = {
|
||||
environment = {
|
||||
MINIO_ROOT_USER = "minioadmin";
|
||||
@@ -119,39 +71,7 @@ in
|
||||
MINIO_BROWSER_REDIRECT_URL = "https://minio.nul.ie";
|
||||
};
|
||||
};
|
||||
|
||||
sharry = awaitPostgres;
|
||||
|
||||
atticd = mkMerge [
|
||||
awaitPostgres
|
||||
{
|
||||
serviceConfig = {
|
||||
# Needs to be able to access its data
|
||||
DynamicUser = mkForce false;
|
||||
BindPaths = [ "/mnt/atticd:/var/lib/atticd/storage" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
harmonia-dev = {
|
||||
# environment.RUST_LOG = mkForce "trace";
|
||||
# serviceConfig = {
|
||||
# StateDirectory = "harmonia";
|
||||
# DynamicUser = mkForce false;
|
||||
# };
|
||||
};
|
||||
harmonia-daemon = {
|
||||
# environment.RUST_LOG = mkForce "trace";
|
||||
preStart = ''
|
||||
${config.nix.package}/bin/nix store info --store /var/lib/harmonia
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "harmonia";
|
||||
Group = "harmonia";
|
||||
StateDirectory = "harmonia";
|
||||
DynamicUser = mkForce false;
|
||||
};
|
||||
};
|
||||
sharry = systemdAwaitPostgres pkgs.postgresql "colony-psql";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -231,16 +151,18 @@ in
|
||||
};
|
||||
|
||||
atticd = {
|
||||
enable = false;
|
||||
environmentFile = config.age.secrets."object/atticd.env".path;
|
||||
enable = true;
|
||||
credentialsFile = config.age.secrets."object/atticd.env".path;
|
||||
settings = {
|
||||
listen = "[::]:8069";
|
||||
allowed-hosts = [ "nix-cache.${pubDomain}" ];
|
||||
api-endpoint = "https://nix-cache.${pubDomain}/";
|
||||
database = mkForce {}; # blank to pull from env
|
||||
storage = {
|
||||
type = "local";
|
||||
path = "/var/lib/atticd/storage";
|
||||
type = "s3";
|
||||
region = "eu-central-1";
|
||||
bucket = "nix-attic";
|
||||
endpoint = "http://localhost:9000";
|
||||
};
|
||||
chunking = {
|
||||
nar-size-threshold = 65536;
|
||||
@@ -250,52 +172,6 @@ in
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
harmonia-dev = {
|
||||
daemon = {
|
||||
enable = true;
|
||||
storeDir = "/nix/store";
|
||||
dbPath = "/var/lib/harmonia/nix/var/nix/db/db.sqlite";
|
||||
};
|
||||
cache = {
|
||||
enable = true;
|
||||
signKeyPaths = [ config.age.secrets."nix-cache.key".path ];
|
||||
settings = {
|
||||
priority = 30;
|
||||
virtual_nix_store = "/nix/store";
|
||||
real_nix_store = "/var/lib/harmonia/nix/store";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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 {
|
||||
|
||||
@@ -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 = { };
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib) mkForce;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
@@ -26,8 +25,6 @@ in
|
||||
let
|
||||
inherit (lib) mkMerge mkIf genAttrs;
|
||||
inherit (lib.my) networkdAssignment systemdAwaitPostgres;
|
||||
|
||||
pdsPort = 3000;
|
||||
in
|
||||
{
|
||||
config = mkMerge [
|
||||
@@ -38,7 +35,7 @@ in
|
||||
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILSslLkDe54AKYzxdtKD70zcU72W0EpYsfbdJ6UFq0QK";
|
||||
files = (genAttrs
|
||||
files = genAttrs
|
||||
(map (f: "toot/${f}") [
|
||||
"postgres-password.txt"
|
||||
"secret-key.txt"
|
||||
@@ -50,20 +47,15 @@ in
|
||||
(_: with config.services.mastodon; {
|
||||
owner = user;
|
||||
inherit group;
|
||||
})) // {
|
||||
"toot/pds.env" = {
|
||||
owner = "pds";
|
||||
group = "pds";
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [
|
||||
19999
|
||||
|
||||
"http"
|
||||
pdsPort
|
||||
config.services.mastodon.webPort
|
||||
config.services.mastodon.streamingPort
|
||||
];
|
||||
};
|
||||
};
|
||||
@@ -86,25 +78,21 @@ in
|
||||
services = {
|
||||
netdata.enable = true;
|
||||
mastodon = mkMerge [
|
||||
rec {
|
||||
enable = false;
|
||||
localDomain = extraConfig.WEB_DOMAIN; # for nginx config
|
||||
extraConfig = {
|
||||
LOCAL_DOMAIN = "nul.ie";
|
||||
WEB_DOMAIN = "toot.nul.ie";
|
||||
};
|
||||
{
|
||||
enable = true;
|
||||
localDomain = "nul.ie";
|
||||
extraConfig.WEB_DOMAIN = "toot.nul.ie";
|
||||
|
||||
secretKeyBaseFile = config.age.secrets."toot/secret-key.txt".path;
|
||||
# TODO: This was removed at some point.
|
||||
# If we want to bring Mastodon back, this will probably need to be addressd.
|
||||
# otpSecretFile = config.age.secrets."toot/otp-secret.txt".path;
|
||||
otpSecretFile = config.age.secrets."toot/otp-secret.txt".path;
|
||||
vapidPrivateKeyFile = config.age.secrets."toot/vapid-key.txt".path;
|
||||
vapidPublicKeyFile = toString (pkgs.writeText
|
||||
"vapid-pubkey.txt"
|
||||
"BAyRyD2pnLQtMHr3J5AzjNMll_HDC6ra1ilOLAUmKyhkEdbm7_OwKZUgw1UefY4CHEcv4OOX9TnnN2DOYYuPZu8=");
|
||||
|
||||
streamingProcesses = 4;
|
||||
configureNginx = true;
|
||||
enableUnixSocket = false;
|
||||
configureNginx = false;
|
||||
trustedProxy = allAssignments.middleman.internal.ipv6.address;
|
||||
|
||||
database = {
|
||||
createLocally = false;
|
||||
@@ -146,57 +134,13 @@ in
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
# Override some stuff since we are proxying upstream
|
||||
nginx = {
|
||||
recommendedProxySettings = mkForce false;
|
||||
virtualHosts."${config.services.mastodon.localDomain}" =
|
||||
let
|
||||
extraConfig = ''
|
||||
proxy_set_header Host $host;
|
||||
'';
|
||||
in
|
||||
{
|
||||
forceSSL = false;
|
||||
enableACME = false;
|
||||
locations = {
|
||||
"@proxy" = { inherit extraConfig; };
|
||||
"/api/v1/streaming/" = { inherit extraConfig; };
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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 {
|
||||
virtualisation = {
|
||||
forwardPorts = with config.services.mastodon; [
|
||||
{ from = "host"; guest.port = webPort; }
|
||||
{ from = "host"; guest.port = streamingPort; }
|
||||
];
|
||||
};
|
||||
})
|
||||
|
||||
@@ -83,7 +83,7 @@ in
|
||||
DOMAIN = "https://pass.${lib.my.c.pubDomain}";
|
||||
|
||||
ROCKET_ADDRESS = "::";
|
||||
ROCKET_PORT = 8080;
|
||||
ROCKET_PORT = 80;
|
||||
|
||||
SMTP_HOST = "mail.nul.ie";
|
||||
SMTP_FROM = "pass@nul.ie";
|
||||
@@ -99,8 +99,6 @@ in
|
||||
};
|
||||
|
||||
borgbackup.jobs.vaultwarden = {
|
||||
readWritePaths = [ "/var/lib/borgbackup" "/var/cache/borgbackup" ];
|
||||
|
||||
paths = [ vwData ];
|
||||
repo = "zh2855@zh2855.rsync.net:borg/vaultwarden2";
|
||||
doInit = true;
|
||||
|
||||
@@ -1,100 +0,0 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
nixos.systems.waffletail = { config, ... }: {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
rendered = config.configuration.config.my.asContainer;
|
||||
|
||||
assignments = {
|
||||
internal = {
|
||||
name = "waffletail-ctr";
|
||||
inherit domain;
|
||||
ipv4.address = net.cidr.host 9 prefixes.ctrs.v4;
|
||||
ipv6 = {
|
||||
iid = "::9";
|
||||
address = net.cidr.host 9 prefixes.ctrs.v6;
|
||||
};
|
||||
};
|
||||
tailscale = with lib.my.c.tailscale; {
|
||||
ipv4 = {
|
||||
address = net.cidr.host 5 prefix.v4;
|
||||
mask = 32;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6 = {
|
||||
address = net.cidr.host 5 prefix.v6;
|
||||
mask = 128;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, config, assignments, ... }:
|
||||
let
|
||||
inherit (lib) concatStringsSep mkMerge mkIf mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
my = {
|
||||
deploy.enable = false;
|
||||
server.enable = true;
|
||||
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAICZc88lcSQ9zzQzDITdE/T5ty++TxFQUAED7p9YfFBiR";
|
||||
files = {
|
||||
"tailscale-auth.key" = {};
|
||||
};
|
||||
};
|
||||
|
||||
firewall = {
|
||||
trustedInterfaces = [ "tailscale0" ];
|
||||
extraRules = ''
|
||||
table inet filter {
|
||||
chain forward {
|
||||
iifname host0 oifname tailscale0 ip saddr ${prefixes.all.v4} accept
|
||||
iifname host0 oifname tailscale0 ip6 saddr ${prefixes.all.v6} accept
|
||||
}
|
||||
}
|
||||
table inet nat {
|
||||
chain postrouting {
|
||||
iifname tailscale0 ip daddr != ${prefixes.all.v4} snat to ${assignments.internal.ipv4.address}
|
||||
iifname tailscale0 ip6 daddr != ${prefixes.all.v6} snat ip6 to ${assignments.internal.ipv6.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
network.networks."80-container-host0" = networkdAssignment "host0" assignments.internal;
|
||||
};
|
||||
|
||||
services = {
|
||||
tailscale =
|
||||
let
|
||||
advRoutes = concatStringsSep "," (with prefixes.all; [ v4 v6 ]);
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
authKeyFile = config.age.secrets."tailscale-auth.key".path;
|
||||
port = 41641;
|
||||
openFirewall = true;
|
||||
interfaceName = "tailscale0";
|
||||
extraUpFlags = [
|
||||
"--operator=${config.my.user.config.name}"
|
||||
"--login-server=https://hs.nul.ie"
|
||||
"--netfilter-mode=off"
|
||||
"--advertise-exit-node"
|
||||
"--advertise-routes=${advRoutes}"
|
||||
"--accept-routes=false"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net nft;
|
||||
inherit (lib.my.c.colony) domain prefixes firewallForwards;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.colony) domain prefixes;
|
||||
in
|
||||
{
|
||||
imports = [ ./containers ];
|
||||
@@ -49,11 +49,7 @@ in
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/profiles/qemu-guest.nix"
|
||||
|
||||
./containers-ext.nix
|
||||
];
|
||||
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ./gitea.nix ];
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
@@ -85,7 +81,6 @@ in
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
|
||||
"/mnt/media" = {
|
||||
device = "/dev/disk/by-label/media";
|
||||
fsType = "ext4";
|
||||
@@ -94,10 +89,6 @@ in
|
||||
device = "/dev/disk/by-label/minio";
|
||||
fsType = "xfs";
|
||||
};
|
||||
"/mnt/nix-cache" = {
|
||||
device = "/dev/disk/by-label/nix-cache";
|
||||
fsType = "ext4";
|
||||
};
|
||||
};
|
||||
|
||||
nix.settings = {
|
||||
@@ -140,22 +131,7 @@ in
|
||||
};
|
||||
ipv6Prefixes = [
|
||||
{
|
||||
Prefix = prefixes.ctrs.v6;
|
||||
}
|
||||
];
|
||||
routes = [
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v4;
|
||||
Gateway = allAssignments.waffletail.internal.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v6;
|
||||
Gateway = allAssignments.waffletail.internal.ipv6.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = prefixes.qclk.v4;
|
||||
Gateway = allAssignments.qclk.internal.ipv4.address;
|
||||
ipv6PrefixConfig.Prefix = prefixes.ctrs.v6;
|
||||
}
|
||||
];
|
||||
}
|
||||
@@ -170,7 +146,6 @@ in
|
||||
firewall = {
|
||||
tcp.allowed = [ 19999 ];
|
||||
trustedInterfaces = [ "ctrs" ];
|
||||
nat.forwardPorts."${allAssignments.estuary.internal.ipv4.address}" = firewallForwards allAssignments;
|
||||
extraRules = ''
|
||||
table inet filter {
|
||||
chain forward {
|
||||
@@ -178,17 +153,6 @@ in
|
||||
iifname vms oifname ctrs accept
|
||||
}
|
||||
}
|
||||
table inet nat {
|
||||
# Hack to fix our NAT situation with internal routing
|
||||
# We need to snat to our public IP, otherwise on the return path from e.g. middleman it will
|
||||
# try to forward packet directly with its own IP, bypassing our carefully crafted DNAT...
|
||||
chain ${nft.dnatChain allAssignments.estuary.internal.ipv4.address} {
|
||||
ct mark set 0x1337
|
||||
}
|
||||
chain postrouting {
|
||||
ct mark 0x1337 snat ip to ${assignments.internal.ipv4.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
|
||||
@@ -211,13 +175,9 @@ in
|
||||
object = {
|
||||
bindMounts = {
|
||||
"/mnt/minio".readOnly = false;
|
||||
"/mnt/nix-cache".readOnly = false;
|
||||
};
|
||||
};
|
||||
toot = {};
|
||||
waffletail = {};
|
||||
qclk = {};
|
||||
gam = {};
|
||||
};
|
||||
in
|
||||
mkMerge [
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
{ lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.colony) prefixes;
|
||||
in
|
||||
@@ -26,25 +25,20 @@ in
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
gitea = mkMerge [
|
||||
(lib.my.systemdAwaitPostgres pkgs.postgresql "colony-psql")
|
||||
{
|
||||
preStart =
|
||||
let
|
||||
repSec = "${pkgs.replace-secret}/bin/replace-secret";
|
||||
confPath = "${config.services.gitea.customDir}/conf/app.ini";
|
||||
in
|
||||
''
|
||||
gitea_extra_setup() {
|
||||
chmod u+w '${confPath}'
|
||||
${repSec} '#miniosecret#' '${config.age.secrets."gitea/minio.txt".path}' '${confPath}'
|
||||
chmod u-w '${confPath}'
|
||||
}
|
||||
|
||||
(umask 027; gitea_extra_setup)
|
||||
'';
|
||||
gitea.preStart =
|
||||
let
|
||||
repSec = "${pkgs.replace-secret}/bin/replace-secret";
|
||||
confPath = "${config.services.gitea.customDir}/conf/app.ini";
|
||||
in
|
||||
''
|
||||
gitea_extra_setup() {
|
||||
chmod u+w '${confPath}'
|
||||
${repSec} '#miniosecret#' '${config.age.secrets."gitea/minio.txt".path}' '${confPath}'
|
||||
chmod u-w '${confPath}'
|
||||
}
|
||||
];
|
||||
|
||||
(umask 027; gitea_extra_setup)
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -129,6 +123,21 @@ in
|
||||
"gitea/minio.txt" = ownedByGit;
|
||||
};
|
||||
};
|
||||
|
||||
firewall.extraRules = ''
|
||||
table inet filter {
|
||||
chain input {
|
||||
ip saddr ${prefixes.all.v4} tcp dport 3000 accept
|
||||
ip6 saddr ${prefixes.all.v6} tcp dport 3000 accept
|
||||
}
|
||||
}
|
||||
table inet nat {
|
||||
chain prerouting {
|
||||
ip daddr ${assignments.internal.ipv4.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv4.address}
|
||||
ip6 daddr ${assignments.internal.ipv6.address} tcp dport { http, https } dnat to ${allAssignments.middleman.internal.ipv6.address}
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -50,12 +50,6 @@ in
|
||||
};
|
||||
}) {
|
||||
valheim-oci = 2;
|
||||
simpcraft-oci = 3;
|
||||
simpcraft-staging-oci = 4;
|
||||
enshrouded-oci = 5;
|
||||
kevcraft-oci = 6;
|
||||
kinkcraft-oci = 7;
|
||||
graeme-oci = 8;
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
|
||||
@@ -69,8 +63,7 @@ in
|
||||
"${modulesPath}/profiles/qemu-guest.nix"
|
||||
|
||||
./valheim.nix
|
||||
./minecraft
|
||||
# ./enshrouded.nix
|
||||
./gitea-actions.nix
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
@@ -113,30 +106,45 @@ in
|
||||
oci-containers = {
|
||||
backend = "podman";
|
||||
};
|
||||
containers.containersConf.settings.network = {
|
||||
network_backend = "netavark";
|
||||
firewall_driver = mkForce "none";
|
||||
};
|
||||
# NixOS has switched to using netavark, which is native to podman. It's currently missing an option to
|
||||
# disable iptables rules generation, which is very annoying.
|
||||
containers.containersConf.settings.network.network_backend = mkForce "cni";
|
||||
};
|
||||
|
||||
environment = {
|
||||
etc = {
|
||||
"containers/networks/colony.json".text = toJSON {
|
||||
"cni/net.d/90-colony.conflist".text = toJSON {
|
||||
cniVersion = "0.4.0";
|
||||
name = "colony";
|
||||
id = "0000000000000000000000000000000000000000000000000000000000000001";
|
||||
driver = "bridge";
|
||||
network_interface = "oci";
|
||||
ipv6_enabled = true;
|
||||
internal = false;
|
||||
dns_enabled = false;
|
||||
subnets = [
|
||||
plugins = [
|
||||
{
|
||||
subnet = prefixes.oci.v4;
|
||||
gateway = net.cidr.host 1 prefixes.oci.v4;
|
||||
}
|
||||
{
|
||||
subnet = prefixes.oci.v6;
|
||||
gateway = net.cidr.host 1 prefixes.oci.v6;
|
||||
type = "bridge";
|
||||
bridge = "oci";
|
||||
isGateway = true;
|
||||
ipMasq = false;
|
||||
hairpinMode = true;
|
||||
ipam = {
|
||||
type = "host-local";
|
||||
routes = [
|
||||
{ dst = "0.0.0.0/0"; }
|
||||
{ dst = "::/0"; }
|
||||
];
|
||||
ranges = [
|
||||
[
|
||||
{
|
||||
subnet = prefixes.oci.v4;
|
||||
gateway = net.cidr.host 1 prefixes.oci.v4;
|
||||
}
|
||||
]
|
||||
[
|
||||
{
|
||||
subnet = prefixes.oci.v6;
|
||||
gateway = net.cidr.host 1 prefixes.oci.v6;
|
||||
}
|
||||
]
|
||||
];
|
||||
};
|
||||
capabilities.ips = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
@@ -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" = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -6,7 +6,7 @@ let
|
||||
|
||||
cfgFile = pkgs.writeText "gitea-actions-runner.yaml" (toJSON {
|
||||
container = {
|
||||
network = "podman";
|
||||
network = "colony";
|
||||
privileged = true;
|
||||
};
|
||||
cache = {
|
||||
@@ -30,16 +30,10 @@ in
|
||||
enable = true;
|
||||
name = "main-docker";
|
||||
labels = [
|
||||
"debian-node-bullseye:docker://node:18-bullseye"
|
||||
"ubuntu-22.04:docker://git.nul.ie/dev/actions-ubuntu:22.04"
|
||||
];
|
||||
url = "https://git.${pubDomain}";
|
||||
tokenFile = config.age.secrets."gitea/actions-runner.env".path;
|
||||
settings = {
|
||||
runner = {
|
||||
timeout = "8h";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -1,271 +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"}''
|
||||
];
|
||||
};
|
||||
|
||||
graeme = {
|
||||
# 2026.2.1-java21-alpine
|
||||
image = "itzg/minecraft-server@sha256:82adaddfe0156f07c34228f1c1065cdbd298abc174de0a9961abb068b11beebb";
|
||||
|
||||
environment = {
|
||||
TYPE = "VANILLA";
|
||||
SERVER_PORT = "25569";
|
||||
QUERY_PORT = "25569";
|
||||
|
||||
EULA = "true";
|
||||
ENABLE_QUERY = "true";
|
||||
ENABLE_RCON = "false";
|
||||
MOTD = "§4§k----- §9G§ar§ba§ce§dm§ee §4§k-----";
|
||||
ICON = "/ext/icon.png";
|
||||
|
||||
EXISTING_WHITELIST_FILE = "SYNCHRONIZE";
|
||||
WHITELIST = concatStringsSep "," [
|
||||
op
|
||||
"fffa146c-0bc8-421c-9e3a-3635c0aca2ea" # Scarlehh
|
||||
"1ea05f48-76cc-4034-bcd3-2fa1fc5a7375" # Dario
|
||||
"4bf837b1-01db-4491-a0e0-700d98542833" # JoeSpencer
|
||||
"d07a9554-1b05-4b0b-b558-27e4a86e1f53" # AmyClover
|
||||
];
|
||||
EXISTING_OPS_FILE = "SYNCHRONIZE";
|
||||
OPS = op;
|
||||
DIFFICULTY = "hard";
|
||||
SPAWN_PROTECTION = "0";
|
||||
VIEW_DISTANCE = "20";
|
||||
|
||||
MAX_MEMORY = "4G";
|
||||
|
||||
TZ = "Europe/Dublin";
|
||||
};
|
||||
|
||||
volumes = [
|
||||
"graeme_data:/data"
|
||||
"${./graeme.png}:/ext/icon.png:ro"
|
||||
];
|
||||
|
||||
extraOptions = [
|
||||
''--network=colony:${dockerNetAssignment allAssignments "graeme-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" = {};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
Before Width: | Height: | Size: 8.9 KiB |
|
Before Width: | Height: | Size: 5.4 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 4.2 MiB |
@@ -1,227 +0,0 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net mkVLAN;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.home) domain vlans prefixes vips hiMTU;
|
||||
in
|
||||
{
|
||||
imports = [ ./vms ];
|
||||
|
||||
nixos.systems.palace = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine-stable";
|
||||
home-manager = "mine-stable";
|
||||
|
||||
assignments = {
|
||||
hi = {
|
||||
inherit domain;
|
||||
mtu = hiMTU;
|
||||
ipv4 = {
|
||||
address = net.cidr.host 22 prefixes.hi.v4;
|
||||
mask = 22;
|
||||
gateway = vips.hi.v4;
|
||||
};
|
||||
ipv6 = {
|
||||
iid = "::2:1";
|
||||
address = net.cidr.host (65536*2+1) prefixes.hi.v6;
|
||||
};
|
||||
};
|
||||
core = {
|
||||
inherit domain;
|
||||
name = "palace-core";
|
||||
mtu = 1500;
|
||||
ipv4 = {
|
||||
address = net.cidr.host 20 prefixes.core.v4;
|
||||
gateway = null;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, systems, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkForce mkMerge;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
inherit (lib.my.c) networkd;
|
||||
in
|
||||
{
|
||||
boot = {
|
||||
kernelPackages = (lib.my.c.kernel.lts pkgs).extend (self: super: {
|
||||
kernel = super.kernel.override {
|
||||
structuredExtraConfig = with lib.kernel; {
|
||||
ACPI_APEI_PCIEAER = yes;
|
||||
PCIEAER = yes;
|
||||
};
|
||||
};
|
||||
});
|
||||
kernelModules = [ "kvm-amd" ];
|
||||
kernelParams = [ "amd_iommu=on" ];
|
||||
initrd = {
|
||||
availableKernelModules = [ "xhci_pci" "ahci" "usb_storage" "usbhid" "sd_mod" "sr_mod" ];
|
||||
};
|
||||
};
|
||||
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
cpu = {
|
||||
amd.updateMicrocode = true;
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/c06a8d24-2af9-4416-bf5e-cfe6defdbd47";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-uuid/450e1f72-238a-4160-98b8-b5e6d0d6fdf6";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/disk/by-uuid/9d6d53a8-dff8-49e0-9bc3-fb5f7c6760d0";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
lvm = {
|
||||
boot.thin.enable = true;
|
||||
dmeventd.enable = true;
|
||||
};
|
||||
smartd = {
|
||||
enable = true;
|
||||
autodetect = true;
|
||||
extraOptions = [ "-A /var/log/smartd/" "--interval=600" ];
|
||||
};
|
||||
udev.extraRules = ''
|
||||
ACTION=="add", SUBSYSTEM=="net", ENV{ID_NET_DRIVER}=="mlx5_core", ENV{ID_PATH}=="pci-0000:44:00.0", ATTR{device/sriov_numvfs}="4"
|
||||
'';
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
pciutils
|
||||
usbutils
|
||||
partclone
|
||||
lm_sensors
|
||||
linuxPackages.cpupower
|
||||
smartmontools
|
||||
mstflint
|
||||
ethtool
|
||||
hwloc
|
||||
];
|
||||
|
||||
networking = { inherit domain; };
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"d /var/log/smartd 0755 root root"
|
||||
];
|
||||
|
||||
network = {
|
||||
links = {
|
||||
"10-et1g0" = {
|
||||
matchConfig = {
|
||||
PermanentMACAddress = "e0:d5:5e:68:0c:6e";
|
||||
Driver = "igb";
|
||||
};
|
||||
linkConfig.Name = "et1g0";
|
||||
};
|
||||
"10-lan-core" = {
|
||||
matchConfig.PermanentMACAddress = "e0:d5:5e:68:0c:70";
|
||||
linkConfig.Name = "lan-core";
|
||||
};
|
||||
"10-et100g" = {
|
||||
matchConfig = {
|
||||
PermanentMACAddress = "24:8a:07:ac:59:c0";
|
||||
Driver = "mlx5_core";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "et100g";
|
||||
MTUBytes = toString hiMTU;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
netdevs = mkMerge [
|
||||
(mkVLAN "lan-hi" vlans.hi)
|
||||
(mkVLAN "lan-lo-phy" vlans.lo)
|
||||
{
|
||||
"25-lan-lo".netdevConfig = {
|
||||
Name = "lan-lo";
|
||||
Kind = "bridge";
|
||||
};
|
||||
}
|
||||
];
|
||||
|
||||
networks = {
|
||||
"50-lan-core" = mkMerge [
|
||||
(networkdAssignment "lan-core" assignments.core)
|
||||
{
|
||||
matchConfig.Name = "lan-core";
|
||||
vlan = [ "lan-lo-phy" ];
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
}
|
||||
];
|
||||
|
||||
"50-et100g" = {
|
||||
matchConfig.Name = "et100g";
|
||||
vlan = [ "lan-hi" ];
|
||||
networkConfig = networkd.noL3;
|
||||
linkConfig.RequiredForOnline = "no";
|
||||
extraConfig = ''
|
||||
# cellar
|
||||
[SR-IOV]
|
||||
VirtualFunction=0
|
||||
VLANId=${toString vlans.hi}
|
||||
LinkState=yes
|
||||
MACAddress=52:54:00:cc:3e:70
|
||||
|
||||
# river
|
||||
[SR-IOV]
|
||||
VirtualFunction=1
|
||||
LinkState=yes
|
||||
MACAddress=52:54:00:8a:8a:f2
|
||||
|
||||
# sfh
|
||||
[SR-IOV]
|
||||
VirtualFunction=2
|
||||
VLANId=${toString vlans.hi}
|
||||
LinkState=yes
|
||||
MACAddress=52:54:00:ac:15:a9
|
||||
|
||||
# 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;
|
||||
|
||||
"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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIHzVJpoDz/AAYLJGzU8t6DgZ2sY3oehRqrlSO7C+GWiK";
|
||||
};
|
||||
|
||||
server.enable = true;
|
||||
deploy.node.hostname = "192.168.68.22";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,99 +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.cellar = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
|
||||
assignments = {
|
||||
hi = {
|
||||
inherit domain;
|
||||
mtu = hiMTU;
|
||||
ipv4 = {
|
||||
address = net.cidr.host 80 prefixes.hi.v4;
|
||||
mask = 22;
|
||||
gateway = vips.hi.v4;
|
||||
};
|
||||
ipv6 = {
|
||||
iid = "::4:1";
|
||||
address = net.cidr.host (65536*4+1) prefixes.hi.v6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, modulesPath, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
in
|
||||
{
|
||||
imports = [
|
||||
"${modulesPath}/profiles/qemu-guest.nix"
|
||||
./spdk.nix
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
{
|
||||
boot = {
|
||||
kernelParams = [ "console=ttyS0,115200n8" "intel_iommu=on" ];
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/f7562ee6-34c1-4e94-8ae7-c6e71794d563";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-uuid/f31f6abd-0832-4014-a761-f3c3126d5739";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/disk/by-uuid/620364e3-3a30-4704-be80-8593516e7482";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking = { inherit domain; };
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
pciutils
|
||||
partclone
|
||||
];
|
||||
|
||||
services = {
|
||||
fstrim.enable = true;
|
||||
netdata.enable = true;
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
links = {
|
||||
"10-lan-hi" = {
|
||||
matchConfig.PermanentMACAddress = "52:54:00:cc:3e:70";
|
||||
linkConfig.Name = "lan-hi";
|
||||
};
|
||||
};
|
||||
|
||||
networks = {
|
||||
"80-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets.key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDcklmJp8xVRddNDU1DruKV+Ipim3Jtl6nE1oCWmpmZH";
|
||||
server.enable = true;
|
||||
deploy.node.hostname = "192.168.68.80";
|
||||
|
||||
firewall = {
|
||||
tcp.allowed = [ 19999 ];
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,143 +0,0 @@
|
||||
{ lib, pkgs, config, assignments, ... }:
|
||||
let
|
||||
inherit (lib) mapAttrsToList;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
boot.blacklistedKernelModules = [ "nvme" ];
|
||||
|
||||
systemd.services = {
|
||||
spdk-tgt.after = [ "systemd-networkd-wait-online@lan-hi.service" ];
|
||||
};
|
||||
|
||||
my = {
|
||||
spdk = {
|
||||
enable = true;
|
||||
extraArgs = "--mem-channels 2 --cpumask 0xffff";
|
||||
debugCommands = ''
|
||||
spdk-rpc bdev_nvme_attach_controller -t pcie -a 02:00.0 -b NVMe0
|
||||
spdk-rpc bdev_nvme_attach_controller -t pcie -a 03:00.0 -b NVMe1
|
||||
spdk-rpc bdev_nvme_attach_controller -t pcie -a 04:00.0 -b NVMe2
|
||||
spdk-rpc bdev_raid_create -n NVMeRaid -z 64 -r 0 -b 'NVMe0n1 NVMe1n1 NVMe2n1'
|
||||
|
||||
spdk-rpc ublk_create_target
|
||||
spdk-rpc ublk_start_disk NVMeRaid 1
|
||||
'';
|
||||
config.subsystems =
|
||||
let
|
||||
nvmeAttaches = mapAttrsToList (name: bdf: {
|
||||
method = "bdev_nvme_attach_controller";
|
||||
params = {
|
||||
hostnqn =
|
||||
"nqn.2014-08.org.nvmexpress:uuid:2b16606f-b82c-49f8-9b20-a589dac8b775";
|
||||
trtype = "PCIe";
|
||||
inherit name;
|
||||
traddr = bdf;
|
||||
};
|
||||
}) {
|
||||
"NVMe0" = "02:00.0";
|
||||
"NVMe1" = "03:00.0";
|
||||
"NVMe2" = "04:00.0";
|
||||
};
|
||||
|
||||
nvmfListener = nqn: {
|
||||
method = "nvmf_subsystem_add_listener";
|
||||
params = {
|
||||
inherit nqn;
|
||||
listen_address = {
|
||||
adrfam = "IPv4";
|
||||
traddr = assignments.hi.ipv4.address;
|
||||
trsvcid = "4420";
|
||||
trtype = "RDMA";
|
||||
};
|
||||
secure_channel = false;
|
||||
};
|
||||
};
|
||||
nvmfBdev = { nqn, hostnqn, bdev, serial }: [
|
||||
{
|
||||
method = "nvmf_create_subsystem";
|
||||
params = {
|
||||
inherit nqn;
|
||||
serial_number = serial;
|
||||
};
|
||||
}
|
||||
(nvmfListener nqn)
|
||||
{
|
||||
method = "nvmf_subsystem_add_host";
|
||||
params = {
|
||||
inherit nqn;
|
||||
host = hostnqn;
|
||||
};
|
||||
}
|
||||
{
|
||||
method = "nvmf_subsystem_add_ns";
|
||||
params = {
|
||||
inherit nqn;
|
||||
namespace = {
|
||||
bdev_name = bdev;
|
||||
nsid = 1;
|
||||
};
|
||||
};
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
scheduler = [
|
||||
{
|
||||
method = "framework_set_scheduler";
|
||||
params.name = "dynamic";
|
||||
}
|
||||
];
|
||||
|
||||
bdev = [
|
||||
{
|
||||
method = "bdev_set_options";
|
||||
params.bdev_auto_examine = false;
|
||||
}
|
||||
] ++ nvmeAttaches ++ [
|
||||
{
|
||||
method = "bdev_raid_create";
|
||||
params = {
|
||||
base_bdevs = [ "NVMe0n1" "NVMe1n1" "NVMe2n1" ];
|
||||
name = "NVMeRaid";
|
||||
raid_level = "raid0";
|
||||
strip_size_kb = 64;
|
||||
};
|
||||
}
|
||||
{
|
||||
method = "bdev_examine";
|
||||
params.name = "NVMeRaid";
|
||||
}
|
||||
{ method = "bdev_wait_for_examine"; }
|
||||
];
|
||||
|
||||
nvmf = [
|
||||
{
|
||||
method = "nvmf_create_transport";
|
||||
params.trtype = "RDMA";
|
||||
}
|
||||
(nvmfListener "nqn.2014-08.org.nvmexpress.discovery")
|
||||
] ++ (nvmfBdev {
|
||||
bdev = "NVMeRaidp1";
|
||||
nqn = "nqn.2016-06.io.spdk:river";
|
||||
hostnqn =
|
||||
"nqn.2014-08.org.nvmexpress:uuid:12b52d80-ccb6-418d-9b2e-2be34bff3cd9";
|
||||
serial = "SPDK00000000000001";
|
||||
}) ++ (nvmfBdev {
|
||||
bdev = "NVMeRaidp2";
|
||||
nqn = "nqn.2016-06.io.spdk:castle";
|
||||
hostnqn =
|
||||
"nqn.2014-08.org.nvmexpress:uuid:2230b066-a674-4f45-a1dc-f7727b3a9e7b";
|
||||
serial = "SPDK00000000000002";
|
||||
}) ++ (nvmfBdev {
|
||||
bdev = "NVMeRaidp3";
|
||||
nqn = "nqn.2016-06.io.spdk:sfh";
|
||||
hostnqn =
|
||||
"nqn.2014-08.org.nvmexpress:uuid:85d7df36-0de0-431b-b06e-51f7c0a455b4";
|
||||
serial = "SPDK00000000000003";
|
||||
});
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,203 +0,0 @@
|
||||
{
|
||||
imports = [
|
||||
./cellar
|
||||
./river.nix
|
||||
./sfh
|
||||
];
|
||||
|
||||
nixos.systems.palace.configuration = { lib, pkgs, config, systems, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkMerge;
|
||||
inherit (lib.my) vm;
|
||||
inherit (lib.my.c) networkd;
|
||||
|
||||
installerDisk = {
|
||||
name = "installer";
|
||||
backend = {
|
||||
driver = "file";
|
||||
filename = "/persist/home/dev/nixos-installer-devplayer0.iso";
|
||||
read-only = "on";
|
||||
};
|
||||
format.driver = "raw";
|
||||
frontend = "ide-cd";
|
||||
frontendOpts = {
|
||||
bootindex = 1;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
systemd.network = {
|
||||
netdevs = {
|
||||
"25-vm-et1g0" = {
|
||||
netdevConfig = {
|
||||
Name = "vm-et1g0";
|
||||
Kind = "macvtap";
|
||||
};
|
||||
# TODO: Upstream this missing section
|
||||
extraConfig = ''
|
||||
[MACVTAP]
|
||||
Mode=passthru
|
||||
'';
|
||||
};
|
||||
};
|
||||
networks = {
|
||||
"75-et1g0" = {
|
||||
matchConfig.Name = "et1g0";
|
||||
linkConfig.RequiredForOnline = "no";
|
||||
networkConfig = {
|
||||
MACVTAP = "vm-et1g0";
|
||||
} // networkd.noL3;
|
||||
};
|
||||
"75-vm-et1g0" = {
|
||||
matchConfig.Name = "vm-et1g0";
|
||||
linkConfig.RequiredForOnline = "no";
|
||||
networkConfig = networkd.noL3;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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" = {
|
||||
serviceConfig = {
|
||||
CPUAffinity = "numa";
|
||||
NUMAPolicy = "bind";
|
||||
NUMAMask = "1";
|
||||
};
|
||||
};
|
||||
|
||||
"vm@river" =
|
||||
let
|
||||
vtapUnit = "sys-subsystem-net-devices-vm\\x2det1g0.device";
|
||||
in
|
||||
mkMerge [
|
||||
(awaitVM "cellar")
|
||||
{
|
||||
requires = [ vtapUnit ];
|
||||
after = [ vtapUnit ];
|
||||
}
|
||||
];
|
||||
"vm@sfh" = (awaitVM "river");
|
||||
};
|
||||
|
||||
my = {
|
||||
vms = {
|
||||
instances = {
|
||||
cellar = {
|
||||
uuid = "b126d135-9fc1-415a-b675-aaf727bf2f38";
|
||||
cpu = "host,topoext";
|
||||
smp = {
|
||||
cpus = 8;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 16384;
|
||||
cleanShutdown.timeout = 120;
|
||||
drives = [
|
||||
(mkMerge [ (vm.disk "cellar" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
(vm.disk "cellar" "nix")
|
||||
(vm.disk "cellar" "persist")
|
||||
];
|
||||
hostDevices = {
|
||||
et100g0vf0 = {
|
||||
index = 0;
|
||||
hostBDF = "44:00.1";
|
||||
};
|
||||
nvme0 = {
|
||||
index = 1;
|
||||
hostBDF = "41:00.0";
|
||||
};
|
||||
nvme1 = {
|
||||
index = 2;
|
||||
hostBDF = "42:00.0";
|
||||
};
|
||||
nvme2 = {
|
||||
index = 3;
|
||||
hostBDF = "43:00.0";
|
||||
};
|
||||
};
|
||||
qemuFlags = [
|
||||
"machine kernel-irqchip=split"
|
||||
"device intel-iommu,caching-mode=on,device-iotlb=on,intremap=on"
|
||||
];
|
||||
};
|
||||
|
||||
river = {
|
||||
uuid = "12b52d80-ccb6-418d-9b2e-2be34bff3cd9";
|
||||
cpu = "host,topoext";
|
||||
smp = {
|
||||
cpus = 3;
|
||||
threads = 2;
|
||||
};
|
||||
memory = 4096;
|
||||
cleanShutdown.timeout = 60;
|
||||
networks = {
|
||||
et1g0 = {
|
||||
ifname = "vm-et1g0";
|
||||
bridge = null;
|
||||
tapFD = 100;
|
||||
# Real hardware MAC
|
||||
mac = "e0:d5:5e:68:0c:6e";
|
||||
waitOnline = false;
|
||||
};
|
||||
};
|
||||
drives = [
|
||||
installerDisk
|
||||
(mkMerge [ (vm.disk "river" "esp") { frontendOpts.bootindex = 0; } ])
|
||||
];
|
||||
hostDevices = {
|
||||
et100g0vf1 = {
|
||||
index = 0;
|
||||
hostBDF = "44:00.2";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
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"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,134 +0,0 @@
|
||||
{
|
||||
imports = [ (import ../../routing-common 0) ];
|
||||
|
||||
config.nixos.systems.river = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
home-manager = "mine";
|
||||
|
||||
configuration = { lib, modulesPath, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib.my) networkdAssignment mkVLAN;
|
||||
inherit (lib.my.c) networkd;
|
||||
inherit (lib.my.c.home) vlans domain prefixes roceBootModules;
|
||||
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"
|
||||
"8021q"
|
||||
] ++ roceBootModules;
|
||||
kernelModules = [ "dm-snapshot" ];
|
||||
systemd = {
|
||||
network = {
|
||||
# Don't need to put the link config here, they're copied from main config
|
||||
netdevs = mkVLAN "lan-hi" vlans.hi;
|
||||
networks = {
|
||||
"20-lan" = {
|
||||
matchConfig.Name = "lan";
|
||||
vlan = [ "lan-hi" ];
|
||||
linkConfig.RequiredForOnline = "no";
|
||||
networkConfig = networkd.noL3;
|
||||
};
|
||||
"30-lan-hi" = networkdAssignment "lan-hi" assignments.hi;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/3ec6c49e-b485-40cb-8eff-315581ac6fe9";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/main/nix";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/main/persist";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
lvm = {
|
||||
boot.thin.enable = true;
|
||||
dmeventd.enable = true;
|
||||
};
|
||||
fstrim.enable = true;
|
||||
};
|
||||
|
||||
systemd.network = {
|
||||
links = {
|
||||
"10-wan" = {
|
||||
matchConfig = {
|
||||
# Matching against MAC address seems to break VLAN interfaces
|
||||
# (since they share the same MAC address)
|
||||
Driver = "virtio_net";
|
||||
PermanentMACAddress = "e0:d5:5e:68:0c:6e";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "wan";
|
||||
RxBufferSize = 4096;
|
||||
TxBufferSize = 4096;
|
||||
};
|
||||
};
|
||||
|
||||
"10-lan" = {
|
||||
matchConfig = {
|
||||
Driver = "mlx5_core";
|
||||
PermanentMACAddress = "52:54:00:8a:8a:f2";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "lan";
|
||||
MTUBytes = toString lib.my.c.home.hiMTU;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# So we don't drop the IP we use to connect to NVMe-oF!
|
||||
networks."60-lan-hi".networkConfig.KeepConfiguration = "static";
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIP9uFa4z9WPuXRFVA+PClQSitQCSPckhKTxo1Hq585Oa";
|
||||
};
|
||||
server.enable = true;
|
||||
nvme = {
|
||||
uuid = "12b52d80-ccb6-418d-9b2e-2be34bff3cd9";
|
||||
boot = {
|
||||
nqn = "nqn.2016-06.io.spdk:river";
|
||||
address = "192.168.68.80";
|
||||
};
|
||||
};
|
||||
|
||||
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";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
imports = [
|
||||
# ./unifi.nix
|
||||
./hass.nix
|
||||
];
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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)
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,406 +0,0 @@
|
||||
index: { lib, allAssignments, ... }:
|
||||
let
|
||||
inherit (builtins) elemAt;
|
||||
inherit (lib.my) net mkVLAN;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.home) domain vlans prefixes vips routers routersPubV4;
|
||||
|
||||
name = elemAt routers index;
|
||||
otherIndex = 1 - index;
|
||||
in
|
||||
{
|
||||
nixos.systems."${name}" = {
|
||||
assignments = {
|
||||
modem = {
|
||||
ipv4 = {
|
||||
address = net.cidr.host (254 - index) prefixes.modem.v4;
|
||||
gateway = null;
|
||||
};
|
||||
};
|
||||
core = {
|
||||
name = "${name}-core";
|
||||
inherit domain;
|
||||
mtu = 1500;
|
||||
ipv4 = {
|
||||
address = net.cidr.host (index + 1) prefixes.core.v4;
|
||||
gateway = null;
|
||||
};
|
||||
};
|
||||
hi = {
|
||||
name = "${name}-hi";
|
||||
inherit domain;
|
||||
mtu = 9000;
|
||||
ipv4 = {
|
||||
address = net.cidr.host (index + 1) prefixes.hi.v4;
|
||||
mask = 22;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6.address = net.cidr.host (index + 1) prefixes.hi.v6;
|
||||
};
|
||||
lo = {
|
||||
name = "${name}-lo";
|
||||
inherit domain;
|
||||
mtu = 1500;
|
||||
ipv4 = {
|
||||
address = net.cidr.host (index + 1) prefixes.lo.v4;
|
||||
mask = 21;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6.address = net.cidr.host (index + 1) prefixes.lo.v6;
|
||||
};
|
||||
untrusted = {
|
||||
name = "${name}-ut";
|
||||
inherit domain;
|
||||
mtu = 1500;
|
||||
ipv4 = {
|
||||
address = net.cidr.host (index + 1) prefixes.untrusted.v4;
|
||||
mask = 24;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6.address = net.cidr.host (index + 1) prefixes.untrusted.v6;
|
||||
};
|
||||
as211024 = {
|
||||
ipv4 = {
|
||||
address = net.cidr.host (index + 2) prefixes.as211024.v4;
|
||||
gateway = null;
|
||||
};
|
||||
ipv6 = {
|
||||
address = net.cidr.host ((1*65536*65536*65536) + index + 1) prefixes.as211024.v6;
|
||||
gateway = net.cidr.host ((2*65536*65536*65536) + 1) prefixes.as211024.v6;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
extraAssignments = {
|
||||
router-hi.hi = {
|
||||
name = "router-hi";
|
||||
inherit domain;
|
||||
ipv4 = {
|
||||
address = vips.hi.v4;
|
||||
mask = 22;
|
||||
};
|
||||
ipv6.address = vips.hi.v6;
|
||||
};
|
||||
router-lo.lo = {
|
||||
name = "router-lo";
|
||||
inherit domain;
|
||||
ipv4 = {
|
||||
address = vips.lo.v4;
|
||||
mask = 21;
|
||||
};
|
||||
ipv6.address = vips.lo.v6;
|
||||
};
|
||||
router-ut.untrusted = {
|
||||
name = "router-ut";
|
||||
inherit domain;
|
||||
ipv4.address = vips.untrusted.v4;
|
||||
ipv6.address = vips.untrusted.v6;
|
||||
};
|
||||
};
|
||||
|
||||
configuration = { lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkIf mkMerge mkForce;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
inherit (lib.my.c) networkd;
|
||||
in
|
||||
{
|
||||
imports = map (m: import m index) [
|
||||
./keepalived.nix
|
||||
./dns.nix
|
||||
./radvd.nix
|
||||
./kea.nix
|
||||
];
|
||||
|
||||
config = {
|
||||
environment = {
|
||||
systemPackages = with pkgs; [
|
||||
ethtool
|
||||
conntrack-tools
|
||||
];
|
||||
};
|
||||
|
||||
services = {
|
||||
resolved.settings.Resolve = {
|
||||
LLMNR = false;
|
||||
MulticastDNS = false;
|
||||
};
|
||||
|
||||
iperf3 = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
networkd-dispatcher = {
|
||||
enable = true;
|
||||
rules = {
|
||||
# tc filter hasn't been networkd-ified yet
|
||||
setup-wan-mirror = {
|
||||
onState = [ "configured" ];
|
||||
script = ''
|
||||
#!${pkgs.runtimeShell}
|
||||
if [ "$IFACE" = "wan-ifb" ]; then
|
||||
${pkgs.iproute2}/bin/tc filter add dev wan parent ffff: matchall action mirred egress redirect dev "$IFACE"
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
nginx.enable = true;
|
||||
};
|
||||
|
||||
networking = { inherit domain; };
|
||||
|
||||
systemd.services =
|
||||
let
|
||||
waitOnline = "systemd-networkd-wait-online@wan.service";
|
||||
in
|
||||
{
|
||||
ipsec = {
|
||||
after = [ 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 = {
|
||||
wait-online.enable = false;
|
||||
config = {
|
||||
networkConfig = {
|
||||
ManageForeignRoutes = false;
|
||||
};
|
||||
};
|
||||
|
||||
netdevs = mkMerge [
|
||||
{
|
||||
"25-wan-ifb".netdevConfig = {
|
||||
Name = "wan-ifb";
|
||||
Kind = "ifb";
|
||||
};
|
||||
"30-lan-core".netdevConfig = {
|
||||
Name = "lan-core";
|
||||
Kind = "macvlan";
|
||||
MTUBytes = "1500";
|
||||
};
|
||||
}
|
||||
|
||||
(mkVLAN "lan-hi" vlans.hi)
|
||||
(mkVLAN "lan-lo" vlans.lo)
|
||||
(mkVLAN "lan-untrusted" vlans.untrusted)
|
||||
];
|
||||
|
||||
networks =
|
||||
let
|
||||
mkVLANConfig = name:
|
||||
let
|
||||
iface = "lan-${name}";
|
||||
in
|
||||
{
|
||||
"60-${iface}" = mkMerge [
|
||||
(networkdAssignment iface assignments."${name}")
|
||||
{
|
||||
dns = [ "127.0.0.1" "::1" ];
|
||||
domains = [ config.networking.domain ];
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
}
|
||||
];
|
||||
};
|
||||
in
|
||||
mkMerge [
|
||||
{
|
||||
"50-wan-ifb" = {
|
||||
matchConfig.Name = "wan-ifb";
|
||||
networkConfig = networkd.noL3;
|
||||
extraConfig = ''
|
||||
[CAKE]
|
||||
Bandwidth=490M
|
||||
RTTSec=50ms
|
||||
PriorityQueueingPreset=besteffort
|
||||
# DOCSIS preset
|
||||
OverheadBytes=18
|
||||
MPUBytes=64
|
||||
CompensationMode=none
|
||||
'';
|
||||
};
|
||||
"50-wan" = mkMerge [
|
||||
(networkdAssignment "wan" assignments.modem)
|
||||
{
|
||||
matchConfig.Name = "wan";
|
||||
DHCP = "ipv4";
|
||||
dns = [ "127.0.0.1" "::1" ];
|
||||
dhcpV4Config.UseDNS = false;
|
||||
|
||||
qdiscConfig = {
|
||||
Parent = "ingress";
|
||||
Handle = "0xffff";
|
||||
};
|
||||
extraConfig = ''
|
||||
[CAKE]
|
||||
Parent=root
|
||||
Bandwidth=48M
|
||||
RTTSec=50ms
|
||||
'';
|
||||
}
|
||||
];
|
||||
|
||||
"55-lan" = {
|
||||
matchConfig.Name = "lan";
|
||||
vlan = [ "lan-hi" "lan-lo" "lan-untrusted" "wan-tunnel" ];
|
||||
macvlan = [ "lan-core" ];
|
||||
networkConfig = networkd.noL3;
|
||||
};
|
||||
"60-lan-core" = mkMerge [
|
||||
(networkdAssignment "lan-core" assignments.core)
|
||||
{
|
||||
matchConfig.Name = "lan-core";
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
}
|
||||
];
|
||||
|
||||
"90-l2mesh-as211024" = mkMerge [
|
||||
(networkdAssignment "as211024" assignments.as211024)
|
||||
{
|
||||
matchConfig.Name = "as211024";
|
||||
networkConfig.IPv6AcceptRA = mkForce false;
|
||||
routes = [
|
||||
{
|
||||
Destination = lib.my.c.colony.prefixes.all.v4;
|
||||
Gateway = allAssignments.estuary.as211024.ipv4.address;
|
||||
}
|
||||
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v4;
|
||||
Gateway = allAssignments.britway.as211024.ipv4.address;
|
||||
}
|
||||
{
|
||||
Destination = lib.my.c.tailscale.prefix.v6;
|
||||
Gateway = allAssignments.britway.as211024.ipv6.address;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
(mkVLANConfig "hi")
|
||||
(mkVLANConfig "lo")
|
||||
(mkVLANConfig "untrusted")
|
||||
|
||||
{
|
||||
"60-lan-hi" = {
|
||||
routes = [
|
||||
{
|
||||
Destination = elemAt routersPubV4 otherIndex;
|
||||
Gateway = net.cidr.host (otherIndex + 1) prefixes.hi.v4;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
files = {
|
||||
"l2mesh/as211024.key" = {};
|
||||
};
|
||||
};
|
||||
|
||||
vpns = {
|
||||
l2.pskFiles = {
|
||||
as211024 = config.age.secrets."l2mesh/as211024.key".path;
|
||||
};
|
||||
};
|
||||
firewall = {
|
||||
trustedInterfaces = [ "lan-hi" "lan-lo" ];
|
||||
udp.allowed = [ 5353 ];
|
||||
tcp.allowed = [ 5353 ];
|
||||
nat = {
|
||||
enable = true;
|
||||
externalInterface = "wan";
|
||||
};
|
||||
extraRules =
|
||||
let
|
||||
aa = allAssignments;
|
||||
in
|
||||
''
|
||||
table inet filter {
|
||||
chain input {
|
||||
${lib.my.c.as211024.nftTrust}
|
||||
iifname base meta l4proto { udp, tcp } th dport domain accept
|
||||
iifname lan-core meta l4proto vrrp accept
|
||||
}
|
||||
|
||||
chain routing-tcp {
|
||||
ip daddr {
|
||||
${aa.castle.hi.ipv4.address},
|
||||
${aa.cellar.hi.ipv4.address},
|
||||
${aa.palace.hi.ipv4.address}
|
||||
} tcp dport ssh accept
|
||||
ip6 daddr {
|
||||
${aa.castle.hi.ipv6.address},
|
||||
${aa.cellar.hi.ipv6.address},
|
||||
${aa.palace.hi.ipv6.address}
|
||||
} tcp dport ssh accept
|
||||
|
||||
return
|
||||
}
|
||||
chain routing-udp {
|
||||
return
|
||||
}
|
||||
chain filter-routing {
|
||||
tcp flags & (fin|syn|rst|ack) == syn ct state new jump routing-tcp
|
||||
meta l4proto udp ct state new jump routing-udp
|
||||
return
|
||||
}
|
||||
chain filter-untrusted {
|
||||
ip daddr ${prefixes.modem.v4} reject
|
||||
oifname wan accept
|
||||
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 {
|
||||
${lib.my.c.as211024.nftTrust}
|
||||
iifname lan-untrusted jump filter-untrusted
|
||||
iifname { wan, as211024, lan-untrusted } oifname { lan-hi, lan-lo } jump filter-routing
|
||||
oifname as211024 accept
|
||||
}
|
||||
chain output { }
|
||||
}
|
||||
table inet nat {
|
||||
chain prerouting {
|
||||
ip daddr ${elemAt routersPubV4 index} meta l4proto { udp, tcp } th dport domain redirect to :5353
|
||||
ip6 daddr ${assignments.as211024.ipv6.address} meta l4proto { udp, tcp } th dport domain redirect to :5353
|
||||
}
|
||||
chain postrouting {
|
||||
oifname wan masquerade
|
||||
}
|
||||
}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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
|
||||
@@ -1,291 +0,0 @@
|
||||
index: { lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (builtins) attrNames elemAt;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c) pubDomain;
|
||||
inherit (lib.my.c.home) prefixes vips routers;
|
||||
|
||||
name = elemAt routers index;
|
||||
otherIndex = 1 - index;
|
||||
otherName = elemAt routers otherIndex;
|
||||
|
||||
authZones = attrNames config.my.pdns.auth.bind.zones;
|
||||
in
|
||||
{
|
||||
config = {
|
||||
my = {
|
||||
secrets.files = {
|
||||
"home/pdns/auth.conf" = {
|
||||
owner = "pdns";
|
||||
group = "pdns";
|
||||
};
|
||||
"home/pdns/recursor.yml" = {
|
||||
owner = "pdns-recursor";
|
||||
group = "pdns-recursor";
|
||||
};
|
||||
"home/ddclient-cloudflare.key" = {};
|
||||
};
|
||||
|
||||
pdns.recursor = {
|
||||
enable = true;
|
||||
extraSettingsFile = config.age.secrets."home/pdns/recursor.yml".path;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
pdns-recursor = {
|
||||
yaml-settings = {
|
||||
incoming = {
|
||||
listen = [
|
||||
"127.0.0.1" "::1"
|
||||
assignments.hi.ipv4.address assignments.hi.ipv6.address
|
||||
assignments.lo.ipv4.address assignments.lo.ipv6.address
|
||||
];
|
||||
allow_from = [
|
||||
"127.0.0.0/8" "::1/128"
|
||||
prefixes.hi.v4 prefixes.hi.v6
|
||||
prefixes.lo.v4 prefixes.lo.v6
|
||||
] ++ (with lib.my.c.tailscale.prefix; [ v4 v6 ]);
|
||||
|
||||
# DNS NOTIFY messages override TTL
|
||||
allow_notify_for = authZones;
|
||||
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;
|
||||
address = "::";
|
||||
allow_from = [ "127.0.0.1" "::1" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
# Add AF_NETLINK to allow pulling IP from network interfaces
|
||||
pdns.serviceConfig.RestrictAddressFamilies = "AF_UNIX AF_INET AF_INET6 AF_NETLINK";
|
||||
ddns-update = {
|
||||
description = "DNS update script";
|
||||
after = [ "network.target" ];
|
||||
path = [
|
||||
(pkgs.python3.withPackages (ps: [ ps.cloudflare ]))
|
||||
pkgs.ldns
|
||||
];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
ExecStart =
|
||||
''${./dns_update.py} -k ${config.age.secrets."home/ddclient-cloudflare.key".path} '' +
|
||||
''${pubDomain} ns${toString (index + 1)}.${config.networking.domain}'';
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
timers = {
|
||||
ddns-update = {
|
||||
description = "Periodically update DNS";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnBootSec = "5min";
|
||||
OnUnitInactiveSec = "5min";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# For rec_control
|
||||
pdns-recursor
|
||||
sqlite
|
||||
];
|
||||
|
||||
my.pdns.auth = {
|
||||
enable = true;
|
||||
extraSettingsFile = config.age.secrets."home/pdns/auth.conf".path;
|
||||
settings = {
|
||||
primary = true;
|
||||
resolver = "127.0.0.1";
|
||||
expand-alias = true;
|
||||
local-address = [
|
||||
"0.0.0.0:5353" "[::]:5353"
|
||||
];
|
||||
also-notify = [ "127.0.0.1" ];
|
||||
enable-lua-records = true;
|
||||
# loglevel = 7;
|
||||
# log-dns-queries = true;
|
||||
# log-dns-details = true;
|
||||
|
||||
api = true;
|
||||
webserver = true;
|
||||
webserver-address = "::";
|
||||
webserver-allow-from = [ "127.0.0.1" "::1" ];
|
||||
|
||||
dnsupdate = true;
|
||||
launch = [ "gsqlite3" ];
|
||||
gsqlite3-database = "/var/lib/pdns/dynamic.sqlite3";
|
||||
};
|
||||
|
||||
bind.zones =
|
||||
let
|
||||
names = [ "core" "hi" "lo" "untrusted" ];
|
||||
i = toString (index + 1);
|
||||
in
|
||||
{
|
||||
"${config.networking.domain}" = {
|
||||
type = "master";
|
||||
text = ''
|
||||
$TTL 60
|
||||
@ IN SOA ns${i}.${config.networking.domain}. dev.nul.ie. (
|
||||
@@SERIAL@@ ; serial
|
||||
3h ; refresh
|
||||
1h ; retry
|
||||
1w ; expire
|
||||
1h ; minimum
|
||||
)
|
||||
|
||||
${name} IN LUA ${lib.my.dns.ifaceA {
|
||||
inherit pkgs;
|
||||
iface = "wan";
|
||||
skipBroadcasts = [ (lib.my.netBroadcast prefixes.modem.v4) ];
|
||||
}}
|
||||
${otherName} IN LUA ${lib.my.dns.lookupIP {
|
||||
inherit pkgs;
|
||||
hostname = "${otherName}.${config.networking.domain}";
|
||||
server = net.cidr.host (otherIndex + 1) prefixes.hi.v4;
|
||||
}}
|
||||
${elemAt routers 0} IN AAAA ${allAssignments."${elemAt routers 0}".as211024.ipv6.address}
|
||||
${elemAt routers 1} IN AAAA ${allAssignments."${elemAt routers 1}".as211024.ipv6.address}
|
||||
boot IN CNAME river-hi.${config.networking.domain}.
|
||||
|
||||
@ IN NS ns1
|
||||
@ IN NS ns2
|
||||
ns1 IN ALIAS ${elemAt routers 0}.${config.networking.domain}.
|
||||
ns2 IN ALIAS ${elemAt routers 1}.${config.networking.domain}.
|
||||
|
||||
dyn IN NS ns1.dyn.h.nul.ie.
|
||||
dyn IN NS ns2.dyn.h.nul.ie.
|
||||
ns1.dyn.h.nul.ie. IN ALIAS ${elemAt routers 0}.${config.networking.domain}.
|
||||
ns2.dyn.h.nul.ie. IN ALIAS ${elemAt routers 1}.${config.networking.domain}.
|
||||
|
||||
jim-core IN A ${net.cidr.host 10 prefixes.core.v4}
|
||||
jim IN A ${net.cidr.host 10 prefixes.hi.v4}
|
||||
jim IN AAAA ${net.cidr.host (65536+1) prefixes.hi.v6}
|
||||
jim-lo IN A ${net.cidr.host 10 prefixes.lo.v4}
|
||||
jim-lo IN AAAA ${net.cidr.host (65536+1) prefixes.lo.v6}
|
||||
|
||||
dave-core IN A ${net.cidr.host 11 prefixes.core.v4}
|
||||
dave IN A ${net.cidr.host 11 prefixes.hi.v4}
|
||||
dave IN AAAA ${net.cidr.host (65536+2) prefixes.hi.v6}
|
||||
dave-lo IN A ${net.cidr.host 11 prefixes.lo.v4}
|
||||
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}
|
||||
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 {
|
||||
inherit allAssignments names;
|
||||
domain = config.networking.domain;
|
||||
}}
|
||||
'';
|
||||
};
|
||||
"168.192.in-addr.arpa" = {
|
||||
type = "master";
|
||||
text = ''
|
||||
$TTL 60
|
||||
@ IN SOA ns${i}.${config.networking.domain}. dev.nul.ie. (
|
||||
@@SERIAL@@ ; serial
|
||||
3h ; refresh
|
||||
1h ; retry
|
||||
1w ; expire
|
||||
1h ; minimum
|
||||
)
|
||||
|
||||
@ IN NS ns1.${config.networking.domain}.
|
||||
@ IN NS ns2.${config.networking.domain}.
|
||||
|
||||
${lib.my.dns.ptrRecords {
|
||||
inherit allAssignments names;
|
||||
domain = config.networking.domain;
|
||||
ndots = 2;
|
||||
}}
|
||||
'';
|
||||
};
|
||||
"0.d.4.0.0.c.7.9.e.0.a.2.ip6.arpa" = {
|
||||
type = "master";
|
||||
text = ''
|
||||
$TTL 60
|
||||
@ IN SOA ns${i}.${config.networking.domain}. dev.nul.ie. (
|
||||
@@SERIAL@@ ; serial
|
||||
3h ; refresh
|
||||
1h ; retry
|
||||
1w ; expire
|
||||
1h ; minimum
|
||||
)
|
||||
|
||||
@ IN NS ns1.${config.networking.domain}.
|
||||
@ IN NS ns2.${config.networking.domain}.
|
||||
|
||||
${lib.my.dns.ptr6Records {
|
||||
inherit allAssignments names;
|
||||
domain = config.networking.domain;
|
||||
ndots = 20;
|
||||
}}
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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, name=args.record,
|
||||
type='A', content=address)
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -1,214 +0,0 @@
|
||||
index: { lib, pkgs, config, assignments, allAssignments, ... }:
|
||||
let
|
||||
inherit (lib) mkForce;
|
||||
inherit (lib.my) net netbootKeaClientClasses;
|
||||
inherit (lib.my.c.home) domain prefixes vips hiMTU;
|
||||
|
||||
dns-servers = [
|
||||
{
|
||||
ip-address = net.cidr.host 1 prefixes.core.v4;
|
||||
port = 5353;
|
||||
}
|
||||
{
|
||||
ip-address = net.cidr.host 2 prefixes.core.v4;
|
||||
port = 5353;
|
||||
}
|
||||
];
|
||||
in
|
||||
{
|
||||
users = with lib.my.c.ids; {
|
||||
users.kea= {
|
||||
isSystemUser = true;
|
||||
uid = uids.kea;
|
||||
group = "kea";
|
||||
};
|
||||
groups.kea.gid = gids.kea;
|
||||
};
|
||||
|
||||
systemd.services = {
|
||||
kea-dhcp4-server.serviceConfig = {
|
||||
# Sometimes interfaces might not be ready in time and Kea doesn't like that
|
||||
Restart = "on-failure";
|
||||
DynamicUser = mkForce false;
|
||||
};
|
||||
kea-dhcp-ddns-server.serviceConfig.DynamicUser = mkForce false;
|
||||
};
|
||||
|
||||
services = {
|
||||
kea = {
|
||||
dhcp4 = {
|
||||
enable = true;
|
||||
settings = {
|
||||
interfaces-config = {
|
||||
interfaces = [
|
||||
"lan-hi/${assignments.hi.ipv4.address}"
|
||||
"lan-lo/${assignments.lo.ipv4.address}"
|
||||
"lan-untrusted/${assignments.untrusted.ipv4.address}"
|
||||
];
|
||||
};
|
||||
lease-database = {
|
||||
type = "memfile";
|
||||
persist = true;
|
||||
name = "/var/lib/kea/dhcp.leases";
|
||||
};
|
||||
|
||||
option-data = [
|
||||
{
|
||||
name = "domain-name";
|
||||
data = domain;
|
||||
}
|
||||
{
|
||||
name = "domain-search";
|
||||
data = "${domain}, dyn.${domain}, ${lib.my.c.colony.domain}, ${lib.my.c.britway.domain}";
|
||||
always-send = true;
|
||||
}
|
||||
];
|
||||
client-classes = netbootKeaClientClasses {
|
||||
tftpIP = allAssignments.river.lo.ipv4.address;
|
||||
hostname = "boot.${domain}";
|
||||
systems = {
|
||||
sfh = "52:54:00:a5:7e:93";
|
||||
castle = "c8:7f:54:6e:17:0f";
|
||||
};
|
||||
};
|
||||
subnet4 = [
|
||||
{
|
||||
id = 1;
|
||||
subnet = prefixes.hi.v4;
|
||||
interface = "lan-hi";
|
||||
option-data = [
|
||||
{
|
||||
name = "routers";
|
||||
data = vips.hi.v4;
|
||||
}
|
||||
{
|
||||
name = "domain-name-servers";
|
||||
data = "${net.cidr.host 1 prefixes.hi.v4}, ${net.cidr.host 2 prefixes.hi.v4}";
|
||||
}
|
||||
{
|
||||
name = "interface-mtu";
|
||||
data = toString hiMTU;
|
||||
}
|
||||
];
|
||||
pools = [
|
||||
{
|
||||
pool = if index == 0
|
||||
then "192.168.68.120 - 192.168.69.255"
|
||||
else "192.168.70.0 - 192.168.71.240";
|
||||
}
|
||||
];
|
||||
reservations = [
|
||||
{
|
||||
# castle
|
||||
hw-address = "24:8a:07:a8:fe:3a";
|
||||
ip-address = net.cidr.host 40 prefixes.hi.v4;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
id = 2;
|
||||
subnet = prefixes.lo.v4;
|
||||
interface = "lan-lo";
|
||||
option-data = [
|
||||
{
|
||||
name = "routers";
|
||||
data = vips.lo.v4;
|
||||
}
|
||||
{
|
||||
name = "domain-name-servers";
|
||||
data = "${net.cidr.host 1 prefixes.lo.v4}, ${net.cidr.host 2 prefixes.lo.v4}";
|
||||
}
|
||||
];
|
||||
pools = [
|
||||
{
|
||||
pool = if index == 0
|
||||
then "192.168.72.120 - 192.168.75.255"
|
||||
else "192.168.76.0 - 192.168.79.240";
|
||||
}
|
||||
];
|
||||
reservations = [
|
||||
{
|
||||
# castle
|
||||
hw-address = "24:8a:07:a8:fe:3a";
|
||||
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;
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
id = 3;
|
||||
subnet = prefixes.untrusted.v4;
|
||||
interface = "lan-untrusted";
|
||||
option-data = [
|
||||
{
|
||||
name = "routers";
|
||||
data = vips.untrusted.v4;
|
||||
}
|
||||
{
|
||||
name = "domain-name-servers";
|
||||
data = "1.1.1.1, 1.0.0.1";
|
||||
}
|
||||
];
|
||||
pools = [
|
||||
{
|
||||
pool = if index == 0
|
||||
then "192.168.80.10 - 192.168.80.127"
|
||||
else "192.168.80.128 - 192.168.80.250";
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
ddns-send-updates = true;
|
||||
ddns-replace-client-name = "when-not-present";
|
||||
ddns-qualifying-suffix = "dyn.${domain}";
|
||||
ddns-generated-prefix = "ip";
|
||||
ddns-update-on-renew = true;
|
||||
|
||||
dhcp-ddns.enable-updates = true;
|
||||
};
|
||||
};
|
||||
|
||||
dhcp-ddns = {
|
||||
enable = true;
|
||||
settings = {
|
||||
forward-ddns.ddns-domains = [
|
||||
{
|
||||
name = "dyn.${domain}.";
|
||||
inherit dns-servers;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,83 +0,0 @@
|
||||
index: { lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (builtins) attrNames concatMap length;
|
||||
inherit (lib) optional concatMapStringsSep;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.home) prefixes vips;
|
||||
|
||||
pingScriptFor = name: ips:
|
||||
let
|
||||
script' = pkgs.writeShellScript
|
||||
"keepalived-ping-${name}"
|
||||
(concatMapStringsSep " || " (ip: "${pkgs.iputils}/bin/ping -qnc 1 -W 1 ${ip}") ips);
|
||||
in
|
||||
{
|
||||
script = toString script';
|
||||
interval = 1;
|
||||
timeout = (length ips) + 1;
|
||||
rise = 3;
|
||||
fall = 3;
|
||||
};
|
||||
|
||||
vlanIface = vlan: if vlan == "as211024" then vlan else "lan-${vlan}";
|
||||
vrrpIPs = family: concatMap (vlan: [
|
||||
{
|
||||
addr = "${vips.${vlan}.${family}}/${toString (net.cidr.length prefixes.${vlan}.${family})}";
|
||||
dev = vlanIface vlan;
|
||||
}
|
||||
]) (attrNames vips);
|
||||
mkVRRP = family: routerId: {
|
||||
state = if index == 0 then "MASTER" else "BACKUP";
|
||||
interface = "lan-core";
|
||||
priority = 255 - index;
|
||||
virtualRouterId = routerId;
|
||||
virtualIps = vrrpIPs family;
|
||||
trackScripts = [ "${family}Alive" ];
|
||||
};
|
||||
in
|
||||
{
|
||||
users = with lib.my.c.ids; {
|
||||
users.keepalived_script = {
|
||||
uid = uids.keepalived_script;
|
||||
isSystemUser = true;
|
||||
group = "keepalived_script";
|
||||
};
|
||||
groups.keepalived_script.gid = gids.keepalived_script;
|
||||
};
|
||||
|
||||
services = {
|
||||
keepalived = {
|
||||
enable = true;
|
||||
enableScriptSecurity = true;
|
||||
extraGlobalDefs = ''
|
||||
vrrp_version 3
|
||||
nftables keepalived
|
||||
'';
|
||||
vrrpScripts = {
|
||||
v4Alive = pingScriptFor "v4" [ "1.1.1.1" "8.8.8.8" "216.218.236.2" ];
|
||||
v6Alive = pingScriptFor "v6" [ "2606:4700:4700::1111" "2001:4860:4860::8888" "2600::" ];
|
||||
};
|
||||
vrrpInstances = {
|
||||
v4 = mkVRRP "v4" 51;
|
||||
v6 = (mkVRRP "v6" 52) // {
|
||||
extraConfig = ''
|
||||
virtual_ipaddress_excluded {
|
||||
${concatMapStringsSep "\n" (vlan: "fe80::1/64 dev ${vlanIface vlan}") (attrNames vips)}
|
||||
}
|
||||
notify_master "${config.systemd.package}/bin/systemctl start radvd.service" root
|
||||
notify_backup "${config.systemd.package}/bin/systemctl stop radvd.service" root
|
||||
'';
|
||||
};
|
||||
};
|
||||
# Actually disable this for now, don't want to fault IPv4 just because IPv6 is broken...
|
||||
# extraConfig = ''
|
||||
# vrrp_sync_group main {
|
||||
# group {
|
||||
# v4
|
||||
# v6
|
||||
# }
|
||||
# }
|
||||
# '';
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,53 +0,0 @@
|
||||
{ lib, pkgs, ... }:
|
||||
let
|
||||
# TODO: Move into nixpkgs
|
||||
mstpd = pkgs.mstpd.overrideAttrs {
|
||||
patches = [ ./mstpd.patch ];
|
||||
};
|
||||
in
|
||||
{
|
||||
environment = {
|
||||
systemPackages = [
|
||||
mstpd
|
||||
];
|
||||
etc = {
|
||||
"bridge-stp.conf".text = ''
|
||||
MANAGE_MSTPD=n
|
||||
MSTP_BRIDGES=lan
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
networkd-dispatcher.rules = {
|
||||
configure-mstpd = {
|
||||
onState = [ "routable" ];
|
||||
script = ''
|
||||
#!${pkgs.runtimeShell}
|
||||
if [ "$IFACE" = "lan" ]; then
|
||||
${mstpd}/sbin/mstpctl setforcevers "$IFACE" rstp
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd = {
|
||||
services = {
|
||||
mstpd = {
|
||||
description = "MSTP daemon";
|
||||
before = [ "network-pre.target" ];
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
ExecStart = "${mstpd}/sbin/bridge-stp restart";
|
||||
ExecReload = "${mstpd}/sbin/bridge-stp restart_config";
|
||||
PIDFile = "/run/mstpd.pid";
|
||||
Restart = "always";
|
||||
PrivateTmp = true;
|
||||
ProtectHome = true;
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
diff --git a/bridge-stp.in b/bridge-stp.in
|
||||
index 3807873..9c73126 100755
|
||||
--- a/bridge-stp.in
|
||||
+++ b/bridge-stp.in
|
||||
@@ -31,6 +31,10 @@
|
||||
# bridge or any associated kernel network interfaces in any code paths that are
|
||||
# used when this script is called by the kernel.
|
||||
|
||||
+# Ensure that we have a sane PATH.
|
||||
+PATH='/run/current-system/sw/bin'
|
||||
+export PATH
|
||||
+
|
||||
# Parse arguments.
|
||||
CalledAs="$(basename "$0")"
|
||||
if [ "$CalledAs" = 'mstpctl_restart_config' ]; then
|
||||
@@ -62,10 +66,6 @@ fi
|
||||
# Ensure that we have a sane umask.
|
||||
umask 022
|
||||
|
||||
-# Ensure that we have a sane PATH.
|
||||
-PATH='/sbin:/usr/sbin:/bin:/usr/bin'
|
||||
-export PATH
|
||||
-
|
||||
# Define some relevant paths.
|
||||
mstpctl='@mstpctlfile@'
|
||||
mstpd='@mstpdfile@'
|
||||
@@ -1,28 +0,0 @@
|
||||
index: { lib, pkgs, ... }:
|
||||
let
|
||||
inherit (lib) mkForce concatMapStringsSep;
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.home) domain prefixes;
|
||||
|
||||
mkInterface = name: ''
|
||||
interface lan-${name} {
|
||||
AdvSendAdvert on;
|
||||
AdvRASrcAddress { fe80::1; };
|
||||
AdvLinkMTU ${toString prefixes."${name}".mtu};
|
||||
prefix ${prefixes."${name}".v6} {};
|
||||
RDNSS ${net.cidr.host 1 prefixes."${name}".v6} ${net.cidr.host 2 prefixes."${name}".v6} {};
|
||||
DNSSL ${domain} dyn.${domain} ${lib.my.c.colony.domain} ${lib.my.c.britway.domain} {};
|
||||
};
|
||||
'';
|
||||
in
|
||||
{
|
||||
# To be started by keepalived
|
||||
systemd.services.radvd.wantedBy = mkForce [ ];
|
||||
|
||||
services = {
|
||||
radvd = {
|
||||
enable = true;
|
||||
config = concatMapStringsSep "\n" mkInterface [ "hi" "lo" "untrusted" ];
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,163 +0,0 @@
|
||||
{
|
||||
imports = [ (import ./routing-common 1) ];
|
||||
|
||||
config.nixos.systems.stream = {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
home-manager = "mine";
|
||||
|
||||
configuration = { lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (lib);
|
||||
in
|
||||
{
|
||||
imports = [ ./routing-common/mstpd.nix ];
|
||||
|
||||
config = {
|
||||
boot = {
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
kernelParams = [ "intel_iommu=on" ];
|
||||
initrd.availableKernelModules = [ "xhci_pci" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" ];
|
||||
};
|
||||
|
||||
hardware = {
|
||||
enableRedistributableFirmware = true;
|
||||
cpu = {
|
||||
intel.updateMicrocode = true;
|
||||
};
|
||||
};
|
||||
|
||||
fileSystems = {
|
||||
"/boot" = {
|
||||
device = "/dev/disk/by-partuuid/fe081885-9157-46b5-be70-46ac6fcb4069";
|
||||
fsType = "vfat";
|
||||
};
|
||||
"/nix" = {
|
||||
device = "/dev/disk/by-partuuid/a195e55e-397f-440d-a190-59ffa63cdb3f";
|
||||
fsType = "ext4";
|
||||
};
|
||||
"/persist" = {
|
||||
device = "/dev/disk/by-partuuid/ad71fafd-2d26-49c8-b0cb-794a28e0beb7";
|
||||
fsType = "ext4";
|
||||
neededForBoot = true;
|
||||
};
|
||||
};
|
||||
|
||||
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 = {
|
||||
netdevs = {
|
||||
"25-lan" = {
|
||||
netdevConfig = {
|
||||
Name = "lan";
|
||||
Kind = "bridge";
|
||||
};
|
||||
extraConfig = ''
|
||||
[Bridge]
|
||||
STP=true
|
||||
'';
|
||||
};
|
||||
};
|
||||
links = {
|
||||
"10-wan" = {
|
||||
matchConfig = {
|
||||
# Matching against MAC address seems to break VLAN interfaces
|
||||
# (since they share the same MAC address)
|
||||
Driver = "igc";
|
||||
PermanentMACAddress = "00:f0:cb:ee:ca:dd";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "wan";
|
||||
RxBufferSize = 4096;
|
||||
TxBufferSize = 4096;
|
||||
};
|
||||
};
|
||||
"10-lan-jim" = {
|
||||
matchConfig = {
|
||||
Driver = "igc";
|
||||
PermanentMACAddress = "00:f0:cb:ee:ca:de";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "lan-jim";
|
||||
MTUBytes = toString lib.my.c.home.hiMTU;
|
||||
};
|
||||
};
|
||||
"10-et2" = {
|
||||
matchConfig = {
|
||||
Driver = "igc";
|
||||
PermanentMACAddress = "00:f0:cb:ee:ca:df";
|
||||
};
|
||||
linkConfig.Name = "et2";
|
||||
};
|
||||
|
||||
"10-lan-dave" = {
|
||||
matchConfig = {
|
||||
Driver = "mlx4_en";
|
||||
PermanentMACAddress = "00:02:c9:d5:b1:d6";
|
||||
};
|
||||
linkConfig = {
|
||||
Name = "lan-dave";
|
||||
MTUBytes = toString lib.my.c.home.hiMTU;
|
||||
};
|
||||
};
|
||||
"10-et5" = {
|
||||
matchConfig = {
|
||||
Driver = "mlx4_en";
|
||||
PermanentMACAddress = "00:02:c9:d5:b1:d7";
|
||||
};
|
||||
linkConfig.Name = "et5";
|
||||
};
|
||||
};
|
||||
networks = {
|
||||
"50-lan-jim" = {
|
||||
matchConfig.Name = "lan-jim";
|
||||
networkConfig.Bridge = "lan";
|
||||
};
|
||||
"50-lan-dave" = {
|
||||
matchConfig.Name = "lan-dave";
|
||||
networkConfig.Bridge = "lan";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPYTB4zeAqotrEJ8M+AiGm/s9PFsWlAodz3hYSROGuDb";
|
||||
};
|
||||
server.enable = true;
|
||||
# deploy.node.hostname = "192.168.68.2";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -26,10 +26,10 @@ in
|
||||
|
||||
config = {
|
||||
# Hardware acceleration for Jellyfin
|
||||
hardware.graphics = {
|
||||
hardware.opengl = {
|
||||
enable = true;
|
||||
extraPackages = with pkgs; [
|
||||
intel-vaapi-driver
|
||||
vaapiIntel
|
||||
intel-ocl
|
||||
];
|
||||
};
|
||||
@@ -65,31 +65,16 @@ in
|
||||
systemd = {
|
||||
services = {
|
||||
jackett.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";
|
||||
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 = {
|
||||
transmission = {
|
||||
enable = true;
|
||||
package = pkgs.transmission_4;
|
||||
downloadDirPermissions = null;
|
||||
performanceNetParameters = true;
|
||||
settings = {
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
let
|
||||
inherit (lib) mkMerge mkIf;
|
||||
inherit (lib.my) networkdAssignment;
|
||||
inherit (lib.my.c.kelder) ipv4MTU;
|
||||
|
||||
wg = {
|
||||
keyFile = "kelder/acquisition/airvpn-privkey";
|
||||
@@ -73,12 +72,14 @@ in
|
||||
RouteTable = routeTable;
|
||||
};
|
||||
wireguardPeers = [
|
||||
# AirVPN IE
|
||||
{
|
||||
Endpoint = "146.70.94.2:1637";
|
||||
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
|
||||
PresharedKeyFile = config.age.secrets."${pskFile}".path;
|
||||
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||
# AirVPN IE
|
||||
wireguardPeerConfig = {
|
||||
Endpoint = "146.70.94.2:1637";
|
||||
PublicKey = "PyLCXAQT8KkM4T+dUsOQfn+Ub3pGxfGlxkIApuig+hk=";
|
||||
PresharedKeyFile = config.age.secrets."${pskFile}".path;
|
||||
AllowedIPs = [ "0.0.0.0/0" "::/0" ];
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -88,14 +89,13 @@ in
|
||||
(networkdAssignment "host0" assignments.internal)
|
||||
{
|
||||
networkConfig.DNSDefaultRoute = false;
|
||||
linkConfig.MTUBytes = toString ipv4MTU;
|
||||
}
|
||||
];
|
||||
"90-vpn" = with wg; {
|
||||
matchConfig.Name = "vpn";
|
||||
address = [ "10.161.170.28/32" "fd7d:76ee:e68f:a993:b12d:6d15:c80a:9516/128" ];
|
||||
dns = [ "10.128.0.1" "fd7d:76ee:e68f:a993::1" ];
|
||||
routingPolicyRules = [
|
||||
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
|
||||
{
|
||||
Family = "both";
|
||||
SuppressPrefixLength = 0;
|
||||
|
||||
@@ -88,23 +88,21 @@ in
|
||||
};
|
||||
|
||||
services = {
|
||||
resolved.settings.Resolve = mkForce { };
|
||||
resolved.extraConfig = mkForce "";
|
||||
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
# TODO: Might need to do some bullshit to go from Nextcloud 28 (?) to 32
|
||||
package = pkgs.nextcloud32;
|
||||
package = pkgs.nextcloud27;
|
||||
datadir = "/mnt/storage/nextcloud";
|
||||
hostName = "cloud.${domain}";
|
||||
https = true;
|
||||
config = {
|
||||
extraTrustedDomains = [ "cloud-local.${domain}" ];
|
||||
adminpassFile = config.age.secrets."kelder/nextcloud-root.txt".path;
|
||||
dbtype = "sqlite";
|
||||
defaultPhoneRegion = "IE";
|
||||
};
|
||||
settings = {
|
||||
extraOptions = {
|
||||
updatechecker = false;
|
||||
trusted_domains = [ "cloud-local.${domain}" ];
|
||||
default_phone_region = "IE";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let
|
||||
inherit (builtins) mapAttrs;
|
||||
inherit (lib) mkMerge mkIf mkDefault;
|
||||
inherit (lib.my.c.nginx) baseHttpConfig proxyHeaders;
|
||||
inherit (lib.my.c.nginx) proxyHeaders;
|
||||
inherit (lib.my.c.kelder) domain;
|
||||
in
|
||||
{
|
||||
@@ -39,7 +39,43 @@ in
|
||||
|
||||
# Based on recommended*Settings, but probably better to be explicit about these
|
||||
appendHttpConfig = ''
|
||||
${baseHttpConfig}
|
||||
# NixOS provides a logrotate config that auto-compresses :)
|
||||
log_format main
|
||||
'$remote_addr - $remote_user [$time_local] $scheme "$host" "$request" $status $body_bytes_sent "$http_referer" "$http_user_agent"';
|
||||
access_log /var/log/nginx/access.log main;
|
||||
|
||||
# optimisation
|
||||
sendfile on;
|
||||
tcp_nopush on;
|
||||
tcp_nodelay on;
|
||||
keepalive_timeout 65;
|
||||
|
||||
# gzip
|
||||
gzip on;
|
||||
gzip_proxied any;
|
||||
gzip_comp_level 5;
|
||||
gzip_types
|
||||
application/atom+xml
|
||||
application/javascript
|
||||
application/json
|
||||
application/xml
|
||||
application/xml+rss
|
||||
image/svg+xml
|
||||
text/css
|
||||
text/javascript
|
||||
text/plain
|
||||
text/xml;
|
||||
gzip_vary on;
|
||||
|
||||
# proxying
|
||||
proxy_buffering off;
|
||||
proxy_redirect off;
|
||||
proxy_connect_timeout 60s;
|
||||
proxy_read_timeout 60s;
|
||||
proxy_send_timeout 60s;
|
||||
proxy_http_version 1.1;
|
||||
|
||||
${proxyHeaders}
|
||||
|
||||
# caching
|
||||
proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=CACHE:10m inactive=7d max_size=4g;
|
||||
@@ -84,7 +120,6 @@ in
|
||||
c
|
||||
];
|
||||
acquisition = "http://${allAssignments.kelder-acquisition.internal.ipv4.address}";
|
||||
# This is kinda borked because Virgin Media filters DNS responses with local IPs...
|
||||
localRedirect = to: ''
|
||||
rewrite_by_lua_block {
|
||||
if ngx.var.remote_addr == pub_ip then
|
||||
@@ -104,7 +139,7 @@ in
|
||||
|
||||
"monitor.${domain}" = withAuth {
|
||||
serverAliases = [ "monitor-local.${domain}" ];
|
||||
# extraConfig = localRedirect "monitor-local.${domain}";
|
||||
extraConfig = localRedirect "monitor-local.${domain}";
|
||||
locations = {
|
||||
"/" = {
|
||||
proxyPass = "http://${allAssignments.kelder.ctrs.ipv4.address}:19999";
|
||||
@@ -137,17 +172,17 @@ in
|
||||
};
|
||||
"torrents.${domain}" = withAuth {
|
||||
serverAliases = [ "torrents-local.${domain}" ];
|
||||
# extraConfig = localRedirect "torrents-local.${domain}";
|
||||
extraConfig = localRedirect "torrents-local.${domain}";
|
||||
locations."/".proxyPass = "${acquisition}:9091";
|
||||
};
|
||||
"jackett.${domain}" = withAuth {
|
||||
serverAliases = [ "jackett-local.${domain}" ];
|
||||
# extraConfig = localRedirect "jackett-local.${domain}";
|
||||
extraConfig = localRedirect "jackett-local.${domain}";
|
||||
locations."/".proxyPass = "${acquisition}:9117";
|
||||
};
|
||||
"radarr.${domain}" = withAuth {
|
||||
serverAliases = [ "radarr-local.${domain}" ];
|
||||
# extraConfig = localRedirect "radarr-local.${domain}";
|
||||
extraConfig = localRedirect "radarr-local.${domain}";
|
||||
locations."/" = {
|
||||
proxyPass = "${acquisition}:7878";
|
||||
proxyWebsockets = true;
|
||||
@@ -156,7 +191,7 @@ in
|
||||
};
|
||||
"sonarr.${domain}" = withAuth {
|
||||
serverAliases = [ "sonarr-local.${domain}" ];
|
||||
# extraConfig = localRedirect "sonarr-local.${domain}";
|
||||
extraConfig = localRedirect "sonarr-local.${domain}";
|
||||
locations."/" = {
|
||||
proxyPass = "${acquisition}:8989";
|
||||
proxyWebsockets = true;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{ lib, ... }:
|
||||
let
|
||||
inherit (lib.my) net;
|
||||
inherit (lib.my.c.kelder) domain prefixes ipv4MTU;
|
||||
inherit (lib.my.c.kelder) domain prefixes;
|
||||
in
|
||||
{
|
||||
imports = [ ./containers ];
|
||||
@@ -54,7 +54,7 @@ in
|
||||
efi.canTouchEfiVariables = true;
|
||||
timeout = 5;
|
||||
};
|
||||
kernelPackages = lib.my.c.kernel.lts pkgs;
|
||||
kernelPackages = pkgs.linuxKernel.packages.linux_6_1;
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
kernelParams = [ "intel_iommu=on" ];
|
||||
initrd = {
|
||||
@@ -121,7 +121,8 @@ in
|
||||
|
||||
samba = {
|
||||
enable = true;
|
||||
settings = {
|
||||
enableNmbd = true;
|
||||
shares = {
|
||||
storage = {
|
||||
path = "/mnt/storage";
|
||||
browseable = "yes";
|
||||
@@ -130,20 +131,16 @@ in
|
||||
"directory mask" = "0775";
|
||||
};
|
||||
};
|
||||
|
||||
nmbd.enable = true;
|
||||
};
|
||||
samba-wsdd.enable = true;
|
||||
|
||||
minecraft-server = {
|
||||
enable = false;
|
||||
package = pkgs.minecraftServers.vanilla-1-20;
|
||||
enable = true;
|
||||
package = pkgs.minecraftServers.vanilla-1-19;
|
||||
declarative = true;
|
||||
eula = true;
|
||||
whitelist = {
|
||||
devplayer0 = "6d7d971b-ce10-435b-85c5-c99c0d8d288c";
|
||||
Elderlypug = "dcd2ecb9-2b5e-49cb-9d4f-f5a76162df56";
|
||||
shr3kas0ras = "1d366062-12c0-4e29-aba7-6ab5d8c6bb05";
|
||||
};
|
||||
serverProperties = {
|
||||
motd = "Simpcraft";
|
||||
@@ -181,10 +178,12 @@ in
|
||||
};
|
||||
wireguardPeers = [
|
||||
{
|
||||
PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
|
||||
Endpoint = "${allAssignments.estuary.internal.ipv4.address}:${toString lib.my.c.kelder.vpn.port}";
|
||||
AllowedIPs = [ "0.0.0.0/0" ];
|
||||
PersistentKeepalive = 25;
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = "bP1XUNxp9i8NLOXhgPaIaRzRwi5APbam44/xjvYcyjU=";
|
||||
Endpoint = "estuary-vm.${lib.my.c.colony.domain}:${toString lib.my.c.kelder.vpn.port}";
|
||||
AllowedIPs = [ "0.0.0.0/0" ];
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
@@ -199,7 +198,6 @@ in
|
||||
"50-lan" = {
|
||||
matchConfig.Name = "et1g0";
|
||||
DHCP = "yes";
|
||||
linkConfig.MTUBytes = toString ipv4MTU;
|
||||
};
|
||||
"80-ctrs" = mkMerge [
|
||||
(networkdAssignment "ctrs" assignments.ctrs)
|
||||
@@ -212,7 +210,7 @@ in
|
||||
address = with assignments.estuary; [
|
||||
(with ipv4; "${address}/${toString mask}")
|
||||
];
|
||||
routingPolicyRules = [
|
||||
routingPolicyRules = map (r: { routingPolicyRuleConfig = r; }) [
|
||||
{
|
||||
Family = "both";
|
||||
SuppressPrefixLength = 0;
|
||||
@@ -272,7 +270,7 @@ in
|
||||
config.name = "kontent";
|
||||
};
|
||||
|
||||
# deploy.node.hostname = "192.168.0.69";
|
||||
#deploy.node.hostname = "10.16.9.21";
|
||||
secrets = {
|
||||
key = "ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIOFvUdJshXkqmchEgkZDn5rgtZ1NO9vbd6Px+S6YioWi";
|
||||
files = {
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
cpu = {
|
||||
intel.updateMicrocode = true;
|
||||
};
|
||||
graphics.extraPackages = with pkgs; [
|
||||
opengl.extraPackages = with pkgs; [
|
||||
intel-media-driver
|
||||
];
|
||||
bluetooth.enable = true;
|
||||
@@ -25,20 +25,23 @@
|
||||
efi.canTouchEfiVariables = true;
|
||||
timeout = 10;
|
||||
};
|
||||
kernelPackages = lib.my.c.kernel.latest pkgs;
|
||||
kernelPackages = pkgs.linuxKernel.packages.linux_6_5;
|
||||
kernelModules = [ "kvm-intel" ];
|
||||
kernelParams = [ "intel_iommu=on" ];
|
||||
initrd = {
|
||||
availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "usbhid" "thunderbolt" ];
|
||||
luks = {
|
||||
reusePassphrases = true;
|
||||
devices = {
|
||||
persist = {
|
||||
device = "/dev/disk/by-uuid/27840c6f-445c-4b95-8c39-e69d07219f33";
|
||||
allowDiscards = true;
|
||||
preLVM = false;
|
||||
};
|
||||
home = {
|
||||
device = "/dev/disk/by-uuid/c16c5038-7883-42c3-960a-a085a99364eb";
|
||||
allowDiscards = true;
|
||||
preLVM = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
@@ -99,21 +102,18 @@
|
||||
};
|
||||
};
|
||||
|
||||
resolved = {
|
||||
enable = true;
|
||||
extraConfig = mkForce "";
|
||||
dnssec = "false";
|
||||
};
|
||||
|
||||
fprintd.enable = true;
|
||||
blueman.enable = true;
|
||||
|
||||
tailscale = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
|
||||
programs = {
|
||||
steam.enable = true;
|
||||
wireshark = {
|
||||
enable = true;
|
||||
package = pkgs.wireshark-qt;
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
@@ -123,9 +123,10 @@
|
||||
wifi = {
|
||||
backend = "wpa_supplicant";
|
||||
};
|
||||
settings = {
|
||||
main.no-auto-default = "*";
|
||||
};
|
||||
extraConfig = ''
|
||||
[main]
|
||||
no-auto-default=*
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
@@ -168,14 +169,6 @@
|
||||
packages = with pkgs; [ ];
|
||||
};
|
||||
|
||||
programs = {
|
||||
fish = {
|
||||
shellAbbrs = {
|
||||
tsup = "doas tailscale up --login-server=https://hs.nul.ie --accept-routes";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
blueman-applet.enable = true;
|
||||
};
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ self, lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
|
||||
{ lib, pkgsFlakes, hmFlakes, inputs, pkgs', config, ... }:
|
||||
let
|
||||
inherit (builtins) attrValues mapAttrs;
|
||||
inherit (lib)
|
||||
@@ -23,19 +23,15 @@ let
|
||||
pkgs = pkgs'.${config'.nixpkgs}.${config'.system};
|
||||
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
|
||||
# Import eval-config ourselves since the flake now force-sets lib
|
||||
import "${pkgsFlake}/nixos/lib/eval-config.nix" {
|
||||
pkgsFlake.lib.nixosSystem {
|
||||
# Gotta override lib here unforunately, eval-config.nix likes to import its own (unextended) lib. We explicitly
|
||||
# don't pass pkgs so that it'll be imported with modularly applied config and overlays.
|
||||
lib = pkgs.lib.extend (lib.my.versionOverlay { inherit self pkgsFlake; });
|
||||
|
||||
# Set to null since we pass modularly
|
||||
system = null;
|
||||
lib = pkgs.lib;
|
||||
|
||||
# Put the inputs in specialArgs to avoid infinite recursion when modules try to do imports
|
||||
specialArgs = { inherit 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 =
|
||||
@@ -55,7 +51,7 @@ let
|
||||
pkgs' = allPkgs;
|
||||
};
|
||||
|
||||
system = { inherit name; };
|
||||
system.name = name;
|
||||
networking = {
|
||||
domain = let d = config'.assignments.internal.domain or null; in mkIf (d != null) (mkDefault' d);
|
||||
hostName = mkDefault (config'.assignments.internal.name or name);
|
||||
@@ -90,8 +86,6 @@ let
|
||||
pkgsPath = toString pkgsFlakes.${config'.hmNixpkgs};
|
||||
pkgs' = allPkgs;
|
||||
};
|
||||
|
||||
home.enableNixpkgsReleaseCheck = false;
|
||||
}
|
||||
(homeStateVersion config'.home-manager)
|
||||
];
|
||||
@@ -106,7 +100,6 @@ let
|
||||
altNames = mkOpt' (listOf str) [ ] "Extra names to assign.";
|
||||
visible = mkBoolOpt' true "Whether or not this assignment should be visible.";
|
||||
domain = mkOpt' (nullOr str) null "Domain for this assignment.";
|
||||
mtu = mkOpt' (nullOr ints.unsigned) null "Interface MTU.";
|
||||
ipv4 = {
|
||||
address = mkOpt' net.types.ipv4 null "IPv4 address.";
|
||||
mask = mkOpt' ints.u8 24 "Network mask.";
|
||||
@@ -132,10 +125,6 @@ let
|
||||
l2MeshOpts = with lib.types; { name, ... }: {
|
||||
options = {
|
||||
interface = mkOpt' str name "Name of VXLAN interface.";
|
||||
ipv6 = mkBoolOpt' false "Whether this mesh's underlay operates over IPv6.";
|
||||
baseMTU = mkOpt' ints.unsigned 1500 "Base MTU to calculate VXLAN MTU with.";
|
||||
l3Overhead = mkOpt' ints.unsigned 40 "Overhead of L3 header (to calculate MTU).";
|
||||
udpEncapsulation = mkBoolOpt' false "Whether to encapsulate ESP frames in UDP.";
|
||||
firewall = mkBoolOpt' true "Whether to generate firewall rules.";
|
||||
vni = mkOpt' ints.unsigned 1 "VXLAN VNI.";
|
||||
peers = mkOpt' (attrsOf (submodule l2PeerOpts)) { } "Peers.";
|
||||
@@ -192,11 +181,6 @@ in
|
||||
secretsPath = mkOpt' path null "Path to encrypted secret files.";
|
||||
modules = mkOpt' (attrsOf commonOpts.moduleType) { } "NixOS modules to be exported by nixfiles.";
|
||||
systems = mkOpt' (attrsOf (submodule systemOpts)) { } "NixOS systems to be exported by nixfiles.";
|
||||
allAssignments = mkOption {
|
||||
type = attrsOf (attrsOf (submodule assignmentOpts));
|
||||
description = "All network assignments.";
|
||||
readOnly = true;
|
||||
};
|
||||
vpns = {
|
||||
l2 = mkOpt' (attrsOf (submodule l2MeshOpts)) { } "Layer 2 meshes.";
|
||||
};
|
||||
@@ -222,9 +206,5 @@ in
|
||||
message = "Duplicate assignments: ${toString dupIPs}";
|
||||
}
|
||||
];
|
||||
|
||||
nixos = {
|
||||
inherit allAssignments;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
nixos.systems.installer = { config, ... }: {
|
||||
system = "x86_64-linux";
|
||||
nixpkgs = "mine";
|
||||
nixpkgs = "unstable";
|
||||
docCustom = false;
|
||||
rendered = config.configuration.config.my.asISO;
|
||||
|
||||
@@ -31,11 +31,8 @@
|
||||
server.enable = true;
|
||||
};
|
||||
|
||||
image = {
|
||||
baseName = "jackos-installer";
|
||||
};
|
||||
isoImage = {
|
||||
volumeID = "jackos-${config.system.nixos.release}-${pkgs.stdenv.hostPlatform.uname.processor}";
|
||||
isoBaseName = "nixos-installer-devplayer0";
|
||||
edition = "devplayer0";
|
||||
appendToMenuLabel = " /dev/player0 Installer";
|
||||
};
|
||||
@@ -54,8 +51,6 @@
|
||||
home.shellAliases = {
|
||||
show-hw-config = "nixos-generate-config --show-hardware-config --root $INSTALL_ROOT";
|
||||
};
|
||||
|
||||
my.gui.enable = false;
|
||||
};
|
||||
|
||||
services = {
|
||||
@@ -63,8 +58,8 @@
|
||||
};
|
||||
|
||||
networking = {
|
||||
# Will be set dynamically, but need something to satisfy `/etc/os-release` stuff
|
||||
hostName = "installer";
|
||||
# Will be set dynamically
|
||||
hostName = "";
|
||||
useNetworkd = false;
|
||||
};
|
||||
|
||||
@@ -84,8 +79,6 @@
|
||||
${pkgs.gawk}/bin/awk '{ print $1 }')"
|
||||
'';
|
||||
|
||||
boot.supportedFilesystems.nfs = true;
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
dhcpcd
|
||||
lm_sensors
|
||||
@@ -99,7 +92,7 @@
|
||||
|
||||
# Enable wpa_supplicant, but don't start it by default.
|
||||
networking.wireless.enable = mkDefault true;
|
||||
networking.wireless.userControlled = true;
|
||||
networking.wireless.userControlled.enable = true;
|
||||
systemd.services.wpa_supplicant.wantedBy = mkForce [];
|
||||
|
||||
# Tell the Nix evaluator to garbage collect more aggressively.
|
||||
|
||||
@@ -14,12 +14,8 @@
|
||||
network = ./network.nix;
|
||||
pdns = ./pdns.nix;
|
||||
nginx-sso = ./nginx-sso.nix;
|
||||
gui = ./gui;
|
||||
gui = ./gui.nix;
|
||||
l2mesh = ./l2mesh.nix;
|
||||
borgthin = ./borgthin.nix;
|
||||
nvme = ./nvme;
|
||||
spdk = ./spdk.nix;
|
||||
librespeed = ./librespeed;
|
||||
netboot = ./netboot;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
{ inputs, lib, pkgs, config, ... }:
|
||||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (builtins) substring match;
|
||||
inherit (lib)
|
||||
@@ -127,9 +127,7 @@ in
|
||||
enable = mkBoolOpt' false "Whether to enable borgthin jobs";
|
||||
lvmPackage = mkOpt' package pkgs.lvm2 "Packge containing LVM 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...
|
||||
# Not bothering to update until Borg 2.0 releases
|
||||
package = mkOpt' package inputs.borgthin.packages.${config.nixpkgs.system}.borgthin "borgthin package";
|
||||
package = mkOpt' package pkgs.borgthin "borgthin package";
|
||||
jobs = mkOpt' (attrsOf jobType) { } "borgthin jobs";
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{ lib, pkgs, extendModules, modulesPath, options, config, ... }:
|
||||
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;
|
||||
|
||||
cfg = config.my.build;
|
||||
@@ -18,9 +18,6 @@ let
|
||||
"${modulesPath}/installer/cd-dvd/iso-image.nix"
|
||||
allHardware
|
||||
{
|
||||
# Doesn't work right now... (missing /dev/root)
|
||||
boot.initrd.systemd.enable = false;
|
||||
|
||||
isoImage = {
|
||||
makeEfiBootable = true;
|
||||
makeUsbBootable = true;
|
||||
@@ -46,146 +43,6 @@ let
|
||||
];
|
||||
};
|
||||
|
||||
asNetboot = extendModules {
|
||||
modules = flatten [
|
||||
allHardware
|
||||
({ pkgs, config, ... }: {
|
||||
boot = {
|
||||
loader.grub.enable = false;
|
||||
initrd = {
|
||||
kernelModules = [ "nbd" ];
|
||||
availableKernelModules = [ "igb" "igc" ];
|
||||
|
||||
systemd = {
|
||||
storePaths = with pkgs; [
|
||||
gnused
|
||||
nbd
|
||||
netcat
|
||||
];
|
||||
extraBin = with pkgs; {
|
||||
dmesg = "${util-linux}/bin/dmesg";
|
||||
ip = "${iproute2}/bin/ip";
|
||||
nbd-client = "${nbd}/bin/nbd-client";
|
||||
};
|
||||
extraConfig = ''
|
||||
DefaultTimeoutStartSec=20
|
||||
DefaultDeviceTimeoutSec=20
|
||||
'';
|
||||
|
||||
network = {
|
||||
enable = true;
|
||||
wait-online.enable = true;
|
||||
|
||||
networks."10-netboot" = {
|
||||
matchConfig.Name = "et-boot";
|
||||
DHCP = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
nbd = {
|
||||
description = "NBD Root FS";
|
||||
|
||||
script = ''
|
||||
get_cmdline() {
|
||||
${pkgs.gnused}/bin/sed -rn "s/^.*$1=(\\S+).*\$/\\1/p" < /proc/cmdline
|
||||
}
|
||||
|
||||
s="$(get_cmdline nbd_server)"
|
||||
until ${pkgs.netcat}/bin/nc -zv "$s" 22; do
|
||||
sleep 0.1
|
||||
done
|
||||
|
||||
exec ${pkgs.nbd}/bin/nbd-client -systemd-mark -N "$(get_cmdline nbd_export)" "$s" /dev/nbd0
|
||||
'';
|
||||
unitConfig = {
|
||||
IgnoreOnIsolate = "yes";
|
||||
DefaultDependencies = "no";
|
||||
};
|
||||
serviceConfig = {
|
||||
Type = "forking";
|
||||
Restart = "on-failure";
|
||||
RestartSec = 10;
|
||||
};
|
||||
|
||||
wantedBy = [ "initrd-root-device.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
postBootCommands = ''
|
||||
# After booting, register the contents of the Nix store
|
||||
# in the Nix database in the COW root.
|
||||
${config.nix.package}/bin/nix-store --load-db < /nix-path-registration
|
||||
|
||||
# nixos-rebuild also requires a "system" profile and an
|
||||
# /etc/NIXOS tag.
|
||||
touch /etc/NIXOS
|
||||
${config.nix.package.out}/bin/nix-env -p /nix/var/nix/profiles/system --set /run/current-system
|
||||
'';
|
||||
};
|
||||
|
||||
programs.nbd.enable = true;
|
||||
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
fsType = "ext4";
|
||||
device = "/dev/nbd0";
|
||||
noCheck = true;
|
||||
autoResize = true;
|
||||
};
|
||||
};
|
||||
|
||||
networking.useNetworkd = mkForce true;
|
||||
|
||||
systemd = {
|
||||
network.networks."10-boot" = {
|
||||
matchConfig.Name = "et-boot";
|
||||
DHCP = "yes";
|
||||
networkConfig.KeepConfiguration = "yes";
|
||||
};
|
||||
};
|
||||
|
||||
system.build = {
|
||||
rootImage = pkgs.callPackage "${modulesPath}/../lib/make-ext4-fs.nix" {
|
||||
storePaths = [ config.system.build.toplevel ];
|
||||
volumeLabel = "netboot-root";
|
||||
};
|
||||
netbootScript = pkgs.writeText "boot.ipxe" ''
|
||||
#!ipxe
|
||||
kernel ${pkgs.stdenv.hostPlatform.linux-kernel.target} init=${config.system.build.toplevel}/init initrd=initrd ifname=et-boot:''${mac} nbd_server=''${next-server} ${toString config.boot.kernelParams} ''${cmdline}
|
||||
initrd initrd
|
||||
boot
|
||||
'';
|
||||
|
||||
netbootTree = pkgs.linkFarm "netboot-${config.system.name}" [
|
||||
{
|
||||
name = config.system.boot.loader.kernelFile;
|
||||
path = "${config.system.build.kernel}/${config.system.boot.loader.kernelFile}";
|
||||
}
|
||||
{
|
||||
name = "initrd";
|
||||
path = "${config.system.build.initialRamdisk}/initrd";
|
||||
}
|
||||
{
|
||||
name = "rootfs.ext4";
|
||||
path = config.system.build.rootImage;
|
||||
}
|
||||
{
|
||||
name = "boot.ipxe";
|
||||
path = config.system.build.netbootScript;
|
||||
}
|
||||
];
|
||||
netbootArchive = pkgs.runCommand "netboot-${config.system.name}.tar.zst" { } ''
|
||||
export PATH=${pkgs.zstd}/bin:$PATH
|
||||
${pkgs.gnutar}/bin/tar --dereference --zstd -cvC ${config.system.build.netbootTree} -f "$out" .
|
||||
'';
|
||||
};
|
||||
})
|
||||
];
|
||||
};
|
||||
|
||||
mkAsOpt = ext: desc: with lib.types; mkOption {
|
||||
type = unspecified;
|
||||
default = ext;
|
||||
@@ -207,7 +64,6 @@ in
|
||||
asISO = mkAsOpt asISO "a bootable .iso image";
|
||||
asContainer = mkAsOpt asContainer "a container";
|
||||
asKexecTree = mkAsOpt asKexecTree "a kexec-able kernel and initrd";
|
||||
asNetboot = mkAsOpt asNetboot "a netboot-able kernel initrd, and iPXE script";
|
||||
|
||||
buildAs = options.system.build;
|
||||
};
|
||||
@@ -221,9 +77,8 @@ in
|
||||
memorySize = dummyOption;
|
||||
qemu.options = dummyOption;
|
||||
};
|
||||
image.baseName = dummyOption;
|
||||
isoImage = {
|
||||
volumeID = dummyOption;
|
||||
isoBaseName = dummyOption;
|
||||
edition = dummyOption;
|
||||
appendToMenuLabel = dummyOption;
|
||||
};
|
||||
@@ -241,8 +96,6 @@ in
|
||||
iso = config.my.asISO.config.system.build.isoImage;
|
||||
container = config.my.asContainer.config.system.build.toplevel;
|
||||
kexecTree = config.my.asKexecTree.config.system.build.kexecTree;
|
||||
netbootTree = config.my.asNetboot.config.system.build.netbootTree;
|
||||
netbootArchive = config.my.asNetboot.config.system.build.netbootArchive;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{ lib, pkgsFlake, pkgs, pkgs', self, inputs, config, ... }:
|
||||
{ lib, pkgs, pkgs', inputs, config, ... }:
|
||||
let
|
||||
inherit (lib) mkIf mkDefault mkMerge;
|
||||
inherit (lib.my) mkDefault';
|
||||
inherit (lib.my) mkBoolOpt' dummyOption;
|
||||
in
|
||||
{
|
||||
options = with lib.types; {
|
||||
@@ -9,11 +9,10 @@ in
|
||||
};
|
||||
|
||||
imports = [
|
||||
inputs.impermanence.nixosModules.default
|
||||
inputs.impermanence.nixosModule
|
||||
inputs.ragenix.nixosModules.age
|
||||
inputs.sharry.nixosModules.default
|
||||
inputs.copyparty.nixosModules.default
|
||||
inputs.harmonia.nixosModules.harmonia
|
||||
inputs.attic.nixosModules.atticd
|
||||
];
|
||||
|
||||
config = mkMerge [
|
||||
@@ -42,20 +41,20 @@ in
|
||||
|
||||
nix = {
|
||||
package = pkgs'.mine.nix;
|
||||
channel.enable = false;
|
||||
settings = with lib.my.c.nix; {
|
||||
settings = {
|
||||
trusted-users = [ "@wheel" ];
|
||||
experimental-features = [ "nix-command" "flakes" "ca-derivations" ];
|
||||
extra-substituters = cache.substituters;
|
||||
extra-trusted-public-keys = cache.keys;
|
||||
connect-timeout = 5;
|
||||
fallback = true;
|
||||
substituters = [
|
||||
#"https://nix-cache.nul.ie"
|
||||
"https://cache.nixos.org"
|
||||
];
|
||||
trusted-public-keys = lib.my.c.nix.cacheKeys;
|
||||
};
|
||||
registry = {
|
||||
pkgs = {
|
||||
to = {
|
||||
type = "path";
|
||||
path = "${pkgsFlake}";
|
||||
path = "${pkgs.path}";
|
||||
};
|
||||
exact = true;
|
||||
};
|
||||
@@ -67,12 +66,10 @@ in
|
||||
};
|
||||
nixpkgs = {
|
||||
overlays = [
|
||||
inputs.deploy-rs.overlays.default
|
||||
inputs.deploy-rs.overlay
|
||||
inputs.sharry.overlays.default
|
||||
# TODO: Re-enable when borgthin is updated
|
||||
# inputs.borgthin.overlays.default
|
||||
inputs.borgthin.overlays.default
|
||||
inputs.boardie.overlays.default
|
||||
inputs.copyparty.overlays.default
|
||||
];
|
||||
config = {
|
||||
allowUnfree = true;
|
||||
@@ -92,13 +89,12 @@ in
|
||||
|
||||
boot = {
|
||||
# Use latest LTS release by default
|
||||
kernelPackages = mkDefault (lib.my.c.kernel.lts pkgs);
|
||||
kernelPackages = mkDefault pkgs.linuxKernel.packages.linux_6_1;
|
||||
kernel = {
|
||||
sysctl = {
|
||||
"net.ipv6.route.max_size" = mkDefault 16384;
|
||||
};
|
||||
};
|
||||
|
||||
loader = {
|
||||
efi = {
|
||||
efiSysMountPoint = mkDefault "/boot";
|
||||
@@ -116,30 +112,14 @@ in
|
||||
memtest86.enable = mkDefault true;
|
||||
};
|
||||
};
|
||||
|
||||
initrd = {
|
||||
systemd = {
|
||||
enable = mkDefault true;
|
||||
emergencyAccess = 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 [
|
||||
[
|
||||
bash-completion
|
||||
vim
|
||||
git
|
||||
unzip
|
||||
tcpdump
|
||||
]
|
||||
(mkIf config.services.netdata.enable [ netdata ])
|
||||
];
|
||||
@@ -150,10 +130,6 @@ in
|
||||
fish.enable = mkDefault true;
|
||||
# TODO: This is expecting to look up the channel for the database...
|
||||
command-not-found.enable = mkDefault false;
|
||||
vim = {
|
||||
enable = true;
|
||||
defaultEditor = true;
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
@@ -167,7 +143,6 @@ in
|
||||
font-name=SauceCodePro Nerd Font Mono
|
||||
'';
|
||||
};
|
||||
getty.greetingLine = mkDefault' ''<<< Welcome to ${config.system.nixos.distroName} ${config.system.nixos.label} (\m) - \l >>>'';
|
||||
|
||||
openssh = {
|
||||
enable = mkDefault true;
|
||||
@@ -220,35 +195,14 @@ in
|
||||
# python.d plugin script does #!/usr/bin/env bash
|
||||
path = with pkgs; [ bash ];
|
||||
};
|
||||
|
||||
nixfiles-mutable = {
|
||||
description = "Mutable nixfiles";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
RemainAfterExit = true;
|
||||
};
|
||||
|
||||
path = with pkgs; [ util-linux ];
|
||||
script = ''
|
||||
nixfilesDir="${self}"
|
||||
|
||||
mkdir -p /run/nixfiles{,/.rw,/.work}
|
||||
mount -t overlay overlay -o lowerdir="$nixfilesDir",upperdir=/run/nixfiles/.rw,workdir=/run/nixfiles/.work /run/nixfiles
|
||||
chmod -R u+w /run/nixfiles
|
||||
'';
|
||||
preStop = ''
|
||||
umount /run/nixfiles
|
||||
rm -rf /run/nixfiles
|
||||
'';
|
||||
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
(mkIf config.services.kmscon.enable {
|
||||
fonts.fonts = with pkgs; [
|
||||
nerd-fonts.sauce-code-pro
|
||||
(nerdfonts.override {
|
||||
fonts = [ "SourceCodePro" ];
|
||||
})
|
||||
];
|
||||
})
|
||||
];
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{ lib, pkgs, options, config, systems, ... }:
|
||||
let
|
||||
inherit (builtins) attrNames attrValues all hashString toJSON any;
|
||||
inherit (builtins) attrNames attrValues all hashString toJSON;
|
||||
inherit (lib)
|
||||
groupBy' mapAttrsToList optionalString optional concatMapStringsSep filterAttrs mkOption mkDefault mkIf mkMerge;
|
||||
inherit (lib.my) mkOpt' mkBoolOpt';
|
||||
@@ -15,7 +15,6 @@ let
|
||||
passAsFile = [ "code" ];
|
||||
code = ''
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <signal.h>
|
||||
#include <unistd.h>
|
||||
#include <systemd/sd-daemon.h>
|
||||
@@ -99,7 +98,6 @@ let
|
||||
};
|
||||
networking = {
|
||||
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;
|
||||
message = "Containers currently require systemd-networkd!";
|
||||
}
|
||||
{
|
||||
assertion = all (i: i.networking.bridge == null || i.networking.macVLAN == null) (attrValues cfg.instances);
|
||||
message = "Only bridge OR MACVLAN can be set";
|
||||
}
|
||||
];
|
||||
|
||||
# TODO: Better security
|
||||
my.firewall.trustedInterfaces =
|
||||
mapAttrsToList
|
||||
(n: _: "ve-${n}")
|
||||
(filterAttrs (_: c: c.networking.bridge == null && 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}" = {
|
||||
execConfig = {
|
||||
Boot = true;
|
||||
@@ -160,8 +165,6 @@ in
|
||||
};
|
||||
networkConfig = if (c.networking.bridge != null) then {
|
||||
Bridge = c.networking.bridge;
|
||||
} else if (c.networking.macVLAN != null) then {
|
||||
MACVLAN = "${c.networking.macVLAN}:host0";
|
||||
} else {
|
||||
VirtualEthernet = true;
|
||||
};
|
||||
@@ -179,9 +182,6 @@ in
|
||||
c.containerSystem;
|
||||
in
|
||||
{
|
||||
# To prevent creating a whole new unit file
|
||||
overrideStrategy = "asDropin";
|
||||
|
||||
environment = {
|
||||
# systemd.nspawn units can't set the root directory directly, but /run/machines/${n} is one of the search paths
|
||||
root = "/run/machines/${n}";
|
||||
@@ -208,17 +208,7 @@ in
|
||||
|
||||
mkdir -p -m 0755 "$root"/sbin "$root"/etc
|
||||
touch "$root"/etc/os-release
|
||||
|
||||
${if system == sysProfile then ''
|
||||
if [ -e "${sysProfile}"/prepare-root ]; then
|
||||
initSource="${containerSystem}"/prepare-root
|
||||
else
|
||||
initSource="${containerSystem}"/init
|
||||
fi
|
||||
ln -sf "$initSource" "$root"/sbin/init
|
||||
'' else ''
|
||||
ln -sf "${containerSystem}/prepare-root" "$root"/sbin/init
|
||||
''}
|
||||
ln -sf "${containerSystem}"/init "$root"/sbin/init
|
||||
'';
|
||||
postStop =
|
||||
''
|
||||
@@ -247,7 +237,7 @@ in
|
||||
Bridge = c.networking.bridge;
|
||||
};
|
||||
};
|
||||
}) cfg.instances);
|
||||
}) cfg.instances));
|
||||
})
|
||||
|
||||
# Inside container
|
||||
|
||||
@@ -15,20 +15,16 @@ let
|
||||
# Based on https://github.com/serokell/deploy-rs/blob/master/flake.nix
|
||||
nixosActivate = cfg': base: (pkgs.deploy-rs.lib.activate.custom // {
|
||||
dryActivate = "$PROFILE/bin/switch-to-configuration dry-activate";
|
||||
boot = ''
|
||||
$PROFILE/bin/switch-to-configuration boot
|
||||
|
||||
${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
|
||||
'';
|
||||
boot = "$PROFILE/bin/switch-to-configuration boot";
|
||||
}) base.config.system.build.toplevel ''
|
||||
# work around https://github.com/NixOS/nixpkgs/issues/73404
|
||||
cd /tmp
|
||||
|
||||
"$PROFILE"/bin/switch-to-configuration switch
|
||||
"$PROFILE"/bin/switch-to-configuration ${cfg'.mode}
|
||||
|
||||
# https://github.com/serokell/deploy-rs/issues/31
|
||||
${with base.config.boot.loader;
|
||||
optionalString systemd-boot.enable
|
||||
optionalString ((cfg'.mode == "switch" || cfg'.mode == "boot") && systemd-boot.enable)
|
||||
"sed -i '/^default /d' ${efi.efiSysMountPoint}/loader/loader.conf"}
|
||||
|
||||
${keepGensSnippet "$PROFILE" cfg'.keepGenerations}
|
||||
@@ -45,9 +41,8 @@ let
|
||||
|
||||
journalctl -o cat --no-pager -n 0 -f -u "$unit" &
|
||||
jPid=$!
|
||||
|
||||
# shellcheck disable=SC2329
|
||||
cleanup() {
|
||||
# shellcheck disable=SC2317
|
||||
kill "$jPid"
|
||||
}
|
||||
trap cleanup EXIT
|
||||
@@ -64,11 +59,7 @@ let
|
||||
{
|
||||
name = "container-${n}";
|
||||
value = {
|
||||
path = (pkgs.deploy-rs.lib.activate.custom // {
|
||||
boot = ''
|
||||
echo "Next systemd-nspawn@${n}.service restart / reload will load config"
|
||||
'';
|
||||
}) ctrConfig.my.buildAs.container ''
|
||||
path = pkgs.deploy-rs.lib.activate.custom ctrConfig.my.buildAs.container ''
|
||||
source ${systemdUtil}/bin/systemd-util.sh
|
||||
${if c.hotReload then ''
|
||||
if (! systemctl show -p ActiveState systemd-nspawn@${n} | grep -q "ActiveState=active") || \
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
{ lib, options, config, ... }:
|
||||
let
|
||||
inherit (builtins) typeOf attrNames;
|
||||
inherit (lib)
|
||||
optionalString concatStringsSep concatMapStringsSep mapAttrsToList optionalAttrs mkIf
|
||||
mkDefault mkMerge mkOverride;
|
||||
inherit (lib) optionalString concatStringsSep concatMapStringsSep optionalAttrs mkIf mkDefault mkMerge mkOverride;
|
||||
inherit (lib.my) isIPv6 mkOpt' mkBoolOpt';
|
||||
|
||||
allowICMP = ''
|
||||
@@ -66,8 +63,8 @@ in
|
||||
|
||||
nat = with options.networking.nat; {
|
||||
enable = mkBoolOpt' true "Whether to enable IP forwarding and NAT.";
|
||||
inherit externalInterface;
|
||||
forwardPorts = mkOpt' (either (listOf (submodule forwardOpts)) (attrsOf (listOf (submodule forwardOpts)))) [ ] "IPv4 port forwards";
|
||||
inherit externalInterface externalIP;
|
||||
forwardPorts = mkOpt' (listOf (submodule forwardOpts)) [ ] "List of port forwards.";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -134,15 +131,9 @@ in
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority dstnat;
|
||||
}
|
||||
chain output {
|
||||
type nat hook output priority dstnat;
|
||||
}
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority srcnat;
|
||||
}
|
||||
chain input {
|
||||
type nat hook input priority srcnat;
|
||||
}
|
||||
}
|
||||
|
||||
${cfg.extraRules}
|
||||
@@ -150,16 +141,11 @@ in
|
||||
};
|
||||
};
|
||||
}
|
||||
(mkIf cfg.nat.enable (
|
||||
let
|
||||
iifForward = typeOf cfg.nat.forwardPorts == "list" && cfg.nat.forwardPorts != [ ];
|
||||
dipForward = typeOf cfg.nat.forwardPorts == "set" && cfg.nat.forwardPorts != { };
|
||||
in
|
||||
{
|
||||
(mkIf cfg.nat.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = with cfg.nat; iifForward -> (externalInterface != null);
|
||||
message = "my.firewall.nat.forwardPorts as list requires my.firewall.nat.externalInterface";
|
||||
assertion = with cfg.nat; (forwardPorts != [ ]) -> (externalInterface != null);
|
||||
message = "my.firewall.nat.forwardPorts requires my.firewall.nat.external{Interface,IP}";
|
||||
}
|
||||
];
|
||||
|
||||
@@ -182,75 +168,43 @@ in
|
||||
|
||||
my.firewall.extraRules =
|
||||
let
|
||||
inherit (lib.my.nft) natFilterChain dnatChain;
|
||||
ipK = ip: "ip${optionalString (isIPv6 ip) "6"}";
|
||||
|
||||
makeFilter = f:
|
||||
"${ipK f.dst} daddr ${f.dst} ${f.proto} dport ${toString f.dstPort} accept";
|
||||
let
|
||||
v6 = isIPv6 f.dst;
|
||||
in
|
||||
"ip${optionalString v6 "6"} daddr ${f.dst} ${f.proto} dport ${toString f.dstPort} accept";
|
||||
makeForward = f:
|
||||
"${f.proto} dport ${toString f.port} dnat ${ipK f.dst} to ${f.dst}:${toString f.dstPort}";
|
||||
|
||||
dnatJumps = ''
|
||||
${optionalString
|
||||
iifForward
|
||||
"iifname ${cfg.nat.externalInterface} jump iif-port-forward"}
|
||||
${optionalString
|
||||
dipForward
|
||||
(concatMapStringsSep "\n " (ip: "${ipK ip} daddr ${ip} jump ${dnatChain ip}") (attrNames cfg.nat.forwardPorts))}
|
||||
'';
|
||||
let
|
||||
v6 = isIPv6 f.dst;
|
||||
in
|
||||
"${f.proto} dport ${toString f.port} dnat ip${optionalString v6 "6"} to ${f.dst}:${toString f.dstPort}";
|
||||
in
|
||||
''
|
||||
table inet filter {
|
||||
${optionalString iifForward ''
|
||||
chain filter-iif-port-forwards {
|
||||
${concatMapStringsSep "\n " makeFilter cfg.nat.forwardPorts}
|
||||
return
|
||||
}
|
||||
''}
|
||||
${optionalString
|
||||
dipForward
|
||||
(concatStringsSep "\n" (mapAttrsToList (ip: fs: ''
|
||||
chain ${natFilterChain ip} {
|
||||
${concatMapStringsSep "\n " makeFilter fs}
|
||||
return
|
||||
}
|
||||
'') cfg.nat.forwardPorts))}
|
||||
|
||||
chain filter-port-forwards {
|
||||
${concatMapStringsSep "\n " makeFilter cfg.nat.forwardPorts}
|
||||
return
|
||||
}
|
||||
chain forward {
|
||||
${optionalString
|
||||
iifForward
|
||||
"iifname ${cfg.nat.externalInterface} jump filter-iif-port-forwards"}
|
||||
${optionalString
|
||||
dipForward
|
||||
(concatMapStringsSep "\n " (ip: "jump ${natFilterChain ip}") (attrNames cfg.nat.forwardPorts))}
|
||||
(cfg.nat.externalInterface != null)
|
||||
"iifname ${cfg.nat.externalInterface} jump filter-port-forwards"}
|
||||
}
|
||||
}
|
||||
|
||||
table inet nat {
|
||||
${optionalString iifForward ''
|
||||
chain iif-port-forward {
|
||||
${concatMapStringsSep "\n " makeForward cfg.nat.forwardPorts}
|
||||
return
|
||||
}
|
||||
''}
|
||||
${optionalString
|
||||
dipForward
|
||||
(concatStringsSep "\n" (mapAttrsToList (ip: fs: ''
|
||||
chain ${dnatChain ip} {
|
||||
${concatMapStringsSep "\n " makeForward fs}
|
||||
return
|
||||
}
|
||||
'') cfg.nat.forwardPorts))}
|
||||
|
||||
chain prerouting {
|
||||
${dnatJumps}
|
||||
chain port-forward {
|
||||
${concatMapStringsSep "\n " makeForward cfg.nat.forwardPorts}
|
||||
return
|
||||
}
|
||||
chain output {
|
||||
${dnatJumps}
|
||||
chain prerouting {
|
||||
${optionalString
|
||||
(cfg.nat.externalInterface != null)
|
||||
"${if (cfg.nat.externalIP != null) then "ip daddr ${cfg.nat.externalIP}" else "iifname ${cfg.nat.externalInterface}"} jump port-forward"}
|
||||
}
|
||||
}
|
||||
'';
|
||||
}))
|
||||
})
|
||||
]);
|
||||
|
||||
meta.buildDocsInSandbox = false;
|
||||
|
||||
77
nixos/modules/gui.nix
Normal file
@@ -0,0 +1,77 @@
|
||||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (lib) optional mkIf mkDefault mkMerge;
|
||||
inherit (lib.my) mkBoolOpt';
|
||||
|
||||
cfg = config.my.gui;
|
||||
in
|
||||
{
|
||||
options.my.gui = with lib.types; {
|
||||
enable = mkBoolOpt' true "Whether to enable GUI system options.";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
hardware = {
|
||||
opengl.enable = mkDefault true;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"d /tmp/screenshots 0777 root root"
|
||||
];
|
||||
};
|
||||
|
||||
security = {
|
||||
polkit.enable = true;
|
||||
pam.services.swaylock = {};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# for pw-jack
|
||||
pipewire.jack
|
||||
swaylock
|
||||
];
|
||||
services = {
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
};
|
||||
dbus = {
|
||||
packages = with pkgs; [ gcr ];
|
||||
};
|
||||
gnome = {
|
||||
gnome-keyring.enable = true;
|
||||
};
|
||||
|
||||
udev = {
|
||||
extraRules = ''
|
||||
# Nvidia
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
|
||||
# Nintendo
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
programs.dconf.enable = true;
|
||||
|
||||
fonts.fonts = with pkgs; [
|
||||
dejavu_fonts
|
||||
freefont_ttf
|
||||
gyre-fonts # TrueType substitutes for standard PostScript fonts
|
||||
liberation_ttf
|
||||
unifont
|
||||
noto-fonts-emoji
|
||||
];
|
||||
|
||||
xdg = {
|
||||
portal = {
|
||||
enable = true;
|
||||
# For sway
|
||||
wlr.enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,128 +0,0 @@
|
||||
{ lib, pkgs, config, ... }:
|
||||
let
|
||||
inherit (lib) optional mkIf mkDefault mkMerge mkOverride;
|
||||
inherit (lib.my) mkBoolOpt';
|
||||
|
||||
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
|
||||
{
|
||||
options.my.gui = with lib.types; {
|
||||
enable = mkBoolOpt' true "Whether to enable GUI system options.";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
hardware = {
|
||||
graphics.enable = mkDefault true;
|
||||
};
|
||||
|
||||
systemd = {
|
||||
tmpfiles.rules = [
|
||||
"d /tmp/screenshots 0777 root root"
|
||||
];
|
||||
};
|
||||
|
||||
security = {
|
||||
polkit.enable = true;
|
||||
pam.services.swaylock-plugin = {};
|
||||
};
|
||||
|
||||
users = {
|
||||
groups = {
|
||||
adbusers.gid = lib.my.c.ids.gids.adbusers;
|
||||
};
|
||||
};
|
||||
|
||||
environment.systemPackages = with pkgs; [
|
||||
# for pw-jack
|
||||
pipewire.jack
|
||||
swaylock-plugin
|
||||
];
|
||||
services = {
|
||||
# TODO: Remove if-else when 26.05 releases
|
||||
resolved = if (config.system.nixos.release == "25.11:u-26.05") then {
|
||||
settings.Resolve = {
|
||||
FallbackDNS = mkOverride 99 (
|
||||
"1.1.1.1#cloudflare-dns.com 8.8.8.8#dns.google " +
|
||||
"1.0.0.1#cloudflare-dns.com 8.8.4.4#dns.google " +
|
||||
"2606:4700:4700::1111#cloudflare-dns.com 2001:4860:4860::8888#dns.google " +
|
||||
"2606:4700:4700::1001#cloudflare-dns.com 2001:4860:4860::8844#dns.google" );
|
||||
LLMNR = "resolve";
|
||||
};
|
||||
} else { };
|
||||
|
||||
pipewire = {
|
||||
enable = true;
|
||||
alsa.enable = true;
|
||||
pulse.enable = true;
|
||||
jack.enable = true;
|
||||
};
|
||||
dbus = {
|
||||
packages = with pkgs; [ gcr ];
|
||||
};
|
||||
gnome = {
|
||||
gnome-keyring.enable = true;
|
||||
};
|
||||
udisks2.enable = true;
|
||||
|
||||
udev = {
|
||||
packages = [
|
||||
androidUdevRules
|
||||
];
|
||||
extraRules = ''
|
||||
# Nvidia
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0955", MODE="0664", GROUP="wheel"
|
||||
# Nintendo
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="057e", MODE="0664", GROUP="wheel"
|
||||
# FT
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="0403", MODE="0664", GROUP="wheel"
|
||||
# /dev/player0
|
||||
SUBSYSTEM=="usb", ATTR{idVendor}=="6969", MODE="0664", GROUP="wheel"
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
programs.dconf.enable = true;
|
||||
|
||||
fonts.packages = with pkgs; [
|
||||
dejavu_fonts
|
||||
freefont_ttf
|
||||
gyre-fonts # TrueType substitutes for standard PostScript fonts
|
||||
liberation_ttf
|
||||
unifont
|
||||
noto-fonts-color-emoji
|
||||
];
|
||||
|
||||
xdg = {
|
||||
portal = {
|
||||
enable = true;
|
||||
extraPortals = with pkgs; [
|
||||
xdg-desktop-portal-gtk
|
||||
];
|
||||
# For sway
|
||||
wlr.enable = true;
|
||||
configPackages = [
|
||||
(pkgs.writeTextDir "share/xdg-desktop-portal/sway-portals.conf" ''
|
||||
[preferred]
|
||||
default=gtk
|
||||
org.freedesktop.impl.portal.Screenshot=wlr
|
||||
org.freedesktop.impl.portal.ScreenCast=wlr
|
||||
'')
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
my = {
|
||||
user = {
|
||||
config = {
|
||||
extraGroups = [ "adbusers" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,8 +1,7 @@
|
||||
{ lib, config, vpns, ... }:
|
||||
{ lib, pkgs, config, vpns, ... }:
|
||||
let
|
||||
inherit (builtins) any attrValues;
|
||||
inherit (lib) optionalString mapAttrsToList concatStringsSep concatMapStringsSep filterAttrs mkIf mkMerge;
|
||||
inherit (lib.my) isIPv6 mkOpt';
|
||||
inherit (lib) optionalString mapAttrsToList concatStringsSep filterAttrs mkIf mkMerge;
|
||||
inherit (lib.my) isIPv6;
|
||||
|
||||
vxlanPort = 4789;
|
||||
|
||||
@@ -25,32 +24,38 @@ let
|
||||
Local = ownAddr;
|
||||
MacLearning = true;
|
||||
DestinationPort = vxlanPort;
|
||||
PortRange = "${toString vxlanPort}-${toString (vxlanPort + 1)}";
|
||||
Independent = true;
|
||||
};
|
||||
};
|
||||
links."20-l2mesh-${name}" = {
|
||||
matchConfig.Name = mesh.interface;
|
||||
# TODO: ipv6? ipsec?
|
||||
linkConfig.MTUBytes = "1450";
|
||||
};
|
||||
networks."90-l2mesh-${name}" = {
|
||||
matchConfig.Name = mesh.interface;
|
||||
linkConfig.MTUBytes =
|
||||
let
|
||||
espOverhead =
|
||||
if (!mesh.security.enable) then 0
|
||||
else
|
||||
# UDP encap + SPI + seq + IV + pad / header + ICV
|
||||
(if mesh.udpEncapsulation then 8 else 0) + 4 + 4 + (if mesh.security.encrypt then 8 else 0) + 2 + 16;
|
||||
# UDP + VXLAN + Ethernet + L3 (IPv4/IPv6)
|
||||
overhead = espOverhead + 8 + 8 + 14 + mesh.l3Overhead;
|
||||
in
|
||||
toString (mesh.baseMTU - overhead);
|
||||
|
||||
bridgeFDBs = mapAttrsToList (n: peer: {
|
||||
MACAddress = "00:00:00:00:00:00";
|
||||
Destination = peer.addr;
|
||||
}) otherPeers;
|
||||
extraConfig = concatStringsSep "\n" (mapAttrsToList (n: peer: ''
|
||||
[BridgeFDB]
|
||||
MACAddress=00:00:00:00:00:00
|
||||
Destination=${peer.addr}
|
||||
'') otherPeers);
|
||||
};
|
||||
};
|
||||
|
||||
vxlanAllow = vni: "udp dport ${toString vxlanPort} @th,96,24 ${toString vni} accept";
|
||||
mkLibreswanConfig = name: mesh: with info mesh; {
|
||||
enable = true;
|
||||
# TODO: finish this...
|
||||
connections."l2mesh-${name}" = ''
|
||||
keyexchange=ike
|
||||
type=transport
|
||||
left=${ownAddr}
|
||||
|
||||
auto=start
|
||||
phase2=esp
|
||||
ikev2=yes
|
||||
'';
|
||||
};
|
||||
|
||||
mkFirewallConfig = name: mesh: with info mesh;
|
||||
let
|
||||
netProto = if (isIPv6 ownAddr) then "ip6" else "ip";
|
||||
@@ -58,15 +63,8 @@ let
|
||||
''
|
||||
table inet filter {
|
||||
chain l2mesh-${name} {
|
||||
${optionalString mesh.security.enable ''
|
||||
udp dport isakmp accept
|
||||
${if mesh.udpEncapsulation then ''
|
||||
udp dport ipsec-nat-t accept
|
||||
'' else ''
|
||||
meta l4proto esp accept
|
||||
''}
|
||||
''}
|
||||
${optionalString (!mesh.security.enable) (vxlanAllow mesh.vni)}
|
||||
${optionalString mesh.security.enable "meta l4proto esp accept"}
|
||||
udp dport ${toString vxlanPort} @th,96,24 ${toString mesh.vni} accept
|
||||
return
|
||||
}
|
||||
chain input {
|
||||
@@ -74,64 +72,12 @@ let
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
mkLibreswanConfig = name: mesh: with info mesh; {
|
||||
enable = true;
|
||||
connections = mkMerge (mapAttrsToList
|
||||
(pName: peer: {
|
||||
"l2mesh-${name}-${pName}" = ''
|
||||
keyexchange=ike
|
||||
hostaddrfamily=ipv${if mesh.ipv6 then "6" else "4"}
|
||||
type=transport
|
||||
|
||||
left=${ownAddr}
|
||||
leftprotoport=udp/${toString vxlanPort}
|
||||
right=${peer.addr}
|
||||
rightprotoport=udp/${toString vxlanPort}
|
||||
rightupdown=
|
||||
|
||||
auto=start
|
||||
authby=secret
|
||||
phase2=esp
|
||||
esp=${if mesh.security.encrypt then "aes_gcm256" else "null-sha256"}
|
||||
ikev2=yes
|
||||
modecfgpull=no
|
||||
encapsulation=${if mesh.udpEncapsulation then "yes" else "no"}
|
||||
'';
|
||||
})
|
||||
otherPeers);
|
||||
};
|
||||
genSecrets = name: mesh: with info mesh; concatMapStringsSep "\n" (p: ''
|
||||
echo "${ownAddr} ${p.addr} : PSK \"$(< "${config.my.vpns.l2.pskFiles.${name}}")\"" >> /run/l2mesh.secrets
|
||||
'') (attrValues otherPeers);
|
||||
anySecurity = any (c: c.security.enable) (attrValues memberMeshes);
|
||||
in
|
||||
{
|
||||
options = {
|
||||
my.vpns.l2 = with lib.types; {
|
||||
pskFiles = mkOpt' (attrsOf str) { } "PSK files for secured meshes.";
|
||||
};
|
||||
};
|
||||
|
||||
config = {
|
||||
systemd.network = mkMerge (mapAttrsToList mkNetConfig memberMeshes);
|
||||
|
||||
environment.etc."ipsec.d/l2mesh.secrets" = mkIf anySecurity {
|
||||
source = "/run/l2mesh.secrets";
|
||||
};
|
||||
systemd.services.ipsec = mkIf anySecurity {
|
||||
preStart = ''
|
||||
oldUmask="$(umask)"
|
||||
umask 006
|
||||
|
||||
> /run/l2mesh.secrets
|
||||
${concatStringsSep "\n" (mapAttrsToList genSecrets memberMeshes)}
|
||||
|
||||
umask "$oldUmask"
|
||||
'';
|
||||
};
|
||||
|
||||
services.libreswan = mkMerge (mapAttrsToList mkLibreswanConfig (filterAttrs (_: c: c.security.enable) memberMeshes));
|
||||
# TODO: finish this...
|
||||
#services.libreswan = mkMerge (mapAttrsToList mkLibreswanConfig (filterAttrs (_: c: c.security.enable) memberMeshes));
|
||||
my.firewall.extraRules = concatStringsSep "\n" (mapAttrsToList mkFirewallConfig (filterAttrs (_: c: c.firewall) memberMeshes));
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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" ];
|
||||
};
|
||||
})
|
||||
];
|
||||
}
|
||||