Merge branch 'dev' into feat/solidtime

This commit is contained in:
Tibo De Peuter 2026-02-10 08:08:49 +01:00
commit 2a392b0581
Signed by: tdpeuter
GPG key ID: 38297DE43F75FFE2
21 changed files with 312 additions and 259 deletions

View file

@ -12,7 +12,16 @@ let
PGID = toString config.users.groups.media.gid;
UMASK = "002";
in {
options.homelab.apps.arr = {
options.homelab.apps.arr = let
mkAppOption = appName: {
enable = lib.mkEnableOption "${appName} using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose ${appName} port";
default = cfg.exposePorts;
};
};
in {
enable = lib.mkEnableOption "Arr Stack using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
@ -21,46 +30,11 @@ in {
default = ! config.homelab.apps.traefik.enable;
};
bazarr = {
enable = lib.mkEnableOption "Bazarr using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose Bazarr port";
default = cfg.exposePorts;
};
};
prowlarr = {
enable = lib.mkEnableOption "Prowlarr using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose Prowlarr port";
default = cfg.exposePorts;
};
};
qbittorrent = {
enable = lib.mkEnableOption "qBittorrent using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose qBittorrent port";
default = cfg.exposePorts;
};
};
radarr = {
enable = lib.mkEnableOption "Radarr using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose Radarr port";
default = cfg.exposePorts;
};
};
sonarr = {
enable = lib.mkEnableOption "Sonarr using Docker";
exposePorts = lib.mkOption {
type = lib.types.bool;
description = "Expose Sonarr port";
default = cfg.exposePorts;
};
};
bazarr = mkAppOption "Bazarr";
prowlarr = mkAppOption "Prowlarr";
qbittorrent = mkAppOption "qBittorrent";
radarr = mkAppOption "Radarr";
sonarr = mkAppOption "Sonarr";
};
config = {
@ -87,9 +61,9 @@ in {
virtualisation.containers.enable = lib.mkIf inUse true;
};
fileSystems = lib.mkIf inUse {
"/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable {
device = "192.168.0.11:/mnt/BIG/BACKUP/BAZARR";
fileSystems = let
mkFileSystem = device: {
inherit device;
fsType = "nfs";
options = [
"rw"
@ -102,75 +76,14 @@ in {
];
};
"/srv/prowlarr-backup" = lib.mkIf cfg.prowlarr.enable {
device = "192.168.0.11:/mnt/BIG/BACKUP/PROWLARR";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"rsize=1048576" "wsize=1048576"
"hard"
"timeo=600" "retrans=2"
"_netdev" "nosuid" "tcp"
];
};
"/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable {
device = "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"rsize=1048576" "wsize=1048576"
"hard"
"timeo=600" "retrans=2"
"_netdev" "nosuid" "tcp"
];
};
"/srv/radarr-backup" = lib.mkIf cfg.radarr.enable {
device = "192.168.0.11:/mnt/BIG/BACKUP/RADARR";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"rsize=1048576" "wsize=1048576"
"hard"
"timeo=600" "retrans=2"
"_netdev" "nosuid" "tcp"
];
};
"/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable {
device = "192.168.0.11:/mnt/BIG/BACKUP/SONARR";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"rsize=1048576" "wsize=1048576"
"hard"
"timeo=600" "retrans=2"
"_netdev" "nosuid" "tcp"
];
};
"/srv/torrent" = {
device = "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"rsize=1048576" "wsize=1048576"
"hard"
"timeo=600" "retrans=2"
"_netdev" "nosuid" "tcp"
];
};
hugoBackup = "192.168.0.11:/mnt/BIG/BACKUP";
in lib.mkIf inUse {
"/srv/bazarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/BAZARR");
"/srv/prowlarr-backup" = lib.mkIf cfg.bazarr.enable (mkFileSystem "${hugoBackup}/PROWLARR");
"/srv/qbittorrent" = lib.mkIf cfg.qbittorrent.enable (mkFileSystem "192.168.0.11:/mnt/SMALL/CONFIG/QBITTORRENT");
"/srv/radarr-backup" = lib.mkIf cfg.radarr.enable (mkFileSystem "${hugoBackup}/RADARR");
"/srv/sonarr-backup" = lib.mkIf cfg.sonarr.enable (mkFileSystem "${hugoBackup}/SONARR");
"/srv/torrent" = mkFileSystem "192.168.0.11:/mnt/SMALL/MEDIA/TORRENT";
};
# Make sure the Docker network exists.
@ -195,45 +108,24 @@ in {
};
# Create a user for each app.
users.users = {
bazarr = lib.mkIf cfg.bazarr.enable {
uid = lib.mkForce 3003;
users.users = let
mkUser = uid: {
uid = lib.mkForce uid;
isSystemUser = true;
group = config.users.groups.media.name;
home = "/var/empty";
shell = null;
};
prowlarr = lib.mkIf cfg.prowlarr.enable {
uid = lib.mkForce 3004;
isSystemUser = true;
group = config.users.groups.media.name;
home = "/var/empty";
shell = null;
};
qbittorrent = lib.mkIf cfg.qbittorrent.enable {
uid = lib.mkForce 3005;
isSystemUser = true;
group = config.users.groups.media.name;
in {
bazarr = lib.mkIf cfg.bazarr.enable (mkUser 3003);
prowlarr = lib.mkIf cfg.prowlarr.enable (mkUser 3004);
qbittorrent = lib.mkIf cfg.qbittorrent.enable (mkUser 3005) // {
extraGroups = [
config.users.groups.apps.name
];
home = "/var/empty";
shell = null;
};
radarr = lib.mkIf cfg.radarr.enable {
uid = lib.mkForce 3006;
isSystemUser = true;
group = config.users.groups.media.name;
home = "/var/empty";
shell = null;
};
sonarr = lib.mkIf cfg.sonarr.enable {
uid = lib.mkForce 3007;
isSystemUser = true;
group = config.users.groups.media.name;
home = "/var/empty";
shell = null;
};
radarr = lib.mkIf cfg.radarr.enable (mkUser 3006);
sonarr = lib.mkIf cfg.sonarr.enable (mkUser 3007);
};
virtualisation.oci-containers.containers = let

View file

@ -6,6 +6,7 @@
./changedetection
./freshrss
./gitea
./homepage
./jellyfin
./plex
./speedtest

View file

@ -27,7 +27,7 @@ in {
"rw"
"auto"
"nfsvers=4.2"
"sync" "hard" "timeo=600"
"async" "soft" "timeo=600"
"retrans=2"
"_netdev"
"nosuid"
@ -53,24 +53,41 @@ in {
virtualisation.oci-containers.containers.freshrss = {
hostname = "freshrss";
image = "freshrss/freshrss:1.24.0";
image = "freshrss/freshrss:1.25.0";
autoStart = true;
user = "0:33";
ports = [
"${toString port}:${toString port}/tcp"
"${toString port}:80/tcp"
];
extraOptions = [
"--network=${networkName}"
];
environment = {
TZ = config.time.timeZone;
CRON_TIME = "3,18,33,48"; # Alternatively, configure cron inside container.
LISTEN = "0.0.0.0:${toString port}";
CRON_MIN = "3,18,33,48"; # Alternatively, configure cron inside container.
SERVER_DNS = "rss.depeuter.dev";
TRUSTED_PROXY = "172.16.0.1/12 192.168.0.1/16";
};
volumes = [
"/srv/freshrss/www/freshrss/data:/var/www/FreshRSS/data"
"/srv/freshrss/www/freshrss/extensions:/var/www/FreshRSS/extensions"
];
labels = {
"traefik.enable" = "true";
"traefik.http.middlewares.freshrssM1.compress" = "true";
"traefik.http.middlewares.freshrssM2.headers.browserXssFilter" = "true";
"traefik.http.middlewares.freshrssM2.headers.forceSTSHeader" = "true";
"traefik.http.middlewares.freshrssM2.headers.frameDeny" = "true";
"traefik.http.middlewares.freshrssM2.headers.referrerPolicy" = "no-referrer-when-downgrade";
"traefik.http.middlewares.freshrssM2.headers.stsSeconds" = "31536000";
"traefik.http.routers.freshrss.entryPoints" = "websecure";
"traefik.http.routers.freshrss.tls" = "true";
"traefik.http.services.freshrss.loadbalancer.server.port" = "80";
"traefik.http.routers.freshrss.middlewares" = "freshrssM1,freshrssM2";
"traefik.http.routers.freshrss.rule" = "Host(`rss.depeuter.dev`)";
};
};
};
}

View file

@ -124,7 +124,7 @@ in {
gitea = {
hostname = "gitea";
image = "codeberg.org/forgejo/forgejo:8.0.3-rootless";
image = "codeberg.org/forgejo/forgejo:11.0.1-rootless";
autoStart = true;
user = "${toString UID}:${toString GID}";
ports = [
@ -576,7 +576,7 @@ in {
#FORGEJO__picture__AVATAR_RENDERED_SIZE_FACTOR = "2";
# Maximum allowed file size for uploaded avatars.
# This is to limit the amount of RAM used when resizing the image.
#FORGEJO__picture__AVATAR_MAX_FILE_SIZE = "1048576";
FORGEJO__picture__AVATAR_MAX_FILE_SIZE = "1048576";
# If the uploaded file is not larger than this byte size, the image will be used as is, without resizing/converting.
#FORGEJO__picture__AVATAR_MAX_ORIGIN_SIZE = "262144";
# Chinese users can choose "duoshuo"

View file

@ -0,0 +1,79 @@
{ config, lib, ... }:
let
cfg = config.homelab.apps.homepage;
PUID = toString config.users.users.homepage.uid;
PGID = toString config.users.groups.apps.gid;
homepage-config = "/srv/homepage-config";
proxyNet = config.homelab.apps.traefik.sharedNetworkName;
in {
options.homelab.apps.homepage = {
enable = lib.mkEnableOption "homepage";
port = lib.mkOption {
type = lib.types.int;
default = 3000;
description = "homepage WebUI port";
};
exposePort = lib.mkEnableOption "expose homepage port";
};
config = lib.mkIf cfg.enable {
homelab = {
users.apps.enable = true;
virtualisation.containers.enable = true;
};
users.users.homepage = {
uid = lib.mkForce 3018;
isSystemUser = true;
group = config.users.groups.apps.name;
home = "/var/empty";
shell = null;
};
fileSystems."${homepage-config}" = {
device = "192.168.0.11:/mnt/SMALL/CONFIG/HOMEPAGE";
fsType = "nfs";
options = [
"rw"
"auto"
"nfsvers=4.2"
"async" "soft" "timeo=100" "retry=50" "actimeo=1800" "lookupcache=all"
"nosuid" "tcp"
];
};
virtualisation.oci-containers.containers.homepage = let
host = "homepage.${config.networking.domain}";
in {
hostname = "homepage";
image = "ghcr.io/gethomepage/homepage:v1.10.1";
autoStart = true;
user = "${toString PUID}:${toString PGID}";
ports = lib.mkIf cfg.exposePort [
"${toString cfg.port}:3000/tcp"
];
networks = [
proxyNet
];
volumes = [
"${homepage-config}:/app/config"
# "/var/run/docker.sock:/var/run/docker.sock:ro" # For docker integrations
];
labels = {
"traefik.enable" = "true";
"traefik.docker.network" = proxyNet;
"traefik.http.routers.homepage.rule" = "Host(`${host}`)";
"traefik.http.services.homepage.loadbalancer.server.port" = toString cfg.port;
};
environment = {
inherit PUID PGID;
HOMEPAGE_ALLOWED_HOSTS = "${host},192.168.0.91:3000";
};
};
};
}

View file

@ -1,6 +1,7 @@
{
imports = [
./apps
./fileSystems
./services
./virtualisation