move stuff
This commit is contained in:
131
modules/nixos/services/actual/default.nix
Normal file
131
modules/nixos/services/actual/default.nix
Normal file
@@ -0,0 +1,131 @@
|
||||
{
|
||||
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;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
containers.actual = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = hostAddress;
|
||||
localAddress = cfg.localAddress;
|
||||
|
||||
bindMounts = {
|
||||
${dataDir} = {
|
||||
hostPath = cfg.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
{ lib, ... }:
|
||||
{
|
||||
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 "${pkgs.actual-server}/bin/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;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
};
|
||||
# Use systemd-resolved inside the container
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = lib.mkForce false;
|
||||
};
|
||||
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
};
|
||||
|
||||
services.traefik.dynamicConfigOptions = lib.mkIf cfg.reverseProxy.enable {
|
||||
services.actual.loadBalancer.servers = [
|
||||
{
|
||||
url = "http://${cfg.localAddress}:${toString cfg.port}";
|
||||
}
|
||||
];
|
||||
routers.actual = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`${cfg.reverseProxy.host}`)";
|
||||
service = "actual";
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
nat = {
|
||||
forwardPorts = [
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.port}";
|
||||
sourcePort = cfg.port;
|
||||
}
|
||||
];
|
||||
};
|
||||
firewall = {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
25
modules/nixos/services/actual/options.nix
Normal file
25
modules/nixos/services/actual/options.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ lib, namespace, ... }:
|
||||
let
|
||||
inherit (lib.mjallen) mkOpt mkBoolOpt;
|
||||
in
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.actual = {
|
||||
enable = mkEnableOption "actual service";
|
||||
|
||||
port = mkOpt types.int 80 "Port for Actual 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 = {
|
||||
enable = mkBoolOpt false "Enable reverse proxy support";
|
||||
|
||||
host = mkOpt types.str "" "Address of the proxy";
|
||||
|
||||
middlewares = with types; mkOpt (listOf str) [ ] "List of middlewares to use";
|
||||
|
||||
};
|
||||
};
|
||||
}
|
||||
71
modules/nixos/services/ai/default.nix
Executable file
71
modules/nixos/services/ai/default.nix
Executable file
@@ -0,0 +1,71 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.ai;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.ollama = {
|
||||
enable = true;
|
||||
port = 11434;
|
||||
host = "0.0.0.0";
|
||||
user = "nix-apps";
|
||||
group = "jallen-nas";
|
||||
openFirewall = true;
|
||||
acceleration = "cuda";
|
||||
home = "/media/nas/main/nix-app-data/ollama";
|
||||
};
|
||||
|
||||
environment.systemPackages = [ pkgs.stable.llama-cpp ];
|
||||
|
||||
services.llama-cpp = {
|
||||
enable = true;
|
||||
port = 8127;
|
||||
host = "0.0.0.0";
|
||||
openFirewall = true;
|
||||
model = "/media/nas/main/nix-app-data/llama-cpp/models/functionary-small-v3.2-GGUF/functionary-small-v3.2.Q4_0.gguf";
|
||||
package = pkgs.stable.llama-cpp;
|
||||
extraFlags = [
|
||||
"--n_gpu-layers"
|
||||
"500"
|
||||
"-c"
|
||||
"0"
|
||||
"--numa"
|
||||
"numactl"
|
||||
"--jinja"
|
||||
];
|
||||
};
|
||||
|
||||
services.open-webui = {
|
||||
enable = false;
|
||||
host = "0.0.0.0";
|
||||
port = 8888;
|
||||
openFirewall = true;
|
||||
# stateDir = "/media/nas/main/nix-app-data/open-webui";
|
||||
environmentFile = config.sops.secrets."jallen-nas/open-webui".path;
|
||||
environment = {
|
||||
OPENID_PROVIDER_URL = "https://authentik.mjallen.dev/application/o/chat/.well-known/openid-configuration";
|
||||
OAUTH_PROVIDER_NAME = "authentik";
|
||||
OPENID_REDIRECT_URI = "https://chat.mjallen.dev/oauth/oidc/callback";
|
||||
ENABLE_OAUTH_SIGNUP = "False";
|
||||
OAUTH_MERGE_ACCOUNTS_BY_EMAIL = "True";
|
||||
ENABLE_SIGNUP = "False";
|
||||
ENABLE_LOGIN_FORM = "False";
|
||||
ANONYMIZED_TELEMETRY = "False";
|
||||
DO_NOT_TRACK = "True";
|
||||
SCARF_NO_ANALYTICS = "True";
|
||||
OLLAMA_API_BASE_URL = "http://127.0.0.1:11434";
|
||||
LOCAL_FILES_ONLY = "False";
|
||||
WEBUI_AUTH = "False";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/ai/options.nix
Normal file
7
modules/nixos/services/ai/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.ai = {
|
||||
enable = mkEnableOption "enable ai";
|
||||
};
|
||||
}
|
||||
14
modules/nixos/services/appimage/default.nix
Normal file
14
modules/nixos/services/appimage/default.nix
Normal file
@@ -0,0 +1,14 @@
|
||||
{ lib, pkgs, ... }:
|
||||
{
|
||||
boot = {
|
||||
# Enable AppImage
|
||||
binfmt.registrations.appimage = {
|
||||
wrapInterpreterInShell = lib.mkDefault false;
|
||||
interpreter = "${pkgs.appimage-run}/bin/appimage-run";
|
||||
recognitionType = "magic";
|
||||
offset = 0;
|
||||
mask = "\\xff\\xff\\xff\\xff\\x00\\x00\\x00\\x00\\xff\\xff\\xff";
|
||||
magicOrExtension = "\\x7fELF....AI\\x02";
|
||||
};
|
||||
};
|
||||
}
|
||||
257
modules/nixos/services/arrs/default.nix
Executable file
257
modules/nixos/services/arrs/default.nix
Executable file
@@ -0,0 +1,257 @@
|
||||
{
|
||||
config,
|
||||
pkgs,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.arrs;
|
||||
radarrDataDir = "/var/lib/radarr";
|
||||
downloadDir = "/downloads";
|
||||
incompleteDir = "/downloads-incomplete";
|
||||
sonarrDataDir = "/var/lib/sonarr";
|
||||
sabnzbdConfig = "/var/lib/sabnzbd";
|
||||
jackettDir = "/var/lib/jackett/.config/Jackett";
|
||||
mediaDir = "/media";
|
||||
arrUserId = config.users.users.nix-apps.uid;
|
||||
arrGroupId = config.users.groups.jallen-nas.gid;
|
||||
radarrPkg = pkgs.radarr;
|
||||
sonarrPkg = pkgs.sonarr;
|
||||
delugePkg = pkgs.deluge;
|
||||
jackettPkg = pkgs.jackett;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
containers.arrs = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = "10.0.1.3";
|
||||
localAddress = cfg.localAddress;
|
||||
|
||||
config =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
nixpkgs.config = {
|
||||
allowUnfree = lib.mkForce true;
|
||||
allowUnfreePredicate =
|
||||
pkg:
|
||||
builtins.elem (lib.getName pkg) [
|
||||
"unrar"
|
||||
];
|
||||
};
|
||||
|
||||
# Enable radarr service
|
||||
services.radarr = {
|
||||
enable = cfg.radarr.enable;
|
||||
openFirewall = true;
|
||||
user = "arrs";
|
||||
group = "media";
|
||||
dataDir = radarrDataDir;
|
||||
package = radarrPkg;
|
||||
};
|
||||
|
||||
# Enable Sonarr service
|
||||
services.sonarr = {
|
||||
enable = cfg.sonarr.enable;
|
||||
openFirewall = true;
|
||||
user = "arrs";
|
||||
group = "media";
|
||||
dataDir = sonarrDataDir;
|
||||
package = sonarrPkg;
|
||||
};
|
||||
|
||||
# Enable Sabnzbd service
|
||||
services.sabnzbd = {
|
||||
enable = cfg.sabnzbd.enable;
|
||||
openFirewall = true;
|
||||
user = "arrs";
|
||||
group = "media";
|
||||
configFile = "${sabnzbdConfig}/sabnzbd.ini";
|
||||
package = pkgs.sabnzbd;
|
||||
};
|
||||
|
||||
services.deluge = {
|
||||
enable = cfg.deluge.enable;
|
||||
user = "arrs";
|
||||
group = "media";
|
||||
openFirewall = true;
|
||||
dataDir = "/media";
|
||||
package = delugePkg;
|
||||
web = {
|
||||
enable = true;
|
||||
port = cfg.deluge.port;
|
||||
openFirewall = true;
|
||||
};
|
||||
};
|
||||
|
||||
services.jackett = {
|
||||
enable = cfg.jackett.enable;
|
||||
user = "arrs";
|
||||
group = "media";
|
||||
openFirewall = true;
|
||||
package = jackettPkg;
|
||||
};
|
||||
|
||||
# Create required users and groups
|
||||
users.users.arrs = {
|
||||
isSystemUser = true;
|
||||
uid = lib.mkForce arrUserId;
|
||||
group = "media";
|
||||
extraGroups = [ "downloads" ];
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
media = {
|
||||
gid = lib.mkForce arrGroupId;
|
||||
};
|
||||
downloads = { };
|
||||
};
|
||||
|
||||
# System packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
glib
|
||||
sqlite
|
||||
mono
|
||||
mediainfo
|
||||
protonvpn-cli_2
|
||||
];
|
||||
|
||||
# Create and set permissions for required directories
|
||||
system.activationScripts.arr-dirs = ''
|
||||
mkdir -p ${radarrDataDir}
|
||||
mkdir -p ${sonarrDataDir}
|
||||
mkdir -p ${sabnzbdConfig}
|
||||
mkdir -p ${downloadDir}
|
||||
mkdir -p ${incompleteDir}
|
||||
mkdir -p ${mediaDir}
|
||||
|
||||
chown -R arrs:media ${radarrDataDir}
|
||||
chown -R arrs:media ${sonarrDataDir}
|
||||
chown -R arrs:media ${sabnzbdConfig}
|
||||
chown -R arrs:media ${downloadDir}
|
||||
chown -R arrs:media ${incompleteDir}
|
||||
chown -R arrs:media ${mediaDir}
|
||||
|
||||
chmod -R 775 ${radarrDataDir}
|
||||
chmod -R 775 ${sonarrDataDir}
|
||||
chmod -R 775 ${sabnzbdConfig}
|
||||
chmod -R 775 ${downloadDir}
|
||||
chmod -R 775 ${incompleteDir}
|
||||
chmod -R 775 ${mediaDir}
|
||||
|
||||
'';
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
cfg.radarr.port
|
||||
cfg.sonarr.port
|
||||
cfg.sabnzbd.port
|
||||
8080
|
||||
];
|
||||
};
|
||||
# Use systemd-resolved inside the container
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = lib.mkForce false;
|
||||
};
|
||||
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
|
||||
# Bind mount directories from host
|
||||
bindMounts = {
|
||||
"${radarrDataDir}" = {
|
||||
hostPath = cfg.radarr.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${sonarrDataDir}" = {
|
||||
hostPath = cfg.sonarr.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${sabnzbdConfig}" = {
|
||||
hostPath = cfg.sabnzbd.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${downloadDir}" = {
|
||||
hostPath = cfg.downloadsDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${incompleteDir}" = {
|
||||
hostPath = cfg.incompleteDownloadsDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"${jackettDir}" = {
|
||||
hostPath = cfg.jackett.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/media/movies" = {
|
||||
hostPath = cfg.moviesDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/media/tv" = {
|
||||
hostPath = cfg.tvDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
"/media/isos" = {
|
||||
hostPath = cfg.isosDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
nat = {
|
||||
forwardPorts = [
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.radarr.port}";
|
||||
sourcePort = cfg.radarr.port;
|
||||
}
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.sonarr.port}";
|
||||
sourcePort = cfg.sonarr.port;
|
||||
}
|
||||
{
|
||||
destination = "${cfg.localAddress}:8080";
|
||||
sourcePort = cfg.sabnzbd.port;
|
||||
}
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.deluge.port}";
|
||||
sourcePort = cfg.deluge.port;
|
||||
}
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.jackett.port}";
|
||||
sourcePort = cfg.jackett.port;
|
||||
}
|
||||
];
|
||||
};
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
cfg.radarr.port
|
||||
cfg.sonarr.port
|
||||
cfg.sabnzbd.port
|
||||
8080
|
||||
cfg.deluge.port
|
||||
cfg.jackett.port
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
cfg.radarr.port
|
||||
cfg.sonarr.port
|
||||
cfg.sabnzbd.port
|
||||
8080
|
||||
cfg.deluge.port
|
||||
cfg.jackett.port
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
112
modules/nixos/services/arrs/options.nix
Normal file
112
modules/nixos/services/arrs/options.nix
Normal file
@@ -0,0 +1,112 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.arrs = {
|
||||
enable = mkEnableOption "arrs services";
|
||||
|
||||
radarr = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 7878;
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
sonarr = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8989;
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
sabnzbd = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8280;
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
deluge = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 8112;
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
jackett = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
port = mkOption {
|
||||
type = types.int;
|
||||
default = 9117;
|
||||
};
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
|
||||
localAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
downloadsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
incompleteDownloadsDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
moviesDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
tvDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
isosDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
};
|
||||
}
|
||||
155
modules/nixos/services/attic/default.nix
Normal file
155
modules/nixos/services/attic/default.nix
Normal file
@@ -0,0 +1,155 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.attic;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.atticd = {
|
||||
enable = true;
|
||||
environmentFile = cfg.environmentFile;
|
||||
settings = {
|
||||
listen = "${cfg.listenAddress}:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
# Open firewall for attic if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
# Include the attic watch-store service and rebuild cache services
|
||||
systemd.services = {
|
||||
attic-watch-store = {
|
||||
enable = true;
|
||||
description = "watch store for cache";
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "admin";
|
||||
Group = "jallen-nas";
|
||||
WorkingDirectory = "/etc/nixos";
|
||||
StandardOutput = "journal+console";
|
||||
StandardError = "journal+console";
|
||||
Restart = "always";
|
||||
RestartSec = "5";
|
||||
};
|
||||
path = with pkgs; [
|
||||
bash
|
||||
attic-client
|
||||
];
|
||||
script = ''
|
||||
#!/usr/bin/env bash
|
||||
attic watch-store nas-cache
|
||||
'';
|
||||
};
|
||||
|
||||
nix-rebuild-cache = {
|
||||
enable = true;
|
||||
description = "Rebuild NixOS configurations for cache";
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
User = "admin";
|
||||
Group = "jallen-nas";
|
||||
WorkingDirectory = "/etc/nixos";
|
||||
StandardOutput = "journal+console";
|
||||
StandardError = "journal+console";
|
||||
Restart = "no";
|
||||
TimeoutStartSec = "2h";
|
||||
};
|
||||
path = with pkgs; [
|
||||
nix
|
||||
git
|
||||
coreutils
|
||||
gnugrep
|
||||
gnused
|
||||
openssh
|
||||
];
|
||||
script = ''
|
||||
#!/usr/bin/env bash
|
||||
if [ -d .git ]; then
|
||||
git pull || echo "Warning: Could not pull latest changes"
|
||||
fi
|
||||
echo "Updating flake at $(date)"
|
||||
if nix flake update; then
|
||||
echo "flake updated successfully at $(date)"
|
||||
else
|
||||
echo "failed to update flake $(date)"
|
||||
fi
|
||||
|
||||
if NIXPKGS_ALLOW_UNFREE=1 nix flake check --impure; then
|
||||
echo "flake checked successfully at $(date)"
|
||||
else
|
||||
echo "flake check failed at $(date)"
|
||||
git reset --hard
|
||||
fi
|
||||
|
||||
if nh os build --hostname=nas; then
|
||||
echo "nas built successfully at $(date)"
|
||||
fi;
|
||||
|
||||
if nh os build --hostname=nuc; then
|
||||
echo "nuc built successfully at $(date)"
|
||||
fi;
|
||||
|
||||
if nh os build --hostname=desktop; then
|
||||
echo "desktop built successfully at $(date)"
|
||||
fi;
|
||||
|
||||
if nh os build --hostname=steamdeck; then
|
||||
echo "steamdeck built successfully at $(date)"
|
||||
fi;
|
||||
|
||||
if nh os build --hostname=pi4; then
|
||||
echo "pi4 built successfully at $(date)"
|
||||
fi;
|
||||
|
||||
if nh os build --hostname=pi5; then
|
||||
echo "pi5 built successfully at $(date)"
|
||||
fi;
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# Include timers for cache rebuilds
|
||||
systemd.timers = {
|
||||
nix-rebuild-cache = {
|
||||
description = "Timer for rebuilding NixOS configurations cache";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "weekly";
|
||||
Persistent = true;
|
||||
RandomizedDelaySec = "24h";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
# Configure distributed builds
|
||||
nix = {
|
||||
settings.builders-use-substitutes = true;
|
||||
distributedBuilds = true;
|
||||
buildMachines = [
|
||||
{
|
||||
hostName = "pi5.local";
|
||||
system = "aarch64-linux";
|
||||
maxJobs = 4;
|
||||
sshUser = "matt";
|
||||
supportedFeatures = [
|
||||
"nixos-test"
|
||||
"benchmark"
|
||||
"big-parallel"
|
||||
"kvm"
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
31
modules/nixos/services/attic/options.nix
Normal file
31
modules/nixos/services/attic/options.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.attic = {
|
||||
enable = mkEnableOption "attic binary cache daemon";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 9012;
|
||||
description = "Port for attic cache daemon";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for attic";
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Path to environment file containing attic secrets";
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "[::1]";
|
||||
description = "Address to listen on";
|
||||
};
|
||||
};
|
||||
}
|
||||
47
modules/nixos/services/authentik/default.nix
Normal file
47
modules/nixos/services/authentik/default.nix
Normal file
@@ -0,0 +1,47 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.authentik;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.authentik = {
|
||||
enable = true;
|
||||
environmentFile = cfg.environmentFile;
|
||||
settings = {
|
||||
port = cfg.port;
|
||||
};
|
||||
};
|
||||
|
||||
# Open firewall for authentik if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
# Ensure PostgreSQL is configured for authentik
|
||||
services.postgresql = {
|
||||
enable = mkDefault true;
|
||||
ensureDatabases = [ "authentik" ];
|
||||
ensureUsers = [
|
||||
{
|
||||
name = "authentik";
|
||||
ensureDBOwnership = true;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
# Ensure Redis is configured for authentik
|
||||
services.redis.servers.authentik = {
|
||||
enable = mkDefault true;
|
||||
port = mkDefault 6379;
|
||||
};
|
||||
};
|
||||
}
|
||||
31
modules/nixos/services/authentik/options.nix
Normal file
31
modules/nixos/services/authentik/options.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.authentik = {
|
||||
enable = mkEnableOption "authentik identity provider";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 9000;
|
||||
description = "Port for authentik web interface";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for authentik";
|
||||
};
|
||||
|
||||
environmentFile = mkOption {
|
||||
type = types.nullOr types.path;
|
||||
default = null;
|
||||
description = "Path to environment file containing authentik secrets";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/authentik";
|
||||
description = "Data directory for authentik";
|
||||
};
|
||||
};
|
||||
}
|
||||
37
modules/nixos/services/code-server/default.nix
Normal file
37
modules/nixos/services/code-server/default.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.code-server;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Configure the standard NixOS code-server service
|
||||
services.code-server = {
|
||||
enable = true;
|
||||
port = cfg.port;
|
||||
user = cfg.user;
|
||||
group = cfg.group;
|
||||
host = cfg.host;
|
||||
auth = cfg.auth;
|
||||
disableTelemetry = cfg.disableTelemetry;
|
||||
disableUpdateCheck = cfg.disableUpdateCheck;
|
||||
extraEnvironment = cfg.extraEnvironment;
|
||||
}
|
||||
// optionalAttrs (cfg.hashedPassword != null) {
|
||||
hashedPassword = cfg.hashedPassword;
|
||||
};
|
||||
|
||||
# Open firewall for code-server if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
}
|
||||
70
modules/nixos/services/code-server/options.nix
Normal file
70
modules/nixos/services/code-server/options.nix
Normal file
@@ -0,0 +1,70 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.code-server = {
|
||||
enable = mkEnableOption "code-server with enhanced configuration";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 4444;
|
||||
description = "Port for code-server";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for code-server";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "admin";
|
||||
description = "User to run code-server as";
|
||||
};
|
||||
|
||||
group = mkOption {
|
||||
type = types.str;
|
||||
default = "users";
|
||||
description = "Group to run code-server as";
|
||||
};
|
||||
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Host to bind code-server to";
|
||||
};
|
||||
|
||||
auth = mkOption {
|
||||
type = types.enum [
|
||||
"none"
|
||||
"password"
|
||||
];
|
||||
default = "none";
|
||||
description = "Authentication method for code-server";
|
||||
};
|
||||
|
||||
hashedPassword = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Hashed password for code-server authentication";
|
||||
};
|
||||
|
||||
extraEnvironment = mkOption {
|
||||
type = types.attrsOf types.str;
|
||||
default = { };
|
||||
description = "Extra environment variables for code-server";
|
||||
};
|
||||
|
||||
disableTelemetry = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to disable telemetry";
|
||||
};
|
||||
|
||||
disableUpdateCheck = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to disable update checks";
|
||||
};
|
||||
};
|
||||
}
|
||||
66
modules/nixos/services/crowdsec/default.nix
Executable file
66
modules/nixos/services/crowdsec/default.nix
Executable file
@@ -0,0 +1,66 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.crowdsec;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
config = lib.mkIf cfg.enable {
|
||||
services = {
|
||||
crowdsec =
|
||||
let
|
||||
yaml = (pkgs.formats.yaml { }).generate;
|
||||
acquisitions_file = yaml "acquisitions.yaml" {
|
||||
source = "journalctl";
|
||||
journalctl_filter = [ "_SYSTEMD_UNIT=sshd.service" ];
|
||||
labels.type = "syslog";
|
||||
};
|
||||
in
|
||||
{
|
||||
enable = true;
|
||||
enrollKeyFile = "${cfg.dataDir}/enroll.key";
|
||||
settings = {
|
||||
crowdsec_service.acquisition_path = acquisitions_file;
|
||||
api.server = {
|
||||
listen_uri = "0.0.0.0:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
crowdsec-firewall-bouncer = {
|
||||
enable = true;
|
||||
settings = {
|
||||
api_key = cfg.apiKey;
|
||||
api_url = "http://${cfg.apiAddress}:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
systemd.services.crowdsec.serviceConfig = {
|
||||
ExecStartPre =
|
||||
let
|
||||
script = pkgs.writeScriptBin "register-bouncer" ''
|
||||
#!${pkgs.runtimeShell}
|
||||
set -eu
|
||||
set -o pipefail
|
||||
|
||||
if ! cscli bouncers list | grep -q "nas-bouncer"; then
|
||||
cscli bouncers add "nas-bouncer" --key "${cfg.apiKey}"
|
||||
fi
|
||||
'';
|
||||
in
|
||||
[ "${script}/bin/register-bouncer" ];
|
||||
};
|
||||
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
}
|
||||
37
modules/nixos/services/crowdsec/options.nix
Normal file
37
modules/nixos/services/crowdsec/options.nix
Normal file
@@ -0,0 +1,37 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.crowdsec = {
|
||||
enable = mkEnableOption "crowdsec service";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 9898;
|
||||
description = "Port for crowdsec API";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for crowdsec";
|
||||
};
|
||||
|
||||
apiAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
description = "API address for crowdsec";
|
||||
};
|
||||
|
||||
apiKey = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "API key for crowdsec bouncer";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
description = "Data directory for crowdsec";
|
||||
};
|
||||
};
|
||||
}
|
||||
145
modules/nixos/services/gitea/default.nix
Normal file
145
modules/nixos/services/gitea/default.nix
Normal file
@@ -0,0 +1,145 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.gitea;
|
||||
hostAddress = "10.0.1.3";
|
||||
# localAddress = "10.0.4.18";
|
||||
# httpPort = 3000;
|
||||
# sshPort = 2222;
|
||||
rootUrl = "https://gitea.mjallen.dev/";
|
||||
# stateDir = "/media/nas/main/nix-app-data/gitea";
|
||||
dataDir = "/var/lib/gitea";
|
||||
secretsDir = "/run/secrets/jallen-nas/gitea";
|
||||
mailerPasswordFile = config.sops.secrets."jallen-nas/gitea/mail-key".path;
|
||||
metricsTokenFile = config.sops.secrets."jallen-nas/gitea/metrics-key".path;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
config = mkIf cfg.enable {
|
||||
containers.gitea = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = hostAddress;
|
||||
localAddress = cfg.localAddress;
|
||||
|
||||
bindMounts = {
|
||||
${dataDir} = {
|
||||
hostPath = cfg.dataDir;
|
||||
isReadOnly = false;
|
||||
};
|
||||
secrets = {
|
||||
hostPath = secretsDir;
|
||||
isReadOnly = true;
|
||||
mountPoint = secretsDir;
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
{ lib, ... }:
|
||||
{
|
||||
services.gitea = {
|
||||
enable = true;
|
||||
stateDir = dataDir;
|
||||
mailerPasswordFile = mailerPasswordFile;
|
||||
metricsTokenFile = metricsTokenFile;
|
||||
settings = {
|
||||
server = {
|
||||
DOMAIN = "jallen-nas";
|
||||
HTTP_ADDR = "0.0.0.0";
|
||||
HTTP_PORT = cfg.httpPort;
|
||||
PROTOCOL = "http";
|
||||
ROOT_URL = rootUrl;
|
||||
START_SSH_SERVER = true;
|
||||
SSH_PORT = cfg.sshPort;
|
||||
};
|
||||
service = {
|
||||
REGISTER_EMAIL_CONFIRM = false;
|
||||
ENABLE_CAPTCHA = false;
|
||||
DISABLE_REGISTRATION = true;
|
||||
ENABLE_OPENID_SIGNIN = false;
|
||||
ENABLE_LDAP_SIGNIN = false;
|
||||
ENABLE_SSH_SIGNIN = true;
|
||||
ENABLE_BUILTIN_SSH_SERVER = true;
|
||||
ENABLE_REVERSE_PROXY_AUTHENTICATION = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
users.users.gitea = {
|
||||
extraGroups = [ "keys" ];
|
||||
};
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
cfg.httpPort
|
||||
cfg.sshPort
|
||||
];
|
||||
};
|
||||
# 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.gitea-dirs = ''
|
||||
mkdir -p /var/lib/gitea
|
||||
chown -R gitea:gitea /var/lib/gitea
|
||||
chmod -R 775 /var/lib/gitea
|
||||
mkdir -p /run/secrets/jallen-nas
|
||||
chown -R gitea:gitea /run/secrets/jallen-nas
|
||||
chmod -R 775 /run/secrets/jallen-nas
|
||||
'';
|
||||
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
};
|
||||
|
||||
services.traefik.dynamicConfigOptions = lib.mkIf cfg.reverseProxy.enable {
|
||||
services.gitea.loadBalancer.servers = [
|
||||
{
|
||||
url = "http://${cfg.localAddress}:${toString cfg.httpPort}";
|
||||
}
|
||||
];
|
||||
routers.gitea = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`${cfg.reverseProxy.host}`)";
|
||||
service = "gitea";
|
||||
middlewares = cfg.reverseProxy.middlewares;
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
nat = {
|
||||
forwardPorts = [
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.httpPort}";
|
||||
sourcePort = cfg.httpPort;
|
||||
}
|
||||
{
|
||||
destination = "${cfg.localAddress}:${toString cfg.sshPort}";
|
||||
sourcePort = cfg.sshPort;
|
||||
}
|
||||
];
|
||||
};
|
||||
firewall = {
|
||||
allowedTCPPorts = [
|
||||
cfg.httpPort
|
||||
cfg.sshPort
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
cfg.httpPort
|
||||
cfg.sshPort
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
42
modules/nixos/services/gitea/options.nix
Normal file
42
modules/nixos/services/gitea/options.nix
Normal file
@@ -0,0 +1,42 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.gitea = {
|
||||
enable = mkEnableOption "gitea service";
|
||||
|
||||
httpPort = mkOption {
|
||||
type = types.int;
|
||||
default = 80;
|
||||
};
|
||||
|
||||
sshPort = mkOption {
|
||||
type = types.int;
|
||||
default = 22;
|
||||
};
|
||||
|
||||
localAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "127.0.0.1";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
reverseProxy = {
|
||||
enable = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
host = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
middlewares = mkOption {
|
||||
type = with types; listOf str;
|
||||
default = [ ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
63
modules/nixos/services/glances/default.nix
Normal file
63
modules/nixos/services/glances/default.nix
Normal file
@@ -0,0 +1,63 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.glances;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Open firewall for glances if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
|
||||
# Install glances package
|
||||
environment.systemPackages = with pkgs; [
|
||||
glances
|
||||
];
|
||||
|
||||
# Configure systemd service for glances
|
||||
systemd.services.glances-server = {
|
||||
description = "Glances system monitoring web server";
|
||||
enable = true;
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
after = [ "network.target" ];
|
||||
|
||||
path = with pkgs; [
|
||||
bash
|
||||
glances
|
||||
];
|
||||
|
||||
script = ''
|
||||
glances -w --bind ${cfg.bindAddress} --port ${toString cfg.port}
|
||||
'';
|
||||
|
||||
serviceConfig = {
|
||||
Type = "simple";
|
||||
User = "glances";
|
||||
Group = "glances";
|
||||
Restart = "always";
|
||||
RestartSec = "5";
|
||||
StandardOutput = "journal";
|
||||
StandardError = "journal";
|
||||
};
|
||||
};
|
||||
|
||||
# Create glances user and group
|
||||
users.users.glances = {
|
||||
isSystemUser = true;
|
||||
group = "glances";
|
||||
description = "Glances monitoring user";
|
||||
};
|
||||
|
||||
users.groups.glances = { };
|
||||
};
|
||||
}
|
||||
25
modules/nixos/services/glances/options.nix
Normal file
25
modules/nixos/services/glances/options.nix
Normal file
@@ -0,0 +1,25 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.glances = {
|
||||
enable = mkEnableOption "glances system monitoring service";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 61208;
|
||||
description = "Port for glances web interface";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for glances";
|
||||
};
|
||||
|
||||
bindAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Address to bind glances web server to";
|
||||
};
|
||||
};
|
||||
}
|
||||
38
modules/nixos/services/immich/default.nix
Executable file
38
modules/nixos/services/immich/default.nix
Executable file
@@ -0,0 +1,38 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.immich;
|
||||
|
||||
immichPort = 2283;
|
||||
dataDir = "/media/nas/main/photos";
|
||||
dbPassword = config.sops.secrets."jallen-nas/immich/db-password".path;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Enable immich service
|
||||
services.immich = {
|
||||
enable = true;
|
||||
port = immichPort;
|
||||
openFirewall = true;
|
||||
secretsFile = dbPassword;
|
||||
mediaLocation = dataDir;
|
||||
|
||||
environment = {
|
||||
IMMICH_HOST = lib.mkForce "0.0.0.0";
|
||||
IMMICH_TRUSTED_PROXIES = "10.0.1.3";
|
||||
TZ = "America/Chicago";
|
||||
};
|
||||
|
||||
machine-learning = {
|
||||
enable = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/immich/options.nix
Normal file
7
modules/nixos/services/immich/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.immich = {
|
||||
enable = mkEnableOption "enable immich";
|
||||
};
|
||||
}
|
||||
24
modules/nixos/services/jellyfin/default.nix
Executable file
24
modules/nixos/services/jellyfin/default.nix
Executable file
@@ -0,0 +1,24 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.jellyfin;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.jellyfin = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
user = "nix-apps";
|
||||
group = "jallen-nas";
|
||||
dataDir = "/media/nas/main/nix-app-data/jellyfin";
|
||||
# cacheDir = "/cache";
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/jellyfin/options.nix
Normal file
7
modules/nixos/services/jellyfin/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.jellyfin = {
|
||||
enable = mkEnableOption "enable jellyfin";
|
||||
};
|
||||
}
|
||||
83
modules/nixos/services/jellyseerr/default.nix
Executable file
83
modules/nixos/services/jellyseerr/default.nix
Executable 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;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/jellyseerr/options.nix
Normal file
7
modules/nixos/services/jellyseerr/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.jellyseerr = {
|
||||
enable = mkEnableOption "enable jellyseerr";
|
||||
};
|
||||
}
|
||||
39
modules/nixos/services/lubelogger/default.nix
Normal file
39
modules/nixos/services/lubelogger/default.nix
Normal file
@@ -0,0 +1,39 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.lubelogger;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation.oci-containers.containers.lubelogger = {
|
||||
autoStart = true;
|
||||
image = "ghcr.io/hargata/lubelogger";
|
||||
ports = [ "${toString cfg.port}:8080" ];
|
||||
volumes = [
|
||||
"/media/nas/main/nix-app-data/lubelogger:/App/data"
|
||||
"/media/nas/main/nix-app-data/lubelogger/keys:/root/.aspnet/DataProtection-Keys"
|
||||
];
|
||||
environmentFiles = [
|
||||
"/media/nas/main/nix-app-data/lubelogger/lubelogger.env"
|
||||
];
|
||||
environment = {
|
||||
PUID = toString config.users.users.nix-apps.uid;
|
||||
PGID = toString config.users.groups.jallen-nas.gid;
|
||||
TZ = "America/Chicago";
|
||||
};
|
||||
};
|
||||
|
||||
# Open firewall for lubelogger if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
}
|
||||
19
modules/nixos/services/lubelogger/options.nix
Normal file
19
modules/nixos/services/lubelogger/options.nix
Normal file
@@ -0,0 +1,19 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.lubelogger = {
|
||||
enable = mkEnableOption "enable lubelogger";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 6754;
|
||||
description = "Port for lubelogger web interface";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for lubelogger";
|
||||
};
|
||||
};
|
||||
}
|
||||
45
modules/nixos/services/netbootxyz/default.nix
Normal file
45
modules/nixos/services/netbootxyz/default.nix
Normal file
@@ -0,0 +1,45 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.netbootxyz;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Open firewall for netbootxyz if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [
|
||||
cfg.webPort
|
||||
cfg.assetPort
|
||||
cfg.tftpPort
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
cfg.webPort
|
||||
cfg.assetPort
|
||||
cfg.tftpPort
|
||||
];
|
||||
};
|
||||
|
||||
virtualisation.oci-containers = {
|
||||
containers.netbootxyz = {
|
||||
autoStart = true;
|
||||
image = "ghcr.io/netbootxyz/netbootxyz:latest";
|
||||
ports = [
|
||||
"${toString cfg.webPort}:3000"
|
||||
"${toString cfg.assetPort}:80"
|
||||
"${toString cfg.tftpPort}:69"
|
||||
];
|
||||
volumes = [
|
||||
"${cfg.dataDir}:/config"
|
||||
"${cfg.assetDir}:/assets"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
43
modules/nixos/services/netbootxyz/options.nix
Normal file
43
modules/nixos/services/netbootxyz/options.nix
Normal file
@@ -0,0 +1,43 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.netbootxyz = {
|
||||
enable = mkEnableOption "netbootxyz network boot service";
|
||||
|
||||
webPort = mkOption {
|
||||
type = types.port;
|
||||
default = 4000;
|
||||
description = "HTTP port for netbootxyz";
|
||||
};
|
||||
|
||||
assetPort = mkOption {
|
||||
type = types.port;
|
||||
default = 4001;
|
||||
description = "NGINX server for hosting assets.";
|
||||
};
|
||||
|
||||
tftpPort = mkOption {
|
||||
type = types.port;
|
||||
default = 69;
|
||||
description = "HTTPS port for netbootxyz";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for netbootxyz";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/nas/main/nix-app-data/netbootxyz";
|
||||
description = "Data directory for netbootxyz";
|
||||
};
|
||||
|
||||
assetDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/nas/main/isos";
|
||||
description = "Asset directory for netbootxyz";
|
||||
};
|
||||
};
|
||||
}
|
||||
249
modules/nixos/services/nextcloud/default.nix
Executable file
249
modules/nixos/services/nextcloud/default.nix
Executable file
@@ -0,0 +1,249 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.nextcloud;
|
||||
|
||||
adminpass = config.sops.secrets."jallen-nas/nextcloud/adminpassword".path;
|
||||
secretsFile = config.sops.secrets."jallen-nas/nextcloud/smtp_settings".path;
|
||||
jwtSecretFile = config.sops.secrets."jallen-nas/onlyoffice-key".path;
|
||||
nextcloudUserId = config.users.users.nix-apps.uid;
|
||||
nextcloudGroupId = config.users.groups.jallen-nas.gid;
|
||||
hostAddress = "10.0.1.3";
|
||||
localAddress = "10.0.2.18";
|
||||
nextcloudPortExtHttp = 9988;
|
||||
nextcloudPortExtHttps = 9943;
|
||||
onlyofficePortExt = 9943;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
containers.nextcloud = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = hostAddress;
|
||||
localAddress = localAddress;
|
||||
specialArgs = {
|
||||
inherit namespace;
|
||||
};
|
||||
|
||||
bindMounts = {
|
||||
secrets = {
|
||||
hostPath = "/run/secrets/jallen-nas/nextcloud";
|
||||
isReadOnly = true;
|
||||
mountPoint = "/run/secrets/jallen-nas/nextcloud";
|
||||
};
|
||||
|
||||
secrets2 = {
|
||||
hostPath = "/run/secrets/jallen-nas/onlyoffice-key";
|
||||
isReadOnly = true;
|
||||
mountPoint = "/run/secrets/jallen-nas/onlyoffice-key";
|
||||
};
|
||||
|
||||
data = {
|
||||
hostPath = "/media/nas/main/nextcloud";
|
||||
isReadOnly = false;
|
||||
mountPoint = "/data";
|
||||
};
|
||||
|
||||
"/var/lib/nextcloud" = {
|
||||
hostPath = "/media/nas/main/nix-app-data/nextcloud";
|
||||
isReadOnly = false;
|
||||
mountPoint = "/var/lib/nextcloud";
|
||||
};
|
||||
|
||||
"/var/lib/onlyoffice" = {
|
||||
hostPath = "/media/nas/main/nix-app-data/onlyoffice";
|
||||
isReadOnly = false;
|
||||
mountPoint = "/var/lib/onlyoffice";
|
||||
};
|
||||
};
|
||||
|
||||
config =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
nixpkgs.config.allowUnfree = true;
|
||||
networking.extraHosts = ''
|
||||
${hostAddress} host.containers protonmail-bridge
|
||||
'';
|
||||
|
||||
services = {
|
||||
nextcloud = {
|
||||
enable = true;
|
||||
package = pkgs.nextcloud31;
|
||||
# datadir = "/data";
|
||||
database.createLocally = true;
|
||||
hostName = "cloud.mjallen.dev";
|
||||
appstoreEnable = true;
|
||||
caching.redis = true;
|
||||
configureRedis = true;
|
||||
enableImagemagick = true;
|
||||
https = true;
|
||||
secretFile = secretsFile;
|
||||
|
||||
config = {
|
||||
adminuser = "mjallen";
|
||||
adminpassFile = adminpass;
|
||||
dbhost = "localhost";
|
||||
dbtype = "sqlite";
|
||||
dbname = "nextcloud";
|
||||
dbuser = "nextcloud";
|
||||
};
|
||||
settings = {
|
||||
loglevel = 3;
|
||||
allow_local_remote_servers = true;
|
||||
upgrade.disable-web = false;
|
||||
datadirectory = "/data";
|
||||
trusted_domains = [
|
||||
"${hostAddress}:${toString nextcloudPortExtHttp}"
|
||||
"${hostAddress}:${toString nextcloudPortExtHttps}"
|
||||
"${localAddress}:80"
|
||||
"${localAddress}:443"
|
||||
"cloud.mjallen.dev"
|
||||
];
|
||||
opcache.interned_strings_buffer = 16;
|
||||
trusted_proxies = [ hostAddress ];
|
||||
maintenance_window_start = 6;
|
||||
default_phone_region = "US";
|
||||
enable_previews = true;
|
||||
enabledPreviewProviders = [
|
||||
"OC\\Preview\\PNG"
|
||||
"OC\\Preview\\JPEG"
|
||||
"OC\\Preview\\GIF"
|
||||
"OC\\Preview\\BMP"
|
||||
"OC\\Preview\\XBitmap"
|
||||
"OC\\Preview\\MP3"
|
||||
"OC\\Preview\\TXT"
|
||||
"OC\\Preview\\MarkDown"
|
||||
"OC\\Preview\\OpenDocument"
|
||||
"OC\\Preview\\Krita"
|
||||
"OC\\Preview\\HEIC"
|
||||
"OC\\Preview\\Movie"
|
||||
"OC\\Preview\\MSOffice2003"
|
||||
"OC\\Preview\\MSOffice2007"
|
||||
"OC\\Preview\\MSOfficeDoc"
|
||||
];
|
||||
installed = true;
|
||||
user_oidc = {
|
||||
auto_provision = false;
|
||||
soft_auto_provision = false;
|
||||
allow_multiple_user_backends = false; # auto redirect to authentik for login
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services.onlyoffice = {
|
||||
enable = true;
|
||||
port = onlyofficePortExt;
|
||||
hostname = "office.mjallen.dev";
|
||||
jwtSecretFile = jwtSecretFile;
|
||||
};
|
||||
|
||||
# System packages
|
||||
environment.systemPackages = with pkgs; [
|
||||
cudaPackages.cudnn
|
||||
cudatoolkit
|
||||
ffmpeg
|
||||
# libtensorflow-bin
|
||||
nextcloud31
|
||||
nodejs
|
||||
onlyoffice-documentserver
|
||||
sqlite
|
||||
];
|
||||
|
||||
# Create required users and groups
|
||||
users.users.nextcloud = {
|
||||
isSystemUser = true;
|
||||
uid = lib.mkForce nextcloudUserId;
|
||||
group = "nextcloud";
|
||||
};
|
||||
|
||||
users.users.onlyoffice = {
|
||||
group = lib.mkForce "nextcloud";
|
||||
};
|
||||
|
||||
users.groups = {
|
||||
nextcloud = {
|
||||
gid = lib.mkForce nextcloudGroupId;
|
||||
};
|
||||
downloads = { };
|
||||
};
|
||||
|
||||
# Create and set permissions for required directories
|
||||
system.activationScripts.nextcloud-dirs = ''
|
||||
mkdir -p /data
|
||||
|
||||
chown -R nextcloud:nextcloud /data
|
||||
|
||||
chown -R nextcloud:nextcloud /run/secrets/jallen-nas/nextcloud
|
||||
|
||||
chmod -R 775 /data
|
||||
|
||||
chmod -R 750 /run/secrets/jallen-nas/nextcloud
|
||||
|
||||
'';
|
||||
|
||||
hardware = {
|
||||
graphics = {
|
||||
enable = true;
|
||||
# setLdLibraryPath = true;
|
||||
};
|
||||
};
|
||||
|
||||
programs = {
|
||||
nix-ld.enable = true;
|
||||
};
|
||||
|
||||
system.stateVersion = "23.11";
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [
|
||||
80
|
||||
443
|
||||
onlyofficePortExt
|
||||
];
|
||||
};
|
||||
# Use systemd-resolved inside the container
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = lib.mkForce false;
|
||||
};
|
||||
services.resolved.enable = true;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
networking = {
|
||||
nat = {
|
||||
forwardPorts = [
|
||||
{
|
||||
destination = "${localAddress}:443";
|
||||
sourcePort = nextcloudPortExtHttps;
|
||||
}
|
||||
{
|
||||
destination = "${localAddress}:80";
|
||||
sourcePort = nextcloudPortExtHttp;
|
||||
}
|
||||
{
|
||||
destination = "${localAddress}:8000";
|
||||
sourcePort = 8000;
|
||||
}
|
||||
{
|
||||
destination = "${localAddress}:${toString onlyofficePortExt}";
|
||||
sourcePort = onlyofficePortExt;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/nextcloud/options.nix
Normal file
7
modules/nixos/services/nextcloud/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.nextcloud = {
|
||||
enable = mkEnableOption "enable nextcloud";
|
||||
};
|
||||
}
|
||||
30
modules/nixos/services/orca/default.nix
Normal file
30
modules/nixos/services/orca/default.nix
Normal file
@@ -0,0 +1,30 @@
|
||||
{
|
||||
lib,
|
||||
config,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.orca-slicer;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
virtualisation.oci-containers.containers."${cfg.name}" = {
|
||||
autoStart = cfg.autoStart;
|
||||
image = cfg.image;
|
||||
ports = [
|
||||
"${cfg.httpPort}:3000"
|
||||
"${cfg.httpsPort}:3001"
|
||||
];
|
||||
volumes = [ "${cfg.configPath}:/config" ];
|
||||
environment = {
|
||||
PUID = cfg.puid;
|
||||
PGID = cfg.pgid;
|
||||
TZ = cfg.timeZone;
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
57
modules/nixos/services/orca/options.nix
Normal file
57
modules/nixos/services/orca/options.nix
Normal file
@@ -0,0 +1,57 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.orca-slicer = {
|
||||
enable = mkEnableOption "orca slicer docker service";
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
|
||||
httpPort = mkOption {
|
||||
type = types.str;
|
||||
default = "3000";
|
||||
};
|
||||
|
||||
httpsPort = mkOption {
|
||||
type = types.str;
|
||||
default = "3001";
|
||||
};
|
||||
|
||||
name = mkOption {
|
||||
type = types.str;
|
||||
default = "orca-slicer";
|
||||
};
|
||||
|
||||
image = mkOption {
|
||||
type = types.str;
|
||||
default = "linuxserver/orcaslicer";
|
||||
};
|
||||
|
||||
configPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/nas/main/ssd_app_data/orca-slicer";
|
||||
};
|
||||
|
||||
dataPath = mkOption {
|
||||
type = types.str;
|
||||
default = "/media/nas/main/3d_printer";
|
||||
};
|
||||
|
||||
puid = mkOption {
|
||||
type = types.str;
|
||||
default = "911";
|
||||
};
|
||||
|
||||
pgid = mkOption {
|
||||
type = types.str;
|
||||
default = "1000";
|
||||
};
|
||||
|
||||
timeZone = mkOption {
|
||||
type = types.str;
|
||||
default = "America/Chicago";
|
||||
};
|
||||
};
|
||||
}
|
||||
110
modules/nixos/services/paperless/default.nix
Executable file
110
modules/nixos/services/paperless/default.nix
Executable file
@@ -0,0 +1,110 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.paperless;
|
||||
|
||||
paperlessPort = 28981;
|
||||
paperlessUserId = config.users.users.nix-apps.uid;
|
||||
paperlessGroupId = config.users.groups.jallen-nas.gid;
|
||||
paperlessPkg = pkgs.paperless-ngx;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
containers.paperless = {
|
||||
autoStart = true;
|
||||
privateNetwork = true;
|
||||
hostAddress = "10.0.1.3";
|
||||
localAddress = "10.0.1.20";
|
||||
hostAddress6 = "fc00::1";
|
||||
localAddress6 = "fc00::20";
|
||||
|
||||
config =
|
||||
{
|
||||
lib,
|
||||
...
|
||||
}:
|
||||
{
|
||||
# Enable paperless service
|
||||
services.paperless = {
|
||||
enable = false;
|
||||
package = paperlessPkg;
|
||||
port = paperlessPort;
|
||||
user = "paperless";
|
||||
address = "0.0.0.0";
|
||||
passwordFile = "/var/lib/paperless/paperless-password";
|
||||
# environmentFile = paperlessEnv; # unstable is too unstable, but this doesnt exist in stable.... disabling altogether....
|
||||
};
|
||||
|
||||
# Create required users and groups
|
||||
users.groups = {
|
||||
documents = {
|
||||
gid = lib.mkForce paperlessGroupId;
|
||||
};
|
||||
};
|
||||
|
||||
users.users.paperless = {
|
||||
isSystemUser = true;
|
||||
uid = lib.mkForce paperlessUserId;
|
||||
group = lib.mkForce "documents";
|
||||
};
|
||||
|
||||
# Create and set permissions for required directories
|
||||
system.activationScripts.paperless-dirs = ''
|
||||
mkdir -p /var/lib/paperless
|
||||
|
||||
chown -R paperless:documents /var/lib/paperless
|
||||
|
||||
chmod -R 775 /var/lib/paperless
|
||||
|
||||
'';
|
||||
|
||||
networking = {
|
||||
firewall = {
|
||||
enable = true;
|
||||
allowedTCPPorts = [ paperlessPort ];
|
||||
};
|
||||
# Use systemd-resolved inside the container
|
||||
# Workaround for bug https://github.com/NixOS/nixpkgs/issues/162686
|
||||
useHostResolvConf = lib.mkForce false;
|
||||
};
|
||||
|
||||
services.resolved.enable = true;
|
||||
system.stateVersion = "23.11";
|
||||
};
|
||||
|
||||
# Bind mount directories from host
|
||||
bindMounts = {
|
||||
"/var/lib/paperless" = {
|
||||
hostPath = "/media/nas/main/nix-app-data/paperless";
|
||||
isReadOnly = false;
|
||||
};
|
||||
secrets = {
|
||||
hostPath = "/run/secrets/jallen-nas/paperless";
|
||||
isReadOnly = true;
|
||||
mountPoint = "/run/secrets/jallen-nas/paperless";
|
||||
};
|
||||
secret-env = {
|
||||
hostPath = "/run/secrets/rendered/paperless.env";
|
||||
isReadOnly = true;
|
||||
mountPoint = "/run/secrets/rendered/paperless.env";
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.nat = {
|
||||
forwardPorts = [
|
||||
{
|
||||
destination = "10.0.1.20:28981";
|
||||
sourcePort = paperlessPort;
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/paperless/options.nix
Normal file
7
modules/nixos/services/paperless/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.paperless = {
|
||||
enable = mkEnableOption "enable paperless";
|
||||
};
|
||||
}
|
||||
65
modules/nixos/services/protonmail-bridge/default.nix
Normal file
65
modules/nixos/services/protonmail-bridge/default.nix
Normal file
@@ -0,0 +1,65 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
pkgs,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.protonmail-bridge;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Open firewall for protonmail bridge if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [
|
||||
cfg.smtpPort
|
||||
cfg.imapPort
|
||||
];
|
||||
allowedUDPPorts = [
|
||||
cfg.smtpPort
|
||||
cfg.imapPort
|
||||
];
|
||||
};
|
||||
|
||||
# Install protonmail-bridge package
|
||||
environment.systemPackages = with pkgs; [
|
||||
protonmail-bridge
|
||||
gnome-keyring
|
||||
gnupg
|
||||
pass
|
||||
];
|
||||
|
||||
# Configure systemd user service for protonmail-bridge
|
||||
systemd.user.services.protonmail-bridge = {
|
||||
description = "Protonmail Bridge";
|
||||
enable = true;
|
||||
environment = {
|
||||
GNUPGHOME = "%h/.gnupg";
|
||||
PASSWORD_STORE_DIR = "%h/.password-store";
|
||||
};
|
||||
script = "${pkgs.protonmail-bridge}/bin/protonmail-bridge --noninteractive";
|
||||
path = with pkgs; [
|
||||
gnome-keyring
|
||||
gnupg
|
||||
pass
|
||||
protonmail-bridge
|
||||
];
|
||||
wantedBy = [ "default.target" ];
|
||||
after = [ "gpg-agent.service" ];
|
||||
};
|
||||
|
||||
# Enable gnome keyring for password storage
|
||||
security.pam.services.login.enableGnomeKeyring = true;
|
||||
services.gnome.gnome-keyring.enable = true;
|
||||
|
||||
# Configure gpg-agent
|
||||
programs.gnupg.agent = {
|
||||
enable = true;
|
||||
enableSSHSupport = true;
|
||||
};
|
||||
};
|
||||
}
|
||||
31
modules/nixos/services/protonmail-bridge/options.nix
Normal file
31
modules/nixos/services/protonmail-bridge/options.nix
Normal file
@@ -0,0 +1,31 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.protonmail-bridge = {
|
||||
enable = mkEnableOption "protonmail bridge service";
|
||||
|
||||
smtpPort = mkOption {
|
||||
type = types.port;
|
||||
default = 1025;
|
||||
description = "SMTP port for protonmail bridge";
|
||||
};
|
||||
|
||||
imapPort = mkOption {
|
||||
type = types.port;
|
||||
default = 1143;
|
||||
description = "IMAP port for protonmail bridge";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for protonmail bridge";
|
||||
};
|
||||
|
||||
user = mkOption {
|
||||
type = types.str;
|
||||
default = "admin";
|
||||
description = "User to run protonmail bridge as";
|
||||
};
|
||||
};
|
||||
}
|
||||
33
modules/nixos/services/restic/default.nix
Normal file
33
modules/nixos/services/restic/default.nix
Normal file
@@ -0,0 +1,33 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.restic;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# Configure the standard NixOS restic server service
|
||||
services.restic.server = {
|
||||
enable = true;
|
||||
dataDir = cfg.dataDir;
|
||||
prometheus = cfg.prometheus;
|
||||
listenAddress = "${cfg.listenAddress}:${toString cfg.port}";
|
||||
extraFlags = cfg.extraFlags;
|
||||
}
|
||||
// optionalAttrs (cfg.htpasswdFile != null) {
|
||||
htpasswd-file = cfg.htpasswdFile;
|
||||
};
|
||||
|
||||
# Open firewall for restic server if enabled
|
||||
networking.firewall = mkIf cfg.openFirewall {
|
||||
allowedTCPPorts = [ cfg.port ];
|
||||
allowedUDPPorts = [ cfg.port ];
|
||||
};
|
||||
};
|
||||
}
|
||||
49
modules/nixos/services/restic/options.nix
Normal file
49
modules/nixos/services/restic/options.nix
Normal file
@@ -0,0 +1,49 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.restic = {
|
||||
enable = mkEnableOption "restic server with enhanced configuration";
|
||||
|
||||
port = mkOption {
|
||||
type = types.port;
|
||||
default = 8008;
|
||||
description = "Port for restic server";
|
||||
};
|
||||
|
||||
openFirewall = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to open firewall for restic server";
|
||||
};
|
||||
|
||||
dataDir = mkOption {
|
||||
type = types.str;
|
||||
default = "/var/lib/restic";
|
||||
description = "Data directory for restic server";
|
||||
};
|
||||
|
||||
listenAddress = mkOption {
|
||||
type = types.str;
|
||||
default = "0.0.0.0";
|
||||
description = "Address to bind restic server to";
|
||||
};
|
||||
|
||||
prometheus = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
description = "Whether to enable prometheus metrics";
|
||||
};
|
||||
|
||||
htpasswdFile = mkOption {
|
||||
type = types.nullOr types.str;
|
||||
default = null;
|
||||
description = "Path to htpasswd file for authentication";
|
||||
};
|
||||
|
||||
extraFlags = mkOption {
|
||||
type = types.listOf types.str;
|
||||
default = [ ];
|
||||
description = "Extra flags to pass to restic server";
|
||||
};
|
||||
};
|
||||
}
|
||||
58
modules/nixos/services/samba/default.nix
Executable file
58
modules/nixos/services/samba/default.nix
Executable file
@@ -0,0 +1,58 @@
|
||||
{ lib, config, ... }:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.nas-samba;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
# make shares visible for Windows clients
|
||||
services.samba-wsdd = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
};
|
||||
|
||||
services.netatalk = {
|
||||
enable = cfg.enableTimeMachine;
|
||||
settings = {
|
||||
time-machine = {
|
||||
path = cfg.timeMachinePath;
|
||||
"valid users" = "whoever";
|
||||
"time machine" = cfg.enableTimeMachine;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall.enable = true;
|
||||
networking.firewall.allowPing = true;
|
||||
|
||||
services.samba = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
nsswins = true;
|
||||
nmbd.enable = true;
|
||||
settings =
|
||||
let
|
||||
make =
|
||||
name: share:
|
||||
nameValuePair "${name}" {
|
||||
path = share.sharePath;
|
||||
public = if share.enableTimeMachine then "no" else "yes";
|
||||
browseable = if share.browseable then "yes" else "no";
|
||||
writable = "yes";
|
||||
"force group" = "jallen-nas";
|
||||
"read only" = if share.readOnly then "yes" else "no";
|
||||
"guest ok" = if share.guestOk then "yes" else "no";
|
||||
"create mask" = share.createMask;
|
||||
"directory mask" = share.directoryMask;
|
||||
"fruit:aapl" = if share.enableTimeMachine then "yes" else "no";
|
||||
"fruit:time machine" = if share.enableTimeMachine then "yes" else "no";
|
||||
"vfs objects" = "catia fruit streams_xattr";
|
||||
"fruit:time machine max size" = share.timeMachineMaxSize;
|
||||
};
|
||||
in
|
||||
mapAttrs' make cfg.shares;
|
||||
};
|
||||
};
|
||||
}
|
||||
70
modules/nixos/services/samba/options.nix
Executable file
70
modules/nixos/services/samba/options.nix
Executable file
@@ -0,0 +1,70 @@
|
||||
{ lib, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.nas-samba = {
|
||||
enable = mkEnableOption "nas samba service";
|
||||
|
||||
autoStart = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
enableTimeMachine = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
timeMachinePath = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
hostsAllow = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
|
||||
shares = mkOption {
|
||||
type = types.attrsOf (
|
||||
types.submodule {
|
||||
options = {
|
||||
public = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
sharePath = mkOption {
|
||||
type = types.str;
|
||||
default = "";
|
||||
};
|
||||
readOnly = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
browseable = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
guestOk = mkOption {
|
||||
type = types.bool;
|
||||
default = true;
|
||||
};
|
||||
createMask = mkOption {
|
||||
type = types.str;
|
||||
default = "0774";
|
||||
};
|
||||
directoryMask = mkOption {
|
||||
type = types.str;
|
||||
default = "0775";
|
||||
};
|
||||
enableTimeMachine = mkOption {
|
||||
type = types.bool;
|
||||
default = false;
|
||||
};
|
||||
timeMachineMaxSize = mkOption {
|
||||
type = types.str;
|
||||
default = "0K";
|
||||
};
|
||||
};
|
||||
}
|
||||
);
|
||||
default = { };
|
||||
};
|
||||
};
|
||||
}
|
||||
455
modules/nixos/services/traefik/default.nix
Executable file
455
modules/nixos/services/traefik/default.nix
Executable file
@@ -0,0 +1,455 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.traefik;
|
||||
|
||||
domain = "mjallen.dev";
|
||||
serverIp = "10.0.1.3";
|
||||
|
||||
# Forward services
|
||||
authUrl = "http://${serverIp}:9000/outpost.goauthentik.io";
|
||||
|
||||
actualUrl = "http://${config.containers.actual.localAddress}:${toString config.containers.actual.config.services.actual.settings.port}";
|
||||
authentikUrl = "http://${serverIp}:9000";
|
||||
cacheUrl = "http://${serverIp}:9012";
|
||||
cloudUrl = "http://${config.containers.nextcloud.localAddress}:80";
|
||||
giteaUrl = "http://${config.containers.gitea.localAddress}:${toString config.containers.gitea.config.services.gitea.settings.server.HTTP_PORT}";
|
||||
hassUrl = "http://nuc-nixos.local:8123";
|
||||
immichUrl = "http://${serverIp}:${toString config.services.immich.port}";
|
||||
jellyfinUrl = "http://${serverIp}:8096";
|
||||
jellyseerrUrl = "http://${config.containers.jellyseerr.localAddress}:${toString config.containers.jellyseerr.config.services.jellyseerr.port}";
|
||||
lubeloggerUrl = "http://${serverIp}:6754";
|
||||
onlyofficeUrl = "http://${config.containers.nextcloud.localAddress}:${toString config.containers.nextcloud.config.services.onlyoffice.port}";
|
||||
openWebUIUrl = "http://${serverIp}:8888";
|
||||
paperlessUrl = "http://${config.containers.paperless.localAddress}:${toString config.containers.paperless.config.services.paperless.port}";
|
||||
|
||||
# Plugins
|
||||
traefikPlugins = {
|
||||
bouncer = {
|
||||
moduleName = "github.com/maxlerebourg/crowdsec-bouncer-traefik-plugin";
|
||||
version = "v1.4.2";
|
||||
};
|
||||
geoblock = {
|
||||
moduleName = "github.com/PascalMinder/geoblock";
|
||||
version = "v0.2.5";
|
||||
};
|
||||
};
|
||||
|
||||
crowdsecAppsecHost = "${serverIp}:7422";
|
||||
crowdsecLapiKeyFile = config.sops.secrets."jallen-nas/traefik/crowdsec-lapi-key".path;
|
||||
|
||||
# Ports
|
||||
httpPort = 80;
|
||||
httpsPort = 443;
|
||||
traefikPort = 8080;
|
||||
metricsPort = 8082;
|
||||
|
||||
forwardPorts = [
|
||||
httpPort
|
||||
httpsPort
|
||||
traefikPort
|
||||
metricsPort
|
||||
];
|
||||
|
||||
# misc
|
||||
letsEncryptEmail = "jalle008@proton.me";
|
||||
dataDir = "/media/nas/main/nix-app-data/traefik";
|
||||
authentikAddress = "http://${serverIp}:9000/outpost.goauthentik.io/auth/traefik";
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
sops = {
|
||||
secrets = {
|
||||
"jallen-nas/traefik/crowdsec-lapi-key" = {
|
||||
sopsFile = (lib.snowfall.fs.get-file "secrets/nas-secrets.yaml");
|
||||
owner = config.users.users.traefik.name;
|
||||
group = config.users.users.traefik.group;
|
||||
restartUnits = [ "traefik.service" ];
|
||||
};
|
||||
"jallen-nas/traefik/cloudflare-dns-api-token" = {
|
||||
sopsFile = (lib.snowfall.fs.get-file "secrets/nas-secrets.yaml");
|
||||
};
|
||||
"jallen-nas/traefik/cloudflare-zone-api-token" = {
|
||||
sopsFile = (lib.snowfall.fs.get-file "secrets/nas-secrets.yaml");
|
||||
};
|
||||
"jallen-nas/traefik/cloudflare-api-key" = {
|
||||
sopsFile = (lib.snowfall.fs.get-file "secrets/nas-secrets.yaml");
|
||||
};
|
||||
"jallen-nas/traefik/cloudflare-email" = {
|
||||
sopsFile = (lib.snowfall.fs.get-file "secrets/nas-secrets.yaml");
|
||||
};
|
||||
};
|
||||
templates = {
|
||||
"traefik.env" = {
|
||||
content = ''
|
||||
CLOUDFLARE_DNS_API_TOKEN = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-dns-api-token"}
|
||||
CLOUDFLARE_ZONE_API_TOKEN = ${
|
||||
config.sops.placeholder."jallen-nas/traefik/cloudflare-zone-api-token"
|
||||
}
|
||||
CLOUDFLARE_API_KEY = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-api-key"}
|
||||
CLOUDFLARE_EMAIL = ${config.sops.placeholder."jallen-nas/traefik/cloudflare-email"}
|
||||
'';
|
||||
owner = config.users.users.traefik.name;
|
||||
group = config.users.users.traefik.group;
|
||||
restartUnits = [ "traefik.service" ];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
networking.firewall = {
|
||||
allowedTCPPorts = forwardPorts;
|
||||
allowedUDPPorts = forwardPorts;
|
||||
};
|
||||
|
||||
services.traefik = {
|
||||
enable = true;
|
||||
dataDir = dataDir;
|
||||
group = "jallen-nas"; # group;
|
||||
environmentFiles = [ "${config.services.traefik.dataDir}/traefik.env" ]; # todo: sops
|
||||
|
||||
staticConfigOptions = {
|
||||
entryPoints = {
|
||||
web = {
|
||||
address = ":${toString httpPort}";
|
||||
asDefault = true;
|
||||
http.redirections.entrypoint = {
|
||||
to = "websecure";
|
||||
scheme = "https";
|
||||
};
|
||||
};
|
||||
|
||||
websecure = {
|
||||
address = ":${toString httpsPort}";
|
||||
asDefault = true;
|
||||
http.tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
metrics = {
|
||||
address = ":${toString metricsPort}"; # Port for metrics
|
||||
};
|
||||
};
|
||||
|
||||
log = {
|
||||
level = "INFO";
|
||||
};
|
||||
|
||||
metrics = {
|
||||
prometheus = {
|
||||
entryPoint = "metrics";
|
||||
addEntryPointsLabels = true;
|
||||
addServicesLabels = true;
|
||||
buckets = [
|
||||
0.1
|
||||
0.3
|
||||
1.2
|
||||
5.0
|
||||
]; # Response time buckets
|
||||
};
|
||||
};
|
||||
|
||||
certificatesResolvers.letsencrypt.acme = {
|
||||
email = letsEncryptEmail;
|
||||
storage = "${config.services.traefik.dataDir}/acme.json";
|
||||
dnsChallenge = {
|
||||
provider = "cloudflare";
|
||||
resolvers = [
|
||||
"1.1.1.1:53"
|
||||
"8.8.8.8:53"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
api.dashboard = true;
|
||||
# Access the Traefik dashboard on <Traefik IP>:8080 of your server
|
||||
api.insecure = true;
|
||||
|
||||
experimental = {
|
||||
plugins = traefikPlugins;
|
||||
};
|
||||
};
|
||||
|
||||
dynamicConfigOptions = {
|
||||
http = {
|
||||
middlewares = {
|
||||
authentik = {
|
||||
forwardAuth = {
|
||||
tls.insecureSkipVerify = true;
|
||||
address = authentikAddress;
|
||||
trustForwardHeader = true;
|
||||
authResponseHeaders = [
|
||||
"X-authentik-username"
|
||||
"X-authentik-groups"
|
||||
"X-authentik-email"
|
||||
"X-authentik-name"
|
||||
"X-authentik-uid"
|
||||
"X-authentik-jwt"
|
||||
"X-authentik-meta-jwks"
|
||||
"X-authentik-meta-outpost"
|
||||
"X-authentik-meta-provider"
|
||||
"X-authentik-meta-app"
|
||||
"X-authentik-meta-version"
|
||||
];
|
||||
};
|
||||
};
|
||||
onlyoffice-websocket = {
|
||||
headers.customrequestheaders = {
|
||||
X-Forwarded-Proto = "https";
|
||||
};
|
||||
};
|
||||
crowdsec = {
|
||||
plugin = {
|
||||
bouncer = {
|
||||
crowdsecAppsecEnabled = true;
|
||||
crowdsecAppsecHost = crowdsecAppsecHost;
|
||||
crowdsecAppsecFailureBlock = true;
|
||||
crowdsecAppsecUnreachableBlock = true;
|
||||
crowdsecLapiKeyFile = crowdsecLapiKeyFile;
|
||||
};
|
||||
};
|
||||
};
|
||||
whitelist-geoblock = {
|
||||
plugin = {
|
||||
geoblock = {
|
||||
silentStartUp = false;
|
||||
allowLocalRequests = true;
|
||||
logLocalRequests = false;
|
||||
logAllowedRequests = false;
|
||||
logApiRequests = false;
|
||||
api = "https://get.geojs.io/v1/ip/country/{ip}";
|
||||
apiTimeoutMs = 500;
|
||||
cacheSize = 25;
|
||||
forceMonthlyUpdate = true;
|
||||
allowUnknownCountries = false;
|
||||
unknownCountryApiResponse = "nil";
|
||||
blackListMode = false;
|
||||
countries = [
|
||||
"CA"
|
||||
"US"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
internal-ipallowlist = {
|
||||
ipAllowList = {
|
||||
sourceRange = [
|
||||
"127.0.0.1/32"
|
||||
"10.0.1.0/24"
|
||||
];
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
services = {
|
||||
auth.loadBalancer.servers = [
|
||||
{
|
||||
url = authUrl;
|
||||
}
|
||||
];
|
||||
|
||||
actual.loadBalancer.servers = [
|
||||
{
|
||||
url = actualUrl;
|
||||
}
|
||||
];
|
||||
authentik.loadBalancer.servers = [
|
||||
{
|
||||
url = authentikUrl;
|
||||
}
|
||||
];
|
||||
cache.loadBalancer.servers = [
|
||||
{
|
||||
url = cacheUrl;
|
||||
}
|
||||
];
|
||||
chat.loadBalancer.servers = [
|
||||
{
|
||||
url = openWebUIUrl;
|
||||
}
|
||||
];
|
||||
cloud.loadBalancer.servers = [
|
||||
{
|
||||
url = cloudUrl;
|
||||
}
|
||||
];
|
||||
gitea.loadBalancer.servers = [
|
||||
{
|
||||
url = giteaUrl;
|
||||
}
|
||||
];
|
||||
hass.loadBalancer.servers = [
|
||||
{
|
||||
url = hassUrl;
|
||||
}
|
||||
];
|
||||
immich.loadBalancer.servers = [
|
||||
{
|
||||
url = immichUrl;
|
||||
}
|
||||
];
|
||||
jellyfin.loadBalancer.servers = [
|
||||
{
|
||||
url = jellyfinUrl;
|
||||
}
|
||||
];
|
||||
jellyseerr.loadBalancer.servers = [
|
||||
{
|
||||
url = jellyseerrUrl;
|
||||
}
|
||||
];
|
||||
lubelogger.loadBalancer.servers = [
|
||||
{
|
||||
url = lubeloggerUrl;
|
||||
}
|
||||
];
|
||||
onlyoffice.loadBalancer.servers = [
|
||||
{
|
||||
url = onlyofficeUrl;
|
||||
}
|
||||
];
|
||||
paperless.loadBalancer.servers = [
|
||||
{
|
||||
url = paperlessUrl;
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
routers = {
|
||||
auth = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "HostRegexp(`{subdomain:[a-z]+}.mjallen.dev`) && PathPrefix(`/outpost.goauthentik.io/`)";
|
||||
service = "auth";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
priority = 15;
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
|
||||
actual = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`actual.${domain}`)";
|
||||
service = "actual";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
authentik = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`authentik.${domain}`)";
|
||||
service = "authentik";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
cache = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`cache.${domain}`)";
|
||||
service = "cache";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
priority = 10;
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
cloud = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`cloud.${domain}`)";
|
||||
service = "cloud";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
gitea = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`gitea.${domain}`)";
|
||||
service = "gitea";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
hass = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`hass.${domain}`)";
|
||||
service = "hass";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"authentik"
|
||||
];
|
||||
priority = 10;
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
immich = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`immich.${domain}`)";
|
||||
service = "immich";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
jellyfin = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`jellyfin.${domain}`)";
|
||||
service = "jellyfin";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
jellyseerr = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`jellyseerr.${domain}`)";
|
||||
service = "jellyseerr";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
lubelogger = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`lubelogger.${domain}`)";
|
||||
service = "lubelogger";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
onlyoffice = {
|
||||
entryPoints = [ "websecure" ];
|
||||
rule = "Host(`office.${domain}`)";
|
||||
service = "onlyoffice";
|
||||
middlewares = [
|
||||
"crowdsec"
|
||||
"whitelist-geoblock"
|
||||
"onlyoffice-websocket"
|
||||
];
|
||||
tls.certResolver = "letsencrypt";
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/traefik/options.nix
Normal file
7
modules/nixos/services/traefik/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.traefik = {
|
||||
enable = mkEnableOption "enable traefik";
|
||||
};
|
||||
}
|
||||
32
modules/nixos/services/wyoming/default.nix
Executable file
32
modules/nixos/services/wyoming/default.nix
Executable file
@@ -0,0 +1,32 @@
|
||||
{
|
||||
config,
|
||||
lib,
|
||||
namespace,
|
||||
...
|
||||
}:
|
||||
with lib;
|
||||
let
|
||||
cfg = config.${namespace}.services.wyoming;
|
||||
in
|
||||
{
|
||||
imports = [ ./options.nix ];
|
||||
|
||||
config = mkIf cfg.enable {
|
||||
services.wyoming = {
|
||||
faster-whisper.servers.hass-whisper = {
|
||||
enable = true;
|
||||
useTransformers = false;
|
||||
device = lib.mkForce "cuda";
|
||||
language = "en";
|
||||
model = "distil-large-v3";
|
||||
uri = "tcp://0.0.0.0:10300";
|
||||
};
|
||||
|
||||
piper.servers.hass-piper = {
|
||||
enable = true;
|
||||
voice = "en-us-ryan-high";
|
||||
uri = "tcp://0.0.0.0:10200";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
7
modules/nixos/services/wyoming/options.nix
Normal file
7
modules/nixos/services/wyoming/options.nix
Normal file
@@ -0,0 +1,7 @@
|
||||
{ lib, namespace, ... }:
|
||||
with lib;
|
||||
{
|
||||
options.${namespace}.services.wyoming = {
|
||||
enable = mkEnableOption "enable wyoming";
|
||||
};
|
||||
}
|
||||
Reference in New Issue
Block a user