refactor: split configurations for fail2ban, postgres, and qbittorent into folders
This commit is contained in:
parent
ad04be6534
commit
0f5507c328
13 changed files with 296 additions and 263 deletions
|
|
@ -1,8 +1,8 @@
|
||||||
{...}: {
|
{...}: {
|
||||||
imports = [
|
imports = [
|
||||||
./reverseProxy
|
./reverseProxy
|
||||||
./fail2ban.nix
|
./fail2ban
|
||||||
./postgres.nix
|
./postgres
|
||||||
./network_storage
|
./network_storage
|
||||||
|
|
||||||
./actual
|
./actual
|
||||||
|
|
@ -17,7 +17,7 @@
|
||||||
./lidarr
|
./lidarr
|
||||||
./panoramax
|
./panoramax
|
||||||
./paperless
|
./paperless
|
||||||
./qbittorent.nix
|
./qbittorent
|
||||||
./radarr
|
./radarr
|
||||||
./searx
|
./searx
|
||||||
./sonarr
|
./sonarr
|
||||||
|
|
|
||||||
|
|
@ -1,74 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
dataFolder = "/var/lib/fail2ban";
|
|
||||||
dataFile = "fail2ban.sqlite3";
|
|
||||||
in {
|
|
||||||
config = lib.mkIf config.services.fail2ban.enable (lib.mkMerge [
|
|
||||||
{
|
|
||||||
environment.etc = {
|
|
||||||
"fail2ban/filter.d/nginx.local".text = lib.mkIf config.services.nginx.enable (
|
|
||||||
pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
|
|
||||||
[Definition]
|
|
||||||
failregex = "limiting requests, excess:.* by zone.*client: <HOST>"
|
|
||||||
'')
|
|
||||||
);
|
|
||||||
};
|
|
||||||
|
|
||||||
services.fail2ban = {
|
|
||||||
maxretry = 5;
|
|
||||||
ignoreIP = [
|
|
||||||
# Whitelist local networks
|
|
||||||
"10.0.0.0/8"
|
|
||||||
"172.16.0.0/12"
|
|
||||||
"192.168.0.0/16"
|
|
||||||
|
|
||||||
# tail scale tailnet
|
|
||||||
"100.64.0.0/10"
|
|
||||||
"fd7a:115c:a1e0::/48"
|
|
||||||
];
|
|
||||||
bantime = "24h"; # Ban IPs for one day on the first ban
|
|
||||||
bantime-increment = {
|
|
||||||
enable = true; # Enable increment of bantime after each violation
|
|
||||||
formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
|
|
||||||
maxtime = "168h"; # Do not ban for more than 1 week
|
|
||||||
overalljails = true; # Calculate the ban time based on all the violations
|
|
||||||
};
|
|
||||||
jails = {
|
|
||||||
nginx-iptables.settings = lib.mkIf config.services.nginx.enable {
|
|
||||||
enabled = true;
|
|
||||||
filter = "nginx";
|
|
||||||
action = ''iptables-multiport[name=HTTP, port="http,https"]'';
|
|
||||||
backend = "auto";
|
|
||||||
findtime = 600;
|
|
||||||
bantime = 600;
|
|
||||||
maxretry = 5;
|
|
||||||
};
|
|
||||||
# TODO; figure out if there is any fail2ban things we can do on searx
|
|
||||||
# searx-iptables.settings = lib.mkIf config.services.searx.enable {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
(lib.mkIf config.host.impermanence.enable {
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = config.services.fail2ban.daemonSettings.Definition.dbfile == "${dataFolder}/${dataFile}";
|
|
||||||
message = "fail2ban data file does not match persistence";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.persistence."/persist/system/root" = {
|
|
||||||
directories = [
|
|
||||||
{
|
|
||||||
directory = dataFolder;
|
|
||||||
user = "fail2ban";
|
|
||||||
group = "fail2ban";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
6
modules/nixos-modules/server/fail2ban/default.nix
Normal file
6
modules/nixos-modules/server/fail2ban/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{...}: {
|
||||||
|
imports = [
|
||||||
|
./fail2ban.nix
|
||||||
|
./impermanence.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
51
modules/nixos-modules/server/fail2ban/fail2ban.nix
Normal file
51
modules/nixos-modules/server/fail2ban/fail2ban.nix
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
config = lib.mkIf config.services.fail2ban.enable {
|
||||||
|
environment.etc = {
|
||||||
|
"fail2ban/filter.d/nginx.local".text = lib.mkIf config.services.nginx.enable (
|
||||||
|
pkgs.lib.mkDefault (pkgs.lib.mkAfter ''
|
||||||
|
[Definition]
|
||||||
|
failregex = "limiting requests, excess:.* by zone.*client: <HOST>"
|
||||||
|
'')
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
services.fail2ban = {
|
||||||
|
maxretry = 5;
|
||||||
|
ignoreIP = [
|
||||||
|
# Whitelist local networks
|
||||||
|
"10.0.0.0/8"
|
||||||
|
"172.16.0.0/12"
|
||||||
|
"192.168.0.0/16"
|
||||||
|
|
||||||
|
# tail scale tailnet
|
||||||
|
"100.64.0.0/10"
|
||||||
|
"fd7a:115c:a1e0::/48"
|
||||||
|
];
|
||||||
|
bantime = "24h"; # Ban IPs for one day on the first ban
|
||||||
|
bantime-increment = {
|
||||||
|
enable = true; # Enable increment of bantime after each violation
|
||||||
|
formula = "ban.Time * math.exp(float(ban.Count+1)*banFactor)/math.exp(1*banFactor)";
|
||||||
|
maxtime = "168h"; # Do not ban for more than 1 week
|
||||||
|
overalljails = true; # Calculate the ban time based on all the violations
|
||||||
|
};
|
||||||
|
jails = {
|
||||||
|
nginx-iptables.settings = lib.mkIf config.services.nginx.enable {
|
||||||
|
enabled = true;
|
||||||
|
filter = "nginx";
|
||||||
|
action = ''iptables-multiport[name=HTTP, port="http,https"]'';
|
||||||
|
backend = "auto";
|
||||||
|
findtime = 600;
|
||||||
|
bantime = 600;
|
||||||
|
maxretry = 5;
|
||||||
|
};
|
||||||
|
# TODO; figure out if there is any fail2ban things we can do on searx
|
||||||
|
# searx-iptables.settings = lib.mkIf config.services.searx.enable {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
27
modules/nixos-modules/server/fail2ban/impermanence.nix
Normal file
27
modules/nixos-modules/server/fail2ban/impermanence.nix
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
dataFolder = "/var/lib/fail2ban";
|
||||||
|
dataFile = "fail2ban.sqlite3";
|
||||||
|
in {
|
||||||
|
config = lib.mkIf (config.services.fail2ban.enable && config.host.impermanence.enable) {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = config.services.fail2ban.daemonSettings.Definition.dbfile == "${dataFolder}/${dataFile}";
|
||||||
|
message = "fail2ban data file does not match persistence";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.persistence."/persist/system/root" = {
|
||||||
|
directories = [
|
||||||
|
{
|
||||||
|
directory = dataFolder;
|
||||||
|
user = "fail2ban";
|
||||||
|
group = "fail2ban";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,121 +0,0 @@
|
||||||
{
|
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
dataDir = "/var/lib/postgresql/16";
|
|
||||||
adminUsers = lib.lists.filter (user: user.isAdmin) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
|
||||||
clientUsers = lib.lists.filter (user: user.isClient) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
|
||||||
createUsers = lib.lists.filter (user: user.createUser) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
|
||||||
createDatabases = lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraDatabases;
|
|
||||||
in {
|
|
||||||
options = {
|
|
||||||
host.postgres = {
|
|
||||||
enable = lib.mkEnableOption "enable postgres";
|
|
||||||
extraUsers = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
|
||||||
options = {
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = name;
|
|
||||||
};
|
|
||||||
isAdmin = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
isClient = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
createUser = lib.mkOption {
|
|
||||||
type = lib.types.bool;
|
|
||||||
default = false;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
extraDatabases = lib.mkOption {
|
|
||||||
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
|
||||||
options = {
|
|
||||||
name = lib.mkOption {
|
|
||||||
type = lib.types.str;
|
|
||||||
default = name;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}));
|
|
||||||
default = {};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf config.host.postgres.enable (lib.mkMerge [
|
|
||||||
{
|
|
||||||
services = {
|
|
||||||
postgresql = {
|
|
||||||
enable = true;
|
|
||||||
package = pkgs.postgresql_16;
|
|
||||||
ensureUsers =
|
|
||||||
[
|
|
||||||
{
|
|
||||||
name = "postgres";
|
|
||||||
}
|
|
||||||
]
|
|
||||||
++ (
|
|
||||||
builtins.map (user: {
|
|
||||||
name = user.name;
|
|
||||||
ensureDBOwnership = true;
|
|
||||||
})
|
|
||||||
createUsers
|
|
||||||
);
|
|
||||||
ensureDatabases = builtins.map (database: database.name) createDatabases;
|
|
||||||
identMap =
|
|
||||||
''
|
|
||||||
# ArbitraryMapName systemUser DBUser
|
|
||||||
|
|
||||||
# Administration Users
|
|
||||||
superuser_map root postgres
|
|
||||||
superuser_map postgres postgres
|
|
||||||
''
|
|
||||||
+ (
|
|
||||||
lib.strings.concatLines (builtins.map (user: "superuser_map ${user.name} postgres") adminUsers)
|
|
||||||
)
|
|
||||||
+ ''
|
|
||||||
|
|
||||||
# Client Users
|
|
||||||
''
|
|
||||||
+ (
|
|
||||||
lib.strings.concatLines (builtins.map (user: "user_map ${user.name} ${user.name}") clientUsers)
|
|
||||||
);
|
|
||||||
# configuration here lets users access the db that matches their name and lets user postgres access everything
|
|
||||||
authentication = pkgs.lib.mkOverride 10 ''
|
|
||||||
# type database DBuser origin-address auth-method optional_ident_map
|
|
||||||
local all postgres peer map=superuser_map
|
|
||||||
local sameuser all peer map=user_map
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
(lib.mkIf config.host.impermanence.enable {
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = config.services.postgresql.dataDir == dataDir;
|
|
||||||
message = "postgres data directory does not match persistence";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
environment.persistence."/persist/system/root" = {
|
|
||||||
enable = true;
|
|
||||||
hideMounts = true;
|
|
||||||
directories = [
|
|
||||||
{
|
|
||||||
directory = dataDir;
|
|
||||||
user = "postgres";
|
|
||||||
group = "postgres";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
6
modules/nixos-modules/server/postgres/default.nix
Normal file
6
modules/nixos-modules/server/postgres/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{...}: {
|
||||||
|
imports = [
|
||||||
|
./postgres.nix
|
||||||
|
./impermanence.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
27
modules/nixos-modules/server/postgres/impermanence.nix
Normal file
27
modules/nixos-modules/server/postgres/impermanence.nix
Normal file
|
|
@ -0,0 +1,27 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
dataDir = "/var/lib/postgresql/16";
|
||||||
|
in {
|
||||||
|
config = lib.mkIf (config.host.postgres.enable && config.host.impermanence.enable) {
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = config.services.postgresql.dataDir == dataDir;
|
||||||
|
message = "postgres data directory does not match persistence";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
environment.persistence."/persist/system/root" = {
|
||||||
|
enable = true;
|
||||||
|
hideMounts = true;
|
||||||
|
directories = [
|
||||||
|
{
|
||||||
|
directory = dataDir;
|
||||||
|
user = "postgres";
|
||||||
|
group = "postgres";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
98
modules/nixos-modules/server/postgres/postgres.nix
Normal file
98
modules/nixos-modules/server/postgres/postgres.nix
Normal file
|
|
@ -0,0 +1,98 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
adminUsers = lib.lists.filter (user: user.isAdmin) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
||||||
|
clientUsers = lib.lists.filter (user: user.isClient) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
||||||
|
createUsers = lib.lists.filter (user: user.createUser) (lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraUsers);
|
||||||
|
createDatabases = lib.attrsets.mapAttrsToList (_: user: user) config.host.postgres.extraDatabases;
|
||||||
|
in {
|
||||||
|
options = {
|
||||||
|
host.postgres = {
|
||||||
|
enable = lib.mkEnableOption "enable postgres";
|
||||||
|
extraUsers = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
isAdmin = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
isClient = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
createUser = lib.mkOption {
|
||||||
|
type = lib.types.bool;
|
||||||
|
default = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
extraDatabases = lib.mkOption {
|
||||||
|
type = lib.types.attrsOf (lib.types.submodule ({name, ...}: {
|
||||||
|
options = {
|
||||||
|
name = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = name;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}));
|
||||||
|
default = {};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.host.postgres.enable {
|
||||||
|
services = {
|
||||||
|
postgresql = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.postgresql_16;
|
||||||
|
ensureUsers =
|
||||||
|
[
|
||||||
|
{
|
||||||
|
name = "postgres";
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++ (
|
||||||
|
builtins.map (user: {
|
||||||
|
name = user.name;
|
||||||
|
ensureDBOwnership = true;
|
||||||
|
})
|
||||||
|
createUsers
|
||||||
|
);
|
||||||
|
ensureDatabases = builtins.map (database: database.name) createDatabases;
|
||||||
|
identMap =
|
||||||
|
''
|
||||||
|
# ArbitraryMapName systemUser DBUser
|
||||||
|
|
||||||
|
# Administration Users
|
||||||
|
superuser_map root postgres
|
||||||
|
superuser_map postgres postgres
|
||||||
|
''
|
||||||
|
+ (
|
||||||
|
lib.strings.concatLines (builtins.map (user: "superuser_map ${user.name} postgres") adminUsers)
|
||||||
|
)
|
||||||
|
+ ''
|
||||||
|
|
||||||
|
# Client Users
|
||||||
|
''
|
||||||
|
+ (
|
||||||
|
lib.strings.concatLines (builtins.map (user: "user_map ${user.name} ${user.name}") clientUsers)
|
||||||
|
);
|
||||||
|
# configuration here lets users access the db that matches their name and lets user postgres access everything
|
||||||
|
authentication = pkgs.lib.mkOverride 10 ''
|
||||||
|
# type database DBuser origin-address auth-method optional_ident_map
|
||||||
|
local all postgres peer map=superuser_map
|
||||||
|
local sameuser all peer map=user_map
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
@ -1,65 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
config,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
qbittorent_profile_directory = "/var/lib/qBittorrent/";
|
|
||||||
in {
|
|
||||||
options.services.qbittorrent = {
|
|
||||||
mediaDir = lib.mkOption {
|
|
||||||
type = lib.types.path;
|
|
||||||
description = lib.mdDoc ''
|
|
||||||
The directory to create to store qbittorrent media.
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
config = lib.mkIf config.services.qbittorrent.enable (lib.mkMerge [
|
|
||||||
(lib.mkIf config.host.impermanence.enable {
|
|
||||||
fileSystems."/persist/system/qbittorrent".neededForBoot = true;
|
|
||||||
|
|
||||||
host.storage.pool.extraDatasets = {
|
|
||||||
# sops age key needs to be available to pre persist for user generation
|
|
||||||
"persist/system/qbittorrent" = {
|
|
||||||
type = "zfs_fs";
|
|
||||||
mountpoint = "/persist/system/qbittorrent";
|
|
||||||
options = {
|
|
||||||
canmount = "on";
|
|
||||||
};
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
assertions = [
|
|
||||||
{
|
|
||||||
assertion = config.services.qbittorrent.profileDir == qbittorent_profile_directory;
|
|
||||||
message = "qbittorrent data directory does not match persistence";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
|
|
||||||
environment.persistence = {
|
|
||||||
"/persist/system/root" = {
|
|
||||||
directories = [
|
|
||||||
{
|
|
||||||
directory = qbittorent_profile_directory;
|
|
||||||
user = "qbittorrent";
|
|
||||||
group = "qbittorrent";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
"/persist/system/qbittorrent" = {
|
|
||||||
enable = true;
|
|
||||||
hideMounts = true;
|
|
||||||
directories = [
|
|
||||||
{
|
|
||||||
directory = config.services.qbittorrent.mediaDir;
|
|
||||||
user = "qbittorrent";
|
|
||||||
group = "qbittorrent";
|
|
||||||
mode = "1775";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
})
|
|
||||||
]);
|
|
||||||
}
|
|
||||||
6
modules/nixos-modules/server/qbittorent/default.nix
Normal file
6
modules/nixos-modules/server/qbittorent/default.nix
Normal file
|
|
@ -0,0 +1,6 @@
|
||||||
|
{...}: {
|
||||||
|
imports = [
|
||||||
|
./qbittorent.nix
|
||||||
|
./impermanence.nix
|
||||||
|
];
|
||||||
|
}
|
||||||
54
modules/nixos-modules/server/qbittorent/impermanence.nix
Normal file
54
modules/nixos-modules/server/qbittorent/impermanence.nix
Normal file
|
|
@ -0,0 +1,54 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
qbittorent_profile_directory = "/var/lib/qBittorrent/";
|
||||||
|
in {
|
||||||
|
config = lib.mkIf (config.services.qbittorrent.enable && config.host.impermanence.enable) {
|
||||||
|
fileSystems."/persist/system/qbittorrent".neededForBoot = true;
|
||||||
|
|
||||||
|
host.storage.pool.extraDatasets = {
|
||||||
|
# sops age key needs to be available to pre persist for user generation
|
||||||
|
"persist/system/qbittorrent" = {
|
||||||
|
type = "zfs_fs";
|
||||||
|
mountpoint = "/persist/system/qbittorrent";
|
||||||
|
options = {
|
||||||
|
canmount = "on";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
assertions = [
|
||||||
|
{
|
||||||
|
assertion = config.services.qbittorrent.profileDir == qbittorent_profile_directory;
|
||||||
|
message = "qbittorrent data directory does not match persistence";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
environment.persistence = {
|
||||||
|
"/persist/system/root" = {
|
||||||
|
directories = [
|
||||||
|
{
|
||||||
|
directory = qbittorent_profile_directory;
|
||||||
|
user = "qbittorrent";
|
||||||
|
group = "qbittorrent";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
"/persist/system/qbittorrent" = {
|
||||||
|
enable = true;
|
||||||
|
hideMounts = true;
|
||||||
|
directories = [
|
||||||
|
{
|
||||||
|
directory = config.services.qbittorrent.mediaDir;
|
||||||
|
user = "qbittorrent";
|
||||||
|
group = "qbittorrent";
|
||||||
|
mode = "1775";
|
||||||
|
}
|
||||||
|
];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
18
modules/nixos-modules/server/qbittorent/qbittorent.nix
Normal file
18
modules/nixos-modules/server/qbittorent/qbittorent.nix
Normal file
|
|
@ -0,0 +1,18 @@
|
||||||
|
{
|
||||||
|
lib,
|
||||||
|
config,
|
||||||
|
...
|
||||||
|
}: {
|
||||||
|
options.services.qbittorrent = {
|
||||||
|
mediaDir = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
description = lib.mdDoc ''
|
||||||
|
The directory to create to store qbittorrent media.
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
config = lib.mkIf config.services.qbittorrent.enable {
|
||||||
|
# Main qbittorrent configuration goes here if needed
|
||||||
|
};
|
||||||
|
}
|
||||||
Loading…
Add table
Add a link
Reference in a new issue