initial(ish) commit
This commit is contained in:
commit
b744693f0e
88 changed files with 4925 additions and 0 deletions
62
hosts/daedalus/default.nix
Normal file
62
hosts/daedalus/default.nix
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
{ pkgs, inputs, lib, ... }:
|
||||
with lib;
|
||||
with lib.my;
|
||||
{
|
||||
|
||||
users.users.ragon = {
|
||||
name = "ragon";
|
||||
home = "/Users/ragon";
|
||||
};
|
||||
programs.gnupg.agent.enable = true;
|
||||
home-manager.users.ragon = { pkgs, lib, inputs, config, ... }: {
|
||||
programs.home-manager.enable = true;
|
||||
home.stateVersion = "21.11";
|
||||
|
||||
home.sessionVariables = {
|
||||
EDITOR = "nvim";
|
||||
VISUAL = "nvim";
|
||||
PATH = "$PATH:$HOME/development/flutter/bin:/Applications/Android Studio.app/Contents/bin/:/Applications/Docker.app/Contents/Resources/bin:/Applications/Android Studio.app/Contents/jre/Contents/Home/bin:$HOME/.nix-profile/bin:/nix/var/nix/profiles/system/sw/bin";
|
||||
JAVA_HOME = "/Applications/Android Studio.app/Contents/jre/Contents/Home/";
|
||||
};
|
||||
home.packages = with pkgs; [
|
||||
terraform-ls
|
||||
terraform
|
||||
|
||||
#tectonic
|
||||
pandoc
|
||||
|
||||
yabai
|
||||
|
||||
google-cloud-sdk
|
||||
];
|
||||
|
||||
home.activation = {
|
||||
aliasApplications =
|
||||
let
|
||||
apps = pkgs.buildEnv {
|
||||
name = "home-manager-applications";
|
||||
paths = config.home.packages;
|
||||
pathsToLink = "/Applications";
|
||||
};
|
||||
in
|
||||
lib.hm.dag.entryAfter [ "writeBoundary" ] ''
|
||||
# Install MacOS applications to the user environment.
|
||||
HM_APPS="$HOME/Applications/Home Manager Apps"
|
||||
|
||||
# Reset current state
|
||||
[ -e "$HM_APPS" ] && $DRY_RUN_CMD rm -r "$HM_APPS"
|
||||
$DRY_RUN_CMD mkdir -p "$HM_APPS"
|
||||
|
||||
# .app dirs need to be actual directories for Finder to detect them as Apps.
|
||||
# The files inside them can be symlinks though.
|
||||
$DRY_RUN_CMD cp --recursive --symbolic-link --no-preserve=mode -H ${apps}/Applications/* "$HM_APPS" || true # can fail if no apps exist
|
||||
# Modes need to be stripped because otherwise the dirs wouldn't have +w,
|
||||
# preventing us from deleting them again
|
||||
# In the env of Apps we build, the .apps are symlinks. We pass all of them as
|
||||
# arguments to cp and make it dereference those using -H
|
||||
'';
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
213
hosts/ds9/default.nix
Normal file
213
hosts/ds9/default.nix
Normal file
|
|
@ -0,0 +1,213 @@
|
|||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||
|
||||
{ config, inputs, pkgs, lib, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
# Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
# Don't Use the systemd-boot EFI boot loader.
|
||||
boot.loader.systemd-boot.enable = true;
|
||||
|
||||
services.syncthing.enable = true;
|
||||
services.syncthing.user = "ragon";
|
||||
|
||||
security.sudo.wheelNeedsPassword = false;
|
||||
networking.useDHCP = true;
|
||||
networking.bridges."br0".interfaces = [ ];
|
||||
networking.hostId = "7b4c2932";
|
||||
boot.binfmt.emulatedSystems = [ "aarch64-linux" "armv7l-linux" ];
|
||||
boot.initrd.network = {
|
||||
enable = true;
|
||||
postCommands = ''
|
||||
zpool import rpool
|
||||
echo "zfs load-key -a; killall zfs" >> /root/.profile
|
||||
'';
|
||||
ssh = {
|
||||
enable = true;
|
||||
port = 2222;
|
||||
hostKeys = [
|
||||
"/persistent/etc/nixos/secrets/initrd/ssh_host_rsa_key"
|
||||
"/persistent/etc/nixos/secrets/initrd/ssh_host_ed25519_key"
|
||||
];
|
||||
authorizedKeys = pkgs.pubkeys.ragon.computers;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
# services.restic.backups."ds9" = {
|
||||
# rcloneConfigFile = "/run/secrets/ds9rcloneConfig";
|
||||
# passwordFile = "/run/secrets/ds9resticPassword";
|
||||
# pruneOpts = [
|
||||
# "--keep-daily 7"
|
||||
# "--keep-weekly 5"
|
||||
# "--keep-monthly 12"
|
||||
# "--keep-yearly 75"
|
||||
# ];
|
||||
# initialize = true;
|
||||
# repository = "rclone:ds9:/ds9";
|
||||
# paths = [
|
||||
# "/data"
|
||||
# "/persistent/var/lib"
|
||||
# ];
|
||||
|
||||
# };
|
||||
|
||||
ragon.agenix.secrets."ds9rcloneConfig" = { };
|
||||
ragon.agenix.secrets."ds9resticPassword" = { };
|
||||
|
||||
|
||||
# Enable Scanning
|
||||
hardware.sane.enable = true;
|
||||
hardware.sane.extraBackends = [ pkgs.sane-airscan ];
|
||||
services.avahi.enable = true;
|
||||
services.avahi.nssmdns = true;
|
||||
services.avahi.publish.enable = true;
|
||||
services.avahi.extraServiceFiles.smb = ''
|
||||
<?xml version="1.0" standalone='no'?>
|
||||
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
|
||||
<service-group>
|
||||
<name replace-wildcards="yes">%h</name>
|
||||
<service>
|
||||
<type>_smb._tcp</type>
|
||||
<port>445</port>
|
||||
<host-name>ds9.hailsatan.eu</host-name>
|
||||
</service>
|
||||
<service>
|
||||
<type>_device-info._tcp</type>
|
||||
<port>0</port>
|
||||
<txt-record>model=MacPro7,1@ECOLOR=226,226,224</txt-record>
|
||||
</service>
|
||||
<service>
|
||||
<type>_adisk._tcp</type>
|
||||
<txt-record>sys=waMa=0,adVF=0x100</txt-record>
|
||||
<txt-record>dk0=adVN=TimeMachine,adVF=0x82</txt-record>
|
||||
<host-name>ds9.hailsatan.eu</host-name>
|
||||
</service>
|
||||
</service-group>
|
||||
'';
|
||||
# Webhook service to trigger scanning the ADF from HomeAssistant
|
||||
systemd.services.scanhook = {
|
||||
description = "webhook go server to trigger scanning";
|
||||
documentation = [ "https://github.com/adnanh/webhook" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
path = with pkgs; [ bash ];
|
||||
serviceConfig = {
|
||||
TemporaryFileSystem = "/:ro";
|
||||
BindReadOnlyPaths = [
|
||||
"/nix/store"
|
||||
"-/etc/resolv.conf"
|
||||
"-/etc/nsswitch.conf"
|
||||
"-/etc/hosts"
|
||||
"-/etc/localtime"
|
||||
];
|
||||
BindPaths = [
|
||||
"/data/applications/paperless-consumption"
|
||||
];
|
||||
LockPersonality = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
PrivateUsers = true;
|
||||
ProcSubset = "pid";
|
||||
ProtectHome = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
DynamicUser = true;
|
||||
ExecStart =
|
||||
let
|
||||
scanScript = pkgs.writeScript "plscan.sh" ''
|
||||
#!/usr/bin/env bash
|
||||
export PATH=${lib.makeBinPath [ pkgs.strace pkgs.gnugrep pkgs.coreutils pkgs.sane-backends pkgs.sane-airscan pkgs.imagemagick ]}
|
||||
export LD_LIBRARY_PATH=${config.environment.sessionVariables.LD_LIBRARY_PATH} # Adds SANE Libraries to the ld library path of this script
|
||||
set -x
|
||||
date="''$(date --iso-8601=seconds)"
|
||||
filename="Scan ''$date.pdf"
|
||||
tmpdir="''$(mktemp -d)"
|
||||
pushd "''$tmpdir"
|
||||
scanimage --batch=out%d.jpg --format=jpeg --mode Gray -d "airscan:e0:Canon MB5100 series" --source "ADF Duplex" --resolution 300
|
||||
for i in $(ls out*.jpg | grep 'out.*[24680]\.jpg'); do convert $i -rotate 180 $i; done # rotate even stuff
|
||||
convert out*.jpg /data/applications/paperless-consumption/"''$filename"
|
||||
chmod 666 /data/applications/paperless-consumption/"''$filename"
|
||||
popd
|
||||
rm -r "''$tmpdir"
|
||||
'';
|
||||
hooksFile = pkgs.writeText "webhook.json" (builtins.toJSON [
|
||||
{
|
||||
id = "scan-webhook";
|
||||
execute-command = "${scanScript}";
|
||||
|
||||
}
|
||||
]);
|
||||
in
|
||||
"${pkgs.webhook}/bin/webhook -hooks ${hooksFile} -verbose";
|
||||
};
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [ 9000 ];
|
||||
|
||||
# Immutable users due to tmpfs
|
||||
users.mutableUsers = false;
|
||||
|
||||
services.samba.extraConfig = ''
|
||||
min protocol = SMB3
|
||||
vfs objects = acl_xattr catia fruit streams_xattr
|
||||
fruit:nfs_aces = no
|
||||
inherit permissions = yes
|
||||
fruit:posix_rename = yes
|
||||
fruit:model = MacPro7,1@ECOLOR=226,226,224
|
||||
fruit:veto_appledouble = no
|
||||
fruit:wipe_intentionally_left_blank_rfork = yes
|
||||
fruit:delete_empty_adfiles = yes
|
||||
fruit:metadata = stream
|
||||
'';
|
||||
|
||||
ragon = {
|
||||
cli.enable = true;
|
||||
user.enable = true;
|
||||
home-manager.enable = true;
|
||||
persist.enable = true;
|
||||
persist.extraDirectories = [ "/var/lib/syncthing" ];
|
||||
|
||||
services = {
|
||||
samba.enable = true;
|
||||
samba.shares = {
|
||||
TimeMachine = {
|
||||
path = "/backups/DaedalusTimeMachine";
|
||||
comment = "DaedalusTimeMachine";
|
||||
"write list" = "@wheel";
|
||||
"fruit:time machine" = "yes";
|
||||
"fruit:time machine max size" = "2050G";
|
||||
"vfs objects" = "acl_xattr fruit streams_xattr";
|
||||
"inherit acls" = "yes";
|
||||
};
|
||||
data = {
|
||||
path = "/data";
|
||||
comment = "some data for the people";
|
||||
"write list" = "@wheel";
|
||||
};
|
||||
};
|
||||
docker.enable = true;
|
||||
ssh.enable = true;
|
||||
nginx.enable = true;
|
||||
jellyfin.enable = true;
|
||||
tailscale.enable = true;
|
||||
grafana.enable = true;
|
||||
libvirt.enable = true;
|
||||
paperless.enable = true;
|
||||
unifi.enable = true;
|
||||
};
|
||||
|
||||
};
|
||||
}
|
||||
52
hosts/ds9/hardware-configuration.nix
Normal file
52
hosts/ds9/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,52 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ "${modulesPath}/installer/scan/not-detected.nix" ];
|
||||
|
||||
boot.initrd.availableKernelModules = [ "r8169" "ahci" "vfio-pci" "xhci_pci" "ehci_pci" "nvme" "usbhid" "sd_mod" "sr_mod" ];
|
||||
boot.kernelModules = [ "kvm-amd" ];
|
||||
nix.maxJobs = lib.mkDefault 12;
|
||||
powerManagement.cpuFreqGovernor = "performance";
|
||||
|
||||
services.zfs.autoScrub.enable = true;
|
||||
ragon.system.fs = {
|
||||
enable = true;
|
||||
mediadata = false;
|
||||
swap = false;
|
||||
persistentSnapshot = false;
|
||||
nix = "rpool/content/local/nix";
|
||||
varlog = "rpool/content/local/journal";
|
||||
persistent = "rpool/content/safe/persist";
|
||||
arcSize = 8;
|
||||
};
|
||||
services.syncoid.enable = false; # TODO setup offsite backups
|
||||
|
||||
services.sanoid.datasets."rpool/content/safe".recursive = true;
|
||||
services.sanoid.datasets."rpool/content/local/backups" = { };
|
||||
services.sanoid.enable = true;
|
||||
|
||||
swapDevices = [ { device = "/dev/disk/by-id/nvme-eui.000000000000000100a075202c247839-part1"; randomEncryption = true; } ];
|
||||
fileSystems."/boot".device = "/dev/disk/by-uuid/149F-23AA";
|
||||
|
||||
fileSystems."/data" = {
|
||||
device = "rpool/content/safe/data";
|
||||
fsType = "zfs";
|
||||
};
|
||||
fileSystems."/data/media" = {
|
||||
device = "rpool/content/safe/data/media";
|
||||
fsType = "zfs";
|
||||
};
|
||||
fileSystems."/backups" = {
|
||||
device = "rpool/content/local/backups";
|
||||
fsType = "zfs";
|
||||
};
|
||||
fileSystems."/data/media/nzbr" = {
|
||||
device = "10.0.1.2:/storage/media";
|
||||
fsType = "nfs";
|
||||
options = [ "x-systemd.automount" "noauto" ];
|
||||
};
|
||||
|
||||
}
|
||||
63
hosts/picard/default.nix
Normal file
63
hosts/picard/default.nix
Normal file
|
|
@ -0,0 +1,63 @@
|
|||
# Edit this configuration file to define what should be installed on
|
||||
# your system. Help is available in the configuration.nix(5) man page
|
||||
# and in the NixOS manual (accessible by running ‘nixos-help’).
|
||||
|
||||
{ inputs, config, pkgs, ... }:
|
||||
|
||||
{
|
||||
imports =
|
||||
[
|
||||
# Include the results of the hardware scan.
|
||||
./hardware-configuration.nix
|
||||
];
|
||||
|
||||
boot.loader.grub.enable = true;
|
||||
boot.loader.grub.version = 2;
|
||||
boot.loader.grub.device = "/dev/sda";
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
|
||||
services.syncthing.enable = true;
|
||||
|
||||
|
||||
networking.interfaces."ens3" = {
|
||||
ipv6 = {
|
||||
addresses = [
|
||||
{
|
||||
address = "2a03:4000:54:a98::1";
|
||||
prefixLength = 64;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
networking.defaultGateway6 = { address = "fe80::1"; interface = "enp0s3"; };
|
||||
networking.nameservers = [ "1.1.1.1" "8.8.8.8" ];
|
||||
# networking.interfaces.eno1.useDHCP = true;
|
||||
networking.hostId = "7c21236a";
|
||||
|
||||
# Immutable users due to tmpfs
|
||||
users.mutableUsers = false;
|
||||
|
||||
services.postgresql.package = pkgs.postgresql_13;
|
||||
|
||||
ragon = {
|
||||
cli.enable = true;
|
||||
user.enable = true;
|
||||
home-manager.enable = true;
|
||||
persist.enable = true;
|
||||
persist.extraDirectories = [ "/var/lib/syncthing" ];
|
||||
|
||||
services = {
|
||||
ssh.enable = true;
|
||||
bitwarden.enable = true;
|
||||
gitlab.enable = true; # TODO gitlab-runner
|
||||
synapse.enable = true;
|
||||
tailscale.enable = true;
|
||||
hedgedoc.enable = true;
|
||||
ts3.enable = true;
|
||||
nginx.enable = true;
|
||||
nginx.domain = "ragon.xyz";
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
42
hosts/picard/hardware-configuration.nix
Normal file
42
hosts/picard/hardware-configuration.nix
Normal file
|
|
@ -0,0 +1,42 @@
|
|||
# Do not modify this file! It was generated by ‘nixos-generate-config’
|
||||
# and may be overwritten by future invocations. Please make changes
|
||||
# to /etc/nixos/configuration.nix instead.
|
||||
{ config, lib, pkgs, modulesPath, ... }:
|
||||
|
||||
{
|
||||
imports = [ "${modulesPath}/profiles/qemu-guest.nix" ];
|
||||
boot.zfs.requestEncryptionCredentials = true;
|
||||
ragon.system.fs.enable = true;
|
||||
ragon.system.fs.nix = "rpool/nix";
|
||||
ragon.system.fs.varlog = "rpool/varlog";
|
||||
ragon.system.fs.persistent = "rpool/persist";
|
||||
ragon.system.fs.swap = false;
|
||||
ragon.system.fs.mediadata = false;
|
||||
swapDevices = [
|
||||
{ device = "/dev/sda2"; randomEncryption.enable = true; }
|
||||
];
|
||||
services.syncoid.enable = false; # disable failing zfs syncing
|
||||
boot.initrd = {
|
||||
network = {
|
||||
enable = true;
|
||||
postCommands = ''
|
||||
zpool import rpool
|
||||
echo "zfs load-key -a; killall zfs" >> /root/.profile
|
||||
'';
|
||||
ssh = {
|
||||
enable = true;
|
||||
port = 2222;
|
||||
hostKeys = [
|
||||
"/persistent/etc/nixos/secrets/initrd/ssh_host_rsa_key"
|
||||
"/persistent/etc/nixos/secrets/initrd/ssh_host_ed25519_key"
|
||||
];
|
||||
authorizedKeys = pkgs.pubkeys.ragon.user;
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
powerManagement.cpuFreqGovernor = "performance";
|
||||
}
|
||||
92
hosts/wormhole/default.nix
Normal file
92
hosts/wormhole/default.nix
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
{ config, inputs, pkgs, lib, ... }:
|
||||
{
|
||||
imports = [
|
||||
"${inputs.nixpkgs}/nixos/modules/installer/sd-card/sd-image-aarch64.nix"
|
||||
"${inputs.nixos-hardware}/raspberry-pi/4/default.nix"
|
||||
./router.nix
|
||||
];
|
||||
nixpkgs.overlays = [
|
||||
(final: super: {
|
||||
makeModulesClosure = x:
|
||||
super.makeModulesClosure (x // { allowMissing = true; });
|
||||
})
|
||||
];
|
||||
boot.loader.systemd-boot.enable = false;
|
||||
boot.kernelPackages = pkgs.linuxPackages_rpi4;
|
||||
boot.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here
|
||||
boot.inird.supportedFilesystems = lib.mkForce [ "reiserfs" "vfat" "zfs" "ext4" ]; # we dont need zfs here
|
||||
networking.hostId = "eec43f51";
|
||||
# networking.usePredictableInterfaceNames = false;
|
||||
documentation.enable = false;
|
||||
documentation.nixos.enable = false;
|
||||
|
||||
nix = {
|
||||
autoOptimiseStore = true;
|
||||
gc = {
|
||||
automatic = true;
|
||||
dates = "weekly";
|
||||
options = "--delete-older-than 30d";
|
||||
};
|
||||
# Free up to 1GiB whenever there is less than 100MiB left.
|
||||
extraOptions = ''
|
||||
min-free = ${toString (100 * 1024 * 1024)}
|
||||
max-free = ${toString (1024 * 1024 * 1024)}
|
||||
'';
|
||||
};
|
||||
powerManagement.cpuFreqGovernor = "ondemand";
|
||||
|
||||
# Assuming this is installed on top of the disk image.
|
||||
fileSystems = {
|
||||
"/" = {
|
||||
device = "/dev/disk/by-label/NIXOS_SD";
|
||||
fsType = "ext4";
|
||||
options = [ "noatime" ];
|
||||
};
|
||||
};
|
||||
|
||||
ragon.networking.router.enable = true;
|
||||
ragon.services.ssh.enable = true;
|
||||
ragon.cli.enable = true;
|
||||
ragon.cli.maximal = false;
|
||||
services.lorri.enable = false;
|
||||
ragon.services.ddns.enable = true;
|
||||
ragon.services.tailscale.enable = true;
|
||||
ragon.services.nginx.enable = true;
|
||||
services.nginx.virtualHosts."h.hailsatan.eu" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "hailsatan.eu";
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".proxyPass = "http://10.0.0.20:8123";
|
||||
locations."/".proxyWebsockets = true;
|
||||
};
|
||||
services.nginx.virtualHosts."hailsatan.eu" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "hailsatan.eu";
|
||||
root = pkgs.runCommand "homepage" { } ''
|
||||
mkdir -p $out
|
||||
echo "Hail Satan" > $out/index.html
|
||||
echo "User-agent: *" > $out/robots.txt
|
||||
echo "Disallow: /" >> $out/robots.txt
|
||||
'';
|
||||
};
|
||||
services.nginx.virtualHosts."j.hailsatan.eu" = {
|
||||
forceSSL = true;
|
||||
useACMEHost = "hailsatan.eu";
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/".proxyPass = "https://j.hailsatan.eu";
|
||||
locations."/".proxyWebsockets = true;
|
||||
};
|
||||
|
||||
users.users.root.openssh.autorizedKeys = [
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDiKJEYNUU+ZpbOyJf9k9ZZdTTL0qLiZ6fXEBVCjNfas"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIkFgHr6OMwsnGhdG4TwKdthlJC/B9ELqZfrmJ9Sf7qk"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCJVa1zAjR6stS4qIEysQbR9n0/AV2h62QRfsRvNfQiL19ExKFR7ZHaUFBr6jnGjzl5eyK0DtwZMlyaDlTR/AXiTZHJrvEPL1lna42wK252uZb66DXAG23L+iFeXySq3f+a6Prw8NU3HvIvC/YkEYwjjbqPKEjvnIHd2dJ1FZ9T9FeoKup3nMWYGDRqrja8NcRwCY9OpPd3ZKZJlNJcPfbfAipGAuQ6EGgGi0GzqoYP9OqZx9PBQQEY7a5+cUgYYEI75NJNuk4/WBm8fkFKrcOmvhTOEb90kbNmpHusDOrFEo8LATdpmJSG013DpPb1W7pMxMq+YgFF4INqIxrhBGht"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH8RjUQ6DDDDgsVbqq+6zz1q6cBkus/BLUGa9JoWsqB4"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCWwrrROqkBEZi8t7Czu1jDDJjSqomGXx7dhIx73GTb3bBlgThqUSsrG+NpP9mxNl4sYgmJYQ9idpUW/RTX3/sXBvNQi4rOqv9z1qdEyzF86CcyWGk4f+D2hJffLlcIbvbDCJ92PF+k5NbH+PC/yVZKSIRC3ENBHf38l8n25ABuBcpCI16bPCIbqbpekqStXClug//uAyENuS6+orHFQg3muUihEedEhJly1QAfDhOzZRlBxTGQcDvZA/XMaIyjAqbXaNVRsDLmKezm/Dg5M3jMIRxApUd9hcuZlfemxUgD0qqnJSTahb9rMxUKk5jdY95EthAp0s2e6tc2O76sYPqb"
|
||||
"ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH99QITZa3hSa+7sMo4M5IC5mXWEjsRqXUSaYKKRyQfE"
|
||||
];
|
||||
}
|
||||
422
hosts/wormhole/router.nix
Normal file
422
hosts/wormhole/router.nix
Normal file
|
|
@ -0,0 +1,422 @@
|
|||
{ config, lib, pkgs, ... }:
|
||||
with lib;
|
||||
with lib.my;
|
||||
let
|
||||
wgEnabled = hasAttrByPath [ "hosts" config.networking.hostName ] (importTOML ../../data/wireguard.toml);
|
||||
cfg = config.ragon.networking.router;
|
||||
waninterface = cfg.waninterface;
|
||||
laninterface = cfg.laninterface;
|
||||
prefixSize = cfg.prefixSize;
|
||||
statics = cfg.statics;
|
||||
domain = cfg.domain;
|
||||
disableFirewallFor = cfg.disableFirewallFor;
|
||||
lan = {
|
||||
name = "lan";
|
||||
internet = true;
|
||||
allowipv6 = true;
|
||||
ipv4addr = "10.0.0.1";
|
||||
netipv4addr = "10.0.0.0";
|
||||
dhcpv4start = "10.0.10.1";
|
||||
dhcpv4end = "10.0.255.240";
|
||||
routes = [
|
||||
{ address = "10.12.0.0"; prefixLength = 16; via = "10.0.1.2"; }
|
||||
{ address = "10.13.0.0"; prefixLength = 16; via = "10.0.1.2"; }
|
||||
];
|
||||
ipv4size = 16;
|
||||
vlan = 4;
|
||||
};
|
||||
iot = {
|
||||
name = "iot";
|
||||
internet = false;
|
||||
allowipv6 = false;
|
||||
ipv4addr = "10.1.0.1";
|
||||
netipv4addr = "10.1.0.0";
|
||||
dhcpv4start = "10.1.1.1";
|
||||
dhcpv4end = "10.1.255.240";
|
||||
routes = [ ];
|
||||
ipv4size = 16;
|
||||
vlan = 2;
|
||||
};
|
||||
guest = {
|
||||
name = "guest";
|
||||
internet = true;
|
||||
allowipv6 = false;
|
||||
ipv4addr = "192.168.2.1";
|
||||
netipv4addr = "192.168.2.0";
|
||||
dhcpv4start = "192.168.2.10";
|
||||
dhcpv4end = "192.168.2.240";
|
||||
routes = [ ];
|
||||
ipv4size = 24;
|
||||
vlan = 3;
|
||||
};
|
||||
nets = [ lan iot guest ];
|
||||
ipv6nets = builtins.filter (a: a.allowipv6) nets;
|
||||
interfaceGenerator = obj: {
|
||||
"${obj.name}".ipv4 = {
|
||||
addresses = [{
|
||||
address = obj.ipv4addr;
|
||||
prefixLength = obj.ipv4size;
|
||||
}];
|
||||
routes = [{
|
||||
address = obj.netipv4addr;
|
||||
prefixLength = obj.ipv4size;
|
||||
}] ++ obj.routes;
|
||||
};
|
||||
};
|
||||
in
|
||||
{
|
||||
options.ragon.networking.router.enable = mkBoolOpt false;
|
||||
options.ragon.networking.router.waninterface =
|
||||
lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "eth1";
|
||||
};
|
||||
options.ragon.networking.router.laninterface =
|
||||
lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "eth0";
|
||||
};
|
||||
options.ragon.networking.router.domain =
|
||||
lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hailsatan.eu";
|
||||
};
|
||||
options.ragon.networking.router.prefixSize =
|
||||
lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 59;
|
||||
};
|
||||
options.ragon.networking.router.statics =
|
||||
lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [
|
||||
{ name = "j.hailsatan.eu"; ip = "10.0.0.2"; }
|
||||
{ name = "paperless.hailsatan.eu"; ip = "10.0.0.2"; }
|
||||
{ name = "unifi.hailsatan.eu"; ip = "10.0.0.2"; }
|
||||
{ name = "nix.hailsatan.eu"; ip = "10.0.0.2"; }
|
||||
{ name = "h.hailsatan.eu"; ip = "10.0.0.1"; }
|
||||
{ name = "grafana.hailsatan.eu"; ip = "10.0.0.2"; }
|
||||
{ name = "nzbr.de"; ip = "10.0.1.2"; }
|
||||
{ name = "storm.nzbr.de"; ip = "45.9.63.165"; }
|
||||
{ name = "avalanche.nzbr.de"; ip = "202.61.247.0"; }
|
||||
];
|
||||
};
|
||||
options.ragon.networking.router.disableFirewallFor =
|
||||
lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [
|
||||
{ hostname = "enterprise"; mac = "d8:cb:8a:76:09:0a"; tcpports = [ 22 ]; udpports = [ ]; }
|
||||
{ hostname = "earthquake"; mac = "78:24:af:bc:0c:07"; tcpports = [ 22 22000 ]; udpports = [ 22000 51820 ]; }
|
||||
];
|
||||
};
|
||||
options.ragon.networking.router.staticDHCPs =
|
||||
lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [
|
||||
# ragon - machines
|
||||
{ name = "enterprise"; ip = "10.0.0.9"; mac = "d8:cb:8a:76:09:0a"; }
|
||||
{ name = "ds9"; ip = "10.0.0.2"; mac = "f4:b5:20:0e:21:d5"; }
|
||||
# ragon - vms
|
||||
{ name = "homeassistant"; ip = "10.0.0.20"; mac = "52:54:00:a1:04:14"; }
|
||||
{ name = "enterprise-win"; ip = "10.0.0.201"; mac = "52:54:00:f3:ab:dd"; }
|
||||
# ragon - iot
|
||||
{ name = "zbbridge"; ip = "10.1.0.5"; mac = "98:f4:ab:e2:b6:a3"; }
|
||||
{ name = "wled-Schrank-Philipp"; ip = "10.1.0.10"; mac = "2c:f4:32:20:74:60"; }
|
||||
{ name = "wled-Betthintergrund-Phi"; ip = "10.1.0.11"; mac = "2c:3a:e8:0e:ab:71"; }
|
||||
|
||||
# nzbr - machines
|
||||
{ name = "earthquake"; ip = "10.0.1.2"; mac = "78:24:af:bc:0c:07"; }
|
||||
{ name = "comet"; ip = "10.0.1.4"; mac = "0c:98:38:d3:16:8f"; }
|
||||
{ name = "meteor"; ip = "10.0.1.8"; mac = "54:27:1e:5c:1f:ed"; } # Wireless
|
||||
{ name = "meteor"; ip = "10.0.1.16"; mac = "00:21:cc:5c:f5:dc"; } # Wired
|
||||
{ name = "hurricane"; ip = "10.0.1.32"; mac = "f0:2f:74:1b:af:e0"; }
|
||||
|
||||
# nzbr - vms
|
||||
{ name = "earthquake-macos"; ip = "10.0.1.201"; mac = "52:54:00:8e:e2:66"; }
|
||||
{ name = "earthquake-win"; ip = "10.0.1.202"; mac = "52:54:00:97:37:69"; }
|
||||
|
||||
# nzbr - consoles
|
||||
{ name = "xbox"; ip = "10.0.2.1"; mac = "58:82:a8:30:2d:1c"; }
|
||||
{ name = "wii"; ip = "10.0.2.2"; mac = "00:23:cc:50:78:00"; }
|
||||
{ name = "switch"; ip = "10.0.2.3"; mac = "dc:68:eb:bb:01:fc"; } # Wireless
|
||||
];
|
||||
};
|
||||
options.ragon.networking.router.forwardedPorts =
|
||||
lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [
|
||||
#{ proto = "tcp"; sourcePort = "5060-5061"; destination = "10.0.0.11"; }
|
||||
];
|
||||
};
|
||||
config = {
|
||||
# https://www.willghatch.net/blog/2020/06/22/nixos-raspberry-pi-4-google-fiber-router/
|
||||
|
||||
# You’d better forward packets if you actually want a router.
|
||||
boot.kernel.sysctl = {
|
||||
"net.ipv4.ip_forward" = 1;
|
||||
"net.ipv6.conf.all.forwarding" = 1;
|
||||
"net.ipv6.conf.default.forwarding" = 1;
|
||||
"net.ipv6.conf.6rdtun.forwarding" = 1;
|
||||
};
|
||||
|
||||
networking.vlans =
|
||||
let
|
||||
genVlan = obj: {
|
||||
"${obj.name}" = {
|
||||
id = obj.vlan;
|
||||
interface = laninterface;
|
||||
};
|
||||
};
|
||||
in
|
||||
lib.foldl (a: b: a // b) { } (map genVlan nets);
|
||||
|
||||
networking.interfaces =
|
||||
let
|
||||
genVlanConf = lib.foldl (a: b: a // b) { } (map interfaceGenerator nets);
|
||||
in
|
||||
{
|
||||
"${waninterface}" = {
|
||||
useDHCP = true;
|
||||
};
|
||||
} // genVlanConf;
|
||||
networking.dhcpcd = {
|
||||
enable = true;
|
||||
allowInterfaces = [
|
||||
"${waninterface}"
|
||||
] ++ (map (a: a.name) ipv6nets);
|
||||
extraConfig =
|
||||
let
|
||||
genDesc = obj: ''
|
||||
# We don’t want dhcpcd to give us an address on the ${obj.name} interface.
|
||||
interface ${obj.name}
|
||||
noipv4
|
||||
|
||||
'';
|
||||
allGenIntDescs = builtins.concatStringsSep "\n" (map genDesc ipv6nets);
|
||||
in
|
||||
''
|
||||
# The man page says that ipv6rs should be disabled globally when
|
||||
# using a prefix delegation.
|
||||
noipv6rs
|
||||
|
||||
interface ${waninterface}
|
||||
# On the wan interface, we want to ask for a prefix delegation.
|
||||
iaid 0
|
||||
ipv6rs
|
||||
ia_pd 0/::/${toString prefixSize} lan/0/${toString prefixSize}
|
||||
|
||||
${allGenIntDescs}
|
||||
'';
|
||||
runHook = ''
|
||||
if [[ "$reason" == "BOUND6" ]] || [[ "$reason" == "REBIND6" ]]; then
|
||||
${pkgs.python3}/bin/python3 ${pkgs.writeScript "dhcpcd-runHook.py" ''
|
||||
import json
|
||||
import sys
|
||||
import subprocess
|
||||
import os
|
||||
|
||||
prefix = os.environ.get("new_dhcp6_ia_pd1_prefix1")[:-1]
|
||||
|
||||
# https://stackoverflow.com/a/37316533/12852285
|
||||
def mac2ipv6(mac):
|
||||
# only accept MACs separated by a colon
|
||||
parts = mac.split(":")
|
||||
|
||||
# modify parts to match IPv6 value
|
||||
parts.insert(3, "ff")
|
||||
parts.insert(4, "fe")
|
||||
parts[0] = "%x" % (int(parts[0], 16) ^ 2)
|
||||
|
||||
# format output
|
||||
ipv6Parts = []
|
||||
for i in range(0, len(parts), 2):
|
||||
ipv6Parts.append("".join(parts[i:i+2]))
|
||||
ipv6 = "%s%s" % (prefix, ":".join(ipv6Parts))
|
||||
return ipv6
|
||||
|
||||
data = json.loads("""${builtins.toJSON disableFirewallFor}""")
|
||||
for host in data:
|
||||
print('setting firewall rules for ' + host["hostname"])
|
||||
IP = mac2ipv6(host["mac"])
|
||||
if len(host["tcpports"]) > 0:
|
||||
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "tcp", "dport", f'{{ {", ".join(map(str, host["tcpports"]))} }}', "accept" ])
|
||||
if len(host["udpports"]) > 0:
|
||||
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "udp", "dport", f'{{ {", ".join(map(str, host["udpports"]))} }}', "accept" ])
|
||||
subprocess.run(["${pkgs.nftables}/bin/nft", "insert", "rule", "inet", "filter", "forward", "ip6", "daddr", IP, "icmpv6", "type", "{ destination-unreachable, packet-too-big, time-exceeded, parameter-problem, echo-request, echo-reply, nd-router-advert, nd-neighbor-solicit, nd-neighbor-advert }", "accept"])
|
||||
''}
|
||||
fi
|
||||
'';
|
||||
};
|
||||
|
||||
networking.firewall.enable = false; # disable iptables cause it's ass to set up
|
||||
networking.nftables.enable = true;
|
||||
networking.nftables.ruleset =
|
||||
let
|
||||
unsafeInterfaces = (map (x: x.name) (filter (x: x.internet == false) nets));
|
||||
safeInterfaces = (map (x: x.name) (filter (x: x.internet == true) nets)) ++ [ "lo" ] ++ (optionals (wgEnabled) [ "wg0" ]);
|
||||
allInternalInterfaces = (map (x: x.name) nets) ++ [ "lo" ];
|
||||
portForwards = concatStringsSep "\n" (map (x: "iifname ${waninterface} ${x.proto} dport ${toString x.sourcePort} dnat ${x.destination}") cfg.forwardedPorts);
|
||||
dropUnsafe = concatStringsSep "\n" (map (x: "iifname ${x} drop") unsafeInterfaces);
|
||||
allowSafe = concatStringsSep "\n" (map (x: "iifname ${x} accept") safeInterfaces);
|
||||
allowSafeOif = concatStringsSep "\n" (map (x: "oifname ${x} ct state { established, related } accept") safeInterfaces);
|
||||
allowAll = concatStringsSep "\n" (map (x: "iifname ${x} accept") (allInternalInterfaces ++ (optionals (wgEnabled) [ "wg0" ])));
|
||||
in
|
||||
''
|
||||
define unsafe_interfaces = {
|
||||
${concatStringsSep ",\n" unsafeInterfaces}
|
||||
}
|
||||
define safe_interfaces = {
|
||||
lo,
|
||||
${concatStringsSep ",\n" safeInterfaces}
|
||||
}
|
||||
define all_interfaces = {
|
||||
lo,
|
||||
${concatStringsSep ",\n" allInternalInterfaces}
|
||||
}
|
||||
table inet filter {
|
||||
chain input {
|
||||
type filter hook input priority 0;
|
||||
|
||||
# allow established/related connections
|
||||
ct state { established, related } accept
|
||||
|
||||
# early drop of invalid connections
|
||||
ct state invalid drop
|
||||
|
||||
# allow from loopback and internal nic
|
||||
${allowAll}
|
||||
|
||||
# allow icmp
|
||||
ip protocol icmp icmp type echo-request limit rate over 1/second burst 5 packets drop
|
||||
ip6 nexthdr icmpv6 icmpv6 type echo-request limit rate over 1/second burst 5 packets drop
|
||||
ip protocol icmp icmp type { destination-unreachable, echo-reply, echo-request, source-quench, time-exceeded } accept
|
||||
ip6 nexthdr icmpv6 icmpv6 type { destination-unreachable, echo-reply, echo-request, nd-neighbor-solicit, nd-router-advert, nd-neighbor-advert, packet-too-big, parameter-problem, time-exceeded } accept
|
||||
|
||||
# open port 22, but only allow 2 new connections per minute from each ip
|
||||
tcp dport 22 ct state new flow table ssh-ftable { ip saddr limit rate 2/minute } accept
|
||||
tcp dport 80 accept
|
||||
tcp dport 443 accept
|
||||
udp dport 51820 accept
|
||||
|
||||
# everything else
|
||||
reject with icmp type port-unreachable
|
||||
}
|
||||
chain forward {
|
||||
type filter hook forward priority 0;
|
||||
|
||||
# allow from loopback and internal nic
|
||||
${allowSafe}
|
||||
|
||||
# allow established/related connections
|
||||
${allowSafeOif}
|
||||
|
||||
# Drop everything else
|
||||
drop
|
||||
}
|
||||
chain output {
|
||||
type filter hook output priority 0
|
||||
# dont allow any trafic from iot and stuff to escape to the wild
|
||||
${dropUnsafe}
|
||||
}
|
||||
}
|
||||
table ip nat {
|
||||
chain prerouting {
|
||||
type nat hook prerouting priority 0
|
||||
${portForwards}
|
||||
}
|
||||
|
||||
chain postrouting {
|
||||
type nat hook postrouting priority 0
|
||||
|
||||
oifname ${waninterface} masquerade
|
||||
}
|
||||
}
|
||||
'';
|
||||
|
||||
services.dnsmasq = {
|
||||
enable = true;
|
||||
alwaysKeepRunning = true;
|
||||
extraConfig =
|
||||
let
|
||||
inherit (pkgs) runCommand;
|
||||
gen = obj: ''
|
||||
interface=${obj.name}
|
||||
dhcp-range=${obj.name},${obj.dhcpv4start},${obj.dhcpv4end},12h
|
||||
'';
|
||||
|
||||
genHosts = obj: ''
|
||||
dhcp-host=${obj.mac},${obj.ip},${obj.name}
|
||||
'';
|
||||
genall = builtins.concatStringsSep "\n" (map gen nets);
|
||||
genallHosts = builtins.concatStringsSep "\n" (map genHosts cfg.staticDHCPs);
|
||||
genstatics = builtins.concatStringsSep "\n" (map (a: "address=/${a.name}/${a.ip}") statics);
|
||||
netbootxyz = builtins.fetchurl {
|
||||
url = "https://github.com/netbootxyz/netboot.xyz/releases/download/2.0.40/netboot.xyz.efi";
|
||||
sha256 = "1gvgvlaxhjkr9i0b2bjq85h12ni9h5fn6r8nphsag3il9kificcc";
|
||||
};
|
||||
netbootxyzpath = runCommand "netbootpath" { } ''
|
||||
mkdir $out
|
||||
ln -s ${netbootxyz} $out/netbootxyz.efi
|
||||
'';
|
||||
in
|
||||
''
|
||||
no-resolv
|
||||
# unbound broke
|
||||
# server=127.0.0.1#5353 # unbound
|
||||
server=1.1.1.1
|
||||
server=1.0.0.1
|
||||
|
||||
# https://hveem.no/using-dnsmasq-for-dhcpv6
|
||||
|
||||
# don't ever listen to anything on wan and stuff
|
||||
except-interface=${waninterface},${laninterface}
|
||||
|
||||
listen-address=0.0.0.0,::
|
||||
|
||||
# don't send bogus requests out on the internets
|
||||
bogus-priv
|
||||
|
||||
# enable IPv6 Route Advertisements
|
||||
enable-ra
|
||||
|
||||
# Construct a valid IPv6 range from reading the address set on the interface. The :: part refers to the ifid in dhcp6c.conf. Make sure you get this right or dnsmasq will get confused.
|
||||
dhcp-range=lan,::,constructor:lan, ra-names,slaac, 12h
|
||||
|
||||
# ra-names enables a mode which gives DNS names to dual-stack hosts which do SLAAC for IPv6.
|
||||
# Add your local-only LAN domain
|
||||
local=/${domain}/
|
||||
|
||||
# have your simple hosts expanded to domain
|
||||
expand-hosts
|
||||
|
||||
# set your domain for expand-hosts
|
||||
domain=${domain}
|
||||
|
||||
# forward .kube domains to coredns
|
||||
server=/kube/10.13.0.10
|
||||
|
||||
|
||||
${genall}
|
||||
'' +
|
||||
optionalString wgEnabled ''
|
||||
interface=wg0
|
||||
no-dhcp-interface=wg0
|
||||
addn-hosts=/run/wireguard-hosts
|
||||
'' + ''
|
||||
interface=lo # otherwise localhost dns does not work
|
||||
${genstatics}
|
||||
${genallHosts}
|
||||
|
||||
dhcp-boot=netbootxyz.efi
|
||||
|
||||
enable-tftp
|
||||
tftp-root=${netbootxyzpath}
|
||||
|
||||
# set authoritative mode
|
||||
dhcp-authoritative
|
||||
|
||||
'';
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue