un container

This commit is contained in:
mjallen18
2025-10-09 17:48:27 -05:00
parent ef22231dd7
commit 76c0cd98d8
9 changed files with 388 additions and 147 deletions

View File

@@ -8,68 +8,40 @@
with lib; with lib;
let let
cfg = config.${namespace}.services.actual; cfg = config.${namespace}.services.actual;
dataDir = "/data";
hostAddress = "10.0.1.3";
actualUserId = config.users.users.nix-apps.uid;
actualGroupId = config.users.groups.jallen-nas.gid;
actualConfig = { actualConfig = {
services.actual = { services.actual = {
enable = true; enable = true;
openFirewall = true; openFirewall = true;
settings = { settings = {
trustedProxies = [ hostAddress ]; trustedProxies = [ "10.0.1.3" ];
port = cfg.port; port = cfg.port;
dataDir = dataDir; dataDir = cfg.dataDir;
serverFiles = "${dataDir}/server-files"; serverFiles = "${cfg.dataDir}/server-files";
userFiles = "${dataDir}/user-files"; userFiles = "${cfg.dataDir}/user-files";
}; };
}; };
users.users.actual = {
isSystemUser = true;
uid = lib.mkForce actualUserId;
group = "actual";
};
users.groups = {
actual = {
gid = lib.mkForce actualGroupId;
};
};
# System packages
environment.systemPackages = with pkgs; [
sqlite
];
# Create and set permissions for required directories
system.activationScripts.actual-dirs = ''
mkdir -p ${dataDir}
chown -R actual:actual ${dataDir}
chmod -R 0700 ${dataDir}
'';
systemd.services = { systemd.services = {
actual = { actual = {
environment.ACTUAL_CONFIG_PATH = lib.mkForce "${dataDir}/config.json"; environment.ACTUAL_CONFIG_PATH = lib.mkForce "${cfg.dataDir}/config.json";
serviceConfig = { serviceConfig = {
ExecStart = lib.mkForce "${lib.getExe pkgs.actual-server} --config ${dataDir}/config.json"; ExecStart = lib.mkForce "${lib.getExe pkgs.actual-server} --config ${cfg.dataDir}/config.json";
WorkingDirectory = lib.mkForce dataDir; WorkingDirectory = lib.mkForce cfg.dataDir;
StateDirectory = lib.mkForce dataDir; StateDirectory = lib.mkForce cfg.dataDir;
StateDirectoryMode = lib.mkForce 700; StateDirectoryMode = lib.mkForce 700;
DynamicUser = lib.mkForce false; DynamicUser = lib.mkForce false;
ProtectSystem = lib.mkForce null; ProtectSystem = lib.mkForce null;
}; };
}; };
}; };
};
bindMounts = { users.users.actual = {
"${dataDir}" = { isSystemUser = true;
hostPath = cfg.dataDir; group = "actual";
isReadOnly = false; home = cfg.dataDir;
}; };
users.groups.actual = {};
}; };
# Create reverse proxy configuration using mkReverseProxy # Create reverse proxy configuration using mkReverseProxy
@@ -80,22 +52,12 @@ let
middlewares = cfg.reverseProxy.middlewares; middlewares = cfg.reverseProxy.middlewares;
}; };
actualContainer =
(lib.${namespace}.mkContainer {
name = "actual";
localAddress = cfg.localAddress;
ports = [ cfg.port ];
bindMounts = bindMounts;
config = actualConfig;
})
{ inherit lib; };
fullConfig = { fullConfig = {
"${namespace}".services.traefik = lib.mkIf cfg.reverseProxy.enable { "${namespace}".services.traefik = lib.mkIf cfg.reverseProxy.enable {
reverseProxies = [ reverseProxyConfig ]; reverseProxies = [ reverseProxyConfig ];
}; };
} }
// actualContainer; // actualConfig;
in in
{ {
imports = [ ./options.nix ]; imports = [ ./options.nix ];

View File

@@ -0,0 +1,104 @@
{
config,
pkgs,
lib,
namespace,
...
}:
with lib;
let
cfg = config.${namespace}.services.actual;
dataDir = "/data";
hostAddress = "10.0.1.3";
actualUserId = config.users.users.nix-apps.uid;
actualGroupId = config.users.groups.jallen-nas.gid;
actualConfig = {
services.actual = {
enable = true;
openFirewall = true;
settings = {
trustedProxies = [ hostAddress ];
port = cfg.port;
dataDir = dataDir;
serverFiles = "${dataDir}/server-files";
userFiles = "${dataDir}/user-files";
};
};
users.users.actual = {
isSystemUser = true;
uid = lib.mkForce actualUserId;
group = "actual";
};
users.groups = {
actual = {
gid = lib.mkForce actualGroupId;
};
};
# System packages
environment.systemPackages = with pkgs; [
sqlite
];
# Create and set permissions for required directories
system.activationScripts.actual-dirs = ''
mkdir -p ${dataDir}
chown -R actual:actual ${dataDir}
chmod -R 0700 ${dataDir}
'';
systemd.services = {
actual = {
environment.ACTUAL_CONFIG_PATH = lib.mkForce "${dataDir}/config.json";
serviceConfig = {
ExecStart = lib.mkForce "${lib.getExe pkgs.actual-server} --config ${dataDir}/config.json";
WorkingDirectory = lib.mkForce dataDir;
StateDirectory = lib.mkForce dataDir;
StateDirectoryMode = lib.mkForce 700;
DynamicUser = lib.mkForce false;
ProtectSystem = lib.mkForce null;
};
};
};
};
bindMounts = {
"${dataDir}" = {
hostPath = cfg.dataDir;
isReadOnly = false;
};
};
# Create reverse proxy configuration using mkReverseProxy
reverseProxyConfig = lib.${namespace}.mkReverseProxy {
name = "actual";
subdomain = cfg.reverseProxy.subdomain;
url = "http://${cfg.localAddress}:${toString cfg.port}";
middlewares = cfg.reverseProxy.middlewares;
};
actualContainer =
(lib.${namespace}.mkContainer {
name = "actual";
localAddress = cfg.localAddress;
ports = [ cfg.port ];
bindMounts = bindMounts;
config = actualConfig;
})
{ inherit lib; };
fullConfig = {
"${namespace}".services.traefik = lib.mkIf cfg.reverseProxy.enable {
reverseProxies = [ reverseProxyConfig ];
};
}
// actualContainer;
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable fullConfig;
}

88
modules/nixos/services/jellyseerr/default.nix Executable file → Normal file
View File

@@ -6,78 +6,46 @@
}: }:
with lib; with lib;
let let
inherit (lib.${namespace}) mkOpt mkReverseProxyOpt;
cfg = config.${namespace}.services.jellyseerr; cfg = config.${namespace}.services.jellyseerr;
jellyseerrPort = 5055; jellyseerrPort = 5055;
dataDir = "/var/lib/private/jellyseerr";
in in
{ {
imports = [ ./options.nix ]; options.${namespace}.services.jellyseerr = {
enable = mkEnableOption "enable jellyseerr";
port = mkOpt types.int 5055 "jellyseerr port";
dataDir = mkOpt types.str "" "data dir";
};
config = mkIf cfg.enable { config = mkIf cfg.enable {
containers.jellyseerr = { # Enable jellyseerr service
autoStart = true; services.jellyseerr = {
privateNetwork = true; enable = true;
hostAddress = "10.0.1.3"; port = cfg.port;
localAddress = "10.0.1.52"; openFirewall = true;
hostAddress6 = "fc00::1"; configDir = cfg.dataDir;
localAddress6 = "fc00::4"; };
bindMounts = { systemd.services = {
${dataDir} = { jellyseerr = {
hostPath = "/media/nas/main/nix-app-data/jellyseerr"; serviceConfig = {
isReadOnly = false; WorkingDirectory = lib.mkForce cfg.dataDir;
StateDirectory = lib.mkForce cfg.dataDir;
StateDirectoryMode = lib.mkForce 700;
DynamicUser = lib.mkForce false;
ProtectSystem = lib.mkForce null;
}; };
}; };
config =
{
lib,
...
}:
{
# Enable jellyseerr service
services.jellyseerr = {
enable = true;
port = jellyseerrPort;
# package = package;
openFirewall = true;
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ jellyseerrPort ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
# Create and set permissions for required directories
system.activationScripts.jellyseerr-dirs = ''
mkdir -p /var/lib/private/jellyseerr
chown -R jellyseerr:jellyseerr /var/lib/private/jellyseerr
chmod -R 775 /var/lib/private/jellyseerr
ln -sf /var/lib/private/jellyseerr /var/lib/jellyfin
'';
services.resolved.enable = true;
system.stateVersion = "23.11";
};
}; };
networking.nat = { users.users.jellyseerr = {
forwardPorts = [ isSystemUser = true;
{ group = "jellyseerr";
destination = "10.0.1.52:5055"; home = cfg.dataDir;
sourcePort = jellyseerrPort;
}
];
}; };
users.groups.jellyseerr = {};
}; };
} }

View File

@@ -0,0 +1,83 @@
{
config,
lib,
namespace,
...
}:
with lib;
let
cfg = config.${namespace}.services.jellyseerr;
jellyseerrPort = 5055;
dataDir = "/var/lib/private/jellyseerr";
in
{
imports = [ ./options.nix ];
config = mkIf cfg.enable {
containers.jellyseerr = {
autoStart = true;
privateNetwork = true;
hostAddress = "10.0.1.3";
localAddress = "10.0.1.52";
hostAddress6 = "fc00::1";
localAddress6 = "fc00::4";
bindMounts = {
${dataDir} = {
hostPath = "/media/nas/main/nix-app-data/jellyseerr";
isReadOnly = false;
};
};
config =
{
lib,
...
}:
{
# Enable jellyseerr service
services.jellyseerr = {
enable = true;
port = jellyseerrPort;
# package = package;
openFirewall = true;
};
networking = {
firewall = {
enable = true;
allowedTCPPorts = [ jellyseerrPort ];
};
# Use systemd-resolved inside the container
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
useHostResolvConf = lib.mkForce false;
};
# Create and set permissions for required directories
system.activationScripts.jellyseerr-dirs = ''
mkdir -p /var/lib/private/jellyseerr
chown -R jellyseerr:jellyseerr /var/lib/private/jellyseerr
chmod -R 775 /var/lib/private/jellyseerr
ln -sf /var/lib/private/jellyseerr /var/lib/jellyfin
'';
services.resolved.enable = true;
system.stateVersion = "23.11";
};
};
networking.nat = {
forwardPorts = [
{
destination = "10.0.1.52:5055";
sourcePort = jellyseerrPort;
}
];
};
};
}

View File

@@ -19,62 +19,52 @@ let
base-url = "https://${cfg.reverseProxy.subdomain}.mjallen.dev"; base-url = "https://${cfg.reverseProxy.subdomain}.mjallen.dev";
enable-login = true; enable-login = true;
listen-http = ":${toString cfg.port}"; listen-http = ":${toString cfg.port}";
cache-file = "/var/lib/ntfy-sh/cache.db"; cache-file = "${cfg.dataDir}/cache.db";
attachment-cache-dir = "/var/lib/ntfy-sh/attachments"; attachment-cache-dir = "/${cfg.dataDir}/attachments";
behind-proxy = true; behind-proxy = true;
auth-default-access = "deny-all"; auth-default-access = "deny-all";
auth-file = "/var/lib/ntfy-sh/user.db"; auth-file = "${cfg.dataDir}/user.db";
auth-users = [ auth-users = [
"mjallen:$2a$10$g4TqI8UiKKVaKTmrwnXIw.wtajiLBM6oc3UCfJ//lPZFilJnBirn.:admin" "mjallen:$2a$10$g4TqI8UiKKVaKTmrwnXIw.wtajiLBM6oc3UCfJ//lPZFilJnBirn.:admin"
]; ];
}; };
}; };
}; };
# Create and set permissions for required directories
system.activationScripts.ntfy-dirs = ''
mkdir -p /var/lib/ntfy-sh
chown -R ntfy-sh:ntfy-sh /var/lib/ntfy-sh systemd.services = {
ntfy-sh = {
chmod -R 775 /var/lib/ntfy-sh serviceConfig = {
''; WorkingDirectory = lib.mkForce cfg.dataDir;
}; StateDirectory = lib.mkForce cfg.dataDir;
StateDirectoryMode = lib.mkForce 700;
bindMounts = { DynamicUser = lib.mkForce false;
"/var/lib/ntfy-sh" = { ProtectSystem = lib.mkForce null;
hostPath = cfg.dataDir; };
isReadOnly = false; };
}; };
"/run/.env" = {
hostPath = ntfyEnvFile; users.users.ntfy-sh = {
isReadOnly = true; isSystemUser = true;
group = "ntfy-sh";
home = cfg.dataDir;
}; };
users.groups.ntfy-sh = {};
}; };
# Create reverse proxy configuration using mkReverseProxy # Create reverse proxy configuration using mkReverseProxy
reverseProxyConfig = lib.${namespace}.mkReverseProxy { reverseProxyConfig = lib.${namespace}.mkReverseProxy {
name = "ntfy"; name = "ntfy";
subdomain = cfg.reverseProxy.subdomain; subdomain = cfg.reverseProxy.subdomain;
url = "http://${cfg.localAddress}:${toString cfg.port}"; url = "http://10.0.1.3:${toString cfg.port}";
middlewares = cfg.reverseProxy.middlewares; middlewares = cfg.reverseProxy.middlewares;
}; };
ntfyContainer =
(lib.${namespace}.mkContainer {
name = "ntfy";
localAddress = cfg.localAddress;
ports = [ cfg.port ];
bindMounts = bindMounts;
config = ntfyConfig;
})
{ inherit lib; };
fullConfig = { fullConfig = {
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable { "${namespace}".services.traefik = lib.mkIf cfg.reverseProxy.enable {
reverseProxies = [ reverseProxyConfig ]; reverseProxies = [ reverseProxyConfig ];
}; };
} }
// ntfyContainer; // ntfyConfig;
in in
with lib; with lib;
{ {

View File

@@ -0,0 +1,94 @@
{
config,
lib,
namespace,
...
}:
let
inherit (lib.${namespace}) mkOpt mkReverseProxyOpt;
cfg = config.${namespace}.services.ntfy;
ntfyEnvFile = config.sops.secrets."jallen-nas/ntfy/auth-users".path;
ntfyConfig = {
services = {
ntfy-sh = {
enable = true;
# environmentFile = "/run/.env";
settings = {
base-url = "https://${cfg.reverseProxy.subdomain}.mjallen.dev";
enable-login = true;
listen-http = ":${toString cfg.port}";
cache-file = "/var/lib/ntfy-sh/cache.db";
attachment-cache-dir = "/var/lib/ntfy-sh/attachments";
behind-proxy = true;
auth-default-access = "deny-all";
auth-file = "/var/lib/ntfy-sh/user.db";
auth-users = [
"mjallen:$2a$10$g4TqI8UiKKVaKTmrwnXIw.wtajiLBM6oc3UCfJ//lPZFilJnBirn.:admin"
];
};
};
};
# Create and set permissions for required directories
system.activationScripts.ntfy-dirs = ''
mkdir -p /var/lib/ntfy-sh
chown -R ntfy-sh:ntfy-sh /var/lib/ntfy-sh
chmod -R 775 /var/lib/ntfy-sh
'';
};
bindMounts = {
"/var/lib/ntfy-sh" = {
hostPath = cfg.dataDir;
isReadOnly = false;
};
"/run/.env" = {
hostPath = ntfyEnvFile;
isReadOnly = true;
};
};
# Create reverse proxy configuration using mkReverseProxy
reverseProxyConfig = lib.${namespace}.mkReverseProxy {
name = "ntfy";
subdomain = cfg.reverseProxy.subdomain;
url = "http://${cfg.localAddress}:${toString cfg.port}";
middlewares = cfg.reverseProxy.middlewares;
};
ntfyContainer =
(lib.${namespace}.mkContainer {
name = "ntfy";
localAddress = cfg.localAddress;
ports = [ cfg.port ];
bindMounts = bindMounts;
config = ntfyConfig;
})
{ inherit lib; };
fullConfig = {
${namespace}.services.traefik = lib.mkIf cfg.reverseProxy.enable {
reverseProxies = [ reverseProxyConfig ];
};
}
// ntfyContainer;
in
with lib;
{
options.${namespace}.services.ntfy = {
enable = mkEnableOption "ntfy service";
port = mkOpt types.int 8008 "Port for ntfy to be hosted on";
localAddress = mkOpt types.str "127.0.0.1" "local address of the service";
dataDir = mkOpt types.str "" "Path to the data dir";
reverseProxy = mkReverseProxyOpt;
};
config = lib.mkIf cfg.enable fullConfig;
}

View File

@@ -66,7 +66,7 @@ let
hassUrl = "http://10.0.1.4:8123"; hassUrl = "http://10.0.1.4:8123";
immichUrl = "http://${serverIp}:${toString config.services.immich.port}"; immichUrl = "http://${serverIp}:${toString config.services.immich.port}";
jellyfinUrl = "http://${serverIp}:8096"; jellyfinUrl = "http://${serverIp}:8096";
jellyseerrUrl = "http://${config.containers.jellyseerr.localAddress}:${toString config.containers.jellyseerr.config.services.jellyseerr.port}"; jellyseerrUrl = "http://10.0.1.3:${toString config.services.jellyseerr.port}";
lubeloggerUrl = "http://${serverIp}:6754"; lubeloggerUrl = "http://${serverIp}:6754";
onlyofficeUrl = "http://${config.containers.nextcloud.localAddress}:${toString config.containers.nextcloud.config.services.onlyoffice.port}"; onlyofficeUrl = "http://${config.containers.nextcloud.localAddress}:${toString config.containers.nextcloud.config.services.onlyoffice.port}";
openWebUIUrl = "http://${serverIp}:8888"; openWebUIUrl = "http://${serverIp}:8888";
@@ -243,6 +243,22 @@ in
}; };
dynamicConfigOptions = { dynamicConfigOptions = {
# udp = {
# services = {
# wireguard.loadBalancer.servers = [
# {
# url = "localhost:51820";
# }
# ];
# };
# routers = {
# wireguard = {
# entryPoints = [ "websecure" ];
# service = "wireguard";
# };
# };
# };
http = { http = {
middlewares = { middlewares = {
authentik = { authentik = {
@@ -330,6 +346,12 @@ in
} }
]; ];
actual.loadBalancer.servers = [
{
url = "http://10.0.1.3:3333";
}
];
authentik.loadBalancer.servers = [ authentik.loadBalancer.servers = [
{ {
url = authentikUrl; url = authentikUrl;
@@ -413,6 +435,17 @@ in
tls.certResolver = "letsencrypt"; tls.certResolver = "letsencrypt";
}; };
actual = {
entryPoints = [ "websecure" ];
rule = "Host(`actual.${domain}`)";
service = "actual";
middlewares = [
"crowdsec"
"whitelist-geoblock"
];
tls.certResolver = "letsencrypt";
};
authentik = { authentik = {
entryPoints = [ "websecure" ]; entryPoints = [ "websecure" ];
rule = "Host(`authentik.${domain}`)"; rule = "Host(`authentik.${domain}`)";

View File

@@ -5,7 +5,10 @@
# Existing properly namespaced services # Existing properly namespaced services
immich.enable = true; immich.enable = true;
jellyfin.enable = true; jellyfin.enable = true;
jellyseerr.enable = true; jellyseerr = {
enable = true;
dataDir = "/media/nas/main/nix-app-data/jellyseerr";
};
lubelogger.enable = true; lubelogger.enable = true;
nextcloud.enable = true; nextcloud.enable = true;
ai.enable = true; ai.enable = true;

View File

@@ -24,12 +24,16 @@
enable = true; enable = true;
package = pkgs.postgresql_16; package = pkgs.postgresql_16;
dataDir = "/media/nas/main/nix-app-data/postgresql"; dataDir = "/media/nas/main/nix-app-data/postgresql";
ensureDatabases = [ "authentik" ]; ensureDatabases = [ "authentik" "homeassistant" ];
ensureUsers = [ ensureUsers = [
{ {
name = "authentik"; name = "authentik";
ensureDBOwnership = true; ensureDBOwnership = true;
} }
{
name = "homeassistant";
ensureDBOwnership = true;
}
]; ];
}; };