This commit is contained in:
mjallen18
2025-08-23 10:26:12 -05:00
parent a96b8ddf86
commit bc18b0775b
43 changed files with 796 additions and 177 deletions

View File

@@ -0,0 +1,132 @@
{
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-desktop = {
enable = true;
description = "Rebuild desktop 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 "Starting build of matt-nixos at $(date)"
if nix flake update desktop-nixpkgs desktop-chaotic desktop-home-manager desktop-impermanence desktop-lanzaboote desktop-nixos-hardware desktop-sops-nix desktop-steam-rom-manager nixpkgs-unstable nixpkgs-stable nix-darwin; then
echo "matt-nixos flake updated successfully at $(date)"
else
echo "matt-nixos failed to build at $(date)"
fi
if nix build .\#nixosConfigurations.matt-nixos.config.system.build.toplevel --no-link; then
echo "matt-nixos built successfully at $(date)"
git add .
git commit -m "Desktop Updates $(date)"
else
echo "matt-nixos failed to build at $(date)"
git reset --hard
fi
'';
};
};
# Include timers for cache rebuilds
systemd.timers = {
nix-rebuild-cache-desktop = {
description = "Timer for rebuilding desktop 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"
];
}
];
};
};
}

View 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";
};
};
}

View 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;
};
};
}

View 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";
};
};
}

View 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 ];
};
};
}

View 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";
};
};
}

View File

@@ -58,11 +58,9 @@ in
[ "${script}/bin/register-bouncer" ];
};
networking = {
firewall = {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
};
}

View File

@@ -5,23 +5,33 @@ with lib;
enable = mkEnableOption "crowdsec service";
port = mkOption {
type = types.int;
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";
};
};
}

View 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 = { };
};
}

View 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";
};
};
}

View File

@@ -15,7 +15,7 @@ in
virtualisation.oci-containers.containers.lubelogger = {
autoStart = true;
image = "ghcr.io/hargata/lubelogger";
ports = [ "6754:8080" ];
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"
@@ -29,5 +29,11 @@ in
TZ = "America/Chicago";
};
};
# Open firewall for lubelogger if enabled
networking.firewall = mkIf cfg.openFirewall {
allowedTCPPorts = [ cfg.port ];
allowedUDPPorts = [ cfg.port ];
};
};
}

View File

@@ -3,5 +3,17 @@ 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";
};
};
}

View File

@@ -0,0 +1,57 @@
{
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.httpPort
cfg.httpsPort
];
allowedUDPPorts = [
cfg.httpPort
cfg.httpsPort
];
};
# Create data directory
systemd.tmpfiles.rules = [
"d ${cfg.dataDir} 0755 root root -"
];
# Configure netbootxyz as a container service
virtualisation.oci-containers = {
backend = "podman";
containers.netbootxyz = {
image = "ghcr.io/netbootxyz/netbootxyz:latest";
ports = [
"${toString cfg.httpPort}:3000"
"${toString cfg.httpsPort}:3001"
];
volumes = [
"${cfg.dataDir}:/app/src/config"
];
environment = {
MENU_VERSION = "2.0.76";
PORT_RANGE = "30000:30010";
};
extraOptions = [
"--restart=unless-stopped"
];
};
};
# Enable podman for oci-containers
virtualisation.podman.enable = true;
};
}

View File

@@ -0,0 +1,31 @@
{ lib, namespace, ... }:
with lib;
{
options.${namespace}.services.netbootxyz = {
enable = mkEnableOption "netbootxyz network boot service";
httpPort = mkOption {
type = types.port;
default = 4000;
description = "HTTP port for netbootxyz";
};
httpsPort = mkOption {
type = types.port;
default = 4080;
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 = "/var/lib/netbootxyz";
description = "Data directory for netbootxyz";
};
};
}

View 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;
};
};
}

View 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";
};
};
}

View 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 ];
};
};
}

View 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";
};
};
}