test restructure

This commit is contained in:
2026-05-02 17:43:53 -05:00
parent 6fdc826b2a
commit 7302648b57
59 changed files with 3151 additions and 25 deletions
@@ -0,0 +1,89 @@
{
config,
lib,
pkgs,
...
}:
/*
to restore mysql/marinadb database:
mysql -u root -p -e "DROP DATABASE IF EXISTS <database_name>;" # delete old db if still lingering
mysql -u root -p -e "CREATE DATABASE IF NOT EXISTS <database_name>;" # create empty db w/ correct name
zstd -dc <path_to_backup> | mysql -u root -p <database_name>
to restore a postgres database:
sudo -u postgres psql -c "DROP DATABASE IF EXISTS <database_name>;" # delete old db if lingering (prolly wont work)
sudo -u postgres psql -c "CREATE DATABASE <database_name>;" # create empty db w/ correct name
zstd -dc <path_to_backup> | sudo -u postgres psql -d immich # restore from the dump
*/
let
cfg = config.homelab.backups;
sec = config.sops.secrets;
in {
options.homelab.backups = {
enable = lib.mkEnableOption "enables borg backups for state files and db backup services";
baks = lib.mkOption {
type = lib.types.attrsOf (lib.types.attrsOf (lib.types.listOf lib.types.path));
default = {};
description = "backup jobs, nested attribute sets should be <bak_name> = paths [<list_of_paths>]";
};
backup_repo = lib.mkOption {
type = lib.types.path;
default = "/holocron/archives/homelab";
description = "path to take daily backups to with borg!";
};
};
config = lib.mkIf cfg.enable {
# backups homelab with borg
services.borgbackup.jobs.homelab = lib.mkIf (cfg.baks != {}) {
archiveBaseName = "homelab";
repo = cfg.backup_repo;
paths = lib.flatten (lib.attrsets.mapAttrsToList (_: arg: arg.paths) cfg.baks);
compression = "auto,zstd";
startAt = "03:30";
group = "archives";
encryption.mode = "repokey-blake2";
encryption.passCommand = "cat ${sec."borg_passwd".path}";
preHook = ''
systemctl start mysql-backup.service
systemctl start $(systemctl list-unit-files 'postgresqlBackup-*.service' --no-legend --no-pager | cut -d' ' -f1)
'';
extraArgs = ["--verbose" "--show-rc" "--umask" "0007"];
extraCreateArgs = ["--list" "--stats" "--filter" "AME"];
prune.keep = {
within = "1d"; # Keep all archives from the last day
daily = 7;
weekly = 12;
monthly = -1; # Keep at least one archive for each month
};
};
# mysql backups currently minecraft_recpro is the only thing using this
services.mysqlBackup = lib.mkIf (config.services.mysql.ensureDatabases != []) {
enable = true;
location = "/var/backup/mysql";
user = "root";
calendar = "daily"; # goes fast, included in back up with server dirs at **:00
compressionAlg = "zstd";
databases = config.services.mysql.ensureDatabases; # set to all databases defined in esure databases
};
# postgresql backups currently immich is the only user
services.postgresqlBackup = lib.mkIf (config.services.postgresql.ensureDatabases != []) {
enable = true;
location = "/var/backup/postgresql";
compression = "zstd"; # optional: "xz", "zstd", "none"
startAt = "daily"; # the dump is included in a backup taken at 4:00
databases = config.services.postgresql.ensureDatabases; # set to all databases defined in esure databases
};
# helpful and for scripts
environment.systemPackages = with pkgs; [borgbackup tree];
sops.secrets = {
"borg_passwd" = {
owner = "root";
group = "root";
};
};
};
}
+11
View File
@@ -0,0 +1,11 @@
{ pkgs, config, lib, ... }:
{
# the order determines the order in glance :3
imports = [
./motd
./backups
./uptime-kuma
./postfix
];
}
+98
View File
@@ -0,0 +1,98 @@
{
config,
lib,
pkgs,
...
}: let
inherit (lib) mkIf mkOption types filterAttrs mapAttrsToList;
cfg = config.homelab.motd;
# collect services to display
motd_list =
mapAttrsToList (_: v: v.motd)
(filterAttrs (_: v: v ? motd && v.motd != null) config.homelab);
in {
options.homelab.motd = {
enable = mkOption {
type = types.bool;
default = true;
description = "enable motd script";
};
};
config = mkIf cfg.enable {
environment.etc."motd".text = ''
#!/usr/bin/env bash
active=$'\033[1;34m'
inactive=$'\033[1;31m'
headings=$'\033[1;35m'
bold=$'\e[1m'
reset=$'\033[0m'
memory=`free -m | awk 'NR==2{printf "%s/%sMB (%.2f%%)\n", $3,$2,$3*100 / $2 }'`
load1=`cat /proc/loadavg | awk {'print $1'}`
load5=`cat /proc/loadavg | awk {'print $2'}`
load15=`cat /proc/loadavg | awk {'print $3'}`
uptime=`cat /proc/uptime | cut -f1 -d.`
up_days=$((uptime/60/60/24))
up_hours=$((uptime/60/60%24))
up_mins=$((uptime/60%60))
up_secs=$((uptime%60))
nixos_version=$(nixos-version | sed -E 's/^([0-9]{2}\.[0-9]{2}).*\(([^)]+)\)$/\1 (\2)/')
cpu_usage=$(top -bn1 | grep "Cpu(s)" | awk '{print 100 - $8 "%"}')
mem_total=$(grep MemTotal /proc/meminfo | awk '{print $2}')
mem_avail=$(grep MemAvailable /proc/meminfo | awk '{print $2}')
mem_used=$((mem_total - mem_avail))
mem_percent=$((100 * mem_used / mem_total))
uptime_fmt=$(uptime -p 2>/dev/null || cat /proc/uptime | awk '{print int($1/3600)"h "int(($1%3600)/60)"m"}')
printf "$bold welcome to $(hostname)!$reset\n"
printf "\n"
printf "$bold * %-20s$reset %s\n" "Release" "$nixos_version"
printf "$bold * %-20s$reset %s\n" "Kernel" "$(uname -rs)"
printf "\n"
printf "$bold * %-20s$reset %s\n" "CPU usage" "$load1, $load5, $load15 (1, 5, 15 min)"
printf "$bold * %-20s$reset %s\n" "Memory" "$memory"
printf "$bold * %-20s$reset %s\n" "System uptime" "$up_days days $up_hours hours $up_mins minutes $up_secs seconds"
echo
# --- services ---
echo -e "''${headings}homelab services:''${reset}"
${lib.concatStringsSep "\n" (map (service: ''
if systemctl list-units --type=service --all | grep -q "${service}"; then
status=$(systemctl is-active ${service} 2>/dev/null)
if [ "$status" = "active" ]; then
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "running"
else
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "not running"
fi
else
printf "%-32s%s\n" " ''${active}[${service}]''${reset}" "not found"
fi
'')
motd_list)}
echo
# --- gameservers ---
echo -e "''${headings}gameservers:''${reset}"
for service in velocity smp superflat bento cobblemon; do
status=$(systemctl is-active $service 2>/dev/null)
if [ "$status" = "active" ]; then
printf "%-32s%s\n" " ''${active}[$service]''${reset}" "running"
else
printf "%-32s%s\n" " ''${active}[$service]''${reset}" "not running"
fi
done
echo
'';
environment.etc."motd".mode = "0755";
programs.zsh.interactiveShellInit = ''
/etc/motd
'';
};
}
@@ -0,0 +1,99 @@
{
pkgs,
config,
lib,
...
}: let
service = "postfix";
cfg = config.homelab.${service};
sec = config.sops.secrets;
homelab = config.homelab;
in {
options.homelab.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 587;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${service}.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
# users.groups.${service} = {
# gid = lib.mkForce cfg.ids;
# };
#
# # declare ${service} user
# users.users.${service} = {
# description = "${service} server user";
# uid = lib.mkForce cfg.ids;
# isSystemUser = true;
# home = cfg.data_dir;
# createHome = true;
# group = service;
# extraGroups = [];
# };
# enable the ${service} service
services.postfix = {
enable = true;
settings.main = {
relayhost = ["smtp.gmail.com:${toString cfg.port}"];
smtp_tls_security_level = "may";
smtp_sasl_auth_enable = "yes";
smtp_sasl_security_options = "noanonymous";
smtp_sasl_password_maps = "texthash:${config.sops.secrets."postfix_passwd".path}";
# optional: Forward mails to root (e.g. from cron jobs, smartd)
# to me privately and to my work email:
virtual_alias_maps = "inline:{ {root=me@blakedheld.xyz, throwedspam@gmail.com} }";
};
};
# override umask to make permissions work out
# systemd.services.${service}.serviceConfig = {
# UMask = lib.mkForce "0007";
# User = service;
# Group = service;
#};
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port ];
sops.secrets = {
"${service}_passwd" = {
owner = config.services.postfix.user;
group = config.services.postfix.group;
};
};
# add to backups
homelab.backups.baks = {
${service} = {
paths = [cfg.data_dir];
};
};
};
}
@@ -0,0 +1,100 @@
{
pkgs,
config,
lib,
...
}: let
service = "postfix";
cfg = config.homelab.${service};
sec = config.sops.secrets;
homelab = config.homelab;
in {
options.homelab.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 587;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "${service}.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
# users.groups.${service} = {
# gid = lib.mkForce cfg.ids;
# };
#
# # declare ${service} user
# users.users.${service} = {
# description = "${service} server user";
# uid = lib.mkForce cfg.ids;
# isSystemUser = true;
# home = cfg.data_dir;
# createHome = true;
# group = service;
# extraGroups = [];
# };
# enable the ${service} service
services.postfix = {
enable = true;
relayHost = "smtp.mail.me.com";
relayPort = cfg.port;
config = {
smtp_tls_security_level = "may";
smtp_sasl_auth_enable = "yes";
smtp_sasl_security_options = "";
smtp_sasl_password_maps = "texthash:${config.sops.secrets."postfix_passwd".path}";
# optional: Forward mails to root (e.g. from cron jobs, smartd)
# to me privately and to my work email:
virtual_alias_maps = "inline:{ {root=me@blakedheld.xyz} }";
};
};
# override umask to make permissions work out
# systemd.services.${service}.serviceConfig = {
# UMask = lib.mkForce "0007";
# User = service;
# Group = service;
#};
# open firewall
networking.firewall.allowedTCPPorts = [ cfg.port ];
sops.secrets = {
"${service}_passwd" = {
owner = config.services.postfix.user;
group = config.services.postfix.group;
};
};
# add to backups
homelab.backups.baks = {
${service} = {
paths = [cfg.data_dir];
};
};
};
}
@@ -0,0 +1,101 @@
{ pkgs, config, lib, ... }:
let
service = "uptime-kuma";
cfg = config.homelab.${service};
sec = config.sops.secrets;
homelab = config.homelab;
in
{
options.homelab.${service} = {
enable = lib.mkEnableOption "enables ${service}";
# set port options
port = lib.mkOption {
type = lib.types.int;
default = 7901;
description = "set port for ${service} (default: ${toString cfg.port}";
};
url = lib.mkOption {
type = lib.types.str;
default = "up.${homelab.base_domain}";
description = "set domain for ${service}";
};
data_dir = lib.mkOption {
type = lib.types.str;
default = "/var/lib/${service}";
description = "set data directory for ${service}";
};
ids = lib.mkOption {
type = lib.types.int;
default = cfg.port;
description = "set uid and pid of ${service} user (matches port by default)";
};
backup = lib.mkOption {
type = lib.types.bool;
default = true;
description = "enable backups for ${service}";
};
motd = lib.mkOption {
type = lib.types.nullOr lib.types.str;
default = service;
};
};
config = lib.mkIf cfg.enable {
# declare ${service} group
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
# declare ${service} user
users.users.${service} = {
description = "${service} server user";
uid = lib.mkForce cfg.ids;
isSystemUser = true;
home = cfg.data_dir;
createHome = true;
group = "${service}";
extraGroups = [];
};
# enable the ${service} service
services.${service} = {
enable = true;
settings =
{
PORT = toString cfg.port;
HOST = "0.0.0.0";
};
};
# override umask to make permissions work out
systemd.services.${service}.serviceConfig = {
UMask = lib.mkForce "0007";
};
# # open firewall
# networking.firewall.allowedTCPPorts = [ cfg.port ];
# add to caddy for reverse proxy
services.caddy.virtualHosts."${cfg.url}" = {
serverAliases = [ "up.${homelab.public_domain}" ];
extraConfig = ''
tls internal
reverse_proxy 127.0.0.1:${toString cfg.port}
'';
};
# add to glance
homelab.glance.links.system = [{
title = service;
url = "https://${cfg.url}";
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
icon = "di:${service}"; }];
# add to backups
homelab.backups.baks = {
${service} = { paths = [ cfg.data_dir ]; };
};
};
}