Add selfhosted services

This commit is contained in:
aloslider
2026-06-30 04:26:40 +03:00
parent f212c874b5
commit 13e407847f
78 changed files with 2346 additions and 690 deletions
@@ -0,0 +1,288 @@
{
config,
lib,
pkgs,
...
}:
with lib;
let
common = config.selfhosted.common;
cfg = config.selfhosted;
in
{
imports = [
./gitea
./homarr
./immich
./jellyfin
./netbird
./pocket-id
./seafile
./traefik
./vaultwarden
./zapret2
./zerobyte
];
options.selfhosted.common = {
backend = mkOption {
type = types.str;
};
rootTarget = {
name = mkOption {
type = types.str;
};
};
network = {
name = mkOption {
type = types.str;
};
address = mkOption {
type = types.str;
};
mask = mkOption {
type = types.str;
};
gateway = mkOption {
type = types.str;
};
};
dataDir = mkOption {
type = types.str;
};
user = {
name = mkOption {
type = types.str;
};
uid = mkOption {
type = types.str;
};
};
group = {
name = mkOption {
type = types.str;
};
gid = mkOption {
type = types.str;
};
};
};
config = {
selfhosted = {
common = {
backend = "docker";
rootTarget.name = "sh-root";
network = {
name = "selfhosted";
address = "172.30.0.0";
mask = "24";
gateway = "172.30.0.1";
};
dataDir = "/mnt/data";
user = {
name = config.users.users.benq.name;
uid = "1000";
};
group = {
name = "users";
gid = "1000";
};
};
jellyfin = {
name = "jellyfin";
subdomain = "media";
hostHttpPort = 5040;
hostUdpPort = 5041;
};
gitea = {
targetName = "gitea";
gitea = {
name = "gitea";
subdomain = "gitea";
hostWebPort = 5060;
hostSshPort = 5061;
};
postgresql = {
name = "gitea-db";
};
};
immich = {
targetName = "immich";
version = "v2";
immich = {
name = "immich";
subdomain = "photos";
hostPort = 5090;
};
ml = {
name = "immich-ml";
};
redis = {
name = "immich-cache";
};
postgresql = {
name = "immich-db";
db = "immich";
user = "immich";
};
};
netbird = {
targetName = "netbird";
subdomain = "nb";
dashboard = {
name = "nb-dashboard";
};
proxy = {
name = "nb-proxy";
};
server = {
name = "nb-server";
};
};
homarr = {
name = "homarr";
subdomain = "dash";
hostPort = 5030;
};
pocket-id = {
name = "pocket-id";
subdomain = "id";
hostPort = 5020;
};
seafile = {
targetName = "seafile";
server = {
name = "sf-server";
subdomain = "cloud";
hostHttpPort = 5050;
};
mariadb = {
name = "sf-db";
};
redis = {
name = "sf-cache";
};
seadoc = {
name = "sf-seadoc";
hostHttpPort = 5051;
};
notification = {
name = "sf-notification";
hostHttpPort = 5052;
};
};
traefik = {
name = "traefik";
ip = "172.30.0.10";
};
vaultwarden = {
name = "vaultwarden";
subdomain = "vault";
hostPort = 5010;
};
zapret2 = {
name = "zapret2";
socksPort = 6000;
ssPort = 6001;
};
zerobyte = {
name = "zerobyte";
subdomain = "backup";
hostPort = 5070;
};
};
virtualisation = lib.mkMerge [
{ oci-containers.backend = config.selfhosted.common.backend; }
(
if config.selfhosted.common.backend == "docker" then
{
docker = {
enable = true;
};
}
else if config.selfhosted.common.backend == "podman" then
{
podman = {
enable = true;
dockerCompat = true;
};
}
else
abort "virtualisation.backend is not set"
)
];
services.netbird.clients = {
homelab = {
port = 51820;
openFirewall = true;
openInternalFirewall = true;
login = {
enable = true;
setupKeyFile = config.sops.secrets."netbird/setup_keys/homelab".path;
};
};
};
sops.secrets = {
"netbird/setup_keys/homelab" = { };
"netbird/setup_keys/site" = { };
};
sops.templates."netbird-homelab.env".content = ''
NB_MANAGEMENT_URL=https://${cfg.netbird.subdomain}.${config.sops.placeholder."domains/serv"}
'';
# Override to pass env file
systemd.services = {
"netbird-homelab" = {
serviceConfig = {
EnvironmentFile = [ config.sops.templates."netbird-homelab.env".path ];
};
after = [ "sops-nix.service" ];
wants = [ "sops-nix.service" ];
};
"netbird-homelab-login" = {
after = [ "sops-nix.service" ];
wants = [ "sops-nix.service" ];
};
};
systemd.targets."${common.backend}-${common.rootTarget.name}" = {
unitConfig = {
Description = "Root target for homelab stack";
};
wantedBy = [ "multi-user.target" ];
};
systemd.services."${common.backend}-network-${common.network.name}" = {
path = [ pkgs.${common.backend} ];
serviceConfig = {
Type = "oneshot";
RemainAfterExit = true;
ExecStop = "${common.backend} network rm -f ${common.network.name}";
};
script = ''
${common.backend} network inspect ${common.network.name} \
|| ${common.backend} network create ${common.network.name} --driver=bridge --subnet=${common.network.address}/${common.network.mask} --gateway=${common.network.gateway}
'';
partOf = [ "${common.backend}-${common.rootTarget.name}.target" ];
wantedBy = [ "${common.backend}-${common.rootTarget.name}.target" ];
};
networking.firewall.interfaces = lib.mkMerge [
(lib.mkIf (config.selfhosted.common.backend == "podman") (
let
matchAll = if !config.networking.nftables.enable then "podman+" else "podman*";
in
{
"${matchAll}" = {
allowedUDPPorts = [ 53 ];
};
}
))
];
};
}