summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authoradikro <adikro@disroot.org>2026-06-27 02:41:27 +0200
committeradikro <adikro@disroot.org>2026-06-27 02:41:27 +0200
commit9b8f9a4bf5e13efe49ec101f127d0df3d7bb3cf3 (patch)
treeb857cd260647dea82b0c63367eef9fa18cd63b8d
parent30f34740891096471b5663704fbbd9bf67ebe885 (diff)
revamped sanoid, syncoid and nfs
-rw-r--r--flake.lock72
-rw-r--r--hosts/bibus-lab/disko.nix111
-rw-r--r--os/core/networking.nix23
-rw-r--r--os/srv/authelia.nix152
-rw-r--r--os/srv/backup.nix110
-rw-r--r--os/srv/cluster.nix16
-rw-r--r--os/srv/crowdsec.nix81
-rw-r--r--os/srv/default.nix4
-rw-r--r--os/srv/gaming.nix27
-rw-r--r--os/srv/headscale.nix40
-rw-r--r--os/srv/i2p.nix98
-rw-r--r--os/srv/lldap.nix52
-rw-r--r--os/srv/monero.nix88
-rw-r--r--os/srv/nfs.nix13
-rw-r--r--os/srv/nginx.nix2
-rw-r--r--os/srv/postgres.nix72
-rw-r--r--os/srv/redis.nix37
-rw-r--r--os/srv/restic.nix12
-rw-r--r--os/srv/wireguard.nix8
-rw-r--r--os/srv/zfs.nix48
20 files changed, 811 insertions, 255 deletions
diff --git a/flake.lock b/flake.lock
index 481872c..0bbd8f4 100644
--- a/flake.lock
+++ b/flake.lock
@@ -374,11 +374,11 @@
]
},
"locked": {
- "lastModified": 1782051614,
- "narHash": "sha256-xBRAhYLEXcjp8hM2tkkTTLb6PWU7VDxDoogl25g7Ezs=",
+ "lastModified": 1782423922,
+ "narHash": "sha256-qPNd6lUohHP5gcJhqQ7rLV87RwIx0xYR2A4Frb9Zjc4=",
"owner": "nix-community",
"repo": "home-manager",
- "rev": "d1ccd0721ec599866622665f3651e19e6e2d4c6a",
+ "rev": "5d320ab301cfaaca7d32514f13815d19d109f5f4",
"type": "github"
},
"original": {
@@ -417,11 +417,11 @@
"spectrum": "spectrum"
},
"locked": {
- "lastModified": 1781738058,
- "narHash": "sha256-wgKY6pbZbFpBXae+8bjvJtW1Z9qekZergGly44n2qZw=",
+ "lastModified": 1782324740,
+ "narHash": "sha256-EpaYlgijQUv8nvbhMStQEFoO7aDWxJmVTOlsoHWqHpg=",
"owner": "microvm-nix",
"repo": "microvm.nix",
- "rev": "225b35c204e29efb5bbe9b55b1a38b07b3fca2af",
+ "rev": "49a3e9fe33d33f189d24dafca36096766faa60ad",
"type": "github"
},
"original": {
@@ -492,11 +492,11 @@
"xwayland-satellite-unstable": "xwayland-satellite-unstable"
},
"locked": {
- "lastModified": 1781795508,
- "narHash": "sha256-VKrApQ3WCkEe9D8DbaeFjGqLAh7zqYGYjbQYtY5ikxc=",
+ "lastModified": 1782333733,
+ "narHash": "sha256-QYrNYMNPKErRgNlxWwk0cjNKftnq6WzSs84pcZnUskM=",
"owner": "sodiboo",
"repo": "niri-flake",
- "rev": "493ce1e33e72f86312584f331c8cf52b3432ec99",
+ "rev": "a6351044a3d69877d1c23be54971d18f8531c930",
"type": "github"
},
"original": {
@@ -543,11 +543,11 @@
"nixpkgs": "nixpkgs_2"
},
"locked": {
- "lastModified": 1781622756,
- "narHash": "sha256-JrPh4M6S7aPsEE9tOENuZrxC6o2szSLlK+t4+nLke9s=",
+ "lastModified": 1782379505,
+ "narHash": "sha256-zPvPiU+a7pqtH47xrtZLNRABJKpOjfZQclDbcvNtH+I=",
"owner": "NixOS",
"repo": "nixos-hardware",
- "rev": "08018c72174a4df5657f8d94178ac69fb9c243e5",
+ "rev": "603d3afd1b6145bd66e97ae38a34d91c95df70cf",
"type": "github"
},
"original": {
@@ -614,11 +614,11 @@
},
"nixpkgs-stable": {
"locked": {
- "lastModified": 1781509190,
- "narHash": "sha256-uJZs9Di8I6ciTp6jiojj0HzlNpBkud8ax5aT/O5aJkw=",
+ "lastModified": 1782188297,
+ "narHash": "sha256-imdcA5fgbHK259bhHlyiiSr7bMY1AZ6onOWDdAcydc4=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "d6df3513510aa548c83868fd22bfddd0a8c0a0d4",
+ "rev": "9a1a7dbb18f0eb31c49b031babb8def7eab0af54",
"type": "github"
},
"original": {
@@ -630,11 +630,11 @@
},
"nixpkgs-stable_2": {
"locked": {
- "lastModified": 1781216227,
- "narHash": "sha256-9mUW6gNwoN2SWc/l0fW4svPNOulXLl8ijqKyeSOGgJE=",
+ "lastModified": 1782233679,
+ "narHash": "sha256-QyuGP5+QOtmXpy4i2X4DhBVBaySBdDKQEhqKcphcp34=",
"owner": "NixOS",
"repo": "nixpkgs",
- "rev": "a0374025a863d007d98e3297f6aa46cc3141c2f0",
+ "rev": "667d5cf1c59585031d743c78b394b0a647537c35",
"type": "github"
},
"original": {
@@ -698,11 +698,11 @@
"systems": "systems_2"
},
"locked": {
- "lastModified": 1782062554,
- "narHash": "sha256-v2J6/S33H2ms6jz3qr6in0UUlGFqUW46+iB3hMJDuD4=",
+ "lastModified": 1782254890,
+ "narHash": "sha256-kjsEECqhpPnJWqhooXp6tWh2qGQftCPAo2G1GvZtKdw=",
"owner": "nix-community",
"repo": "nixvim",
- "rev": "b3e7b2d2e568f29becae04217242ed18a90febc4",
+ "rev": "dbf9550dba8448b03e11d58e5695d6c44a464554",
"type": "github"
},
"original": {
@@ -722,11 +722,11 @@
"systems": "systems_3"
},
"locked": {
- "lastModified": 1781997110,
- "narHash": "sha256-6D6xtYN5t1kZGNd69eMZsRBkgX5Df1roErn/kFR1C+A=",
+ "lastModified": 1782369036,
+ "narHash": "sha256-jxbvrIvE+NklSd6HPNSdEhGr8RvwNj4b7Gd5tgEXwSQ=",
"owner": "NotAShelf",
"repo": "nvf",
- "rev": "320f60b97075a58d38b90fc5e39f478421dbd38a",
+ "rev": "096045d0e927bf7064989e9181a89b47c1b8779c",
"type": "github"
},
"original": {
@@ -909,11 +909,11 @@
"rust-overlay": "rust-overlay"
},
"locked": {
- "lastModified": 1781902199,
- "narHash": "sha256-VD/bm9ZinziQdfUZDeTXd4H+T+TQ5WHwWXK9FpOniUs=",
+ "lastModified": 1782333283,
+ "narHash": "sha256-57ycRZHQkootKokT5VDSVZIyeGGaq05G7i2iqh1NApI=",
"owner": "gabm",
"repo": "Satty",
- "rev": "32b2be3618a5617b196942b8fc023f998b44beca",
+ "rev": "26848045f3565cb05f6c18ad9e0d8ca5b3a7e1c1",
"type": "github"
},
"original": {
@@ -929,11 +929,11 @@
]
},
"locked": {
- "lastModified": 1781157498,
- "narHash": "sha256-gDNHztsHGFAmbbj7Gcu8vWcFU5+4c1EeGU4lhb7Hnqo=",
+ "lastModified": 1782389855,
+ "narHash": "sha256-LhalI4N/bv20fvi0ag+f6ESWLS5VbOdzJKLoEGnJDMk=",
"owner": "AceSLS",
"repo": "SLSsteam",
- "rev": "981da676e76f72b1ed3c387f192509ac9a1b91e4",
+ "rev": "ceb07e711cc0e831b2851236b46629827f87bbc4",
"type": "github"
},
"original": {
@@ -972,11 +972,11 @@
]
},
"locked": {
- "lastModified": 1781943681,
- "narHash": "sha256-NFHmA7H47adqiyp+0iEOyZOQhmigDqA/NBAlf4imB6U=",
+ "lastModified": 1782165805,
+ "narHash": "sha256-478kKQBvK6SYTOdN2h9jhKJv94nbXRbFMfuL1WshErg=",
"owner": "Mic92",
"repo": "sops-nix",
- "rev": "420f8d2e9882911f65cfac15cc706f639ba96cca",
+ "rev": "56b24064fdcaedca53553b1a6d607fd23b613a24",
"type": "github"
},
"original": {
@@ -1155,11 +1155,11 @@
"rust-overlay": "rust-overlay_2"
},
"locked": {
- "lastModified": 1781971032,
- "narHash": "sha256-lxliQTpjaN1iF2ntK2gJ4UO55HM4w47Hcqwe6gBo85o=",
+ "lastModified": 1782458355,
+ "narHash": "sha256-qa+ReXlH0m+5SZrmUKWK3xAri4qE45M8FcmM4L7VC5s=",
"owner": "sxyazi",
"repo": "yazi",
- "rev": "4f45ddb514c3db558da0c5fffabaaa44f18cc18e",
+ "rev": "bf1274315dbcef858b46a55f212cfa34b916c3d3",
"type": "github"
},
"original": {
diff --git a/hosts/bibus-lab/disko.nix b/hosts/bibus-lab/disko.nix
index 5d0f0b8..6ca17b9 100644
--- a/hosts/bibus-lab/disko.nix
+++ b/hosts/bibus-lab/disko.nix
@@ -2,7 +2,8 @@
disko.devices = {
main = {
type = "disk";
- device = "/dev/disk/by-id/";
+ # TODO fill id
+ device = "/dev/disk/by-id/CHANGEME";
content = {
type = "gpt";
partitions = {
@@ -10,7 +11,7 @@
size = "2G";
type = "EF00";
content = {
- type = "flesystem";
+ type = "filesystem";
format = "vfat";
mountpoint = "/boot";
};
@@ -27,7 +28,8 @@
};
hdd1 = {
type = "disk";
- device = "/dev/disk/by-id/";
+ # TODO fill id
+ device = "/dev/disk/by-id/CHANGEME";
content = {
type = "gpt";
partitions = {
@@ -43,7 +45,8 @@
};
hdd2 = {
type = "disk";
- device = "/dev/disk/by-id/";
+ # TODO fill id
+ device = "/dev/disk/by-id/CHANGEME";
content = {
type = "gpt";
partitions = {
@@ -59,7 +62,8 @@
};
hdd3 = {
type = "disk";
- device = "/dev/disk/by-id/";
+ # TODO fill id
+ device = "/dev/disk/by-id/CHANGEME";
content = {
type = "gpt";
partitions = {
@@ -80,11 +84,11 @@
datasets = {
"rpool" = {
type = "zfs_fs";
- options.mountpoint = "none";
- encryption = "aes-256-gcm";
- keyformat = "raw";
- keylocation = "file:///mnt/zroot.key";
options = {
+ encryption = "on";
+ keyformat = "passphrase";
+ keylocation = "prompt";
+ mountpoint = "none";
compression = "zstd";
atime = "off";
};
@@ -92,10 +96,12 @@
"rpool/root" = {
type = "zfs_fs";
mountpoint = "/";
+ options.mountpoint = "legacy";
};
"rpool/nix" = {
type = "zfs_fs";
mountpoint = "/nix";
+ options.mountpoint = "legacy";
};
"rpool/home" = {
type = "zfs_fs";
@@ -104,32 +110,61 @@
"rpool/log" = {
type = "zfs_fs";
mountpoint = "/var/log";
+ options.mountpoint = "legacy";
};
- "rpool/var/systemd" = {
+ "rpool/var" = {
type = "zfs_fs";
- mountpoint = "/var/lib/systemd";
+ options.mountpoint = "none";
};
"rpool/var/acme" = {
type = "zfs_fs";
mountpoint = "/var/lib/acme";
};
- "rpool/docker" = {
+ "rpool/containers" = {
type = "zfs_fs";
mountpoint = "/var/lib/containers";
};
- "rpool/appdata/configs" = {
+ "rpool/appdata" = {
type = "zfs_fs";
- mountpoint = "/var/lib/appdata/configs";
+ options.mountpoint = "none";
};
- "rpool/appdata/databases" = {
+ "rpool/appdata/cfg" = {
type = "zfs_fs";
- mountpoint = "/var/lib/appdata/databases";
- options.recordsize = "16K";
+ mountpoint = "/var/lib/appdata/cfg";
+ };
+ "rpool/appdata/db" = {
+ type = "zfs_fs";
+ mountpoint = "/var/lib/appdata/db";
+ options.canmount = "off";
+ };
+ "rpool/appdata/db/postgres" = {
+ type = "zfs_fs";
+ mountpoint = "/var/lib/appdata/db/postgres";
+ options = {
+ recordsize = "8K";
+ logbias = "latency";
+ };
+ };
+ "rpool/appdata/db/couchdb" = {
+ type = "zfs_fs";
+ mountpoint = "/var/lib/appdata/db/couchdb";
+ options.recordsize = "64K";
+ };
+ "rpool/appdata/db/redis" = {
+ type = "zfs_fs";
+ mountpoint = "/var/lib/appdata/db/redis";
+ options = {
+ recordsize = "128K";
+ compression = "lz4";
+ };
};
"rpool/appdata/monero" = {
type = "zfs_fs";
mountpoint = "/var/lib/monero";
- options.recordsize = "8K";
+ options = {
+ compression = "off";
+ recordsize = "8K";
+ };
};
"rpool/appdata/mail" = {
type = "zfs_fs";
@@ -154,10 +189,10 @@
"ztank" = {
type = "zfs_fs";
mountpoint = "none";
- encryption = "aes-256-gcm";
- keyformat = "raw";
- keylocation = "file:///mnt/ztank.key";
options = {
+ encryption = "on";
+ keyformat = "passphrase";
+ keylocation = "prompt";
compression = "zstd";
atime = "off";
};
@@ -173,39 +208,39 @@
"ztank/vault" = {
type = "zfs_fs";
mountpoint = "/data/vault";
+ options.xattr = "sa";
};
- "ztank/vault/seafile" = {
+ "ztank/seafile" = {
type = "zfs_fs";
- mountpoint = "/data/vault/seafile";
- options.recordsize = "1M";
+ mountpoint = "none";
+ options.recordsize = "128K";
};
- "ztank/vault/seafile/personal" = {
+ "ztank/seafile/personal" = {
type = "zfs_fs";
- mountpoint = "/data/vault/seafile/personal";
+ mountpoint = "/data/seafile/personal";
};
- "ztank/vault/seafile/shared" = {
+ "ztank/seafile/shared" = {
type = "zfs_fs";
- mountpoint = "/data/vault/seafile/shared";
+ mountpoint = "/data/seafile/shared";
refquota = "1T";
};
- "ztank/downloads/active" = {
+ "ztank/dl" = {
type = "zfs_fs";
- mountpoint = "/data/downloads/active";
- options.recordsize = "16K";
+ options.mountpoint = "none";
};
- "ztank/downloads/complete" = {
+ "ztank/dl/active" = {
type = "zfs_fs";
- mountpoint = "/data/downloads/complete";
- options.recordsize = "1M";
+ mountpoint = "/data/dl/active";
+ options.recordsize = "16K";
};
- "ztank/cctv" = {
+ "ztank/dl/complete" = {
type = "zfs_fs";
- mountpoint = "/data/cctv";
+ mountpoint = "/data/dl/complete";
options.recordsize = "1M";
};
- "ztank/backups" = {
+ "ztank/backup" = {
type = "zfs_fs";
- mountpoint = "/data/backups";
+ mountpoint = "/data/backup";
options.recordsize = "1M";
};
};
diff --git a/os/core/networking.nix b/os/core/networking.nix
index 638ecd4..b94b540 100644
--- a/os/core/networking.nix
+++ b/os/core/networking.nix
@@ -21,18 +21,19 @@ in
ips = lib.mkOption {
type = lib.types.attrsOf lib.types.str;
default = rec {
- router = vm1-opnsense;
+ router = opnsense-vm;
host = "10.0.0.2";
- vm1-opnsense = "10.0.0.1";
- vm2-gateway = "10.0.0.3";
- vm3-monitor = "10.0.0.4";
- vm4-media = "10.0.0.5";
- vm5-sandbox = "10.0.0.6";
- vm6-storage = "10.0.0.7";
- vm7-web = "10.0.0.8";
- vm8-mail = "10.0.0.9";
- vm9-relays = "10.0.0.10";
- vm10-mc = "10.0.0.11";
+ opnsense-vm = "10.0.0.1";
+ gateway-vm = "10.0.0.3";
+ databse-vm = "10.0.0.4";
+ monitor-vm = "10.0.0.5";
+ media-vm = "10.0.0.6";
+ sandbox-vm = "10.0.0.7";
+ storage-vm = "10.0.0.8";
+ web-vm = "10.0.0.9";
+ mail-vm = "10.0.0.10";
+ relay-vm = "10.0.0.11";
+ gameserver-vm = "10.0.0.12";
};
description = "Central registry of static IP allocations for the cluster.";
};
diff --git a/os/srv/authelia.nix b/os/srv/authelia.nix
index 52b7114..2c42b0a 100644
--- a/os/srv/authelia.nix
+++ b/os/srv/authelia.nix
@@ -2,48 +2,146 @@
config,
lib,
masterDomain,
+ securityTemplates,
...
}:
let
cfg = config.os.srv.authelia;
+ computedBaseDN = lib.concatStringsSep "," (
+ map (domainPart: "dc=${domainPart}") (lib.splitString "." masterDomain)
+ );
in
{
- options.os.srv.authelia = {
- enable = lib.mkEnableOption "enables authelia scanning";
- extraRules = lib.mkOption {
- type = lib.types.listOf lib.types.attrs;
- default = [ ];
- description = "Additional access control rules to be appended to Authelia.";
- };
- };
+ options.os.srv.authelia.enable =
+ lib.mkEnableOption "enables authelia authentication gateway instance";
+
config = lib.mkIf cfg.enable {
assertions = [
{
assertion = config.os.srv.sops.enable;
- message = "Required for password secure password storing";
+ message = "sops must be enabled for secure cryptographic token storage";
}
{
- assertion = config.os.srv.lldap.enable;
- message = "required for user accounts";
+ assertion = config.os.core.network.enableFirewall;
+ message = "Requires firewall";
}
];
+
+ sops.secrets = {
+ "authelia/jwt_secret" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+ "authelia/session_secret" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+ "authelia/encryption_key" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+
+ "authelia/oidc_hmac" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+ "authelia/oidc_private_key" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+
+ "postgres/authelia_password" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+ "redis/password" = {
+ owner = "authelia-main";
+ group = "authelia-main";
+ restartUnits = [ "authelia-main.service" ];
+ };
+ };
+
services.authelia.instances.main = {
enable = true;
+
secrets = {
jwtSecretFile = config.sops.secrets."authelia/jwt_secret".path;
- storageEncryptionKeyFile = config.sops.secrets."authelia/encryptionKey".path;
+ sessionSecretFile = config.sops.secrets."authelia/session_secret".path;
+ storageEncryptionKeyFile = config.sops.secrets."authelia/encryption_key".path;
+
+ oidcHmacSecretFile = config.sops.secrets."authelia/oidc_hmac".path;
+ oidcIssuerPrivateKeyFile = config.sops.secrets."authelia/oidc_private_key".path;
};
+
settings = {
theme = "dark";
+ default_2fa_method = "totp";
+
+ log = {
+ level = "info";
+ format = "json";
+ path = "/var/log/authelia/authelia.log";
+ keep_stdout = true;
+ };
+
+ server.address = "tcp://127.0.0.1:9091";
+
+ telemetry.metrics = {
+ enabled = true;
+ address = "tcp://127.0.0.1:9959";
+ };
+
+ storage = {
+ postgres = {
+ host = config.os.core.network.ips.database-vm;
+ port = 5432;
+ database = "authelia";
+ username = "authelia";
+ timeout = "5s";
+ schema = "public";
+ };
+ };
+
+ session = {
+ name = "authelia_session";
+ expiration = "1h";
+ inactivity = "15m";
+ remember_me = "1M";
+ provider = {
+ redis = {
+ host = config.os.core.network.ips.database-vm;
+ port = 6379;
+ database = 0;
+ timeout = "5s";
+ };
+ };
+ };
+
authentication_backend = {
ldap = {
- address = "ldap://127.0.0.1:3890";
+ address = "ldap://${config.os.core.network.ips.gateway-vm}:3890";
implementation = "lldap";
- base_dn = "dc=example,dc=com";
- user = "uid=authelia,ou=people,dc=example,dc=com";
- password_file = config.sops.secrets."lldap/bind_password".path;
+ base_dn = computedBaseDN;
+ user = "uid=authelia,ou=people,${computedBaseDN}";
};
};
+
+ identity_providers = {
+ oidc = {
+ cors.allowed_origins = map (domain: "https://${domain}") (
+ builtins.attrNames config.os.cluster.nginxProxies
+ );
+
+ clients = config.os.cluster.oidcClients;
+ };
+ };
+
access_control = {
default_policy = "deny";
rules = [
@@ -52,10 +150,30 @@ in
policy = "bypass";
}
]
- ++ cfg.extraRules;
+ ++ config.os.cluster.autheliaRules;
};
+
session.domain = masterDomain;
};
+
+ environmentVariables = {
+ AUTHELIA_AUTHENTICATION_BACKEND_LDAP_PASSWORD_FILE = config.sops.secrets."lldap/password".path;
+ AUTHELIA_SESSION_REDIS_PASSWORD_FILE = config.sops.secrets."redis/password".path;
+ AUTHELIA_STORAGE_POSTGRES_PASSWORD_FILE = config.sops.secrets."postreg/authelia_password".path;
+ };
+ };
+
+ os.cluster.nginxProxies."auth.${masterDomain}" = {
+ enableACME = true;
+ forceSSL = true;
+ locations."/" = {
+ proxyPass = "http://${config.os.core.network.ips.gateway-vm}:9091";
+ extraConfig = securityTemplates.restrictToInternal;
+ };
};
+
+ networking.firewall.extraInputRules = ''
+ ip saddr ${config.os.core.network.ips.monitor-vm} tcp dport 9959 accept
+ '';
};
}
diff --git a/os/srv/backup.nix b/os/srv/backup.nix
index dad9b66..3d1d583 100644
--- a/os/srv/backup.nix
+++ b/os/srv/backup.nix
@@ -1,32 +1,94 @@
-{ config, lib, ... }:
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
let
- cfg = config.os.srv.backup;
+ cfg = config.os.srv.replication;
+ pgLockScript = pkgs.writeScriptBin "pg-lock" ''
+ #!/bin/sh
+ microvm -s database-vm -- sudo -u postgres psql -c "SELECT pg_backup_start('sanoid_snap');"
+ '';
+
+ pgUnlockScript = pkgs.writeScriptBin "pg-unlock" ''
+ #!/bin/sh
+ microvm -s database-vm -- sudo -u postgres psql -c "SELECT pg_backup_stop();"
+ '';
in
{
- options.os.srv.backup.enable = lib.mkEnableOption "enables backups";
+ options.os.srv.replication.enable = lib.mkEnableOption "enables replications";
config = lib.mkIf cfg.enable {
- services.sanoid = {
- enable = true;
- templates.production = {
- hourly = 36;
- daily = 30;
- monthly = 3;
- };
- datasets."zroot/rpool/appdata/databases".useTemplate = [ "production" ];
- datasets."ztank/vault".useTemplates = [ "production" ];
- };
- services.syncoid = {
- enable = true;
- commands = {
- "sync-db" = {
- source = "zroot/rpool/appdata/databases";
- target = "ztank/backups/nvme/databases";
- sendOptions = "w";
+ services = {
+ sanoid = {
+ enable = true;
+ templates.production = {
+ autosnap = true;
+ autoprune = true;
+ hourly = 24;
+ daily = 7;
+ weekly = 4;
+ monthly = 3;
};
- "sync-configs" = {
- source = "zroot/rpool/appdata/configs";
- target = "ztank/backups/nvme/configs";
- sendOptions = "w";
+ datasets = {
+ "zroot/rpool/appdata/db/postgres" = {
+ useTemplate = [ "production" ];
+
+ pre_snapshot_script = "${pgLockScript}/bin/pg-lock";
+ post_snapshot_script = "${pgUnlockScript}/bin/pg-unlock";
+ no_inconsistent_snapshot = true;
+ force_post_snapshot_script = true;
+ script_timeout = 30;
+ };
+
+ "zroot/rpool/appdata/db/redis".useTemplate = [ "production" ];
+
+ "zroot/rpool/appdata/db/couchdb".useTemplate = [ "production" ];
+
+ "zroot/rpool/appdata/cfg".useTemplate = [ "production" ];
+
+ "zroot/rpool/appdata/games".useTemplate = [ "production" ];
+
+ "zroot/rpool/appdata/mail".useTemplate = [ "production" ];
+
+ "zroot/rpool/containers".useTemplate = [ "production" ];
+ };
+ };
+
+ syncoid = {
+ enable = true;
+ commonArgs = [
+ "-w"
+ "--delete-target-snapshots"
+ "--use-hold"
+ "--no-sync-snap"
+ ];
+ commands = {
+ "sync-databases" = {
+ source = "zroot/rpool/appdata/db";
+ target = "tank/ztank/backup/nvme/db";
+ recursive = true;
+ };
+
+ "sync-config" = {
+ source = "zroot/rpool/appdata/cfg";
+ target = "tank/ztank/backup/nvme/cfg";
+ };
+
+ "sync-games" = {
+ source = "zroot/rpool/appdata/games";
+ target = "tank/ztank/backup/nvme/games";
+ };
+
+ "sync-mail" = {
+ source = "zroot/rpool/appdata/mail";
+ target = "tank/ztank/backup/nvme/mail";
+ };
+
+ "sync-docker" = {
+ source = "zroot/rpool/containers";
+ target = "tank/ztank/backup/nvme/containers";
+ };
};
};
};
diff --git a/os/srv/cluster.nix b/os/srv/cluster.nix
new file mode 100644
index 0000000..6e54ee2
--- /dev/null
+++ b/os/srv/cluster.nix
@@ -0,0 +1,16 @@
+{ lib, ... }: {
+ options.os.cluster = {
+ nginxProxies = lib.mkOption {
+ type = lib.types.attrsOf lib.types.attrs;
+ default = { };
+ };
+ autheliaRules = lib.mkOption {
+ type = lib.types.listOf lib.types.attrs;
+ default = [ ];
+ };
+ oidcClients = lib.mkOption {
+ type = lib.types.listOf lib.types.attrs;
+ default = [ ];
+ };
+ };
+}
diff --git a/os/srv/crowdsec.nix b/os/srv/crowdsec.nix
index 79c8718..71818bd 100644
--- a/os/srv/crowdsec.nix
+++ b/os/srv/crowdsec.nix
@@ -5,6 +5,9 @@ in
{
options.os.srv.security.crowdsec = {
enable = lib.mkEnableOption "enables CrowdSec collaborative intrusion prevention";
+
+ aggregator.enable = lib.mkEnableOption "this node acting as a central LAPI aggregator for the network";
+ agent.enable = lib.mkEnableOption "local log parsing and threat intelligence generation on this node";
};
config = lib.mkIf cfg.enable {
@@ -13,66 +16,104 @@ in
assertion = config.networking.nftables.enable;
message = "CrowdSec requires networking.nftables to be enabled for blocking.";
}
+ {
+ assertion = cfg.agent.enable || cfg.aggregator.enable;
+ message = "You must enable at least one CrowdSec role: 'agent.enable' or 'aggregator.enable'.";
+ }
];
services.crowdsec = {
enable = true;
autoUpdateService = true;
+ openFirewall = cfg.aggregator.enable;
+
+ settings = {
+ api.server.enable = cfg.aggregator.enable;
+ lapi.client.api_url = "http://${config.os.core.network.ips.gateway-vm}:8080";
+ };
+
+ hub = lib.mkIf cfg.agent.enable {
+ collections = [
+ "crowdsecurity/linux"
+ "crowdsecurity/nginx"
+ "crowdsecurity/authelia"
+ "crowdsecurity/sshd"
+ ];
+ };
+
localConfig = {
- acquisitions = [
+ acquisitions = lib.mkIf cfg.agent.enable [
{
source = "journalctl";
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
labels.type = "syslog";
}
{
- filenames = [
- "/var/log/nginx/access.log"
- "/var/log/nginx/error.log"
- ];
+ source = "file";
+ filenames = [ "/var/log/nginx/*.log" ];
labels.type = "nginx";
}
+ {
+ source = "file";
+ filenames = [ "/var/log/authelia/authelia.log" ];
+ labels.type = "authelia";
+ }
];
- parsers.s02Enrich = [
+ parsers.s02Enrich = lib.mkIf cfg.agent.enable [
{
name = "myips/whitelist";
description = "Prevent local address ranges from triggering bans";
whitelist = {
reason = "Internal private subnets";
cidr = [
- "10.0.0.0/16"
+ "10.0.0.0/24"
+ "10.1.0.0/24"
+ "10.3.0.0/24"
+ "10.4.0.0/24"
];
};
}
];
- };
- hub = {
- collections = [
- "crowdsecurity/linux"
- "crowdsecurity/nginx"
- "crowdsecurity/sshd"
+ notifications = lib.mkIf cfg.aggregator.enable [
+ {
+ name = "ntfy_alerts";
+ type = "http";
+ method = "POST";
+ #TODO add ntfy sops thing
+ url = "https://ntfy.sh/your_secret_topic_here";
+ headers = {
+ Title = "CrowdSec Alert on Bibus-Lab";
+ Priority = "high";
+ };
+ format = ''
+ {{range .}} {{.Alert.Message}} (Scenario: {{.Alert.Scenario}}) from IP {{.Alert.Source.IP}} {{end}}
+ '';
+ log_level = "info";
+ }
];
};
-
- settings = {
- lapi.credentialsFile = "/var/lib/crowdsec/state/lapi.yaml";
- capi.credentialsFile = "/var/lib/crowdsec/state/capi.yaml";
- };
};
services.crowdsec-firewall-bouncer = {
enable = true;
+
+ registerBouncer.enable = cfg.aggregator.enable;
+
settings = {
+ mode = "nftables";
update_frequency = "10s";
+
+ api_url = "http://${config.os.core.network.ips.gateway-vm}:8080";
};
};
- users.users.crowdsec.extraGroups = [
- "nginx"
+ users.users.crowdsec.extraGroups = lib.mkIf cfg.agent.enable [
"systemd-journal"
+ "nginx"
+ "authelia-main"
];
};
}
diff --git a/os/srv/default.nix b/os/srv/default.nix
index 34aa179..073067d 100644
--- a/os/srv/default.nix
+++ b/os/srv/default.nix
@@ -5,6 +5,7 @@
./backup.nix
./bluetooth.nix
./clamav.nix
+ ./cluster.nix
./compat.nix
./crowdsec.nix
./dns.nix
@@ -26,7 +27,9 @@
./ntopng.nix
./oci.nix
./omnisearch.nix
+ ./postgres.nix
./prometheus.nix
+ ./redis.nix
./scrutiny.nix
./simplex.nix
./sops.nix
@@ -37,6 +40,7 @@
./tor.nix
./ups.nix
./uptime-kuma.nix
+ ./vector.nix
./virtualization.nix
./wireguard.nix
./yggdrasil.nix
diff --git a/os/srv/gaming.nix b/os/srv/gaming.nix
index 36f2db5..730dcd2 100644
--- a/os/srv/gaming.nix
+++ b/os/srv/gaming.nix
@@ -30,22 +30,24 @@ in
config = lib.mkMerge [
# --- PERFORMANCE & TOOLING ---
(lib.mkIf cfg.tools.enable {
- programs.gamescope = {
- enable = true;
- capSysNice = true;
- };
+ hardware.xone.enable = true;
+ programs = {
+ gamescope = {
+ enable = true;
+ capSysNice = true;
+ };
- programs.gamemode = {
- enable = true;
- enableRenice = true;
- settings = {
- general.renice = 10;
+ gamemode = {
+ enable = true;
+ enableRenice = true;
+ settings = {
+ general.renice = 10;
+ };
};
};
environment = {
- # sets the optiscaler shortcut key to be home by default
sessionVariables = {
- OPTISCALER_ShortcutKey = "0x24";
+ OPTISCALER_ShortcutKey = "0x24"; # sets the optiscaler shortcut key to be home by default
};
systemPackages = with pkgs; [
@@ -61,10 +63,9 @@ in
(lib.mkIf cfg.launchers.enable {
environment.systemPackages = with pkgs; [
heroic
- # (pkgs.bottles.override { removeWarningPopup = true; })
(prismlauncher.override {
additionalLibs = with pkgs; [ ocl-icd ];
- jdks = with pkgs; [ javaPackages.compiler.temurin-bin.jdk-25 ];
+ jdks = with pkgs; [ javaPackages.compiler.temurin-bin.jdk-26 ];
})
];
})
diff --git a/os/srv/headscale.nix b/os/srv/headscale.nix
index a650067..01fc06c 100644
--- a/os/srv/headscale.nix
+++ b/os/srv/headscale.nix
@@ -1,14 +1,46 @@
{
config,
lib,
+ pkgs,
masterDomain,
...
}:
let
cfg = config.os.srv.headscale;
+ aclPolicy = pkgs.writeText "headscale-policy.json" (
+ builtins.toJSON {
+ groups = {
+ "group:admin" = [ "your-device-name" ];
+ "group:friends" = [ "friend-device-name" ];
+ };
+
+ hosts = {
+ "server" = "10.4.0.1";
+ };
+
+ acls = [
+ {
+ action = "accept";
+ src = [ "group:admin" ];
+ dst = [ "*:*" ];
+ }
+
+ {
+ action = "accept";
+ src = [ "group:friends" ];
+ dst = [
+ "server:18080"
+ "server:18081"
+ "server:25565"
+ ];
+ }
+ ];
+ }
+ );
in
{
options.os.srv.headscale.enable = lib.mkEnableOption "enables headscales";
+
config = lib.mkIf cfg.enable {
services.headscale = {
enable = true;
@@ -18,14 +50,16 @@ in
settings = {
server_url = "https://vpn.${masterDomain}";
+ policy.path = "${aclPolicy}";
+
dns = {
magic_dns = true;
- base_domain = "vpn.internal";
- nameservers = [ "10.255.1.1" ];
+ base_domain = "vpn";
+ nameservers = [ config.os.core.network.ips.vm2-gateway ];
};
ip_prefixes = [
- "10.254.0.0/16"
+ "10.4.0.0/16"
];
};
};
diff --git a/os/srv/i2p.nix b/os/srv/i2p.nix
index fa7f102..5e36c20 100644
--- a/os/srv/i2p.nix
+++ b/os/srv/i2p.nix
@@ -1,7 +1,8 @@
{
config,
lib,
- pkgs,
+ masterDomain,
+ securityTemplates,
...
}:
let
@@ -9,45 +10,72 @@ let
in
{
options.os.srv.i2p = {
- enable = lib.mkEnableOption "enables i2pd";
- enableBrowser = lib.mkEnableOption "enables mullvad browser for browsing eepsites";
+ enable = lib.mkEnableOption "enables a flexible, polymorphic i2pd deployment profile";
+
+ mode = lib.mkOption {
+ type = lib.types.enum [
+ "server"
+ "client"
+ ];
+ default = "client";
+ description = "";
+ };
};
- config = lib.mkMerge [
- (lib.mkIf cfg.enable {
- services.i2pd = {
- enable = true;
- enableIPv6 = true;
- # upnp.enable = true;
- bandwidth = 1024;
- reseed.verify = true;
- ntcp2 = {
- enable = true;
- # published = true;
- };
- ssu2 = {
+ config = lib.mkIf cfg.enable (
+ lib.mkMerge [
+ {
+ services.i2pd = {
enable = true;
- # published = true;
+ enableIPv6 = true;
+ reseed.verify = true;
+
+ yggdrasil.enable = true;
+
+ proto = {
+ http.enable = true;
+ httpProxy.enable = true;
+ socksProxy = {
+ enable = true;
+ outproxyEnable = true;
+ };
+ sam.enable = true;
+ i2pControl.enable = true;
+ };
};
- yggdrasil = {
- enable = true;
- address = "200:5857:a255:4db6:8687:6928:ddc4:dad6";
+ }
+
+ (lib.mkIf (cfg.mode == "server") {
+ services.i2pd = {
+ bandwidth = 4096;
+
+ ntcp2.published = true;
+ ssu2.published = true;
+
+ #TODO add address
+ yggdrasil.address = "";
};
- proto = {
- http.enable = true;
- httpProxy.enable = true;
- socksProxy = {
- enable = true;
- outproxyEnable = true;
+
+ os.cluster.nginxProxies."i2p.${masterDomain}" = {
+ enableACME = true;
+ forceSSL = true;
+ locations."/" = {
+ proxyPass = "http://${config.os.core.network.ips.relay-vm}:7070";
+ extraConfig = securityTemplates.restrictToInternal;
};
- sam.enable = true;
- i2pControl.enable = true;
};
- };
- # environment.systemPackages = [ pkgs.i2pd-tools ];
- })
- (lib.mkIf cfg.enableBrowser {
- environment.systemPackages = [ pkgs.mullvad-browser ];
- })
- ];
+ })
+
+ (lib.mkIf (cfg.mode == "client") {
+ services.i2pd = {
+ bandwidth = 512;
+
+ ntcp2.published = false;
+ ssu2.published = false;
+
+ yggdrasil.address = "";
+ };
+ })
+ ]
+ );
}
diff --git a/os/srv/lldap.nix b/os/srv/lldap.nix
index 1cf43e4..1463ab6 100644
--- a/os/srv/lldap.nix
+++ b/os/srv/lldap.nix
@@ -1,6 +1,15 @@
-{ config, lib, ... }:
+{
+ config,
+ lib,
+ masterDomain,
+ securityTemplates,
+ ...
+}:
let
cfg = config.os.srv.lldap;
+ computedBaseDN = lib.concatStringsSep "," (
+ map (domainPart: "dc=${domainPart}") (lib.splitString "." masterDomain)
+ );
in
{
options.os.srv.lldap.enable = lib.mkEnableOption "enables lldap scanning";
@@ -10,15 +19,48 @@ in
assertion = config.os.srv.sops.enable;
message = "Required for password secure password storing";
}
+ {
+ assertion = config.os.core.network.enableFirewall;
+ message = "Requires firewall";
+ }
];
+
+ sops.secrets = {
+ "lldap/password" = {
+ owner = "lldap";
+ group = "lldap";
+ };
+ "lldap/env_file" = {
+ owner = "lldap";
+ group = "lldap";
+ };
+ };
+
services.lldap = {
enable = true;
settings = {
- ldap_base_dn = "dc=example,dc=com";
- ldap_port = 3890;
- http_port = 17170;
+ ldap_base_dn = computedBaseDN;
+ http_host = "127.0.0.1";
+ http_url = "https://lldap.${masterDomain}";
+ ldap_user_email = "adikro@disroot.org";
+ ldap_user_pass_file = config.sops.secrets."lldap/password".path;
+ silenceForceUserPassResetWarning = true;
+ };
+ environmentFile = config.sops.secrets."lldap/env_file".path;
+ };
+
+ os.cluster.nginxProxies."lldap.${masterDomain}" = {
+ enableACME = true;
+ forceSSL = true;
+
+ locations."/" = {
+ proxyPass = "http://${config.os.core.network.ips.gateway-vm}:17170";
+ extraConfig = securityTemplates.restrictToInternal;
};
- environmentFile = config.sops.secrets."lldap/env".path;
};
+
+ networking.firewall.extraInputRules = ''
+ ip saddr 10.0.0.0/24 tcp dport 3890 accept
+ '';
};
}
diff --git a/os/srv/monero.nix b/os/srv/monero.nix
index f00413d..6b50e1d 100644
--- a/os/srv/monero.nix
+++ b/os/srv/monero.nix
@@ -8,16 +8,28 @@
}:
let
cfg = config.os.srv.monero;
+ banlist1 = pkgs.fetchurl {
+ url = "https://gui.xmr.pm/files/block.txt";
+ hash = "sha256-0ik4d66js6wvrvciza0li6bsajj8dvxsqlf09hcz7hg610szdxcw";
+ };
+ banlist2 = pkgs.fetchurl {
+ url = "https://raw.githubusercontent.com/Boog900/monero-ban-list/refs/heads/main/ban_list.txt";
+ hash = "sh256-01z4wm2mp4z1wq2wdkrm66j50gwk3r82m2ml4n0pwjcbajxkdc87";
+ };
+
+ combinedBanlist = pkgs.writeText "combined-monero-banlist.txt" ''
+ ${builtins.readFile banlist1}
+ ${builtins.readFile banlist2}
+ '';
in
{
options.os.srv.monero = {
wallet.enable = lib.mkEnableOption "enables the monero wallet";
service = {
enable = lib.mkEnableOption "enables hosting a monero node";
- proxyConfig = lib.mkOption {
- type = lib.types.attrs;
- default = { };
- };
+ public = lib.mkEnableOption "makes the RPC node public (disables authentication for general wallet syncing)";
+ tor.enable = lib.mkEnableOption "exposes monero RPC via Tor Onion Service";
+ i2p.enable = lib.mkEnableOption "exposes monero RPC via I2P Tunnel";
};
};
@@ -28,8 +40,16 @@ in
(lib.mkIf cfg.service.enable {
assertions = [
{
- assertion = config.os.srv.sops.enable;
- message = "Required for password secure password storing";
+ assertion = if (!cfg.service.public) then config.os.srv.sops.enable else true;
+ message = "sops must be enabled";
+ }
+ {
+ assertion = if cfg.service.tor.enable then config.os.srv.tor.enable else true;
+ message = "tor must be enabled";
+ }
+ {
+ assertion = if cfg.service.i2p.enable then config.os.srv.i2p.enable else true;
+ message = "i2p must be enabled";
}
];
@@ -41,37 +61,59 @@ in
services.monero = {
enable = true;
prune = true;
+ banlist = combinedBanlist;
+
limits = {
upload = 1250;
download = 12500;
threads = 8;
};
- banlist = builtins.fetchurl {
- url = "https://gui.xmr.pm/files/block.txt";
- hash = "0ik4d66js6wvrvciza0li6bsajj8dvxsqlf09hcz7hg610szdxcw";
- };
+
rpc = {
+ address = "0.0.0.0";
+ }
+ // lib.optionalAttrs (!cfg.service.public) {
restricted = true;
user = "admin";
password = config.sops.secrets."monero/rpc-password".path;
};
+
+ };
+
+ services.tor = lib.mkIf cfg.service.tor.enable {
+ onionServices."xmr-rpc" = {
+ to = [
+ {
+ port = 18081;
+ address = config.os.core.network.ips.vm9-relays;
+ }
+ ];
+ };
+ };
+
+ services.i2pd = lib.mkIf cfg.service.i2p.enable {
+ tunnels.server."xmr-rpc" = {
+ port = 18081;
+ address = config.os.core.network.ips.vm9-relays;
+ keys = "xmr-rpc-key.dat";
+ inbound.length = 3;
+ outbound.length = 3;
+ };
};
- os.srv.monero.service.proxyConfig = {
- "xmr.${masterDomain}" = {
- enableACME = true;
- forceSSL = true;
+ os.cluster.nginxProxies."xmr.${masterDomain}" = {
+ enableACME = true;
+ forceSSL = true;
- locations."/" = {
- proxyPass = "http://${config.os.core.network.ips.vm9-relays}:18081";
- extraConfig = ''
- proxy_read_timeout 600s;
- proxy_send_timeout 600s;
- client_max_body_size 50m;
+ locations."/" = {
+ proxyPass = "http://${config.os.core.network.ips.vm9-relays}:18081";
+ extraConfig = ''
+ proxy_read_timeout 600s;
+ proxy_send_timeout 600s;
+ client_max_body_size 50m;
- ${securityTemplates.restrictToInternal}
- '';
- };
+ ${securityTemplates.restrictToInternal}
+ '';
};
};
diff --git a/os/srv/nfs.nix b/os/srv/nfs.nix
index 9e5b16f..07f331e 100644
--- a/os/srv/nfs.nix
+++ b/os/srv/nfs.nix
@@ -7,14 +7,17 @@ in
config = lib.mkIf cfg.enable {
services.nfs.server = {
enable = true;
+ nproc = 4; # Lowered due to low traffic for a home server
+ createMountPoints = true;
- # TODO exports
exports = ''
- /data 192.168.1.0/24(ro,fsid=0,no_subtree_check)
+ /data/media 10.1.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check) \
+ 10.3.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check) \
+ 10.4.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check)
- /data/media 192.168.1.0/24(ro,nohide,insecure,no_subtree_check,async)
-
- /data/backups 192.168.1.50(rw,nohide,no_subtree_check,sync,no_root_squash)
+ /data/vault 10.1.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check) \
+ 10.3.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check) \
+ 10.4.0.0/24(rw,all_squash,anonuid=1000,anongid=100,async,insecure,no_subtree_check)
'';
};
diff --git a/os/srv/nginx.nix b/os/srv/nginx.nix
index 5161920..2194ecb 100644
--- a/os/srv/nginx.nix
+++ b/os/srv/nginx.nix
@@ -51,7 +51,7 @@ in
locations."/".return = "444";
};
}
- config.os.srv.monero.proxyConfig
+ config.os.cluster.nginxProxies
];
};
diff --git a/os/srv/postgres.nix b/os/srv/postgres.nix
new file mode 100644
index 0000000..f669f63
--- /dev/null
+++ b/os/srv/postgres.nix
@@ -0,0 +1,72 @@
+{
+ config,
+ lib,
+ pkgs,
+ ...
+}:
+let
+ cfg = config.os.srv.postgres;
+in
+{
+ options.os.srv.postgres.enable = lib.mkEnableOption "";
+ config = lib.mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = config.os.srv.sops.enable;
+ message = "Required for password secure password storing";
+ }
+ {
+ assertion = config.os.core.network.enableFirewall;
+ message = "Requires firewall";
+ }
+ ];
+
+ sops.secrets."postgres/authelia_password" = {
+ owner = "postgres";
+ group = "postgres";
+ restartUnits = [ "postgresql.service" ];
+ };
+
+ services.postgresql = {
+ enable = true;
+ package = pkgs.postgresql_18;
+
+ extraPlugins = [ config.services.postgresql.package.pkgs.pgvector ];
+
+ settings = {
+ listen_addresses = config.os.core.network.ips.database-vm;
+
+ max_connections = 100;
+ shared_buffers = "256MB";
+ work_mem = "4MB";
+ };
+
+ ensureDatabases = [ "authelia" ];
+ ensureUsers = [
+ {
+ name = "authelia";
+ ensureDBOwnership = true;
+ }
+ ];
+
+ initialScript = pkgs.writeText "init-postgres-passwords.sql" ''
+ CREATE USER authelia;
+ ALTER USER authelia WITH PASSWORD 'scram-sha-256';
+ '';
+
+ authentication = pkgs.lib.mkForce ''
+ local all all trust
+ host all all 10.0.0.0/24 scram-sha-256
+ '';
+ };
+
+ systemd.services.postgresql.postStart = lib.mkAfter ''
+ PASS=$(cat ${config.sops.secrets."postgres/authelia_password".path})
+ ${config.services.postgresql.package}/bin/psql -tAc "ALTER USER authelia WITH PASSWORD '$PASS';"
+ '';
+
+ networking.firewall.extraInputRules = ''
+ ip saddr 10.0.0.0/24 tcp dport 5432 accept
+ '';
+ };
+}
diff --git a/os/srv/redis.nix b/os/srv/redis.nix
new file mode 100644
index 0000000..a51f9db
--- /dev/null
+++ b/os/srv/redis.nix
@@ -0,0 +1,37 @@
+{ config, lib, ... }:
+let
+ cfg = config.os.srv.redis;
+in
+{
+ options.os.srv.redis.enable = lib.mkEnableOption "";
+ config = lib.mkIf cfg.enable {
+ assertions = [
+ {
+ assertion = config.os.srv.sops.enable;
+ message = "Required for password secure password storing";
+ }
+ {
+ assertion = config.os.core.network.enableFirewall;
+ message = "Requires firewall";
+ }
+ ];
+
+ sops.secrets."redis/password" = {
+ owner = "redis-main";
+ restartUnits = [ "redis-servers-main.service" ];
+ };
+
+ services.redis.servers."main" = {
+ enable = true;
+ bind = config.os.core.network.ips.database-vm;
+ port = 6379;
+
+ requirePassFile = config.sops.secrets."redis/password".path;
+ };
+
+ networking.firewall.extraInputRules = ''
+ ip saddr 10.0.0.0/24 tcp dport 6379 accept
+ '';
+
+ };
+}
diff --git a/os/srv/restic.nix b/os/srv/restic.nix
new file mode 100644
index 0000000..fb2bd19
--- /dev/null
+++ b/os/srv/restic.nix
@@ -0,0 +1,12 @@
+{ config, lib, ... }:
+let
+ cfg = config.os.srv.restic;
+in
+{
+ options.os.srv.restic.enable = lib.mkEnableOption "enables restic backups";
+
+ config = lib.mkIf cfg.enable {
+ assertions = [
+ ];
+ };
+}
diff --git a/os/srv/wireguard.nix b/os/srv/wireguard.nix
index 363ac9f..c758174 100644
--- a/os/srv/wireguard.nix
+++ b/os/srv/wireguard.nix
@@ -107,13 +107,13 @@ in
};
networking.wireguard.interfaces.wg0 = {
- ips = [ "10.255.1.1/24" ];
+ ips = [ "10.3.0.1/24" ];
listenPort = 51280;
privateKeyFile = config.sops.secrets."wg_private_key/${hostname}".path;
peers = lib.imap1 (i: peer: {
publicKey = peer.publicKey;
- allowedIPs = [ "10.255.0.${toString i}/32" ];
+ allowedIPs = [ "10.3.0.${toString (i + 1)}/32" ];
persistentKeepalive = 25;
}) cfg.server.peers;
};
@@ -128,12 +128,12 @@ in
];
networking.nameservers = [
- "10.255.1.1"
+ config.os.core.network.ips.vm2-gateway
"9.9.9.9"
];
networking.wireguard.interfaces.wg0 = {
- ips = [ "10.255.0.${toString cfg.client.index}/24" ];
+ ips = [ "10.3.0.${toString cfg.client.index + 1}/24" ];
privateKeyFile = config.sops.secrets."wg_private_key/${hostname}".path;
peers = [
diff --git a/os/srv/zfs.nix b/os/srv/zfs.nix
index fadfd82..3bfd2de 100644
--- a/os/srv/zfs.nix
+++ b/os/srv/zfs.nix
@@ -10,43 +10,51 @@ in
assertion = config.os.core.drivers.kernel == "zfs";
message = "ZFS requires the zfs supported kernel";
}
+ {
+ assertion = config.os.srv.sops.enable;
+ message = "required for storing the ntfy token";
+ }
];
+
+ sops.secrets."ntfy/zed".neededForUsers = false;
+
boot = {
- kernelParams = [ "zfs.zfs_arc_max=34359738368" ];
- supportedFilesystems = [ "zfs" ];
- initrd = {
- supportedFilesystems = [ "zfs" ];
- # fileSystems."/mnt" = {
- # device = "/dev/disk/by-label/KEYS";
- # fsType = "vfat";
- # options = [ "ro" ];
- # };
+ kernelParams = [ "zfs.zfs_arc_max=${toString (32 * 1024 * 1024 * 1024)}" ];
+ zfs = {
+ requestEncryptionCredentials = [ "zroot" ];
+ useKeyringForCredentials = true;
+ extraPools = [ "tank" ];
};
+ supportedFilesystems = [ "zfs" ];
+ initrd.supportedFilesystems = [ "zfs" ];
};
services.zfs = {
- autoScrub = {
+ expandOnBoot = "all";
+ autoScrub.enable = true;
+ trim.enable = true;
+ autoSnapshot = {
enable = true;
- interval = "weekly";
+ flags = "-k -p --utc";
};
- trim.enable = true;
zed = {
- enableMail = true;
+ enableCustomScripts = true;
settings = {
ZED_DEBUG_LOG = "/var/log/zed.debug.log";
- ZED_EMAIL_ADDR = [ "adikro@disroot.org" ];
- ZED_EMAIL_PROG = "mail";
- ZED_EMAIL_OPTS = "-s '@SUBJECT@' @ADDRESS@";
-
ZED_NOTIFY_INTERVAL_SECS = 3600;
- ZED_NOTIFY_VERBOSE = false;
+ ZED_NOTIFY_VERBOSE = 0;
- ZED_USE_ENCLOSURE_LEDS = true;
- ZED_SCRUB_AFTER_RESILVER = false;
+ ZED_USE_ENCLOSURE_LEDS = 1;
+ ZED_SCRUB_AFTER_RESILVER = 1;
+ ZED_POWER_OFF_ENCLOSURE_SLOT_ON_FAULT = 1;
+ ZED_POWER_OFF_ENCLOSURE_SLOT_ON_DEADMAN = 1;
+ ZED_NTFY_TOPIC = "zed-alerts-bibus-lab";
+ ZED_NTFY_URL = "http://${config.os.core.network.ips.monitor-vm}:8085";
};
};
};
+ systemd.services.zfs-zed.serviceConfig.EnvironmentFile = config.sops.secrets."ntfy/zed".path;
networking.hostId = "4e3e22e1";
};
}