feat: modify all servarr and qbittorrent services to use postgresql

This commit is contained in:
Ceferino Patino 2026-06-24 22:54:03 -05:00
commit 0d902afdc3
Signed by: c4patino
SSH key fingerprint: SHA256:Wu+cU1t+7zVT9wzew/4meNmeulo66NzMqc22MdDBgXI
10 changed files with 275 additions and 70 deletions

View file

@ -69,7 +69,7 @@ in {
impermanence = enabled;
postgresql = {
databases = {
shiori = ["autobrr" "bazarr" "lidarr" "lidarr-log" "prowlarr" "prowlarr-log" "radarr" "radarr-log" "seerr" "sonarr" "sonarr-log"];
shiori = ["autobrr" "bazarr" "lidarr" "lidarr-log" "prowlarr" "prowlarr-log" "qui" "radarr" "radarr-log" "seerr" "sonarr" "sonarr-log"];
tsuki = ["forgejo" "grafana" "terraform" "vaultwarden"];
};
};

View file

@ -7,10 +7,11 @@
...
}: let
inherit (lib) mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost hostHasService resolveServicePort resolveDatabaseIP readJsonOrEmpty getIn;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
uid = 980;
gid = 975;
@ -18,6 +19,7 @@
isEnabled = hostHasService networkCfg.network-services hostName "qbittorrent";
port = resolveServicePort networkCfg.network-services "qbittorrent" 9000;
torrentingPort = 23345;
dbHost = resolveDatabaseHost pgCfg.databases "qui";
in {
config = mkIf isEnabled {
containers.qbittorrent = {
@ -178,9 +180,25 @@ in {
settings = {
host = "0.0.0.0";
port = port;
databaseEngine = "postgres";
databaseHost = resolveDatabaseIP networkCfg.devices pgCfg.databases "qui";
databasePort = 5600;
databaseName = "qui";
databaseUser = "qui";
databasePassword =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.qui.password";
};
};
systemd.services.qui = mkIf (dbHost == hostName) {
after = ["postgresql.service"];
requires = ["postgresql.service"];
serviceConfig.RestartSec = "1s";
};
sops.secrets = {
"openvpn" = {};
"qui" = {};
@ -200,6 +218,7 @@ in {
${namespace}.services.storage.impermanence.folders = let
qbittorrentUser = config.users.users.qbittorrent;
quiUser = config.users.users.qui;
in [
{
directory = "/var/lib/qBittorrent";
@ -207,6 +226,12 @@ in {
group = qbittorrentUser.group;
mode = "700";
}
{
directory = "/var/lib/qui";
user = quiUser.name;
group = quiUser.group;
mode = "700";
}
];
networking = {

View file

@ -1,18 +1,21 @@
{
config,
inputs,
lib,
namespace,
pkgs,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "autobrr";
port = resolveServicePort networkCfg.network-services "autobrr" 7474;
dbHost = resolveDatabaseHost pgCfg.databases "autobrr";
in {
config = mkIf isEnabled {
services.autobrr = {
@ -22,6 +25,17 @@ in {
settings = {
host = "0.0.0.0";
port = port;
databaseType = "postgres";
postgresHost = resolveDatabaseIP networkCfg.devices pgCfg.databases "autobrr";
postgresPort = 5600;
postgresDatabase = "autobrr";
postgresUser = "autobrr";
postgresPass =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.autobrr.password";
postgresSSLMode = "disable";
};
};
@ -62,15 +76,23 @@ in {
[ "$remaining_space" -gt "$required_space" ]
'';
in {
path = [checkAutobrrSpace];
serviceConfig = {
DynamicUser = mkForce false;
User = autobrrUser.name;
Group = autobrrUser.group;
UMask = mkForce "0002";
};
};
in
mkMerge [
{
path = [checkAutobrrSpace];
serviceConfig = {
DynamicUser = mkForce false;
User = autobrrUser.name;
Group = autobrrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
};
sops.secrets = {

View file

@ -1,17 +1,20 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "bazarr";
port = resolveServicePort networkCfg.network-services "bazarr" 6767;
dbHost = resolveDatabaseHost pgCfg.databases "bazarr";
in {
config = mkIf isEnabled {
services.bazarr = {
@ -19,14 +22,38 @@ in {
listenPort = port;
};
systemd.services.bazarr.serviceConfig = let
systemd.services.bazarr = let
bazarrUser = config.users.users.bazarr;
in {
DynamicUser = mkForce false;
User = bazarrUser.name;
Group = bazarrUser.group;
UMask = mkForce "0002";
};
dbIp = resolveDatabaseIP networkCfg.devices pgCfg.databases "bazarr";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.bazarr.password";
in
mkMerge [
{
environment = {
POSTGRES_ENABLED = "true";
POSTGRES_HOST = "${dbIp}";
POSTGRES_PORT = "5600";
POSTGRES_DATABASE = "bazarr";
POSTGRES_USERNAME = "bazarr";
POSTGRES_PASSWORD = password;
};
serviceConfig = {
DynamicUser = mkForce false;
User = bazarrUser.name;
Group = bazarrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.bazarr = {

View file

@ -1,32 +1,58 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "lidarr";
port = resolveServicePort networkCfg.network-services "lidarr" 8686;
dbHost = resolveDatabaseHost pgCfg.databases "lidarr";
in {
config = mkIf isEnabled {
services.lidarr = {
enable = true;
settings.server.port = port;
settings = {
server.port = port;
postgres = {
host = resolveDatabaseIP networkCfg.devices pgCfg.databases "lidarr";
port = 5600;
user = "lidarr";
maindb = "lidarr";
logdb = "lidarr-log";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.lidarr.password";
};
};
};
systemd.services.lidarr.serviceConfig = let
systemd.services.lidarr = let
lidarrUser = config.users.users.lidarr;
in {
DynamicUser = mkForce false;
User = lidarrUser.name;
Group = lidarrUser.group;
UMask = mkForce "0002";
};
in
mkMerge [
{
serviceConfig = {
DynamicUser = mkForce false;
User = lidarrUser.name;
Group = lidarrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.lidarr = {

View file

@ -1,32 +1,58 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "prowlarr";
port = resolveServicePort networkCfg.network-services "prowlarr" 9696;
dbHost = resolveDatabaseHost pgCfg.databases "prowlarr";
in {
config = mkIf isEnabled {
services.prowlarr = {
enable = true;
settings.server.port = port;
settings = {
server.port = port;
postgres = {
host = resolveDatabaseIP networkCfg.devices pgCfg.databases "prowlarr";
port = 5600;
user = "prowlarr";
maindb = "prowlarr";
logdb = "prowlarr-log";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.prowlarr.password";
};
};
};
systemd.services.prowlarr.serviceConfig = let
systemd.services.prowlarr = let
prowlarrUser = config.users.users.prowlarr;
in {
DynamicUser = mkForce false;
User = prowlarrUser.name;
Group = prowlarrUser.group;
UMask = mkForce "0002";
};
in
mkMerge [
{
serviceConfig = {
DynamicUser = mkForce false;
User = prowlarrUser.name;
Group = prowlarrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.prowlarr = {

View file

@ -1,32 +1,58 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "radarr";
port = resolveServicePort networkCfg.network-services "radarr" 7878;
dbHost = resolveDatabaseHost pgCfg.databases "radarr";
in {
config = mkIf isEnabled {
services.radarr = {
enable = true;
settings.server.port = port;
settings = {
server.port = port;
postgres = {
host = resolveDatabaseIP networkCfg.devices pgCfg.databases "radarr";
port = 5600;
user = "radarr";
maindb = "radarr";
logdb = "radarr-log";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.radarr.password";
};
};
};
systemd.services.radarr.serviceConfig = let
systemd.services.radarr = let
radarrUser = config.users.users.radarr;
in {
DynamicUser = mkForce false;
User = radarrUser.name;
Group = radarrUser.group;
UMask = mkForce "0002";
};
in
mkMerge [
{
serviceConfig = {
DynamicUser = mkForce false;
User = radarrUser.name;
Group = radarrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.radarr = {

View file

@ -1,17 +1,20 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "seerr";
port = resolveServicePort networkCfg.network-services "seerr" 5055;
dbHost = resolveDatabaseHost pgCfg.databases "seerr";
in {
config = mkIf isEnabled {
services.seerr = {
@ -20,13 +23,37 @@ in {
openFirewall = true;
};
systemd.services.seerr.serviceConfig = let
systemd.services.seerr = let
seerrUser = config.users.users.seerr;
in {
DynamicUser = mkForce false;
User = seerrUser.name;
Group = seerrUser.group;
};
dbIp = resolveDatabaseIP networkCfg.devices pgCfg.databases "seerr";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.seerr.password";
in
mkMerge [
{
environment = {
DB_TYPE = "postgres";
DB_HOST = dbIp;
DB_PORT = "5600";
DB_USER = "seerr";
DB_PASS = password;
DB_NAME = "seerr";
};
serviceConfig = {
DynamicUser = mkForce false;
User = seerrUser.name;
Group = seerrUser.group;
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.seerr = {

View file

@ -1,32 +1,58 @@
{
config,
inputs,
lib,
namespace,
...
}: let
inherit (lib) mkForce mkIf;
inherit (lib.${namespace}) getAttrByNamespace hostHasService resolveServicePort;
inherit (lib) mkForce mkIf mkMerge;
inherit (lib.${namespace}) getAttrByNamespace resolveDatabaseHost resolveDatabaseIP readJsonOrEmpty getIn hostHasService resolveServicePort;
inherit (config.networking) hostName;
networkCfg = getAttrByNamespace config "${namespace}.services.networking";
pgCfg = getAttrByNamespace config "${namespace}.services.storage.postgresql";
isEnabled = hostHasService networkCfg.network-services hostName "sonarr";
port = resolveServicePort networkCfg.network-services "sonarr" 8989;
dbHost = resolveDatabaseHost pgCfg.databases "sonarr";
in {
config = mkIf isEnabled {
services.sonarr = {
enable = true;
settings.server.port = port;
settings = {
server.port = port;
postgres = {
host = resolveDatabaseIP networkCfg.devices pgCfg.databases "sonarr";
port = 5600;
user = "sonarr";
maindb = "sonarr";
logdb = "sonarr-log";
password =
"${inputs.self}/secrets/crypt/secrets.json"
|> readJsonOrEmpty
|> getIn "postgresql.sonarr.password";
};
};
};
systemd.services.sonarr.serviceConfig = let
systemd.services.sonarr = let
sonarrUser = config.users.users.sonarr;
in {
DynamicUser = mkForce false;
User = sonarrUser.name;
Group = sonarrUser.group;
UMask = mkForce "0002";
};
in
mkMerge [
{
serviceConfig = {
DynamicUser = mkForce false;
User = sonarrUser.name;
Group = sonarrUser.group;
UMask = mkForce "0002";
};
}
(mkIf (dbHost == hostName) {
after = ["postgresql.service" "pgbouncer.service"];
requires = ["postgresql.service" "pgbouncer.service"];
serviceConfig.RestartSec = "1s";
})
];
users = {
users.sonarr = {

Binary file not shown.