global reformat with treefmt

This commit is contained in:
nyanloutre 2025-04-23 11:15:31 +02:00
parent 97f849e454
commit 393e92fe14
17 changed files with 979 additions and 726 deletions

143
flake.nix
View file

@ -21,81 +21,88 @@
}; };
}; };
outputs = { outputs =
self, {
nixpkgs, self,
nixpkgs-unstable, nixpkgs,
nixpkgs-4a3fc4cf7, nixpkgs-unstable,
simple-nixos-mailserver, nixpkgs-4a3fc4cf7,
dogetipbot-telegram, simple-nixos-mailserver,
ipmihddtemp dogetipbot-telegram,
}@inputs: { ipmihddtemp,
}@inputs:
{
packages.x86_64-linux = (import ./pkgs nixpkgs.legacyPackages.x86_64-linux); packages.x86_64-linux = (import ./pkgs nixpkgs.legacyPackages.x86_64-linux);
nixosConfigurations.paul-fixe = nixpkgs-unstable.lib.nixosSystem { nixosConfigurations.paul-fixe = nixpkgs-unstable.lib.nixosSystem {
system = "x86_64-linux"; system = "x86_64-linux";
modules = [ modules = [
nixpkgs-unstable.nixosModules.notDetected nixpkgs-unstable.nixosModules.notDetected
{ {
nixpkgs.config.allowUnfree = true; nixpkgs.config.allowUnfree = true;
nix = { nix = {
settings.experimental-features = [ "nix-command" "flakes" ]; settings.experimental-features = [
registry = { "nix-command"
nixpkgs.to = { "flakes"
type = "path"; ];
path = nixpkgs-unstable.legacyPackages.x86_64-linux.path; registry = {
nixpkgs.to = {
type = "path";
path = nixpkgs-unstable.legacyPackages.x86_64-linux.path;
};
}; };
}; };
}; }
} ./systems/PC-Fixe/configuration.nix
./systems/PC-Fixe/configuration.nix ];
];
};
nixosConfigurations.loutreos = nixpkgs.lib.nixosSystem rec {
system = "x86_64-linux";
specialArgs = {
inputs = inputs;
pkgs-4a3fc4cf7 = import nixpkgs-4a3fc4cf7 {
inherit system;
};
}; };
modules = [
nixpkgs-unstable.nixosModules.notDetected nixosConfigurations.loutreos = nixpkgs.lib.nixosSystem rec {
simple-nixos-mailserver.nixosModule system = "x86_64-linux";
dogetipbot-telegram.nixosModule specialArgs = {
ipmihddtemp.nixosModule inputs = inputs;
{ pkgs-4a3fc4cf7 = import nixpkgs-4a3fc4cf7 {
nix = { inherit system;
settings.experimental-features = [ "nix-command" "flakes" ]; };
registry = { };
nixpkgs.to = { modules = [
type = "path"; nixpkgs-unstable.nixosModules.notDetected
path = nixpkgs.legacyPackages.x86_64-linux.path; simple-nixos-mailserver.nixosModule
dogetipbot-telegram.nixosModule
ipmihddtemp.nixosModule
{
nix = {
settings.experimental-features = [
"nix-command"
"flakes"
];
registry = {
nixpkgs.to = {
type = "path";
path = nixpkgs.legacyPackages.x86_64-linux.path;
};
}; };
}; };
}; systemd.services.watcharr = {
systemd.services.watcharr = { description = "Watcharr";
description = "Watcharr"; after = [ "network.target" ];
after = [ "network.target" ]; environment = {
environment = { PORT = "3005";
PORT = "3005"; WATCHARR_DATA = "/var/lib/watcharr";
WATCHARR_DATA = "/var/lib/watcharr"; };
serviceConfig = {
DynamicUser = true;
StateDirectory = "watcharr";
ExecStart = "${self.packages.x86_64-linux.watcharr}/bin/Watcharr";
PrivateTmp = true;
};
wantedBy = [ "multi-user.target" ];
}; };
serviceConfig = { }
DynamicUser = true; ./systems/LoutreOS/configuration.nix
StateDirectory = "watcharr"; ];
ExecStart = "${self.packages.x86_64-linux.watcharr}/bin/Watcharr"; };
PrivateTmp = true;
};
wantedBy = [ "multi-user.target" ];
};
}
./systems/LoutreOS/configuration.nix
];
}; };
};
} }

View file

@ -1,13 +1,14 @@
{ lib {
, pkgs lib,
, buildGoModule pkgs,
, fetchFromGitHub buildGoModule,
, buildNpmPackage fetchFromGitHub,
, nixosTests buildNpmPackage,
, caddy nixosTests,
, testers caddy,
, installShellFiles testers,
, stdenv installShellFiles,
stdenv,
}: }:
let let

View file

@ -5,12 +5,11 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
imports = imports = [
[ ../common-cli.nix
../common-cli.nix ../common-gui.nix
../common-gui.nix ./hardware-configuration.nix
./hardware-configuration.nix ];
];
boot.loader.systemd-boot.enable = true; boot.loader.systemd-boot.enable = true;
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
@ -56,7 +55,12 @@
users.extraUsers.paul = { users.extraUsers.paul = {
isNormalUser = true; isNormalUser = true;
uid = 1000; uid = 1000;
extraGroups = [ "wheel" "networkmanager" "wireshark" "dialout" ]; extraGroups = [
"wheel"
"networkmanager"
"wireshark"
"dialout"
];
}; };
services.syncthing.enable = true; services.syncthing.enable = true;

View file

@ -1,14 +1,25 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
imports = imports = [
[ <nixpkgs/nixos/modules/installer/scan/not-detected.nix> <nixpkgs/nixos/modules/installer/scan/not-detected.nix>
]; ];
boot.initrd.availableKernelModules = [ "xhci_pci" "ehci_pci" "ahci" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [
"xhci_pci"
"ehci_pci"
"ahci"
"usb_storage"
"sd_mod"
];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
@ -19,19 +30,19 @@
hardware.nvidia.optimus_prime.nvidiaBusId = "PCI:1:0:0"; hardware.nvidia.optimus_prime.nvidiaBusId = "PCI:1:0:0";
hardware.nvidia.optimus_prime.intelBusId = "PCI:0:2:0"; hardware.nvidia.optimus_prime.intelBusId = "PCI:0:2:0";
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/7bd3a09b-b188-4ce7-bdcc-d5c5087edc86"; device = "/dev/disk/by-uuid/7bd3a09b-b188-4ce7-bdcc-d5c5087edc86";
fsType = "ext4"; fsType = "ext4";
}; };
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/A25A-1786"; device = "/dev/disk/by-uuid/A25A-1786";
fsType = "vfat"; fsType = "vfat";
}; };
swapDevices = swapDevices = [
[ { device = "/dev/disk/by-uuid/156cd5e8-715c-48a5-9df4-14565227a6c9"; } { device = "/dev/disk/by-uuid/156cd5e8-715c-48a5-9df4-14565227a6c9"; }
]; ];
nix.maxJobs = lib.mkDefault 8; nix.maxJobs = lib.mkDefault 8;
powerManagement.cpuFreqGovernor = lib.mkDefault "performance"; powerManagement.cpuFreqGovernor = lib.mkDefault "performance";

View file

@ -1,4 +1,9 @@
{ config, pkgs, inputs, ... }: {
config,
pkgs,
inputs,
...
}:
{ {
imports = [ imports = [
@ -9,7 +14,10 @@
./services.nix ./services.nix
]; ];
nix.settings.trusted-users = [ "root" "paul" ]; nix.settings.trusted-users = [
"root"
"paul"
];
boot = { boot = {
loader = { loader = {

View file

@ -1,190 +1,202 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
boot.initrd.availableKernelModules = [ "ahci" "xhci_pci" "nvme" "usbhid" "usb_storage" "sd_mod" "sr_mod" ]; boot.initrd.availableKernelModules = [
"ahci"
"xhci_pci"
"nvme"
"usbhid"
"usb_storage"
"sd_mod"
"sr_mod"
];
boot.kernelModules = [ "kvm-intel" ]; boot.kernelModules = [ "kvm-intel" ];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
fileSystems."/" = fileSystems."/" = {
{ device = "/dev/disk/by-uuid/fec13566-5528-4859-b185-ce37ac2665eb"; device = "/dev/disk/by-uuid/fec13566-5528-4859-b185-ce37ac2665eb";
fsType = "ext4"; fsType = "ext4";
}; };
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/5306-AD9A"; device = "/dev/disk/by-uuid/5306-AD9A";
fsType = "vfat"; fsType = "vfat";
}; };
fileSystems."/var/lib/acme" = fileSystems."/var/lib/acme" = {
{ device = "loutrepool/var/acme"; device = "loutrepool/var/acme";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/certs" = fileSystems."/var/certs" = {
{ device = "loutrepool/var/certs"; device = "loutrepool/var/certs";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/transmission" = fileSystems."/var/lib/transmission" = {
{ device = "loutrepool/var/transmission"; device = "loutrepool/var/transmission";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/matrix-synapse" = fileSystems."/var/lib/matrix-synapse" = {
{ device = "loutrepool/var/matrix-synapse"; device = "loutrepool/var/matrix-synapse";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/radarr" = fileSystems."/var/lib/radarr" = {
{ device = "loutrepool/var/radarr"; device = "loutrepool/var/radarr";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/grafana" = fileSystems."/var/lib/grafana" = {
{ device = "loutrepool/var/grafana"; device = "loutrepool/var/grafana";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/slimserver" = fileSystems."/var/lib/slimserver" = {
{ device = "loutrepool/var/slimserver"; device = "loutrepool/var/slimserver";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/db/influxdb" = fileSystems."/var/db/influxdb" = {
{ device = "loutrepool/var/influxdb"; device = "loutrepool/var/influxdb";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/postgresql" = fileSystems."/var/lib/postgresql" = {
{ device = "loutrepool/var/postgresql"; device = "loutrepool/var/postgresql";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/syncthing" = fileSystems."/var/lib/syncthing" = {
{ device = "loutrepool/var/syncthing"; device = "loutrepool/var/syncthing";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/medias/incomplete" = fileSystems."/mnt/medias/incomplete" = {
{ device = "loutrepool/torrent-dl"; device = "loutrepool/torrent-dl";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/medias" = fileSystems."/mnt/medias" = {
{ device = "loutrepool/medias"; device = "loutrepool/medias";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/sieve" = fileSystems."/var/sieve" = {
{ device = "loutrepool/var/sieve"; device = "loutrepool/var/sieve";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/vmail" = fileSystems."/var/vmail" = {
{ device = "loutrepool/var/vmail"; device = "loutrepool/var/vmail";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/sonarr" = fileSystems."/var/lib/sonarr" = {
{ device = "loutrepool/var/sonarr"; device = "loutrepool/var/sonarr";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/jackett" = fileSystems."/var/lib/jackett" = {
{ device = "loutrepool/var/jackett"; device = "loutrepool/var/jackett";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/gitea" = fileSystems."/var/lib/gitea" = {
{ device = "loutrepool/var/gitea"; device = "loutrepool/var/gitea";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/private/sdtdserver" = fileSystems."/var/lib/private/sdtdserver" = {
{ device = "loutrepool/var/sdtdserver"; device = "loutrepool/var/sdtdserver";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/private/factorio" = fileSystems."/var/lib/private/factorio" = {
{ device = "loutrepool/var/factorio"; device = "loutrepool/var/factorio";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/dkim" = fileSystems."/var/dkim" = {
{ device = "loutrepool/var/dkim"; device = "loutrepool/var/dkim";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/vsftpd" = fileSystems."/var/vsftpd" = {
{ device = "loutrepool/var/vsftpd"; device = "loutrepool/var/vsftpd";
fsType = "zfs"; fsType = "zfs";
}; };
# fileSystems."/mnt/backup" = # fileSystems."/mnt/backup" =
# { device = "backup"; # { device = "backup";
# fsType = "zfs"; # fsType = "zfs";
# }; # };
fileSystems."/mnt/backup_loutre" = fileSystems."/mnt/backup_loutre" = {
{ device = "loutrepool/backup"; device = "loutrepool/backup";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/secrets" = fileSystems."/mnt/secrets" = {
{ device = "loutrepool/secrets"; device = "loutrepool/secrets";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/minecraft" = fileSystems."/var/lib/minecraft" = {
{ device = "loutrepool/var/minecraft"; device = "loutrepool/var/minecraft";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/www" = fileSystems."/var/www" = {
{ device = "loutrepool/var/www"; device = "loutrepool/var/www";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/mastodon" = fileSystems."/var/lib/mastodon" = {
{ device = "loutrepool/var/mastodon"; device = "loutrepool/var/mastodon";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/hass" = fileSystems."/var/lib/hass" = {
{ device = "loutrepool/var/hass"; device = "loutrepool/var/hass";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/nextcloud" = fileSystems."/var/lib/nextcloud" = {
{ device = "loutrepool/var/nextcloud"; device = "loutrepool/var/nextcloud";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/var/lib/private/photoprism" = fileSystems."/var/lib/private/photoprism" = {
{ device = "loutrepool/var/photoprism"; device = "loutrepool/var/photoprism";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/paul-home" = fileSystems."/mnt/paul-home" = {
{ device = "loutrepool/zfs-replicate/paul-fixe/fastaf/home"; device = "loutrepool/zfs-replicate/paul-fixe/fastaf/home";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/webdav" = fileSystems."/mnt/webdav" = {
{ device = "loutrepool/webdav"; device = "loutrepool/webdav";
fsType = "zfs"; fsType = "zfs";
}; };
swapDevices = swapDevices = [
[ {
{ device = "/var/swapfile";
device = "/var/swapfile"; size = 8096;
size = 8096; }
} ];
];
nix.settings.max-jobs = lib.mkDefault 4; nix.settings.max-jobs = lib.mkDefault 4;
powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand"; powerManagement.cpuFreqGovernor = lib.mkDefault "ondemand";

View file

@ -1,4 +1,10 @@
{ config, lib, pkgs, pkgs-4a3fc4cf7, ... }: {
config,
lib,
pkgs,
pkgs-4a3fc4cf7,
...
}:
{ {
services = { services = {

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
let let
domaine = "nyanlout.re"; domaine = "nyanlout.re";
@ -23,28 +28,44 @@ in
enable = true; enable = true;
extraConfig = { extraConfig = {
inputs = { inputs = {
zfs = { poolMetrics = true; }; zfs = {
net = { interfaces = [ "eno1" "eno2" "eno3" "eno4" ]; }; poolMetrics = true;
netstat = {}; };
cpu = { totalcpu = true; }; net = {
kernel = {}; interfaces = [
mem = {}; "eno1"
processes = {}; "eno2"
system = {}; "eno3"
disk = {}; "eno4"
];
};
netstat = { };
cpu = {
totalcpu = true;
};
kernel = { };
mem = { };
processes = { };
system = { };
disk = { };
cgroup = [ cgroup = [
{ {
paths = [ paths = [
"/sys/fs/cgroup/system.slice/*" "/sys/fs/cgroup/system.slice/*"
]; ];
files = ["memory.current" "cpu.stat"]; files = [
"memory.current"
"cpu.stat"
];
} }
]; ];
ipmi_sensor = { path = "${pkgs.ipmitool}/bin/ipmitool"; }; ipmi_sensor = {
path = "${pkgs.ipmitool}/bin/ipmitool";
};
smart = { smart = {
path = "${pkgs.writeShellScriptBin "smartctl" "/run/wrappers/bin/sudo ${pkgs.smartmontools}/bin/smartctl $@"}/bin/smartctl"; path = "${pkgs.writeShellScriptBin "smartctl" "/run/wrappers/bin/sudo ${pkgs.smartmontools}/bin/smartctl $@"}/bin/smartctl";
}; };
exec= [ exec = [
{ {
commands = [ commands = [
"${pkgs.python3}/bin/python ${pkgs.writeText "zpool.py" '' "${pkgs.python3}/bin/python ${pkgs.writeText "zpool.py" ''
@ -76,7 +97,10 @@ in
]; ];
}; };
outputs = { outputs = {
influxdb = { database = "telegraf"; urls = [ "http://localhost:8086" ]; }; influxdb = {
database = "telegraf";
urls = [ "http://localhost:8086" ];
};
}; };
}; };
}; };
@ -122,6 +146,14 @@ in
}; };
security.sudo.extraRules = [ security.sudo.extraRules = [
{ commands = [ { command = "${pkgs.smartmontools}/bin/smartctl"; options = [ "NOPASSWD" ]; } ]; users = [ "telegraf" ]; } {
commands = [
{
command = "${pkgs.smartmontools}/bin/smartctl";
options = [ "NOPASSWD" ];
}
];
users = [ "telegraf" ];
}
]; ];
} }

View file

@ -1,4 +1,9 @@
{ config, pkgs, inputs, ... }: {
config,
pkgs,
inputs,
...
}:
{ {
boot = { boot = {
@ -52,7 +57,10 @@
}; };
eno2 = { eno2 = {
ipv4.addresses = [ ipv4.addresses = [
{ address = "10.30.0.1"; prefixLength = 16; } {
address = "10.30.0.1";
prefixLength = 16;
}
]; ];
}; };
enp0s21u1.useDHCP = true; enp0s21u1.useDHCP = true;
@ -110,18 +118,31 @@
firewall = { firewall = {
enable = true; enable = true;
allowedTCPPorts = [ 80 443 ]; allowedTCPPorts = [
80
443
];
allowedUDPPorts = [ ]; allowedUDPPorts = [ ];
# Open ports on local netwok only # Open ports on local netwok only
interfaces.eno2 = { interfaces.eno2 = {
allowedTCPPorts = [ allowedTCPPorts = [
111 2049 4000 4001 4002 # NFS 111
3483 9000 9090 # Slimserver 2049
4000
4001
4002 # NFS
3483
9000
9090 # Slimserver
1935 # RTMP 1935 # RTMP
]; ];
allowedUDPPorts = [ allowedUDPPorts = [
111 2049 4000 4001 4002 # NFS 111
2049
4000
4001
4002 # NFS
3483 # Slimserver 3483 # Slimserver
67 # DHCP 67 # DHCP
]; ];
@ -142,8 +163,8 @@
}; };
serviceConfig = { serviceConfig = {
LoadCredential = [ LoadCredential = [
"network.wireguard.private.wg0:/mnt/secrets/wireguard/wireguard.private" "network.wireguard.private.wg0:/mnt/secrets/wireguard/wireguard.private"
"network.wireguard.preshared.wg0:/mnt/secrets/wireguard/wireguard.preshared" "network.wireguard.preshared.wg0:/mnt/secrets/wireguard/wireguard.preshared"
]; ];
}; };
}; };
@ -162,204 +183,209 @@
# 51000: from all lookup fiber # first table encountered with a default route if fiber is up # 51000: from all lookup fiber # first table encountered with a default route if fiber is up
# 52000: from all lookup lte # first table encountered with a default route if fiber is down # 52000: from all lookup lte # first table encountered with a default route if fiber is down
systemd.network = let systemd.network =
routeTables = { let
fiber = 1; routeTables = {
lte = 2; fiber = 1;
vpn = 3; lte = 2;
}; vpn = 3;
in {
enable = true;
config = {
inherit routeTables;
addRouteTablesToIPRoute2 = true;
};
# Wireguard ARN device configuation
netdevs = {
"10-wg0" = {
netdevConfig = {
Kind = "wireguard";
Name = "wg0";
MTUBytes = "1450";
};
wireguardConfig = {
PrivateKey = "@network.wireguard.private.wg0";
RouteTable = routeTables.vpn;
};
wireguardPeers = [
{
Endpoint = "89.234.141.83:8095";
PublicKey = "t3+JkBfXI1uw8fa9P6JfxXJfTPm9cOHcgIN215UHg2g=";
PresharedKey = "@network.wireguard.preshared.wg0";
AllowedIPs = ["0.0.0.0/0" "::/0"];
PersistentKeepalive = 15;
}
];
}; };
}; in
{
enable = true;
networks = { config = {
######### inherit routeTables;
# FIBER # addRouteTablesToIPRoute2 = true;
#########
# Set route metric to highest priority
# Set DHCP client magic settings for Bouygues
"40-bouygues" = {
dhcpV4Config.RouteTable = routeTables.fiber;
dhcpV6Config = {
DUIDRawData = "00:03:00:01:E8:AD:A6:21:73:68";
WithoutRA = "solicit";
};
ipv6AcceptRAConfig = {
DHCPv6Client = true;
RouteTable = routeTables.fiber;
};
networkConfig = {
KeepConfiguration = "dhcp-on-stop";
IPv6AcceptRA = true;
DHCPPrefixDelegation = true;
};
# Static attribution of first IPv6 subnet
dhcpPrefixDelegationConfig.SubnetId = "0";
# Route everything to fiber link with a priority of 40000
routingPolicyRules = [
{
FirewallMark = 1;
Table = routeTables.fiber;
Priority = 41000;
Family = "both";
}
{
Table = routeTables.fiber;
Priority = 51000;
Family = "both";
}
];
}; };
# Don't check VLAN physical interface as it is not directly used # Wireguard ARN device configuation
"40-eno1".linkConfig.RequiredForOnline = "no"; netdevs = {
"10-wg0" = {
####### netdevConfig = {
# LTE # Kind = "wireguard";
####### Name = "wg0";
MTUBytes = "1450";
# Set LTE route to lower priority };
"40-enp0s21u1" = { wireguardConfig = {
dhcpV4Config.RouteTable = routeTables.lte; PrivateKey = "@network.wireguard.private.wg0";
RouteTable = routeTables.vpn;
# Route all to lte link with a priority of 50000 };
routingPolicyRules = [ wireguardPeers = [
{ {
FirewallMark = 2; Endpoint = "89.234.141.83:8095";
Table = routeTables.lte; PublicKey = "t3+JkBfXI1uw8fa9P6JfxXJfTPm9cOHcgIN215UHg2g=";
Priority = 42000; PresharedKey = "@network.wireguard.preshared.wg0";
Family = "both"; AllowedIPs = [
} "0.0.0.0/0"
{ "::/0"
Table = routeTables.lte; ];
Priority = 52000; PersistentKeepalive = 15;
Family = "both"; }
}
];
};
#######
# VPN #
#######
# Wireguard ARN network configuation
"10-wg0" = {
matchConfig.Name = "wg0";
address = [
"89.234.141.196/32"
"2a00:5881:8119:400::1/128"
];
routingPolicyRules = [
# Route outgoing emails to VPN table
{
IncomingInterface = "lo";
DestinationPort = "25";
Table = routeTables.vpn;
Priority = 60;
Family = "both";
}
# Route packets originating from wg0 device to VPN table
# Allow server to respond on the wg0 interface requests
{
FirewallMark = 3;
Table = routeTables.vpn;
Priority = 43000;
Family = "both";
}
];
};
#######
# LAN #
#######
# LAN DHCP server config
"40-eno2" = {
networkConfig = {
IPv6SendRA = true;
DHCPPrefixDelegation = true;
DHCPServer = true;
IPMasquerade = "ipv4";
};
dhcpServerConfig = {
EmitRouter = true;
EmitDNS = true;
DNS = [
# https://www.dns0.eu/fr
"193.110.81.0"
"185.253.5.0"
];
};
dhcpServerStaticLeases = [
# IPMI
{
Address = "10.30.1.1";
MACAddress = "ac:1f:6b:4b:01:15";
}
# paul-fixe
{
Address = "10.30.50.1";
MACAddress = "b4:2e:99:ed:24:26";
}
# salonled
{
Address = "10.30.40.1";
MACAddress = "e0:98:06:85:e9:ce";
}
# miroir-bleu
{
Address = "10.30.40.2";
MACAddress = "e0:98:06:86:38:fc";
}
# miroir-orange
{
Address = "10.30.40.3";
MACAddress = "50:02:91:78:be:be";
}
];
ipv6SendRAConfig = {
EmitDNS = true;
DNS = [
# https://www.dns0.eu/fr
"2a0f:fc80::"
"2a0f:fc81::"
]; ];
}; };
}; };
networks = {
#########
# FIBER #
#########
# Set route metric to highest priority
# Set DHCP client magic settings for Bouygues
"40-bouygues" = {
dhcpV4Config.RouteTable = routeTables.fiber;
dhcpV6Config = {
DUIDRawData = "00:03:00:01:E8:AD:A6:21:73:68";
WithoutRA = "solicit";
};
ipv6AcceptRAConfig = {
DHCPv6Client = true;
RouteTable = routeTables.fiber;
};
networkConfig = {
KeepConfiguration = "dhcp-on-stop";
IPv6AcceptRA = true;
DHCPPrefixDelegation = true;
};
# Static attribution of first IPv6 subnet
dhcpPrefixDelegationConfig.SubnetId = "0";
# Route everything to fiber link with a priority of 40000
routingPolicyRules = [
{
FirewallMark = 1;
Table = routeTables.fiber;
Priority = 41000;
Family = "both";
}
{
Table = routeTables.fiber;
Priority = 51000;
Family = "both";
}
];
};
# Don't check VLAN physical interface as it is not directly used
"40-eno1".linkConfig.RequiredForOnline = "no";
#######
# LTE #
#######
# Set LTE route to lower priority
"40-enp0s21u1" = {
dhcpV4Config.RouteTable = routeTables.lte;
# Route all to lte link with a priority of 50000
routingPolicyRules = [
{
FirewallMark = 2;
Table = routeTables.lte;
Priority = 42000;
Family = "both";
}
{
Table = routeTables.lte;
Priority = 52000;
Family = "both";
}
];
};
#######
# VPN #
#######
# Wireguard ARN network configuation
"10-wg0" = {
matchConfig.Name = "wg0";
address = [
"89.234.141.196/32"
"2a00:5881:8119:400::1/128"
];
routingPolicyRules = [
# Route outgoing emails to VPN table
{
IncomingInterface = "lo";
DestinationPort = "25";
Table = routeTables.vpn;
Priority = 60;
Family = "both";
}
# Route packets originating from wg0 device to VPN table
# Allow server to respond on the wg0 interface requests
{
FirewallMark = 3;
Table = routeTables.vpn;
Priority = 43000;
Family = "both";
}
];
};
#######
# LAN #
#######
# LAN DHCP server config
"40-eno2" = {
networkConfig = {
IPv6SendRA = true;
DHCPPrefixDelegation = true;
DHCPServer = true;
IPMasquerade = "ipv4";
};
dhcpServerConfig = {
EmitRouter = true;
EmitDNS = true;
DNS = [
# https://www.dns0.eu/fr
"193.110.81.0"
"185.253.5.0"
];
};
dhcpServerStaticLeases = [
# IPMI
{
Address = "10.30.1.1";
MACAddress = "ac:1f:6b:4b:01:15";
}
# paul-fixe
{
Address = "10.30.50.1";
MACAddress = "b4:2e:99:ed:24:26";
}
# salonled
{
Address = "10.30.40.1";
MACAddress = "e0:98:06:85:e9:ce";
}
# miroir-bleu
{
Address = "10.30.40.2";
MACAddress = "e0:98:06:86:38:fc";
}
# miroir-orange
{
Address = "10.30.40.3";
MACAddress = "50:02:91:78:be:be";
}
];
ipv6SendRAConfig = {
EmitDNS = true;
DNS = [
# https://www.dns0.eu/fr
"2a0f:fc80::"
"2a0f:fc81::"
];
};
};
};
}; };
};
} }

View file

@ -1,17 +1,24 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
let let
domaine = "nyanlout.re"; domaine = "nyanlout.re";
sendMail = to: subject: message: pkgs.writeShellScriptBin "mail.sh" '' sendMail =
${pkgs.system-sendmail}/bin/sendmail ${to} <<EOF to: subject: message:
From: root@nyanlout.re pkgs.writeShellScriptBin "mail.sh" ''
Subject: ${subject} ${pkgs.system-sendmail}/bin/sendmail ${to} <<EOF
${message} From: root@nyanlout.re
EOF Subject: ${subject}
''; ${message}
EOF
'';
login_mail_alert = pkgs.writeShellScriptBin "mail_alert.sh" '' login_mail_alert = pkgs.writeShellScriptBin "mail_alert.sh" ''
if [ "$PAM_TYPE" != "close_session" ] && [ "$PAM_USER" != "zfspaulfixe" ] && [ "$PAM_USER" != "synology" ] && [ "$PAM_USER" != "rezome" ]; then if [ "$PAM_TYPE" != "close_session" ] && [ "$PAM_USER" != "zfspaulfixe" ] && [ "$PAM_USER" != "synology" ] && [ "$PAM_USER" != "rezome" ]; then
@ -19,7 +26,9 @@ let
fi fi
''; '';
backup_mail_alert = sendMail "paul@nyanlout.re" "ERREUR: Sauvegarde Borg" "Impossible de terminer la sauvegarde. Merci de voir les logs"; backup_mail_alert =
sendMail "paul@nyanlout.re" "ERREUR: Sauvegarde Borg"
"Impossible de terminer la sauvegarde. Merci de voir les logs";
in in
{ {
@ -128,7 +137,9 @@ in
"/mnt/paul-home/paul/.cache" "/mnt/paul-home/paul/.cache"
]; ];
repo = "ssh://u306925@u306925.your-storagebox.de:23/./loutreos"; repo = "ssh://u306925@u306925.your-storagebox.de:23/./loutreos";
environment = { BORG_RSH = "ssh -i /mnt/secrets/hetzner_ssh_key"; }; environment = {
BORG_RSH = "ssh -i /mnt/secrets/hetzner_ssh_key";
};
encryption = { encryption = {
mode = "repokey-blake2"; mode = "repokey-blake2";
passCommand = "cat /mnt/secrets/borgbackup_loutre_encryption_pass"; passCommand = "cat /mnt/secrets/borgbackup_loutre_encryption_pass";
@ -154,12 +165,16 @@ in
borgbackup.repos = { borgbackup.repos = {
diskstation = { diskstation = {
authorizedKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDllbxON66dBju7sMnhX8/E0VRo3+PDYvDsHP0/FK+h8JHol4+pouLmI7KIDKYOJmSuom283OqnyZOMqk+RShTwWIFm9hOd2R9aj45Zrd9jPW2APOCec/Epgogj0bwBnc0l2v6qxkxaBMgL5DnAQ+E00uvL1UQpK8c8j4GGiPlkWJD6Kf+pxmnfH1TIm+J2XCwl0oeCkSK/Frd8eM+wCraMSzoaGiEcfMz2jK8hxDWjDxX7epU0ELF22BVCuyN8cYRoFTnV88E38PlaqsOqD5ePkxk425gDh7j/C06f8QKgnasVH2diixo92kYSd7i/RmfeXDDwAD5xqUvODczEuIdt root@DiskStation" ]; authorizedKeys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDllbxON66dBju7sMnhX8/E0VRo3+PDYvDsHP0/FK+h8JHol4+pouLmI7KIDKYOJmSuom283OqnyZOMqk+RShTwWIFm9hOd2R9aj45Zrd9jPW2APOCec/Epgogj0bwBnc0l2v6qxkxaBMgL5DnAQ+E00uvL1UQpK8c8j4GGiPlkWJD6Kf+pxmnfH1TIm+J2XCwl0oeCkSK/Frd8eM+wCraMSzoaGiEcfMz2jK8hxDWjDxX7epU0ELF22BVCuyN8cYRoFTnV88E38PlaqsOqD5ePkxk425gDh7j/C06f8QKgnasVH2diixo92kYSd7i/RmfeXDDwAD5xqUvODczEuIdt root@DiskStation"
];
path = "/mnt/backup_loutre/diskstation_borg"; path = "/mnt/backup_loutre/diskstation_borg";
user = "synology"; user = "synology";
}; };
minecraft-rezome = { minecraft-rezome = {
authorizedKeys = [ "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc1nGsSesW96k0DPMSt/chjvCrYmfgPgHG1hdUYB5x0pZPdOJaVRIlETWdoFlO+ViviC518B3TF7Qc3oJXPZMchJQl684Nukbc312juf+j9z/KT3dqD8YvKX6o5ynx1Dyq52ftrfkBAEAvzE0OfRljUPbwGBOM0dGRD4R1jbiHquTXpITlbgGTZymbwr4Jr9W9atgf5kHMiX7xOqMZcasDtUE8g+AG4ysHdpjOrBOUM9QeRbVP1bxEFP8xjqOOoET5tbkwektP4B2jaf+EHBPUy2lkwjVEKT6MaSlkJx/wMvUWp25kG9mrXgwUw1bgfOeZIsK6ztcki3l92BJQD9ip shame@minecraft.rezom.eu" ]; authorizedKeys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQDc1nGsSesW96k0DPMSt/chjvCrYmfgPgHG1hdUYB5x0pZPdOJaVRIlETWdoFlO+ViviC518B3TF7Qc3oJXPZMchJQl684Nukbc312juf+j9z/KT3dqD8YvKX6o5ynx1Dyq52ftrfkBAEAvzE0OfRljUPbwGBOM0dGRD4R1jbiHquTXpITlbgGTZymbwr4Jr9W9atgf5kHMiX7xOqMZcasDtUE8g+AG4ysHdpjOrBOUM9QeRbVP1bxEFP8xjqOOoET5tbkwektP4B2jaf+EHBPUy2lkwjVEKT6MaSlkJx/wMvUWp25kG9mrXgwUw1bgfOeZIsK6ztcki3l92BJQD9ip shame@minecraft.rezom.eu"
];
path = "/mnt/backup_loutre/minecraft_rezome"; path = "/mnt/backup_loutre/minecraft_rezome";
user = "rezome"; user = "rezome";
}; };
@ -241,7 +256,7 @@ in
"radio_browser" "radio_browser"
]; ];
config = { config = {
default_config = {}; default_config = { };
homeassistant = { homeassistant = {
country = "FR"; country = "FR";
latitude = 48.60038; latitude = 48.60038;
@ -290,13 +305,13 @@ in
systemd = { systemd = {
timers."lg-devmode-reset" = { timers."lg-devmode-reset" = {
wantedBy = [ "timers.target" ]; wantedBy = [ "timers.target" ];
timerConfig = { timerConfig = {
OnBootSec = "5m"; OnBootSec = "5m";
OnUnitActiveSec = "1w"; OnUnitActiveSec = "1w";
}; };
}; };
services = { services = {
"borgbackup-job-loutre".serviceConfig.TemporaryFileSystem = ["/mnt/borgsnap"]; "borgbackup-job-loutre".serviceConfig.TemporaryFileSystem = [ "/mnt/borgsnap" ];
"lg-devmode-reset" = { "lg-devmode-reset" = {
script = '' script = ''
${pkgs.curl}/bin/curl https://developer.lge.com/secure/ResetDevModeSession.dev\?sessionToken\=9f94269da0dc14fd924b65d8dca28b076f931ad1ca04fe7a09ac78cdb0e22cb4 ${pkgs.curl}/bin/curl https://developer.lge.com/secure/ResetDevModeSession.dev\?sessionToken\=9f94269da0dc14fd924b65d8dca28b076f931ad1ca04fe7a09ac78cdb0e22cb4
@ -314,7 +329,9 @@ in
users.groups.nginx.members = [ "matrix-synapse" ]; users.groups.nginx.members = [ "matrix-synapse" ];
security.pam.services.sshd.text = pkgs.lib.mkDefault( pkgs.lib.mkAfter "session optional ${pkgs.pam}/lib/security/pam_exec.so seteuid ${login_mail_alert}/bin/mail_alert.sh" ); security.pam.services.sshd.text = pkgs.lib.mkDefault (
pkgs.lib.mkAfter "session optional ${pkgs.pam}/lib/security/pam_exec.so seteuid ${login_mail_alert}/bin/mail_alert.sh"
);
networking = { networking = {
firewall.interfaces.eno2.allowedTCPPorts = [ firewall.interfaces.eno2.allowedTCPPorts = [
@ -322,11 +339,15 @@ in
]; ];
firewall.allowedTCPPorts = [ firewall.allowedTCPPorts = [
20 21 # FTP 20
21 # FTP
]; ];
firewall.allowedTCPPortRanges = [ firewall.allowedTCPPortRanges = [
{ from = 64000; to = 65535; } # FTP {
from = 64000;
to = 65535;
} # FTP
]; ];
}; };
} }

View file

@ -1,4 +1,9 @@
{ lib, config, pkgs, ... }: {
lib,
config,
pkgs,
...
}:
{ {
users.users = { users.users = {
@ -6,7 +11,12 @@
uid = 1000; uid = 1000;
isNormalUser = true; isNormalUser = true;
description = "Paul TREHIOU"; description = "Paul TREHIOU";
extraGroups = [ "wheel" "medias" "transmission" "podman" ]; extraGroups = [
"wheel"
"medias"
"transmission"
"podman"
];
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAF7VlzHzgg70uFbRFtVTS34qNBke/RD36mRENAsa33RxztxrqMsIDscAD/d6CTe6HDy7MCGzJnWCJSXj5iOQFM4RRMvKNEgCKPHqfhmfVvO4YZuMjNB0ufVf6zhJL4Hy43STf7NIWrenGemUP+OvVSwN/ujgl2KKw4KJZt25/h/7JjlCgsZm4lWg4xcjoiKL701W2fbEoU73XKdbRTgTvKoeK1CGxdAPFefFDFcv/mtJ7d+wIxw9xODcLcA66Bu94WGMdpyEAJc4nF8IOy4pW8AzllDi0qNEZGCQ5+94upnLz0knG1ue9qU2ScAkW1/5rIJTHCVtBnmbLNSAOBAstaGQJuSL40TWZ1oPA5i1qUEhunNcJ+Sgtp6XP69qY34T/AeJvHRyw5M5LfN0g+4ka9k06NPBhbpHFASz4M8nabQ0iM63++xcapnw/8gk+EPhYVKW86SsyTa9ur+tt6oDWEKNaOhgscX44LexY7jKdeBRt3GaObtBJtVLBRx3Z2aRXgjgnKGqS40mGRiSkqb2DShspI1l8DV2RrPiuwdBzXVQjWRc0KXmJrcgXX9uoPSxihxwaUQyvmITOV1Y+NEuek4gRkVNOxjoG7RGnaYvYzxEQVoI5TwZC2/DCrAUgCv8DQawkcpEiWnBq7Q5VnpmFx5juVQ/I0G8byOkPXgRUOk9 openpgp:0xAB524BBC" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAF7VlzHzgg70uFbRFtVTS34qNBke/RD36mRENAsa33RxztxrqMsIDscAD/d6CTe6HDy7MCGzJnWCJSXj5iOQFM4RRMvKNEgCKPHqfhmfVvO4YZuMjNB0ufVf6zhJL4Hy43STf7NIWrenGemUP+OvVSwN/ujgl2KKw4KJZt25/h/7JjlCgsZm4lWg4xcjoiKL701W2fbEoU73XKdbRTgTvKoeK1CGxdAPFefFDFcv/mtJ7d+wIxw9xODcLcA66Bu94WGMdpyEAJc4nF8IOy4pW8AzllDi0qNEZGCQ5+94upnLz0knG1ue9qU2ScAkW1/5rIJTHCVtBnmbLNSAOBAstaGQJuSL40TWZ1oPA5i1qUEhunNcJ+Sgtp6XP69qY34T/AeJvHRyw5M5LfN0g+4ka9k06NPBhbpHFASz4M8nabQ0iM63++xcapnw/8gk+EPhYVKW86SsyTa9ur+tt6oDWEKNaOhgscX44LexY7jKdeBRt3GaObtBJtVLBRx3Z2aRXgjgnKGqS40mGRiSkqb2DShspI1l8DV2RrPiuwdBzXVQjWRc0KXmJrcgXX9uoPSxihxwaUQyvmITOV1Y+NEuek4gRkVNOxjoG7RGnaYvYzxEQVoI5TwZC2/DCrAUgCv8DQawkcpEiWnBq7Q5VnpmFx5juVQ/I0G8byOkPXgRUOk9 openpgp:0xAB524BBC"
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCACVI2dL4AmOdcb7RSl3JZpfK33NhqrYFfWfXMYow5SPJ9VPteOp5kVvKUuSbGH3chjpttYC/ueQJJhFagiKmkeftQTslIw6C009wUExGpJwRotHqISXv2ctURGURKy2FF848whd7xZJzdj49ZJ6S+SCbRFZvVWfT2dP/JwTiWW1mbEaWKyOgrixH6wSKt9ECumjX9KjqSWGw+k3yLJxIhdqiZAjNv4soJs1mQYdIlFCXCuznzoZIQBexZPQCx0j9HjczPz1feMLWkrHzEMexNjsBE2uA6yXLbH1wa8xCJ4VOeD7u9JqVY579AsicD62G+qIgw0B2zmyz7xTrdPv+061zmYn6qYr8EXGTk4dVgedZp8M1XzZ1PVoeeftPFcClXC7zCGyCR2uzJbQLzlaTwZrdghAiS9UhMRuKpNgZy2zDWw4MqdojrF5bndPkoijlXWYrPYBFED5OU1mpwzpanYgldowJC/Ixjwi+Hmse2q4XgZ+egfuotBqPfqB+bWsCa5GNiJWGdLP69uBSsXubGnqLwvE0FAQ2GHb+SEoZKFy/QV9GzOLlVrGlgK5YFgKJD+Q1nn1QRycXt1oMVC/AtR/NshOGanhdvIRpPATGmaxLVXSY093vyAOW4MPrS00fPAXzAfJUwIuWcloFfLMo5Jitj5rpE1s6FX8xrl4upQ== paul@nyanlout.re" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDCACVI2dL4AmOdcb7RSl3JZpfK33NhqrYFfWfXMYow5SPJ9VPteOp5kVvKUuSbGH3chjpttYC/ueQJJhFagiKmkeftQTslIw6C009wUExGpJwRotHqISXv2ctURGURKy2FF848whd7xZJzdj49ZJ6S+SCbRFZvVWfT2dP/JwTiWW1mbEaWKyOgrixH6wSKt9ECumjX9KjqSWGw+k3yLJxIhdqiZAjNv4soJs1mQYdIlFCXCuznzoZIQBexZPQCx0j9HjczPz1feMLWkrHzEMexNjsBE2uA6yXLbH1wa8xCJ4VOeD7u9JqVY579AsicD62G+qIgw0B2zmyz7xTrdPv+061zmYn6qYr8EXGTk4dVgedZp8M1XzZ1PVoeeftPFcClXC7zCGyCR2uzJbQLzlaTwZrdghAiS9UhMRuKpNgZy2zDWw4MqdojrF5bndPkoijlXWYrPYBFED5OU1mpwzpanYgldowJC/Ixjwi+Hmse2q4XgZ+egfuotBqPfqB+bWsCa5GNiJWGdLP69uBSsXubGnqLwvE0FAQ2GHb+SEoZKFy/QV9GzOLlVrGlgK5YFgKJD+Q1nn1QRycXt1oMVC/AtR/NshOGanhdvIRpPATGmaxLVXSY093vyAOW4MPrS00fPAXzAfJUwIuWcloFfLMo5Jitj5rpE1s6FX8xrl4upQ== paul@nyanlout.re"
@ -56,6 +66,12 @@
users.extraGroups.medias = { users.extraGroups.medias = {
gid = 498; gid = 498;
members = [ "slimserver" "radarr" "sonarr" "jellyfin" "transmission" ]; members = [
"slimserver"
"radarr"
"sonarr"
"jellyfin"
"transmission"
];
}; };
} }

View file

@ -1,4 +1,9 @@
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
with lib; with lib;
@ -15,7 +20,7 @@ let
internal; internal;
# Access /auth endpoint to query login state # Access /auth endpoint to query login state
proxy_pass http://127.0.0.1:${toString(config.services.nginx.sso.configuration.listen.port)}/auth; proxy_pass http://127.0.0.1:${toString (config.services.nginx.sso.configuration.listen.port)}/auth;
# Do not forward the request body (nginx-sso does not care about it) # Do not forward the request body (nginx-sso does not care about it)
proxy_pass_request_body off; proxy_pass_request_body off;
@ -53,7 +58,7 @@ in
}; };
users.groups = { users.groups = {
webdav = {}; webdav = { };
}; };
users.users = { users.users = {
webdav = { webdav = {
@ -83,7 +88,10 @@ in
nginx = { nginx = {
enable = true; enable = true;
package = pkgs.nginx.override { package = pkgs.nginx.override {
modules = with pkgs.nginxModules; [ dav moreheaders ]; modules = with pkgs.nginxModules; [
dav
moreheaders
];
}; };
recommendedGzipSettings = true; recommendedGzipSettings = true;
recommendedOptimisation = true; recommendedOptimisation = true;
@ -115,7 +123,12 @@ in
}; };
audit_log = { audit_log = {
targets = [ "fd://stdout" ]; targets = [ "fd://stdout" ];
events = [ "access_denied" "login_success" "login_failure" "logout" ]; events = [
"access_denied"
"login_success"
"login_failure"
"logout"
];
}; };
providers.simple = { providers.simple = {
enable_basic_auth = true; enable_basic_auth = true;
@ -129,165 +142,188 @@ in
acl = { acl = {
rule_sets = [ rule_sets = [
{ {
rules = [ { field = "x-host"; regexp = ".*"; } ]; rules = [
{
field = "x-host";
regexp = ".*";
}
];
allow = [ "@admins" ]; allow = [ "@admins" ];
} }
]; ];
}; };
}; };
}; };
virtualHosts = let virtualHosts =
base = locations: { let
locations = locations // { base = locations: {
"@maintenance" = { locations = locations // {
root = "/var/www/errorpages/"; "@maintenance" = {
extraConfig = '' root = "/var/www/errorpages/";
rewrite ^(.*)$ /50x.html break; extraConfig = ''
''; rewrite ^(.*)$ /50x.html break;
'';
};
}; };
forceSSL = true;
enableACME = true;
extraConfig = ''
error_page 500 502 503 504 = @maintenance;
'';
}; };
forceSSL = true; simpleReverse =
enableACME = true; rport:
extraConfig = '' base {
error_page 500 502 503 504 = @maintenance; "/" = {
''; proxyPass = "http://127.0.0.1:${toString (rport)}/";
}; };
simpleReverse = rport: base { };
"/" = { authReverse =
proxyPass = "http://127.0.0.1:${toString(rport)}/"; rport:
}; zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0) [
}; (base {
authReverse = rport: zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0) [ "/" = {
(base { proxyPass = "http://127.0.0.1:${toString (rport)}/";
extraConfig = ''
auth_request_set $cookie $upstream_http_set_cookie;
auth_request_set $username $upstream_http_x_username;
proxy_set_header X-WEBAUTH-USER $username;
add_header Set-Cookie $cookie;
'';
};
})
{
extraConfig = ''
include ${nginxSsoAuth};
'';
}
];
in
{
"nyanlout.re" =
base {
"/" = {
alias = "/var/www/site-perso/";
};
"/maintenance/" = {
alias = "/var/www/errorpages/";
};
"/.well-known/openpgpkey/" = {
alias = "/var/lib/gnupg/wks/nyanlout.re";
extraConfig = ''
add_header Access-Control-Allow-Origin * always;
'';
};
}
// {
default = true;
};
"musique-meyenheim.fr" = base {
"/" = { "/" = {
proxyPass = "http://127.0.0.1:${toString(rport)}/"; proxyPass = "http://unix:/run/site-musique.sock";
extraConfig = ''
auth_request_set $cookie $upstream_http_set_cookie;
auth_request_set $username $upstream_http_x_username;
proxy_set_header X-WEBAUTH-USER $username;
add_header Set-Cookie $cookie;
'';
}; };
}) "/static/" = {
{ alias = "/var/www/site-musique/staticfiles/";
extraConfig = ''
include ${nginxSsoAuth};
'';
}
];
in {
"nyanlout.re" = base {
"/" = {
alias = "/var/www/site-perso/";
};
"/maintenance/" = {
alias = "/var/www/errorpages/";
};
"/.well-known/openpgpkey/" = {
alias = "/var/lib/gnupg/wks/nyanlout.re";
extraConfig = ''
add_header Access-Control-Allow-Origin * always;
'';
};
} // { default = true; };
"musique-meyenheim.fr" = base {
"/" = {
proxyPass = "http://unix:/run/site-musique.sock";
};
"/static/" = {
alias = "/var/www/site-musique/staticfiles/";
};
"/media/" = {
alias = "/var/www/site-musique/media/";
};
};
"www.musique-meyenheim.fr" = {
enableACME = true;
forceSSL = true;
globalRedirect = "musique-meyenheim.fr";
};
"login.nyanlout.re" = simpleReverse config.services.nginx.sso.configuration.listen.port;
"grafana.nyanlout.re" = authReverse config.services.grafana.settings.server.http_port;
"transmission.nyanlout.re" = authReverse config.services.transmission.settings.rpc-port;
"radarr.nyanlout.re" = authReverse 7878;
"sonarr.nyanlout.re" = authReverse 8989;
"syncthing.nyanlout.re" = authReverse 8384;
"prowlarr.nyanlout.re" = authReverse 9696;
"watcharr.nyanlout.re" = simpleReverse 3080;
"emby.nyanlout.re" = recursiveUpdate (simpleReverse 8096) {
locations."/" = {
proxyWebsockets = true;
};
};
"gitea.nyanlout.re" = simpleReverse config.services.forgejo.settings.server.HTTP_PORT;
"photo.nyanlout.re" = recursiveUpdate (simpleReverse config.services.photoprism.port) {
locations."/" = {
proxyWebsockets = true;
};
};
"zigbee.nyanlout.re" = recursiveUpdate (authReverse config.services.zigbee2mqtt.settings.frontend.port) {
locations."/" = {
proxyWebsockets = true;
};
};
"apart.nyanlout.re" = recursiveUpdate (simpleReverse config.services.home-assistant.config.http.server_port) {
locations."/" = {
proxyWebsockets = true;
};
};
"drive.nyanlout.re" = base {
"/" = {
extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.drive.socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_intercept_errors on;
fastcgi_buffers 64 4K;
client_body_temp_path /mnt/webdav/tmp_upload;
client_max_body_size 0;
proxy_request_buffering off;
'';
};
} // {
root = "/mnt/webdav";
};
"rspamd.nyanlout.re" = zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0) [
(base {
"/" = {
proxyPass = "http://unix:/run/rspamd/worker-controller.sock";
extraConfig = ''
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
'';
}; };
}) "/media/" = {
{ alias = "/var/www/site-musique/media/";
extraConfig = '' };
include ${nginxSsoAuth}; };
''; "www.musique-meyenheim.fr" = {
} enableACME = true;
]; forceSSL = true;
"designyourfuture.amandoline-creations.fr" = base { globalRedirect = "musique-meyenheim.fr";
"/".alias = "/var/www/amandoline-designyourfuture/"; };
"login.nyanlout.re" = simpleReverse config.services.nginx.sso.configuration.listen.port;
"grafana.nyanlout.re" = authReverse config.services.grafana.settings.server.http_port;
"transmission.nyanlout.re" = authReverse config.services.transmission.settings.rpc-port;
"radarr.nyanlout.re" = authReverse 7878;
"sonarr.nyanlout.re" = authReverse 8989;
"syncthing.nyanlout.re" = authReverse 8384;
"prowlarr.nyanlout.re" = authReverse 9696;
"watcharr.nyanlout.re" = simpleReverse 3080;
"emby.nyanlout.re" = recursiveUpdate (simpleReverse 8096) {
locations."/" = {
proxyWebsockets = true;
};
};
"gitea.nyanlout.re" = simpleReverse config.services.forgejo.settings.server.HTTP_PORT;
"photo.nyanlout.re" = recursiveUpdate (simpleReverse config.services.photoprism.port) {
locations."/" = {
proxyWebsockets = true;
};
};
"zigbee.nyanlout.re" =
recursiveUpdate (authReverse config.services.zigbee2mqtt.settings.frontend.port)
{
locations."/" = {
proxyWebsockets = true;
};
};
"apart.nyanlout.re" =
recursiveUpdate (simpleReverse config.services.home-assistant.config.http.server_port)
{
locations."/" = {
proxyWebsockets = true;
};
};
"drive.nyanlout.re" =
base {
"/" = {
extraConfig = ''
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass unix:${config.services.phpfpm.pools.drive.socket};
include ${pkgs.nginx}/conf/fastcgi_params;
include ${pkgs.nginx}/conf/fastcgi.conf;
fastcgi_param SCRIPT_FILENAME $document_root/index.php;
fastcgi_intercept_errors on;
fastcgi_buffers 64 4K;
client_body_temp_path /mnt/webdav/tmp_upload;
client_max_body_size 0;
proxy_request_buffering off;
'';
};
}
// {
root = "/mnt/webdav";
};
"rspamd.nyanlout.re" =
zipAttrsWith (name: vs: if name == "extraConfig" then (concatStrings vs) else elemAt vs 0)
[
(base {
"/" = {
proxyPass = "http://unix:/run/rspamd/worker-controller.sock";
extraConfig = ''
auth_request_set $cookie $upstream_http_set_cookie;
add_header Set-Cookie $cookie;
'';
};
})
{
extraConfig = ''
include ${nginxSsoAuth};
'';
}
];
"designyourfuture.amandoline-creations.fr" = base {
"/".alias = "/var/www/amandoline-designyourfuture/";
};
"amandoline-creations.fr" = base {
"/".alias = "/var/www/amandoline-portfolio/";
};
"www.amandoline-creations.fr" = {
enableACME = true;
forceSSL = true;
globalRedirect = "amandoline-creations.fr";
};
"challenge.amandoline-creations.fr" = base {
"/".alias = "/var/www/amandoline-challenge/";
};
${config.services.nextcloud.hostName} = {
forceSSL = true;
enableACME = true;
};
}; };
"amandoline-creations.fr" = base {
"/".alias = "/var/www/amandoline-portfolio/";
};
"www.amandoline-creations.fr" = {
enableACME = true;
forceSSL = true;
globalRedirect = "amandoline-creations.fr";
};
"challenge.amandoline-creations.fr" = base {
"/".alias = "/var/www/amandoline-challenge/";
};
${config.services.nextcloud.hostName} = {
forceSSL = true;
enableACME = true;
};
};
}; };
postgresql = { postgresql = {
@ -382,35 +418,50 @@ in
LoadCredential = "nextcloud_admin.pass:/mnt/secrets/nextcloud_admin.pass"; LoadCredential = "nextcloud_admin.pass:/mnt/secrets/nextcloud_admin.pass";
}; };
systemd.services.site-musique = let systemd.services.site-musique =
djangoEnv =(pkgs.python3.withPackages (ps: with ps; [ gunicorn django_4 pillow setuptools ])); let
in { djangoEnv = (
description = "Site Django de la musique de Meyenheim"; pkgs.python3.withPackages (
after = [ "network.target" ]; ps: with ps; [
requires = [ "site-musique.socket" ]; gunicorn
preStart = '' django_4
${djangoEnv}/bin/python manage.py migrate; pillow
${djangoEnv}/bin/python manage.py collectstatic --no-input; setuptools
''; ]
environment = { )
DJANGO_SETTINGS_MODULE = "site_musique.settings.prod"; );
NGINX_DIRECTORY = "/var/www/site-musique"; in
}; {
serviceConfig = { description = "Site Django de la musique de Meyenheim";
DynamicUser = true; after = [ "network.target" ];
Group = "nginx"; requires = [ "site-musique.socket" ];
StateDirectory = "site-musique"; preStart = ''
WorkingDirectory = "/var/www/site-musique/"; ${djangoEnv}/bin/python manage.py migrate;
ReadWritePaths = [ "/var/www/site-musique/staticfiles" "/var/www/site-musique/media" ]; ${djangoEnv}/bin/python manage.py collectstatic --no-input;
EnvironmentFile = "/mnt/secrets/site-musique.env";
ExecStart = ''${djangoEnv}/bin/gunicorn \
--access-logfile - \
--bind unix:/run/site-musique.sock \
site_musique.wsgi:application
''; '';
PrivateTmp = true; environment = {
DJANGO_SETTINGS_MODULE = "site_musique.settings.prod";
NGINX_DIRECTORY = "/var/www/site-musique";
};
serviceConfig = {
DynamicUser = true;
Group = "nginx";
StateDirectory = "site-musique";
WorkingDirectory = "/var/www/site-musique/";
ReadWritePaths = [
"/var/www/site-musique/staticfiles"
"/var/www/site-musique/media"
];
EnvironmentFile = "/mnt/secrets/site-musique.env";
ExecStart = ''
${djangoEnv}/bin/gunicorn \
--access-logfile - \
--bind unix:/run/site-musique.sock \
site_musique.wsgi:application
'';
PrivateTmp = true;
};
}; };
};
systemd.sockets.site-musique = { systemd.sockets.site-musique = {
description = "Site Musique socket"; description = "Site Musique socket";

View file

@ -5,14 +5,16 @@
{ config, pkgs, ... }: { config, pkgs, ... }:
{ {
imports = imports = [
[ ./hardware-configuration.nix
./hardware-configuration.nix ../common-cli.nix
../common-cli.nix ../common-gui.nix
../common-gui.nix ];
];
nix.settings.trusted-users = [ "root" "paul" ]; nix.settings.trusted-users = [
"root"
"paul"
];
boot.loader.efi.canTouchEfiVariables = true; boot.loader.efi.canTouchEfiVariables = true;
boot.loader.grub = { boot.loader.grub = {
@ -76,7 +78,10 @@
networking.hostId = "3a1f739e"; networking.hostId = "3a1f739e";
networking.hosts = { networking.hosts = {
"10.30.0.1" = ["emby.nyanlout.re" "nyanlout.re"]; "10.30.0.1" = [
"emby.nyanlout.re"
"nyanlout.re"
];
}; };
environment.systemPackages = with pkgs; [ environment.systemPackages = with pkgs; [
@ -95,7 +100,15 @@
users.users.paul = { users.users.paul = {
isNormalUser = true; isNormalUser = true;
extraGroups = [ "wheel" "networkmanager" "wireshark" "input" "dialout" "libvirtd" "vboxusers" ]; extraGroups = [
"wheel"
"networkmanager"
"wireshark"
"input"
"dialout"
"libvirtd"
"vboxusers"
];
uid = 1000; uid = 1000;
openssh.authorizedKeys.keys = [ openssh.authorizedKeys.keys = [
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDstFRwMoTEip5IBSYE4dUj3miO0LsKrnUKQJmp7d5QYo3VhXk43jU6VUU0tVAegkzWLlQ3ohoFns+8bZyf7hj7roftrDfoC9bbbx4ihhWrZTlF0gzoH4t52yetFO5eC/tV2sm/zFoa+3IWLokOEFmAoknAVag1MmVLXTQ6WPoTPD4UsX/D3lyE4dbSKxHpMOIjqIdqSEgO0BeTdnHe5afvGXXO1VYTvPsGDHT9w8EHwQV9JXIPn7KVOp3qin7OwvFFrrB3QbiEVTJvGiH2hrfxcARTN/+TxGtf+aOFeuQykURG9Wz/aBK60EWE0wGrzuIymxtNdOR1NhmnNrUZ976Tb9WdR7FC+yM6+/kdfICy+sGQmmn8TLsGvcJTT/pl4Pa9uRAKjRJuLIEgYY6W/ms9lCRyf484yRkDlq+V0BPuN9Jy6Eb7x+tmZNkpEtkqso7wfXD8sf5BIwv2K69SVMpfTswydHGmDwHZ0zaDKGlyCiyJ1QGqUhCTXqtYVq+kQ3AcjKcysMwVEmwx/ySu0XFuV8oUkl9XK/RUoc++sMEd0EbHcn8uwCmBARNX+GLQ03vxwyMW3HyneP8EAxoqtSepZXbTdVP/0i+l7EUUeA7zsaWfU2a82ktZWpVPFGfxkuo0l3zLF19EsXPKZNqlRfkOWjSgp+qWihAkQIQk3GoduQ== openpgp:0x75EE3375" "ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQDstFRwMoTEip5IBSYE4dUj3miO0LsKrnUKQJmp7d5QYo3VhXk43jU6VUU0tVAegkzWLlQ3ohoFns+8bZyf7hj7roftrDfoC9bbbx4ihhWrZTlF0gzoH4t52yetFO5eC/tV2sm/zFoa+3IWLokOEFmAoknAVag1MmVLXTQ6WPoTPD4UsX/D3lyE4dbSKxHpMOIjqIdqSEgO0BeTdnHe5afvGXXO1VYTvPsGDHT9w8EHwQV9JXIPn7KVOp3qin7OwvFFrrB3QbiEVTJvGiH2hrfxcARTN/+TxGtf+aOFeuQykURG9Wz/aBK60EWE0wGrzuIymxtNdOR1NhmnNrUZ976Tb9WdR7FC+yM6+/kdfICy+sGQmmn8TLsGvcJTT/pl4Pa9uRAKjRJuLIEgYY6W/ms9lCRyf484yRkDlq+V0BPuN9Jy6Eb7x+tmZNkpEtkqso7wfXD8sf5BIwv2K69SVMpfTswydHGmDwHZ0zaDKGlyCiyJ1QGqUhCTXqtYVq+kQ3AcjKcysMwVEmwx/ySu0XFuV8oUkl9XK/RUoc++sMEd0EbHcn8uwCmBARNX+GLQ03vxwyMW3HyneP8EAxoqtSepZXbTdVP/0i+l7EUUeA7zsaWfU2a82ktZWpVPFGfxkuo0l3zLF19EsXPKZNqlRfkOWjSgp+qWihAkQIQk3GoduQ== openpgp:0x75EE3375"

View file

@ -1,12 +1,28 @@
# Do not modify this file! It was generated by nixos-generate-config # Do not modify this file! It was generated by nixos-generate-config
# and may be overwritten by future invocations. Please make changes # and may be overwritten by future invocations. Please make changes
# to /etc/nixos/configuration.nix instead. # to /etc/nixos/configuration.nix instead.
{ config, lib, pkgs, ... }: {
config,
lib,
pkgs,
...
}:
{ {
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "ahci" "usbhid" "usb_storage" "sd_mod" ]; boot.initrd.availableKernelModules = [
"nvme"
"xhci_pci"
"ahci"
"usbhid"
"usb_storage"
"sd_mod"
];
boot.initrd.kernelModules = [ "dm-snapshot" ]; boot.initrd.kernelModules = [ "dm-snapshot" ];
boot.kernelModules = [ "kvm-amd" "coretemp" "it87" ]; boot.kernelModules = [
"kvm-amd"
"coretemp"
"it87"
];
boot.extraModulePackages = [ ]; boot.extraModulePackages = [ ];
services.xserver.videoDrivers = [ "nvidia" ]; services.xserver.videoDrivers = [ "nvidia" ];
@ -17,41 +33,44 @@
package = config.boot.kernelPackages.nvidiaPackages.latest; package = config.boot.kernelPackages.nvidiaPackages.latest;
}; };
fileSystems."/" = fileSystems."/" = {
{ device = "rpool/root/nixos"; device = "rpool/root/nixos";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/boot" = fileSystems."/boot" = {
{ device = "/dev/disk/by-uuid/F4EC-57DF"; device = "/dev/disk/by-uuid/F4EC-57DF";
fsType = "vfat"; fsType = "vfat";
}; };
fileSystems."/home" = fileSystems."/home" = {
{ device = "fastaf/home"; device = "fastaf/home";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/steam" = fileSystems."/mnt/steam" = {
{ device = "fastaf/steam"; device = "fastaf/steam";
fsType = "zfs"; fsType = "zfs";
}; };
fileSystems."/mnt/games" = fileSystems."/mnt/games" = {
{ device = "fastaf/games"; device = "fastaf/games";
fsType = "zfs"; fsType = "zfs";
}; };
# fileSystems."/mnt/hdd" = # fileSystems."/mnt/hdd" =
# { device = "/dev/mapper/ManjaroVG-ManjaroRoot"; # { device = "/dev/mapper/ManjaroVG-ManjaroRoot";
# fsType = "ext4"; # fsType = "ext4";
# }; # };
fileSystems."/mnt/medias" = fileSystems."/mnt/medias" = {
{ device = "10.30.0.1:/mnt/medias"; device = "10.30.0.1:/mnt/medias";
fsType = "nfs"; fsType = "nfs";
options = ["x-systemd.automount" "noauto"]; options = [
}; "x-systemd.automount"
"noauto"
];
};
swapDevices = [ ]; swapDevices = [ ];

View file

@ -11,18 +11,22 @@
vimAlias = true; vimAlias = true;
configure = { configure = {
customRC = '' customRC = ''
set tabstop=8 set tabstop=8
set shiftwidth=4 set shiftwidth=4
set softtabstop=0 set softtabstop=0
set expandtab set expandtab
set smarttab set smarttab
set background=dark set background=dark
set mouse= set mouse=
''; '';
packages.myVimPackage = with pkgs.vimPlugins; { packages.myVimPackage = with pkgs.vimPlugins; {
start = [ start = [
vim-startify airline sensible vim-startify
polyglot ale fugitive airline
sensible
polyglot
ale
fugitive
]; ];
opt = [ ]; opt = [ ];
}; };
@ -73,6 +77,8 @@
# Développement # Développement
openssl openssl
treefmt
nixfmt-rfc-style
]; ];
users.defaultUserShell = pkgs.zsh; users.defaultUserShell = pkgs.zsh;
@ -93,8 +99,14 @@
''; '';
ohMyZsh = { ohMyZsh = {
enable = true; enable = true;
plugins = [ "git" "colored-man-pages" "command-not-found" "extract" "nix" ]; plugins = [
customPkgs = with pkgs;[ "git"
"colored-man-pages"
"command-not-found"
"extract"
"nix"
];
customPkgs = with pkgs; [
nix-zsh-completions nix-zsh-completions
]; ];
}; };
@ -107,16 +119,17 @@
git.enable = true; git.enable = true;
}; };
environment.variables = let environment.variables =
starshipConfToml = let
pkgs.writeText "starship.toml" '' starshipConfToml = pkgs.writeText "starship.toml" ''
[[battery.display]] [[battery.display]]
threshold = 50 threshold = 50
''; '';
in { in
EDITOR = "nvim"; {
STARSHIP_CONFIG = "${starshipConfToml}"; EDITOR = "nvim";
}; STARSHIP_CONFIG = "${starshipConfToml}";
};
nix.gc.automatic = true; nix.gc.automatic = true;
nix.gc.options = "--delete-older-than 15d"; nix.gc.options = "--delete-older-than 15d";

View file

@ -45,7 +45,12 @@
kdePackages.kinfocenter kdePackages.kinfocenter
kile kile
(texlive.combine { (texlive.combine {
inherit (texlive) scheme-small titling collection-langfrench cm-super; inherit (texlive)
scheme-small
titling
collection-langfrench
cm-super
;
}) })
libsForQt5.breeze-gtk libsForQt5.breeze-gtk
@ -75,17 +80,22 @@
systemd.extraConfig = "DefaultLimitNOFILE=1048576"; systemd.extraConfig = "DefaultLimitNOFILE=1048576";
security = { security = {
pam.loginLimits = [{ pam.loginLimits = [
domain = "*"; {
type = "hard"; domain = "*";
item = "nofile"; type = "hard";
value = "1048576"; item = "nofile";
}]; value = "1048576";
}
];
rtkit.enable = true; rtkit.enable = true;
}; };
programs = { programs = {
gnupg.agent = { enable = true; enableSSHSupport = true; }; gnupg.agent = {
enable = true;
enableSSHSupport = true;
};
browserpass.enable = true; browserpass.enable = true;
steam.enable = true; steam.enable = true;
firefox.enable = true; firefox.enable = true;
@ -113,13 +123,13 @@
alsa.support32Bit = true; alsa.support32Bit = true;
pulse.enable = true; pulse.enable = true;
extraConfig.pipewire = { extraConfig.pipewire = {
"10-clock-rate" = { "10-clock-rate" = {
"context.properties" = { "context.properties" = {
"default.clock.allowed-rates" = [ 48000 ]; "default.clock.allowed-rates" = [ 48000 ];
};
}; };
}; };
}; };
};
udev.packages = with pkgs; [ ledger-udev-rules ]; udev.packages = with pkgs; [ ledger-udev-rules ];
pcscd.enable = true; pcscd.enable = true;
}; };

3
treefmt.toml Normal file
View file

@ -0,0 +1,3 @@
[formatter.nixfmt-rfc-style]
command = "nixfmt"
includes = ["*.nix"]