chore: merge remote-tracking branch 'refs/remotes/origin/master'

This commit is contained in:
Ahwx 2025-06-03 21:52:21 +02:00
commit c9fb9e22f0
14 changed files with 324 additions and 124 deletions

View file

@ -11,6 +11,24 @@ let
# internalIPs = lib.mapAttrsToList ( # internalIPs = lib.mapAttrsToList (
# _: val: lib.strings.removeSuffix ".1" val.cidr + ".0/24" # _: val: lib.strings.removeSuffix ".1" val.cidr + ".0/24"
# ) networks; # ) networks;
commonDhcpOptions = [
{
name = "domain-name-servers";
data = "9.9.9.9";
}
{
name = "time-servers";
data = "172.16.1.1";
}
{
name = "domain-name";
data = "beeping.local";
}
{
name = "domain-search";
data = "beeping.local";
}
];
in in
{ {
imports = [ imports = [
@ -51,7 +69,26 @@ in
}; };
}; };
# label network interfaces
services.udev.extraRules = ''
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:47:67:6e", ATTR{type}=="1", NAME="wan0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:47:67:6f", ATTR{type}=="1", NAME="lan0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:63:0f:80", ATTR{type}=="1", NAME="lan1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:63:0f:81", ATTR{type}=="1", NAME="lan2"
'';
networking = { networking = {
nameservers = [
"9.9.9.9"
"149.112.112.112"
];
interfaces = {
wan0.useDHCP = true;
lan0.useDHCP = false;
lan1.useDHCP = false;
lan2.useDHCP = false;
};
firewall = { firewall = {
enable = false; enable = false;
allowPing = true; allowPing = true;
@ -101,56 +138,108 @@ in
}; };
services = { services = {
udev.extraRules = '' kea.dhcp4 = {
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:47:67:6e", ATTR{type}=="1", NAME="wan0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:47:67:6f", ATTR{type}=="1", NAME="lan0"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:63:0f:80", ATTR{type}=="1", NAME="lan1"
SUBSYSTEM=="net", ACTION=="add", DRIVERS=="?*", ATTR{address}=="00:25:90:63:0f:81", ATTR{type}=="1", NAME="lan2"
'';
dhcpd4 = {
enable = true; enable = true;
interfaces = [ settings = {
"lan" lease-database = {
"servers" name = "/var/lib/kea/dhcp4.leases";
"management" persist = true;
"iot" type = "memfile";
"guest" };
]; interfaces-config = {
extraConfig = '' interfaces = [
option domain-name-servers 9.9.9.9, 149.112.112.112; "lan"
option subnet-mask 255.255.255.0; "servers"
"management"
"iot"
"guest"
];
};
option-data = [
{
name = "domain-name-servers";
data = "";
always-send = true;
}
{
name = "routers";
data = "";
}
{
name = "domain-name";
data = "beeping.local";
}
];
subnet 172.16.1.0 netmask 255.255.255.0 { rebind-timer = 2000;
option broadcast-address 172.16.1.255; renew-timer = 1000;
option routers 172.16.1.1; valid-lifetime = 43200;
interface lan;
range 172.16.1.50 172.16.1.254; # option domain-name-servers 9.9.9.9, 149.112.112.112;
} # TODO: these should be dynamically generated based on ${config.networking.vlans}
subnet 172.16.10.0 netmask 255.255.255.0 { subnet4 = [
option broadcast-address 172.16.10.255; ({
option routers 172.16.10.1; id = 1;
interface servers; interface = "lan";
range 172.16.10.50 172.16.10.254; subnet = "172.16.1.0/24";
} pools = [ { pool = "172.16.1.50 - 172.16.1.254"; } ];
subnet 172.16.21.0 netmask 255.255.255.0 { option-data = [
option broadcast-address 172.16.21.255; {
option routers 172.16.21.1; name = "routers";
interface management; data = "172.16.1.1";
range 172.16.21.50 172.16.21.254; }
} ] ++ commonDhcpOptions;
subnet 172.16.100.0 netmask 255.255.255.0 { })
option broadcast-address 172.16.100.255; ({
option routers 172.16.100.1; id = 10;
interface iot; interface = "servers";
range 172.16.100.50 172.16.100.254; subnet = "172.16.10.0/24";
} pools = [ { pool = "172.16.10.50 - 172.16.10.254"; } ];
subnet 172.16.110.0 netmask 255.255.255.0 { option-data = [
option broadcast-address 172.16.110.255; {
option routers 172.16.110.1; name = "routers";
interface guest; data = "172.16.10.1";
range 172.16.110.50 172.16.110.254; }
} ] ++ commonDhcpOptions;
''; })
({
id = 21;
interface = "management";
subnet = "172.16.21.0/24";
pools = [ { pool = "172.16.21.50 - 172.16.21.254"; } ];
option-data = [
{
name = "routers";
data = "172.16.21.1";
}
] ++ commonDhcpOptions;
})
({
id = 100;
interface = "iot";
subnet = "172.16.100.0/24";
pools = [ { pool = "172.16.100.50 - 172.16.100.254"; } ];
option-data = [
{
name = "routers";
data = "172.16.100.1";
}
] ++ commonDhcpOptions;
})
({
id = 110;
interface = "guest";
subnet = "172.16.110.0/24";
pools = [ { pool = "172.16.110.50 - 172.16.110.254"; } ];
option-data = [
{
name = "routers";
data = "172.16.110.1";
}
] ++ commonDhcpOptions;
})
];
};
}; };
avahi = { avahi = {
enable = true; enable = true;

View file

@ -2,7 +2,7 @@
{ {
services = { services = {
dnsmasq = { dnsmasq = {
enable = true; enable = false; # try some other options first
settings = { settings = {
cache-size = 10000; # Specifies the size of the DNS query cache. It will store up to n cached DNS queries to improve response times for frequently accessed domains. cache-size = 10000; # Specifies the size of the DNS query cache. It will store up to n cached DNS queries to improve response times for frequently accessed domains.
server = [ server = [

View file

@ -1,7 +1,7 @@
{ pkgs, ... }: { pkgs, ... }:
{ {
services.avahi = { services.avahi = {
enable = true; enable = false;
nssmdns4 = true; nssmdns4 = true;
openFirewall = true; openFirewall = true;
}; };

View file

@ -36,7 +36,7 @@
--replace "incorrect password attempts" "nuu silly, try again ~ >.< ~" \ --replace "incorrect password attempts" "nuu silly, try again ~ >.< ~" \
--replace "incorrect password attempt" "nuu silly, try again ~ >.< ~" \ --replace "incorrect password attempt" "nuu silly, try again ~ >.< ~" \
--replace "authentication failure" "oepsie woepsie alles is stukkie wukkie :3" \ --replace "authentication failure" "oepsie woepsie alles is stukkie wukkie :3" \
--replace "a password is required" "no password for me? 🥺\n" --replace "a password is required" "no password? 😭\n"
''; '';
configureFlags = configureFlags =
(builtins.filter (x: !(lib.strings.hasPrefix x "--with-passprompt=")) old.configureFlags) (builtins.filter (x: !(lib.strings.hasPrefix x "--with-passprompt=")) old.configureFlags)

View file

@ -2,7 +2,7 @@
{ {
services.openssh = { services.openssh = {
enable = true; enable = true;
ports = [ 22 ]; ports = [ 9123 ];
settings = { settings = {
PasswordAuthentication = lib.mkDefault false; PasswordAuthentication = lib.mkDefault false;
AllowUsers = null; AllowUsers = null;

View file

@ -66,6 +66,7 @@
librewolf # main librewolf # main
ungoogled-chromium # for things that don't work with librewolf ungoogled-chromium # for things that don't work with librewolf
nsxiv nsxiv
imv
libreoffice libreoffice
xfce.thunar xfce.thunar
spotify spotify

View file

@ -155,27 +155,24 @@
"/home/${username}/.local/bin/waybar-music" = { "/home/${username}/.local/bin/waybar-music" = {
executable = true; executable = true;
text = '' text = ''
#!/usr/bin/env bash #!/usr/bin/env sh
class=$(playerctl metadata --player=ncspot --format '{{lc(status)}}') META="{{ trunc(artist,17) }} - {{ trunc(title,17) }}"
PLAYERS="spotify ncspot mpv mpd"
if [[ $class == "playing" ]]; then for PLAYER in $PLAYERS; do
info=$(playerctl metadata --player=ncspot --format '{{artist}} - {{title}}') # if the player is not playing, continue to the next player, until we find one that is playing
if [[ $\{#info} > 40 ]]; then [ "$(playerctl --player=$PLAYER status 2>/dev/null)" != "Playing" ] && continue
info=$(echo $info | cut -c1-40)"..." text=$(playerctl metadata --player $PLAYER --format "$META")
fi echo -e "{\"text\":\""$text"\", \"class\":\"Playing\"}"
text="$info" exit 0
elif [[ $class == "paused" ]]; then done
info=$(playerctl metadata --player=ncspot --format '{{artist}} - {{title}}')
if [[ $\{#info} > 40 ]]; then
info=$(echo $info | cut -c1-40)"..."
fi
text=" $info"
elif [[ $class == "stopped" ]]; then
text=""
fi
echo -e "{\"text\":\""$text"\", \"class\":\""$class"\"}" ICON=" "
PAUSERS="spotify ncspot mpd"
for PAUSER in $PAUSERS; do
[ "$(playerctl --player=$PAUSER status 2>/dev/null)" == "Paused" ] || [ "$(playerctl --player=$PAUSER status 2>/dev/null)" == "Stopped" ] && text="$ICON"$(playerctl metadata --player $PAUSER --format "$META") && echo -e "{\"text\":\""$text"\", \"class\":\""paused"\"}" && exit 0
done
''; '';
}; };
"/home/${username}/.local/bin/waybar-devices" = { "/home/${username}/.local/bin/waybar-devices" = {

View file

@ -111,12 +111,12 @@
export export PATH="''${PATH}:''${HOME}/.local/bin/:''${HOME}/.cargo/bin/:''${HOME}/.fzf/bin/" export export PATH="''${PATH}:''${HOME}/.local/bin/:''${HOME}/.cargo/bin/:''${HOME}/.fzf/bin/"
if [[ $(which sxiv&>/dev/null && echo 1) == "1" ]]; then # if [[ $(which sxiv&>/dev/null && echo 1) == "1" ]]; then
alias imv="sxiv" # alias imv="sxiv"
elif [[ $(which nsxiv&>/dev/null && echo 1) == "1" ]]; then # elif [[ $(which nsxiv&>/dev/null && echo 1) == "1" ]]; then
alias imv="nsxiv" # alias imv="nsxiv"
alias sxiv="nsxiv" # alias sxiv="nsxiv"
fi # fi
''; '';
zsh-abbr = { zsh-abbr = {
@ -173,6 +173,7 @@
# nvim = "nix run /home/liv/Development/nixvim --"; # nvim = "nix run /home/liv/Development/nixvim --";
vim = "nvim"; vim = "nvim";
doas = "sudo"; doas = "sudo";
sxiv = "nsxiv";
# NixOS # NixOS
ns = "nix-shell --run zsh"; ns = "nix-shell --run zsh";

View file

@ -23,9 +23,9 @@
]; ];
}; };
}; };
networking.firewall = { # networking.firewall = {
allowedTCPPorts = [ # allowedTCPPorts = [
9001 # 9001
]; # ];
}; # };
} }

View file

@ -2,6 +2,6 @@
{ {
services.murmur = { services.murmur = {
enable = true; enable = true;
openFirewall = true; openFirewall = false;
}; };
} }

View file

@ -37,41 +37,35 @@
recommendedProxySettings = true; recommendedProxySettings = true;
clientMaxBodySize = lib.mkDefault "10G"; clientMaxBodySize = lib.mkDefault "10G";
defaultListen = #defaultListen =
let # let
listen = [ # listen = [
{ # {
addr = "[::]"; # addr = "[::]";
port = 80; # port = 80;
extraParameters = [ "proxy_protocol" ]; # extraParameters = [ "proxy_protocol" ];
} # }
{ # {
addr = "[::]"; # addr = "[::]";
port = 443; # port = 443;
ssl = true; # ssl = true;
extraParameters = [ "proxy_protocol" ]; # extraParameters = [ "proxy_protocol" ];
} # }
]; # ];
in # in
map (x: (x // { addr = "0.0.0.0"; })) listen ++ listen; # map (x: (x // { addr = "0.0.0.0"; })) listen ++ listen;
# Hardened TLS and HSTS preloading # Hardened TLS and HSTS preloading
appendHttpConfig = '' appendHttpConfig = ''
# Proxying # Proxying
# real_ip_header proxy_protocol; # real_ip_header proxy_protocol;
server {
listen 80 proxy_protocol;
listen 443 ssl proxy_protocol;
# set_real_ip_from 10.7.0.0/24;
}
ssl_certificate /var/lib/acme/quack.social/cert.pem; ssl_certificate /var/lib/acme/quack.social/cert.pem;
ssl_certificate_key /var/lib/acme/quack.social/key.pem; ssl_certificate_key /var/lib/acme/quack.social/key.pem;
proxy_set_header Host $host; # proxy_set_header Host $host;
proxy_set_header X-Real-IP $proxy_protocol_addr; # proxy_set_header X-Real-IP $proxy_protocol_addr;
proxy_set_header X-Forwarded-For $proxy_protocol_addr; # proxy_set_header X-Forwarded-For $proxy_protocol_addr;
# Add HSTS header with preloading to HTTPS requests. # Add HSTS header with preloading to HTTPS requests.
# Do not add HSTS header to HTTP requests. # Do not add HSTS header to HTTP requests.
@ -98,19 +92,6 @@
add_header pronouns "any but neopronouns"; add_header pronouns "any but neopronouns";
add_header locale "[en_US, nl_NL]"; add_header locale "[en_US, nl_NL]";
''; '';
appendConfig = ''
# https://docs.nginx.com/nginx/admin-guide/load-balancer/using-proxy-protocol/
# set_real_ip_from 213.210.34.27;
# real_ip_header proxy_protocol;
# proxy_set_header Host $host;
# proxy_set_header X-Real-IP $proxy_protocol_addr;
# proxy_set_header X-Forwarded-For $proxy_protocol_addr;
# proxy_set_header X-Forwarded-Proto $scheme;
# proxy_set_header X-Forwarded-Host $host;
# proxy_set_header X-Forwarded-Server $host;
'';
}; };
networking.firewall = { networking.firewall = {
allowedTCPPorts = [ allowedTCPPorts = [

View file

@ -3,7 +3,7 @@
{ {
services.unifi = { services.unifi = {
enable = true; enable = true;
unifiPackage = pkgs.unifi8; unifiPackage = pkgs.unifi;
mongodbPackage = pkgs.mongodb-7_0; mongodbPackage = pkgs.mongodb-7_0;
}; };
# services.nginx = { # services.nginx = {

122
modules/services/vnstat.nix Normal file
View file

@ -0,0 +1,122 @@
{
lib,
config,
pkgs,
...
}:
let
vnstatUser = "vnstatd";
vnstatImageDir = "/var/www/vnstat";
vnstatDashboardFile = pkgs.writeText "dashboard.html" ''
<!DOCTYPE html>
<html lang="en">
<head>
<title>vnStat dashboard</title>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<noscript>
<meta http-equiv="refresh" content="60" />
</noscript>
<style>
body { max-width: 1341px; margin: auto; padding: 5px; }
div { column-count: 2; column-width: 668px; column-gap: 5px; text-align: center }
img { max-width: 100%; min-width: 320px; }
</style>
</head>
<body>
<div>
<img src="vnstat-s.png"> <img src="vnstat-5g.png"> <img src="vnstat-hg.png">
<img src="vnstat-h.png"> <img src="vnstat-d.png"> <img src="vnstat-t.png">
<img src="vnstat-m.png"> <img src="vnstat-y.png">
</div>
<script>
setInterval(function() {
for (let image of document.images) {
image.src = new URL(image.src).pathname + "?t=" + new Date().getTime();
}
}, 60000);
</script>
</body>
</html>'';
serverName = "vnstat.abnv.me";
serviceConfig = config.services."${serverName}";
options = {
enable = lib.mkEnableOption "${serverName} service";
};
in
{
options.services.${serverName} = options;
config = lib.mkIf serviceConfig.enable {
services.vnstat.enable = true;
systemd = {
tmpfiles.rules = [
"d ${vnstatImageDir} 1775 ${vnstatUser} ${vnstatUser}"
"L+ ${vnstatImageDir}/index.html - - - - ${vnstatDashboardFile}"
"Z ${vnstatImageDir} 755 ${vnstatUser} ${vnstatUser}"
];
services."vnstati-web" = {
enable = true;
description = "service that generates images for vnstat monitoring";
startAt = "*:0/5:00";
restartIfChanged = true;
after = [ "vnstat.service" ];
path = [ pkgs.vnstat ];
serviceConfig = {
User = vnstatUser;
Group = vnstatUser;
WorkingDirectory = vnstatImageDir;
Type = "oneshot";
AmbientCapabilities = [ ];
CapabilityBoundingSet = [ ];
KeyringMode = "private";
LockPersonality = true;
NoNewPrivileges = true;
PrivateDevices = true;
PrivateMounts = true;
PrivateTmp = true;
ProtectClock = true;
ProtectControlGroups = true;
ProtectHome = true;
ProtectHostname = true;
ProtectKernelLogs = true;
ProtectKernelModules = true;
ProtectKernelTunables = true;
ProtectSystem = "full";
RemoveIPC = true;
RestrictAddressFamilies = [ ];
RestrictNamespaces = true;
RestrictRealtime = true;
};
script = ''
vnstati --style 1 -L -s -o vnstat-s.png
vnstati --style 1 -L --fivegraph 576 218 -o vnstat-5g.png
vnstati --style 1 -L -hg -o vnstat-hg.png
vnstati --style 1 -L -h 24 -o vnstat-h.png
vnstati --style 1 -L -d 30 -o vnstat-d.png
vnstati --style 1 -L -t 10 -o vnstat-t.png
vnstati --style 1 -L -m 12 -o vnstat-m.png
vnstati --style 1 -L -y 5 -o vnstat-y.png
'';
};
timers."vnstat-image-gen".timerConfig = {
User = vnstatUser;
Group = vnstatUser;
};
};
services.nginx.virtualHosts.${serverName} = {
root = vnstatImageDir;
extraConfig = ''
add_header Cache-Control 'private no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
'';
};
};
}

View file

@ -1,8 +1,16 @@
{ lib, pkgs, config, username, home-manager, ... }: {
lib,
pkgs,
config,
username,
home-manager,
...
}:
with lib; with lib;
let let
cfg = config.liv.creative; cfg = config.liv.creative;
in { in
{
options.liv.creative = { options.liv.creative = {
enable = mkEnableOption "Enable creative workflow"; enable = mkEnableOption "Enable creative workflow";
}; };
@ -17,6 +25,7 @@ in {
obs-studio obs-studio
kdePackages.kdenlive kdePackages.kdenlive
orca-slicer orca-slicer
freecad
]; ];
}; };
}; };