Compare commits
83 Commits
eb76e0242d
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| f9f3abee19 | |||
| 15bc0f211f | |||
| f0fb53b480 | |||
| 1ae85bd66e | |||
| 87b49d0f58 | |||
| c5a1c2861c | |||
| 8dc67e2b54 | |||
| 322136e4f3 | |||
| 300eb66afc | |||
| 545888878e | |||
| 5042675e0b | |||
| ece5e89a84 | |||
| 2933bcdf02 | |||
| 59e548f02e | |||
| 2ffc94161d | |||
| ff5490194b | |||
| 1dd06ef3f5 | |||
| ec9a3bd845 | |||
| 2c08f78586 | |||
| d22801168f | |||
| 0c86dc56bd | |||
| 3d8deae6f3 | |||
| cd978f5eb6 | |||
| 64df7abad5 | |||
| 8efa649d47 | |||
| 2dc09e23a0 | |||
| 8fd2a7d9ad | |||
| 113892b75d | |||
| 001dfbf27f | |||
| 3deca06206 | |||
| 07333b4544 | |||
| 63f495fa0d | |||
| d2bd385367 | |||
| 57cb48a11c | |||
| 6b7ca2b194 | |||
| e578a280db | |||
| 01ca3d7ebe | |||
| 46aa5a9deb | |||
| 549037fe69 | |||
| 0cb6862dcd | |||
| 9e4454ff57 | |||
| 15a20dd8e0 | |||
| 3306598f8a | |||
| 93f227ba7e | |||
| 9d20eff7f9 | |||
| 94d3f2ad35 | |||
| 1d5bc22274 | |||
| f2386a851e | |||
| c9edc99a85 | |||
| 67e83e3e4e | |||
| 923c810972 | |||
| 6ab35f4e91 | |||
| 593f0e619c | |||
| 688e23d229 | |||
| 725a3ed27e | |||
| e45dc0d223 | |||
| bc78dd7302 | |||
| 94c34f8675 | |||
| fda7d972c4 | |||
| f6bb6672bb | |||
| 68f1cb9b09 | |||
| e721a2088b | |||
| 551a47989c | |||
| 2cb07c45a7 | |||
| 4666731676 | |||
| 8fe6382c48 | |||
| 068f47e9a2 | |||
| 27bd976a60 | |||
| 9adfb329af | |||
| 757c3081fd | |||
| 1d2f934c98 | |||
| 86624f362d | |||
| b752781064 | |||
| 884b40c71d | |||
| f861d363ca | |||
| c63daec95c | |||
| 2e1d28450b | |||
| 1228c800a1 | |||
| 1c8ccb6405 | |||
| 3b7e566545 | |||
| 8c07f3642b | |||
| 0d447771eb | |||
| 73960162b0 |
716
flake.lock
generated
716
flake.lock
generated
File diff suppressed because it is too large
Load Diff
41
flake.nix
41
flake.nix
@@ -1,9 +1,8 @@
|
|||||||
{
|
{
|
||||||
description = "cnix nix";
|
description = "cnix nix";
|
||||||
|
|
||||||
outputs =
|
outputs = inputs:
|
||||||
inputs:
|
inputs.flake-parts.lib.mkFlake {inherit inputs;} {
|
||||||
inputs.flake-parts.lib.mkFlake { inherit inputs; } {
|
|
||||||
systems = [
|
systems = [
|
||||||
"x86_64-linux"
|
"x86_64-linux"
|
||||||
"aarch64-linux"
|
"aarch64-linux"
|
||||||
@@ -17,21 +16,23 @@
|
|||||||
./fmt-hooks.nix
|
./fmt-hooks.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
perSystem =
|
perSystem = {
|
||||||
{ config, pkgs, ... }:
|
config,
|
||||||
{
|
pkgs,
|
||||||
devShells.default = pkgs.mkShell {
|
...
|
||||||
packages = [
|
}: {
|
||||||
pkgs.git
|
devShells.default = pkgs.mkShell {
|
||||||
config.packages.repl
|
packages = [
|
||||||
];
|
pkgs.git
|
||||||
name = "dots";
|
config.packages.repl
|
||||||
env.DIRENV_LOG_FORMAT = "";
|
];
|
||||||
shellHook = ''
|
name = "dots";
|
||||||
${config.pre-commit.installationScript}
|
env.DIRENV_LOG_FORMAT = "";
|
||||||
'';
|
shellHook = ''
|
||||||
};
|
${config.pre-commit.installationScript}
|
||||||
|
'';
|
||||||
};
|
};
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
inputs = {
|
inputs = {
|
||||||
@@ -51,6 +52,10 @@
|
|||||||
inputs.nixpkgs-lib.follows = "nixpkgs";
|
inputs.nixpkgs-lib.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
authentik = {
|
||||||
|
url = "github:nix-community/authentik-nix/version/2025.8.4";
|
||||||
|
};
|
||||||
|
|
||||||
flake-compat.url = "github:edolstra/flake-compat";
|
flake-compat.url = "github:edolstra/flake-compat";
|
||||||
|
|
||||||
# Hyprland environment
|
# Hyprland environment
|
||||||
@@ -135,8 +140,6 @@
|
|||||||
inputs.nixpkgs.follows = "nixpkgs";
|
inputs.nixpkgs.follows = "nixpkgs";
|
||||||
};
|
};
|
||||||
|
|
||||||
niri.url = "github:sodiboo/niri-flake";
|
|
||||||
|
|
||||||
# Custom
|
# Custom
|
||||||
tuirun = {
|
tuirun = {
|
||||||
url = "git+https://git.sr.ht/~canasta/tuirun";
|
url = "git+https://git.sr.ht/~canasta/tuirun";
|
||||||
|
|||||||
@@ -38,17 +38,11 @@ in
|
|||||||
./settings.nix
|
./settings.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
|
boot.initrd.luks.devices."luks-0ad53967-bb38-4485-be75-ca55ae4c3b68".device = "/dev/disk/by-uuid/0ad53967-bb38-4485-be75-ca55ae4c3b68";
|
||||||
networking.hostName = "bunk";
|
networking.hostName = "bunk";
|
||||||
|
|
||||||
swapDevices = [
|
|
||||||
{
|
|
||||||
device = "/var/lib/swapfile";
|
|
||||||
size = 32 * 1024;
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.variables.NH_FLAKE = "/home/cnst/.nix-config";
|
environment.variables.NH_FLAKE = "/home/cnst/.nix-config";
|
||||||
|
|
||||||
# https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
|
# https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
|
||||||
system.stateVersion = lib.mkDefault "23.11";
|
system.stateVersion = lib.mkDefault "25.05";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,47 +1,35 @@
|
|||||||
# 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, modulesPath, ... }:
|
||||||
|
|
||||||
{
|
{
|
||||||
config,
|
imports =
|
||||||
lib,
|
[ (modulesPath + "/installer/scan/not-detected.nix")
|
||||||
modulesPath,
|
];
|
||||||
...
|
|
||||||
}:
|
boot.initrd.availableKernelModules = [ "nvme" "xhci_pci" "usb_storage" "sd_mod" ];
|
||||||
{
|
boot.initrd.kernelModules = [ ];
|
||||||
imports = [ (modulesPath + "/installer/scan/not-detected.nix") ];
|
boot.kernelModules = [ "kvm-amd" ];
|
||||||
boot = {
|
boot.extraModulePackages = [ ];
|
||||||
initrd = {
|
|
||||||
availableKernelModules = [
|
fileSystems."/" =
|
||||||
"nvme"
|
{ device = "/dev/disk/by-uuid/d15672b5-dc97-4f99-9ad2-70f9ddf20447";
|
||||||
"xhci_pci"
|
fsType = "btrfs";
|
||||||
"ahci"
|
options = [ "subvol=@" ];
|
||||||
"usbhid"
|
|
||||||
"usb_storage"
|
|
||||||
"sd_mod"
|
|
||||||
];
|
|
||||||
kernelModules = [ "amdgpu" ];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
kernelModules = [ "kvm-amd" ];
|
boot.initrd.luks.devices."luks-2f0dfe96-bc63-4f38-b190-3d9fa45dc560".device = "/dev/disk/by-uuid/2f0dfe96-bc63-4f38-b190-3d9fa45dc560";
|
||||||
extraModulePackages = [ ];
|
|
||||||
};
|
|
||||||
|
|
||||||
fileSystems."/" = {
|
fileSystems."/boot" =
|
||||||
device = "/dev/disk/by-uuid/da41c89a-7ab8-4697-9a14-0d115b97cc2e";
|
{ device = "/dev/disk/by-uuid/F3FC-3CDF";
|
||||||
fsType = "ext4";
|
fsType = "vfat";
|
||||||
};
|
options = [ "fmask=0077" "dmask=0077" ];
|
||||||
|
};
|
||||||
|
|
||||||
boot.initrd.luks.devices."luks-e75ac560-748f-4071-bbe7-479678400be3".device =
|
swapDevices =
|
||||||
"/dev/disk/by-uuid/e75ac560-748f-4071-bbe7-479678400be3";
|
[ { device = "/dev/disk/by-uuid/e6464248-0d1e-4950-bf48-4cebeabaf871"; }
|
||||||
|
|
||||||
fileSystems."/boot" = {
|
|
||||||
device = "/dev/disk/by-uuid/7E84-D168";
|
|
||||||
fsType = "vfat";
|
|
||||||
options = [
|
|
||||||
"fmask=0022"
|
|
||||||
"dmask=0022"
|
|
||||||
];
|
];
|
||||||
};
|
|
||||||
|
|
||||||
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
# Enables DHCP on each ethernet and wireless interface. In case of scripted networking
|
||||||
# (the default) this is the recommended approach. When using systemd-networkd it's
|
# (the default) this is the recommended approach. When using systemd-networkd it's
|
||||||
|
|||||||
@@ -27,6 +27,13 @@
|
|||||||
};
|
};
|
||||||
network = {
|
network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
nameservers = [
|
||||||
|
"192.168.88.1"
|
||||||
|
"192.168.88.69"
|
||||||
|
];
|
||||||
|
search = [
|
||||||
|
"taila7448a.ts.net"
|
||||||
|
];
|
||||||
interfaces = {
|
interfaces = {
|
||||||
"wlp6s0" = {
|
"wlp6s0" = {
|
||||||
allowedTCPPorts = [
|
allowedTCPPorts = [
|
||||||
@@ -73,8 +80,8 @@
|
|||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
hyprland = {
|
hyprland = {
|
||||||
enable = false;
|
enable = true;
|
||||||
withUWSM = false;
|
withUWSM = true;
|
||||||
};
|
};
|
||||||
inkscape = {
|
inkscape = {
|
||||||
enable = false;
|
enable = false;
|
||||||
@@ -86,7 +93,7 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
niri = {
|
niri = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
pkgs = {
|
pkgs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -123,10 +130,10 @@
|
|||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
thunar = {
|
thunar = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
yubikey = {
|
yubikey = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
zsh = {
|
zsh = {
|
||||||
enable = false;
|
enable = false;
|
||||||
@@ -168,7 +175,7 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
mullvad = {
|
mullvad = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
nix-ld = {
|
nix-ld = {
|
||||||
enable = false;
|
enable = false;
|
||||||
@@ -191,11 +198,14 @@
|
|||||||
samba = {
|
samba = {
|
||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
|
tailscale = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
udisks = {
|
udisks = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
zram = {
|
zram = {
|
||||||
enable = false;
|
enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
system = {
|
system = {
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
name = "DP-3";
|
name = "DP-3";
|
||||||
width = 2560;
|
width = 2560;
|
||||||
height = 1440;
|
height = 1440;
|
||||||
refreshRate = 240;
|
refreshRate = "143.99";
|
||||||
position = "0x0";
|
position = "0x0";
|
||||||
transform = 0;
|
transform = 0;
|
||||||
bitDepth = 10;
|
bitDepth = 10;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
name = "HDMI-A-1";
|
name = "HDMI-A-1";
|
||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1080;
|
height = 1080;
|
||||||
refreshRate = 60;
|
refreshRate = "60";
|
||||||
position = "2560x0";
|
position = "2560x0";
|
||||||
# transform = 3;
|
# transform = 3;
|
||||||
workspace = "5";
|
workspace = "5";
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
name = "eDP-1";
|
name = "eDP-1";
|
||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1200;
|
height = 1200;
|
||||||
refreshRate = 60;
|
refreshRate = "60";
|
||||||
workspace = "1";
|
workspace = "1";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
{
|
{
|
||||||
flake.nixosConfigurations =
|
flake.nixosConfigurations =
|
||||||
let
|
let
|
||||||
cLib = import ../lib inputs.nixpkgs.lib;
|
clib = import ../lib inputs.nixpkgs.lib;
|
||||||
userConfig = "${self}/home";
|
userConfig = "${self}/home";
|
||||||
systemConfig = "${self}/system";
|
systemConfig = "${self}/system";
|
||||||
hostConfig = "${self}/hosts";
|
hostConfig = "${self}/hosts";
|
||||||
@@ -24,7 +24,6 @@
|
|||||||
|
|
||||||
specialArgs = {
|
specialArgs = {
|
||||||
inherit
|
inherit
|
||||||
cLib
|
|
||||||
inputs
|
inputs
|
||||||
outputs
|
outputs
|
||||||
self
|
self
|
||||||
@@ -37,17 +36,20 @@
|
|||||||
smodPath
|
smodPath
|
||||||
;
|
;
|
||||||
};
|
};
|
||||||
|
specialArgsWithClib = specialArgs // {
|
||||||
|
inherit clib;
|
||||||
|
};
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
kima = nixosSystem {
|
kima = nixosSystem {
|
||||||
inherit specialArgs;
|
specialArgs = specialArgsWithClib;
|
||||||
modules = [
|
modules = [
|
||||||
./kima
|
./kima
|
||||||
"${self}/nix"
|
"${self}/nix"
|
||||||
{
|
{
|
||||||
home-manager = {
|
home-manager = {
|
||||||
users.cnst.imports = homeImports."cnst@kima";
|
users.cnst.imports = homeImports."cnst@kima";
|
||||||
extraSpecialArgs = specialArgs;
|
extraSpecialArgs = specialArgsWithClib;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.nixosModules.nixos
|
self.nixosModules.nixos
|
||||||
@@ -57,14 +59,14 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
bunk = nixosSystem {
|
bunk = nixosSystem {
|
||||||
inherit specialArgs;
|
specialArgs = specialArgsWithClib;
|
||||||
modules = [
|
modules = [
|
||||||
./bunk
|
./bunk
|
||||||
"${self}/nix"
|
"${self}/nix"
|
||||||
{
|
{
|
||||||
home-manager = {
|
home-manager = {
|
||||||
users.cnst.imports = homeImports."cnst@bunk";
|
users.cnst.imports = homeImports."cnst@bunk";
|
||||||
extraSpecialArgs = specialArgs;
|
extraSpecialArgs = specialArgsWithClib;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.nixosModules.nixos
|
self.nixosModules.nixos
|
||||||
@@ -82,6 +84,7 @@
|
|||||||
self.nixosModules.settings
|
self.nixosModules.settings
|
||||||
self.nixosModules.server
|
self.nixosModules.server
|
||||||
inputs.agenix.nixosModules.default
|
inputs.agenix.nixosModules.default
|
||||||
|
inputs.authentik.nixosModules.default
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
ziggy = nixosSystem {
|
ziggy = nixosSystem {
|
||||||
@@ -96,14 +99,14 @@
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
toothpc = nixosSystem {
|
toothpc = nixosSystem {
|
||||||
inherit specialArgs;
|
specialArgs = specialArgsWithClib;
|
||||||
modules = [
|
modules = [
|
||||||
./toothpc
|
./toothpc
|
||||||
"${self}/nix"
|
"${self}/nix"
|
||||||
{
|
{
|
||||||
home-manager = {
|
home-manager = {
|
||||||
users.toothpick.imports = homeImports."toothpick@toothpc";
|
users.toothpick.imports = homeImports."toothpick@toothpc";
|
||||||
extraSpecialArgs = specialArgs;
|
extraSpecialArgs = specialArgsWithClib;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
self.nixosModules.nixos
|
self.nixosModules.nixos
|
||||||
|
|||||||
@@ -21,8 +21,9 @@
|
|||||||
"usbhid"
|
"usbhid"
|
||||||
"sd_mod"
|
"sd_mod"
|
||||||
];
|
];
|
||||||
boot.initrd.kernelModules = [ "amdgpu" ];
|
boot.initrd.kernelModules = [ ];
|
||||||
boot.kernelModules = [
|
boot.kernelModules = [
|
||||||
|
"amdgpu"
|
||||||
"kvm-amd"
|
"kvm-amd"
|
||||||
"i2c-dev"
|
"i2c-dev"
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -4,7 +4,8 @@
|
|||||||
kernel = {
|
kernel = {
|
||||||
variant = "latest";
|
variant = "latest";
|
||||||
hardware = [ "amd" ];
|
hardware = [ "amd" ];
|
||||||
extraKernelParams = [ "amdgpu.dcdebugmask=0x10" ];
|
extraKernelParams = [ ];
|
||||||
|
amdOverdrive.enable = true;
|
||||||
};
|
};
|
||||||
loader = {
|
loader = {
|
||||||
default = {
|
default = {
|
||||||
@@ -28,6 +29,13 @@
|
|||||||
};
|
};
|
||||||
network = {
|
network = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
nameservers = [
|
||||||
|
"192.168.88.1"
|
||||||
|
"192.168.88.69"
|
||||||
|
];
|
||||||
|
search = [
|
||||||
|
"taila7448a.ts.net"
|
||||||
|
];
|
||||||
interfaces = {
|
interfaces = {
|
||||||
"eno1" = {
|
"eno1" = {
|
||||||
allowedTCPPorts = [
|
allowedTCPPorts = [
|
||||||
@@ -65,7 +73,7 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
gamescope = {
|
gamescope = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
gimp = {
|
gimp = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -74,8 +82,8 @@
|
|||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
hyprland = {
|
hyprland = {
|
||||||
enable = false;
|
enable = true;
|
||||||
withUWSM = false;
|
withUWSM = true;
|
||||||
};
|
};
|
||||||
inkscape = {
|
inkscape = {
|
||||||
enable = false;
|
enable = false;
|
||||||
@@ -90,7 +98,7 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
niri = {
|
niri = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
pkgs = {
|
pkgs = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -171,8 +179,8 @@
|
|||||||
kanata = {
|
kanata = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
libvirtd = {
|
virtualisation = {
|
||||||
enable = true;
|
enable = false;
|
||||||
};
|
};
|
||||||
locate = {
|
locate = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -214,6 +222,9 @@
|
|||||||
scheduler = "scx_lavd";
|
scheduler = "scx_lavd";
|
||||||
flags = "--performance";
|
flags = "--performance";
|
||||||
};
|
};
|
||||||
|
tailscale = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
udisks = {
|
udisks = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
name = "DP-3";
|
name = "DP-3";
|
||||||
width = 2560;
|
width = 2560;
|
||||||
height = 1440;
|
height = 1440;
|
||||||
refreshRate = 240;
|
refreshRate = "143.99";
|
||||||
position = "0x0";
|
position = "0x0";
|
||||||
transform = 0;
|
transform = 0;
|
||||||
bitDepth = 10;
|
bitDepth = 10;
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
name = "HDMI-A-1";
|
name = "HDMI-A-1";
|
||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1080;
|
height = 1080;
|
||||||
refreshRate = 60;
|
refreshRate = "60";
|
||||||
position = "2560x0";
|
position = "2560x0";
|
||||||
transform = 3;
|
transform = 3;
|
||||||
workspace = "5";
|
workspace = "5";
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
name = "eDP-1";
|
name = "eDP-1";
|
||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1200;
|
height = 1200;
|
||||||
refreshRate = 60;
|
refreshRate = "60";
|
||||||
workspace = "1";
|
workspace = "1";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -3,11 +3,9 @@
|
|||||||
config,
|
config,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
users.users.cnst = {
|
users.users.cnst = {
|
||||||
isNormalUser = true;
|
isNormalUser = true;
|
||||||
shell = pkgs.fish;
|
shell = pkgs.fish;
|
||||||
@@ -41,6 +39,7 @@ in
|
|||||||
"share"
|
"share"
|
||||||
"jellyfin"
|
"jellyfin"
|
||||||
"render"
|
"render"
|
||||||
|
"traefik"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -51,8 +50,7 @@ in
|
|||||||
./server.nix
|
./server.nix
|
||||||
];
|
];
|
||||||
|
|
||||||
boot.initrd.luks.devices."luks-47b35d4b-467a-4637-a5f9-45177da62897".device =
|
boot.initrd.luks.devices."luks-47b35d4b-467a-4637-a5f9-45177da62897".device = "/dev/disk/by-uuid/47b35d4b-467a-4637-a5f9-45177da62897";
|
||||||
"/dev/disk/by-uuid/47b35d4b-467a-4637-a5f9-45177da62897";
|
|
||||||
|
|
||||||
networking = {
|
networking = {
|
||||||
hostName = "sobotka";
|
hostName = "sobotka";
|
||||||
@@ -69,8 +67,11 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
boot = {
|
boot = {
|
||||||
supportedFilesystems = [ "zfs" ];
|
supportedFilesystems = ["zfs"];
|
||||||
zfs.extraPools = [ "data" ];
|
zfs = {
|
||||||
|
package = pkgs.zfs_unstable;
|
||||||
|
extraPools = ["data"];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
services.zfs = {
|
services.zfs = {
|
||||||
@@ -78,6 +79,8 @@ in
|
|||||||
autoScrub.enable = true;
|
autoScrub.enable = true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
environment.etc."nextcloud-admin-pass".text = "DeHKor3x8^eqqnBXjqhQ&QBl*3!sOLg8agfzOILihju#^0!2AfJ9W*vn";
|
||||||
|
|
||||||
environment.variables.NH_FLAKE = "/home/cnst/.nix-config";
|
environment.variables.NH_FLAKE = "/home/cnst/.nix-config";
|
||||||
|
|
||||||
# # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
|
# # https://nixos.wiki/wiki/FAQ/When_do_I_update_stateVersion
|
||||||
|
|||||||
@@ -3,8 +3,8 @@
|
|||||||
boot = {
|
boot = {
|
||||||
kernel = {
|
kernel = {
|
||||||
variant = "latest";
|
variant = "latest";
|
||||||
hardware = [ "amd" ];
|
hardware = ["amd"];
|
||||||
extraKernelParams = [ ];
|
extraKernelParams = [];
|
||||||
};
|
};
|
||||||
loader = {
|
loader = {
|
||||||
default = {
|
default = {
|
||||||
@@ -109,7 +109,7 @@
|
|||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
dev = {
|
dev = {
|
||||||
enable = false;
|
enable = true;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
mysql-workbench = {
|
mysql-workbench = {
|
||||||
@@ -213,6 +213,9 @@
|
|||||||
scheduler = "scx_lavd";
|
scheduler = "scx_lavd";
|
||||||
flags = "--performance";
|
flags = "--performance";
|
||||||
};
|
};
|
||||||
|
tailscale = {
|
||||||
|
enable = false;
|
||||||
|
};
|
||||||
udisks = {
|
udisks = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,91 +1,278 @@
|
|||||||
{ config, ... }:
|
{config, ...}: {
|
||||||
{
|
|
||||||
server = {
|
server = {
|
||||||
enable = true;
|
enable = true;
|
||||||
email = "adam@cnst.dev";
|
email = "adam@cnst.dev";
|
||||||
domain = "cnix.dev";
|
domain = "cnix.dev";
|
||||||
|
ip = "192.168.88.14";
|
||||||
user = "share";
|
user = "share";
|
||||||
group = "share";
|
group = "share";
|
||||||
uid = 994;
|
uid = 994;
|
||||||
gid = 993;
|
gid = 993;
|
||||||
|
|
||||||
gitea = {
|
infra = {
|
||||||
enable = true;
|
authentik = {
|
||||||
};
|
enable = true;
|
||||||
unbound = {
|
url = "auth.cnst.dev";
|
||||||
enable = true;
|
port = 9000;
|
||||||
};
|
cloudflared = {
|
||||||
caddy = {
|
tunnelId = "b66f9368-db9e-4302-8b48-527cda34a635";
|
||||||
enable = true;
|
credentialsFile = config.age.secrets.authentikCloudflared.path;
|
||||||
};
|
};
|
||||||
homepage-dashboard = {
|
};
|
||||||
enable = true;
|
traefik = {
|
||||||
};
|
enable = true;
|
||||||
bazarr = {
|
};
|
||||||
enable = true;
|
tailscale = {
|
||||||
};
|
enable = true;
|
||||||
prowlarr = {
|
};
|
||||||
enable = true;
|
unbound = {
|
||||||
};
|
enable = true;
|
||||||
lidarr = {
|
};
|
||||||
enable = true;
|
fail2ban = {
|
||||||
};
|
enable = true;
|
||||||
sonarr = {
|
apiKeyFile = config.age.secrets.cloudflareFirewallApiKey.path;
|
||||||
enable = true;
|
zoneId = "0027acdfb8bbe010f55b676ad8698dfb";
|
||||||
};
|
};
|
||||||
radarr = {
|
keepalived = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
interface = "enp6s0";
|
||||||
jellyseerr = {
|
};
|
||||||
enable = true;
|
gluetun = {
|
||||||
};
|
enable = true;
|
||||||
jellyfin = {
|
};
|
||||||
enable = true;
|
podman = {
|
||||||
};
|
enable = true;
|
||||||
uptime-kuma = {
|
};
|
||||||
enable = true;
|
www = {
|
||||||
};
|
enable = true;
|
||||||
vaultwarden = {
|
url = "cnst.dev";
|
||||||
enable = true;
|
port = 8283;
|
||||||
url = "vault.cnst.dev";
|
cloudflared = {
|
||||||
cloudflared = {
|
tunnelId = "e5076186-efb7-405a-998c-6155af7fb221";
|
||||||
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
credentialsFile = config.age.secrets.wwwCloudflared.path;
|
||||||
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
nextcloud = {
|
|
||||||
enable = true;
|
services = {
|
||||||
url = "cloud.cnst.dev";
|
homepage-dashboard = {
|
||||||
cloudflared = {
|
enable = true;
|
||||||
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
subdomain = "dash";
|
||||||
credentialsFile = config.age.secrets.nextcloudCloudflared.path;
|
exposure = "local";
|
||||||
|
port = 8082;
|
||||||
|
};
|
||||||
|
n8n = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "n8n";
|
||||||
|
exposure = "local";
|
||||||
|
port = 5678;
|
||||||
|
homepage = {
|
||||||
|
name = "n8n";
|
||||||
|
description = "A workflow automation platform";
|
||||||
|
icon = "n8n.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
ollama = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "ai";
|
||||||
|
exposure = "local";
|
||||||
|
port = 8001;
|
||||||
|
homepage = {
|
||||||
|
name = "ollama";
|
||||||
|
description = "AI platform";
|
||||||
|
icon = "ollama.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
bazarr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "bazarr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 6767;
|
||||||
|
homepage = {
|
||||||
|
name = "Bazarr";
|
||||||
|
description = "Subtitle manager";
|
||||||
|
icon = "bazarr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
prowlarr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "prowlarr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 9696;
|
||||||
|
homepage = {
|
||||||
|
name = "Prowlarr";
|
||||||
|
description = "PVR indexer";
|
||||||
|
icon = "prowlarr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
flaresolverr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "flaresolverr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 8191;
|
||||||
|
homepage = {
|
||||||
|
name = "FlareSolverr";
|
||||||
|
description = "Proxy to bypass Cloudflare/DDoS-GUARD protection";
|
||||||
|
icon = "flaresolverr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
lidarr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "lidarr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 8686;
|
||||||
|
homepage = {
|
||||||
|
name = "Lidarr";
|
||||||
|
description = "Music collection manager";
|
||||||
|
icon = "lidarr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
sonarr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "sonarr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 8989;
|
||||||
|
homepage = {
|
||||||
|
name = "Sonarr";
|
||||||
|
description = "Internet PVR for Usenet and Torrents";
|
||||||
|
icon = "sonarr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
radarr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "radarr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 7878;
|
||||||
|
homepage = {
|
||||||
|
name = "Radarr";
|
||||||
|
description = "Movie collection manager";
|
||||||
|
icon = "radarr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
jellyseerr = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "jellyseerr";
|
||||||
|
exposure = "local";
|
||||||
|
port = 5055;
|
||||||
|
homepage = {
|
||||||
|
name = "Jellyseerr";
|
||||||
|
description = "Media request and discovery manager";
|
||||||
|
icon = "jellyseerr.svg";
|
||||||
|
category = "Arr";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
jellyfin = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "fin";
|
||||||
|
exposure = "tailscale";
|
||||||
|
port = 8096;
|
||||||
|
homepage = {
|
||||||
|
name = "Jellyfin";
|
||||||
|
description = "The Free Software Media System";
|
||||||
|
icon = "jellyfin.svg";
|
||||||
|
category = "Media";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
uptime-kuma = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "uptime";
|
||||||
|
exposure = "local";
|
||||||
|
port = 3001;
|
||||||
|
homepage = {
|
||||||
|
name = "Uptime Kuma";
|
||||||
|
description = "Service monitoring tool";
|
||||||
|
icon = "uptime-kuma.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
gitea = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "git";
|
||||||
|
exposure = "tunnel";
|
||||||
|
port = 5003;
|
||||||
|
cloudflared = {
|
||||||
|
tunnelId = "33e2fb8e-ecef-4d42-b845-6d15e216e448";
|
||||||
|
credentialsFile = config.age.secrets.giteaCloudflared.path;
|
||||||
|
};
|
||||||
|
homepage = {
|
||||||
|
name = "Gitea";
|
||||||
|
description = "Git with a cup of tea";
|
||||||
|
icon = "gitea.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "vault";
|
||||||
|
exposure = "tunnel";
|
||||||
|
port = 8222;
|
||||||
|
cloudflared = {
|
||||||
|
tunnelId = "fdd98086-6a4c-44f2-bba0-eb86b833cce5";
|
||||||
|
credentialsFile = config.age.secrets.vaultwardenCloudflared.path;
|
||||||
|
};
|
||||||
|
homepage = {
|
||||||
|
name = "Vaultwarden";
|
||||||
|
description = "Password manager";
|
||||||
|
icon = "vaultwarden-light.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
nextcloud = {
|
||||||
|
enable = true;
|
||||||
|
subdomain = "cloud";
|
||||||
|
exposure = "local";
|
||||||
|
port = 8182;
|
||||||
|
homepage = {
|
||||||
|
name = "Nextcloud";
|
||||||
|
description = "A safe home for all your data";
|
||||||
|
icon = "nextcloud.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
|
||||||
fail2ban = {
|
|
||||||
enable = true;
|
|
||||||
apiKeyFile = config.age.secrets.cloudflareFirewallApiKey.path;
|
|
||||||
zoneId = "0027acdfb8bbe010f55b676ad8698dfb";
|
|
||||||
};
|
|
||||||
syncthing = {
|
|
||||||
enable = false;
|
|
||||||
};
|
|
||||||
keepalived = {
|
|
||||||
enable = true;
|
|
||||||
interface = "enp6s0";
|
|
||||||
};
|
|
||||||
podman = {
|
|
||||||
enable = true;
|
|
||||||
gluetun.enable = true;
|
|
||||||
qbittorrent = {
|
qbittorrent = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
subdomain = "qbt";
|
||||||
|
exposure = "local";
|
||||||
port = 8080;
|
port = 8080;
|
||||||
|
homepage = {
|
||||||
|
name = "qBittorrent";
|
||||||
|
description = "Torrent client";
|
||||||
|
icon = "qbittorrent.svg";
|
||||||
|
category = "Downloads";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
slskd = {
|
slskd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
subdomain = "slskd";
|
||||||
|
exposure = "local";
|
||||||
|
port = 5030;
|
||||||
|
homepage = {
|
||||||
|
name = "Soulseek";
|
||||||
|
description = "Web-based Soulseek client";
|
||||||
|
icon = "slskd.svg";
|
||||||
|
category = "Downloads";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
pihole = {
|
pihole = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
subdomain = "pihole";
|
||||||
|
exposure = "local";
|
||||||
port = 8053;
|
port = 8053;
|
||||||
|
homepage = {
|
||||||
|
name = "PiHole";
|
||||||
|
description = "Adblocking and DNS service";
|
||||||
|
icon = "pi-hole.svg";
|
||||||
|
category = "Services";
|
||||||
|
path = "/admin";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -4,6 +4,10 @@
|
|||||||
username = "cnst";
|
username = "cnst";
|
||||||
mail = "adam@cnst.dev";
|
mail = "adam@cnst.dev";
|
||||||
sshUser = "sobotka";
|
sshUser = "sobotka";
|
||||||
|
domains = {
|
||||||
|
local = "cnix.dev";
|
||||||
|
public = "cnst.dev";
|
||||||
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
name = "DVI-D-1";
|
name = "DVI-D-1";
|
||||||
width = 1920;
|
width = 1920;
|
||||||
height = 1080;
|
height = 1080;
|
||||||
refreshRate = 144;
|
refreshRate = "144";
|
||||||
position = "0x0";
|
position = "0x0";
|
||||||
transform = 0;
|
transform = 0;
|
||||||
workspace = "1";
|
workspace = "1";
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
{ config, ... }:
|
{config, ...}: {
|
||||||
{
|
|
||||||
server = {
|
server = {
|
||||||
enable = true;
|
enable = true;
|
||||||
email = "adam@cnst.dev";
|
email = "adam@cnst.dev";
|
||||||
@@ -12,9 +11,6 @@
|
|||||||
unbound = {
|
unbound = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
caddy = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
homepage-dashboard = {
|
homepage-dashboard = {
|
||||||
enable = false;
|
enable = false;
|
||||||
};
|
};
|
||||||
|
|||||||
26
lib/server/default.nix
Normal file
26
lib/server/default.nix
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{lib}: let
|
||||||
|
server = {
|
||||||
|
mkDomain = config: service: let
|
||||||
|
localDomain = config.settings.accounts.domains.local;
|
||||||
|
publicDomain = config.settings.accounts.domains.public;
|
||||||
|
tailscaleDomain = "ts.${publicDomain}";
|
||||||
|
in
|
||||||
|
if service.exposure == "tunnel"
|
||||||
|
then publicDomain
|
||||||
|
else if service.exposure == "tailscale"
|
||||||
|
then tailscaleDomain
|
||||||
|
else localDomain;
|
||||||
|
|
||||||
|
mkFullDomain = config: service: let
|
||||||
|
domain = server.mkDomain config service;
|
||||||
|
in "${service.subdomain}.${domain}";
|
||||||
|
|
||||||
|
mkHostDomain = config: service: let
|
||||||
|
domain = server.mkDomain config service;
|
||||||
|
in "${domain}";
|
||||||
|
|
||||||
|
mkSubDomain = config: service: "${service.subdomain}";
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
server = server;
|
||||||
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
lib: {
|
lib: {
|
||||||
bgs = rec {
|
bgs = rec {
|
||||||
files = {
|
files = {
|
||||||
wallpaper_1 = "~/media/images/bg_1.jpg";
|
wallpaper_1 = "~/media/images/bgs/bg_1.jpg";
|
||||||
wallpaper_2 = "~/media/images/bg_2.jpg";
|
wallpaper_2 = "~/media/images/bgs/bg_2.jpg";
|
||||||
wallpaper_3 = "~/media/images/bg_3.jpg";
|
wallpaper_3 = "~/media/images/bgs/bg_3.jpg";
|
||||||
wallpaper_4 = "~/media/images/waterwindow.jpg";
|
wallpaper_4 = "~/media/images/bgs/waterwindow.jpg";
|
||||||
wallpaper_5 = "~/media/images/barngreet.png";
|
wallpaper_5 = "~/media/images/bgs/barngreet.png";
|
||||||
};
|
};
|
||||||
|
|
||||||
list = builtins.attrNames files;
|
list = builtins.attrNames files;
|
||||||
|
|||||||
@@ -97,10 +97,9 @@
|
|||||||
./nixos/services/greetd
|
./nixos/services/greetd
|
||||||
./nixos/services/gvfs
|
./nixos/services/gvfs
|
||||||
./nixos/services/kanata
|
./nixos/services/kanata
|
||||||
./nixos/services/libvirtd
|
./nixos/services/virtualisation
|
||||||
./nixos/services/locate
|
./nixos/services/locate
|
||||||
./nixos/services/mullvad
|
./nixos/services/mullvad
|
||||||
./nixos/services/mullvad-netns
|
|
||||||
./nixos/services/nfs
|
./nixos/services/nfs
|
||||||
./nixos/services/nix-ld
|
./nixos/services/nix-ld
|
||||||
./nixos/services/openssh
|
./nixos/services/openssh
|
||||||
@@ -114,6 +113,7 @@
|
|||||||
./nixos/services/udisks
|
./nixos/services/udisks
|
||||||
./nixos/services/xserver
|
./nixos/services/xserver
|
||||||
./nixos/services/zram
|
./nixos/services/zram
|
||||||
|
./nixos/services/tailscale
|
||||||
|
|
||||||
./nixos/system/fonts
|
./nixos/system/fonts
|
||||||
./nixos/system/locale
|
./nixos/system/locale
|
||||||
@@ -123,24 +123,6 @@
|
|||||||
server = {
|
server = {
|
||||||
imports = [
|
imports = [
|
||||||
./server
|
./server
|
||||||
./server/caddy
|
|
||||||
./server/fail2ban
|
|
||||||
./server/homepage-dashboard
|
|
||||||
./server/vaultwarden
|
|
||||||
./server/bazarr
|
|
||||||
./server/prowlarr
|
|
||||||
./server/lidarr
|
|
||||||
./server/radarr
|
|
||||||
./server/sonarr
|
|
||||||
./server/syncthing
|
|
||||||
./server/jellyseerr
|
|
||||||
./server/jellyfin
|
|
||||||
./server/podman
|
|
||||||
./server/unbound
|
|
||||||
./server/uptime-kuma
|
|
||||||
./server/keepalived
|
|
||||||
./server/gitea
|
|
||||||
./server/postgres
|
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
settings = {
|
settings = {
|
||||||
|
|||||||
@@ -14,36 +14,37 @@ in
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
programs.alacritty = {
|
programs.alacritty = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
theme = "gruvbox_material_hard_dark";
|
||||||
settings = {
|
settings = {
|
||||||
# Default colors
|
# Default colors
|
||||||
colors.primary = {
|
# colors = {
|
||||||
background = "#282828";
|
# primary = {
|
||||||
foreground = "#d4be98";
|
# background = "#282828";
|
||||||
};
|
# foreground = "#d4be98";
|
||||||
colors = {
|
# };
|
||||||
# Normal colors
|
# # Normal colors
|
||||||
normal = {
|
# normal = {
|
||||||
black = "#3c3836";
|
# black = "#3c3836";
|
||||||
red = "#ea6962";
|
# red = "#ea6962";
|
||||||
green = "#a9b665";
|
# green = "#a9b665";
|
||||||
yellow = "#d8a657";
|
# yellow = "#d8a657";
|
||||||
blue = "#7daea3";
|
# blue = "#7daea3";
|
||||||
magenta = "#d3869b";
|
# magenta = "#d3869b";
|
||||||
cyan = "#89b482";
|
# cyan = "#89b482";
|
||||||
white = "#d4be98";
|
# white = "#d4be98";
|
||||||
};
|
# };
|
||||||
# Bright colors (same as normal colors)
|
# # Bright colors (same as normal colors)
|
||||||
bright = {
|
# bright = {
|
||||||
black = "#3c3836";
|
# black = "#3c3836";
|
||||||
red = "#ea6962";
|
# red = "#ea6962";
|
||||||
green = "#a9b665";
|
# green = "#a9b665";
|
||||||
yellow = "#d8a657";
|
# yellow = "#d8a657";
|
||||||
blue = "#7daea3";
|
# blue = "#7daea3";
|
||||||
magenta = "#d3869b";
|
# magenta = "#d3869b";
|
||||||
cyan = "#89b482";
|
# cyan = "#89b482";
|
||||||
white = "#d4be98";
|
# white = "#d4be98";
|
||||||
};
|
# };
|
||||||
};
|
# };
|
||||||
font = {
|
font = {
|
||||||
size = 12;
|
size = 12;
|
||||||
normal = {
|
normal = {
|
||||||
@@ -73,7 +74,7 @@ in
|
|||||||
];
|
];
|
||||||
window = {
|
window = {
|
||||||
dynamic_title = true;
|
dynamic_title = true;
|
||||||
opacity = 0.9;
|
opacity = 0.95;
|
||||||
padding = {
|
padding = {
|
||||||
x = 5;
|
x = 5;
|
||||||
y = 5;
|
y = 5;
|
||||||
|
|||||||
@@ -6,8 +6,9 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
inherit (lib.meta) getExe;
|
packageNames = map (p: p.pname or p.name or null) config.home.packages;
|
||||||
inherit (pkgs) eza bat;
|
hasPackage = name: lib.any (x: x == name) packageNames;
|
||||||
|
hasEza = hasPackage "eza";
|
||||||
cfg = config.home.programs.fish;
|
cfg = config.home.programs.fish;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
@@ -28,7 +29,9 @@ in
|
|||||||
nixclean = "nh clean all --keep 3";
|
nixclean = "nh clean all --keep 3";
|
||||||
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
||||||
nixup = "nh os switch -H $hostname";
|
nixup = "nh os switch -H $hostname";
|
||||||
nixupv = "nh os switch -v -H $hostname";
|
nixupn = "nh os switch -n -H $hostname";
|
||||||
|
nixupv = "nh os switch -v --show-trace -H $hostname";
|
||||||
|
nixupvn = "nh os switch -n -v --show-trace -H $hostname";
|
||||||
flakeup = "nix flake update";
|
flakeup = "nix flake update";
|
||||||
};
|
};
|
||||||
shellAliases = {
|
shellAliases = {
|
||||||
@@ -44,12 +47,8 @@ in
|
|||||||
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
||||||
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||||
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||||
tree = "${getExe eza} --tree --icons=always";
|
ls = mkIf hasEza "eza";
|
||||||
cat = "${getExe bat} --style=plain";
|
tree = mkIf hasEza "eza --tree --icons=always";
|
||||||
ls = "${getExe eza} -h --git --icons --color=auto --group-directories-first -s extension";
|
|
||||||
ll = "${getExe eza} -l --git --icons --color=auto --group-directories-first -s extension";
|
|
||||||
lat = "${getExe eza} -lah --tree --color=auto --group-directories-first -s extension";
|
|
||||||
la = "${getExe eza} -lah --color=auto --group-directories-first -s extension";
|
|
||||||
# Clear screen and scrollback
|
# Clear screen and scrollback
|
||||||
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
||||||
};
|
};
|
||||||
@@ -59,14 +58,12 @@ in
|
|||||||
# Merge history when pressing up
|
# Merge history when pressing up
|
||||||
up-or-search = lib.readFile ./up-or-search.fish;
|
up-or-search = lib.readFile ./up-or-search.fish;
|
||||||
# Check stuff in PATH
|
# Check stuff in PATH
|
||||||
nix-inspect =
|
nix-inspect = # fish
|
||||||
# fish
|
|
||||||
''
|
''
|
||||||
set -s PATH | grep "PATH\[.*/nix/store" | cut -d '|' -f2 | grep -v -e "-man" -e "-terminfo" | perl -pe 's:^/nix/store/\w{32}-([^/]*)/bin$:\1:' | sort | uniq
|
set -s PATH | grep "PATH\[.*/nix/store" | cut -d '|' -f2 | grep -v -e "-man" -e "-terminfo" | perl -pe 's:^/nix/store/\w{32}-([^/]*)/bin$:\1:' | sort | uniq
|
||||||
'';
|
'';
|
||||||
};
|
};
|
||||||
interactiveShellInit =
|
interactiveShellInit = # fish
|
||||||
# fish
|
|
||||||
''
|
''
|
||||||
# Open command buffer in vim when alt+e is pressed
|
# Open command buffer in vim when alt+e is pressed
|
||||||
bind \ee edit_command_buffer
|
bind \ee edit_command_buffer
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ in
|
|||||||
enableFishIntegration = config.programs.fish.enable;
|
enableFishIntegration = config.programs.fish.enable;
|
||||||
enableZshIntegration = config.programs.zsh.enable;
|
enableZshIntegration = config.programs.zsh.enable;
|
||||||
settings = {
|
settings = {
|
||||||
theme = "GruvboxDarkHard";
|
theme = "Gruvbox Dark Hard";
|
||||||
focus-follows-mouse = true;
|
focus-follows-mouse = true;
|
||||||
resize-overlay = "never";
|
resize-overlay = "never";
|
||||||
background-opacity = 0.95;
|
background-opacity = 0.95;
|
||||||
|
|||||||
@@ -15,47 +15,54 @@ in
|
|||||||
};
|
};
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
home.packages = [ pkgs.gh ];
|
home.packages = [ pkgs.gh ];
|
||||||
programs.git = {
|
programs = {
|
||||||
enable = true;
|
git = {
|
||||||
userName = osConfig.settings.accounts.username;
|
enable = true;
|
||||||
userEmail = osConfig.settings.accounts.mail;
|
settings = {
|
||||||
|
# user.signingkey = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
|
||||||
|
user = {
|
||||||
|
name = osConfig.settings.accounts.username;
|
||||||
|
email = osConfig.settings.accounts.mail;
|
||||||
|
signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
|
||||||
|
};
|
||||||
|
signing = {
|
||||||
|
format = lib.mkDefault "ssh";
|
||||||
|
key = "${config.home.homeDirectory}/.ssh/id_ed25519";
|
||||||
|
signByDefault = true;
|
||||||
|
};
|
||||||
|
gpg = {
|
||||||
|
# format = lib.mkDefault "ssh";
|
||||||
|
ssh.allowedSignersFile =
|
||||||
|
config.home.homeDirectory + "/" + config.xdg.configFile."git/allowed_signers".target;
|
||||||
|
};
|
||||||
|
commit = {
|
||||||
|
verbose = true;
|
||||||
|
gpgSign = false;
|
||||||
|
};
|
||||||
|
init.defaultBranch = "main";
|
||||||
|
merge.conflictStyle = "diff3";
|
||||||
|
diff.algorithm = "histogram";
|
||||||
|
log.date = "iso";
|
||||||
|
column.ui = "auto";
|
||||||
|
branch.sort = "committerdate";
|
||||||
|
push.autoSetupRemote = true;
|
||||||
|
rerere.enabled = true;
|
||||||
|
};
|
||||||
|
lfs.enable = true;
|
||||||
|
ignores = [
|
||||||
|
".direnv"
|
||||||
|
"result"
|
||||||
|
".jj"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
delta = {
|
delta = {
|
||||||
|
enableGitIntegration = true;
|
||||||
enable = true;
|
enable = true;
|
||||||
options.dark = true;
|
options.dark = true;
|
||||||
};
|
};
|
||||||
extraConfig = {
|
|
||||||
# user.signingkey = "${config.home.homeDirectory}/.ssh/id_ed25519.pub";
|
|
||||||
user.signingkey = "${config.home.homeDirectory}/.config/git/allowed_signers";
|
|
||||||
signing = {
|
|
||||||
format = lib.mkDefault "ssh";
|
|
||||||
key = "${config.home.homeDirectory}/.ssh/id_ed25519";
|
|
||||||
signByDefault = true;
|
|
||||||
};
|
|
||||||
gpg = {
|
|
||||||
# format = lib.mkDefault "ssh";
|
|
||||||
ssh.allowedSignersFile =
|
|
||||||
config.home.homeDirectory + "/" + config.xdg.configFile."git/allowed_signers".target;
|
|
||||||
};
|
|
||||||
commit = {
|
|
||||||
verbose = true;
|
|
||||||
gpgSign = false;
|
|
||||||
};
|
|
||||||
init.defaultBranch = "main";
|
|
||||||
merge.conflictStyle = "diff3";
|
|
||||||
diff.algorithm = "histogram";
|
|
||||||
log.date = "iso";
|
|
||||||
column.ui = "auto";
|
|
||||||
branch.sort = "committerdate";
|
|
||||||
push.autoSetupRemote = true;
|
|
||||||
rerere.enabled = true;
|
|
||||||
};
|
|
||||||
lfs.enable = true;
|
|
||||||
ignores = [
|
|
||||||
".direnv"
|
|
||||||
"result"
|
|
||||||
".jj"
|
|
||||||
];
|
|
||||||
};
|
};
|
||||||
|
|
||||||
xdg.configFile."git/allowed_signers".text = ''
|
xdg.configFile."git/allowed_signers".text = ''
|
||||||
${osConfig.settings.accounts.mail} namespaces="git" ${osConfig.settings.accounts.sshKey}
|
${osConfig.settings.accounts.mail} namespaces="git" ${osConfig.settings.accounts.sshKey}
|
||||||
'';
|
'';
|
||||||
|
|||||||
@@ -1,26 +1,20 @@
|
|||||||
{
|
{
|
||||||
inputs,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
lib,
|
||||||
osConfig,
|
osConfig,
|
||||||
cLib,
|
clib,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf;
|
||||||
cfg = osConfig.nixos.programs.hyprland;
|
cfg = osConfig.nixos.programs.hyprland;
|
||||||
|
|
||||||
hyprlockFlake = inputs.hyprlock.packages.${pkgs.system}.hyprlock;
|
|
||||||
# hyprlockPkg = pkgs.hyprlock;
|
|
||||||
#
|
|
||||||
bg = osConfig.settings.theme.background;
|
bg = osConfig.settings.theme.background;
|
||||||
inherit (cLib.theme.bgs) resolve;
|
inherit (clib.theme.bgs) resolve;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
programs.hyprlock = {
|
programs.hyprlock = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = hyprlockFlake;
|
|
||||||
settings = {
|
settings = {
|
||||||
general = {
|
general = {
|
||||||
# disable_loading_bar = true;
|
# disable_loading_bar = true;
|
||||||
@@ -60,6 +54,7 @@ in
|
|||||||
position = "0, 20";
|
position = "0, 20";
|
||||||
halign = "center";
|
halign = "center";
|
||||||
valign = "center";
|
valign = "center";
|
||||||
|
font_family = "DepartureMono Nerd Font Mono Italic";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
label = [
|
label = [
|
||||||
@@ -71,7 +66,7 @@ in
|
|||||||
shadow_boost = 0.5;
|
shadow_boost = 0.5;
|
||||||
color = "rgba(FFFFFFFF)";
|
color = "rgba(FFFFFFFF)";
|
||||||
font_size = 25;
|
font_size = 25;
|
||||||
font_family = "Input Mono Compressed";
|
font_family = "DepartureMono Nerd Font Mono Regular";
|
||||||
position = "0, 230";
|
position = "0, 230";
|
||||||
halign = "center";
|
halign = "center";
|
||||||
valign = "center";
|
valign = "center";
|
||||||
@@ -84,7 +79,7 @@ in
|
|||||||
shadow_boost = 0.5;
|
shadow_boost = 0.5;
|
||||||
color = "rgba(FFFFFFFF)";
|
color = "rgba(FFFFFFFF)";
|
||||||
font_size = 85;
|
font_size = 85;
|
||||||
font_family = "Input Mono Compressed";
|
font_family = "DepartureMono Nerd Font Mono Regular";
|
||||||
position = "0, 300";
|
position = "0, 300";
|
||||||
halign = "center";
|
halign = "center";
|
||||||
valign = "center";
|
valign = "center";
|
||||||
|
|||||||
@@ -7,6 +7,9 @@
|
|||||||
let
|
let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
cfg = config.home.programs.mpv;
|
cfg = config.home.programs.mpv;
|
||||||
|
inherit (config.xdg.userDirs) videos;
|
||||||
|
inherit (config.home) homeDirectory;
|
||||||
|
shaders_dir = "${pkgs.mpv-shim-default-shaders}/share/mpv-shim-default-shaders/shaders";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
@@ -15,8 +18,71 @@ in
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
programs.mpv = {
|
programs.mpv = {
|
||||||
enable = true;
|
enable = true;
|
||||||
defaultProfiles = [ "gpu-hq" ];
|
config = {
|
||||||
scripts = [ pkgs.mpvScripts.mpris ];
|
profile = "gpu-hq";
|
||||||
|
gpu-context = "wayland";
|
||||||
|
vo = "gpu-next";
|
||||||
|
video-sync = "display-resample";
|
||||||
|
interpolation = true;
|
||||||
|
tscale = "oversample";
|
||||||
|
fullscreen = false;
|
||||||
|
keep-open = true;
|
||||||
|
sub-auto = "fuzzy";
|
||||||
|
sub-font = "Noto Sans Medium";
|
||||||
|
sub-blur = 10;
|
||||||
|
|
||||||
|
screenshot-format = "png";
|
||||||
|
|
||||||
|
title = "\${filename} - mpv";
|
||||||
|
script-opts = "osc-title=\${filename},osc-boxalpha=150,osc-visibility=never,osc-boxvideo=yes";
|
||||||
|
ytdl-format = "bestvideo[height<=?1440]+bestaudio/best";
|
||||||
|
ao = "pipewire";
|
||||||
|
alang = "eng,en";
|
||||||
|
slang = "eng,en,enUS";
|
||||||
|
|
||||||
|
glsl-shader = "${homeDirectory}/.config/mpv/shaders/FSR.glsl";
|
||||||
|
scale = "lanczos";
|
||||||
|
cscale = "lanczos";
|
||||||
|
dscale = "mitchell";
|
||||||
|
deband = "yes";
|
||||||
|
scale-antiring = 1;
|
||||||
|
|
||||||
|
osc = "no";
|
||||||
|
osd-on-seek = "no";
|
||||||
|
osd-bar = "no";
|
||||||
|
osd-bar-w = 30;
|
||||||
|
osd-bar-h = "0.2";
|
||||||
|
osd-duration = 750;
|
||||||
|
|
||||||
|
really-quiet = "yes";
|
||||||
|
autofit = "65%";
|
||||||
|
};
|
||||||
|
|
||||||
|
bindings = {
|
||||||
|
"ctrl+a" = "script-message osc-visibility cycle";
|
||||||
|
};
|
||||||
|
scripts = with pkgs.mpvScripts; [
|
||||||
|
mpris
|
||||||
|
uosc
|
||||||
|
thumbfast
|
||||||
|
sponsorblock
|
||||||
|
autocrop
|
||||||
|
];
|
||||||
|
};
|
||||||
|
programs.yt-dlp = {
|
||||||
|
enable = true;
|
||||||
|
extraConfig = ''
|
||||||
|
-o ${videos}/youtube/%(title)s.%(ext)s
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
home = {
|
||||||
|
file = {
|
||||||
|
".config/mpv/shaders/FSR.glsl".source = "${shaders_dir}/FSR.glsl";
|
||||||
|
};
|
||||||
|
packages = with pkgs; [
|
||||||
|
jellyfin-mpv-shim
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -62,16 +62,8 @@ in
|
|||||||
[
|
[
|
||||||
cmatrix
|
cmatrix
|
||||||
xcur2png
|
xcur2png
|
||||||
ripgrep
|
|
||||||
file
|
|
||||||
fd
|
|
||||||
gnused
|
|
||||||
nix-tree
|
nix-tree
|
||||||
wireguard-tools
|
wireguard-tools
|
||||||
unzip
|
|
||||||
zip
|
|
||||||
gnutar
|
|
||||||
p7zip
|
|
||||||
]
|
]
|
||||||
|
|
||||||
(mkIf cfg.common.enable [
|
(mkIf cfg.common.enable [
|
||||||
@@ -88,7 +80,7 @@ in
|
|||||||
hyprpicker
|
hyprpicker
|
||||||
libnotify
|
libnotify
|
||||||
pamixer
|
pamixer
|
||||||
oculante
|
loupe
|
||||||
adwaita-icon-theme
|
adwaita-icon-theme
|
||||||
qt5.qtwayland
|
qt5.qtwayland
|
||||||
qt6.qtwayland
|
qt6.qtwayland
|
||||||
|
|||||||
@@ -1,21 +1,26 @@
|
|||||||
[
|
[
|
||||||
{
|
{
|
||||||
|
"height": 25,
|
||||||
|
"layer": "top",
|
||||||
|
"output": [
|
||||||
|
"DP-3",
|
||||||
|
"eDP-1"
|
||||||
|
],
|
||||||
"modules-left": [
|
"modules-left": [
|
||||||
"group/system"
|
"group/system"
|
||||||
],
|
],
|
||||||
"modules-center": [
|
"modules-center": [
|
||||||
"niri/workspaces"
|
"hyprland/workspaces"
|
||||||
],
|
],
|
||||||
"modules-right": [
|
"modules-right": [
|
||||||
"custom/progress",
|
"custom/progress",
|
||||||
"custom/systemd",
|
"custom/systemd",
|
||||||
"group/tray",
|
|
||||||
"pulseaudio",
|
"pulseaudio",
|
||||||
"backlight",
|
"backlight",
|
||||||
"battery",
|
"battery",
|
||||||
"date",
|
"group/tray",
|
||||||
"clock",
|
"custom/dunst",
|
||||||
"custom/dunst"
|
"clock"
|
||||||
],
|
],
|
||||||
"backlight": {
|
"backlight": {
|
||||||
"format": "<span foreground='#928374'>{icon}</span> {percent}%",
|
"format": "<span foreground='#928374'>{icon}</span> {percent}%",
|
||||||
@@ -42,18 +47,9 @@
|
|||||||
"clock": {
|
"clock": {
|
||||||
"interval": 60,
|
"interval": 60,
|
||||||
"format": "{:%H:%M}",
|
"format": "{:%H:%M}",
|
||||||
// "on-click": "calcurse-toggle.sh",
|
|
||||||
// "on-click-right": "calsync.sh",
|
|
||||||
"rotate": 0,
|
"rotate": 0,
|
||||||
"tooltip": false
|
"tooltip": false
|
||||||
},
|
},
|
||||||
// "date": {
|
|
||||||
// "format": "<span foreground='#928374'></span> {%a, %d %b}",
|
|
||||||
// "on-click": "calcurse-toggle.sh",
|
|
||||||
// "on-click-right": "calsync.sh",
|
|
||||||
// "rotate": 0,
|
|
||||||
// "tooltip": false
|
|
||||||
// },
|
|
||||||
"cpu": {
|
"cpu": {
|
||||||
"format": "<span foreground='#928374'></span> {usage}%",
|
"format": "<span foreground='#928374'></span> {usage}%",
|
||||||
"states": {
|
"states": {
|
||||||
@@ -125,37 +121,43 @@
|
|||||||
],
|
],
|
||||||
"orientation": "inherit"
|
"orientation": "inherit"
|
||||||
},
|
},
|
||||||
"height": 25,
|
|
||||||
"hyprland/workspaces": {
|
"hyprland/workspaces": {
|
||||||
"active-only": false,
|
"active-only": false,
|
||||||
"all-outputs": false,
|
"all-outputs": false,
|
||||||
"format": "{icon}",
|
"format": "{icon}",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
"urgent": "",
|
"1": "1",
|
||||||
"active": "",
|
"2": "2",
|
||||||
"visible": "",
|
"3": "3",
|
||||||
"default": "",
|
"4": "4",
|
||||||
"empty": ""
|
"5": "5",
|
||||||
|
"6": "6",
|
||||||
|
"7": "7",
|
||||||
|
"8": "8",
|
||||||
|
"9": "9",
|
||||||
|
"default": "_",
|
||||||
|
"active": "_"
|
||||||
},
|
},
|
||||||
"on-click": "activate",
|
"on-click": "activate",
|
||||||
"show-special": false,
|
"show-special": false,
|
||||||
"on-scroll-up": "hyprctl dispatch workspace r-1",
|
"on-scroll-up": "hyprctl dispatch workspace r-1",
|
||||||
"on-scroll-down": "hyprctl dispatch workspace r+1",
|
"on-scroll-down": "hyprctl dispatch workspace r+1",
|
||||||
"persistent-workspaces": {
|
"persistent-workspaces": {
|
||||||
"*": 3
|
"1": [],
|
||||||
|
"2": [],
|
||||||
|
"3": [],
|
||||||
|
"4": [],
|
||||||
|
"5": []
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"niri/workspaces": {
|
"niri/workspaces": {
|
||||||
"format": "{icon}",
|
"format": "{icon}",
|
||||||
"format-icons": {
|
"format-icons": {
|
||||||
// Named workspaces
|
|
||||||
// (you need to configure them in niri)
|
|
||||||
"browser": "",
|
"browser": "",
|
||||||
"discord": "",
|
"discord": "",
|
||||||
"chat": "<b></b>",
|
"chat": "<b></b>",
|
||||||
// Icons by state
|
"active": "",
|
||||||
"active": "",
|
"default": ""
|
||||||
"default": ""
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"memory": {
|
"memory": {
|
||||||
@@ -173,10 +175,6 @@
|
|||||||
"interval": 2,
|
"interval": 2,
|
||||||
"tooltip-format": "{ifname}: {ipaddr}/{cidr}\n {bandwidthDownBits}\n {bandwidthUpBits}"
|
"tooltip-format": "{ifname}: {ipaddr}/{cidr}\n {bandwidthDownBits}\n {bandwidthUpBits}"
|
||||||
},
|
},
|
||||||
"output": [
|
|
||||||
"DP-3",
|
|
||||||
"eDP-1"
|
|
||||||
],
|
|
||||||
"pulseaudio": {
|
"pulseaudio": {
|
||||||
"format": "<span foreground='#928374'>{icon}</span> {volume}% {format_source}",
|
"format": "<span foreground='#928374'>{icon}</span> {volume}% {format_source}",
|
||||||
"format-bluetooth": "<span foreground='#928374'>{icon}</span> {volume}% {format_source}",
|
"format-bluetooth": "<span foreground='#928374'>{icon}</span> {volume}% {format_source}",
|
||||||
|
|||||||
@@ -2,14 +2,25 @@
|
|||||||
all: unset;
|
all: unset;
|
||||||
border: none;
|
border: none;
|
||||||
border-radius: 0;
|
border-radius: 0;
|
||||||
font-family: "DepartureMono Nerd Font", "Font Awesome 6 Free Solid";
|
font-family:
|
||||||
font-size: 14px;
|
"DepartureMono Nerd Font", "Input Sans Compressed",
|
||||||
|
"Font Awesome 6 Free Solid";
|
||||||
|
font-size: 15px;
|
||||||
min-height: 0;
|
min-height: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
window#waybar {
|
window#waybar {
|
||||||
color: #fbf1c7;
|
color: #fbf1c7;
|
||||||
background-color: rgba(43, 45, 50, 0.6);
|
background-color: rgba(43, 45, 50, 0.5);
|
||||||
|
}
|
||||||
|
|
||||||
|
tooltip {
|
||||||
|
background: rgba(50, 50, 50, 0.9);
|
||||||
|
border: 1px solid rgba(100, 114, 125, 0.6);
|
||||||
|
}
|
||||||
|
tooltip label {
|
||||||
|
color: #fbf1c7;
|
||||||
|
font-family: "Input Sans Compressed";
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button {
|
#workspaces button {
|
||||||
@@ -17,20 +28,16 @@ window#waybar {
|
|||||||
margin: 0 0px;
|
margin: 0 0px;
|
||||||
background-color: transparent;
|
background-color: transparent;
|
||||||
color: #fbf1c7;
|
color: #fbf1c7;
|
||||||
border-top: 3px solid transparent;
|
border-top: 4px solid transparent;
|
||||||
border-bottom: 3px solid transparent;
|
border-bottom: 4px solid transparent;
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button:hover {
|
#workspaces button:hover {
|
||||||
color: #ebdbb2;
|
color: #ebdbb2;
|
||||||
animation: ws_active 0s ease-in-out 1;
|
|
||||||
transition: all 0.2s cubic-bezier(0.55, -0.68, 0.48, 1.682);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#workspaces button.active {
|
#workspaces button.active {
|
||||||
color: #fbf1c7;
|
color: #fbf1c7;
|
||||||
animation: ws_active 0s ease-in-out 1;
|
|
||||||
transition: all 0.2s cubic-bezier(0.55, -0.68, 0.48, 1.682);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#custom-logo {
|
#custom-logo {
|
||||||
@@ -38,7 +45,7 @@ window#waybar {
|
|||||||
background-image: url("assets/button.svg");
|
background-image: url("assets/button.svg");
|
||||||
background-position: center;
|
background-position: center;
|
||||||
background-repeat: no-repeat;
|
background-repeat: no-repeat;
|
||||||
background-size: 18px 15px;
|
background-size: 21px 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#custom-trayicon {
|
#custom-trayicon {
|
||||||
@@ -87,13 +94,14 @@ window#waybar {
|
|||||||
#memory,
|
#memory,
|
||||||
#backlight,
|
#backlight,
|
||||||
#battery,
|
#battery,
|
||||||
#date,
|
#date {
|
||||||
#clock {
|
|
||||||
padding: 0 3px;
|
padding: 0 3px;
|
||||||
margin: 0 3px;
|
margin: 0 3px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#clock {
|
#clock {
|
||||||
|
padding: 0px 3px;
|
||||||
|
margin: 0px 6px 0px 0px;
|
||||||
font-family: "DepartureMono Nerd Font";
|
font-family: "DepartureMono Nerd Font";
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -132,12 +140,17 @@ window#waybar {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#tray menu * {
|
#tray menu * {
|
||||||
background-color: rgba(50, 48, 47, 0.9);
|
background: rgba(50, 50, 50, 0.9);
|
||||||
|
color: #fbf1c7;
|
||||||
font-family: "Input Sans Compressed";
|
font-family: "Input Sans Compressed";
|
||||||
padding: 2px 2px;
|
padding: 2px 2px;
|
||||||
}
|
}
|
||||||
|
|
||||||
#tray menu menuitem:hover {
|
#tray menu {
|
||||||
|
border: 1px solid rgba(100, 114, 125, 0.6);
|
||||||
|
}
|
||||||
|
|
||||||
|
#tray menu item:hover {
|
||||||
color: #4c7a5d;
|
color: #4c7a5d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,10 @@ in
|
|||||||
};
|
};
|
||||||
gtk = {
|
gtk = {
|
||||||
enable = true;
|
enable = true;
|
||||||
theme = {
|
# theme = {
|
||||||
package = pkgs.orchis-theme;
|
# package = pkgs.orchis-theme;
|
||||||
name = "Orchis-Grey-Dark-Compact";
|
# name = "Orchis-Grey-Dark-Compact";
|
||||||
};
|
# };
|
||||||
iconTheme = {
|
iconTheme = {
|
||||||
# package = pkgs.adwaita-icon-theme;
|
# package = pkgs.adwaita-icon-theme;
|
||||||
package = pkgs.papirus-icon-theme;
|
package = pkgs.papirus-icon-theme;
|
||||||
|
|||||||
@@ -1,22 +1,14 @@
|
|||||||
{
|
{
|
||||||
osConfig,
|
osConfig,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
|
||||||
inputs,
|
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf;
|
||||||
cfg = osConfig.nixos.programs.hyprland;
|
cfg = osConfig.nixos.programs.hyprland;
|
||||||
|
in {
|
||||||
hypridleFlake = inputs.hypridle.packages.${pkgs.system}.hypridle;
|
|
||||||
# hypridlePkg = pkgs.hypridle;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.hypridle = {
|
services.hypridle = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = hypridleFlake;
|
|
||||||
settings = {
|
settings = {
|
||||||
general = {
|
general = {
|
||||||
lock_cmd = "hyprlock";
|
lock_cmd = "hyprlock";
|
||||||
|
|||||||
@@ -1,18 +1,14 @@
|
|||||||
{
|
{
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
|
||||||
inputs,
|
|
||||||
osConfig,
|
osConfig,
|
||||||
cLib,
|
clib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib) mkIf;
|
inherit (lib) mkIf;
|
||||||
|
|
||||||
cfg = osConfig.nixos.programs.hyprland;
|
cfg = osConfig.nixos.programs.hyprland;
|
||||||
hyprpaperFlake = inputs.hyprpaper.packages.${pkgs.system}.default;
|
|
||||||
bg = osConfig.settings.theme.background;
|
bg = osConfig.settings.theme.background;
|
||||||
bgs = cLib.theme.bgs;
|
bgs = clib.theme.bgs;
|
||||||
|
|
||||||
monitorMappings = [
|
monitorMappings = [
|
||||||
{
|
{
|
||||||
@@ -32,12 +28,10 @@ let
|
|||||||
bg = bg.primary;
|
bg = bg.primary;
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
services.hyprpaper = {
|
services.hyprpaper = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = hyprpaperFlake;
|
|
||||||
|
|
||||||
settings = {
|
settings = {
|
||||||
ipc = "on";
|
ipc = "on";
|
||||||
|
|||||||
@@ -84,15 +84,15 @@ in
|
|||||||
"application/pdf" = "org.pwmt.zathura-pdf-mupdf.desktop";
|
"application/pdf" = "org.pwmt.zathura-pdf-mupdf.desktop";
|
||||||
"inode/directory" = "thunar.desktop";
|
"inode/directory" = "thunar.desktop";
|
||||||
|
|
||||||
"image/apng" = "oculante.desktop";
|
"image/apng" = "feh.desktop";
|
||||||
"image/avif" = "oculante.desktop";
|
"image/avif" = "feh.desktop";
|
||||||
"image/bmp" = "oculante.desktop";
|
"image/bmp" = "feh.desktop";
|
||||||
"image/gif" = "oculante.desktop";
|
"image/gif" = "feh.desktop";
|
||||||
"image/jpeg" = "oculante.desktop";
|
"image/jpeg" = "feh.desktop";
|
||||||
"image/png" = "oculante.desktop";
|
"image/png" = "feh.desktop";
|
||||||
"image/svg+xml" = "oculante.desktop";
|
"image/svg+xml" = "feh.desktop";
|
||||||
"image/tiff" = "oculante.desktop";
|
"image/tiff" = "feh.desktop";
|
||||||
"image/webp" = "oculante.desktop";
|
"image/webp" = "feh.desktop";
|
||||||
|
|
||||||
"video/H264" = [
|
"video/H264" = [
|
||||||
"mpv.desktop"
|
"mpv.desktop"
|
||||||
|
|||||||
@@ -5,7 +5,12 @@
|
|||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib) mkOption types;
|
inherit (lib)
|
||||||
|
mkOption
|
||||||
|
types
|
||||||
|
mkEnableOption
|
||||||
|
mkIf
|
||||||
|
;
|
||||||
cfg = config.nixos.boot.kernel;
|
cfg = config.nixos.boot.kernel;
|
||||||
|
|
||||||
hasHardware = hw: builtins.elem hw cfg.hardware;
|
hasHardware = hw: builtins.elem hw cfg.hardware;
|
||||||
@@ -37,8 +42,11 @@ in
|
|||||||
);
|
);
|
||||||
default = [ ];
|
default = [ ];
|
||||||
description = "List of hardware types (e.g. GPU and CPU vendors) to configure kernel settings for.";
|
description = "List of hardware types (e.g. GPU and CPU vendors) to configure kernel settings for.";
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
amdOverdrive.enable = mkEnableOption "Enable AMD pstate/overdrive";
|
||||||
|
|
||||||
extraKernelParams = mkOption {
|
extraKernelParams = mkOption {
|
||||||
type = types.listOf types.str;
|
type = types.listOf types.str;
|
||||||
default = [ ];
|
default = [ ];
|
||||||
@@ -74,7 +82,7 @@ in
|
|||||||
"quiet"
|
"quiet"
|
||||||
"splash"
|
"splash"
|
||||||
]
|
]
|
||||||
++ (if hasHardware "amd" then [ "amd_pstate=active" ] else [ ])
|
++ (if hasHardware "amd" then [ ] else [ ])
|
||||||
++ (if hasHardware "intel" then [ ] else [ ])
|
++ (if hasHardware "intel" then [ ] else [ ])
|
||||||
++ (if hasHardware "nvidia" then [ ] else [ ])
|
++ (if hasHardware "nvidia" then [ ] else [ ])
|
||||||
++ cfg.extraKernelParams;
|
++ cfg.extraKernelParams;
|
||||||
@@ -85,5 +93,6 @@ in
|
|||||||
++ (if hasHardware "nvidia" then [ "nouveau" ] else [ ])
|
++ (if hasHardware "nvidia" then [ "nouveau" ] else [ ])
|
||||||
++ cfg.extraBlacklistedModules;
|
++ cfg.extraBlacklistedModules;
|
||||||
};
|
};
|
||||||
|
hardware.amdgpu.overdrive.enable = mkIf cfg.amdOverdrive.enable true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -19,13 +19,13 @@ let
|
|||||||
|
|
||||||
commonPackages = with pkgs; [
|
commonPackages = with pkgs; [
|
||||||
libva
|
libva
|
||||||
vaapiVdpau
|
libva-vdpau-driver
|
||||||
libvdpau-va-gl
|
libvdpau-va-gl
|
||||||
];
|
];
|
||||||
|
|
||||||
commonPackages32 = with pkgs.pkgsi686Linux; [
|
commonPackages32 = with pkgs.pkgsi686Linux; [
|
||||||
libva
|
libva
|
||||||
vaapiVdpau
|
libva-vdpau-driver
|
||||||
libvdpau-va-gl
|
libvdpau-va-gl
|
||||||
];
|
];
|
||||||
|
|
||||||
@@ -89,37 +89,39 @@ in
|
|||||||
|
|
||||||
config = mkIf cfg.enable (mkMerge [
|
config = mkIf cfg.enable (mkMerge [
|
||||||
{
|
{
|
||||||
hardware.graphics = {
|
hardware = {
|
||||||
enable = true;
|
graphics = {
|
||||||
enable32Bit = true;
|
enable = true;
|
||||||
extraPackages = flatten (
|
enable32Bit = true;
|
||||||
concatMap (
|
extraPackages = flatten (
|
||||||
vendor:
|
concatMap (
|
||||||
if vendor == "amd" then
|
vendor:
|
||||||
commonPackages ++ mesaVulkanPackages
|
if vendor == "amd" then
|
||||||
else if vendor == "intel" then
|
commonPackages ++ mesaVulkanPackages
|
||||||
commonPackages
|
else if vendor == "intel" then
|
||||||
++ mesaVulkanPackages
|
commonPackages
|
||||||
++ (with pkgs; [
|
++ mesaVulkanPackages
|
||||||
vpl-gpu-rt
|
++ (with pkgs; [
|
||||||
intel-media-driver
|
vpl-gpu-rt
|
||||||
intel-compute-runtime
|
intel-media-driver
|
||||||
intel-vaapi-driver
|
intel-compute-runtime
|
||||||
])
|
intel-vaapi-driver
|
||||||
else if vendor == "nvidia" then
|
])
|
||||||
commonPackages
|
else if vendor == "nvidia" then
|
||||||
++ (with pkgs; [
|
commonPackages
|
||||||
nvidiaOffloadScript
|
++ (with pkgs; [
|
||||||
intel-media-driver
|
nvidiaOffloadScript
|
||||||
nvidia-vaapi-driver
|
intel-media-driver
|
||||||
vulkan-tools
|
nvidia-vaapi-driver
|
||||||
])
|
vulkan-tools
|
||||||
else
|
])
|
||||||
[ ]
|
else
|
||||||
) cfg.vendors
|
[ ]
|
||||||
);
|
) cfg.vendors
|
||||||
|
);
|
||||||
|
|
||||||
extraPackages32 = flatten (concatMap (_: commonPackages32) cfg.vendors);
|
extraPackages32 = flatten (concatMap (_: commonPackages32) cfg.vendors);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
environment.systemPackages = flatten (
|
environment.systemPackages = flatten (
|
||||||
@@ -145,10 +147,6 @@ in
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
(mkIf (hasVendor "amd") {
|
|
||||||
hardware.amdgpu.overdrive.enable = true;
|
|
||||||
})
|
|
||||||
|
|
||||||
(mkIf (hasVendor "nvidia") {
|
(mkIf (hasVendor "nvidia") {
|
||||||
hardware.nvidia = {
|
hardware.nvidia = {
|
||||||
package =
|
package =
|
||||||
|
|||||||
@@ -2,38 +2,47 @@
|
|||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
inherit
|
||||||
inherit (lib)
|
(lib)
|
||||||
mkIf
|
mkIf
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkOption
|
mkOption
|
||||||
types
|
types
|
||||||
;
|
;
|
||||||
cfg = config.nixos.hardware.network;
|
cfg = config.nixos.hardware.network;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
nixos.hardware.network = {
|
nixos.hardware.network = {
|
||||||
enable = mkEnableOption "Enable the custom networking module";
|
enable = mkEnableOption "Enable the custom networking module";
|
||||||
|
nameservers = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "The list of nameservers ";
|
||||||
|
};
|
||||||
|
search = mkOption {
|
||||||
|
type = types.listOf types.str;
|
||||||
|
default = [];
|
||||||
|
description = "Domain search paths";
|
||||||
|
};
|
||||||
interfaces = mkOption {
|
interfaces = mkOption {
|
||||||
type = types.attrsOf (
|
type = types.attrsOf (
|
||||||
types.submodule {
|
types.submodule {
|
||||||
options = {
|
options = {
|
||||||
allowedTCPPorts = mkOption {
|
allowedTCPPorts = mkOption {
|
||||||
type = types.listOf types.int;
|
type = types.listOf types.int;
|
||||||
default = [ ];
|
default = [];
|
||||||
description = "List of allowed TCP ports for this interface.";
|
description = "List of allowed TCP ports for this interface.";
|
||||||
};
|
};
|
||||||
allowedUDPPorts = mkOption {
|
allowedUDPPorts = mkOption {
|
||||||
type = types.listOf types.int;
|
type = types.listOf types.int;
|
||||||
default = [ ];
|
default = [];
|
||||||
description = "List of allowed UDP ports for this interface.";
|
description = "List of allowed UDP ports for this interface.";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
default = { };
|
default = {};
|
||||||
description = "Network interface configurations.";
|
description = "Network interface configurations.";
|
||||||
};
|
};
|
||||||
extraHosts = mkOption {
|
extraHosts = mkOption {
|
||||||
@@ -47,7 +56,7 @@ in
|
|||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
assertions = [
|
assertions = [
|
||||||
{
|
{
|
||||||
assertion = cfg.interfaces != { } -> config.networking.networkmanager.enable;
|
assertion = cfg.interfaces != {} -> config.networking.networkmanager.enable;
|
||||||
message = "Network interfaces configured but NetworkManager is not enabled";
|
message = "Network interfaces configured but NetworkManager is not enabled";
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
@@ -55,6 +64,8 @@ in
|
|||||||
networking = {
|
networking = {
|
||||||
networkmanager.enable = true;
|
networkmanager.enable = true;
|
||||||
nftables.enable = true;
|
nftables.enable = true;
|
||||||
|
nameservers = cfg.nameservers;
|
||||||
|
search = cfg.search;
|
||||||
firewall = {
|
firewall = {
|
||||||
enable = true;
|
enable = true;
|
||||||
inherit (cfg) interfaces;
|
inherit (cfg) interfaces;
|
||||||
@@ -63,8 +74,8 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
systemd.services.NetworkManager = {
|
systemd.services.NetworkManager = {
|
||||||
wants = [ "nftables.service" ];
|
wants = ["nftables.service"];
|
||||||
after = [ "nftables.service" ];
|
after = ["nftables.service"];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,14 +3,11 @@
|
|||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib.meta) getExe;
|
|
||||||
inherit (pkgs) eza bat;
|
|
||||||
inherit (lib) mkIf mkEnableOption mkMerge;
|
inherit (lib) mkIf mkEnableOption mkMerge;
|
||||||
|
|
||||||
cfg = config.nixos.programs.fish;
|
cfg = config.nixos.programs.fish;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
nixos.programs.fish = {
|
nixos.programs.fish = {
|
||||||
enable = mkEnableOption "Enables fish shell";
|
enable = mkEnableOption "Enables fish shell";
|
||||||
@@ -22,6 +19,7 @@ in
|
|||||||
(mkIf cfg.enable {
|
(mkIf cfg.enable {
|
||||||
programs.fish = {
|
programs.fish = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
useBabelfish = true;
|
||||||
vendor = {
|
vendor = {
|
||||||
completions.enable = true;
|
completions.enable = true;
|
||||||
config.enable = true;
|
config.enable = true;
|
||||||
@@ -37,7 +35,9 @@ in
|
|||||||
nixclean = "nh clean all --keep 3";
|
nixclean = "nh clean all --keep 3";
|
||||||
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
nixdev = "nix develop ~/.nix-config -c $SHELL";
|
||||||
nixup = "nh os switch -H $hostname";
|
nixup = "nh os switch -H $hostname";
|
||||||
nixupv = "nh os switch -v -H $hostname";
|
nixupn = "nh os switch -n -H $hostname";
|
||||||
|
nixupv = "nh os switch -v --show-trace -H $hostname";
|
||||||
|
nixupvn = "nh os switch -n -v --show-trace -H $hostname";
|
||||||
flakeup = "nix flake update";
|
flakeup = "nix flake update";
|
||||||
};
|
};
|
||||||
shellAliases = {
|
shellAliases = {
|
||||||
@@ -53,12 +53,8 @@ in
|
|||||||
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
nset = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/settings.nix";
|
||||||
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
nixosmodules = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||||
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
nmod = "$EDITOR /home/$USER/.nix-config/hosts/$hostname/modules.nix";
|
||||||
tree = "${getExe eza} --tree --icons=always";
|
ls = lib.getExe pkgs.eza;
|
||||||
cat = "${getExe bat} --style=plain";
|
tree = "${lib.getExe pkgs.eza} --tree --icons=always";
|
||||||
ls = "${getExe eza} -h --git --icons --color=auto --group-directories-first -s extension";
|
|
||||||
ll = "${getExe eza} -l --git --icons --color=auto --group-directories-first -s extension";
|
|
||||||
lat = "${getExe eza} -lah --tree --color=auto --group-directories-first -s extension";
|
|
||||||
la = "${getExe eza} -lah --color=auto --group-directories-first -s extension";
|
|
||||||
# Clear screen and scrollback
|
# Clear screen and scrollback
|
||||||
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
clear = "printf '\\033[2J\\033[3J\\033[1;1H'";
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -37,9 +37,9 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
gestures = {
|
gestures = {
|
||||||
workspace_swipe = true;
|
# workspace_swipe = true;
|
||||||
workspace_swipe_distance = 400;
|
workspace_swipe_distance = 400;
|
||||||
workspace_swipe_fingers = 3;
|
# workspace_swipe_fingers = 3;
|
||||||
workspace_swipe_cancel_ratio = 0.2;
|
workspace_swipe_cancel_ratio = 0.2;
|
||||||
workspace_swipe_min_speed_to_force = 5;
|
workspace_swipe_min_speed_to_force = 5;
|
||||||
workspace_swipe_direction_lock = true;
|
workspace_swipe_direction_lock = true;
|
||||||
|
|||||||
@@ -49,20 +49,6 @@ in
|
|||||||
"$mod, P, pseudo,"
|
"$mod, P, pseudo,"
|
||||||
"$mod, J, togglesplit,"
|
"$mod, J, togglesplit,"
|
||||||
"$mod, C, exec, hyprctl dispatch exec copyq toggle"
|
"$mod, C, exec, hyprctl dispatch exec copyq toggle"
|
||||||
"$mod, left, movefocus, l"
|
|
||||||
"$mod, right, movefocus, r"
|
|
||||||
"$mod, up, movefocus, u"
|
|
||||||
"$mod, down, movefocus, d"
|
|
||||||
"$mod, 1, workspace, 1"
|
|
||||||
"$mod, 2, workspace, 2"
|
|
||||||
"$mod, 3, workspace, 3"
|
|
||||||
"$mod, 4, workspace, 4"
|
|
||||||
"$mod, 5, workspace, 5"
|
|
||||||
"$mod, 6, workspace, 6"
|
|
||||||
"$mod, 7, workspace, 7"
|
|
||||||
"$mod, 8, workspace, 8"
|
|
||||||
"$mod, 9, workspace, 9"
|
|
||||||
"$mod, 0, workspace, 10"
|
|
||||||
"$mod SHIFT, 1, movetoworkspace, 1"
|
"$mod SHIFT, 1, movetoworkspace, 1"
|
||||||
"$mod SHIFT, 2, movetoworkspace, 2"
|
"$mod SHIFT, 2, movetoworkspace, 2"
|
||||||
"$mod SHIFT, 3, movetoworkspace, 3"
|
"$mod SHIFT, 3, movetoworkspace, 3"
|
||||||
@@ -75,6 +61,30 @@ in
|
|||||||
"$mod SHIFT, 0, movetoworkspace, 10"
|
"$mod SHIFT, 0, movetoworkspace, 10"
|
||||||
"CTRL SHIFT, Escape, exec, ${runOnce "resources"}"
|
"CTRL SHIFT, Escape, exec, ${runOnce "resources"}"
|
||||||
|
|
||||||
|
"$mod, 1, workspace, 1"
|
||||||
|
"$mod, 2, workspace, 2"
|
||||||
|
"$mod, 3, workspace, 3"
|
||||||
|
"$mod, 4, workspace, 4"
|
||||||
|
"$mod, 5, workspace, 5"
|
||||||
|
"$mod, 6, workspace, 6"
|
||||||
|
"$mod, 7, workspace, 7"
|
||||||
|
"$mod, 8, workspace, 8"
|
||||||
|
"$mod, 9, workspace, 9"
|
||||||
|
"$mod, 0, workspace, 10"
|
||||||
|
|
||||||
|
"$mod, left, movefocus, l"
|
||||||
|
"$mod, right, movefocus, r"
|
||||||
|
"$mod, up, movefocus, u"
|
||||||
|
"$mod, down, movefocus, d"
|
||||||
|
"$mod SHIFT, left, resizeactive, -20 0"
|
||||||
|
"$mod SHIFT, right, resizeactive, 20 0"
|
||||||
|
"$mod SHIFT, up, resizeactive, 0 -20"
|
||||||
|
"$mod SHIFT, down, resizeactive, 0 20"
|
||||||
|
"$mod CTRL, left, swapwindow, l"
|
||||||
|
"$mod CTRL, right, swapwindow, r"
|
||||||
|
"$mod CTRL, up, swapwindow, u"
|
||||||
|
"$mod CTRL, down, swapwindow, d"
|
||||||
|
|
||||||
",XF86AudioLowerVolume, exec, volume-control.sh --dec"
|
",XF86AudioLowerVolume, exec, volume-control.sh --dec"
|
||||||
",XF86AudioRaiseVolume, exec, volume-control.sh --inc"
|
",XF86AudioRaiseVolume, exec, volume-control.sh --inc"
|
||||||
",XF86AudioMute, exec, volume-control.sh --toggle"
|
",XF86AudioMute, exec, volume-control.sh --toggle"
|
||||||
@@ -99,7 +109,7 @@ in
|
|||||||
|
|
||||||
(mkIf (host == "kima") {
|
(mkIf (host == "kima") {
|
||||||
programs.hyprland.settings = {
|
programs.hyprland.settings = {
|
||||||
"$terminal" = "ghostty";
|
"$terminal" = "alacritty";
|
||||||
"$browser" = "zen";
|
"$browser" = "zen";
|
||||||
"$browserinc" = "zen --private-window";
|
"$browserinc" = "zen --private-window";
|
||||||
"$mod" = "SUPER";
|
"$mod" = "SUPER";
|
||||||
@@ -111,7 +121,7 @@ in
|
|||||||
|
|
||||||
(mkIf (host == "bunk") {
|
(mkIf (host == "bunk") {
|
||||||
programs.hyprland.settings = {
|
programs.hyprland.settings = {
|
||||||
"$terminal" = "foot";
|
"$terminal" = "alacritty";
|
||||||
"$browser" = "zen";
|
"$browser" = "zen";
|
||||||
"$browserinc" = "zen --private-window";
|
"$browserinc" = "zen --private-window";
|
||||||
"$mod" = "ALT_L";
|
"$mod" = "ALT_L";
|
||||||
|
|||||||
@@ -21,7 +21,7 @@ in
|
|||||||
let
|
let
|
||||||
resolution =
|
resolution =
|
||||||
if m.width != null && m.height != null then
|
if m.width != null && m.height != null then
|
||||||
"${toString m.width}x${toString m.height}@${toString m.refreshRate}"
|
"${toString m.width}x${toString m.height}@${m.refreshRate}"
|
||||||
else
|
else
|
||||||
"preferred";
|
"preferred";
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
inputs,
|
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
pkgs,
|
||||||
...
|
...
|
||||||
@@ -14,22 +13,22 @@ in
|
|||||||
nixos.programs.niri.enable = mkEnableOption "Enables niri";
|
nixos.programs.niri.enable = mkEnableOption "Enables niri";
|
||||||
};
|
};
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
nixpkgs.overlays = [ inputs.niri.overlays.niri ];
|
|
||||||
environment = {
|
environment = {
|
||||||
variables = {
|
variables = {
|
||||||
|
DISPLAY = ":0";
|
||||||
NIXOS_OZONE_WL = "1";
|
NIXOS_OZONE_WL = "1";
|
||||||
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
QT_WAYLAND_DISABLE_WINDOWDECORATION = "1";
|
||||||
};
|
};
|
||||||
systemPackages = with pkgs; [
|
systemPackages = with pkgs; [
|
||||||
xwayland-satellite-unstable
|
xwayland-satellite
|
||||||
wl-clipboard
|
wl-clipboard
|
||||||
wayland-utils
|
wayland-utils
|
||||||
|
xdg-utils
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
systemd.user.services.niri-flake-polkit.enable = false;
|
systemd.user.services.niri-flake-polkit.enable = false;
|
||||||
programs.niri = {
|
programs.niri = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.niri-unstable;
|
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,10 +78,17 @@ in
|
|||||||
openssl
|
openssl
|
||||||
xmrig
|
xmrig
|
||||||
ocl-icd
|
ocl-icd
|
||||||
|
dig
|
||||||
|
unzip
|
||||||
|
zip
|
||||||
|
gnutar
|
||||||
|
gnused
|
||||||
|
p7zip
|
||||||
|
ripgrep
|
||||||
|
file
|
||||||
]
|
]
|
||||||
|
|
||||||
(mkIf cfg.common.enable [
|
(mkIf cfg.common.enable [
|
||||||
qt6.full
|
|
||||||
swappy
|
swappy
|
||||||
wayfreeze
|
wayfreeze
|
||||||
imagemagick
|
imagemagick
|
||||||
@@ -96,9 +103,6 @@ in
|
|||||||
])
|
])
|
||||||
|
|
||||||
(mkIf cfg.desktop.enable [
|
(mkIf cfg.desktop.enable [
|
||||||
protonup
|
|
||||||
winetricks
|
|
||||||
wine
|
|
||||||
geekbench
|
geekbench
|
||||||
unigine-heaven
|
unigine-heaven
|
||||||
])
|
])
|
||||||
@@ -109,15 +113,13 @@ in
|
|||||||
|
|
||||||
(mkIf cfg.server.enable [
|
(mkIf cfg.server.enable [
|
||||||
nvtopPackages.intel
|
nvtopPackages.intel
|
||||||
nvtopPackages.amd
|
|
||||||
dig
|
|
||||||
helix
|
helix
|
||||||
zfs
|
|
||||||
zfstools
|
zfstools
|
||||||
])
|
])
|
||||||
|
|
||||||
(mkIf cfg.dev.enable [
|
(mkIf cfg.dev.enable [
|
||||||
# lldb_20 # some biuld error atm
|
# lldb_20 # some biuld error atm
|
||||||
|
sqlite
|
||||||
gemini-cli
|
gemini-cli
|
||||||
nfs-utils
|
nfs-utils
|
||||||
gcc
|
gcc
|
||||||
@@ -144,7 +146,6 @@ in
|
|||||||
prettierd
|
prettierd
|
||||||
# php84Packages.php-cs-fixer
|
# php84Packages.php-cs-fixer
|
||||||
shfmt
|
shfmt
|
||||||
luaformatter
|
|
||||||
black
|
black
|
||||||
])
|
])
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
|
pkgs,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
@@ -17,6 +18,20 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
gamescopeSession.enable = true;
|
gamescopeSession.enable = true;
|
||||||
};
|
};
|
||||||
|
gamescope = {
|
||||||
|
enable = true;
|
||||||
|
capSysNice = true;
|
||||||
|
args = [
|
||||||
|
"--rt"
|
||||||
|
"--expose-wayland"
|
||||||
|
];
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
protonup-ng
|
||||||
|
wine
|
||||||
|
winetricks
|
||||||
|
wine-wayland
|
||||||
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,17 +5,16 @@
|
|||||||
pkgs,
|
pkgs,
|
||||||
self,
|
self,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
inherit
|
||||||
inherit (lib)
|
(lib)
|
||||||
mkIf
|
mkIf
|
||||||
mkEnableOption
|
mkEnableOption
|
||||||
mkOption
|
mkOption
|
||||||
mkMerge
|
mkMerge
|
||||||
;
|
;
|
||||||
cfg = config.nixos.services.agenix;
|
cfg = config.nixos.services.agenix;
|
||||||
in
|
in {
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
nixos.services.agenix = {
|
nixos.services.agenix = {
|
||||||
enable = mkEnableOption "Enables agenix system environment";
|
enable = mkEnableOption "Enables agenix system environment";
|
||||||
@@ -75,17 +74,11 @@ in
|
|||||||
wgCredentials.file = "${self}/secrets/wgCredentials.age";
|
wgCredentials.file = "${self}/secrets/wgCredentials.age";
|
||||||
wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age";
|
wgSobotkaPrivateKey.file = "${self}/secrets/wgSobotkaPrivateKey.age";
|
||||||
gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age";
|
gluetunEnvironment.file = "${self}/secrets/gluetunEnvironment.age";
|
||||||
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
|
|
||||||
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
|
||||||
homepageEnvironment.file = "${self}/secrets/homepageEnvironment.age";
|
|
||||||
pihole.file = "${self}/secrets/pihole.age";
|
|
||||||
slskd.file = "${self}/secrets/slskd.age";
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(mkIf cfg.ziggy.enable {
|
(mkIf cfg.ziggy.enable {
|
||||||
secrets = {
|
secrets = {
|
||||||
cloudflareDnsCredentialsZiggy.file = "${self}/secrets/cloudflareDnsCredentialsZiggy.age";
|
cloudflareDnsCredentialsZiggy.file = "${self}/secrets/cloudflareDnsCredentialsZiggy.age";
|
||||||
piholeZiggy.file = "${self}/secrets/piholeZiggy.age";
|
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
(mkIf cfg.toothpc.enable {
|
(mkIf cfg.toothpc.enable {
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ in
|
|||||||
settings = rec {
|
settings = rec {
|
||||||
tuigreet_session =
|
tuigreet_session =
|
||||||
let
|
let
|
||||||
session = "${pkgs.niri-unstable}/bin/niri-session";
|
session = "${pkgs.niri}/bin/niri-session";
|
||||||
tuigreet = "${lib.getExe pkgs.tuigreet}";
|
tuigreet = "${lib.getExe pkgs.tuigreet}";
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -16,14 +16,10 @@ in
|
|||||||
services.kanata = {
|
services.kanata = {
|
||||||
enable = true;
|
enable = true;
|
||||||
package = pkgs.kanata-with-cmd;
|
package = pkgs.kanata-with-cmd;
|
||||||
keyboards.hhkbse = {
|
keyboards.default = {
|
||||||
extraDefCfg = ''
|
extraDefCfg = ''
|
||||||
process-unmapped-keys yes
|
process-unmapped-keys yes
|
||||||
'';
|
'';
|
||||||
devices = [
|
|
||||||
"/dev/input/by-id/usb-PFU_Limited_HHKB-Hybrid-event-kbd"
|
|
||||||
"/dev/input/event2"
|
|
||||||
];
|
|
||||||
config = builtins.readFile (./. + "/hhkbse.kbd");
|
config = builtins.readFile (./. + "/hhkbse.kbd");
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
2 3 4 5 6 7 8 9 0 + ´ ' §
|
2 3 4 5 6 7 8 9 0 + ´ ' §
|
||||||
e p ¨
|
e p ¨
|
||||||
l ö ä
|
l ö ä
|
||||||
|
-
|
||||||
z x rmet
|
z x rmet
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -25,13 +26,16 @@
|
|||||||
_ _ _ _ _ _ _ _ _ _ pgdn pgup del
|
_ _ _ _ _ _ _ _ _ _ pgdn pgup del
|
||||||
_ _ '
|
_ _ '
|
||||||
_ _ _
|
_ _ _
|
||||||
|
_
|
||||||
_ _ @level3
|
_ _ @level3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
(deflayer level3
|
(deflayer level3
|
||||||
RA-2 RA-3 S-4 RA-5 S-¨ RA-7 RA-8 RA-9 RA-0 RA-+ ⇥ ⇤ S-'
|
RA-2 RA-3 S-4 RA-5 S-¨ RA-7 RA-8 RA-9 RA-0 RA-+ ⇥ ⇤ S-'
|
||||||
RA-5 ▲ RA-¨
|
RA-5 ▲ RA-¨
|
||||||
◀ ▼ ▶
|
◀ ▼ ▶
|
||||||
|
RA-<
|
||||||
RA-S-z RA-S-x @level3
|
RA-S-z RA-S-x @level3
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
@@ -1,50 +0,0 @@
|
|||||||
{ self, pkgs, ... }:
|
|
||||||
{
|
|
||||||
age.secrets.wgCredentials = {
|
|
||||||
file = "${self}/secrets/wgCredentials.age";
|
|
||||||
mode = "0400";
|
|
||||||
owner = "root";
|
|
||||||
group = "root";
|
|
||||||
path = "/etc/wireguard/mullvad.conf";
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.mullvad-netns = {
|
|
||||||
description = "WireGuard Mullvad netns for VMs";
|
|
||||||
|
|
||||||
serviceConfig = {
|
|
||||||
Type = "oneshot";
|
|
||||||
RemainAfterExit = true;
|
|
||||||
|
|
||||||
ExecStart = "${pkgs.writeShellScript "mullvad-netns-up" ''
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ip netns add mullvad || true
|
|
||||||
|
|
||||||
ip link add veth0 type veth peer name veth1 || true
|
|
||||||
ip link set veth1 netns mullvad
|
|
||||||
ip addr add 10.250.0.1/24 dev veth0 || true
|
|
||||||
ip link set veth0 up
|
|
||||||
ip netns exec mullvad ip addr add 10.250.0.2/24 dev veth1 || true
|
|
||||||
ip netns exec mullvad ip link set veth1 up
|
|
||||||
|
|
||||||
ip netns exec mullvad wg-quick up /etc/wireguard/mullvad.conf
|
|
||||||
ip netns exec mullvad ip route add default dev wg0 || true
|
|
||||||
|
|
||||||
nft add table ip mullvad-nat || true
|
|
||||||
nft add chain ip mullvad-nat postrouting { type nat hook postrouting priority 100 \; } || true
|
|
||||||
nft add rule ip mullvad-nat postrouting ip saddr 10.250.0.0/24 oif "wg0" masquerade || true
|
|
||||||
''}";
|
|
||||||
|
|
||||||
ExecStop = "${pkgs.writeShellScript "mullvad-netns-down" ''
|
|
||||||
set -euo pipefail
|
|
||||||
|
|
||||||
ip netns exec mullvad wg-quick down /etc/wireguard/mullvad.conf || true
|
|
||||||
ip link delete veth0 || true
|
|
||||||
ip netns delete mullvad || true
|
|
||||||
nft delete table ip mullvad-nat || true
|
|
||||||
''}";
|
|
||||||
};
|
|
||||||
|
|
||||||
# no wantedBy here -> won't start at boot
|
|
||||||
};
|
|
||||||
}
|
|
||||||
16
modules/nixos/services/tailscale/default.nix
Normal file
16
modules/nixos/services/tailscale/default.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.nixos.services.tailscale;
|
||||||
|
in {
|
||||||
|
options.nixos.services.tailscale = {
|
||||||
|
enable = mkEnableOption "Enable tailscale";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
services.tailscale.enable = true;
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -6,12 +6,15 @@
|
|||||||
}:
|
}:
|
||||||
let
|
let
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
cfg = config.nixos.services.libvirtd;
|
cfg = config.nixos.services.virtualisation;
|
||||||
in
|
in
|
||||||
{
|
{
|
||||||
options = {
|
options = {
|
||||||
nixos.services.libvirtd.enable = mkEnableOption "Enables libvirtd";
|
nixos.services.virtualisation.enable = mkEnableOption "Enables virtualisation";
|
||||||
};
|
};
|
||||||
|
imports = [
|
||||||
|
./vfio.nix
|
||||||
|
];
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
networking.firewall.trustedInterfaces = [ "virbr0" ];
|
networking.firewall.trustedInterfaces = [ "virbr0" ];
|
||||||
@@ -21,7 +24,6 @@ in
|
|||||||
];
|
];
|
||||||
|
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
kvmgt.enable = true;
|
|
||||||
spiceUSBRedirection.enable = true;
|
spiceUSBRedirection.enable = true;
|
||||||
libvirtd = {
|
libvirtd = {
|
||||||
enable = true;
|
enable = true;
|
||||||
@@ -34,5 +36,6 @@ in
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
nixos.services.virtualisation.vfio.enable = true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
41
modules/nixos/services/virtualisation/vfio.nix
Normal file
41
modules/nixos/services/virtualisation/vfio.nix
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
{ lib, config, ... }:
|
||||||
|
let
|
||||||
|
gpuIDs = [
|
||||||
|
"1002:13c0"
|
||||||
|
"1002:1640"
|
||||||
|
];
|
||||||
|
|
||||||
|
vfioIds = "vfio-pci.ids=" + lib.concatStringsSep "," gpuIDs;
|
||||||
|
baseBootKernelParams = config.boot.kernelParams or [ ];
|
||||||
|
cfg = config.nixos.services.virtualisation.vfio;
|
||||||
|
in
|
||||||
|
{
|
||||||
|
options = {
|
||||||
|
nixos.services.virtualisation.vfio.enable =
|
||||||
|
lib.mkEnableOption "Enable VFIO passthrough for the iGPU";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
boot = {
|
||||||
|
initrd.kernelModules = [
|
||||||
|
"vfio_pci"
|
||||||
|
"vfio"
|
||||||
|
"vfio_iommu_type1"
|
||||||
|
];
|
||||||
|
|
||||||
|
kernelParams = [
|
||||||
|
"amd_iommu=on"
|
||||||
|
"iommu=pt"
|
||||||
|
]
|
||||||
|
++ [ vfioIds ];
|
||||||
|
};
|
||||||
|
|
||||||
|
specialisation.vfio.configuration = {
|
||||||
|
system.nixos.tags = [ "vfio" ];
|
||||||
|
boot = {
|
||||||
|
kernelParams = baseBootKernelParams ++ [ vfioIds ];
|
||||||
|
blacklistedKernelModules = [ "amdgpu:0f:00.0" ];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -45,7 +45,6 @@ in
|
|||||||
# nodePackages_latest.sql-formatter
|
# nodePackages_latest.sql-formatter
|
||||||
prettierd
|
prettierd
|
||||||
shfmt
|
shfmt
|
||||||
luaformatter
|
|
||||||
black
|
black
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ in
|
|||||||
inputs.fonts.packages.${pkgs.system}.vcr-mono
|
inputs.fonts.packages.${pkgs.system}.vcr-mono
|
||||||
noto-fonts
|
noto-fonts
|
||||||
noto-fonts-cjk-sans
|
noto-fonts-cjk-sans
|
||||||
noto-fonts-emoji
|
noto-fonts-color-emoji
|
||||||
liberation_ttf
|
liberation_ttf
|
||||||
fira-code-symbols
|
fira-code-symbols
|
||||||
font-awesome
|
font-awesome
|
||||||
|
|||||||
@@ -30,13 +30,19 @@ in
|
|||||||
enable = true;
|
enable = true;
|
||||||
xdgOpenUsePortal = cfg.xdgOpenUsePortal;
|
xdgOpenUsePortal = cfg.xdgOpenUsePortal;
|
||||||
config = {
|
config = {
|
||||||
common.default = [ "gtk" ];
|
common.default = [
|
||||||
|
"gtk"
|
||||||
|
"gnome"
|
||||||
|
];
|
||||||
hyprland.default = [
|
hyprland.default = [
|
||||||
"gtk"
|
"gtk"
|
||||||
"hyprland"
|
"hyprland"
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
extraPortals = [ pkgs.xdg-desktop-portal-gtk ];
|
extraPortals = with pkgs; [
|
||||||
|
xdg-desktop-portal-gtk
|
||||||
|
xdg-desktop-portal-gnome
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
2
modules/server/README.md
Normal file
2
modules/server/README.md
Normal file
@@ -0,0 +1,2 @@
|
|||||||
|
This server/homelab configuration is largely a copy (with some tweaks) of
|
||||||
|
@notthebee's homelab setup.
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "bazarr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Bazarr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Subtitle manager";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "bazarr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
group = srv.group;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString config.services.${unit}.listenPort}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,63 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
cfg = config.server.caddy;
|
|
||||||
|
|
||||||
getCloudflareCredentials = hostname:
|
|
||||||
if hostname == "ziggy"
|
|
||||||
then config.age.secrets.cloudflareDnsCredentialsZiggy.path
|
|
||||||
else if hostname == "sobotka"
|
|
||||||
then config.age.secrets.cloudflareDnsCredentials.path
|
|
||||||
else throw "Unknown hostname: ${hostname}";
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
server.caddy.enable = mkEnableOption "Enables caddy";
|
|
||||||
};
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
networking.firewall = let
|
|
||||||
ports = [
|
|
||||||
80
|
|
||||||
443
|
|
||||||
];
|
|
||||||
in {
|
|
||||||
allowedTCPPorts = ports;
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme = {
|
|
||||||
acceptTerms = true;
|
|
||||||
defaults.email = config.server.email;
|
|
||||||
certs.${config.server.domain} = {
|
|
||||||
reloadServices = ["caddy.service"];
|
|
||||||
domain = "${config.server.domain}";
|
|
||||||
extraDomainNames = ["*.${config.server.domain}"];
|
|
||||||
dnsProvider = "cloudflare";
|
|
||||||
dnsResolver = "1.1.1.1:53";
|
|
||||||
dnsPropagationCheck = true;
|
|
||||||
group = config.services.caddy.group;
|
|
||||||
environmentFile = getCloudflareCredentials config.networking.hostName;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.caddy = {
|
|
||||||
enable = true;
|
|
||||||
globalConfig = ''
|
|
||||||
auto_https off
|
|
||||||
'';
|
|
||||||
virtualHosts = {
|
|
||||||
"http://${config.server.domain}" = {
|
|
||||||
extraConfig = ''
|
|
||||||
redir https://{host}{uri}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
"http://*.${config.server.domain}" = {
|
|
||||||
extraConfig = ''
|
|
||||||
redir https://{host}{uri}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,97 +1,16 @@
|
|||||||
{
|
{
|
||||||
|
self,
|
||||||
lib,
|
lib,
|
||||||
config,
|
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
clib = import "${self}/lib/server" {inherit lib;};
|
||||||
inherit (lib) mkOption types;
|
in {
|
||||||
cfg = config.server;
|
imports = [
|
||||||
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
{
|
||||||
in
|
_module.args.clib = clib;
|
||||||
{
|
}
|
||||||
options.server = {
|
./options.nix
|
||||||
enable = lib.mkEnableOption "The server services and configuration variables";
|
./infra
|
||||||
email = mkOption {
|
./services
|
||||||
default = "";
|
];
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
Email name to be used to access the server services via Caddy reverse proxy
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
domain = mkOption {
|
|
||||||
default = "";
|
|
||||||
type = types.str;
|
|
||||||
description = ''
|
|
||||||
Domain name to be used to access the server services via Caddy reverse proxy
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
user = lib.mkOption {
|
|
||||||
default = "share";
|
|
||||||
type = lib.types.str;
|
|
||||||
description = ''
|
|
||||||
User to run the server services as
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
group = lib.mkOption {
|
|
||||||
default = "share";
|
|
||||||
type = lib.types.str;
|
|
||||||
description = ''
|
|
||||||
Group to run the server services as
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
uid = lib.mkOption {
|
|
||||||
default = 1000;
|
|
||||||
type = lib.types.int;
|
|
||||||
description = ''
|
|
||||||
UID to run the server services as
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
gid = lib.mkOption {
|
|
||||||
default = 1000;
|
|
||||||
type = lib.types.int;
|
|
||||||
description = ''
|
|
||||||
GID to run the server services as
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
timeZone = lib.mkOption {
|
|
||||||
default = "Europe/Stockholm";
|
|
||||||
type = lib.types.str;
|
|
||||||
description = ''
|
|
||||||
Time zone to be used for the server services
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
users = {
|
|
||||||
groups.${cfg.group} = {
|
|
||||||
gid = cfg.gid;
|
|
||||||
};
|
|
||||||
users.${cfg.user} = {
|
|
||||||
uid = cfg.uid;
|
|
||||||
isSystemUser = true;
|
|
||||||
group = cfg.group;
|
|
||||||
extraGroups = ifTheyExist [
|
|
||||||
"audio"
|
|
||||||
"video"
|
|
||||||
"docker"
|
|
||||||
"libvirtd"
|
|
||||||
"qemu-libvirtd"
|
|
||||||
"rtkit"
|
|
||||||
"fail2ban"
|
|
||||||
"vaultwarden"
|
|
||||||
"qbittorrent"
|
|
||||||
"lidarr"
|
|
||||||
"prowlarr"
|
|
||||||
"bazarr"
|
|
||||||
"sonarr"
|
|
||||||
"radarr"
|
|
||||||
"media"
|
|
||||||
"share"
|
|
||||||
"render"
|
|
||||||
"input"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,111 +0,0 @@
|
|||||||
# from @notthebee
|
|
||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
cfg = config.server.fail2ban;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.fail2ban = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable cloudflare fail2ban";
|
|
||||||
};
|
|
||||||
apiKeyFile = lib.mkOption {
|
|
||||||
description = "File containing your API key, scoped to Firewall Rules: Edit";
|
|
||||||
type = lib.types.str;
|
|
||||||
example = lib.literalExpression ''
|
|
||||||
Authorization: Bearer Qj06My1wXJEzcW46QCyjFbSMgVtwIGfX63Ki3NOj79o=
|
|
||||||
'''
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
zoneId = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
jails = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf (
|
|
||||||
lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
serviceName = lib.mkOption {
|
|
||||||
example = "vaultwarden";
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
failRegex = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "Login failed from IP: <HOST>";
|
|
||||||
};
|
|
||||||
ignoreRegex = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "";
|
|
||||||
};
|
|
||||||
maxRetry = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 3;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.fail2ban = {
|
|
||||||
enable = true;
|
|
||||||
extraPackages = [
|
|
||||||
pkgs.curl
|
|
||||||
pkgs.jq
|
|
||||||
];
|
|
||||||
|
|
||||||
jails = lib.attrsets.mapAttrs (name: value: {
|
|
||||||
settings = {
|
|
||||||
bantime = "30d";
|
|
||||||
findtime = "1h";
|
|
||||||
enabled = true;
|
|
||||||
backend = "systemd";
|
|
||||||
journalmatch = "_SYSTEMD_UNIT=${value.serviceName}.service";
|
|
||||||
port = "http,https";
|
|
||||||
filter = "${name}";
|
|
||||||
maxretry = 3;
|
|
||||||
action = "cloudflare-token-agenix";
|
|
||||||
};
|
|
||||||
}) cfg.jails;
|
|
||||||
};
|
|
||||||
|
|
||||||
environment.etc = lib.attrsets.mergeAttrsList [
|
|
||||||
(lib.attrsets.mapAttrs' (
|
|
||||||
name: value:
|
|
||||||
(lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
|
|
||||||
text = ''
|
|
||||||
[Definition]
|
|
||||||
failregex = ${value.failRegex}
|
|
||||||
ignoreregex = ${value.ignoreRegex}
|
|
||||||
'';
|
|
||||||
})
|
|
||||||
) cfg.jails)
|
|
||||||
{
|
|
||||||
"fail2ban/action.d/cloudflare-token-agenix.conf".text =
|
|
||||||
let
|
|
||||||
notes = "Fail2Ban on ${config.networking.hostName}";
|
|
||||||
cfapi = "https://api.cloudflare.com/client/v4/zones/${cfg.zoneId}/firewall/access_rules/rules";
|
|
||||||
in
|
|
||||||
''
|
|
||||||
[Definition]
|
|
||||||
actionstart =
|
|
||||||
actionstop =
|
|
||||||
actioncheck =
|
|
||||||
actionunban = id=$(curl -s -X GET "${cfapi}" \
|
|
||||||
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
|
||||||
| jq -r '.result[] | select(.notes == "${notes}" and .configuration.target == "ip" and .configuration.value == "<ip>") | .id')
|
|
||||||
if [ -z "$id" ]; then echo "id for <ip> cannot be found"; exit 0; fi; \
|
|
||||||
curl -s -X DELETE "${cfapi}/$id" \
|
|
||||||
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
|
||||||
--data '{"cascade": "none"}'
|
|
||||||
actionban = curl -X POST "${cfapi}" -H @${cfg.apiKeyFile} -H "Content-Type: application/json" --data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"${notes}"}'
|
|
||||||
[Init]
|
|
||||||
name = cloudflare-token-agenix
|
|
||||||
'';
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
# taken from @jtojnar
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "gitea";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "git.${srv.domain}";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 5003;
|
|
||||||
description = "The port to host Gitea on.";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Gitea";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Git with a cup of tea";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "gitea.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Services";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
appName = "cnix code forge";
|
|
||||||
|
|
||||||
database = {
|
|
||||||
type = "postgres";
|
|
||||||
socket = "/run/postgresql";
|
|
||||||
name = "gitea";
|
|
||||||
user = "gitea";
|
|
||||||
createDatabase = false;
|
|
||||||
};
|
|
||||||
|
|
||||||
lfs = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
settings = {
|
|
||||||
cors = {
|
|
||||||
ENABLED = true;
|
|
||||||
SCHEME = "https";
|
|
||||||
ALLOW_DOMAIN = cfg.url;
|
|
||||||
};
|
|
||||||
log = {
|
|
||||||
MODE = "console";
|
|
||||||
};
|
|
||||||
mailer = {
|
|
||||||
ENABLED = false;
|
|
||||||
MAILER_TYPE = "sendmail";
|
|
||||||
FROM = "noreply+adam@cnst.dev";
|
|
||||||
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
|
|
||||||
};
|
|
||||||
picture = {
|
|
||||||
DISABLE_GRAVATAR = true;
|
|
||||||
};
|
|
||||||
repository = {
|
|
||||||
DEFAULT_BRANCH = "main";
|
|
||||||
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
|
||||||
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
|
|
||||||
};
|
|
||||||
indexer = {
|
|
||||||
REPO_INDEXER_ENABLED = true;
|
|
||||||
};
|
|
||||||
server = {
|
|
||||||
DOMAIN = cfg.url;
|
|
||||||
LANDING_PAGE = "explore";
|
|
||||||
HTTP_PORT = cfg.port;
|
|
||||||
ROOT_URL = "https://${cfg.url}/";
|
|
||||||
};
|
|
||||||
security = {
|
|
||||||
DISABLE_GIT_HOOKS = false;
|
|
||||||
};
|
|
||||||
service = {
|
|
||||||
DISABLE_REGISTRATION = true;
|
|
||||||
};
|
|
||||||
session = {
|
|
||||||
COOKIE_SECURE = true;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:5003
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
|
|
||||||
server.postgresql.databases = [
|
|
||||||
{
|
|
||||||
database = "gitea";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,233 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "homepage-dashboard";
|
|
||||||
cfg = config.server.homepage-dashboard;
|
|
||||||
srv = config.server;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.homepage-dashboard = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
misc = lib.mkOption {
|
|
||||||
default = [ ];
|
|
||||||
type = lib.types.listOf (
|
|
||||||
lib.types.attrsOf (
|
|
||||||
lib.types.submodule {
|
|
||||||
options = {
|
|
||||||
description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
href = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
siteMonitor = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
)
|
|
||||||
);
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.glances.enable = true;
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
allowedHosts = srv.domain;
|
|
||||||
settings = {
|
|
||||||
layout = [
|
|
||||||
{
|
|
||||||
Glances = {
|
|
||||||
header = false;
|
|
||||||
style = "row";
|
|
||||||
columns = 4;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Arr = {
|
|
||||||
header = true;
|
|
||||||
style = "column";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Downloads = {
|
|
||||||
header = true;
|
|
||||||
style = "column";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Media = {
|
|
||||||
header = true;
|
|
||||||
style = "column";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Services = {
|
|
||||||
header = true;
|
|
||||||
style = "column";
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
headerStyle = "clean";
|
|
||||||
statusStyle = "dot";
|
|
||||||
hideVersion = "true";
|
|
||||||
};
|
|
||||||
|
|
||||||
widgets = [
|
|
||||||
{
|
|
||||||
openmeteo = {
|
|
||||||
label = "Kalmar";
|
|
||||||
timezone = "Europe/Stockholm";
|
|
||||||
units = "metric";
|
|
||||||
cache = 5;
|
|
||||||
latitude = 56.707262;
|
|
||||||
longitude = 16.324541;
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
datetime = {
|
|
||||||
text_size = "x1";
|
|
||||||
format = {
|
|
||||||
hour12 = false;
|
|
||||||
timeStyle = "short";
|
|
||||||
dateStyle = "long";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
resources = {
|
|
||||||
label = "";
|
|
||||||
memory = true;
|
|
||||||
disk = [ "/" ];
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
services =
|
|
||||||
let
|
|
||||||
homepageCategories = [
|
|
||||||
"Arr"
|
|
||||||
"Media"
|
|
||||||
"Downloads"
|
|
||||||
"Services"
|
|
||||||
"Smart Home"
|
|
||||||
];
|
|
||||||
hl = config.server;
|
|
||||||
mergedServices = hl // hl.podman;
|
|
||||||
homepageServices =
|
|
||||||
x:
|
|
||||||
(lib.attrsets.filterAttrs (
|
|
||||||
name: value: value ? homepage && value.homepage.category == x
|
|
||||||
) mergedServices);
|
|
||||||
in
|
|
||||||
lib.lists.forEach homepageCategories (cat: {
|
|
||||||
"${cat}" =
|
|
||||||
lib.lists.forEach
|
|
||||||
(lib.attrsets.mapAttrsToList (name: value: {
|
|
||||||
inherit name;
|
|
||||||
url = value.url;
|
|
||||||
homepage = value.homepage;
|
|
||||||
}) (homepageServices "${cat}"))
|
|
||||||
(x: {
|
|
||||||
"${x.homepage.name}" = {
|
|
||||||
icon = x.homepage.icon;
|
|
||||||
description = x.homepage.description;
|
|
||||||
href = "https://${x.url}${x.homepage.path or ""}";
|
|
||||||
siteMonitor = "https://${x.url}${x.homepage.path or ""}";
|
|
||||||
};
|
|
||||||
});
|
|
||||||
})
|
|
||||||
++ [ { Misc = cfg.misc; } ]
|
|
||||||
++ [
|
|
||||||
{
|
|
||||||
Glances =
|
|
||||||
let
|
|
||||||
port = toString config.services.glances.port;
|
|
||||||
in
|
|
||||||
[
|
|
||||||
{
|
|
||||||
Info = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "info";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
"CPU Temp" = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "sensor:Tctl";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
"GPU Radeon" = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "sensor:junction";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
"GPU Intel" = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "sensor:pkg";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Processes = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "process";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
{
|
|
||||||
Network = {
|
|
||||||
widget = {
|
|
||||||
type = "glances";
|
|
||||||
url = "http://localhost:${port}";
|
|
||||||
metric = "network:enp6s0";
|
|
||||||
chart = false;
|
|
||||||
version = 4;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${srv.domain}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString config.services.${unit}.listenPort}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
133
modules/server/infra/authentik/default.nix
Normal file
133
modules/server/infra/authentik/default.nix
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "authentik";
|
||||||
|
cfg = config.server.infra.${unit};
|
||||||
|
srv = config.server.infra;
|
||||||
|
in {
|
||||||
|
options.server.infra.${unit} = {
|
||||||
|
enable = lib.mkEnableOption {
|
||||||
|
description = "Enable ${unit}";
|
||||||
|
};
|
||||||
|
url = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "auth.${srv.www.url}";
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.port;
|
||||||
|
description = "The local port the service runs on";
|
||||||
|
};
|
||||||
|
cloudflared = {
|
||||||
|
credentialsFile = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
pkgs.writeText "cloudflare-credentials.json" '''
|
||||||
|
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
tunnelId = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "00000000-0000-0000-0000-000000000000";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
homepage = {
|
||||||
|
name = "Authentik";
|
||||||
|
description = "An open-source IdP for modern SSO";
|
||||||
|
icon = "authentik.svg";
|
||||||
|
category = "Services";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
authentikEnv = {
|
||||||
|
file = "${self}/secrets/authentikEnv.age";
|
||||||
|
};
|
||||||
|
authentikCloudflared = {
|
||||||
|
file = "${self}/secrets/authentikCloudflared.age";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
server.infra = {
|
||||||
|
fail2ban = {
|
||||||
|
jails = {
|
||||||
|
authentik = {
|
||||||
|
serviceName = "authentik";
|
||||||
|
failRegex = ''^.*Username or password is incorrect.*IP:\s*<HOST>'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
authentik = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = config.age.secrets.authentikEnv.path;
|
||||||
|
settings = {
|
||||||
|
email = {
|
||||||
|
};
|
||||||
|
disable_startup_analytics = true;
|
||||||
|
avatars = "initials";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cloudflared = {
|
||||||
|
enable = true;
|
||||||
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
|
default = "http_status:404";
|
||||||
|
ingress."${cfg.url}".service = "http://127.0.0.1:9000";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
traefik = {
|
||||||
|
dynamicConfigOptions = {
|
||||||
|
http = {
|
||||||
|
middlewares = {
|
||||||
|
authentik = {
|
||||||
|
forwardAuth = {
|
||||||
|
address = "https://localhost:9443/outpost.goauthentik.io/auth/traefik";
|
||||||
|
trustForwardHeader = true;
|
||||||
|
authResponseHeaders = [
|
||||||
|
"X-authentik-username"
|
||||||
|
"X-authentik-groups"
|
||||||
|
"X-authentik-email"
|
||||||
|
"X-authentik-name"
|
||||||
|
"X-authentik-uid"
|
||||||
|
"X-authentik-jwt"
|
||||||
|
"X-authentik-meta-jwks"
|
||||||
|
"X-authentik-meta-outpost"
|
||||||
|
"X-authentik-meta-provider"
|
||||||
|
"X-authentik-meta-app"
|
||||||
|
"X-authentik-meta-version"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
auth.loadBalancer.servers = [
|
||||||
|
{
|
||||||
|
url = "http://localhost:9000";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
routers = {
|
||||||
|
auth = {
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
rule = "Host(`${cfg.url}`) && PathPrefix(`/outpost.goauthentik.io/`)";
|
||||||
|
service = "auth";
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
13
modules/server/infra/default.nix
Normal file
13
modules/server/infra/default.nix
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./authentik
|
||||||
|
./fail2ban
|
||||||
|
./keepalived
|
||||||
|
./podman
|
||||||
|
./postgres
|
||||||
|
./tailscale
|
||||||
|
./traefik
|
||||||
|
./unbound
|
||||||
|
./www
|
||||||
|
];
|
||||||
|
}
|
||||||
131
modules/server/infra/fail2ban/default.nix
Normal file
131
modules/server/infra/fail2ban/default.nix
Normal file
@@ -0,0 +1,131 @@
|
|||||||
|
# from @notthebee
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
cfg = config.server.infra.fail2ban;
|
||||||
|
in {
|
||||||
|
options.server.infra.fail2ban = {
|
||||||
|
enable = lib.mkEnableOption {
|
||||||
|
description = "Enable cloudflare fail2ban";
|
||||||
|
};
|
||||||
|
apiKeyFile = lib.mkOption {
|
||||||
|
description = "File containing your API key, scoped to Firewall Rules: Edit";
|
||||||
|
type = lib.types.str;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
Authorization: Bearer vH6-p0y=i4w3n7TjKqZ@x8D_lR!A9b2cOezXgUuJdE5F
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
zoneId = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
jails = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (
|
||||||
|
lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
serviceName = lib.mkOption {
|
||||||
|
example = "vaultwarden";
|
||||||
|
type = lib.types.str;
|
||||||
|
};
|
||||||
|
_groupsre = lib.mkOption {
|
||||||
|
type = lib.types.lines;
|
||||||
|
example = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||||
|
default = "";
|
||||||
|
};
|
||||||
|
failRegex = lib.mkOption {
|
||||||
|
type = lib.types.lines;
|
||||||
|
example = ''
|
||||||
|
^Login failed from IP: <HOST>$
|
||||||
|
^Two-factor challenge failed from <HOST>$
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
ignoreRegex = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
};
|
||||||
|
datePattern = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
example = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
||||||
|
description = "Optional datepattern line for the fail2ban filter.";
|
||||||
|
};
|
||||||
|
maxRetry = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 3;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.fail2ban = {
|
||||||
|
enable = true;
|
||||||
|
extraPackages = [
|
||||||
|
pkgs.curl
|
||||||
|
pkgs.jq
|
||||||
|
];
|
||||||
|
|
||||||
|
jails =
|
||||||
|
lib.attrsets.mapAttrs (name: value: {
|
||||||
|
settings = {
|
||||||
|
bantime = "24h";
|
||||||
|
findtime = "10m";
|
||||||
|
enabled = true;
|
||||||
|
backend = "systemd";
|
||||||
|
journalmatch = "_SYSTEMD_UNIT=${value.serviceName}.service";
|
||||||
|
port = "http,https";
|
||||||
|
filter = "${name}";
|
||||||
|
maxretry = 3;
|
||||||
|
action = "cloudflare-token-agenix";
|
||||||
|
};
|
||||||
|
})
|
||||||
|
cfg.jails;
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.etc = lib.attrsets.mergeAttrsList [
|
||||||
|
(lib.attrsets.mapAttrs' (
|
||||||
|
name: value: (lib.nameValuePair "fail2ban/filter.d/${name}.conf" {
|
||||||
|
text =
|
||||||
|
''
|
||||||
|
[Definition]
|
||||||
|
failregex = ${value.failRegex}
|
||||||
|
ignoreregex = ${value.ignoreRegex}
|
||||||
|
''
|
||||||
|
+ lib.optionalString (value.datePattern != "") ''
|
||||||
|
datepattern = ${value.datePattern}
|
||||||
|
''
|
||||||
|
+ lib.optionalString (value._groupsre != "") ''
|
||||||
|
_groupsre = ${value._groupsre}
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
)
|
||||||
|
cfg.jails)
|
||||||
|
{
|
||||||
|
"fail2ban/action.d/cloudflare-token-agenix.conf".text = let
|
||||||
|
notes = "Fail2Ban on ${config.networking.hostName}";
|
||||||
|
cfapi = "https://api.cloudflare.com/client/v4/zones/${cfg.zoneId}/firewall/access_rules/rules";
|
||||||
|
in ''
|
||||||
|
[Definition]
|
||||||
|
actionstart =
|
||||||
|
actionstop =
|
||||||
|
actioncheck =
|
||||||
|
actionunban = id=$(curl -s -X GET "${cfapi}" \
|
||||||
|
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
||||||
|
| jq -r '.result[] | select(.notes == "${notes}" and .configuration.target == "ip" and .configuration.value == "<ip>") | .id')
|
||||||
|
if [ -z "$id" ]; then echo "id for <ip> cannot be found"; exit 0; fi; \
|
||||||
|
curl -s -X DELETE "${cfapi}/$id" \
|
||||||
|
-H @${cfg.apiKeyFile} -H "Content-Type: application/json" \
|
||||||
|
--data '{"cascade": "none"}'
|
||||||
|
actionban = curl -X POST "${cfapi}" -H @${cfg.apiKeyFile} -H "Content-Type: application/json" --data '{"mode":"block","configuration":{"target":"ip","value":"<ip>"},"notes":"${notes}"}'
|
||||||
|
[Init]
|
||||||
|
name = cloudflare-token-agenix
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -3,27 +3,24 @@
|
|||||||
config,
|
config,
|
||||||
self,
|
self,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
unit = "keepalived";
|
unit = "keepalived";
|
||||||
cfg = config.server.${unit};
|
cfg = config.server.infra.${unit};
|
||||||
|
|
||||||
hostCfg =
|
hostCfg = hostname:
|
||||||
hostname:
|
if hostname == "sobotka"
|
||||||
if hostname == "sobotka" then
|
then {
|
||||||
{
|
ip = "192.168.88.14";
|
||||||
ip = "192.168.88.14";
|
priority = 20;
|
||||||
priority = 20;
|
state = "MASTER";
|
||||||
state = "MASTER";
|
}
|
||||||
}
|
else if hostname == "ziggy"
|
||||||
else if hostname == "ziggy" then
|
then {
|
||||||
{
|
ip = "192.168.88.12";
|
||||||
ip = "192.168.88.12";
|
priority = 10;
|
||||||
priority = 10;
|
state = "BACKUP";
|
||||||
state = "BACKUP";
|
}
|
||||||
}
|
else throw "No keepalived config defined for host ${hostname}";
|
||||||
else
|
|
||||||
throw "No keepalived config defined for host ${hostname}";
|
|
||||||
|
|
||||||
_self = hostCfg config.networking.hostName;
|
_self = hostCfg config.networking.hostName;
|
||||||
|
|
||||||
@@ -34,9 +31,8 @@ let
|
|||||||
|
|
||||||
# Remove self from peers
|
# Remove self from peers
|
||||||
peers = builtins.filter (ip: ip != _self.ip) allPeers;
|
peers = builtins.filter (ip: ip != _self.ip) allPeers;
|
||||||
in
|
in {
|
||||||
{
|
options.server.infra.${unit} = {
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
enable = lib.mkEnableOption {
|
||||||
description = "Enable ${unit}";
|
description = "Enable ${unit}";
|
||||||
};
|
};
|
||||||
6
modules/server/infra/podman/acquis.yaml
Normal file
6
modules/server/infra/podman/acquis.yaml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
---
|
||||||
|
filenames:
|
||||||
|
- /var/log/traefik/access.log
|
||||||
|
poll_without_inotify: true
|
||||||
|
labels:
|
||||||
|
type: traefik
|
||||||
@@ -1,18 +1,11 @@
|
|||||||
{
|
{
|
||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
pkgs,
|
self,
|
||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
srv = config.server;
|
infra = config.server.infra;
|
||||||
cfg = config.server.podman;
|
cfg = config.server.services;
|
||||||
|
|
||||||
piholeUrl =
|
|
||||||
if config.networking.hostName == "sobotka"
|
|
||||||
then "pihole0"
|
|
||||||
else if config.networking.hostName == "ziggy"
|
|
||||||
then "pihole1"
|
|
||||||
else throw "Unknown hostname";
|
|
||||||
|
|
||||||
getPiholeSecret = hostname:
|
getPiholeSecret = hostname:
|
||||||
if hostname == "ziggy"
|
if hostname == "ziggy"
|
||||||
@@ -21,106 +14,16 @@
|
|||||||
then [config.age.secrets.pihole.path]
|
then [config.age.secrets.pihole.path]
|
||||||
else throw "Unknown hostname: ${hostname}";
|
else throw "Unknown hostname: ${hostname}";
|
||||||
in {
|
in {
|
||||||
options.server.podman = {
|
options.server.infra = {
|
||||||
enable = lib.mkEnableOption "Enables Podman";
|
podman.enable = lib.mkEnableOption "Enables Podman";
|
||||||
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
||||||
|
|
||||||
qbittorrent = {
|
|
||||||
enable = lib.mkEnableOption "Enable qBittorrent";
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "qbt.${srv.domain}";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 8080;
|
|
||||||
description = "The port to host qBittorrent on.";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "qBittorrent";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Torrent client";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "qbittorrent.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Downloads";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
slskd = {
|
|
||||||
enable = lib.mkEnableOption "Enable Soulseek";
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "slskd.${srv.domain}";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 5030;
|
|
||||||
description = "The port to host Soulseek webui on.";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "slskd";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Web-based Soulseek client";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "slskd.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Downloads";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
pihole = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.int;
|
|
||||||
default = 8053;
|
|
||||||
description = "The port to host PiHole on.";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${piholeUrl}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "PiHole";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Adblocking and DNS service";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "pi-hole.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Services";
|
|
||||||
};
|
|
||||||
homepage.path = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/admin";
|
|
||||||
description = "Optional path suffix for homepage links (e.g. /admin).";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
config = lib.mkIf infra.podman.enable {
|
||||||
|
age.secrets = {
|
||||||
|
pihole.file = "${self}/secrets/${config.networking.hostName}Pihole.age";
|
||||||
|
slskd.file = "${self}/secrets/slskd.age";
|
||||||
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
virtualisation = {
|
virtualisation = {
|
||||||
containers.enable = true;
|
containers.enable = true;
|
||||||
podman.enable = true;
|
podman.enable = true;
|
||||||
@@ -137,37 +40,8 @@ in {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
|
|
||||||
services.caddy.virtualHosts = lib.mkMerge [
|
|
||||||
(lib.mkIf cfg.qbittorrent.enable {
|
|
||||||
"${cfg.qbittorrent.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString cfg.qbittorrent.port}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(lib.mkIf cfg.slskd.enable {
|
|
||||||
"${cfg.slskd.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString cfg.slskd.port}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
})
|
|
||||||
|
|
||||||
(lib.mkIf cfg.pihole.enable {
|
|
||||||
"${cfg.pihole.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString cfg.pihole.port}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
})
|
|
||||||
];
|
|
||||||
|
|
||||||
virtualisation.oci-containers.containers = lib.mkMerge [
|
virtualisation.oci-containers.containers = lib.mkMerge [
|
||||||
(lib.mkIf cfg.gluetun.enable {
|
(lib.mkIf infra.gluetun.enable {
|
||||||
gluetun = {
|
gluetun = {
|
||||||
image = "qmcgaw/gluetun";
|
image = "qmcgaw/gluetun";
|
||||||
ports = [
|
ports = [
|
||||||
@@ -260,7 +134,7 @@ in {
|
|||||||
(lib.mkIf cfg.pihole.enable {
|
(lib.mkIf cfg.pihole.enable {
|
||||||
pihole = {
|
pihole = {
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
image = "pihole/pihole:latest";
|
image = "pihole/pihole:2025.08.0";
|
||||||
volumes = [
|
volumes = [
|
||||||
"/var/lib/pihole:/etc/pihole/"
|
"/var/lib/pihole:/etc/pihole/"
|
||||||
"/var/lib/dnsmasq.d:/etc/dnsmasq.d/"
|
"/var/lib/dnsmasq.d:/etc/dnsmasq.d/"
|
||||||
@@ -268,9 +142,6 @@ in {
|
|||||||
environment = {
|
environment = {
|
||||||
TZ = "Europe/Stockholm";
|
TZ = "Europe/Stockholm";
|
||||||
CUSTOM_CACHE_SIZE = "0";
|
CUSTOM_CACHE_SIZE = "0";
|
||||||
# PIHOLE_DNS_ = "10.88.0.1#5335";
|
|
||||||
# DNSSEC = "false";
|
|
||||||
# REV_SERVER = "true";
|
|
||||||
WEBTHEME = "default-darker";
|
WEBTHEME = "default-darker";
|
||||||
};
|
};
|
||||||
environmentFiles = getPiholeSecret config.networking.hostName;
|
environmentFiles = getPiholeSecret config.networking.hostName;
|
||||||
@@ -286,6 +157,38 @@ in {
|
|||||||
];
|
];
|
||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
(lib.mkIf cfg.ollama.enable {
|
||||||
|
intel-llm = {
|
||||||
|
autoStart = true;
|
||||||
|
image = "intelanalytics/ipex-llm-inference-cpp-xpu:latest";
|
||||||
|
devices = [
|
||||||
|
"/dev/dri:/dev/dri:rwm"
|
||||||
|
];
|
||||||
|
volumes = [
|
||||||
|
"/var/lib/ollama:/models"
|
||||||
|
];
|
||||||
|
environment = {
|
||||||
|
OLLAMA_ORIGINS = "http://192.168.*";
|
||||||
|
SYCL_PI_LEVEL_ZERO_USE_IMMEDIATE_COMMANDLISTS = "1";
|
||||||
|
ONEAPI_DEVICE_SELECTOR = "level_zero:0";
|
||||||
|
OLLAMA_HOST = "[::]:11434";
|
||||||
|
no_proxy = "localhost,127.0.0.1";
|
||||||
|
DEVICE = "Arc";
|
||||||
|
OLLAMA_NUM_GPU = "999";
|
||||||
|
ZES_ENABLE_SYSMAN = "1";
|
||||||
|
};
|
||||||
|
cmd = [
|
||||||
|
"/bin/sh"
|
||||||
|
"-c"
|
||||||
|
"/llm/scripts/start-ollama.sh && echo 'Startup script finished, container is now idling.' && sleep infinity"
|
||||||
|
];
|
||||||
|
extraOptions = [
|
||||||
|
"--net=host"
|
||||||
|
"--memory=32G"
|
||||||
|
"--shm-size=16g"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
];
|
];
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -7,10 +7,10 @@
|
|||||||
}: let
|
}: let
|
||||||
inherit (lib) types mkOption;
|
inherit (lib) types mkOption;
|
||||||
|
|
||||||
cfg = config.server.postgresql;
|
cfg = config.server.infra.postgresql;
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
server.postgresql = {
|
server.infra.postgresql = {
|
||||||
upgradeTargetPackage = mkOption {
|
upgradeTargetPackage = mkOption {
|
||||||
type = types.nullOr types.package;
|
type = types.nullOr types.package;
|
||||||
default = null;
|
default = null;
|
||||||
@@ -7,7 +7,7 @@
|
|||||||
}: let
|
}: let
|
||||||
inherit (lib) types mkOption;
|
inherit (lib) types mkOption;
|
||||||
|
|
||||||
cfg = config.server.postgresql;
|
cfg = config.server.infra.postgresql;
|
||||||
|
|
||||||
database = {name, ...}: {
|
database = {name, ...}: {
|
||||||
options = {
|
options = {
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
};
|
};
|
||||||
in {
|
in {
|
||||||
options = {
|
options = {
|
||||||
server.postgresql = {
|
server.infra.postgresql = {
|
||||||
databases = mkOption {
|
databases = mkOption {
|
||||||
type = types.listOf (types.submodule database);
|
type = types.listOf (types.submodule database);
|
||||||
default = [];
|
default = [];
|
||||||
@@ -54,14 +54,28 @@ in {
|
|||||||
local all postgres peer
|
local all postgres peer
|
||||||
local sameuser all peer
|
local sameuser all peer
|
||||||
|
|
||||||
# extra users
|
# local peer access for extra users
|
||||||
${lib.concatMapStringsSep "\n" (
|
${lib.concatMapStringsSep "\n" (
|
||||||
{
|
{
|
||||||
database,
|
database,
|
||||||
extraUsers,
|
extraUsers,
|
||||||
...
|
...
|
||||||
}:
|
}:
|
||||||
lib.concatMapStringsSep "\n" (user: "local ${database} ${user} peer") extraUsers
|
lib.concatMapStringsSep "\n" (user: "local ${database} ${user} peer") ([database] ++ extraUsers)
|
||||||
|
)
|
||||||
|
cfg.databases}
|
||||||
|
|
||||||
|
# host access (TCP) for databases and their users
|
||||||
|
${lib.concatMapStringsSep "\n" (
|
||||||
|
{
|
||||||
|
database,
|
||||||
|
extraUsers,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
lib.concatMapStringsSep "\n" (user: ''
|
||||||
|
host ${database} ${user} 127.0.0.1/32 trust
|
||||||
|
host ${database} ${user} ::1/128 trust
|
||||||
|
'') ([database] ++ extraUsers)
|
||||||
)
|
)
|
||||||
cfg.databases}
|
cfg.databases}
|
||||||
'';
|
'';
|
||||||
26
modules/server/infra/tailscale/default.nix
Normal file
26
modules/server/infra/tailscale/default.nix
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}:
|
||||||
|
with lib; let
|
||||||
|
cfg = config.server.infra.tailscale;
|
||||||
|
in {
|
||||||
|
options.server.infra.tailscale = {
|
||||||
|
enable = mkEnableOption "Enable tailscale server configuration";
|
||||||
|
};
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
age.secrets.sobotkaTsAuth.file = "${self}/secrets/sobotkaTsAuth.age";
|
||||||
|
|
||||||
|
services.tailscale = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
useRoutingFeatures = "server";
|
||||||
|
authKeyFile = config.age.secrets.sobotkaTsAuth.path;
|
||||||
|
extraSetFlags = [
|
||||||
|
"--advertise-exit-node"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
183
modules/server/infra/traefik/default.nix
Normal file
183
modules/server/infra/traefik/default.nix
Normal file
@@ -0,0 +1,183 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
clib,
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkEnableOption mkIf types;
|
||||||
|
|
||||||
|
cfg = config.server.infra.traefik;
|
||||||
|
srv = config.server;
|
||||||
|
|
||||||
|
generateRouters = services: config:
|
||||||
|
lib.mapAttrs' (
|
||||||
|
name: service:
|
||||||
|
lib.nameValuePair name {
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
# FIX 3: Use backticks for the Host rule and interpolation
|
||||||
|
rule = "Host(`${clib.server.mkFullDomain config service}`)";
|
||||||
|
service = name;
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
}
|
||||||
|
) (lib.filterAttrs (_: s: s.enable) services);
|
||||||
|
|
||||||
|
generateServices = services:
|
||||||
|
lib.mapAttrs' (name: service:
|
||||||
|
lib.nameValuePair name {
|
||||||
|
loadBalancer.servers = [{url = "http://localhost:${toString service.port}";}];
|
||||||
|
}) (lib.filterAttrs (name: service: service.enable) services);
|
||||||
|
|
||||||
|
getCloudflareCredentials = hostname:
|
||||||
|
if hostname == "ziggy"
|
||||||
|
then config.age.secrets.cloudflareDnsCredentialsZiggy.path
|
||||||
|
else if hostname == "sobotka"
|
||||||
|
then config.age.secrets.cloudflareDnsCredentials.path
|
||||||
|
else throw "Unknown hostname: ${hostname}";
|
||||||
|
in {
|
||||||
|
options.server.infra.traefik = {
|
||||||
|
enable = mkEnableOption "Enable global Traefik reverse proxy with ACME";
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
traefikEnv = {
|
||||||
|
file = "${self}/secrets/traefikEnv.age";
|
||||||
|
mode = "640";
|
||||||
|
owner = "traefik";
|
||||||
|
group = "traefik";
|
||||||
|
};
|
||||||
|
crowdsecApi.file = "${self}/secrets/crowdsecApi.age";
|
||||||
|
};
|
||||||
|
|
||||||
|
systemd.services.traefik = {
|
||||||
|
serviceConfig = {
|
||||||
|
EnvironmentFile = [config.age.secrets.traefikEnv.path];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
networking.firewall.allowedTCPPorts = [80 443];
|
||||||
|
|
||||||
|
services = {
|
||||||
|
tailscale.permitCertUid = "traefik";
|
||||||
|
traefik = {
|
||||||
|
enable = true;
|
||||||
|
|
||||||
|
staticConfigOptions = {
|
||||||
|
log = {
|
||||||
|
level = "DEBUG";
|
||||||
|
};
|
||||||
|
|
||||||
|
accesslog = {filepath = "/var/lib/traefik/logs/access.log";};
|
||||||
|
|
||||||
|
tracing = {};
|
||||||
|
api = {
|
||||||
|
dashboard = true;
|
||||||
|
insecure = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
certificatesResolvers = {
|
||||||
|
vpn.tailscale = {};
|
||||||
|
letsencrypt = {
|
||||||
|
acme = {
|
||||||
|
email = "adam@cnst.dev";
|
||||||
|
storage = "/var/lib/traefik/cert.json";
|
||||||
|
dnsChallenge = {
|
||||||
|
provider = "cloudflare";
|
||||||
|
resolvers = [
|
||||||
|
"1.1.1.1:53"
|
||||||
|
"1.0.0.1:53"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
entryPoints = {
|
||||||
|
# redis = {
|
||||||
|
# address = "0.0.0.0:6381";
|
||||||
|
# };
|
||||||
|
# postgres = {
|
||||||
|
# address = "0.0.0.0:5433";
|
||||||
|
# };
|
||||||
|
web = {
|
||||||
|
address = ":80";
|
||||||
|
forwardedHeaders.insecure = true;
|
||||||
|
http.redirections.entryPoint = {
|
||||||
|
to = "websecure";
|
||||||
|
scheme = "https";
|
||||||
|
permanent = true;
|
||||||
|
};
|
||||||
|
# http.middlewares = "crowdsec@file";
|
||||||
|
};
|
||||||
|
|
||||||
|
websecure = {
|
||||||
|
address = ":443";
|
||||||
|
forwardedHeaders.insecure = true;
|
||||||
|
http.tls = {
|
||||||
|
certResolver = "letsencrypt";
|
||||||
|
domains = [
|
||||||
|
{
|
||||||
|
main = "cnix.dev";
|
||||||
|
sans = ["*.cnix.dev"];
|
||||||
|
}
|
||||||
|
{
|
||||||
|
main = "ts.cnst.dev";
|
||||||
|
sans = ["*ts.cnst.dev"];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
# http.middlewares = "crowdsec@file";
|
||||||
|
};
|
||||||
|
|
||||||
|
experimental = {
|
||||||
|
address = ":1111";
|
||||||
|
forwardedHeaders.insecure = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
experimental = {
|
||||||
|
# Install the Crowdsec Bouncer plugin
|
||||||
|
plugins = {
|
||||||
|
#enabled = "true";
|
||||||
|
bouncer = {
|
||||||
|
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin";
|
||||||
|
version = "v1.4.5";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
dynamicConfigOptions = {
|
||||||
|
http = {
|
||||||
|
services = generateServices srv.services;
|
||||||
|
|
||||||
|
routers =
|
||||||
|
(generateRouters srv.services config)
|
||||||
|
// {
|
||||||
|
api = {
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
rule = "Host(`traefik.${srv.domain}`)";
|
||||||
|
service = "api@internal";
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
# middlewares = {
|
||||||
|
# crowdsec = {
|
||||||
|
# plugin = {
|
||||||
|
# bouncer = {
|
||||||
|
# enabled = "true";
|
||||||
|
# logLevel = "DEBUG";
|
||||||
|
# crowdsecLapiKeyFile = config.age.secrets.crowdsecApi.path;
|
||||||
|
# crowdsecMode = "live";
|
||||||
|
# crowdsecLapiHost = ":4223";
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
# };
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -5,7 +5,20 @@
|
|||||||
...
|
...
|
||||||
}: let
|
}: let
|
||||||
unit = "unbound";
|
unit = "unbound";
|
||||||
cfg = config.server.${unit};
|
cfg = config.server.infra.${unit};
|
||||||
|
srv = config.server;
|
||||||
|
|
||||||
|
svcNames = lib.attrNames srv.services;
|
||||||
|
|
||||||
|
localARecords = builtins.concatLists (map (
|
||||||
|
name: let
|
||||||
|
s = srv.services.${name};
|
||||||
|
in
|
||||||
|
if s != null && s.enable && s.subdomain != null
|
||||||
|
then [''"${s.subdomain}.${srv.domain}. A ${srv.ip}"'']
|
||||||
|
else []
|
||||||
|
)
|
||||||
|
svcNames);
|
||||||
|
|
||||||
hostIp = hostname:
|
hostIp = hostname:
|
||||||
if hostname == "ziggy"
|
if hostname == "ziggy"
|
||||||
@@ -14,11 +27,12 @@
|
|||||||
then "192.168.88.14"
|
then "192.168.88.14"
|
||||||
else throw "No IP defined for host ${hostname}";
|
else throw "No IP defined for host ${hostname}";
|
||||||
in {
|
in {
|
||||||
options.server.${unit} = {
|
options.server.infra.${unit} = {
|
||||||
enable = lib.mkEnableOption {
|
enable = lib.mkEnableOption {
|
||||||
description = "Enable ${unit}";
|
description = "Enable ${unit}";
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
services = {
|
services = {
|
||||||
# resolved.enable = lib.mkForce false;
|
# resolved.enable = lib.mkForce false;
|
||||||
@@ -97,6 +111,11 @@ in {
|
|||||||
"255.255.255.255/32"
|
"255.255.255.255/32"
|
||||||
"2001:db8::/32"
|
"2001:db8::/32"
|
||||||
];
|
];
|
||||||
|
local-data =
|
||||||
|
[
|
||||||
|
''"traefik.${config.settings.accounts.domains.local}. A 192.168.88.14"''
|
||||||
|
]
|
||||||
|
++ localARecords;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
135
modules/server/infra/www/default.nix
Normal file
135
modules/server/infra/www/default.nix
Normal file
@@ -0,0 +1,135 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkIf mkEnableOption mkOption types;
|
||||||
|
cfg = config.server.infra.www;
|
||||||
|
in {
|
||||||
|
options.server.infra.www = {
|
||||||
|
enable = mkEnableOption {
|
||||||
|
description = "Enable personal website";
|
||||||
|
};
|
||||||
|
url = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Public domain name to be used to access the server services via Traefik reverse proxy
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 8283;
|
||||||
|
description = "The port to host webservice on.";
|
||||||
|
};
|
||||||
|
|
||||||
|
cloudflared = {
|
||||||
|
credentialsFile = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
pkgs.writeText "cloudflare-credentials.json" '''
|
||||||
|
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
tunnelId = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "00000000-0000-0000-0000-000000000000";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
wwwCloudflared.file = "${self}/secrets/wwwCloudflared.age";
|
||||||
|
};
|
||||||
|
|
||||||
|
server.infra = {
|
||||||
|
fail2ban = {
|
||||||
|
jails = {
|
||||||
|
nginx-404 = {
|
||||||
|
serviceName = "nginx";
|
||||||
|
failRegex = ''^.*\[error\].*directory index of.* is forbidden.*client: <HOST>.*$'';
|
||||||
|
ignoreRegex = '''';
|
||||||
|
maxRetry = 5;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
nginx = {
|
||||||
|
enable = true;
|
||||||
|
defaultListen = [
|
||||||
|
{
|
||||||
|
addr = "127.0.0.1";
|
||||||
|
port = 8283;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
virtualHosts."webfinger" = {
|
||||||
|
forceSSL = false;
|
||||||
|
serverName = cfg.url;
|
||||||
|
root = "/var/www/webfinger";
|
||||||
|
|
||||||
|
locations."= /.well-known/webfinger" = {
|
||||||
|
root = "/var/www/webfinger";
|
||||||
|
extraConfig = ''
|
||||||
|
default_type application/jrd+json;
|
||||||
|
try_files /.well-known/webfinger =404;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
locations."= /robots.txt" = {
|
||||||
|
root = "/var/www/webfinger";
|
||||||
|
extraConfig = ''
|
||||||
|
default_type text/plain;
|
||||||
|
try_files /robots.txt =404;
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
cloudflared = {
|
||||||
|
enable = true;
|
||||||
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
|
default = "http_status:404";
|
||||||
|
ingress."${cfg.url}".service = "http://127.0.0.1:8283";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
environment.etc = {
|
||||||
|
"webfinger/.well-known/webfinger".text = ''
|
||||||
|
{
|
||||||
|
"subject": "acct:adam@${cfg.url}",
|
||||||
|
"links": [
|
||||||
|
{
|
||||||
|
"rel": "http://openid.net/specs/connect/1.0/issuer",
|
||||||
|
"href": "https://auth.${cfg.url}/application/o/tailscale/"
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
'';
|
||||||
|
|
||||||
|
"webfinger/robots.txt".text = ''
|
||||||
|
User-agent: *
|
||||||
|
Disallow: /
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services.traefik.dynamicConfigOptions.http = {
|
||||||
|
routers.webfinger = {
|
||||||
|
entryPoints = ["websecure"];
|
||||||
|
rule = "Host(`${cfg.url}`) && Path(`/.well-known/webfinger`)";
|
||||||
|
service = "webfinger";
|
||||||
|
tls.certResolver = "letsencrypt";
|
||||||
|
};
|
||||||
|
|
||||||
|
services.webfinger.loadBalancer.servers = [
|
||||||
|
{url = "http://127.0.0.1:8283";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,58 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
service = "jellyfin";
|
|
||||||
cfg = config.server.${service};
|
|
||||||
srv = config.server;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${service} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${service}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${service}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "jellyfin.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Jellyfin";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "The Free Software Media System";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "jellyfin.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Media";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${service} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
group = srv.group;
|
|
||||||
};
|
|
||||||
environment.systemPackages = with pkgs; [
|
|
||||||
jellyfin-ffmpeg
|
|
||||||
];
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:8096
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,53 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
service = "jellyseerr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${service};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${service} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${service}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${service}.${srv.domain}";
|
|
||||||
};
|
|
||||||
port = lib.mkOption {
|
|
||||||
type = lib.types.port;
|
|
||||||
default = 5055;
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Jellyseerr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Media request and discovery manager";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "jellyseerr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${service} = {
|
|
||||||
enable = true;
|
|
||||||
port = cfg.port;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString cfg.port}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "lidarr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Lidarr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Music collection manager";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "lidarr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
group = srv.group;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:8686
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,138 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
pkgs,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "nextcloud";
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
srv = config.server;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
adminUser = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "cnst";
|
|
||||||
};
|
|
||||||
adminPass = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "cloud.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Nextcloud";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "A safe home for all your data";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "nextcloud.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Services";
|
|
||||||
};
|
|
||||||
cloudflared = {
|
|
||||||
credentialsFile = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = lib.literalExpression ''
|
|
||||||
pkgs.writeText "cloudflare-credentials.json" '''
|
|
||||||
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
|
||||||
'''
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
tunnelId = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "00000000-0000-0000-0000-000000000000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
server = {
|
|
||||||
postgresql.databases = [
|
|
||||||
{
|
|
||||||
database = "nextcloud";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
|
||||||
jails = {
|
|
||||||
nextcloud = {
|
|
||||||
serviceName = "phpfm-nextcloud";
|
|
||||||
failRegex = "^.*Login failed:.*(Remote IP: <HOST>).*$";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
cloudflared = {
|
|
||||||
enable = true;
|
|
||||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
|
||||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
|
||||||
default = "http_status:404";
|
|
||||||
ingress."${cfg.url}".service = "http://127.0.0.1:8083";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
${unit} = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.nextcloud31;
|
|
||||||
hostName = "nextcloud";
|
|
||||||
configureRedis = true;
|
|
||||||
caching = {
|
|
||||||
redis = true;
|
|
||||||
};
|
|
||||||
maxUploadSize = "50G";
|
|
||||||
settings = {
|
|
||||||
trusted_proxies = [ "127.0.0.1" ];
|
|
||||||
overwriteprotocol = "https";
|
|
||||||
overwritehost = "cloud.${srv.domain}";
|
|
||||||
overwrite.cli.url = "https://cloud.${srv.domain}";
|
|
||||||
mail_smtpmode = "sendmail";
|
|
||||||
mail_sendmailmode = "pipe";
|
|
||||||
user_oidc = {
|
|
||||||
allow_multiple_user_backends = 0;
|
|
||||||
};
|
|
||||||
forwarded_for_headers = [
|
|
||||||
"HTTP_CF_CONNECTING_IP"
|
|
||||||
];
|
|
||||||
enabledPreviewProviders = [
|
|
||||||
"OC\\Preview\\BMP"
|
|
||||||
"OC\\Preview\\GIF"
|
|
||||||
"OC\\Preview\\JPEG"
|
|
||||||
"OC\\Preview\\Krita"
|
|
||||||
"OC\\Preview\\MarkDown"
|
|
||||||
"OC\\Preview\\MP3"
|
|
||||||
"OC\\Preview\\OpenDocument"
|
|
||||||
"OC\\Preview\\PNG"
|
|
||||||
"OC\\Preview\\TXT"
|
|
||||||
"OC\\Preview\\XBitmap"
|
|
||||||
"OC\\Preview\\HEIC"
|
|
||||||
];
|
|
||||||
};
|
|
||||||
config = {
|
|
||||||
dbtype = "pgsql";
|
|
||||||
dbuser = "nextcloud";
|
|
||||||
dbhost = "/run/postgresql";
|
|
||||||
dbname = "nextcloud";
|
|
||||||
adminuser = cfg.adminUser;
|
|
||||||
adminpassFile = cfg.adminPass;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
180
modules/server/options.nix
Normal file
180
modules/server/options.nix
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) mkOption types;
|
||||||
|
ifTheyExist = groups: builtins.filter (group: builtins.hasAttr group config.users.groups) groups;
|
||||||
|
cfg = config.server;
|
||||||
|
in {
|
||||||
|
options.server = {
|
||||||
|
enable = lib.mkEnableOption "The server services and configuration variables";
|
||||||
|
email = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Email name to be used to access the server services via Caddy reverse proxy
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
domain = mkOption {
|
||||||
|
default = "";
|
||||||
|
type = types.str;
|
||||||
|
description = ''
|
||||||
|
Domain name to be used to access the server services via Caddy reverse proxy
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
ip = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "127.0.0.1";
|
||||||
|
description = "The local IP of the service.";
|
||||||
|
};
|
||||||
|
user = lib.mkOption {
|
||||||
|
default = "share";
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
User to run the server services as
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
group = lib.mkOption {
|
||||||
|
default = "share";
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
Group to run the server services as
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
uid = lib.mkOption {
|
||||||
|
default = 1000;
|
||||||
|
type = lib.types.int;
|
||||||
|
description = ''
|
||||||
|
UID to run the server services as
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
gid = lib.mkOption {
|
||||||
|
default = 1000;
|
||||||
|
type = lib.types.int;
|
||||||
|
description = ''
|
||||||
|
GID to run the server services as
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
timeZone = lib.mkOption {
|
||||||
|
default = "Europe/Stockholm";
|
||||||
|
type = lib.types.str;
|
||||||
|
description = ''
|
||||||
|
Time zone to be used for the server services
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
services = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
enable = lib.mkEnableOption "the service";
|
||||||
|
subdomain = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
description = "The subdomain for the service (e.g., 'jellyfin')";
|
||||||
|
};
|
||||||
|
exposure = lib.mkOption {
|
||||||
|
type = lib.types.enum ["local" "tunnel" "tailscale"];
|
||||||
|
default = "local";
|
||||||
|
description = "Controls where the service is exposed";
|
||||||
|
};
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 80;
|
||||||
|
description = "The port to host service on.";
|
||||||
|
};
|
||||||
|
configDir = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
default = "/var/lib/${name}";
|
||||||
|
description = "Configuration directory for ${name}.";
|
||||||
|
};
|
||||||
|
cloudflared = lib.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
credentialsFile = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = lib.literalExpression ''
|
||||||
|
pkgs.writeText "cloudflare-credentials.json" '''
|
||||||
|
{"AccountTag":"secret","TunnelSecret":"secret","TunnelID":"secret"}
|
||||||
|
'''
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
tunnelId = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
example = "00000000-0000-0000-0000-000000000000";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
description = "Cloudflare tunnel configuration for this service.";
|
||||||
|
};
|
||||||
|
homepage = lib.mkOption {
|
||||||
|
type = lib.types.submodule {
|
||||||
|
options = {
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
description = "Display name on the homepage.";
|
||||||
|
};
|
||||||
|
description = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
description = "A short description for the homepage tile.";
|
||||||
|
};
|
||||||
|
icon = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "Zervices c00l stuff";
|
||||||
|
description = "Icon file name for the homepage tile.";
|
||||||
|
};
|
||||||
|
category = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
description = "Homepage category grouping.";
|
||||||
|
};
|
||||||
|
path = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "";
|
||||||
|
example = "/admin";
|
||||||
|
description = "Optional path suffix for homepage links (e.g. /admin).";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
description = "Homepage metadata for this service.";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
};
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
users = {
|
||||||
|
groups.${cfg.group} = {
|
||||||
|
gid = cfg.gid;
|
||||||
|
};
|
||||||
|
users.${cfg.user} = {
|
||||||
|
uid = cfg.uid;
|
||||||
|
isSystemUser = true;
|
||||||
|
group = cfg.group;
|
||||||
|
extraGroups = ifTheyExist [
|
||||||
|
"audio"
|
||||||
|
"video"
|
||||||
|
"docker"
|
||||||
|
"libvirtd"
|
||||||
|
"qemu-libvirtd"
|
||||||
|
"rtkit"
|
||||||
|
"fail2ban"
|
||||||
|
"vaultwarden"
|
||||||
|
"qbittorrent"
|
||||||
|
"lidarr"
|
||||||
|
"prowlarr"
|
||||||
|
"bazarr"
|
||||||
|
"sonarr"
|
||||||
|
"radarr"
|
||||||
|
"media"
|
||||||
|
"share"
|
||||||
|
"render"
|
||||||
|
"input"
|
||||||
|
"authentik"
|
||||||
|
"traefik"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,66 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "prowlarr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Prowlarr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "PVR indexer";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "prowlarr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services = {
|
|
||||||
${unit} = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
flaresolverr = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
|
|
||||||
caddy = {
|
|
||||||
virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:9696
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
virtualHosts."flaresolverr.${srv.domain}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:8191
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "radarr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Radarr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Film collection manager";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "radarr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
group = srv.group;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:7878
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
17
modules/server/services/bazarr/default.nix
Normal file
17
modules/server/services/bazarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "bazarr";
|
||||||
|
srv = config.server;
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
user = srv.user;
|
||||||
|
group = srv.group;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
19
modules/server/services/default.nix
Normal file
19
modules/server/services/default.nix
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
{
|
||||||
|
imports = [
|
||||||
|
./bazarr
|
||||||
|
./flaresolverr
|
||||||
|
./gitea
|
||||||
|
./homepage-dashboard
|
||||||
|
./jellyfin
|
||||||
|
./jellyseerr
|
||||||
|
./lidarr
|
||||||
|
./n8n
|
||||||
|
./nextcloud
|
||||||
|
./ollama
|
||||||
|
./prowlarr
|
||||||
|
./radarr
|
||||||
|
./sonarr
|
||||||
|
./uptime-kuma
|
||||||
|
./vaultwarden
|
||||||
|
];
|
||||||
|
}
|
||||||
16
modules/server/services/flaresolverr/default.nix
Normal file
16
modules/server/services/flaresolverr/default.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "flaresolverr";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services = {
|
||||||
|
${unit} = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
94
modules/server/services/gitea/default.nix
Normal file
94
modules/server/services/gitea/default.nix
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "gitea";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
age.secrets.giteaCloudflared.file = "${self}/secrets/giteaCloudflared.age";
|
||||||
|
|
||||||
|
server.infra = {
|
||||||
|
fail2ban.jails.${unit} = {
|
||||||
|
serviceName = "${unit}";
|
||||||
|
failRegex = ''.*(Failed authentication attempt|invalid credentials|Attempted access of unknown user).* from <HOST>'';
|
||||||
|
};
|
||||||
|
|
||||||
|
postgresql.databases = [
|
||||||
|
{database = "gitea";}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
cloudflared = {
|
||||||
|
enable = true;
|
||||||
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
|
default = "http_status:404";
|
||||||
|
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
gitea = {
|
||||||
|
enable = true;
|
||||||
|
appName = "cnix code forge";
|
||||||
|
|
||||||
|
database = {
|
||||||
|
type = "postgres";
|
||||||
|
socket = "/run/postgresql";
|
||||||
|
name = "gitea";
|
||||||
|
user = "gitea";
|
||||||
|
createDatabase = false;
|
||||||
|
};
|
||||||
|
|
||||||
|
lfs.enable = true;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
cors = {
|
||||||
|
ENABLED = true;
|
||||||
|
SCHEME = "https";
|
||||||
|
ALLOW_DOMAIN = domain;
|
||||||
|
};
|
||||||
|
|
||||||
|
log.MODE = "console";
|
||||||
|
|
||||||
|
mailer = {
|
||||||
|
ENABLED = false;
|
||||||
|
MAILER_TYPE = "sendmail";
|
||||||
|
FROM = "noreply+adam@cnst.dev";
|
||||||
|
SENDMAIL_PATH = "/run/wrappers/bin/sendmail";
|
||||||
|
};
|
||||||
|
|
||||||
|
picture.DISABLE_GRAVATAR = true;
|
||||||
|
|
||||||
|
repository = {
|
||||||
|
DEFAULT_BRANCH = "main";
|
||||||
|
DEFAULT_REPO_UNITS = "repo.code,repo.issues,repo.pulls";
|
||||||
|
DISABLE_DOWNLOAD_SOURCE_ARCHIVES = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
indexer.REPO_INDEXER_ENABLED = true;
|
||||||
|
|
||||||
|
oauth2_client = {
|
||||||
|
ENABLE_AUTO_REGISTRATION = true;
|
||||||
|
ACCOUNT_LINKING = "auto";
|
||||||
|
};
|
||||||
|
|
||||||
|
server = {
|
||||||
|
DOMAIN = domain;
|
||||||
|
LANDING_PAGE = "explore";
|
||||||
|
HTTP_PORT = cfg.port;
|
||||||
|
ROOT_URL = "https://${domain}/";
|
||||||
|
};
|
||||||
|
|
||||||
|
security.DISABLE_GIT_HOOKS = false;
|
||||||
|
service.DISABLE_REGISTRATION = true;
|
||||||
|
session.COOKIE_SECURE = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
227
modules/server/services/homepage-dashboard/default.nix
Normal file
227
modules/server/services/homepage-dashboard/default.nix
Normal file
@@ -0,0 +1,227 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
clib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "homepage-dashboard";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
srv = config.server;
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
homepageEnvironment = {
|
||||||
|
file = "${self}/secrets/homepageEnvironment.age";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
glances.enable = true;
|
||||||
|
|
||||||
|
${unit} = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = config.age.secrets.homepageEnvironment.path;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
color = "stone";
|
||||||
|
theme = "dark";
|
||||||
|
headerStyle = "clean";
|
||||||
|
statusStyle = "dot";
|
||||||
|
hideVersion = true;
|
||||||
|
useEqualHeights = true;
|
||||||
|
|
||||||
|
layout = [
|
||||||
|
{
|
||||||
|
Glances = {
|
||||||
|
header = false;
|
||||||
|
style = "row";
|
||||||
|
columns = 4;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Arr = {
|
||||||
|
header = true;
|
||||||
|
style = "column";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Downloads = {
|
||||||
|
header = true;
|
||||||
|
style = "column";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Media = {
|
||||||
|
header = true;
|
||||||
|
style = "column";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Services = {
|
||||||
|
header = true;
|
||||||
|
style = "column";
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
widgets = [
|
||||||
|
{
|
||||||
|
openmeteo = {
|
||||||
|
label = "Kalmar";
|
||||||
|
timezone = "Europe/Stockholm";
|
||||||
|
units = "metric";
|
||||||
|
cache = 5;
|
||||||
|
latitude = 56.707262;
|
||||||
|
longitude = 16.324541;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
resources = {
|
||||||
|
label = "SYSTEM";
|
||||||
|
memory = true;
|
||||||
|
cpu = true;
|
||||||
|
uptime = false;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
services = let
|
||||||
|
homepageCategories = [
|
||||||
|
"Arr"
|
||||||
|
"Media"
|
||||||
|
"Downloads"
|
||||||
|
"Services"
|
||||||
|
];
|
||||||
|
allServices = srv.services;
|
||||||
|
|
||||||
|
getDomain = s: clib.server.mkHostDomain config s;
|
||||||
|
|
||||||
|
homepageServicesFor = category:
|
||||||
|
lib.filterAttrs
|
||||||
|
(
|
||||||
|
name: value:
|
||||||
|
name
|
||||||
|
!= unit
|
||||||
|
&& value ? homepage
|
||||||
|
&& value.homepage.category == category
|
||||||
|
)
|
||||||
|
allServices;
|
||||||
|
in
|
||||||
|
lib.lists.forEach homepageCategories (cat: {
|
||||||
|
"${cat}" =
|
||||||
|
lib.lists.forEach
|
||||||
|
(lib.attrsets.mapAttrsToList (name: _value: name) (homepageServicesFor cat))
|
||||||
|
(x: let
|
||||||
|
service = allServices.${x};
|
||||||
|
domain = getDomain service;
|
||||||
|
in {
|
||||||
|
"${service.homepage.name}" = {
|
||||||
|
icon = service.homepage.icon;
|
||||||
|
description = service.homepage.description;
|
||||||
|
href = "https://${service.subdomain}.${domain}${service.homepage.path or ""}";
|
||||||
|
siteMonitor = "https://${service.subdomain}.${domain}${x.homepage.path or ""}";
|
||||||
|
};
|
||||||
|
});
|
||||||
|
})
|
||||||
|
++ [
|
||||||
|
{
|
||||||
|
Glances = let
|
||||||
|
glancesShared = {
|
||||||
|
type = "glances";
|
||||||
|
url = "http://localhost:${toString config.services.glances.port}";
|
||||||
|
chart = true;
|
||||||
|
version = 4;
|
||||||
|
};
|
||||||
|
in [
|
||||||
|
{
|
||||||
|
Memory = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "memory";
|
||||||
|
refreshInterval = 2000;
|
||||||
|
pointsLimit = 30;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"CPU Usage" = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "cpu";
|
||||||
|
refreshInterval = 2000;
|
||||||
|
pointsLimit = 30;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
"CPU Temp" = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "sensor:Tctl";
|
||||||
|
refreshInterval = 5000;
|
||||||
|
pointsLimit = 20;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"GPU Radeon" = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "sensor:junction";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"GPU Intel" = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "sensor:pkg";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
"ZFS Pool" = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "fs:/mnt/data";
|
||||||
|
refreshInterval = 30000;
|
||||||
|
pointsLimit = 20;
|
||||||
|
diskUnits = "bytes";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
Processes = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "process";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
{
|
||||||
|
Network = {
|
||||||
|
widget =
|
||||||
|
glancesShared
|
||||||
|
// {
|
||||||
|
metric = "network:enp6s0";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
21
modules/server/services/jellyfin/default.nix
Normal file
21
modules/server/services/jellyfin/default.nix
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "jellyfin";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
srv = config.server;
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
user = srv.user;
|
||||||
|
group = srv.group;
|
||||||
|
};
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
jellyfin-ffmpeg
|
||||||
|
];
|
||||||
|
};
|
||||||
|
}
|
||||||
15
modules/server/services/jellyseerr/default.nix
Normal file
15
modules/server/services/jellyseerr/default.nix
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "jellyseerr";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
port = cfg.port;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
17
modules/server/services/lidarr/default.nix
Normal file
17
modules/server/services/lidarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "lidarr";
|
||||||
|
srv = config.server;
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
user = srv.user;
|
||||||
|
group = srv.group;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
17
modules/server/services/n8n/default.nix
Normal file
17
modules/server/services/n8n/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "n8n";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services = {
|
||||||
|
n8n = {
|
||||||
|
enable = true;
|
||||||
|
openFirewall = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
101
modules/server/services/nextcloud/default.nix
Normal file
101
modules/server/services/nextcloud/default.nix
Normal file
@@ -0,0 +1,101 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "nextcloud";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
srv = config.server;
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
nextcloudAdminPass.file = "${self}/secrets/nextcloudAdminPass.age";
|
||||||
|
nextcloudCloudflared.file = "${self}/secrets/nextcloudCloudflared.age";
|
||||||
|
};
|
||||||
|
|
||||||
|
server.infra.fail2ban.jails.nextcloud = {
|
||||||
|
serviceName = "${unit}";
|
||||||
|
_groupsre = ''(?:(?:,?\s*"\w+":(?:"[^"]+"|\w+))*)'';
|
||||||
|
failRegex = ''
|
||||||
|
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Login failed:
|
||||||
|
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Two-factor challenge failed:
|
||||||
|
^\{%(_groupsre)s,?\s*"remoteAddr":"<HOST>"%(_groupsre)s,?\s*"message":"Trusted domain error.
|
||||||
|
'';
|
||||||
|
datePattern = '',?\s*"time"\s*:\s*"%%Y-%%m-%%d[T ]%%H:%%M:%%S(%%z)?"'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
${unit} = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.nextcloud32;
|
||||||
|
hostName = "nextcloud";
|
||||||
|
configureRedis = true;
|
||||||
|
caching = {
|
||||||
|
redis = true;
|
||||||
|
};
|
||||||
|
phpOptions = {
|
||||||
|
"opcache.interned_strings_buffer" = "32";
|
||||||
|
};
|
||||||
|
maxUploadSize = "50G";
|
||||||
|
settings = {
|
||||||
|
maintenance_window_start = "1";
|
||||||
|
trusted_proxies = [
|
||||||
|
"127.0.0.1"
|
||||||
|
"::1"
|
||||||
|
];
|
||||||
|
trusted_domains = ["cloud.${srv.domain}"];
|
||||||
|
overwriteprotocol = "https";
|
||||||
|
enabledPreviewProviders = [
|
||||||
|
"OC\\Preview\\BMP"
|
||||||
|
"OC\\Preview\\GIF"
|
||||||
|
"OC\\Preview\\JPEG"
|
||||||
|
"OC\\Preview\\Krita"
|
||||||
|
"OC\\Preview\\MarkDown"
|
||||||
|
"OC\\Preview\\MP3"
|
||||||
|
"OC\\Preview\\OpenDocument"
|
||||||
|
"OC\\Preview\\PNG"
|
||||||
|
"OC\\Preview\\TXT"
|
||||||
|
"OC\\Preview\\XBitmap"
|
||||||
|
"OC\\Preview\\HEIC"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
config = {
|
||||||
|
dbtype = "pgsql";
|
||||||
|
dbuser = "nextcloud";
|
||||||
|
dbhost = "/run/postgresql";
|
||||||
|
dbname = "nextcloud";
|
||||||
|
adminuser = "cnst";
|
||||||
|
adminpassFile = config.age.secrets.nextcloudAdminPass.path;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nginx = {
|
||||||
|
defaultListen = [
|
||||||
|
{
|
||||||
|
addr = "127.0.0.1";
|
||||||
|
port = 8182;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
addr = "127.0.0.1";
|
||||||
|
port = 8482;
|
||||||
|
}
|
||||||
|
];
|
||||||
|
virtualHosts.nextcloud = {
|
||||||
|
forceSSL = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
server.infra.postgresql.databases = [
|
||||||
|
{
|
||||||
|
database = "nextcloud";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
systemd.services."nextcloud-setup" = {
|
||||||
|
requires = ["postgresql.service"];
|
||||||
|
after = ["postgresql.service"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
28
modules/server/services/ollama/default.nix
Normal file
28
modules/server/services/ollama/default.nix
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "ollama";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
environment.systemPackages = with pkgs; [
|
||||||
|
ollama
|
||||||
|
intel-compute-runtime
|
||||||
|
intel-graphics-compiler
|
||||||
|
level-zero
|
||||||
|
];
|
||||||
|
services.open-webui = {
|
||||||
|
enable = true;
|
||||||
|
host = "0.0.0.0";
|
||||||
|
port = 8001;
|
||||||
|
environment = {
|
||||||
|
ANONYMIZED_TELEMETRY = "False";
|
||||||
|
BYPASS_MODEL_ACCESS_CONTROL = "True";
|
||||||
|
OLLAMA_BASE_URL = "http://localhost:11434";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
16
modules/server/services/prowlarr/default.nix
Normal file
16
modules/server/services/prowlarr/default.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "prowlarr";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services = {
|
||||||
|
${unit} = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
17
modules/server/services/radarr/default.nix
Normal file
17
modules/server/services/radarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "radarr";
|
||||||
|
srv = config.server;
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
user = srv.user;
|
||||||
|
group = srv.group;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
17
modules/server/services/sonarr/default.nix
Normal file
17
modules/server/services/sonarr/default.nix
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "sonarr";
|
||||||
|
srv = config.server;
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services.${unit} = {
|
||||||
|
enable = true;
|
||||||
|
user = srv.user;
|
||||||
|
group = srv.group;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
16
modules/server/services/uptime-kuma/default.nix
Normal file
16
modules/server/services/uptime-kuma/default.nix
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "uptime-kuma";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
services = {
|
||||||
|
${unit} = {
|
||||||
|
enable = true;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
59
modules/server/services/vaultwarden/default.nix
Normal file
59
modules/server/services/vaultwarden/default.nix
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
# from @fufexan & @notthebee
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
self,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
unit = "vaultwarden";
|
||||||
|
cfg = config.server.services.${unit};
|
||||||
|
domain = "${cfg.subdomain}.${config.server.infra.www.url}";
|
||||||
|
in {
|
||||||
|
config = lib.mkIf cfg.enable {
|
||||||
|
age.secrets = {
|
||||||
|
vaultwardenCloudflared.file = "${self}/secrets/vaultwardenCloudflared.age";
|
||||||
|
vaultwardenEnvironment.file = "${self}/secrets/vaultwardenEnvironment.age";
|
||||||
|
};
|
||||||
|
|
||||||
|
server.infra.fail2ban.jails.${unit} = {
|
||||||
|
serviceName = "${unit}";
|
||||||
|
failRegex = ''^.*?Username or password is incorrect\. Try again\. IP: <ADDR>\. Username:.*$'';
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
cloudflared = {
|
||||||
|
enable = true;
|
||||||
|
tunnels.${cfg.cloudflared.tunnelId} = {
|
||||||
|
credentialsFile = cfg.cloudflared.credentialsFile;
|
||||||
|
default = "http_status:404";
|
||||||
|
ingress."${domain}".service = "http://localhost:${toString cfg.port}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
vaultwarden = {
|
||||||
|
enable = true;
|
||||||
|
environmentFile = config.age.secrets.vaultwardenEnvironment.path;
|
||||||
|
|
||||||
|
backupDir = "/var/backup/vaultwarden";
|
||||||
|
|
||||||
|
config = {
|
||||||
|
DOMAIN = "https://${domain}";
|
||||||
|
SIGNUPS_ALLOWED = false;
|
||||||
|
ROCKET_ADDRESS = "127.0.0.1";
|
||||||
|
ROCKET_PORT = cfg.port;
|
||||||
|
IP_HEADER = "CF-Connecting-IP";
|
||||||
|
|
||||||
|
logLevel = "warn";
|
||||||
|
extendedLogging = true;
|
||||||
|
useSyslog = true;
|
||||||
|
invitationsAllowed = true;
|
||||||
|
showPasswordHint = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
systemd.services.backup-vaultwarden.serviceConfig = {
|
||||||
|
User = "root";
|
||||||
|
Group = "root";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "sonarr";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Sonarr";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Series collection manager";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "sonarr.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Arr";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
group = srv.group;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:8989
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
unit = "syncthing";
|
|
||||||
srv = config.server;
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
in {
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${unit}.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Syncthing";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Continuous file synchronization program";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "syncthing.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Services";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
networking.firewall = {
|
|
||||||
allowedTCPPorts = [
|
|
||||||
8384
|
|
||||||
22000
|
|
||||||
];
|
|
||||||
allowedUDPPorts = [
|
|
||||||
22000
|
|
||||||
21027
|
|
||||||
];
|
|
||||||
};
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
user = srv.user;
|
|
||||||
guiAddress = "0.0.0.0:8384";
|
|
||||||
overrideFolders = false;
|
|
||||||
overrideDevices = false;
|
|
||||||
dataDir = "/home/${srv.user}/syncthing";
|
|
||||||
configDir = "/home/${srv.user}/syncthing/.config/syncthing";
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:8384
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,52 +0,0 @@
|
|||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
unit = "uptime-kuma";
|
|
||||||
cfg = config.server.${unit};
|
|
||||||
srv = config.server;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.${unit} = {
|
|
||||||
enable = lib.mkEnableOption {
|
|
||||||
description = "Enable ${unit}";
|
|
||||||
};
|
|
||||||
configDir = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "/var/lib/uptime-kuma";
|
|
||||||
};
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "uptime.${srv.domain}";
|
|
||||||
};
|
|
||||||
homepage.name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Uptime Kuma";
|
|
||||||
};
|
|
||||||
homepage.description = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Service monitoring tool";
|
|
||||||
};
|
|
||||||
homepage.icon = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "uptime-kuma.svg";
|
|
||||||
};
|
|
||||||
homepage.category = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "Services";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
config = lib.mkIf cfg.enable {
|
|
||||||
services.${unit} = {
|
|
||||||
enable = true;
|
|
||||||
};
|
|
||||||
services.caddy.virtualHosts."${cfg.url}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:3001
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
@@ -1,85 +0,0 @@
|
|||||||
# from @fufexan & @notthebee
|
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
|
||||||
vcfg = config.services.vaultwarden.config;
|
|
||||||
cfg = config.server.vaultwarden;
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
|
||||||
server.vaultwarden = {
|
|
||||||
enable = mkEnableOption "Enables vaultwarden";
|
|
||||||
url = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = "${cfg.domain}";
|
|
||||||
};
|
|
||||||
cloudflared = {
|
|
||||||
credentialsFile = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = lib.literalExpression ''
|
|
||||||
pkgs.writeText "cloudflare-credentials.json" '''
|
|
||||||
{"AccountTag":"secret"."TunnelSecret":"secret","TunnelID":"secret"}
|
|
||||||
'''
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
tunnelId = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
example = "00000000-0000-0000-0000-000000000000";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = mkIf cfg.enable {
|
|
||||||
server = {
|
|
||||||
fail2ban = lib.mkIf config.server.fail2ban.enable {
|
|
||||||
jails = {
|
|
||||||
vaultwarden = {
|
|
||||||
serviceName = "vaultwarden";
|
|
||||||
failRegex = "^.*Username or password is incorrect. Try again. IP: <HOST>. Username: <F-USER>.*</F-USER>.$";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
systemd.services.backup-vaultwarden.serviceConfig = {
|
|
||||||
User = "root";
|
|
||||||
Group = "root";
|
|
||||||
};
|
|
||||||
|
|
||||||
services = {
|
|
||||||
vaultwarden = {
|
|
||||||
enable = true;
|
|
||||||
environmentFile = config.age.secrets.vaultwardenEnvironment.path;
|
|
||||||
|
|
||||||
backupDir = "/var/backup/vaultwarden";
|
|
||||||
|
|
||||||
config = {
|
|
||||||
DOMAIN = "https://${cfg.url}";
|
|
||||||
SIGNUPS_ALLOWED = false;
|
|
||||||
ROCKET_ADDRESS = "127.0.0.1";
|
|
||||||
ROCKET_PORT = 8222;
|
|
||||||
IP_HEADER = "CF-Connecting-IP";
|
|
||||||
|
|
||||||
logLevel = "warn";
|
|
||||||
extendedLogging = true;
|
|
||||||
useSyslog = true;
|
|
||||||
invitationsAllowed = false;
|
|
||||||
showPasswordHint = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
cloudflared = {
|
|
||||||
enable = true;
|
|
||||||
tunnels.${cfg.cloudflared.tunnelId} = {
|
|
||||||
credentialsFile = cfg.cloudflared.credentialsFile;
|
|
||||||
default = "http_status:404";
|
|
||||||
ingress."${cfg.url}".service = "http://${vcfg.ROCKET_ADDRESS}:${toString vcfg.ROCKET_PORT}";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user