Compare commits
6 commits
284c7bcc89
...
8c418616d8
Author | SHA1 | Date | |
---|---|---|---|
Patrick | 8c418616d8 | ||
Patrick | 3072389561 | ||
Patrick | d86a331fc6 | ||
Patrick | 73b11622d9 | ||
Patrick | 42344b3c60 | ||
Patrick | cfaea8f07f |
|
@ -1,68 +1,14 @@
|
|||
{
|
||||
lib,
|
||||
pkgs,
|
||||
config,
|
||||
...
|
||||
}: {
|
||||
imports = [../../modules/homebox.nix];
|
||||
wireguard.elisabeth = {
|
||||
client.via = "elisabeth";
|
||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.forgejo.settings.server.HTTP_PORT];
|
||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [3000];
|
||||
};
|
||||
systemd.services.homebox = {
|
||||
after = ["network.target"];
|
||||
environment = {
|
||||
HBOX_OPTIONS_ALLOW_REGISTRATION = "false";
|
||||
services.homebox = {
|
||||
enable = true;
|
||||
settings = {
|
||||
HBOX_WEB_PORT = "3000";
|
||||
};
|
||||
script = ''
|
||||
${lib.getExe pkgs.homebox} \
|
||||
--mode production \
|
||||
--web-port 3000 \
|
||||
--storage-data ./data \
|
||||
--storage-sqlite-url "./data/homebox.db?_pragma=busy_timeout=999&_pragma=journal_mode=WAL&_fk=1" \
|
||||
--options-allow-registration false
|
||||
'';
|
||||
serviceConfig = {
|
||||
User = "homebox";
|
||||
Group = "homebox";
|
||||
DynamicUser = true;
|
||||
StateDirectory = "homebox";
|
||||
WorkingDirectory = "/var/lib/homebox";
|
||||
LimitNOFILE = "1048576";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
StateDirectoryMode = "0700";
|
||||
Restart = "always";
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"@pkey"
|
||||
];
|
||||
UMask = "0077";
|
||||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
};
|
||||
environment.persistence."/persist".directories = [
|
||||
{
|
||||
|
|
|
@ -122,6 +122,7 @@ in {
|
|||
|
||||
groups."rss.access" = {};
|
||||
groups."firefly.access" = {};
|
||||
groups."ollama.access" = {};
|
||||
groups."adguardhome.access" = {
|
||||
};
|
||||
systems.oauth2.oauth2-proxy = {
|
||||
|
@ -131,12 +132,14 @@ in {
|
|||
scopeMaps."adguardhome.access" = ["openid" "email" "profile"];
|
||||
scopeMaps."rss.access" = ["openid" "email" "profile"];
|
||||
scopeMaps."firefly.access" = ["openid" "email" "profile"];
|
||||
scopeMaps."ollama.access" = ["openid" "email" "profile"];
|
||||
preferShortUsername = true;
|
||||
claimMaps.groups = {
|
||||
joinType = "array";
|
||||
valuesByGroup."adguardhome.access" = ["adguardhome_access"];
|
||||
valuesByGroup."rss.access" = ["ttrss_access"];
|
||||
valuesByGroup."firefly.access" = ["firefly_access"];
|
||||
valuesByGroup."ollama.access" = ["ollama_access"];
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
lib,
|
||||
...
|
||||
}: {
|
||||
disabledModules = ["services/networking/netbird/server.nix"];
|
||||
imports = [../../modules/netbird/server.nix];
|
||||
wireguard.elisabeth = {
|
||||
client.via = "elisabeth";
|
||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [80 3000 3001];
|
||||
|
|
|
@ -1,10 +1,32 @@
|
|||
{
|
||||
networking.firewall.allowedTCPPorts = [11434];
|
||||
{config, ...}: {
|
||||
wireguard.elisabeth = {
|
||||
client.via = "elisabeth";
|
||||
firewallRuleForNode.elisabeth.allowedTCPPorts = [config.services.open-webui.port];
|
||||
};
|
||||
networking.firewall.allowedTCPPorts = [config.services.open-webui.port];
|
||||
services.ollama = {
|
||||
listenAddress = "0.0.0.0:11434";
|
||||
host = "localhost";
|
||||
port = 3001;
|
||||
enable = true;
|
||||
};
|
||||
services.open-webui = {
|
||||
host = "0.0.0.0";
|
||||
port = 3000;
|
||||
enable = true;
|
||||
environment = {
|
||||
OLLAMA_BASE_URL = "http://localhost:3001";
|
||||
ANONYMIZED_TELEMETRY = "False";
|
||||
DO_NOT_TRACK = "True";
|
||||
SCARF_NO_ANALYTICS = "True";
|
||||
TRANSFORMERS_CACHE = "/var/lib/open-webui/cache/huggingface";
|
||||
WEBUI_AUTH_TRUSTED_EMAIL_HEADER = "X-Email";
|
||||
};
|
||||
};
|
||||
environment.persistence."/state".directories = [
|
||||
{
|
||||
directory = "/var/lib/private/open-webui";
|
||||
mode = "0700";
|
||||
}
|
||||
{
|
||||
directory = "/var/lib/private/ollama";
|
||||
mode = "0700";
|
||||
|
|
214
flake.lock
214
flake.lock
|
@ -12,11 +12,11 @@
|
|||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715290355,
|
||||
"narHash": "sha256-2T7CHTqBXJJ3ZC6R/4TXTcKoXWHcvubKNj9SfomURnw=",
|
||||
"lastModified": 1716561646,
|
||||
"narHash": "sha256-UIGtLO89RxKt7RF2iEgPikSdU53r6v/6WYB0RW3k89I=",
|
||||
"owner": "ryantm",
|
||||
"repo": "agenix",
|
||||
"rev": "8d37c5bdeade12b6479c85acd133063ab53187a0",
|
||||
"rev": "c2fc0762bbe8feb06a2e59a364fa81b3a57671c9",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -37,11 +37,11 @@
|
|||
"pre-commit-hooks": "pre-commit-hooks"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1713903302,
|
||||
"narHash": "sha256-qPy0BYFTenmyG4EU+oXej0V/i4jSsVvWbGGrv9Sb0kQ=",
|
||||
"lastModified": 1717947583,
|
||||
"narHash": "sha256-vN/pfiAzYH4i3cUb5pLqkXgPoAPtaxjUXv5aRpbKShU=",
|
||||
"owner": "oddlama",
|
||||
"repo": "agenix-rekey",
|
||||
"rev": "8da0392e75373711604a07907de25ec9d5277384",
|
||||
"rev": "4551006c2807ab361ea4db5e171afb4798da4fc2",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -270,11 +270,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1713532798,
|
||||
"narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=",
|
||||
"lastModified": 1717408969,
|
||||
"narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40",
|
||||
"rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -336,11 +336,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1713532798,
|
||||
"narHash": "sha256-wtBhsdMJA3Wa32Wtm1eeo84GejtI43pMrFrmwLXrsEc=",
|
||||
"lastModified": 1717408969,
|
||||
"narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
|
||||
"owner": "numtide",
|
||||
"repo": "devshell",
|
||||
"rev": "12e914740a25ea1891ec619bb53cf5e6ca922e40",
|
||||
"rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -356,11 +356,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716291492,
|
||||
"narHash": "sha256-Qvfoa99WdYIneGrrLFIKQCevLgB5vnxvwJe5aWbGYZY=",
|
||||
"lastModified": 1717915259,
|
||||
"narHash": "sha256-VsGPboaleIlPELHY5cNTrXK4jHVmgUra8uC6h7KVC5c=",
|
||||
"owner": "nix-community",
|
||||
"repo": "disko",
|
||||
"rev": "f1654e07728008d354c704d265fc710e3f5f42ee",
|
||||
"rev": "1bbdb06f14e2621290b250e631cf3d8948e4d19b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -435,11 +435,11 @@
|
|||
},
|
||||
"flake-compat_5": {
|
||||
"locked": {
|
||||
"lastModified": 1688025799,
|
||||
"narHash": "sha256-ktpB4dRtnksm9F5WawoIkEneh1nrEvuxb5lJFt1iOyw=",
|
||||
"lastModified": 1717312683,
|
||||
"narHash": "sha256-FrlieJH50AuvagamEvWMIE6D2OAnERuDboFDYAED/dE=",
|
||||
"owner": "nix-community",
|
||||
"repo": "flake-compat",
|
||||
"rev": "8bf105319d44f6b9f0d764efa4fdef9f1cc9ba1c",
|
||||
"rev": "38fd3954cf65ce6faf3d0d45cd26059e059f07ea",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -561,11 +561,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715865404,
|
||||
"narHash": "sha256-/GJvTdTpuDjNn84j82cU6bXztE0MSkdnTWClUCRub78=",
|
||||
"lastModified": 1717285511,
|
||||
"narHash": "sha256-iKzJcpdXih14qYVcZ9QC9XuZYnPc6T8YImb6dX166kw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "8dc45382d5206bd292f9c2768b8058a8fd8311d9",
|
||||
"rev": "2a55567fcf15b1b1c7ed712a2c6fadaec7412ea8",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -574,21 +574,6 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-root": {
|
||||
"locked": {
|
||||
"lastModified": 1713493429,
|
||||
"narHash": "sha256-ztz8JQkI08tjKnsTpfLqzWoKFQF4JGu2LRz8bkdnYUk=",
|
||||
"owner": "srid",
|
||||
"repo": "flake-root",
|
||||
"rev": "bc748b93b86ee76e2032eecda33440ceb2532fcd",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "srid",
|
||||
"repo": "flake-root",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems_3"
|
||||
|
@ -769,6 +754,33 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"git-hooks": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_7",
|
||||
"gitignore": "gitignore_5",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1717664902,
|
||||
"narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=",
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "git-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"gitignore": {
|
||||
"inputs": {
|
||||
"nixpkgs": [
|
||||
|
@ -861,7 +873,7 @@
|
|||
"inputs": {
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"pre-commit-hooks",
|
||||
"git-hooks",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
|
@ -924,11 +936,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715930644,
|
||||
"narHash": "sha256-W9pyM3/vePxrffHtzlJI6lDS3seANQ+Nqp+i58O46LI=",
|
||||
"lastModified": 1717931644,
|
||||
"narHash": "sha256-Sz8Wh9cAiD5FhL8UWvZxBfnvxETSCVZlqWSYWaCPyu0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "e3ad5108f54177e6520535768ddbf1e6af54b59d",
|
||||
"rev": "3d65009effd77cb0d6e7520b68b039836a7606cf",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -945,11 +957,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715930644,
|
||||
"narHash": "sha256-W9pyM3/vePxrffHtzlJI6lDS3seANQ+Nqp+i58O46LI=",
|
||||
"lastModified": 1717525419,
|
||||
"narHash": "sha256-5z2422pzWnPXHgq2ms8lcCfttM0dz+hg+x1pCcNkAws=",
|
||||
"owner": "nix-community",
|
||||
"repo": "home-manager",
|
||||
"rev": "e3ad5108f54177e6520535768ddbf1e6af54b59d",
|
||||
"rev": "a7117efb3725e6197dd95424136f79147aa35e5b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -981,11 +993,11 @@
|
|||
},
|
||||
"impermanence": {
|
||||
"locked": {
|
||||
"lastModified": 1708968331,
|
||||
"narHash": "sha256-VUXLaPusCBvwM3zhGbRIJVeYluh2uWuqtj4WirQ1L9Y=",
|
||||
"lastModified": 1717932370,
|
||||
"narHash": "sha256-7C5lCpiWiyPoIACOcu2mukn/1JRtz6HC/1aEMhUdcw0=",
|
||||
"owner": "nix-community",
|
||||
"repo": "impermanence",
|
||||
"rev": "a33ef102a02ce77d3e39c25197664b7a636f9c30",
|
||||
"rev": "27979f1c3a0d3b9617a3563e2839114ba7d48d3f",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1027,11 +1039,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716120557,
|
||||
"narHash": "sha256-rvNq9YolMY1DRMgwdAti8qwNDjkhTsotSWa15/Ch7+A=",
|
||||
"lastModified": 1717935050,
|
||||
"narHash": "sha256-UWi8G3J+pS+9LVMdjrpLJwncdiMQWrnuUd5ygxCHeNc=",
|
||||
"owner": "nix-community",
|
||||
"repo": "lib-aggregate",
|
||||
"rev": "5fa64b174daa22fe0d20ebbcc0ec2c7905b503f1",
|
||||
"rev": "1b6ea3be6ba37d4d3ba6e5041e2f152bb684ba2c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1064,11 +1076,11 @@
|
|||
"spectrum": "spectrum"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715787097,
|
||||
"narHash": "sha256-TPp2j0ttvBvkk4oXidvo8Y071zEab0BtcNsC3ZEkluI=",
|
||||
"lastModified": 1717441449,
|
||||
"narHash": "sha256-juxjgmLnFbl+/hhIO2cVtIa6caCO4pLKlZWUMwAOznM=",
|
||||
"owner": "astro",
|
||||
"repo": "microvm.nix",
|
||||
"rev": "fa673bf8656fe6f28253b83971a36999bc9995d2",
|
||||
"rev": "e3a4dd5b381fb580804105594cc9c71dc45abdb5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1085,11 +1097,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715901937,
|
||||
"narHash": "sha256-eMyvWP56ZOdraC2IOvZo0/RTDcrrsqJ0oJWDC76JTak=",
|
||||
"lastModified": 1716993688,
|
||||
"narHash": "sha256-vo5k2wQekfeoq/2aleQkBN41dQiQHNTniZeVONWiWLs=",
|
||||
"owner": "lnl7",
|
||||
"repo": "nix-darwin",
|
||||
"rev": "ffc01182f90118119930bdfc528c1ee9a39ecef8",
|
||||
"rev": "c0d5b8c54d6828516c97f6be9f2d00c63a363df4",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1106,11 +1118,11 @@
|
|||
"treefmt-nix": "treefmt-nix"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715804156,
|
||||
"narHash": "sha256-GtIHP86Cz1kD9xZO/cKbNQACHKdoT9WFbLJAq6W2EDY=",
|
||||
"lastModified": 1717698186,
|
||||
"narHash": "sha256-e3/cvm7bAn0RsTBcPfHwuYOi2lwoO4jpTn4nmMSvHfU=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-eval-jobs",
|
||||
"rev": "bb95091f6c6f38f6cfc215a1797a2dd466312c8b",
|
||||
"rev": "b6169e08e76e10b673d1b54f944cddb1e7cbea97",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1148,11 +1160,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716170277,
|
||||
"narHash": "sha256-fCAiox/TuzWGVaAz16PxrR4Jtf9lN5dwWL2W74DS0yI=",
|
||||
"lastModified": 1717919703,
|
||||
"narHash": "sha256-4i/c31+dnpv6KdUA3BhbMDS9Lvg/CDin78caYJlq0bY=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nix-index-database",
|
||||
"rev": "e0638db3db43b582512a7de8c0f8363a162842b9",
|
||||
"rev": "a157a81d0a4bc909b2b6666dd71909bcdc8cd0d6",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1244,11 +1256,11 @@
|
|||
},
|
||||
"nixos-hardware": {
|
||||
"locked": {
|
||||
"lastModified": 1716173274,
|
||||
"narHash": "sha256-FC21Bn4m6ctajMjiUof30awPBH/7WjD0M5yqrWepZbY=",
|
||||
"lastModified": 1717828156,
|
||||
"narHash": "sha256-YvstO0lobf3JWQuAfZCLYRTROC2ZDEgtWeQtWbO49p4=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixos-hardware",
|
||||
"rev": "d9e0b26202fd500cf3e79f73653cce7f7d541191",
|
||||
"rev": "057a7996d012f342a38a26261ee529cebb1755ef",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1296,11 +1308,11 @@
|
|||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1716079763,
|
||||
"narHash": "sha256-DGRfb7fO7c3XDS3twmuaV5NAGPPdU3W7Q35fjIZc8iY=",
|
||||
"lastModified": 1717894324,
|
||||
"narHash": "sha256-4q6ZO3BqHgdd3Aacb/xiQXB4g9TQKpQg/praTpD9vbI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "0df131b5ee4d928a4b664b6d0cd99cf134d6ab6b",
|
||||
"rev": "13eac98dc5233fe7e52f0cd0e2cba7dcd77feca5",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1399,11 +1411,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716308443,
|
||||
"narHash": "sha256-vPJ4VnR1EyW4ft6XlwHst3BMVMqsjXmCtV8ze0+Ox9k=",
|
||||
"lastModified": 1717946219,
|
||||
"narHash": "sha256-FtVXsRY/El4TAVUuM9BnJH2F5tSxd0UMK/AvVzZRsZA=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs-wayland",
|
||||
"rev": "112d54c8a35e974ec03581e44f35d973a89446aa",
|
||||
"rev": "8c7518a4167eb65ca62da3ab49578e728ee9a769",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1414,11 +1426,11 @@
|
|||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1716137900,
|
||||
"narHash": "sha256-sowPU+tLQv8GlqtVtsXioTKeaQvlMz/pefcdwg8MvfM=",
|
||||
"lastModified": 1717786204,
|
||||
"narHash": "sha256-4q0s6m0GUcN7q+Y2DqD27iLvbcd1G50T2lv08kKxkSI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "6c0b7a92c30122196a761b440ac0d46d3d9954f1",
|
||||
"rev": "051f920625ab5aabe37c920346e3e69d7d34400e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1481,21 +1493,20 @@
|
|||
"devshell": "devshell_5",
|
||||
"flake-compat": "flake-compat_6",
|
||||
"flake-parts": "flake-parts_3",
|
||||
"flake-root": "flake-root",
|
||||
"git-hooks": "git-hooks",
|
||||
"home-manager": "home-manager_2",
|
||||
"nix-darwin": "nix-darwin",
|
||||
"nixpkgs": [
|
||||
"nixpkgs"
|
||||
],
|
||||
"pre-commit-hooks": "pre-commit-hooks_4",
|
||||
"treefmt-nix": "treefmt-nix_2"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716294469,
|
||||
"narHash": "sha256-1RdJkVa+axdzLhbeoWJoC3BPODxfx+/Rv7HE+e4CK/Y=",
|
||||
"lastModified": 1717922156,
|
||||
"narHash": "sha256-C/TgTnKY4iWXnBmKocV9KeV+OtZGCh+1Pcw26Elx7JM=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixvim",
|
||||
"rev": "1c9f2a23a6cb9406c35980f4af1a4356f56771e9",
|
||||
"rev": "8a462dc9570bce1de5a7dd1beabd83f95958315b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1620,33 +1631,6 @@
|
|||
}
|
||||
},
|
||||
"pre-commit-hooks_4": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_7",
|
||||
"gitignore": "gitignore_5",
|
||||
"nixpkgs": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
],
|
||||
"nixpkgs-stable": [
|
||||
"nixvim",
|
||||
"nixpkgs"
|
||||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715870890,
|
||||
"narHash": "sha256-nacSOeXtUEM77Gn0G4bTdEOeFIrkCBXiyyFZtdGwuH0=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "fa606cccd7b0ccebe2880051208e4a0f61bfc8c1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"pre-commit-hooks_5": {
|
||||
"inputs": {
|
||||
"flake-compat": "flake-compat_8",
|
||||
"gitignore": "gitignore_6",
|
||||
|
@ -1656,11 +1640,11 @@
|
|||
"nixpkgs-stable": "nixpkgs-stable_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716213921,
|
||||
"narHash": "sha256-xrsYFST8ij4QWaV6HEokCUNIZLjjLP1bYC60K8XiBVA=",
|
||||
"lastModified": 1717664902,
|
||||
"narHash": "sha256-7XfBuLULizXjXfBYy/VV+SpYMHreNRHk9nKMsm1bgb4=",
|
||||
"owner": "cachix",
|
||||
"repo": "pre-commit-hooks.nix",
|
||||
"rev": "0e8fcc54b842ad8428c9e705cb5994eaf05c26a0",
|
||||
"rev": "cc4d466cb1254af050ff7bdf47f6d404a7c646d1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -1689,7 +1673,7 @@
|
|||
"nixpkgs": "nixpkgs_2",
|
||||
"nixpkgs-wayland": "nixpkgs-wayland",
|
||||
"nixvim": "nixvim",
|
||||
"pre-commit-hooks": "pre-commit-hooks_5",
|
||||
"pre-commit-hooks": "pre-commit-hooks_4",
|
||||
"spicetify-nix": "spicetify-nix",
|
||||
"stylix": "stylix",
|
||||
"systems": "systems_12",
|
||||
|
@ -1771,11 +1755,11 @@
|
|||
"nixpkgs": "nixpkgs_5"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1716206302,
|
||||
"narHash": "sha256-5Qc3aQGVyPEOuN82zVamStaV81HebHvLjk3fGfpyCPY=",
|
||||
"lastModified": 1717866166,
|
||||
"narHash": "sha256-iOeRZXIhFpQJdxzNJ3nUAANyDfLqCslRhjGhLD2RstM=",
|
||||
"owner": "danth",
|
||||
"repo": "stylix",
|
||||
"rev": "81df8443556335016d6f0bc22630a95776a56d8b",
|
||||
"rev": "ca3247ed8cfbf369f3fe1b7a421579812a95c101",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
@ -2009,11 +1993,11 @@
|
|||
]
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1715940852,
|
||||
"narHash": "sha256-wJqHMg/K6X3JGAE9YLM0LsuKrKb4XiBeVaoeMNlReZg=",
|
||||
"lastModified": 1717850719,
|
||||
"narHash": "sha256-npYqVg+Wk4oxnWrnVG7416fpfrlRhp/lQ6wQ4DHI8YE=",
|
||||
"owner": "numtide",
|
||||
"repo": "treefmt-nix",
|
||||
"rev": "2fba33a182602b9d49f0b2440513e5ee091d838b",
|
||||
"rev": "4fc1c45a5f50169f9f29f6a98a438fb910b834ed",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
|
@ -117,7 +117,7 @@
|
|||
{
|
||||
secretsConfig = {
|
||||
# This should be a link to one of the age public keys is './keys'
|
||||
masterIdentities = ["/run/decrypt.key.pub"];
|
||||
masterIdentities = [./keys/PatC.pub];
|
||||
extraEncryptionPubkeys = [./secrets/recipients.txt];
|
||||
};
|
||||
agenix-rekey = agenix-rekey.configure {
|
||||
|
|
19
hosts.toml
19
hosts.toml
|
@ -1,19 +0,0 @@
|
|||
[patricknix]
|
||||
type = "nixos"
|
||||
system = "x86_64-linux"
|
||||
|
||||
[desktopnix]
|
||||
type = "nixos"
|
||||
system = "x86_64-linux"
|
||||
|
||||
[gojo]
|
||||
type = "nixos"
|
||||
system = "x86_64-linux"
|
||||
|
||||
[maddy]
|
||||
type = "nixos"
|
||||
system = "x86_64-linux"
|
||||
|
||||
[elisabeth]
|
||||
type = "nixos"
|
||||
system = "x86_64-linux"
|
|
@ -50,9 +50,6 @@
|
|||
dockerCompat = true;
|
||||
};
|
||||
|
||||
system.activationScripts.decryptKey.text = ''
|
||||
ln -f -s ${../../keys/PatC.key} /run/decrypt.key.pub
|
||||
'';
|
||||
boot.binfmt.emulatedSystems = ["aarch64-linux" "riscv64-linux"];
|
||||
nix.settings.system-features = ["kvm" "nixos-test"];
|
||||
|
||||
|
@ -63,4 +60,5 @@
|
|||
services.netbird.enable = true;
|
||||
# Do not cleanup nix store to prevent having to rebuild packages onca a month
|
||||
nix.gc.automatic = lib.mkForce false;
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
}
|
||||
|
|
|
@ -33,4 +33,5 @@
|
|||
variant = "bone";
|
||||
};
|
||||
};
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
}
|
||||
|
|
|
@ -13,7 +13,7 @@
|
|||
forgejo = "forge";
|
||||
immich = "immich";
|
||||
nextcloud = "nc";
|
||||
ollama = "ollama";
|
||||
ollama = "ai";
|
||||
paperless = "ppl";
|
||||
ttrss = "rss";
|
||||
vaultwarden = "pw";
|
||||
|
@ -72,7 +72,8 @@ in {
|
|||
# pass information via X-User and X-Email headers to backend,
|
||||
# requires running with --set-xauthrequest flag
|
||||
auth_request_set $user $upstream_http_x_auth_request_preferred_username;
|
||||
auth_request_set $email $upstream_http_x_auth_request_email;
|
||||
# Set the email to our own domain in case user change their mail
|
||||
auth_request_set $email "''${upstream_http_x_auth_request_preferred_username}@${config.secrets.secrets.global.domains.web}";
|
||||
proxy_set_header X-User $user;
|
||||
proxy_set_header X-Email $email;
|
||||
|
||||
|
@ -162,9 +163,8 @@ in {
|
|||
(proxyProtect "ttrss" {port = 80;} true)
|
||||
(blockOf "yourspotify" {port = 80;})
|
||||
(blockOf "homebox" {})
|
||||
((proxyProtect "firefly" {port = 80;} true)
|
||||
// {
|
||||
})
|
||||
(proxyProtect "ollama" {} true)
|
||||
(proxyProtect "firefly" {port = 80;} true)
|
||||
(blockOf "apispotify" {
|
||||
port = 3000;
|
||||
upstream = "yourspotify";
|
||||
|
|
Binary file not shown.
|
@ -1,43 +0,0 @@
|
|||
{
|
||||
inputs,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
imports = [
|
||||
inputs.nixos-hardware.nixosModules.common-cpu-intel
|
||||
inputs.nixos-hardware.nixosModules.common-gpu-intel
|
||||
inputs.nixos-hardware.nixosModules.common-pc-laptop
|
||||
inputs.nixos-hardware.nixosModules.common-pc-laptop-ssd
|
||||
|
||||
../../config/basic
|
||||
../../config/optional/dev.nix
|
||||
../../config/optional/graphical.nix
|
||||
../../config/optional/wayland.nix
|
||||
../../config/optional/xserver.nix
|
||||
../../config/optional/printing.nix
|
||||
../../config/hardware/bluetooth.nix
|
||||
../../config/hardware/laptop.nix
|
||||
../../config/hardware/physical.nix
|
||||
../../config/hardware/pipewire.nix
|
||||
../../config/hardware/yubikey.nix
|
||||
|
||||
./net.nix
|
||||
./fs.nix
|
||||
|
||||
../../users/simon
|
||||
];
|
||||
stylix.fonts.sizes = {
|
||||
#terminal = 9;
|
||||
#applications = 9;
|
||||
#desktop = 8;
|
||||
};
|
||||
services.xserver = {
|
||||
layout = "de";
|
||||
xkbVariant = "neo";
|
||||
libinput = {
|
||||
touchpad = lib.mkForce {
|
||||
accelSpeed = "0.5";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,30 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: {
|
||||
disko.devices = {
|
||||
disk = {
|
||||
ssd = {
|
||||
type = "disk";
|
||||
device = "/dev/disk/by-id/${config.secrets.secrets.local.disko.ssd}";
|
||||
content = with lib.disko.gpt; {
|
||||
type = "gpt";
|
||||
partitions = {
|
||||
boot = partEfi "260MB";
|
||||
rpool = {
|
||||
content = {
|
||||
type = "zfs";
|
||||
pool = "rpool";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
zpool = with lib.disko.zfs; {
|
||||
rpool = mkZpool {datasets = impermanenceZfsDatasets;};
|
||||
};
|
||||
};
|
||||
fileSystems."/state".neededForBoot = true;
|
||||
}
|
|
@ -1,24 +0,0 @@
|
|||
{config, ...}: {
|
||||
networking = {
|
||||
inherit (config.secrets.secrets.local.networking) hostId;
|
||||
wireless.iwd.enable = true;
|
||||
};
|
||||
|
||||
systemd.network.networks = {
|
||||
"01-wlan1" = {
|
||||
DHCP = "yes";
|
||||
matchConfig.MACAddress = config.secrets.secrets.local.networking.wlan1.mac;
|
||||
networkConfig = {
|
||||
IPv6PrivacyExtensions = "yes";
|
||||
MulticastDNS = true;
|
||||
};
|
||||
dns = ["1.1.1.1"];
|
||||
dhcpV4Config.RouteMetric = 40;
|
||||
dhcpV6Config.RouteMetric = 40;
|
||||
};
|
||||
};
|
||||
age.secrets.eduroam = {
|
||||
rekeyFile = ./secrets/iwd/eduroam.8021x.age;
|
||||
path = "/var/lib/iwd/eduroam.8021x";
|
||||
};
|
||||
}
|
|
@ -1 +0,0 @@
|
|||
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIH+6isyj+sdzilpFSgGjw3xUfoJ1s307OJGcuzmgJL+L
|
|
@ -1,17 +0,0 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 FvDDqK/3eca0id5we/szPNjtkeNg44MPJJa/DkxA8yY
|
||||
bERDGRpArN1wKKvYEDZuP4ktvBj3yYj5ophx5PLC9hU
|
||||
-> piv-p256 XTQkUA AxE8qOeoW7GCN++vsXmKs1p92iiNHuV/DEPR4K1h64gy
|
||||
UUfWj4rXavZA28BM/hBKqLF1MJcakFpEIdzd/78SoVY
|
||||
-> piv-p256 ZFgiIw AtMYu+DvAD//JL7rZfEkkeGyxakvqzArsTjVwe6IRDZI
|
||||
fdTmmtSM1Wy2y+0INVKYbCItuKh/qSipRa/OHeNQoEY
|
||||
-> piv-p256 5vmPtQ A/pjTZCYMU8jMEN1lIDPTsnuMxclc+7tSDZ/jc+vHptt
|
||||
6KAF06R1l47U2RdCkJK+lFc67SMR/+hvxfi2qrJDyS0
|
||||
-> piv-p256 ZFgiIw A0N/CAMSA29+Sqbol4PCs7wYYJT4AvAKd0DKe0hfy8Bp
|
||||
Vlo9T4FZNRK8kR5OuxrAVUe5Tx5x9NAeaI2gKIJeNEA
|
||||
-> dZ2v|-grease *(F:08]t
|
||||
IZuQlw2zI1CelSB69O6XeKI2qG83Cu/bRhusaMtUYfGH5iskbPdh0OJ6ohadEusT
|
||||
sYUVi0mBry7L
|
||||
--- Y5cpADckhrStO9mPQXw8h448VBYUXCiKEYucO8qNHg4
|
||||
6¨É’ôUsüÖ½èK¶tJ4ð8<C3B0>Ë‹Ÿ¸÷%7³¿ËÛ°ãÌ'ó–îæ¤o•<6F>˜êˆ]ß-7nÝ|bx<62>¢¶MŸ–“
Ú–<C39A>¬»m$š¡÷¾<C3B7>X⇸S<C2B8>âæßsUf±|<7C>K6¡ÒŽ©vL<76>._.ì+¬ïùV
|
||||
¥ÿsÅm”ÁÖÀ‘ÿ·nªÜ·~Pñ¸5p!g÷€W×½kÑþ`û+»y}ñî£
|
Binary file not shown.
|
@ -14,4 +14,5 @@
|
|||
};
|
||||
boot.mode = "bios";
|
||||
boot.initrd.availableKernelModules = ["virtio_pci" "virtio_net" "virtio_scsi" "virtio_blk"];
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
}
|
||||
|
|
|
@ -51,8 +51,5 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
system.activationScripts.decryptKey.text = ''
|
||||
ln -f -s ${../../keys/PatC.key} /run/decrypt.key.pub
|
||||
'';
|
||||
services.netbird.enable = true;
|
||||
nixpkgs.hostPlatform = "x86_64-linux";
|
||||
}
|
||||
|
|
93
modules/homebox.nix
Normal file
93
modules/homebox.nix
Normal file
|
@ -0,0 +1,93 @@
|
|||
{
|
||||
lib,
|
||||
config,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
cfg = config.services.homebox;
|
||||
inherit
|
||||
(lib)
|
||||
mkEnableOption
|
||||
mkPackageOption
|
||||
mkDefault
|
||||
types
|
||||
mkIf
|
||||
;
|
||||
in {
|
||||
options.services.homebox = {
|
||||
enable = mkEnableOption "homebox";
|
||||
package = mkPackageOption pkgs "homebox" {};
|
||||
settings = lib.mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
defaultText = ''
|
||||
HBOX_STORAGE_DATA = "/var/lib/homebox/data";
|
||||
HBOX_STORAGE_SQLITE_URL = "/var/lib/homebox/data/homebox.db?_pragma=busy_timeout=999&_pragma=journal_mode=WAL&_fk=1";
|
||||
HBOX_OPTIONS_ALLOW_REGISTRATION = "false";
|
||||
HBOX_MODE = "production";
|
||||
'';
|
||||
description = ''
|
||||
The homebox configuration as Environment variables. For definitions and available options see the upstream documentation at:
|
||||
[docs](https://hay-kot.github.io/homebox/quick-start/#env-variables-configuration).
|
||||
'';
|
||||
};
|
||||
};
|
||||
config = mkIf cfg.enable {
|
||||
services.homebox.settings = {
|
||||
HBOX_STORAGE_DATA = mkDefault "/var/lib/homebox/data";
|
||||
HBOX_STORAGE_SQLITE_URL = mkDefault "/var/lib/homebox/data/homebox.db?_pragma=busy_timeout=999&_pragma=journal_mode=WAL&_fk=1";
|
||||
HBOX_OPTIONS_ALLOW_REGISTRATION = mkDefault "false";
|
||||
HBOX_MODE = mkDefault "production";
|
||||
};
|
||||
systemd.services.homebox = {
|
||||
after = ["network.target"];
|
||||
environment = cfg.settings;
|
||||
serviceConfig = {
|
||||
User = "homebox";
|
||||
Group = "homebox";
|
||||
ExecStart = lib.getExe cfg.package;
|
||||
DynamicUser = true;
|
||||
StateDirectory = "homebox";
|
||||
WorkingDirectory = "/var/lib/homebox";
|
||||
LimitNOFILE = "1048576";
|
||||
PrivateTmp = true;
|
||||
PrivateDevices = true;
|
||||
StateDirectoryMode = "0700";
|
||||
Restart = "always";
|
||||
|
||||
# Hardening
|
||||
CapabilityBoundingSet = "";
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
PrivateUsers = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectProc = "invisible";
|
||||
ProcSubset = "pid";
|
||||
ProtectSystem = "strict";
|
||||
RestrictAddressFamilies = [
|
||||
"AF_INET"
|
||||
"AF_INET6"
|
||||
"AF_NETLINK"
|
||||
];
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
SystemCallArchitectures = "native";
|
||||
SystemCallFilter = [
|
||||
"@system-service"
|
||||
"@pkey"
|
||||
];
|
||||
RestrictSUIDSGID = true;
|
||||
PrivateMounts = true;
|
||||
# System Call Filtering
|
||||
UMask = "0077";
|
||||
};
|
||||
wantedBy = ["multi-user.target"];
|
||||
};
|
||||
};
|
||||
meta.maintainers = with lib.maintainers; [patrickdag];
|
||||
}
|
|
@ -1,162 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
getExe
|
||||
literalExpression
|
||||
mkAfter
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
optionalAttrs
|
||||
optionalString
|
||||
;
|
||||
|
||||
inherit
|
||||
(lib.types)
|
||||
bool
|
||||
listOf
|
||||
nullOr
|
||||
path
|
||||
port
|
||||
str
|
||||
;
|
||||
|
||||
cfg = config.services.netbird.server.coturn;
|
||||
in {
|
||||
options.services.netbird.server.coturn = {
|
||||
enable = mkEnableOption "a Coturn server for Netbird, will also open the firewall on the configured range";
|
||||
|
||||
useAcmeCertificates = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Whether to use ACME certificates corresponding to the given domain for the server.
|
||||
'';
|
||||
};
|
||||
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
description = "The domain under which the coturn server runs.";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = str;
|
||||
default = "netbird";
|
||||
description = ''
|
||||
The username used by netbird to connect to the coturn server.
|
||||
'';
|
||||
};
|
||||
|
||||
password = mkOption {
|
||||
type = nullOr str;
|
||||
default = null;
|
||||
description = ''
|
||||
The password of the user used by netbird to connect to the coturn server.
|
||||
Be advised this will be world readable in the nix store.
|
||||
'';
|
||||
};
|
||||
|
||||
passwordFile = mkOption {
|
||||
type = nullOr path;
|
||||
default = null;
|
||||
description = ''
|
||||
The path to a file containing the password of the user used by netbird to connect to the coturn server.
|
||||
'';
|
||||
};
|
||||
|
||||
openPorts = mkOption {
|
||||
type = listOf port;
|
||||
default = with config.services.coturn; [
|
||||
listening-port
|
||||
alt-listening-port
|
||||
tls-listening-port
|
||||
alt-tls-listening-port
|
||||
];
|
||||
defaultText = literalExpression ''
|
||||
with config.services.coturn; [
|
||||
listening-port
|
||||
alt-listening-port
|
||||
tls-listening-port
|
||||
alt-tls-listening-port
|
||||
];
|
||||
'';
|
||||
|
||||
description = ''
|
||||
The list of ports used by coturn for listening to open in the firewall.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable (mkMerge [
|
||||
{
|
||||
assertions = [
|
||||
{
|
||||
assertion = (cfg.password == null) != (cfg.passwordFile == null);
|
||||
message = "Exactly one of `password` or `passwordFile` must be given for the coturn setup.";
|
||||
}
|
||||
];
|
||||
|
||||
services.coturn =
|
||||
{
|
||||
enable = true;
|
||||
|
||||
realm = cfg.domain;
|
||||
lt-cred-mech = true;
|
||||
no-cli = true;
|
||||
|
||||
extraConfig = ''
|
||||
fingerprint
|
||||
user=${cfg.user}:${
|
||||
if cfg.password != null
|
||||
then cfg.password
|
||||
else "@password@"
|
||||
}
|
||||
no-software-attribute
|
||||
'';
|
||||
}
|
||||
// (optionalAttrs cfg.useAcmeCertificates {
|
||||
cert = "@cert@";
|
||||
pkey = "@pkey@";
|
||||
});
|
||||
|
||||
systemd.services.coturn = let
|
||||
dir = config.security.acme.certs.${cfg.domain}.directory;
|
||||
preStart' =
|
||||
(optionalString (cfg.passwordFile != null) ''
|
||||
${getExe pkgs.replace-secret} @password@ ${cfg.passwordFile} /run/coturn/turnserver.cfg
|
||||
'')
|
||||
+ (optionalString cfg.useAcmeCertificates ''
|
||||
${getExe pkgs.replace-secret} @cert@ "$CREDENTIALS_DIRECTORY/cert.pem" /run/coturn/turnserver.cfg
|
||||
${getExe pkgs.replace-secret} @pkey@ "$CREDENTIALS_DIRECTORY/pkey.pem" /run/coturn/turnserver.cfg
|
||||
'');
|
||||
in
|
||||
(optionalAttrs (preStart' != "") {preStart = mkAfter preStart';})
|
||||
// (optionalAttrs cfg.useAcmeCertificates {
|
||||
serviceConfig.LoadCredential = [
|
||||
"cert.pem:${dir}/fullchain.pem"
|
||||
"pkey.pem:${dir}/key.pem"
|
||||
];
|
||||
});
|
||||
|
||||
security.acme.certs = mkIf cfg.useAcmeCertificates {${cfg.domain}.postRun = "systemctl restart coturn.service";};
|
||||
|
||||
networking.firewall = {
|
||||
allowedUDPPorts = cfg.openPorts;
|
||||
allowedTCPPorts = cfg.openPorts;
|
||||
|
||||
allowedUDPPortRanges = with config.services.coturn; [
|
||||
{
|
||||
from = min-port;
|
||||
to = max-port;
|
||||
}
|
||||
];
|
||||
};
|
||||
}
|
||||
]);
|
||||
}
|
|
@ -1,189 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
boolToString
|
||||
concatStringsSep
|
||||
hasAttr
|
||||
isBool
|
||||
mapAttrs
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
;
|
||||
|
||||
inherit
|
||||
(lib.types)
|
||||
attrsOf
|
||||
bool
|
||||
either
|
||||
package
|
||||
str
|
||||
submodule
|
||||
;
|
||||
|
||||
toStringEnv = value:
|
||||
if isBool value
|
||||
then boolToString value
|
||||
else toString value;
|
||||
|
||||
cfg = config.services.netbird.server.dashboard;
|
||||
in {
|
||||
options.services.netbird.server.dashboard = {
|
||||
enable = mkEnableOption "the static netbird dashboard frontend";
|
||||
|
||||
package = mkPackageOption pkgs "netbird-dashboard" {};
|
||||
|
||||
enableNginx = mkEnableOption "Nginx reverse-proxy to serve the dashboard.";
|
||||
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
default = "localhost";
|
||||
description = "The domain under which the dashboard runs.";
|
||||
};
|
||||
|
||||
managementServer = mkOption {
|
||||
type = str;
|
||||
description = "The address of the management server, used for the API endpoints.";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
type = submodule {freeformType = attrsOf (either str bool);};
|
||||
|
||||
defaultText = ''
|
||||
{
|
||||
AUTH_AUDIENCE = "netbird";
|
||||
AUTH_CLIENT_ID = "netbird";
|
||||
AUTH_SUPPORTED_SCOPES = "openid profile email";
|
||||
NETBIRD_TOKEN_SOURCE = "idToken";
|
||||
USE_AUTH0 = false;
|
||||
}
|
||||
'';
|
||||
|
||||
description = ''
|
||||
An attribute set that will be used to substitute variables when building the dashboard.
|
||||
Any values set here will be templated into the frontend and be public for anyone that can reach your website.
|
||||
The exact values sadly aren't documented anywhere.
|
||||
A starting point when searching for valid values is this [script](https://github.com/netbirdio/dashboard/blob/main/docker/init_react_envs.sh)
|
||||
The only mandatory value is 'AUTH_AUTHORITY' as we cannot set a default value here.
|
||||
'';
|
||||
};
|
||||
|
||||
finalDrv = mkOption {
|
||||
readOnly = true;
|
||||
type = package;
|
||||
description = ''
|
||||
The derivation containing the final templated dashboard.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
assertions = [
|
||||
{
|
||||
assertion = hasAttr "AUTH_AUTHORITY" cfg.settings;
|
||||
message = "The setting AUTH_AUTHORITY is required for the dasboard to function.";
|
||||
}
|
||||
];
|
||||
|
||||
services.netbird.server.dashboard = {
|
||||
settings =
|
||||
{
|
||||
# Due to how the backend and frontend work this secret will be templated into the backend
|
||||
# and then served statically from your website
|
||||
# This enables you to login without the normally needed indirection through the backend
|
||||
# but this also means anyone that can reach your website can
|
||||
# fetch this secret, which is why there is no real need to put it into
|
||||
# special options as its public anyway
|
||||
# As far as I know leaking this secret is just
|
||||
# an information leak as one can fetch some basic app
|
||||
# informations from the IDP
|
||||
# To actually do something one still needs to have login
|
||||
# data and this secret so this being public will not
|
||||
# suffice for anything just decreasing security
|
||||
AUTH_CLIENT_SECRET = "";
|
||||
|
||||
NETBIRD_MGMT_API_ENDPOINT = cfg.managementServer;
|
||||
NETBIRD_MGMT_GRPC_API_ENDPOINT = cfg.managementServer;
|
||||
}
|
||||
// (mapAttrs (_: mkDefault) {
|
||||
# Those values have to be easily overridable
|
||||
AUTH_AUDIENCE = "netbird"; # must be set for your devices to be able to log in
|
||||
AUTH_CLIENT_ID = "netbird";
|
||||
AUTH_SUPPORTED_SCOPES = "openid profile email";
|
||||
NETBIRD_TOKEN_SOURCE = "idToken";
|
||||
USE_AUTH0 = false;
|
||||
});
|
||||
|
||||
# The derivation containing the templated dashboard
|
||||
finalDrv =
|
||||
pkgs.runCommand "netbird-dashboard"
|
||||
{
|
||||
nativeBuildInputs = [pkgs.gettext];
|
||||
env =
|
||||
{
|
||||
ENV_STR = concatStringsSep " " [
|
||||
"$AUTH_AUDIENCE"
|
||||
"$AUTH_AUTHORITY"
|
||||
"$AUTH_CLIENT_ID"
|
||||
"$AUTH_CLIENT_SECRET"
|
||||
"$AUTH_REDIRECT_URI"
|
||||
"$AUTH_SILENT_REDIRECT_URI"
|
||||
"$AUTH_SUPPORTED_SCOPES"
|
||||
"$NETBIRD_DRAG_QUERY_PARAMS"
|
||||
"$NETBIRD_GOOGLE_ANALYTICS_ID"
|
||||
"$NETBIRD_HOTJAR_TRACK_ID"
|
||||
"$NETBIRD_MGMT_API_ENDPOINT"
|
||||
"$NETBIRD_MGMT_GRPC_API_ENDPOINT"
|
||||
"$NETBIRD_TOKEN_SOURCE"
|
||||
"$USE_AUTH0"
|
||||
];
|
||||
}
|
||||
// (mapAttrs (_: toStringEnv) cfg.settings);
|
||||
}
|
||||
''
|
||||
cp -R ${cfg.package} build
|
||||
|
||||
find build -type d -exec chmod 755 {} \;
|
||||
OIDC_TRUSTED_DOMAINS="build/OidcTrustedDomains.js"
|
||||
|
||||
envsubst "$ENV_STR" < "$OIDC_TRUSTED_DOMAINS.tmpl" > "$OIDC_TRUSTED_DOMAINS"
|
||||
|
||||
for f in $(grep -R -l AUTH_SUPPORTED_SCOPES build/); do
|
||||
mv "$f" "$f.copy"
|
||||
envsubst "$ENV_STR" < "$f.copy" > "$f"
|
||||
rm "$f.copy"
|
||||
done
|
||||
|
||||
cp -R build $out
|
||||
'';
|
||||
};
|
||||
|
||||
services.nginx = mkIf cfg.enableNginx {
|
||||
enable = true;
|
||||
|
||||
virtualHosts.${cfg.domain} = {
|
||||
locations = {
|
||||
"/" = {
|
||||
root = cfg.finalDrv;
|
||||
tryFiles = "$uri $uri.html $uri/ =404";
|
||||
};
|
||||
|
||||
"/404.html".extraConfig = ''
|
||||
internal;
|
||||
'';
|
||||
};
|
||||
|
||||
extraConfig = ''
|
||||
error_page 404 /404.html;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,461 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
any
|
||||
concatMap
|
||||
getExe'
|
||||
literalExpression
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
mkPackageOption
|
||||
optional
|
||||
recursiveUpdate
|
||||
;
|
||||
|
||||
inherit
|
||||
(lib.types)
|
||||
bool
|
||||
enum
|
||||
listOf
|
||||
port
|
||||
str
|
||||
;
|
||||
|
||||
inherit (utils) escapeSystemdExecArgs genJqSecretsReplacementSnippet;
|
||||
|
||||
stateDir = "/var/lib/netbird-mgmt";
|
||||
|
||||
settingsFormat = pkgs.formats.json {};
|
||||
|
||||
defaultSettings = {
|
||||
Stuns = [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "stun:${cfg.turnDomain}:3478";
|
||||
Username = "";
|
||||
Password = null;
|
||||
}
|
||||
];
|
||||
|
||||
TURNConfig = {
|
||||
Turns = [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "turn:${cfg.turnDomain}:${builtins.toString cfg.turnPort}";
|
||||
Username = "netbird";
|
||||
Password = "netbird";
|
||||
}
|
||||
];
|
||||
|
||||
CredentialsTTL = "12h";
|
||||
Secret = "not-secure-secret";
|
||||
TimeBasedCredentials = false;
|
||||
};
|
||||
|
||||
Signal = {
|
||||
Proto = "https";
|
||||
URI = "${cfg.domain}:443";
|
||||
Username = "";
|
||||
Password = null;
|
||||
};
|
||||
|
||||
ReverseProxy = {
|
||||
TrustedHTTPProxies = [];
|
||||
TrustedHTTPProxiesCount = 0;
|
||||
TrustedPeers = ["0.0.0.0/0"];
|
||||
};
|
||||
|
||||
Datadir = "${stateDir}/data";
|
||||
DataStoreEncryptionKey = "very-insecure-key";
|
||||
StoreConfig = {
|
||||
Engine = "sqlite";
|
||||
};
|
||||
|
||||
HttpConfig = {
|
||||
Address = "127.0.0.1:${builtins.toString cfg.port}";
|
||||
IdpSignKeyRefreshEnabled = true;
|
||||
OIDCConfigEndpoint = cfg.oidcConfigEndpoint;
|
||||
};
|
||||
|
||||
IdpManagerConfig = {
|
||||
ManagerType = "none";
|
||||
ClientConfig = {
|
||||
Issuer = "";
|
||||
TokenEndpoint = "";
|
||||
ClientID = "netbird";
|
||||
ClientSecret = "";
|
||||
GrantType = "client_credentials";
|
||||
};
|
||||
|
||||
ExtraConfig = {};
|
||||
Auth0ClientCredentials = null;
|
||||
AzureClientCredentials = null;
|
||||
KeycloakClientCredentials = null;
|
||||
ZitadelClientCredentials = null;
|
||||
};
|
||||
|
||||
DeviceAuthorizationFlow = {
|
||||
Provider = "none";
|
||||
ProviderConfig = {
|
||||
Audience = "netbird";
|
||||
Domain = null;
|
||||
ClientID = "netbird";
|
||||
TokenEndpoint = null;
|
||||
DeviceAuthEndpoint = "";
|
||||
Scope = "openid profile email";
|
||||
UseIDToken = false;
|
||||
};
|
||||
};
|
||||
|
||||
PKCEAuthorizationFlow = {
|
||||
ProviderConfig = {
|
||||
Audience = "netbird";
|
||||
ClientID = "netbird";
|
||||
ClientSecret = "";
|
||||
AuthorizationEndpoint = "";
|
||||
TokenEndpoint = "";
|
||||
Scope = "openid profile email";
|
||||
RedirectURLs = ["http://localhost:53000"];
|
||||
UseIDToken = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
managementConfig = recursiveUpdate defaultSettings cfg.settings;
|
||||
|
||||
managementFile = settingsFormat.generate "config.json" managementConfig;
|
||||
|
||||
cfg = config.services.netbird.server.management;
|
||||
in {
|
||||
options.services.netbird.server.management = {
|
||||
enable = mkEnableOption "Netbird Management Service.";
|
||||
|
||||
package = mkPackageOption pkgs "netbird" {};
|
||||
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
description = "The domain under which the management API runs.";
|
||||
};
|
||||
|
||||
turnDomain = mkOption {
|
||||
type = str;
|
||||
description = "The domain of the TURN server to use.";
|
||||
};
|
||||
|
||||
turnPort = mkOption {
|
||||
type = port;
|
||||
default = 3478;
|
||||
description = ''
|
||||
The port of the TURN server to use.
|
||||
'';
|
||||
};
|
||||
|
||||
dnsDomain = mkOption {
|
||||
type = str;
|
||||
default = "netbird.selfhosted";
|
||||
description = "Domain used for peer resolution.";
|
||||
};
|
||||
|
||||
singleAccountModeDomain = mkOption {
|
||||
type = str;
|
||||
default = "netbird.selfhosted";
|
||||
description = ''
|
||||
Enables single account mode.
|
||||
This means that all the users will be under the same account grouped by the specified domain.
|
||||
If the installation has more than one account, the property is ineffective.
|
||||
'';
|
||||
};
|
||||
|
||||
disableAnonymousMetrics = mkOption {
|
||||
type = bool;
|
||||
default = true;
|
||||
description = "Disables push of anonymous usage metrics to NetBird.";
|
||||
};
|
||||
|
||||
disableSingleAccountMode = mkOption {
|
||||
type = bool;
|
||||
default = false;
|
||||
description = ''
|
||||
If set to true, disables single account mode.
|
||||
The `singleAccountModeDomain` property will be ignored and every new user will have a separate NetBird account.
|
||||
'';
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 8011;
|
||||
description = "Internal port of the management server.";
|
||||
};
|
||||
|
||||
extraOptions = mkOption {
|
||||
type = listOf str;
|
||||
default = [];
|
||||
description = ''
|
||||
Additional options given to netbird-mgmt as commandline arguments.
|
||||
'';
|
||||
};
|
||||
|
||||
oidcConfigEndpoint = mkOption {
|
||||
type = str;
|
||||
description = "The oidc discovery endpoint.";
|
||||
example = "https://example.eu.auth0.com/.well-known/openid-configuration";
|
||||
};
|
||||
|
||||
settings = mkOption {
|
||||
inherit (settingsFormat) type;
|
||||
|
||||
defaultText = literalExpression ''
|
||||
defaultSettings = {
|
||||
Stuns = [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "stun:''${cfg.turnDomain}:3478";
|
||||
Username = "";
|
||||
Password = null;
|
||||
}
|
||||
];
|
||||
|
||||
TURNConfig = {
|
||||
Turns = [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "turn:''${cfg.turnDomain}:3478";
|
||||
Username = "netbird";
|
||||
Password = "netbird";
|
||||
}
|
||||
];
|
||||
|
||||
CredentialsTTL = "12h";
|
||||
Secret = "not-secure-secret";
|
||||
TimeBasedCredentials = false;
|
||||
};
|
||||
|
||||
Signal = {
|
||||
Proto = "https";
|
||||
URI = "''${cfg.domain}:443";
|
||||
Username = "";
|
||||
Password = null;
|
||||
};
|
||||
|
||||
ReverseProxy = {
|
||||
TrustedHTTPProxies = [ ];
|
||||
TrustedHTTPProxiesCount = 0;
|
||||
TrustedPeers = [ "0.0.0.0/0" ];
|
||||
};
|
||||
|
||||
Datadir = "''${stateDir}/data";
|
||||
DataStoreEncryptionKey = "genEVP6j/Yp2EeVujm0zgqXrRos29dQkpvX0hHdEUlQ=";
|
||||
StoreConfig = { Engine = "sqlite"; };
|
||||
|
||||
HttpConfig = {
|
||||
Address = "127.0.0.1:''${builtins.toString cfg.port}";
|
||||
IdpSignKeyRefreshEnabled = true;
|
||||
OIDCConfigEndpoint = cfg.oidcConfigEndpoint;
|
||||
};
|
||||
|
||||
IdpManagerConfig = {
|
||||
ManagerType = "none";
|
||||
ClientConfig = {
|
||||
Issuer = "";
|
||||
TokenEndpoint = "";
|
||||
ClientID = "netbird";
|
||||
ClientSecret = "";
|
||||
GrantType = "client_credentials";
|
||||
};
|
||||
|
||||
ExtraConfig = { };
|
||||
Auth0ClientCredentials = null;
|
||||
AzureClientCredentials = null;
|
||||
KeycloakClientCredentials = null;
|
||||
ZitadelClientCredentials = null;
|
||||
};
|
||||
|
||||
DeviceAuthorizationFlow = {
|
||||
Provider = "none";
|
||||
ProviderConfig = {
|
||||
Audience = "netbird";
|
||||
Domain = null;
|
||||
ClientID = "netbird";
|
||||
TokenEndpoint = null;
|
||||
DeviceAuthEndpoint = "";
|
||||
Scope = "openid profile email offline_access api";
|
||||
UseIDToken = false;
|
||||
};
|
||||
};
|
||||
|
||||
PKCEAuthorizationFlow = {
|
||||
ProviderConfig = {
|
||||
Audience = "netbird";
|
||||
ClientID = "netbird";
|
||||
ClientSecret = "";
|
||||
AuthorizationEndpoint = "";
|
||||
TokenEndpoint = "";
|
||||
Scope = "openid profile email offline_access api";
|
||||
RedirectURLs = "http://localhost:53000";
|
||||
UseIDToken = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
'';
|
||||
|
||||
default = {};
|
||||
|
||||
description = ''
|
||||
Configuration of the netbird management server.
|
||||
Options containing secret data should be set to an attribute set containing the attribute _secret
|
||||
- a string pointing to a file containing the value the option should be set to.
|
||||
See the example to get a better picture of this: in the resulting management.json file,
|
||||
the `DataStoreEncryptionKey` key will be set to the contents of the /run/agenix/netbird_mgmt-data_store_encryption_key file.
|
||||
'';
|
||||
|
||||
example = {
|
||||
DataStoreEncryptionKey = {
|
||||
_secret = "/run/agenix/netbird_mgmt-data_store_encryption_key";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = enum [
|
||||
"ERROR"
|
||||
"WARN"
|
||||
"INFO"
|
||||
"DEBUG"
|
||||
];
|
||||
default = "INFO";
|
||||
description = "Log level of the netbird services.";
|
||||
};
|
||||
|
||||
enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird management service.";
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
warnings =
|
||||
concatMap
|
||||
(
|
||||
{
|
||||
check,
|
||||
name,
|
||||
}:
|
||||
optional check "${name} is world-readable in the Nix Store, you should provide it as a _secret."
|
||||
)
|
||||
[
|
||||
{
|
||||
check = builtins.isString managementConfig.TURNConfig.Secret;
|
||||
name = "The TURNConfig.secret";
|
||||
}
|
||||
{
|
||||
check = builtins.isString managementConfig.DataStoreEncryptionKey;
|
||||
name = "The DataStoreEncryptionKey";
|
||||
}
|
||||
{
|
||||
check = any (T: (T ? Password) && builtins.isString T.Password) managementConfig.TURNConfig.Turns;
|
||||
name = "A Turn configuration's password";
|
||||
}
|
||||
];
|
||||
|
||||
systemd.services.netbird-management = {
|
||||
description = "The management server for Netbird, a wireguard VPN";
|
||||
documentation = ["https://netbird.io/docs/"];
|
||||
|
||||
after = ["network.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
restartTriggers = [managementFile];
|
||||
|
||||
preStart = genJqSecretsReplacementSnippet managementConfig "${stateDir}/management.json";
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = escapeSystemdExecArgs (
|
||||
[
|
||||
(getExe' cfg.package "netbird-mgmt")
|
||||
"management"
|
||||
# Config file
|
||||
"--config"
|
||||
"${stateDir}/management.json"
|
||||
# Data directory
|
||||
"--datadir"
|
||||
"${stateDir}/data"
|
||||
# DNS domain
|
||||
"--dns-domain"
|
||||
cfg.dnsDomain
|
||||
# Port to listen on
|
||||
"--port"
|
||||
cfg.port
|
||||
# Log to stdout
|
||||
"--log-file"
|
||||
"console"
|
||||
# Log level
|
||||
"--log-level"
|
||||
cfg.logLevel
|
||||
#
|
||||
"--idp-sign-key-refresh-enabled"
|
||||
# Domain for internal resolution
|
||||
"--single-account-mode-domain"
|
||||
cfg.singleAccountModeDomain
|
||||
]
|
||||
++ (optional cfg.disableAnonymousMetrics "--disable-anonymous-metrics")
|
||||
++ (optional cfg.disableSingleAccountMode "--disable-single-account-mode")
|
||||
++ cfg.extraOptions
|
||||
);
|
||||
Restart = "always";
|
||||
RuntimeDirectory = "netbird-mgmt";
|
||||
StateDirectory = [
|
||||
"netbird-mgmt"
|
||||
"netbird-mgmt/data"
|
||||
];
|
||||
WorkingDirectory = stateDir;
|
||||
|
||||
# hardening
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectSystem = true;
|
||||
RemoveIPC = true;
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
stopIfChanged = false;
|
||||
};
|
||||
|
||||
services.nginx = mkIf cfg.enableNginx {
|
||||
enable = true;
|
||||
|
||||
virtualHosts.${cfg.domain} = {
|
||||
locations = {
|
||||
"/api".proxyPass = "http://localhost:${builtins.toString cfg.port}";
|
||||
|
||||
"/management.ManagementService/".extraConfig = ''
|
||||
# This is necessary so that grpc connections do not get closed early
|
||||
# see https://stackoverflow.com/a/67805465
|
||||
client_body_timeout 1d;
|
||||
|
||||
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
grpc_pass grpc://localhost:${builtins.toString cfg.port};
|
||||
grpc_read_timeout 1d;
|
||||
grpc_send_timeout 1d;
|
||||
grpc_socket_keepalive on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,42 +0,0 @@
|
|||
# Netbird server {#module-services-netbird-server}
|
||||
|
||||
NetBird is a VPN built on top of WireGuard® making it easy to create secure private networks for your organization or home.
|
||||
|
||||
## Quickstart {#module-services-netbird-server-quickstart}
|
||||
|
||||
To fully setup Netbird as a self-hosted server, we need both a Coturn server and an identity provider, the list of supported SSOs and their setup are available [on Netbird's documentation](https://docs.netbird.io/selfhosted/selfhosted-guide#step-3-configure-identity-provider-idp).
|
||||
|
||||
There are quite a few settings that need to be passed to Netbird for it to function, and a minimal config looks like :
|
||||
|
||||
```nix
|
||||
services.netbird.server = {
|
||||
enable = true;
|
||||
|
||||
domain = "netbird.example.selfhosted";
|
||||
|
||||
enableNginx = true;
|
||||
|
||||
coturn = {
|
||||
enable = true;
|
||||
|
||||
passwordFile = "/path/to/a/secret/password";
|
||||
};
|
||||
|
||||
management = {
|
||||
oidcConfigEndpoint = "https://sso.example.selfhosted/oauth2/openid/netbird/.well-known/openid-configuration";
|
||||
|
||||
settings = {
|
||||
TURNConfig = {
|
||||
Turns = [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "turn:netbird.example.selfhosted:3478";
|
||||
Username = "netbird";
|
||||
Password._secret = "/path/to/a/secret/password";
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
```
|
|
@ -1,89 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
mkDefault
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkOption
|
||||
optionalAttrs
|
||||
;
|
||||
|
||||
inherit (lib.types) str;
|
||||
|
||||
cfg = config.services.netbird.server;
|
||||
in {
|
||||
meta = {
|
||||
maintainers = with lib.maintainers; [thubrecht patrickdag];
|
||||
doc = ./server.md;
|
||||
};
|
||||
|
||||
# Import the separate components
|
||||
imports = [
|
||||
./coturn.nix
|
||||
./dashboard.nix
|
||||
./management.nix
|
||||
./signal.nix
|
||||
];
|
||||
|
||||
options.services.netbird.server = {
|
||||
enable = mkEnableOption "Netbird Server stack, comprising the dashboard, management API and signal service";
|
||||
|
||||
enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird server services.";
|
||||
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
description = "The domain under which the netbird server runs.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.netbird.server = {
|
||||
dashboard = {
|
||||
domain = mkDefault cfg.domain;
|
||||
enable = mkDefault cfg.enable;
|
||||
enableNginx = mkDefault cfg.enableNginx;
|
||||
|
||||
managementServer = "https://${cfg.domain}";
|
||||
};
|
||||
|
||||
management =
|
||||
{
|
||||
domain = mkDefault cfg.domain;
|
||||
enable = mkDefault cfg.enable;
|
||||
enableNginx = mkDefault cfg.enableNginx;
|
||||
}
|
||||
// (optionalAttrs cfg.coturn.enable rec {
|
||||
turnDomain = cfg.domain;
|
||||
turnPort = config.services.coturn.tls-listening-port;
|
||||
# We cannot merge a list of attrsets so we have to redefine the whole list
|
||||
settings = {
|
||||
TURNConfig.Turns = mkDefault [
|
||||
{
|
||||
Proto = "udp";
|
||||
URI = "turn:${turnDomain}:${builtins.toString turnPort}";
|
||||
Username = "netbird";
|
||||
Password =
|
||||
if (cfg.coturn.password != null)
|
||||
then cfg.coturn.password
|
||||
else {_secret = cfg.coturn.passwordFile;};
|
||||
}
|
||||
];
|
||||
};
|
||||
});
|
||||
|
||||
signal = {
|
||||
domain = mkDefault cfg.domain;
|
||||
enable = mkDefault cfg.enable;
|
||||
enableNginx = mkDefault cfg.enableNginx;
|
||||
};
|
||||
|
||||
coturn = {
|
||||
domain = mkDefault cfg.domain;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,120 +0,0 @@
|
|||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
utils,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(lib)
|
||||
getExe'
|
||||
mkEnableOption
|
||||
mkIf
|
||||
mkPackageOption
|
||||
mkOption
|
||||
;
|
||||
|
||||
inherit (lib.types) enum port str;
|
||||
|
||||
inherit (utils) escapeSystemdExecArgs;
|
||||
|
||||
cfg = config.services.netbird.server.signal;
|
||||
in {
|
||||
options.services.netbird.server.signal = {
|
||||
enable = mkEnableOption "Netbird's Signal Service";
|
||||
|
||||
package = mkPackageOption pkgs "netbird" {};
|
||||
|
||||
enableNginx = mkEnableOption "Nginx reverse-proxy for the netbird signal service.";
|
||||
|
||||
domain = mkOption {
|
||||
type = str;
|
||||
description = "The domain name for the signal service.";
|
||||
};
|
||||
|
||||
port = mkOption {
|
||||
type = port;
|
||||
default = 8012;
|
||||
description = "Internal port of the signal server.";
|
||||
};
|
||||
|
||||
logLevel = mkOption {
|
||||
type = enum [
|
||||
"ERROR"
|
||||
"WARN"
|
||||
"INFO"
|
||||
"DEBUG"
|
||||
];
|
||||
default = "INFO";
|
||||
description = "Log level of the netbird signal service.";
|
||||
};
|
||||
};
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
systemd.services.netbird-signal = {
|
||||
after = ["network.target"];
|
||||
wantedBy = ["multi-user.target"];
|
||||
|
||||
serviceConfig = {
|
||||
ExecStart = escapeSystemdExecArgs [
|
||||
(getExe' cfg.package "netbird-signal")
|
||||
"run"
|
||||
# Port to listen on
|
||||
"--port"
|
||||
cfg.port
|
||||
# Log to stdout
|
||||
"--log-file"
|
||||
"console"
|
||||
# Log level
|
||||
"--log-level"
|
||||
cfg.logLevel
|
||||
];
|
||||
|
||||
Restart = "always";
|
||||
RuntimeDirectory = "netbird-mgmt";
|
||||
StateDirectory = "netbird-mgmt";
|
||||
WorkingDirectory = "/var/lib/netbird-mgmt";
|
||||
|
||||
# hardening
|
||||
LockPersonality = true;
|
||||
MemoryDenyWriteExecute = true;
|
||||
NoNewPrivileges = true;
|
||||
PrivateMounts = true;
|
||||
PrivateTmp = true;
|
||||
ProtectClock = true;
|
||||
ProtectControlGroups = true;
|
||||
ProtectHome = true;
|
||||
ProtectHostname = true;
|
||||
ProtectKernelLogs = true;
|
||||
ProtectKernelModules = true;
|
||||
ProtectKernelTunables = true;
|
||||
ProtectSystem = true;
|
||||
RemoveIPC = true;
|
||||
RestrictNamespaces = true;
|
||||
RestrictRealtime = true;
|
||||
RestrictSUIDSGID = true;
|
||||
};
|
||||
|
||||
stopIfChanged = false;
|
||||
};
|
||||
|
||||
services.nginx = mkIf cfg.enableNginx {
|
||||
enable = true;
|
||||
|
||||
virtualHosts.${cfg.domain} = {
|
||||
locations."/signalexchange.SignalExchange/".extraConfig = ''
|
||||
# This is necessary so that grpc connections do not get closed early
|
||||
# see https://stackoverflow.com/a/67805465
|
||||
client_body_timeout 1d;
|
||||
|
||||
grpc_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
|
||||
|
||||
grpc_pass grpc://localhost:${builtins.toString cfg.port};
|
||||
grpc_read_timeout 1d;
|
||||
grpc_send_timeout 1d;
|
||||
grpc_socket_keepalive on;
|
||||
'';
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
{self, ...}: nodeName: nodeAttrs: let
|
||||
inherit (self.hosts.${nodeName}) system;
|
||||
#FIXME inherit nodeAttrs. system;
|
||||
system = "x86_64-linux";
|
||||
pkgs = self.pkgs.${system};
|
||||
|
||||
disko-script = pkgs.writeShellScriptBin "disko-script" "${nodeAttrs.config.system.build.diskoScript}";
|
||||
|
|
|
@ -5,15 +5,15 @@ inputs: let
|
|||
concatMapAttrs
|
||||
filterAttrs
|
||||
flip
|
||||
mapAttrs
|
||||
genAttrs
|
||||
mapAttrs'
|
||||
nameValuePair
|
||||
nixosSystem
|
||||
;
|
||||
|
||||
# Creates a new nixosSystem with the correct specialArgs, pkgs and name definition
|
||||
mkHost = {minimal}: name: hostCfg: let
|
||||
pkgs = self.pkgs.${hostCfg.system};
|
||||
mkHost = {minimal}: name: let
|
||||
pkgs = self.pkgs.x86_64-linux;
|
||||
in
|
||||
nixosSystem {
|
||||
specialArgs = {
|
||||
|
@ -28,7 +28,6 @@ inputs: let
|
|||
# inputs.nixpkgs.nixosModules.readOnlyPkgs, since some nixosModules
|
||||
# like nixseparatedebuginfod depend on adding packages via nixpkgs.overlays.
|
||||
# So we just mimic the options and overlays defined by the passed pkgs set.
|
||||
nixpkgs.hostPlatform = hostCfg.system;
|
||||
nixpkgs.overlays = pkgs.overlays;
|
||||
nixpkgs.config = pkgs.config;
|
||||
node.name = name;
|
||||
|
@ -41,12 +40,10 @@ inputs: let
|
|||
# Load the list of hosts that this flake defines, which
|
||||
# associates the minimum amount of metadata that is necessary
|
||||
# to instanciate hosts correctly.
|
||||
hosts = builtins.fromTOML (builtins.readFile ../hosts.toml);
|
||||
# Get all hosts of type "nixos"
|
||||
nixosHosts = filterAttrs (_: x: x.type == "nixos") hosts;
|
||||
hosts = builtins.attrNames (filterAttrs (_: type: type == "directory") (builtins.readDir ../hosts));
|
||||
# Process each nixosHosts declaration and generatea nixosSystem definitions
|
||||
nixosConfigurations = flip mapAttrs nixosHosts (mkHost {minimal = false;});
|
||||
minimalConfigurations = flip mapAttrs nixosHosts (mkHost {minimal = true;});
|
||||
nixosConfigurations = genAttrs hosts (mkHost {minimal = false;});
|
||||
minimalConfigurations = genAttrs hosts (mkHost {minimal = true;});
|
||||
|
||||
# True NixOS nodes can define additional guest nodes that are built
|
||||
# together with it. We collect all defined guests from each node here
|
||||
|
|
|
@ -30,8 +30,8 @@
|
|||
patches =
|
||||
old.patches
|
||||
++ [
|
||||
"${provisionSrc}/patches/${old.version}-oauth2-basic-secret-modify.patch"
|
||||
"${provisionSrc}/patches/${old.version}-recover-account.patch"
|
||||
"${provisionSrc}/patches/1.2.0-oauth2-basic-secret-modify.patch"
|
||||
"${provisionSrc}/patches/1.2.0-recover-account.patch"
|
||||
];
|
||||
passthru.enableSecretProvisioning = true;
|
||||
doCheck = false;
|
||||
|
|
|
@ -129,6 +129,10 @@ in
|
|||
|
||||
meta = with lib; {
|
||||
mainProgram = "api";
|
||||
homepage = "https://hay-kot.github.io/homebox/";
|
||||
maintainers = with maintainers; [patrickdag];
|
||||
license = licenses.agpl3Only;
|
||||
description = "A inventory and organization system built for the Home User";
|
||||
platforms = platforms.all;
|
||||
};
|
||||
}
|
||||
|
|
16
secrets/wireguard/elisabeth/keys/elisabeth-ollama.age
Normal file
16
secrets/wireguard/elisabeth/keys/elisabeth-ollama.age
Normal file
|
@ -0,0 +1,16 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 Fpotjtu7lksK7LzYZTkTP7OXF2etf6k/jAs3qT63pyg
|
||||
Az3CTRHiYmqI9mVSvt61WgbQa1Sw7tTI/GwuwGNm2Rk
|
||||
-> piv-p256 ZFgiIw AwwKW8KYhA3dsUgANUxvffEiFLOadwllahNrchfzQTfq
|
||||
AO08XTSUINWT5eY1EgPqHHSY/y0gsgszz3psNnGSauA
|
||||
-> piv-p256 XTQkUA AuxujxLf1wM1siHqnkbayQ6C4KZbsAzdUO/8dsiTRohe
|
||||
1AUfKkOngKRI4jPG820VihSIP5ms9jH8MvHlEBiwVAE
|
||||
-> piv-p256 ZFgiIw AqLEvSEzM5D4K/W67DVz7icte3mw5+FqFtBiv4Ba2xua
|
||||
mbrEOcAnkiXq1Phh1SlnTjDuhLma+4hqv8FMceymOzQ
|
||||
-> piv-p256 5vmPtQ AzENFlgqOyGbU/FXskgenHamZs/H+78mS9PWsYoXXqae
|
||||
pyx2IlIw+p+7dAUg5Ohj1cKxW/9S51LjR2A47aNgH0c
|
||||
-> AJ/nN^^b-grease P%To4qn; llf1 (\|f~06
|
||||
ROV54+I9IMrCY2DvOXDRsY4otebllTMp6ddWYA
|
||||
--- PGvDf7ZhjEQzcNDXVlDw4Qehrs/lg7hi22vu/2lo0N8
|
||||
{±ˆ¤›rëyÔ<79>_½±³{<7B>f#ßç`M}Ñ”<iö÷<C3B6>d=ÇÔp¾bÍnÿÂåEËé<C38B>-
|
||||
¹$thòˆû:;.9ñw¬
|
1
secrets/wireguard/elisabeth/keys/elisabeth-ollama.pub
Normal file
1
secrets/wireguard/elisabeth/keys/elisabeth-ollama.pub
Normal file
|
@ -0,0 +1 @@
|
|||
wODUgMHl+qSCB8O1purynIY/AaPyIJ4kCFCEHmRedEk=
|
|
@ -0,0 +1,15 @@
|
|||
age-encryption.org/v1
|
||||
-> X25519 809OJmSe9sRVNlpr7tsymq+N/N3RLwBggFHdew4p5lU
|
||||
ef/ZzFm1aqytRapx0iZilQyT9O/xuA97plZbz5LL5O4
|
||||
-> piv-p256 ZFgiIw Aowpy6rEm9eHFxEmwJ35I10linQONgIS13H/Nm0fi+j9
|
||||
rRiW2Y2V5kpmdqGjN72EyKe9nf5fQS4UrUqZAtshkx8
|
||||
-> piv-p256 XTQkUA AtkeDTc+jaagxDYjzJrSsHZTCF3KxpSTMU2ZMxuoawDG
|
||||
YDRFtbrl8QH5YHlTcBLBdxHzx+pqMXLtSSvd/FokSE4
|
||||
-> piv-p256 ZFgiIw ArgQyaNwkuKD1GVVGKmwcHq11pzcgGK9uJpvWFkQ1Zqy
|
||||
Jvue35/d/2CKV6qcVZIW2Q+LUp67CpcMUapfJQGqh84
|
||||
-> piv-p256 5vmPtQ AjMLgWeCMKLwl3205anSTdwYfQ5HG2pmZH5UOU8fnhi5
|
||||
BL+6ZYMBuakv2PZCzcb/W8+UCgGryY/uA3Z0NdMxcc8
|
||||
-> :`n-grease Iq:z[/t( c6Ca. j FSx5@D?
|
||||
uH1pwc6u0ytrAqS9cTXoD64rJBuosYo
|
||||
--- 5BCa7IK4dbXfsXiqMnBHBmLR/qAXbbyqaVRiWun5KJ4
|
||||
eõFsfáB„µ¿ìh·`%ªÔŠñÄþ–8ÀCˆ;Q²™ên·À<C2B7>ÙŽÐz<C390>ÉÊ$<24>ß…©Ì»<C38C>¢‹¶ÉR$Ð5œÚsKl¾TÂ
|
Loading…
Reference in a new issue