refactor: more sane profile structure

This commit is contained in:
Leon Schwarzäugl 2025-01-01 15:59:58 +01:00
parent a73f0e843a
commit 2257a42d38
Signed by: swarsel
GPG key ID: 26A54C31F2A4FD84
123 changed files with 204 additions and 347 deletions

View file

@ -0,0 +1,5 @@
_:
{
services.blueman.enable = true;
services.hardware.bolt.enable = true;
}

View file

@ -0,0 +1,50 @@
_:
{
imports = [
./settings.nix
./home-manager.nix
./xserver.nix
./users.nix
./env.nix
./stylix.nix
./polkit.nix
./gc.nix
./store.nix
./systemd.nix
./network.nix
./time.nix
./hardware.nix
./pipewire.nix
./sops.nix
./packages.nix
./programs.nix
./zsh.nix
./syncthing.nix
./blueman.nix
./networkdevices.nix
./gvfs.nix
./interceptiontools.nix
./hardwarecompatibility.nix
./login.nix
./stylix.nix
./power-profiles-daemon.nix
# ./impermanence.nix
./nvd-rebuild.nix
./nix-ld.nix
./gnome-keyring.nix
./sway.nix
./xdg-portal.nix
# ./yubikey-touch-detector.nix
# ./safeeyes.nix
./distrobox.nix
./lid.nix
./lowbattery.nix
./lanzaboote.nix
];
nixpkgs.config.permittedInsecurePackages = [
"jitsi-meet-1.0.8043"
"electron-29.4.6"
];
}

View file

@ -0,0 +1,13 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
distrobox
boxbuddy
];
virtualisation.podman = {
enable = true;
package = pkgs.stable.podman;
};
}

View file

@ -0,0 +1,16 @@
{ lib, pkgs, ... }:
{
environment = {
wordlist.enable = true;
sessionVariables = {
NIXOS_OZONE_WL = "1";
GST_PLUGIN_SYSTEM_PATH_1_0 = lib.makeSearchPathOutput "lib" "lib/gstreamer-1.0" (with pkgs.gst_all_1; [
gst-plugins-good
gst-plugins-bad
gst-plugins-ugly
gst-libav
]);
};
};
# gstreamer plugins for nautilus (used for file metadata)
}

View file

@ -0,0 +1,9 @@
_:
{
nix.gc = {
automatic = true;
randomizedDelaySec = "14m";
dates = "weekly";
options = "--delete-older-than 10d";
};
}

View file

@ -0,0 +1,8 @@
_:
{
services.gnome.gnome-keyring = {
enable = true;
};
programs.seahorse.enable = true;
}

View file

@ -0,0 +1,4 @@
_:
{
services.gvfs.enable = true;
}

View file

@ -0,0 +1,40 @@
{ pkgs, config, lib, ... }:
{
hardware = {
# opengl.driSupport32Bit = true is replaced with graphics.enable32Bit and hence redundant
graphics = {
enable = true;
enable32Bit = true;
};
trackpoint = lib.mkIf config.swarselsystems.trackpoint.isAvailable {
enable = true;
inherit (config.swarselsystems.trackpoint) device;
};
keyboard.qmk.enable = true;
pulseaudio = {
enable = lib.mkIf (!config.services.pipewire.enable) true;
package = pkgs.pulseaudioFull;
};
enableAllFirmware = true;
bluetooth = lib.mkIf config.swarselsystems.hasBluetooth {
enable = true;
package = pkgs.stable.bluez;
powerOnBoot = true;
settings = {
General = {
Enable = "Source,Sink,Media,Socket";
};
};
};
};
services.fprintd.enable = lib.mkIf config.swarselsystems.hasFingerprint true;
}

View file

@ -0,0 +1,16 @@
{ pkgs, ... }:
{
programs.ssh.startAgent = false;
services.pcscd.enable = true;
hardware.ledger.enable = true;
services.udev.packages = with pkgs; [
yubikey-personalization
ledger-udev-rules
qmk-udev-rules
vial
via
];
}

View file

@ -0,0 +1,8 @@
{ inputs, config, lib, ... }:
{
home-manager = lib.mkIf config.swarselsystems.withHomeManager {
useGlobalPkgs = true;
useUserPackages = true;
extraSpecialArgs = inputs; # used mainly for inputs.self
};
}

View file

@ -0,0 +1,90 @@
{ config, lib, ... }:
let
mapperTarget = lib.swarselsystems.mkIfElse config.swarselsystems.isCrypted "/dev/mapper/cryptroot" "/dev/disk/by-label/nixos";
in
{
security.sudo.extraConfig = lib.mkIf config.swarselsystems.isImpermanence ''
# rollback results in sudo lectures after each reboot
Defaults lecture = never
'';
# This script does the actual wipe of the system
# So if it doesn't run, the btrfs system effectively acts like a normal system
# Taken from https://github.com/NotAShelf/nyx/blob/2a8273ed3f11a4b4ca027a68405d9eb35eba567b/modules/core/common/system/impermanence/default.nix
boot.initrd.systemd.enable = true;
boot.initrd.systemd.services.rollback = lib.mkIf config.swarselsystems.isImpermanence {
description = "Rollback BTRFS root subvolume to a pristine state";
wantedBy = [ "initrd.target" ];
# make sure it's done after encryption
# i.e. LUKS/TPM process
after = lib.swarselsystems.mkIfElseList config.swarselsystems.isCrypted [ "systemd-cryptsetup@cryptroot.service" ] [ "dev-disk-by\\x2dlabel-nixos.device" ];
requires = lib.mkIf (!config.swarselsystems.isCrypted) [ "dev-disk-by\\x2dlabel-nixos.device" ];
# mount the root fs before clearing
before = [ "sysroot.mount" ];
unitConfig.DefaultDependencies = "no";
serviceConfig.Type = "oneshot";
script = ''
mkdir -p /mnt
# We first mount the btrfs root to /mnt
# so we can manipulate btrfs subvolumes.
mount -o subvolid=5 -t btrfs ${mapperTarget} /mnt
btrfs subvolume list -o /mnt/root
# While we're tempted to just delete /root and create
# a new snapshot from /root-blank, /root is already
# populated at this point with a number of subvolumes,
# which makes `btrfs subvolume delete` fail.
# So, we remove them first.
#
# /root contains subvolumes:
# - /root/var/lib/portables
# - /root/var/lib/machines
btrfs subvolume list -o /mnt/root |
cut -f9 -d' ' |
while read subvolume; do
echo "deleting /$subvolume subvolume..."
btrfs subvolume delete "/mnt/$subvolume"
done &&
echo "deleting /root subvolume..." &&
btrfs subvolume delete /mnt/root
echo "restoring blank /root subvolume..."
btrfs subvolume snapshot /mnt/root-blank /mnt/root
# Once we're done rolling back to a blank snapshot,
# we can unmount /mnt and continue on the boot process.
umount /mnt
'';
};
environment.persistence."/persist" = lib.mkIf config.swarselsystems.isImpermanence {
hideMounts = true;
directories =
[
"/.cache/nix"
"/srv"
"/etc/nixos"
"/etc/nix"
"/etc/NetworkManager/system-connections"
# "/etc/secureboot"
"/home/swarsel/.dotfiles"
"/var/db/sudo"
"/var/cache"
"/var/lib"
];
files = [
"/etc/ssh/ssh_host_ed25519_key"
"/etc/ssh/ssh_host_ed25519_key.pub"
"/etc/ssh/ssh_host_rsa_key"
"/etc/ssh/ssh_host_rsa_key.pub"
];
};
}

View file

@ -0,0 +1,29 @@
{ pkgs, ... }:
{
# Make CAPS work as a dual function ESC/CTRL key
services.interception-tools = {
enable = true;
udevmonConfig =
let
dualFunctionKeysConfig = builtins.toFile "dual-function-keys.yaml" ''
TIMING:
TAP_MILLISEC: 200
DOUBLE_TAP_MILLISEC: 0
MAPPINGS:
- KEY: KEY_CAPSLOCK
TAP: KEY_ESC
HOLD: KEY_LEFTCTRL
'';
in
''
- JOB: |
${pkgs.interception-tools}/bin/intercept -g $DEVNODE \
| ${pkgs.interception-tools-plugins.dual-function-keys}/bin/dual-function-keys -c ${dualFunctionKeysConfig} \
| ${pkgs.interception-tools}/bin/uinput -d $DEVNODE
DEVICE:
EVENTS:
EV_KEY: [KEY_CAPSLOCK]
'';
};
}

View file

@ -0,0 +1,13 @@
{ lib, config, ... }:
{
boot = {
loader = {
efi.canTouchEfiVariables = true;
systemd-boot.enable = lib.swarselsystems.mkIfElse (config.swarselsystems.initialSetup || !config.swarselsystems.isSecureBoot) (lib.mkForce true) (lib.mkForce false);
};
lanzaboote = lib.mkIf (!config.swarselsystems.initialSetup && config.swarselsystems.isSecureBoot) {
enable = true;
pkiBundle = "/var/lib/sbctl";
};
};
}

View file

@ -0,0 +1,26 @@
_:
{
services.logind = {
lidSwitch = "suspend";
lidSwitchDocked = "ignore";
};
services.acpid = {
enable = true;
lidEventCommands =
''
export PATH=$PATH:/run/current-system/sw/bin
export WAYLAND_DISPLAY=wayland-1
export XDG_RUNTIME_DIR=/run/user/1000
export SWAYSOCK=$(ls /run/user/1000/sway-ipc.* | head -n 1)
LID_STATE=$(cat /proc/acpi/button/lid/*/state | grep -q closed && echo "closed" || echo "open")
DOCKED=$(swaymsg -t get_outputs | grep -q 'HDMI\|DP' && echo "docked" || echo "undocked")
if [ "$LID_STATE" == "closed" ] && [ "$DOCKED" == "docked" ]; then
swaymsg output eDP-2 disable
else
swaymsg output eDP-2 enable
fi
'';
};
}

View file

@ -0,0 +1,21 @@
{ pkgs, ... }:
{
services.greetd = {
enable = true;
settings = {
initial_session.command = "sway";
# initial_session.user ="swarsel";
default_session.command = ''
${pkgs.greetd.tuigreet}/bin/tuigreet \
--time \
--asterisks \
--user-menu \
--cmd sway
'';
};
};
environment.etc."greetd/environments".text = ''
sway
'';
}

View file

@ -0,0 +1,26 @@
{ pkgs, lib, ... }:
{
systemd.user.services."battery-low" = {
enable = true;
description = "Notify user if battery is below 10%";
partOf = [ "graphical-session.target" ];
wantedBy = [ "graphical-session.target" ];
serviceConfig = {
Type = "simple";
ExecStart = pkgs.writeShellScript "battery-low-notification"
''
if (( 10 >= $(${lib.getExe pkgs.acpi} -b | head -n 1 | ${lib.getExe pkgs.ripgrep} -o "\d+%" | ${lib.getExe pkgs.ripgrep} -o "\d+")));
then ${lib.getExe pkgs.libnotify} --urgency=critical "low battery" "$(${lib.getExe pkgs.acpi} -b | head -n 1 | ${lib.getExe pkgs.ripgrep} -o "\d+%")";
fi;
'';
};
};
systemd.user.timers."battery-low" = {
wantedBy = [ "timers.target" ];
timerConfig = {
# Every Minute
OnCalendar = "*-*-* *:*:00";
Unit = "battery-low.service";
};
};
}

View file

@ -0,0 +1,245 @@
{ lib, config, ... }:
{
networking = {
nftables.enable = lib.mkDefault true;
enableIPv6 = lib.mkDefault true;
firewall = {
checkReversePath = lib.mkDefault false;
enable = lib.mkDefault true;
allowedUDPPorts = [ 51820 ]; # 51820: wireguard
allowedTCPPortRanges = [
{ from = 1714; to = 1764; } # kde-connect
];
allowedUDPPortRanges = [
{ from = 1714; to = 1764; } # kde-connect
];
};
networkmanager = {
enable = true;
ensureProfiles = lib.mkIf (!config.swarselsystems.isPublic) {
environmentFiles = [
"${config.sops.templates."network-manager.env".path}"
];
profiles = {
"Ernest Routerford" = {
connection = {
id = "Ernest Routerford";
permissions = "";
type = "wifi";
};
ipv4 = {
dns-search = "";
method = "auto";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
dns-search = "";
method = "auto";
};
wifi = {
mac-address-blacklist = "";
mode = "infrastructure";
ssid = "Ernest Routerford";
};
wifi-security = {
auth-alg = "open";
key-mgmt = "wpa-psk";
psk = "$ERNEST";
};
};
LAN-Party = {
connection = {
autoconnect = "false";
id = "LAN-Party";
type = "ethernet";
};
ethernet = {
auto-negotiate = "true";
cloned-mac-address = "preserve";
mac-address = "90:2E:16:D0:A1:87";
};
ipv4 = { method = "shared"; };
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
proxy = { };
};
eduroam = {
"802-1x" = {
eap = "ttls;";
identity = "$EDUID";
password = "$EDUPASS";
phase2-auth = "mschapv2";
};
connection = {
id = "eduroam";
type = "wifi";
};
ipv4 = { method = "auto"; };
ipv6 = {
addr-gen-mode = "default";
method = "auto";
};
proxy = { };
wifi = {
mode = "infrastructure";
ssid = "eduroam";
};
wifi-security = {
auth-alg = "open";
key-mgmt = "wpa-eap";
};
};
local = {
connection = {
autoconnect = "false";
id = "local";
type = "ethernet";
};
ethernet = { };
ipv4 = {
address1 = "10.42.1.1/24";
method = "shared";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
proxy = { };
};
HH40V_39F5 = {
connection = {
id = "HH40V_39F5";
type = "wifi";
};
ipv4 = { method = "auto"; };
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
proxy = { };
wifi = {
band = "bg";
mode = "infrastructure";
ssid = "HH40V_39F5";
};
wifi-security = {
key-mgmt = "wpa-psk";
psk = "$FRAUNS";
};
};
magicant = {
connection = {
id = "magicant";
type = "wifi";
};
ipv4 = { method = "auto"; };
ipv6 = {
addr-gen-mode = "default";
method = "auto";
};
proxy = { };
wifi = {
mode = "infrastructure";
ssid = "magicant";
};
wifi-security = {
auth-alg = "open";
key-mgmt = "wpa-psk";
psk = "$HANDYHOTSPOT";
};
};
wireguardvpn = {
connection = {
id = "HomeVPN";
type = "wireguard";
autoconnect = "false";
interface-name = "wg1";
};
wireguard = { private-key = "$WIREGUARDPRIV"; };
"wireguard-peer.$WIREGUARDPUB" = {
endpoint = "$WIREGUARDENDPOINT";
allowed-ips = "0.0.0.0/0";
};
ipv4 = {
method = "ignore";
address1 = "192.168.3.3/32";
};
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "ignore";
};
proxy = { };
};
"sweden-aes-128-cbc-udp-dns" = {
connection = {
autoconnect = "false";
id = "PIA Sweden";
type = "vpn";
};
ipv4 = { method = "auto"; };
ipv6 = {
addr-gen-mode = "stable-privacy";
method = "auto";
};
proxy = { };
vpn = {
auth = "sha1";
ca = config.sops.secrets."sweden-aes-128-cbc-udp-dns-ca.pem".path;
challenge-response-flags = "2";
cipher = "aes-128-cbc";
compress = "yes";
connection-type = "password";
crl-verify-file = config.sops.secrets."sweden-aes-128-cbc-udp-dns-crl-verify.pem".path;
dev = "tun";
password-flags = "0";
remote = "sweden.privacy.network:1198";
remote-cert-tls = "server";
reneg-seconds = "0";
service-type = "org.freedesktop.NetworkManager.openvpn";
username = "$VPNUSER";
};
vpn-secrets = { password = "$VPNPASS"; };
};
Hotspot = {
connection = {
autoconnect = "false";
id = "Hotspot";
type = "wifi";
};
ipv4 = { method = "shared"; };
ipv6 = {
addr-gen-mode = "default";
method = "ignore";
};
proxy = { };
wifi = {
mode = "ap";
ssid = "Hotspot-swarsel";
};
wifi-security = {
group = "ccmp;";
key-mgmt = "wpa-psk";
pairwise = "ccmp;";
proto = "rsn;";
psk = "$HOTSPOT";
};
};
};
};
};
};
systemd.services.NetworkManager-ensure-profiles.after = [ "NetworkManager.service" ];
}

View file

@ -0,0 +1,30 @@
{ pkgs, ... }:
{
# enable scanners over network
hardware.sane = {
enable = true;
extraBackends = [ pkgs.sane-airscan ];
};
# enable discovery and usage of network devices (esp. printers)
services.printing = {
enable = true;
drivers = [
pkgs.gutenprint
pkgs.gutenprintBin
];
browsedConf = ''
BrowseDNSSDSubTypes _cups,_print
BrowseLocalProtocols all
BrowseRemoteProtocols all
CreateIPPPrinterQueues All
BrowseProtocols all
'';
};
services.avahi = {
enable = true;
nssmdns4 = true;
openFirewall = true;
};
}

View file

@ -0,0 +1,110 @@
{ pkgs, ... }:
{
programs.nix-ld = {
enable = true;
libraries = with pkgs; [
SDL
SDL2
SDL2_image
SDL2_mixer
SDL2_ttf
SDL_image
SDL_mixer
SDL_ttf
alsa-lib
at-spi2-atk
at-spi2-core
atk
bzip2
cairo
cups
curl
dbus
dbus-glib
expat
ffmpeg
flac
fontconfig
freeglut
freetype
fuse3
gdk-pixbuf
glew110
glib
stable.gnome2.GConf
pango
gtk2
gtk3
icu
libGL
libappindicator-gtk2
libappindicator-gtk3
libcaca
libcanberra
libcap
libdbusmenu-gtk2
libdrm
libelf
libgcrypt
libglvnd
libidn
libindicator-gtk2
libjpeg
libmikmod
libnotify
libogg
libpng
libpng12
libpulseaudio
librsvg
libsamplerate
libtheora
libtiff
libudev0-shim
libunwind
libusb1
libuuid
libva
libvdpau
libvorbis
libvpx
libxkbcommon
libxml2
libz
mesa
nspr
nss
openssl
pango
pipewire
pixman
speex
stdenv.cc.cc
steam-fhsenv-without-steam
systemd
tbb
vulkan-loader
xorg.libICE
xorg.libSM
xorg.libX11
xorg.libXScrnSaver
xorg.libXcomposite
xorg.libXcursor
xorg.libXdamage
xorg.libXext
xorg.libXfixes
xorg.libXft
xorg.libXi
xorg.libXinerama
xorg.libXmu
xorg.libXrandr
xorg.libXrender
xorg.libXt
xorg.libXtst
xorg.libXxf86vm
xorg.libxcb
xorg.libxshmfence
zlib
];
};
}

View file

@ -0,0 +1,10 @@
{ pkgs, ... }:
{
system.activationScripts.diff = {
supportsDryActivation = true;
text = ''
${pkgs.nvd}/bin/nvd --color=always --nix-bin-dir=${pkgs.nix}/bin diff \
/run/current-system "$systemConfig"
'';
};
}

View file

@ -0,0 +1,115 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
# yubikey packages
gnupg
yubikey-personalization
yubikey-personalization-gui
yubico-pam
yubioath-flutter
yubikey-manager
yubikey-manager-qt
yubikey-touch-detector
yubico-piv-tool
cfssl
pcsctools
pcscliteWithPolkit.out
# ledger packages
ledger-live-desktop
# pinentry
dbus
swaylock-effects
syncthingtray-minimal
# secure boot
sbctl
libsForQt5.qt5.qtwayland
# nix package database
nix-index
nixos-generators
# commit hooks
pre-commit
# proc info
acpi
# better make for general tasks
just
# keyboards
qmk
vial
via
# theme related
adwaita-icon-theme
# kde-connect
xdg-desktop-portal
xdg-desktop-portal-wlr
# bluetooth
bluez
# lsp-related -------------------------------
# nix
# latex
# texlab
ghostscript_headless
# wireguard
wireguard-tools
# rust
# rust-analyzer
# clippy
# rustfmt
# go
# go
# gopls
# nix
nixd
# zig
zig
zls
# cpp
# clang-tools
# + cuda
# cudatoolkit
# ansible
# ansible-lint
ansible-language-server
# molecule
#lsp-bridge / python
# gcc
# gdb
# (python3.withPackages (ps: with ps; [ jupyter ipython pyqt5 epc orjson sexpdata six setuptools paramiko numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server ]))
# (python3.withPackages(ps: with ps; [ jupyter ipython pyqt5 numpy pandas scipy matplotlib requests debugpy flake8 gnureadline python-lsp-server]))
# --------------------------------------------
# (stdenv.mkDerivation {
# name = "oama";
# src = pkgs.fetchurl {
# name = "oama";
# url = "https://github.com/pdobsan/oama/releases/download/0.13.1/oama-0.13.1-Linux-x86_64-static.tgz";
# sha256 = "sha256-OTdCObVfnMPhgZxVtZqehgUXtKT1iyqozdkPIV+i3Gc=";
# };
# phases = [
# "unpackPhase"
# ];
# unpackPhase = ''
# mkdir -p $out/bin
# tar xvf $src -C $out/
# mv $out/oama-0.13.1-Linux-x86_64-static/oama $out/bin/
# '';
# })
];
}

View file

@ -0,0 +1,15 @@
_: {
security.rtkit.enable = true; # this is required for pipewire real-time access
services.pipewire = {
enable = true;
pulse.enable = true;
jack.enable = true;
audio.enable = true;
wireplumber.enable = true;
alsa = {
enable = true;
support32Bit = true;
};
};
}

View file

@ -0,0 +1,16 @@
_:
{
security.pam.services = {
login.u2fAuth = true;
sudo.u2fAuth = true;
swaylock.u2fAuth = true;
swaylock.fprintAuth = false;
};
security.polkit.enable = true;
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
}

View file

@ -0,0 +1,4 @@
_:
{
services.power-profiles-daemon.enable = true;
}

View file

@ -0,0 +1,8 @@
_:
{
programs = {
dconf.enable = true;
evince.enable = true;
kdeconnect.enable = true;
};
}

View file

@ -0,0 +1,4 @@
_:
{
services.safeeyes.enable = true;
}

View file

@ -0,0 +1,45 @@
{ lib, config, outputs, inputs, ... }:
{
nixpkgs = {
overlays = [ outputs.overlays.default ];
config = {
allowUnfree = true;
};
};
nix =
let
flakeInputs = lib.filterAttrs (_: lib.isType "flake") inputs;
in
{
settings = {
experimental-features = [
"nix-command"
"flakes"
"ca-derivations"
"cgroups"
"pipe-operators"
];
trusted-users = [ "@wheel" "swarsel" ];
connect-timeout = 5;
bash-prompt-prefix = "$SHLVL:\\w ";
bash-prompt = "$(if [[ $? -gt 0 ]]; then printf \"\"; else printf \"\"; fi)\[\e[1m\]λ\[\e[0m\] ";
fallback = true;
min-free = 128000000;
max-free = 1000000000;
flake-registry = "";
auto-optimise-store = true;
warn-dirty = false;
max-jobs = 1;
use-cgroups = lib.mkIf config.swarselsystems.isLinux true;
};
channel.enable = false;
registry = lib.mapAttrs (_: flake: { inherit flake; }) flakeInputs;
nixPath = lib.mapAttrsToList (n: _: "${n}=flake:${n}") flakeInputs;
};
system.stateVersion = lib.mkDefault "23.05";
}

View file

@ -0,0 +1,59 @@
{ self, config, lib, ... }:
let
certsSopsFile = self + /secrets/certs/secrets.yaml;
in
{
sops = lib.mkIf (!config.swarselsystems.isPublic) {
age.sshKeyPaths = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs [ "/persist/.ssh/sops" "/persist/.ssh/ssh_host_ed25519_key" ] [ "${config.users.users.swarsel.home}/.ssh/sops" "/etc/ssh/ssh_host_ed25519_key" ];
defaultSopsFile = lib.swarselsystems.mkIfElseList config.swarselsystems.isBtrfs "/persist/.dotfiles/secrets/general/secrets.yaml" "${config.users.users.swarsel.home}/.dotfiles/secrets/general/secrets.yaml";
validateSopsFiles = false;
secrets = {
ernest = { };
frauns = { };
hotspot = { };
eduid = { };
edupass = { };
handyhotspot = { };
vpnuser = { };
vpnpass = { };
wireguardpriv = { };
wireguardpub = { };
wireguardendpoint = { };
stashuser = { };
stashpass = { };
githubforgeuser = { };
githubforgepass = { };
gitlabforgeuser = { };
gitlabforgepass = { };
"sweden-aes-128-cbc-udp-dns-crl-verify.pem" = { sopsFile = certsSopsFile; owner = "swarsel"; };
"sweden-aes-128-cbc-udp-dns-ca.pem" = { sopsFile = certsSopsFile; owner = "swarsel"; };
};
templates = {
"network-manager.env".content = ''
ERNEST=${config.sops.placeholder.ernest}
FRAUNS=${config.sops.placeholder.frauns}
HOTSPOT=${config.sops.placeholder.hotspot}
EDUID=${config.sops.placeholder.eduid}
EDUPASS=${config.sops.placeholder.edupass}
HANDYHOTSPOT=${config.sops.placeholder.handyhotspot}
VPNUSER=${config.sops.placeholder.vpnuser}
VPNPASS=${config.sops.placeholder.vpnpass}
WIREGUARDPRIV=${config.sops.placeholder.wireguardpriv}
WIREGUARDPUB=${config.sops.placeholder.wireguardpub}
WIREGUARDENDPOINT=${config.sops.placeholder.wireguardendpoint}
'';
# ".authinfo" = {
# owner = "swarsel";
# path = "${config.users.users.swarsel.home}/.emacs.d/.authinfo";
# content = ''
# machine stash.swarsel.win:443 port https login ${config.sops.placeholder.stashuser} password ${config.sops.placeholder.stashpass}
# machine gitlab.com/api/v4 login ${config.sops.placeholder.githubforgeuser} password ${config.sops.placeholder.githubforgepass}
# machine api.github.com login ${config.sops.placeholder.gitlabforgeuser} password ${config.sops.placeholder.gitlabforgepass}
# '';
# };
};
};
}

View file

@ -0,0 +1,7 @@
_:
{
nix.optimise = {
automatic = true;
dates = [ "weekly" ];
};
}

View file

@ -0,0 +1,54 @@
{ self, pkgs, home-manager, config, ... }:
{
stylix = {
enable = true;
base16Scheme = "${self}/programs/stylix/swarsel.yaml";
polarity = "dark";
opacity.popups = 0.5;
cursor = {
package = pkgs.capitaine-cursors;
name = "capitaine-cursors";
size = 16;
};
fonts = {
sizes = {
terminal = 10;
applications = 11;
};
serif = {
# package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; });
package = pkgs.cantarell-fonts;
# package = pkgs.montserrat;
name = "Cantarell";
# name = "FiraCode Nerd Font Propo";
# name = "Montserrat";
};
sansSerif = {
# package = (pkgs.nerdfonts.override { fonts = [ "FiraMono" "FiraCode"]; });
package = pkgs.cantarell-fonts;
# package = pkgs.montserrat;
name = "Cantarell";
# name = "FiraCode Nerd Font Propo";
# name = "Montserrat";
};
monospace = {
package = pkgs.nerd-fonts.fira-mono; # has overrides
name = "FiraCode Nerd Font Mono";
};
emoji = {
package = pkgs.noto-fonts-emoji;
name = "Noto Color Emoji";
};
};
targets.grub.enable = false; # the styling makes grub more ugly
image = config.swarselsystems.wallpaper;
};
home-manager.users.swarsel = {
stylix = {
targets = {
emacs.enable = false;
waybar.enable = false;
};
};
};
}

View file

@ -0,0 +1,23 @@
{ pkgs, ... }:
{
programs.sway = {
enable = true;
package = pkgs.swayfx;
wrapperFeatures = {
base = true;
gtk = true;
};
extraSessionCommands = ''
export XDG_SESSION_DESKTOP=sway
export SDL_VIDEODRIVER=wayland
export QT_QPA_PLATFORM=wayland-egl
export QT_WAYLAND_DISABLE_WINDOWDECORATION=1
export QT_QPA_PLATFORM_PLUGIN_PATH="${pkgs.libsForQt5.qt5.qtbase.bin}/lib/qt-${pkgs.libsForQt5.qt5.qtbase.version}/plugins";
export MOZ_ENABLE_WAYLAND=1
export MOZ_DISABLE_RDD_SANDBOX=1
'';
};
}

View file

@ -0,0 +1,50 @@
_:
{
services.syncthing = {
enable = true;
user = "swarsel";
dataDir = "/home/swarsel";
configDir = "/home/swarsel/.config/syncthing";
openDefaultPorts = true;
settings = {
devices = {
"magicant" = {
id = "VMWGEE2-4HDS2QO-KNQOVGN-LXLX6LA-666E4EK-ZBRYRRO-XFEX6FB-6E3XLQO";
};
"sync (@oracle)" = {
id = "ETW6TST-NPK7MKZ-M4LXMHA-QUPQHDT-VTSHH5X-CR5EIN2-YU7E55F-MGT7DQB";
};
"winters" = {
id = "O7RWDMD-AEAHPP7-7TAVLKZ-BSWNBTU-2VA44MS-EYGUNBB-SLHKB3C-ZSLMOAA";
};
};
folders = {
"Default Folder" = {
path = "/home/swarsel/Sync";
devices = [ "sync (@oracle)" "magicant" "winters" ];
id = "default";
};
"Obsidian" = {
path = "/home/swarsel/Nextcloud/Obsidian";
devices = [ "sync (@oracle)" "magicant" "winters" ];
id = "yjvni-9eaa7";
};
"Org" = {
path = "/home/swarsel/Nextcloud/Org";
devices = [ "sync (@oracle)" "magicant" "winters" ];
id = "a7xnl-zjj3d";
};
"Vpn" = {
path = "/home/swarsel/Vpn";
devices = [ "sync (@oracle)" "magicant" "winters" ];
id = "hgp9s-fyq3p";
};
".elfeed" = {
path = "/home/swarsel/.elfeed";
devices = [ "sync (@oracle)" "magicant" "winters" ];
id = "h7xbs-fs9v1";
};
};
};
};
}

View file

@ -0,0 +1,8 @@
_:
{
# systemd
systemd.extraConfig = ''
DefaultTimeoutStartSec=60s
DefaultTimeoutStopSec=15s
'';
}

View file

@ -0,0 +1,22 @@
_:
{
time = {
timeZone = "Europe/Vienna";
# hardwareClockInLocalTime = true;
};
i18n = {
defaultLocale = "en_US.UTF-8";
extraLocaleSettings = {
LC_ADDRESS = "de_AT.UTF-8";
LC_IDENTIFICATION = "de_AT.UTF-8";
LC_MEASUREMENT = "de_AT.UTF-8";
LC_MONETARY = "de_AT.UTF-8";
LC_NAME = "de_AT.UTF-8";
LC_NUMERIC = "de_AT.UTF-8";
LC_PAPER = "de_AT.UTF-8";
LC_TELEPHONE = "de_AT.UTF-8";
LC_TIME = "de_AT.UTF-8";
};
};
}

View file

@ -0,0 +1,16 @@
{ pkgs, config, lib, ... }:
{
sops.secrets.swarseluser = lib.mkIf (!config.swarselsystems.isPublic) { neededForUsers = true; };
users = {
mutableUsers = lib.mkIf (!config.swarselsystems.initialSetup) false;
users.swarsel = {
isNormalUser = true;
description = "Leon S";
password = lib.mkIf config.swarselsystems.initialSetup "setup";
hashedPasswordFile = lib.mkIf (!config.swarselsystems.initialSetup) config.sops.secrets.swarseluser.path;
extraGroups = [ "networkmanager" "syncthing" "docker" "wheel" "lp" "audio" "video" "vboxusers" "libvirtd" "scanner" ];
packages = with pkgs; [ ];
};
};
}

View file

@ -0,0 +1,19 @@
{ pkgs, ... }:
{
xdg.portal = {
enable = true;
config = {
common = {
default = "wlr";
};
};
wlr.enable = true;
wlr.settings.screencast = {
output_name = "eDP-1";
chooser_type = "simple";
chooser_cmd = "${pkgs.slurp}/bin/slurp -f %o -or";
};
};
}

View file

@ -0,0 +1,9 @@
_:
{
services.xserver = {
xkb = {
layout = "us";
variant = "altgr-intl";
};
};
}

View file

@ -0,0 +1,7 @@
{ pkgs, ... }:
{
programs.zsh.enable = true;
users.defaultUserShell = pkgs.zsh;
environment.shells = with pkgs; [ zsh ];
environment.pathsToLink = [ "/share/zsh" ];
}

View file

@ -0,0 +1,7 @@
_:
{
services = {
getty.autologinUser = "swarsel";
greetd.settings.initial_session.user = "swarsel";
};
}

View file

@ -0,0 +1,36 @@
{ pkgs, ... }:
{
specialisation = {
gaming.configuration = {
networking = {
firewall = {
allowedUDPPorts = [ 4380 27036 14242 34197 ]; # 34197: factorio; 4380 27036 14242: barotrauma;
allowedTCPPorts = [ ]; # 34197: factorio; 4380 27036 14242: barotrauma; 51820: wireguard
allowedTCPPortRanges = [
{ from = 27015; to = 27030; } # barotrauma
{ from = 27036; to = 27037; } # barotrauma
];
allowedUDPPortRanges = [
{ from = 27000; to = 27031; } # barotrauma
{ from = 58962; to = 58964; } # barotrauma
];
};
};
programs.steam = {
enable = true;
package = pkgs.stable.steam;
extraCompatPackages = [
pkgs.proton-ge-bin
];
};
hardware.xone.enable = true;
environment.systemPackages = [
pkgs.linuxKernel.packages.linux_6_12.xone
];
};
};
}

View file

@ -0,0 +1,10 @@
{ pkgs, ... }:
{
services.nswitch-rcm = {
enable = true;
package = pkgs.fetchurl {
url = "https://github.com/Atmosphere-NX/Atmosphere/releases/download/1.3.2/fusee.bin";
hash = "sha256-5AXzNsny45SPLIrvWJA9/JlOCal5l6Y++Cm+RtlJppI=";
};
};
}

View file

@ -0,0 +1,21 @@
{ lib, pkgs, ... }:
{
specialisation = {
VBox.configuration = {
virtualisation.virtualbox = {
host = {
enable = true;
enableExtensionPack = true;
};
# leaving this here for future notice. setting guest.enable = true will make 'restarting sysinit-reactivation.target' take till timeout on nixos-rebuild switch
guest = {
enable = false;
};
};
# run an older kernel to provide compatibility with windows vm
boot.kernelPackages = lib.mkForce pkgs.linuxPackages;
};
};
}

View file

@ -0,0 +1,6 @@
_:
{
virtualisation.vmware.host.enable = true;
virtualisation.vmware.guest.enable = true;
}

View file

@ -0,0 +1,129 @@
{ self, pkgs, config, ... }:
let
owner = "swarsel";
sopsFile = self + /secrets/work/secrets.yaml;
in
{
sops = {
secrets = {
clad = {
inherit owner sopsFile;
};
dcad = {
inherit owner sopsFile;
};
wsad = {
inherit owner sopsFile;
};
imbad = {
inherit owner sopsFile;
};
};
};
# boot.initrd.luks.yubikeySupport = true;
programs = {
zsh.shellInit = ''
export CLAD="$(cat ${config.sops.secrets.clad.path})"
export DCAD="$(cat ${config.sops.secrets.dcad.path})"
export GOVC_PASSWORD="$(cat ${config.sops.secrets.dcad.path})"
export WSAD="$(cat ${config.sops.secrets.wsad.path})"
export IMBAD="$(cat ${config.sops.secrets.imbad.path})"
export DCUSER="dc_adm_schwarzaeugl@IMP.UNIVIE.AC.AT"
export GOVC_USERNAME="dc_adm_schwarzaeugl@IMP.UNIVIE.AC.AT"
export PACKER_SSH_EXTRA_ARGS='"--scp-extra-args","'-O'"'
'';
browserpass.enable = true;
_1password.enable = true;
_1password-gui = {
enable = true;
polkitPolicyOwners = [ "swarsel" ];
};
};
networking.firewall.trustedInterfaces = [ "virbr0" ];
virtualisation = {
docker.enable = true;
spiceUSBRedirection.enable = true;
libvirtd = {
enable = true;
qemu = {
package = pkgs.qemu_kvm;
runAsRoot = true;
swtpm.enable = true;
vhostUserPackages = with pkgs; [ virtiofsd ];
ovmf = {
enable = true;
packages = [
(pkgs.OVMFFull.override {
secureBoot = true;
tpmSupport = true;
}).fd
];
};
};
};
};
environment.systemPackages = with pkgs; [
# (python39.withPackages (ps: with ps; [
# cryptography
# ]))
# docker
python39
qemu
packer
gnumake
libisoburn
govc
terraform
# vm
virt-manager
virt-viewer
virtiofsd
spice
spice-gtk
spice-protocol
win-virtio
win-spice
];
services = {
spice-vdagentd.enable = true;
openssh = {
enable = true;
extraConfig = ''
'';
};
syncthing = {
settings = {
"winters" = {
id = "O7RWDMD-AEAHPP7-7TAVLKZ-BSWNBTU-2VA44MS-EYGUNBB-SLHKB3C-ZSLMOAA";
};
folders = {
"Documents" = {
path = "/home/swarsel/Documents";
devices = [ "magicant" "winters" ];
id = "hgr3d-pfu3w";
};
};
};
};
};
# cgroups v1 is required for centos7 dockers
specialisation = {
cgroup_v1.configuration = {
boot.kernelParams = [
"SYSTEMD_CGROUP_ENABLE_LEGACY_FORCE=1"
"systemd.unified_cgroup_hierarchy=0"
];
};
};
}

View file

@ -0,0 +1,41 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.ankisync {
networking.firewall.allowedTCPPorts = [ 22701 ];
sops.secrets.swarsel = { owner = "root"; };
services.anki-sync-server = {
enable = true;
port = 27701;
address = "0.0.0.0";
openFirewall = true;
users = [
{
username = "Swarsel";
passwordFile = config.sops.secrets.swarsel.path;
}
];
};
services.nginx = {
virtualHosts = {
"synki.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:27701";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,41 @@
{ self, ... }:
let
profilesPath = "${self}/profiles";
in
{
imports = [
"${profilesPath}/nixos/common/settings.nix"
"${profilesPath}/nixos/common/home-manager.nix"
"${profilesPath}/nixos/common/xserver.nix"
"${profilesPath}/nixos/common/gc.nix"
"${profilesPath}/nixos/common/store.nix"
"${profilesPath}/nixos/common/time.nix"
"${profilesPath}/nixos/common/users.nix"
"${profilesPath}/nixos/common/nix-ld.nix"
./settings.nix
./packages.nix
./sops.nix
./ssh.nix
./nfs.nix
./nginx.nix
./kavita.nix
./jellyfin.nix
./navidrome.nix
./spotifyd.nix
./mpd.nix
./matrix.nix
./pipewire.nix
./nextcloud.nix
./immich.nix
./paperless.nix
./transmission.nix
./syncthing.nix
./restic.nix
./monitoring.nix
./jenkins.nix
./emacs.nix
./forgejo.nix
./ankisync.nix
./freshrss.nix
];
}

View file

@ -0,0 +1,15 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.emacs {
networking.firewall.allowedTCPPorts = [ 9812 ];
services.emacs = {
enable = true;
install = true;
startWithGraphical = false;
};
};
}

View file

@ -0,0 +1,46 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.forgejo {
networking.firewall.allowedTCPPorts = [ 3000 ];
services.forgejo = {
enable = true;
settings = {
DEFAULT = {
APP_NAME = "~SwaGit~";
};
server = {
PROTOCOL = "http";
HTTP_PORT = 3000;
HTTP_ADDR = "0.0.0.0";
DOMAIN = "swagit.swarsel.win";
ROOT_URL = "https://swagit.swarsel.win";
};
service = {
DISABLE_REGISTRATION = true;
SHOW_REGISTRATION_BUTTON = false;
};
};
};
services.nginx = {
virtualHosts = {
"swagit.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:3000";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,36 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.freshrss {
users.users.freshrss = {
extraGroups = [ "users" ];
group = "freshrss";
isSystemUser = true;
};
users.groups.freshrss = { };
sops.secrets.fresh = { owner = "freshrss"; };
services.freshrss = {
enable = true;
virtualHost = "signpost.swarsel.win";
baseUrl = "https://signpost.swarsel.win";
# authType = "none";
dataDir = "/Vault/data/tt-rss";
defaultUser = "Swarsel";
passwordFile = config.sops.secrets.fresh.path;
};
services.nginx = {
virtualHosts = {
"signpost.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
};
};
};
};
}

View file

@ -0,0 +1,49 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.immich {
users.users.immich = {
extraGroups = [ "video" "render" "users" ];
};
# sops.secrets.nextcloudadminpass = { owner = "nextcloud"; };
services.immich = {
enable = true;
port = 3001;
openFirewall = true;
mediaLocation = "/Vault/Eternor/Immich";
environment.IMMICH_MACHINE_LEARNING_URL = lib.mkForce "http://localhost:3003";
};
services.nginx = {
virtualHosts = {
"shots.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:3001";
extraConfig = ''
client_max_body_size 0;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_redirect off;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
send_timeout 600s;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,44 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.jellyfin {
users.users.jellyfin = {
extraGroups = [ "video" "render" "users" ];
};
nixpkgs.config.packageOverrides = pkgs: {
vaapiIntel = pkgs.vaapiIntel.override { enableHybridCodec = true; };
};
hardware.graphics = {
enable = true;
extraPackages = with pkgs; [
intel-media-driver # LIBVA_DRIVER_NAME=iHD
vaapiIntel # LIBVA_DRIVER_NAME=i965 (older but works better for Firefox/Chromium)
vaapiVdpau
libvdpau-va-gl
];
};
services.jellyfin = {
enable = true;
user = "jellyfin";
openFirewall = true; # this works only for the default ports
};
services.nginx = {
virtualHosts = {
"screen.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:8096";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,35 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.jenkins {
services.jenkins = {
enable = true;
withCLI = true;
port = 8088;
packages = [ pkgs.stdenv pkgs.git pkgs.jdk17 config.programs.ssh.package pkgs.nix ];
listenAddress = "127.0.0.1";
home = "/Vault/apps/jenkins";
};
services.nginx = {
virtualHosts = {
"servant.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:8088";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,42 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.kavita {
environment.systemPackages = with pkgs; [
calibre
];
users.users.jellyfin = {
extraGroups = [ "users" ];
};
sops.secrets.kavita = { owner = "kavita"; };
networking.firewall.allowedTCPPorts = [ 8080 ];
services.kavita = {
enable = true;
user = "kavita";
settings.Port = 8080;
tokenKeyFile = config.sops.secrets.kavita.path;
};
services.nginx = {
virtualHosts = {
"scroll.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:8080";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,317 @@
{ config, lib, pkgs, sops, ... }:
let
matrixDomain = "swatrix.swarsel.win";
baseUrl = "https://${matrixDomain}";
clientConfig."m.homeserver".base_url = baseUrl;
serverConfig."m.server" = "${matrixDomain}:443";
mkWellKnown = data: ''
default_type application/json;
add_header Access-Control-Allow-Origin *;
return 200 '${builtins.toJSON data}';
'';
in
{
config = lib.mkIf config.swarselsystems.server.matrix {
environment.systemPackages = with pkgs; [
matrix-synapse
lottieconverter
ffmpeg
];
sops = {
secrets = {
matrixsharedsecret = { owner = "matrix-synapse"; };
mautrixtelegram_as = { owner = "matrix-synapse"; };
mautrixtelegram_hs = { owner = "matrix-synapse"; };
mautrixtelegram_api_id = { owner = "matrix-synapse"; };
mautrixtelegram_api_hash = { owner = "matrix-synapse"; };
};
templates = {
"matrix_user_register.sh".content = ''
register_new_matrix_user -k ${config.sops.placeholder.matrixsharedsecret} http://localhost:8008
'';
matrixshared = {
owner = "matrix-synapse";
content = ''
registration_shared_secret: ${config.sops.placeholder.matrixsharedsecret}
'';
};
mautrixtelegram = {
owner = "matrix-synapse";
content = ''
MAUTRIX_TELEGRAM_APPSERVICE_AS_TOKEN=${config.sops.placeholder.mautrixtelegram_as}
MAUTRIX_TELEGRAM_APPSERVICE_HS_TOKEN=${config.sops.placeholder.mautrixtelegram_hs}
MAUTRIX_TELEGRAM_TELEGRAM_API_ID=${config.sops.placeholder.mautrixtelegram_api_id}
MAUTRIX_TELEGRAM_TELEGRAM_API_HASH=${config.sops.placeholder.mautrixtelegram_api_hash}
'';
};
};
};
services.postgresql = {
enable = true;
initialScript = pkgs.writeText "synapse-init.sql" ''
CREATE ROLE "matrix-synapse" WITH LOGIN PASSWORD 'synapse';
CREATE DATABASE "matrix-synapse" WITH OWNER "matrix-synapse"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-telegram" WITH LOGIN PASSWORD 'telegram';
CREATE DATABASE "mautrix-telegram" WITH OWNER "mautrix-telegram"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-whatsapp" WITH LOGIN PASSWORD 'whatsapp';
CREATE DATABASE "mautrix-whatsapp" WITH OWNER "mautrix-whatsapp"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
CREATE ROLE "mautrix-signal" WITH LOGIN PASSWORD 'signal';
CREATE DATABASE "mautrix-signal" WITH OWNER "mautrix-signal"
TEMPLATE template0
LC_COLLATE = "C"
LC_CTYPE = "C";
'';
};
services.matrix-synapse = {
enable = true;
settings = {
app_service_config_files = [
"/var/lib/matrix-synapse/telegram-registration.yaml"
"/var/lib/matrix-synapse/whatsapp-registration.yaml"
"/var/lib/matrix-synapse/signal-registration.yaml"
"/var/lib/matrix-synapse/doublepuppet.yaml"
];
server_name = matrixDomain;
public_baseurl = "https://${matrixDomain}";
listeners = [
{
port = 8008;
bind_addresses = [
"127.0.0.1"
# "::1"
];
type = "http";
tls = false;
x_forwarded = true;
resources = [
{
names = [ "client" "federation" ];
compress = true;
}
];
}
];
};
extraConfigFiles = [
config.sops.templates.matrixshared.path
];
};
services.mautrix-telegram = {
enable = true;
environmentFile = config.sops.templates.mautrixtelegram.path;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address = "http://localhost:29317";
hostname = "localhost";
port = "29317";
provisioning.enabled = true;
id = "telegram";
# ephemeral_events = true; # not needed due to double puppeting
public = {
enabled = false;
};
database = "postgresql:///mautrix-telegram?host=/run/postgresql";
};
bridge = {
relaybot.authless_portals = true;
allow_avatar_remove = true;
allow_contact_info = true;
sync_channel_members = true;
startup_sync = true;
sync_create_limit = 0;
sync_direct_chats = true;
telegram_link_preview = true;
permissions = {
"*" = "relaybot";
"@swarsel:${matrixDomain}" = "admin";
};
animated_sticker = {
target = "gif";
args = {
width = 256;
height = 256;
fps = 30; # only for webm
background = "020202"; # only for gif, transparency not supported
};
};
};
};
};
systemd.services.mautrix-telegram.path = with pkgs; [
lottieconverter # for animated stickers conversion, unfree package
ffmpeg # if converting animated stickers to webm (very slow!)
];
services.mautrix-whatsapp = {
enable = true;
registerToSynapse = false;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address = "http://localhost:29318";
hostname = "127.0.0.1";
port = 29318;
database = {
type = "postgres";
uri = "postgresql:///mautrix-whatsapp?host=/run/postgresql";
};
};
bridge = {
displayname_template = "{{or .FullName .PushName .JID}} (WA)";
history_sync = {
backfill = true;
max_initial_conversations = -1;
message_count = -1;
request_full_sync = true;
full_sync_config = {
days_limit = 900;
size_mb_limit = 5000;
storage_quota_mb = 5000;
};
};
login_shared_secret_map = {
matrixDomain = "as_token:doublepuppet";
};
sync_manual_marked_unread = true;
send_presence_on_typing = true;
parallel_member_sync = true;
url_previews = true;
caption_in_message = true;
extev_polls = true;
permissions = {
"*" = "relay";
"@swarsel:${matrixDomain}" = "admin";
};
};
};
};
services.mautrix-signal = {
enable = true;
registerToSynapse = false;
settings = {
homeserver = {
address = "http://localhost:8008";
domain = matrixDomain;
};
appservice = {
address = "http://localhost:29328";
hostname = "127.0.0.1";
port = 29328;
database = {
type = "postgres";
uri = "postgresql:///mautrix-signal?host=/run/postgresql";
};
};
bridge = {
displayname_template = "{{or .ContactName .ProfileName .PhoneNumber}} (Signal)";
login_shared_secret_map = {
matrixDomain = "as_token:doublepuppet";
};
caption_in_message = true;
permissions = {
"*" = "relay";
"@swarsel:${matrixDomain}" = "admin";
};
};
};
};
# restart the bridges daily. this is done for the signal bridge mainly which stops carrying
# messages out after a while.
systemd.timers."restart-bridges" = {
wantedBy = [ "timers.target" ];
timerConfig = {
OnBootSec = "1d";
OnUnitActiveSec = "1d";
Unit = "restart-bridges.service";
};
};
systemd.services."restart-bridges" = {
script = ''
systemctl restart mautrix-whatsapp.service
systemctl restart mautrix-signal.service
systemctl restart mautrix-telegram.service
'';
serviceConfig = {
Type = "oneshot";
User = "root";
};
};
services.nginx = {
virtualHosts = {
"swatrix.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
listen = [
{
addr = "0.0.0.0";
port = 8448;
ssl = true;
extraParameters = [
"default_server"
];
}
{
addr = "[::0]";
port = 8448;
ssl = true;
extraParameters = [
"default_server"
];
}
{
addr = "0.0.0.0";
port = 443;
ssl = true;
}
{
addr = "[::0]";
port = 443;
ssl = true;
}
];
locations = {
"~ ^(/_matrix|/_synapse/client)" = {
# proxyPass = "http://localhost:8008";
proxyPass = "http://localhost:8008";
extraConfig = ''
client_max_body_size 0;
'';
};
"= /.well-known/matrix/server".extraConfig = mkWellKnown serverConfig;
"= /.well-known/matrix/client".extraConfig = mkWellKnown clientConfig;
};
};
};
};
};
}

View file

@ -0,0 +1,160 @@
{ self, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.monitoring {
sops.secrets = {
grafanaadminpass = {
owner = "grafana";
};
prometheusadminpass = {
owner = "grafana";
};
};
users.users.nextcloud-exporter = {
extraGroups = [ "nextcloud" ];
};
users.users.grafana = {
extraGroups = [ "users" ];
};
services.grafana = {
enable = true;
dataDir = "/Vault/data/grafana";
provision = {
enable = true;
datasources.settings = {
datasources = [
{
name = "prometheus";
type = "prometheus";
url = "https://status.swarsel.win/prometheus";
editable = false;
access = "proxy";
basicAuth = true;
basicAuthUser = "admin";
jsonData = {
httpMethod = "POST";
manageAlerts = true;
prometheusType = "Prometheus";
prometheusVersion = "> 2.50.x";
cacheLevel = "High";
disableRecordingRules = false;
incrementalQueryOverlapWindow = "10m";
};
secureJsonData = {
basicAuthPassword = "$__file{/run/secrets/prometheusadminpass}";
};
}
];
};
};
settings = {
security.admin_password = "$__file{/run/secrets/grafanaadminpass}";
server = {
http_port = 3000;
http_addr = "127.0.0.1";
protocol = "http";
domain = "status.swarsel.win";
};
};
};
services.prometheus = {
enable = true;
webExternalUrl = "https://status.swarsel.win/prometheus";
port = 9090;
listenAddress = "127.0.0.1";
globalConfig = {
scrape_interval = "10s";
};
webConfigFile = self + /programs/server/prometheus/web.config;
scrapeConfigs = [
{
job_name = "node";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.node.port}" ];
}];
}
{
job_name = "zfs";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.zfs.port}" ];
}];
}
{
job_name = "nginx";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.nginx.port}" ];
}];
}
{
job_name = "nextcloud";
static_configs = [{
targets = [ "localhost:${toString config.services.prometheus.exporters.nextcloud.port}" ];
}];
}
];
exporters = {
node = {
enable = true;
port = 9000;
enabledCollectors = [ "systemd" ];
extraFlags = [ "--collector.ethtool" "--collector.softirqs" "--collector.tcpstat" "--collector.wifi" ];
};
zfs = {
enable = true;
port = 9134;
pools = [
"Vault"
];
};
restic = {
enable = false;
port = 9753;
};
nginx = {
enable = true;
port = 9113;
sslVerify = false;
scrapeUri = "http://localhost/nginx_status";
};
nextcloud = lib.mkIf config.swarselsystems.server.nextcloud {
enable = true;
port = 9205;
url = "https://stash.swarsel.win/ocs/v2.php/apps/serverinfo/api/v1/info";
username = "admin";
passwordFile = config.sops.secrets.nextcloudadminpass.path;
};
};
};
services.nginx = {
virtualHosts = {
"status.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:3000";
extraConfig = ''
client_max_body_size 0;
'';
};
"/prometheus" = {
proxyPass = "http://localhost:9090";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,51 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.mpd {
users = {
groups = {
mpd = { };
};
users = {
mpd = {
isSystemUser = true;
group = "mpd";
extraGroups = [ "audio" "utmp" ];
};
};
};
sops = {
secrets.mpdpass = { owner = "mpd"; };
};
environment.systemPackages = with pkgs; [
pciutils
alsa-utils
mpv
];
services.mpd = {
enable = true;
musicDirectory = "/media";
user = "mpd";
group = "mpd";
network = {
port = 3254;
listenAddress = "any";
};
credentials = [
{
passwordFile = config.sops.secrets.mpdpass.path;
permissions = [
"read"
"add"
"control"
"admin"
];
}
];
};
};
}

View file

@ -0,0 +1,96 @@
{ pkgs, lib, inputs, config, ... }:
let
secretsDirectory = builtins.toString inputs.nix-secrets;
in
{
config = lib.mkIf config.swarselsystems.server.navidrome {
environment.systemPackages = with pkgs; [
pciutils
alsa-utils
mpv
];
users = {
groups = {
navidrome = {
gid = 61593;
};
};
users = {
navidrome = {
isSystemUser = true;
uid = 61593;
group = "navidrome";
extraGroups = [ "audio" "utmp" "users" "pipewire" ];
};
};
};
hardware = {
# opengl.enable = true;
enableAllFirmware = true;
};
networking.firewall.allowedTCPPorts = [ 4040 ];
services.navidrome = {
enable = true;
openFirewall = true;
settings = {
LogLevel = "error";
Address = "127.0.0.1";
Port = 4040;
MusicFolder = "/Vault/Eternor/Musik";
EnableSharing = true;
EnableTranscodingConfig = true;
Scanner.GroupAlbumReleases = true;
ScanSchedule = "@every 24h";
MPVPath = "${pkgs.mpv}/bin/mpv";
MPVCommandTemplate = "mpv --audio-device=%d --no-audio-display --pause %f";
Jukebox = {
Enabled = true;
Default = "pch";
Devices = [
[ "pch" "alsa/sysdefault:CARD=PCH" ]
];
};
# Switch using --impure as these credential files are not stored within the flake
# sops-nix is not supported for these which is why we need to resort to these
LastFM.ApiKey = builtins.readFile "${secretsDirectory}/navidrome/lastfm-secret";
LastFM.Secret = builtins.readFile "${secretsDirectory}/navidrome/lastfm-key";
Spotify.ID = builtins.readFile "${secretsDirectory}/navidrome/spotify-id";
Spotify.Secret = builtins.readFile "${secretsDirectory}/navidrome/spotify-secret";
UILoginBackgroundUrl = "https://i.imgur.com/OMLxi7l.png";
UIWelcomeMessage = "~SwarselSound~";
};
};
services.nginx = {
virtualHosts = {
"sound.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:4040";
proxyWebsockets = true;
extraConfig = ''
proxy_redirect http:// https://;
proxy_read_timeout 600s;
proxy_send_timeout 600s;
proxy_buffering off;
proxy_request_buffering off;
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,43 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.nextcloud {
sops.secrets.nextcloudadminpass = {
owner = "nextcloud";
group = "nextcloud";
mode = "0440";
};
services.nextcloud = {
enable = true;
package = pkgs.nextcloud30;
hostName = "stash.swarsel.win";
home = "/Vault/apps/nextcloud";
datadir = "/Vault/data/nextcloud";
https = true;
configureRedis = true;
maxUploadSize = "4G";
extraApps = {
inherit (pkgs.nextcloud30Packages.apps) mail calendar contacts cospend phonetrack polls tasks;
};
config = {
adminuser = "admin";
adminpassFile = config.sops.secrets.nextcloudadminpass.path;
};
};
services.nginx = {
virtualHosts = {
"stash.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
# config is automatically added by nixos nextcloud config.
# hence, only provide certificate
};
};
};
};
}

View file

@ -0,0 +1,49 @@
{ pkgs, ... }:
{
services = {
# add a user with sudo smbpasswd -a <user>
samba = {
package = pkgs.samba4Full;
# extraConfig = ''
# workgroup = WORKGROUP
# server role = standalone server
# dns proxy = no
# pam password change = yes
# map to guest = bad user
# create mask = 0664
# force create mode = 0664
# directory mask = 0775
# force directory mode = 0775
# follow symlinks = yes
# '';
enable = true;
openFirewall = true;
settings.Eternor = {
browseable = "yes";
"read only" = "no";
"guest ok" = "no";
path = "/Vault/Eternor";
writable = "true";
comment = "Eternor";
"valid users" = "Swarsel";
};
};
avahi = {
publish.enable = true;
publish.userServices = true; # Needed to allow samba to automatically register mDNS records without the need for an `extraServiceFile`
nssmdns4 = true;
enable = true;
openFirewall = true;
};
# This enables autodiscovery on windows since SMB1 (and thus netbios) support was discontinued
samba-wsdd = {
enable = true;
openFirewall = true;
};
};
}

View file

@ -0,0 +1,35 @@
{ pkgs, config, ... }:
{
environment.systemPackages = with pkgs; [
lego
];
# users.users.acme = {};
sops = {
# secrets.dnstokenfull = { owner = "acme"; };
secrets.dnstokenfull = { };
templates."certs.secret".content = ''
CF_DNS_API_TOKEN=${config.sops.placeholder.dnstokenfull}
'';
};
security.acme = {
acceptTerms = true;
preliminarySelfsigned = false;
defaults.email = "mrswarsel@gmail.com";
defaults.dnsProvider = "cloudflare";
defaults.environmentFile = "${config.sops.templates."certs.secret".path}";
};
services.nginx = {
enable = true;
statusPage = true;
recommendedProxySettings = true;
recommendedTlsSettings = true;
recommendedOptimisation = true;
recommendedGzipSettings = true;
# virtualHosts are defined in the respective sections
};
}

View file

@ -0,0 +1,11 @@
{ pkgs, ... }:
{
environment.systemPackages = with pkgs; [
gnupg
nix-index
ssh-to-age
git
emacs
vim
];
}

View file

@ -0,0 +1,50 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.paperless {
users.users.paperless = {
extraGroups = [ "users" ];
};
sops.secrets.paperless_admin = { owner = "paperless"; };
services.paperless = {
enable = true;
mediaDir = "/Vault/Eternor/Paperless";
dataDir = "/Vault/data/paperless";
user = "paperless";
port = 28981;
passwordFile = config.sops.secrets.paperless_admin.path;
address = "127.0.0.1";
settings = {
PAPERLESS_OCR_LANGUAGE = "deu+eng";
PAPERLESS_URL = "https://scan.swarsel.win";
PAPERLESS_OCR_USER_ARGS = builtins.toJSON {
optimize = 1;
invalidate_digital_signatures = true;
pdfa_image_compression = "lossless";
};
};
};
services.nginx = {
virtualHosts = {
"scan.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:28981";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,20 @@
{ lib, config, ... }:
{
config = lib.mkIf (config.swarselsystems.server.mpd || config.swarselsystems.server.navidrome) {
security.rtkit.enable = true; # this is required for pipewire real-time access
services.pipewire = {
enable = true;
pulse.enable = true;
jack.enable = true;
audio.enable = true;
wireplumber.enable = true;
alsa = {
enable = true;
support32Bit = true;
};
};
};
}

View file

@ -0,0 +1,8 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.restic {
# TODO
};
}

View file

@ -0,0 +1,23 @@
{ lib, config, ... }:
{
environment.shellAliases = lib.recursiveUpdate
{
npswitch = "cd ${config.swarselsystems.flakePath}; git pull; sudo nixos-rebuild --flake .#$(hostname) switch; cd -;";
nswitch = "sudo nixos-rebuild --flake ${config.swarselsystems.flakePath}#$(hostname) switch;";
npiswitch = "cd ${config.swarselsystems.flakePath}; git pull; sudo nixos-rebuild --flake .#$(hostname) switch --impure; cd -;";
nipswitch = "cd ${config.swarselsystems.flakePath}; git pull; sudo nixos-rebuild --flake .#$(hostname) switch --impure; cd -;";
niswitch = "sudo nixos-rebuild --flake ${config.swarselsystems.flakePath}#$(hostname) switch --impure;";
}
config.swarselsystems.shellAliases;
nixpkgs.config.permittedInsecurePackages = [
# matrix
"olm-3.2.16"
# sonarr
"aspnetcore-runtime-wrapped-6.0.36"
"aspnetcore-runtime-6.0.36"
"dotnet-sdk-wrapped-6.0.428"
"dotnet-sdk-6.0.428"
];
}

View file

@ -0,0 +1,9 @@
{ config, lib, ... }:
{
sops = {
age.sshKeyPaths = lib.mkDefault [ "/etc/ssh/sops" ];
defaultSopsFile = lib.mkDefault "${config.swarselsystems.flakePath}/secrets/winters/secrets.yaml";
validateSopsFiles = false;
};
}

View file

@ -0,0 +1,34 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.spotifyd {
users.groups.spotifyd = {
gid = 65136;
};
users.users.spotifyd = {
isSystemUser = true;
uid = 65136;
group = "spotifyd";
extraGroups = [ "audio" "utmp" "pipewire" ];
};
networking.firewall.allowedTCPPorts = [ 1025 ];
services.pipewire.systemWide = true;
services.spotifyd = {
enable = true;
settings = {
global = {
dbus_type = "session";
use_mpris = false;
device = "sysdefault:CARD=PCH";
device_name = "SwarselSpot";
mixer = "alsa";
zeroconf_port = 1025;
};
};
};
};
}

View file

@ -0,0 +1,18 @@
{ self, ... }:
{
services.openssh = {
enable = true;
};
users.users.swarsel.openssh.authorizedKeys.keyFiles = [
(self + /secrets/keys/ssh/nbl-imba-2.pub)
(self + /secrets/keys/ssh/magicant.pub)
];
users.users.root.openssh.authorizedKeys.keyFiles = [
(self + /secrets/keys/ssh/nbl-imba-2.pub)
(self + /secrets/keys/ssh/magicant.pub)
];
security.sudo.extraConfig = ''
Defaults env_keep+=SSH_AUTH_SOCK
'';
}

View file

@ -0,0 +1,110 @@
{ lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.syncthing {
users.users.syncthing = {
extraGroups = [ "users" ];
group = "syncthing";
isSystemUser = true;
};
users.groups.syncthing = { };
services.syncthing = {
enable = true;
user = "swarsel";
dataDir = "/Vault/data/syncthing";
configDir = "/Vault/apps/syncthing";
guiAddress = "0.0.0.0:8384";
openDefaultPorts = true;
relay.enable = false;
settings = {
urAccepted = -1;
devices = {
"magicant" = {
id = "VMWGEE2-4HDS2QO-KNQOVGN-LXLX6LA-666E4EK-ZBRYRRO-XFEX6FB-6E3XLQO";
};
"sync (@oracle)" = {
id = "ETW6TST-NPK7MKZ-M4LXMHA-QUPQHDT-VTSHH5X-CR5EIN2-YU7E55F-MGT7DQB";
};
"nbl-imba-2" = {
id = "YAPV4BV-I26WPTN-SIP32MV-SQP5TBZ-3CHMTCI-Z3D6EP2-MNDQGLP-53FT3AB";
};
};
folders = {
"Default Folder" = {
path = "/Vault/data/syncthing/Sync";
type = "receiveonly";
versioning = null;
devices = [ "sync (@oracle)" "magicant" "nbl-imba-2" ];
id = "default";
};
"Obsidian" = {
path = "/Vault/data/syncthing/Obsidian";
type = "receiveonly";
versioning = {
type = "simple";
params.keep = "5";
};
devices = [ "sync (@oracle)" "magicant" "nbl-imba-2" ];
id = "yjvni-9eaa7";
};
"Org" = {
path = "/Vault/data/syncthing/Org";
type = "receiveonly";
versioning = {
type = "simple";
params.keep = "5";
};
devices = [ "sync (@oracle)" "magicant" "nbl-imba-2" ];
id = "a7xnl-zjj3d";
};
"Vpn" = {
path = "/Vault/data/syncthing/Vpn";
type = "receiveonly";
versioning = {
type = "simple";
params.keep = "5";
};
devices = [ "sync (@oracle)" "magicant" "nbl-imba-2" ];
id = "hgp9s-fyq3p";
};
"Documents" = {
path = "/Vault/data/syncthing/Documents";
type = "receiveonly";
versioning = {
type = "simple";
params.keep = "5";
};
devices = [ "magicant" "nbl-imba-2" ];
id = "hgr3d-pfu3w";
};
# ".elfeed" = {
# path = "/Vault/data/syncthing/.elfeed";
# devices = [ "sync (@oracle)" "magicant" "nbl-imba-2" ];
# id = "h7xbs-fs9v1";
# };
};
};
};
services.nginx = {
virtualHosts = {
"storync.swarsel.win" = {
enableACME = true;
forceSSL = true;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:8384";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
}

View file

@ -0,0 +1,132 @@
{ pkgs, lib, config, ... }:
{
config = lib.mkIf config.swarselsystems.server.transmission {
# this user/group section is probably unneeded
users = {
groups = {
dockeruser = {
gid = 1155;
};
radarr = { };
readarr = { };
sonarr = { };
lidarr = { };
prowlarr = { };
};
users = {
dockeruser = {
isSystemUser = true;
uid = 1155;
group = "docker";
extraGroups = [ "users" ];
};
radarr = {
isSystemUser = true;
group = "radarr";
extraGroups = [ "users" ];
};
readarr = {
isSystemUser = true;
group = "readarr";
extraGroups = [ "users" ];
};
sonarr = {
isSystemUser = true;
group = "sonarr";
extraGroups = [ "users" ];
};
lidarr = {
isSystemUser = true;
group = "lidarr";
extraGroups = [ "users" ];
};
prowlarr = {
isSystemUser = true;
group = "prowlarr";
extraGroups = [ "users" ];
};
};
};
virtualisation.docker.enable = true;
environment.systemPackages = with pkgs; [
docker
];
services = {
radarr = {
enable = true;
openFirewall = true;
dataDir = "/Vault/apps/radarr";
};
readarr = {
enable = true;
openFirewall = true;
dataDir = "/Vault/apps/readarr";
};
sonarr = {
enable = true;
openFirewall = true;
dataDir = "/Vault/apps/sonarr";
};
lidarr = {
enable = true;
openFirewall = true;
dataDir = "/Vault/apps/lidarr";
};
prowlarr = {
enable = true;
openFirewall = true;
};
nginx = {
virtualHosts = {
"store.swarsel.win" = {
enableACME = false;
forceSSL = false;
acmeRoot = null;
locations = {
"/" = {
proxyPass = "http://localhost:9091";
extraConfig = ''
client_max_body_size 0;
'';
};
"/radarr" = {
proxyPass = "http://localhost:7878";
extraConfig = ''
client_max_body_size 0;
'';
};
"/readarr" = {
proxyPass = "http://localhost:8787";
extraConfig = ''
client_max_body_size 0;
'';
};
"/sonarr" = {
proxyPass = "http://localhost:8989";
extraConfig = ''
client_max_body_size 0;
'';
};
"/lidarr" = {
proxyPass = "http://localhost:8686";
extraConfig = ''
client_max_body_size 0;
'';
};
"/prowlarr" = {
proxyPass = "http://localhost:9696";
extraConfig = ''
client_max_body_size 0;
'';
};
};
};
};
};
};
};
}