Compare commits
200 Commits
fd5ef2c7e0
...
384b18b575
| Author | SHA1 | Date | |
|---|---|---|---|
| 384b18b575 | |||
| 21ecf083d2 | |||
| cb340e679c | |||
| 476a2106e1 | |||
| 03cff3b3e0 | |||
| d759a3e747 | |||
| 9fca78ed4c | |||
| 634e450ba1 | |||
| bcfdcad1b2 | |||
| cbaa2b9eb9 | |||
| 3f0900ed10 | |||
| 7326275c09 | |||
| 0ede6674dd | |||
| 5c53a81353 | |||
| e4bdf3af43 | |||
| 82dbb34bd0 | |||
| ada2bf81db | |||
| a17626a9cb | |||
| dbca751466 | |||
| 91f82d7dc3 | |||
| c637b6802b | |||
| f0ec85cc03 | |||
| 47ab6fa142 | |||
| 11028080bb | |||
| 49528805a5 | |||
| bbda7104ba | |||
| 32904bd35e | |||
| b5bbb6fd8e | |||
| 6819b00e6b | |||
| 1911315178 | |||
| 79b903403b | |||
| 634b09fc42 | |||
| 01fe78bffe | |||
| 790e358869 | |||
| 895b5d1add | |||
| de6b452d78 | |||
| 09603e8e30 | |||
| eec5b89396 | |||
| 4ba44f7248 | |||
| c749475fa9 | |||
| 6347aeab13 | |||
| f9f598827a | |||
| 0335d89b2f | |||
| b69c92e6db | |||
| 0077c9028a | |||
| c0e581ff08 | |||
| 5ecb7775ae | |||
| 3d7cad4fea | |||
| 952b0cc69a | |||
| 2f86551967 | |||
| 43e489ff52 | |||
| 3470cb1bbc | |||
| d46d270ad0 | |||
| 7205a6b00e | |||
| d49ed2acc3 | |||
| 89c1be5186 | |||
| 7d02cf9b19 | |||
| d7aabfaa4b | |||
| 2eafe082ba | |||
| efda5e5598 | |||
| 1eb60294cb | |||
| 2031aa443f | |||
| 7f56e043e7 | |||
| 0d78ee24a0 | |||
| fec6c6c146 | |||
| 7bd47ff538 | |||
| 0f0f838c1b | |||
| 247ab094d5 | |||
| 6508ed6159 | |||
| d924c98656 | |||
| 8c33edf4dd | |||
| d4200497a7 | |||
| d4b38ba1e7 | |||
| fa62f88352 | |||
| c818ac0e34 | |||
| a96471232e | |||
| fe35a1ef86 | |||
| e211775905 | |||
| 1055e10921 | |||
| ee7745f83f | |||
| 3e2ada161a | |||
| 51934f6577 | |||
| a27f922c5b | |||
| 7c5d2df922 | |||
| a3b3441b64 | |||
| ea5501723a | |||
| 347b4e9f74 | |||
| fd553ec4ca | |||
| 65af57f6d9 | |||
| 53a3bd0261 | |||
| 4206dbbb35 | |||
| 4f62d2746d | |||
| 6b01510afb | |||
| 3b4d0e3152 | |||
| f51570624b | |||
| 0cb49c0c42 | |||
| f3127697ca | |||
| 846d531ad3 | |||
| 58007d7743 | |||
| d258d95057 | |||
| 8d5743c0bc | |||
| f4b71070ce | |||
| badcab048c | |||
| 730bf26b93 | |||
| d333b3186b | |||
| 12936f35e2 | |||
| f50139dfca | |||
| f5625cc963 | |||
| 2854340455 | |||
| 1533db75f4 | |||
| 6fe75b1221 | |||
| 50e70d1cd1 | |||
| 83e60189b6 | |||
| 6a92cae6f7 | |||
| 9e30589699 | |||
| e6039316db | |||
| 0f5b1d83b5 | |||
| 0fb8657c2e | |||
| 59dd4bbe70 | |||
| 9e00aeca04 | |||
| 0c6c2562f3 | |||
| 4bac164d92 | |||
| afccaa5886 | |||
| 6a60ce6b85 | |||
| bf908ac917 | |||
| 7ceb225b06 | |||
| 6b291ecd40 | |||
| 64d7b799be | |||
| 33bfd2ed4f | |||
| 5ad52957fa | |||
| b3aa8fe80a | |||
| d43f12cdd2 | |||
| ff90df08d0 | |||
| 3fd4bb375e | |||
| a2ebf1dd31 | |||
| 1bab984f02 | |||
| 9fc91817fd | |||
| 4be5721730 | |||
| d45e598a2f | |||
| b2e4ee7e6b | |||
| 1f2d75d848 | |||
| b51aca18c7 | |||
| d7e1708f65 | |||
| a04fa13800 | |||
| 48c6d04db3 | |||
| ff4f6904fd | |||
| d377cda9a9 | |||
| 88bdb0b48c | |||
| e9b193afc2 | |||
| 463250c092 | |||
| 0485e78610 | |||
| ce6847fd36 | |||
| 502e53377f | |||
| f54922caf7 | |||
| fc6b0e9390 | |||
| dc4948063e | |||
| 4abe7423c8 | |||
| 1d7ac94c5d | |||
| 7d5c027da6 | |||
| 180d78430b | |||
| 26eac1e2a7 | |||
| 793ffda17a | |||
| 3e37b91846 | |||
| 5258bd62d8 | |||
| 39e44c0ade | |||
| cc673dde8e | |||
| e3c9bd23ee | |||
| 2fccc66805 | |||
| b78ba63ab5 | |||
| d6260546ca | |||
| 477d0bea34 | |||
| aed29a27de | |||
| d0c59fa764 | |||
| 42f5eb9c1a | |||
| b677b2f547 | |||
| 0632c3735e | |||
| 6b919051d9 | |||
| b6a56848b0 | |||
| 848a8ec406 | |||
| 00992dd0a2 | |||
| a4b0c2b91c | |||
| 7eda531e01 | |||
| a8fecf2c26 | |||
| f2f1b9cba5 | |||
| b5fc9b38e4 | |||
| 4332cbf69b | |||
| 4bc74cf035 | |||
| 622974ad88 | |||
| fa229e997d | |||
| 0e4786a464 | |||
| 83612a7f87 | |||
| 4cf4edff26 | |||
| 9a589ab24a | |||
| 53bf7fd64e | |||
| d61beb3f7b | |||
| 09991aa67d | |||
| a8f2cd7331 | |||
| b9a8012a48 | |||
| bc76eb71c3 | |||
| 7ff5c40f32 |
@@ -1,6 +1,6 @@
|
||||
# flake for blakes nixos config
|
||||
# define new devices in outputs
|
||||
# generation: 240 current 2025-10-10 21:55:37 25.05.20251006.20c4598 6.12.50 *
|
||||
# generation: 313 current 2025-10-11 18:01:55 25.05.20251006.20c4598 6.12.50 *
|
||||
{
|
||||
description = "blakes nix config";
|
||||
inputs = {
|
||||
|
||||
@@ -20,12 +20,9 @@ in
|
||||
backups.enable = true;
|
||||
backups.repo = "/holocron/backups";
|
||||
sops.enable = true;
|
||||
docker.enable = true;
|
||||
podman.enable = true;
|
||||
syncthing.enable = true;
|
||||
tailscale.enable = true;
|
||||
vpns.enable = false;
|
||||
vpns.wg_mex = false;
|
||||
vpn-confinement.enable = false;
|
||||
nvidia.enable = true;
|
||||
};
|
||||
homelab = {
|
||||
@@ -39,9 +36,10 @@ in
|
||||
jellyfin.enable = true;
|
||||
vaultwarden.enable = true;
|
||||
gitea.enable = true;
|
||||
glance.enable = true;
|
||||
qbittorrent.enable = true;
|
||||
immich.enable = true;
|
||||
home-assistant.enable = true;
|
||||
hass.enable = true;
|
||||
zigbee2mqtt.enable = true;
|
||||
mosquitto.enable = true;
|
||||
prowlarr.enable = true;
|
||||
|
||||
@@ -27,6 +27,16 @@ in
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
public_domain = lib.mkOption {
|
||||
default = "blakedheld.xyz";
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
host_ip = lib.mkOption {
|
||||
default = "10.10.0.10";
|
||||
type = lib.types.str;
|
||||
description = "base domain used for reverse proxy";
|
||||
};
|
||||
};
|
||||
|
||||
imports = [
|
||||
|
||||
@@ -62,18 +62,19 @@ in
|
||||
wants = [ "network.target" ];
|
||||
serviceConfig = {
|
||||
User = "minecraft";
|
||||
Group = "minecraft";
|
||||
WorkingDirectory = srv.data_dir;
|
||||
UMask = "0007";
|
||||
ExecStart = "${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar ${srv.data_dir}/server.jar nogui";
|
||||
# ExecStart = "${pkgs.tmux}/bin/tmux new-session -d -s mcrp-${name} '${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar ${srv.data_dir}/server.jar nogui'";
|
||||
# ExecStop = "${pkgs.tmux}/bin/tmux send-keys -t mcrp-${name} C-c"; # stop server by sending Ctrl+C to tmux session
|
||||
ExecStart = "${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar server.jar nogui";
|
||||
# ExecStart = "${pkgs.tmux}/bin/tmux new-session -d -s mc-${name} '${pkgs.openjdk21}/bin/java -Xmx${srv.ram} -jar server.jar nogui'";
|
||||
# ExecStop = "${pkgs.tmux}/bin/tmux send-keys -t mc-${name} C-c";
|
||||
Restart = "on-failure";
|
||||
KillMode = "process";
|
||||
};
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
}) servers;
|
||||
|
||||
environment.systemPackages = with pkgs; [ openjdk21 mcrcon ];
|
||||
environment.systemPackages = with pkgs; [ openjdk21 mcrcon tmux ];
|
||||
|
||||
services.mysql = {
|
||||
enable = true;
|
||||
@@ -128,9 +129,14 @@ in
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = lib.listToAttrs (
|
||||
lib.mapAttrsToList (srv_name: cfg:
|
||||
{
|
||||
name = srv_name; # attribute key
|
||||
value = { paths = [ cfg.data_dir ]; }; # attribute value
|
||||
}
|
||||
) servers
|
||||
);
|
||||
};
|
||||
}
|
||||
|
||||
@@ -81,7 +81,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,7 +83,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,7 +86,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -84,7 +84,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,22 +3,24 @@
|
||||
|
||||
{
|
||||
|
||||
# services show up in glance in reverse import order lmao
|
||||
imports = [
|
||||
./jellyfin
|
||||
./smarthome/zigbee2mqtt
|
||||
./vaultwarden
|
||||
./gitea
|
||||
./qbittorrent
|
||||
./immich
|
||||
./uptime-kuma
|
||||
./nginx-proxy
|
||||
./smarthome/homeassistant
|
||||
./smarthome/zigbee2mqtt
|
||||
./smarthome/mosquitto
|
||||
./arr/prowlarr
|
||||
./arr/flaresolverr
|
||||
./immich
|
||||
./arr/bazarr
|
||||
./arr/sonarr
|
||||
./arr/prowlarr
|
||||
./qbittorrent
|
||||
./arr/radarr
|
||||
./arr/sonarr
|
||||
./jellyfin
|
||||
./nginx-proxy
|
||||
./arr/flaresolverr
|
||||
./smarthome/mosquitto
|
||||
./uptime-kuma
|
||||
./glance
|
||||
];
|
||||
|
||||
}
|
||||
|
||||
@@ -85,6 +85,9 @@ in
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
|
||||
# uncomment for service hosted publicly
|
||||
#---------------------------------------------------------------------------
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
@@ -95,6 +98,22 @@ in
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# # add to glance public service
|
||||
# modules.services.glance.links.<category> = [{
|
||||
# title = service;
|
||||
# url = "https://pass.${homelab.public_domain}";
|
||||
# error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
# icon = "di:${service}"; }];
|
||||
#---------------------------------------------------------------------------
|
||||
# # add to glance local service
|
||||
# modules.services.glance.links.<category> = [{
|
||||
# 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}"; }];
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
@@ -103,6 +122,8 @@ in
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -108,6 +108,14 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://git.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_database_password" = {
|
||||
owner = "${service}";
|
||||
@@ -116,6 +124,8 @@ in
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
256
modules/homelab/services/glance/default.nix
Normal file
256
modules/homelab/services/glance/default.nix
Normal file
@@ -0,0 +1,256 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
/*
|
||||
this is a wrapper module for glance that allows you to
|
||||
to pass monitor entries in with nix, all declaratively!
|
||||
|
||||
| <8yy> |
|
||||
V V
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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}";
|
||||
allow-insecure = true; }];
|
||||
*/
|
||||
|
||||
let
|
||||
service = "glance";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7700;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${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}";
|
||||
};
|
||||
links = {
|
||||
services = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [];
|
||||
description = "list of links for ${service}";
|
||||
};
|
||||
mediastack = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [];
|
||||
description = "list of links for ${service}";
|
||||
};
|
||||
system = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.attrs;
|
||||
default = [];
|
||||
description = "list of links 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 = [];
|
||||
};
|
||||
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
server = {
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
};
|
||||
pages = [
|
||||
{
|
||||
name = "violet";
|
||||
hide-desktop-navigation = true;
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "calendar"; first-day-of-week = "monday"; }
|
||||
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
|
||||
{
|
||||
type = "clock";
|
||||
hour-format = "24h";
|
||||
timezones = [
|
||||
{ timezone = "America/Chicago"; label = "HTX"; }
|
||||
{ timezone = "America/Denver"; label = "AF"; }
|
||||
];
|
||||
}
|
||||
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "search";
|
||||
autofocus = true;
|
||||
search-engine = "https://www.ecosia.org/search?q={QUERY}";
|
||||
new-tab = true;
|
||||
bangs = [
|
||||
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
|
||||
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
|
||||
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "services";
|
||||
sites = cfg.links.services;
|
||||
# sites = [
|
||||
# { title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
|
||||
# { title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
|
||||
# { title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
|
||||
# { title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
|
||||
# { title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
|
||||
# { title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
|
||||
# { title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
|
||||
# { title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
|
||||
# { title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
|
||||
# ];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "mediastack";
|
||||
sites = cfg.links.mediastack;
|
||||
# [
|
||||
# { title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
|
||||
# { title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
|
||||
# { title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
|
||||
# { title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
|
||||
# { title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
|
||||
# { title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
|
||||
# { title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
|
||||
# { title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
|
||||
# ];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "system";
|
||||
sites = cfg.links.system;
|
||||
# [
|
||||
# { title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
|
||||
# { title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
|
||||
# { title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
|
||||
# { title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
|
||||
# { title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
|
||||
# ];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
|
||||
{
|
||||
type = "markets";
|
||||
markets = [
|
||||
{ symbol = "SPY"; name = "S&P 500"; }
|
||||
{ symbol = "XMR-USD"; name = "Monero"; }
|
||||
{ symbol = "NVDA"; name = "NVIDIA"; }
|
||||
{ symbol = "AAPL"; name = "Apple"; }
|
||||
{ symbol = "MSFT"; name = "Microsoft"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "releases";
|
||||
cache = "1d";
|
||||
repositories = [
|
||||
"glanceapp/glance"
|
||||
"go-gitea/gitea"
|
||||
"immich-app/immich"
|
||||
"syncthing/syncthing"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
# 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 ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
230
modules/homelab/services/glance/default.nix.WORKING
Normal file
230
modules/homelab/services/glance/default.nix.WORKING
Normal file
@@ -0,0 +1,230 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "glance";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7700;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${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}";
|
||||
};
|
||||
pages = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options.description = lib.mkOption { type = lib.types.str; };
|
||||
options.url = lib.mkOption { type = lib.types.str; };
|
||||
options.icon = lib.mkOption { type = lib.types.str; };
|
||||
options.category = lib.mkOption { type = lib.types.str; };
|
||||
});
|
||||
default = {};
|
||||
description = "configure the service for use in ${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 = [];
|
||||
};
|
||||
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
server = {
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
};
|
||||
pages = [
|
||||
{
|
||||
name = "violet";
|
||||
hide-desktop-navigation = true;
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "calendar"; first-day-of-week = "monday"; }
|
||||
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
|
||||
{
|
||||
type = "clock";
|
||||
hour-format = "24h";
|
||||
timezones = [
|
||||
{ timezone = "America/Chicago"; label = "HTX"; }
|
||||
{ timezone = "America/Denver"; label = "AF"; }
|
||||
];
|
||||
}
|
||||
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "search";
|
||||
autofocus = true;
|
||||
search-engine = "https://www.ecosia.org/search?q={QUERY}";
|
||||
new-tab = true;
|
||||
bangs = [
|
||||
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
|
||||
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
|
||||
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "mediastack";
|
||||
sites = [
|
||||
{ title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
|
||||
{ title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
|
||||
{ title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
|
||||
{ title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
|
||||
{ title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
|
||||
{ title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
|
||||
{ title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
|
||||
{ title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
|
||||
{ title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "services";
|
||||
sites = [
|
||||
{ title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
|
||||
{ title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
|
||||
{ title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
|
||||
{ title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
|
||||
{ title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
|
||||
{ title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
|
||||
{ title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
|
||||
{ title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "system";
|
||||
sites = [
|
||||
{ title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
|
||||
{ title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
|
||||
{ title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
|
||||
{ title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
|
||||
{ title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
|
||||
{
|
||||
type = "markets";
|
||||
markets = [
|
||||
{ symbol = "SPY"; name = "S&P 500"; }
|
||||
{ symbol = "XMR-USD"; name = "Monero"; }
|
||||
{ symbol = "NVDA"; name = "NVIDIA"; }
|
||||
{ symbol = "AAPL"; name = "Apple"; }
|
||||
{ symbol = "MSFT"; name = "Microsoft"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "releases";
|
||||
cache = "1d";
|
||||
repositories = [
|
||||
"glanceapp/glance"
|
||||
"go-gitea/gitea"
|
||||
"immich-app/immich"
|
||||
"syncthing/syncthing"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
# 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 ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
230
modules/homelab/services/glance/default.nix.hardswing
Normal file
230
modules/homelab/services/glance/default.nix.hardswing
Normal file
@@ -0,0 +1,230 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
service = "glance";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
in
|
||||
{
|
||||
options.modules.services.${service} = {
|
||||
enable = lib.mkEnableOption "enables ${service}";
|
||||
|
||||
# set port options
|
||||
port = lib.mkOption {
|
||||
type = lib.types.int;
|
||||
default = 7700;
|
||||
description = "set port for ${service} (default: ${toString cfg.port}";
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${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}";
|
||||
};
|
||||
pages = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.submodule {
|
||||
options.description = lib.mkOption { type = lib.types.str; };
|
||||
options.url = lib.mkOption { type = lib.types.str; };
|
||||
options.icon = lib.mkOption { type = lib.types.str; };
|
||||
options.category = lib.mkOption { type = lib.types.str; };
|
||||
});
|
||||
default = {};
|
||||
description = "configure the service for use in ${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 = [];
|
||||
};
|
||||
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
openFirewall = true;
|
||||
settings = {
|
||||
server = {
|
||||
host = "0.0.0.0";
|
||||
port = cfg.port;
|
||||
};
|
||||
pages = [
|
||||
{
|
||||
name = "violet";
|
||||
hide-desktop-navigation = true;
|
||||
columns = [
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "calendar"; first-day-of-week = "monday"; }
|
||||
{ type = "server-stats"; servers = [ { type = "local"; name = "violet"; } ]; }
|
||||
{
|
||||
type = "clock";
|
||||
hour-format = "24h";
|
||||
timezones = [
|
||||
{ timezone = "America/Chicago"; label = "HTX"; }
|
||||
{ timezone = "America/Denver"; label = "AF"; }
|
||||
];
|
||||
}
|
||||
{ type = "twitch-channels"; channels = [ "mang0" "SaltSSBM" "thewaffle77" "ironmouse" "linustech" ]; }
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "full";
|
||||
widgets = [
|
||||
{
|
||||
type = "search";
|
||||
autofocus = true;
|
||||
search-engine = "https://www.ecosia.org/search?q={QUERY}";
|
||||
new-tab = true;
|
||||
bangs = [
|
||||
{ title = "YouTube"; shortcut = "!y"; url = "https://www.youtube.com/results?search_query={QUERY}"; }
|
||||
{ title = "Google"; shortcut = "!g"; url = "https://www.google.com/search?q={QUERY}"; }
|
||||
{ title = "Github"; shortcut = "!gh"; url = "https://github.com/search?q={QUERY}&type=repositories"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "mediastack";
|
||||
sites = [
|
||||
{ title = "jellyfin"; url = "https://media.blakedheld.xyz"; icon = "di:jellyfin"; }
|
||||
{ title = "audiobookshelf"; url = "https://audiobooks.blakedheld.xyz"; icon = "di:audiobookshelf"; }
|
||||
{ title = "yacreader"; url = "http://10.10.0.30:3434"; icon = "/assets/icons/yacreader.png"; }
|
||||
{ title = "sonarr"; url = "http://10.10.0.30:3636"; icon = "di:sonarr"; }
|
||||
{ title = "qbittorrent"; url = "http://10.10.0.40:3333"; icon = "di:qbittorrent"; }
|
||||
{ title = "radarr"; url = "http://10.10.0.30:3737"; icon = "di:radarr"; }
|
||||
{ title = "kiwix"; url = "http://10.10.0.30:5050"; icon = "di:kiwix"; }
|
||||
{ title = "prowlarr"; url = "http://10.10.0.30:3535"; icon = "di:prowlarr"; }
|
||||
{ title = "bazarr"; url = "http://10.10.0.30:3838"; icon = "di:bazarr"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "services";
|
||||
sites = [
|
||||
{ title = "immich"; url = "https://pics.blakedheld.xyz"; icon = "di:immich"; }
|
||||
{ title = "vaultwarden"; url = "https://pass.blakedheld.xyz"; icon = "di:vaultwarden"; }
|
||||
{ title = "gitea"; url = "https://git.blakedheld.xyz"; icon = "di:gitea"; }
|
||||
{ title = "home assistant"; url = "https://home.blakedheld.xyz"; icon = "di:home-assistant"; }
|
||||
{ title = "zigbee2mqtt"; url = "http://10.10.0.30:4142"; icon = "di:zigbee2mqtt"; }
|
||||
{ title = "syncthing"; url = "http://10.10.0.20:2222"; icon = "di:syncthing"; }
|
||||
{ title = "archivebox"; url = "http://10.10.0.30:5656"; icon = "sh:archivebox"; }
|
||||
{ title = "copyparty"; url = "http://10.10.0.20:3923"; icon = "sh:copyparty"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "monitor";
|
||||
cache = "1m";
|
||||
title = "system";
|
||||
sites = [
|
||||
{ title = "proxmox"; url = "http://10.10.0.10:8006"; icon = "di:proxmox"; allow-insecure = true; }
|
||||
{ title = "nginx"; url = "http://10.10.0.30:8080"; icon = "di:nginx"; }
|
||||
{ title = "uptime kuma"; url = "http://10.10.0.30:8181"; icon = "di:uptime-kuma"; }
|
||||
{ title = "tn holocron"; url = "https://10.10.0.20"; icon = "di:truenas"; allow-insecure = true; }
|
||||
{ title = "bebe"; url = "https://10.10.0.1"; icon = "di:unifi"; allow-insecure = true; }
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
{
|
||||
size = "small";
|
||||
widgets = [
|
||||
{ type = "weather"; location = "Pearland, Texas, United States"; units = "imperial"; hour-format = "24h"; }
|
||||
{
|
||||
type = "markets";
|
||||
markets = [
|
||||
{ symbol = "SPY"; name = "S&P 500"; }
|
||||
{ symbol = "XMR-USD"; name = "Monero"; }
|
||||
{ symbol = "NVDA"; name = "NVIDIA"; }
|
||||
{ symbol = "AAPL"; name = "Apple"; }
|
||||
{ symbol = "MSFT"; name = "Microsoft"; }
|
||||
];
|
||||
}
|
||||
{
|
||||
type = "releases";
|
||||
cache = "1d";
|
||||
repositories = [
|
||||
"glanceapp/glance"
|
||||
"go-gitea/gitea"
|
||||
"immich-app/immich"
|
||||
"syncthing/syncthing"
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
||||
# 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 ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
services.nginx.virtualHosts."${cfg.url}" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -96,7 +96,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://photos.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir "/var/lib/redis-immich" ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir "/var/lib/redis-immich" ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -90,14 +90,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
title = service;
|
||||
url = "https://media.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -119,7 +119,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.mediastack = [{
|
||||
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
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
{ pkgs, config, lib, inputs, ... }:
|
||||
|
||||
let
|
||||
service = "home-assistant";
|
||||
nixservice = "home-assistant";
|
||||
service = "hass";
|
||||
cfg = config.modules.services.${service};
|
||||
sec = config.sops.secrets;
|
||||
homelab = config.modules.homelab;
|
||||
@@ -18,12 +19,12 @@ in
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "hass.${homelab.base_domain}";
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "/var/lib/hass";
|
||||
default = "/var/lib/${service}";
|
||||
description = "set data directory for ${service}";
|
||||
};
|
||||
ids = lib.mkOption {
|
||||
@@ -41,53 +42,49 @@ in
|
||||
config = lib.mkIf cfg.enable {
|
||||
|
||||
# declare ${service} group
|
||||
users.groups.hass = { gid = lib.mkForce cfg.ids; };
|
||||
users.groups.${service} = { gid = lib.mkForce cfg.ids; };
|
||||
|
||||
# declare ${service} user
|
||||
users.users.hass = {
|
||||
users.users.${service} = {
|
||||
description = "${service} server user";
|
||||
uid = lib.mkForce cfg.ids;
|
||||
isSystemUser = true;
|
||||
#home = cfg.data_dir;
|
||||
#createHome = true;
|
||||
group = "hass";
|
||||
extraGroups = [ "bluetooth" ];
|
||||
home = cfg.data_dir;
|
||||
createHome = true;
|
||||
group = service;
|
||||
extraGroups = [];
|
||||
};
|
||||
|
||||
# enable the ${service} service
|
||||
services.${service} = {
|
||||
enable = true;
|
||||
package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.home-assistant;
|
||||
extraComponents = [
|
||||
# required for onboarding
|
||||
"analytics"
|
||||
"google_translate"
|
||||
"met"
|
||||
"radio_browser"
|
||||
"shopping_list"
|
||||
# zlib
|
||||
"isal"
|
||||
# still suss as fuck bro man fuck
|
||||
virtualisation.oci-containers.containers = {
|
||||
hass = {
|
||||
image = "homeassistant/home-assistant:stable";
|
||||
autoStart = true;
|
||||
extraOptions = [
|
||||
"--pull=newer"
|
||||
"--network=host"
|
||||
];
|
||||
# imperative config
|
||||
# config = null;
|
||||
# lovelaceConfig = null;
|
||||
# configDir = cfg.data_dir;
|
||||
# declartive poggers!
|
||||
config = {
|
||||
# Includes dependencies for a basic setup
|
||||
default_config = {};
|
||||
volumes = [
|
||||
"${cfg.data_dir}:/config"
|
||||
];
|
||||
# ports = [
|
||||
# "0.0.0.0:7704:8123"
|
||||
# "0.0.0.0:4141:4141"
|
||||
# ];
|
||||
environment = {
|
||||
TZ = homelab.tz;
|
||||
PUID = toString config.users.users.${service}.uid;
|
||||
PGID = toString config.users.groups.${service}.gid;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
# override umask to make permissions work out
|
||||
systemd.services.${service}.serviceConfig = {
|
||||
UMask = lib.mkForce "0007";
|
||||
User = lib.mkForce "hass";
|
||||
Group = lib.mkForce "hass";
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port 8123 ];
|
||||
|
||||
# internal reverse proxy entry
|
||||
@@ -95,28 +92,93 @@ in
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
extraConfig =
|
||||
"proxy_set_header Upgrade $http_upgrade;" +
|
||||
"proxy_set_header Connection upgrade;"
|
||||
;
|
||||
};
|
||||
};
|
||||
# external reverse proxy entry
|
||||
services.nginx.virtualHosts."hass.blakedheld.xyz" = {
|
||||
services.nginx.virtualHosts."${service}.blakedheld.xyz" = {
|
||||
forceSSL = true;
|
||||
sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
extraConfig = ''
|
||||
proxy_buffering off;
|
||||
'';
|
||||
locations."/" = {
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
extraConfig =
|
||||
"proxy_set_header Upgrade $http_upgrade;" +
|
||||
"proxy_set_header Connection upgrade;"
|
||||
;
|
||||
};
|
||||
};
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
# add to glance
|
||||
modules.services.glance.links.services = [{
|
||||
title = "home assistant";
|
||||
url = "https://hass.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${nixservice}"; }];
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
# here lies my tough, and I mean fucking tough, swing at
|
||||
# getting this to work bare metal, ggs ill see you again
|
||||
# - didnt take long
|
||||
# --------------------------------------------------------------------------------
|
||||
# # enable the ${service} service
|
||||
# services.${nixservice} = {
|
||||
# enable = true;
|
||||
# package = inputs.nixpkgs-unstable.legacyPackages.${pkgs.system}.home-assistant;
|
||||
# extraComponents = [
|
||||
# # required for onboarding
|
||||
# "analytics"
|
||||
# "google_translate"
|
||||
# "met"
|
||||
# "radio_browser"
|
||||
# "shopping_list"
|
||||
# "isal"
|
||||
# "default_config"
|
||||
# "mqtt"
|
||||
# ];
|
||||
# extraPackages = python3Packages: with python3Packages; [
|
||||
# psycopg2
|
||||
# universal-silabs-flasher
|
||||
# getmac
|
||||
# zha
|
||||
# ha-silabs-firmware-client
|
||||
# paho-mqtt
|
||||
# aiomqtt
|
||||
# aiounifi
|
||||
# ibeacon-ble
|
||||
# ];
|
||||
# # imperative config
|
||||
# config = null;
|
||||
# lovelaceConfig = null;
|
||||
# configDir = cfg.data_dir;
|
||||
# # declartive poggers!
|
||||
## config = {
|
||||
## # Includes dependencies for a basic setup
|
||||
## default_config = {};
|
||||
## };
|
||||
# };
|
||||
|
||||
|
||||
|
||||
@@ -60,8 +60,14 @@ in
|
||||
{
|
||||
port = 1883;
|
||||
address = "0.0.0.0";
|
||||
settings.allow_anonymous = true;
|
||||
#passwordFile = sec."mosquitto_password_file".path; # optional
|
||||
users.zigbee = {
|
||||
acl = [ "readwrite #" ];
|
||||
hashedPassword = "$7$101$140powz2MtsRawFT$ydndjal9wCAywIWtUEAh/IusdfDFvnHMupTFjdS7Ad/EjsEIbJgHrLY9waCe4Z3142XieuxMrXUDjMTp2qwyiw==";
|
||||
};
|
||||
# use with no auth
|
||||
# settings.allow_anonymous = true;
|
||||
# acl = [ "pattern readwrite #" ];
|
||||
# omitPasswordAuth = true;
|
||||
}
|
||||
];
|
||||
# override umask to make permissions work out
|
||||
@@ -71,27 +77,19 @@ in
|
||||
Group = "${service}";
|
||||
};
|
||||
|
||||
# # open firewall
|
||||
# open firewall
|
||||
networking.firewall.allowedTCPPorts = [ cfg.port ];
|
||||
|
||||
# # internal reverse proxy entry
|
||||
# services.nginx.virtualHosts."${cfg.url}" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
# locations."/" = {
|
||||
# proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
# };
|
||||
# };
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_password_file" = {
|
||||
"${service}_hashed_passwd" = {
|
||||
owner = "${service}";
|
||||
group = "${service}";
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ in
|
||||
};
|
||||
url = lib.mkOption {
|
||||
type = lib.types.str;
|
||||
default = "${service}.${homelab.base_domain}";
|
||||
default = "z2m.${homelab.base_domain}";
|
||||
description = "set domain for ${service}";
|
||||
};
|
||||
data_dir = lib.mkOption {
|
||||
@@ -61,7 +61,11 @@ in
|
||||
settings = {
|
||||
mqtt = {
|
||||
base_topic = "zigbee2mqtt";
|
||||
client_id = "zigbee2mqtt";
|
||||
server = "mqtt://localhost:1883";
|
||||
user = "!/run/secrets/mosquitto_passwd.yaml user";
|
||||
password = "!/run/secrets/mosquitto_passwd.yaml password";
|
||||
keepalive = 20;
|
||||
};
|
||||
serial = {
|
||||
port = "/dev/serial/by-id/usb-Itead_Sonoff_Zigbee_3.0_USB_Dongle_Plus_V2_4a4e75d63653ef1198d728e0174bec31-if00-port0";
|
||||
@@ -99,15 +103,25 @@ in
|
||||
proxyPass = "http://127.0.0.1:${toString cfg.port}";
|
||||
};
|
||||
};
|
||||
#
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
# group = "${service}";
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.services = [{
|
||||
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}"; }];
|
||||
|
||||
sops.secrets = {
|
||||
"mosquitto_passwd.yaml" = {
|
||||
owner = "${service}";
|
||||
group = "${service}";
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -60,6 +60,7 @@ in
|
||||
settings =
|
||||
{
|
||||
PORT = toString cfg.port;
|
||||
HOST = "0.0.0.0";
|
||||
};
|
||||
};
|
||||
|
||||
@@ -83,7 +84,7 @@ in
|
||||
};
|
||||
};
|
||||
# # external reverse proxy entry
|
||||
# services.nginx.virtualHosts."uptime.blakedheld.xyz" = {
|
||||
# services.nginx.virtualHosts."up.blakedheld.xyz" = {
|
||||
# forceSSL = true;
|
||||
# sslCertificate = sec."ssl_blakedheld_crt".path;
|
||||
# sslCertificateKey = sec."ssl_blakedheld_key".path;
|
||||
@@ -92,6 +93,14 @@ in
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to glance
|
||||
modules.services.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}"; }];
|
||||
|
||||
# sops.secrets = {
|
||||
# "${service}_" = {
|
||||
# owner = "${service}";
|
||||
|
||||
@@ -103,6 +103,14 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to glance
|
||||
modules.services.glance.links.services = [{
|
||||
title = service;
|
||||
url = "https://pass.${homelab.public_domain}";
|
||||
error-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
check-url = "http://${homelab.host_ip}:${toString cfg.port}";
|
||||
icon = "di:${service}"; }];
|
||||
|
||||
sops.secrets = {
|
||||
"${service}_admin_token" = {
|
||||
owner = "${service}";
|
||||
@@ -111,6 +119,8 @@ in
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -1,76 +1,123 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
/*
|
||||
this module enables a backup script made with borg!
|
||||
to use import & set the options below
|
||||
to declare a backup add the following code
|
||||
to a module and it will backup all listed paths
|
||||
in a borg archive to the specified repo
|
||||
|
||||
| <3yy> |
|
||||
V V
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
*/
|
||||
|
||||
let
|
||||
cfg = config.modules.system.backups;
|
||||
sec = config.sops.secrets;
|
||||
borg = "${pkgs.borgbackup}/bin/borg";
|
||||
backup_paths = lib.unique config.modules.system.backups.paths;
|
||||
passwd_file = config.sops.secrets."borg_passwd".path;
|
||||
in
|
||||
{
|
||||
options.modules.system.backups = {
|
||||
enable = lib.mkEnableOption "enables backups with borg";
|
||||
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>]";
|
||||
};
|
||||
paths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
description = "list of directories to back up";
|
||||
type = lib.types.list;
|
||||
};
|
||||
repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/borg";
|
||||
description = "borg repository path";
|
||||
};
|
||||
passphraseFile = lib.mkOption {
|
||||
passwd_file = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = passwd_file;
|
||||
default = sec."borg_passwd".path;
|
||||
description = "borg repository passphrase file";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.enable && backup_paths != []) {
|
||||
|
||||
# systemd.tmpfiles.rules = [
|
||||
# "d ${cfg.repo} 0755 root root"
|
||||
# ];
|
||||
config = lib.mkIf (cfg.enable && cfg.baks != {}) {
|
||||
|
||||
systemd.services.backups = {
|
||||
description = "backup service with borg!";
|
||||
path = [ pkgs.borgbackup ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = config.modules.system.backups.passphraseFile;
|
||||
# EnvironmentFile = config.modules.system.backups.passphraseFile;
|
||||
# the actual script borg is using
|
||||
ExecStart = pkgs.writeShellScript "borg-backup" ''
|
||||
set -euo pipefail
|
||||
export BORG_PASSPHRASE="$(cat ${passwd_file})"
|
||||
export BORG_PASSPHRASE="$(cat ${cfg.passwd_file})"
|
||||
export BORG_REPO="${cfg.repo}"
|
||||
timestamp="$(date +'%Y-%m-%dT%H:%M:%S')"
|
||||
timestamp="$(date +'%Y-%m-%d_%H:%M:%S')"
|
||||
mode=all
|
||||
|
||||
# Initialize repo if it doesn't exist
|
||||
# init repo in needed
|
||||
if ! borg info "$BORG_REPO" >/dev/null 2>&1; then
|
||||
echo "init borg repo at $BORG_REPO"
|
||||
echo "Initializing Borg repo at $BORG_REPO"
|
||||
borg init --encryption=repokey "$BORG_REPO"
|
||||
fi
|
||||
|
||||
# Create backup
|
||||
echo "starting backup..."
|
||||
borg break-lock "$BORG_REPO" || true
|
||||
|
||||
echo "starting backup at $timestamp"
|
||||
|
||||
if [ "$mode" = "sep" ]; then
|
||||
# loop for each backup
|
||||
${lib.concatStringsSep "\n\n" (lib.mapAttrsToList (bak_name: bak_paths:
|
||||
''
|
||||
echo "------------ Backing up ${bak_name} ------------"
|
||||
archive="$timestamp-${bak_name}"
|
||||
echo "backing up: ${lib.concatStringsSep " " bak_paths.paths} → $archive"
|
||||
borg create \
|
||||
--verbose \
|
||||
--filter AME \
|
||||
--list \
|
||||
--stats \
|
||||
--show-rc \
|
||||
--compression lz4 \
|
||||
"$BORG_REPO::${toString config.networking.hostName}-$timestamp" \
|
||||
${lib.concatStringsSep " " cfg.paths}
|
||||
|
||||
# Prune old backups according to retention policy
|
||||
echo "Pruning old backups..."
|
||||
--compression lzma,9 \
|
||||
"$BORG_REPO::$archive" \
|
||||
${lib.concatStringsSep " " bak_paths.paths}
|
||||
echo "pruning old backups for ${bak_name}..."
|
||||
borg prune -v --list "$BORG_REPO" \
|
||||
--prefix "${bak_name}-" \
|
||||
--keep-daily=7 \
|
||||
--keep-weekly=52 \
|
||||
--keep-monthly=-1
|
||||
echo "backup run complete at \"$BORG_REPO::$archive\""
|
||||
''
|
||||
) cfg.baks)}
|
||||
else
|
||||
# flatten all paths from cfg.baks into one big list
|
||||
all_paths="${
|
||||
lib.concatStringsSep " "
|
||||
(lib.flatten
|
||||
(lib.mapAttrsToList (_: bak: bak.paths) cfg.baks))
|
||||
}"
|
||||
borg create \
|
||||
--verbose \
|
||||
--filter AME \
|
||||
--list \
|
||||
--stats \
|
||||
--show-rc \
|
||||
--compression lzma,9 \
|
||||
"$BORG_REPO::$timestamp-${toString config.networking.hostName}" \
|
||||
$all_paths
|
||||
|
||||
echo "$timestamp - backup completed successfully."
|
||||
echo "pruning old backups for ${toString config.networking.hostName}..."
|
||||
borg prune -v --list "$BORG_REPO" \
|
||||
--prefix "${toString config.networking.hostName}" \
|
||||
--keep-daily=7 \
|
||||
--keep-weekly=52 \
|
||||
--keep-monthly=-1
|
||||
echo "backup run complete at \"$BORG_REPO::${toString config.networking.hostName}\""
|
||||
fi
|
||||
'';
|
||||
};
|
||||
};
|
||||
@@ -97,6 +144,3 @@ in
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
# add to modules
|
||||
# modules.system.backups.paths = lib.mkIf cfg.backups [ <path> ];
|
||||
|
||||
102
modules/system/backups.nix.bak
Normal file
102
modules/system/backups.nix.bak
Normal file
@@ -0,0 +1,102 @@
|
||||
{ config, lib, pkgs, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.backups;
|
||||
borg = "${pkgs.borgbackup}/bin/borg";
|
||||
backup_paths = lib.unique config.modules.system.backups.paths;
|
||||
passwd_file = config.sops.secrets."borg_passwd".path;
|
||||
in
|
||||
{
|
||||
options.modules.system.backups = {
|
||||
enable = lib.mkEnableOption "enables backups with borg";
|
||||
paths = lib.mkOption {
|
||||
type = lib.types.listOf lib.types.path;
|
||||
default = [];
|
||||
description = "list of directories to back up";
|
||||
};
|
||||
repo = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = "/holocron/borg";
|
||||
description = "borg repository path";
|
||||
};
|
||||
passphraseFile = lib.mkOption {
|
||||
type = lib.types.path;
|
||||
default = passwd_file;
|
||||
description = "borg repository passphrase file";
|
||||
};
|
||||
};
|
||||
|
||||
config = lib.mkIf (cfg.enable && backup_paths != []) {
|
||||
|
||||
# systemd.tmpfiles.rules = [
|
||||
# "d ${cfg.repo} 0755 root root"
|
||||
# ];
|
||||
|
||||
systemd.services.backups = {
|
||||
description = "backup service with borg!";
|
||||
path = [ pkgs.borgbackup ];
|
||||
serviceConfig = {
|
||||
Type = "oneshot";
|
||||
EnvironmentFile = config.modules.system.backups.passphraseFile;
|
||||
# the actual script borg is using
|
||||
ExecStart = pkgs.writeShellScript "borg-backup" ''
|
||||
set -euo pipefail
|
||||
export BORG_PASSPHRASE="$(cat ${passwd_file})"
|
||||
export BORG_REPO="${cfg.repo}"
|
||||
timestamp="$(date +'%Y-%m-%dT%H:%M:%S')"
|
||||
|
||||
# Initialize repo if it doesn't exist
|
||||
if ! borg info "$BORG_REPO" >/dev/null 2>&1; then
|
||||
echo "init borg repo at $BORG_REPO"
|
||||
borg init --encryption=repokey "$BORG_REPO"
|
||||
fi
|
||||
|
||||
# Create backup
|
||||
echo "starting backup..."
|
||||
borg create \
|
||||
--verbose \
|
||||
--filter AME \
|
||||
--list \
|
||||
--stats \
|
||||
--show-rc \
|
||||
--compression lzma,9 \
|
||||
"$BORG_REPO::${toString config.networking.hostName}-$timestamp" \
|
||||
${lib.concatStringsSep " " cfg.paths}
|
||||
|
||||
# Prune old backups according to retention policy
|
||||
echo "Pruning old backups..."
|
||||
borg prune -v --list "$BORG_REPO" \
|
||||
--keep-daily=7 \
|
||||
--keep-weekly=52 \
|
||||
--keep-monthly=-1
|
||||
|
||||
echo "$timestamp - backup completed successfully."
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
# create timer to run backups daily
|
||||
systemd.timers.backups = {
|
||||
description = "daily borg backup timer";
|
||||
wantedBy = [ "timers.target" ];
|
||||
timerConfig = {
|
||||
OnCalendar = "daily";
|
||||
Persistent = true;
|
||||
};
|
||||
};
|
||||
|
||||
# install borg binary
|
||||
environment.systemPackages = [ pkgs.borgbackup ];
|
||||
|
||||
# declare secret for repo password
|
||||
sops.secrets = {
|
||||
"borg_passwd" = {
|
||||
owner = "root";
|
||||
group = "root";
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
# add to modules
|
||||
# modules.system.backups.paths = lib.mkIf cfg.backups [ <path> ];
|
||||
@@ -6,6 +6,7 @@
|
||||
./backups.nix
|
||||
./sops.nix
|
||||
./docker.nix
|
||||
./podman.nix
|
||||
./tailscale.nix
|
||||
./vpns.nix
|
||||
./vpn-confinement.nix
|
||||
@@ -23,4 +24,9 @@
|
||||
modules.system.syncthing.enable = lib.mkDefault false;
|
||||
modules.system.nvidia.enable = lib.mkDefault false;
|
||||
|
||||
|
||||
|
||||
# modules.system.backups.baks = {
|
||||
# ${service} = { paths = [ cfg.data_dir ]; };
|
||||
# };
|
||||
}
|
||||
|
||||
24
modules/system/podman.nix
Normal file
24
modules/system/podman.nix
Normal file
@@ -0,0 +1,24 @@
|
||||
{ pkgs, config, lib, ... }:
|
||||
|
||||
let
|
||||
cfg = config.modules.system.podman;
|
||||
in
|
||||
{
|
||||
options.modules.system.podman = {
|
||||
enable = lib.mkEnableOption "enables podman";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
virtualisation = {
|
||||
oci-containers.backend = "podman";
|
||||
podman = {
|
||||
enable = true;
|
||||
dockerCompat = true;
|
||||
autoPrune.enable = true;
|
||||
defaultNetwork.settings = {
|
||||
dns_enabled = true;
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -20,11 +20,12 @@ vpncon_mex_config: ENC[AES256_GCM,data:4i356X97sBoRliskmh5ewcEwZHkpo37IhPcemKVdW
|
||||
vaultwarden_admin_token: ENC[AES256_GCM,data:G1v3N064ci0Fw5EtTzaryailWpsv6f4w6eoHp2vjXIBtIlScdQk1Q0W+eDNRk8Wr2C3ysTXQNbyYismNsls+jeS3W+YqkKL4fnh3a5UTzQrMqvaH11n3ak0X9R9vmt+ZJXBrUrAOKJ6RPHJJSWenhjDB77kwEdQ=,iv:f8X+x/AdmZ3b3dtcSFrxGgA2tCgDRpgddjlVu3mdCmM=,tag:c0MXljVvhwOdvrb/8hWlsQ==,type:str]
|
||||
#ENC[AES256_GCM,data:2ESzSsQZqKdjD7OXN8ZPThj6g9acJREe,iv:aDFPB0vs8NNo8ExLcJw7qtQvWbCb1XK6TJrHSK86qss=,tag:z+dypHAGUjEXP7Y9MHYWwg==,type:comment]
|
||||
gitea_database_password: ENC[AES256_GCM,data:nhFn0/G7gW5rk996OZzlcTt7T9KMbP8MNM+ReFC8w1H9ZqBSJUbs3K+n68uQVrkOVSXE0cKpOR1VbQ+i+46z3g==,iv:bT4GRZZ83v47/EmeV2KaUFo+4qTT4T2AktFUpPiZdF4=,tag:OC9TInkAr1egM+xnBDizxw==,type:str]
|
||||
#ENC[AES256_GCM,data:nbB5Cd7i/KTMCjCzcX8o1sxREZQ/gLAG,iv:iyuO2erxdJM08WHJBjKuNIXYxVhH7rfyOLTcGCcGqNQ=,tag:UeDszimXv8kQUmDetLeFqg==,type:comment]
|
||||
mosquitto_password_file: ENC[AES256_GCM,data:7ifs2hGnFQSgJOAKpN0usfiaqLjj7Rjb7zn1/qBDbqEi5hV0JfUncZGorBivR/+kjXHQO6nxaHcKqYvPedNdJ7Qy4/uil/xwgwSmzcbisdVYkhd2pf/N34EQFxmqohud0aTH9V47QbgTdrUPfvsiL+ljLvLu4w==,iv:z7YPIfJHHaLOJrDVnMQhgcMzYAPordFR11kHRAzZqYU=,tag:LRddczdvy01YTm2DFDgSJQ==,type:str]
|
||||
#ENC[AES256_GCM,data:HJ81OxRD2xtNZKv+8oDqiT8mYpv45JMvjxU5pdmEKzl64SK3lQ==,iv:wStoC6XaZlvRPfbqti2CUbPrOOTt4KktaUp2ecVrggU=,tag:isOwKfNdQZAM+E8YQXBSFA==,type:comment]
|
||||
velocity_forwarding: ENC[AES256_GCM,data:MUNhW3q0/klK51k3,iv:dGT5N+IrZfBxMIwa0mUrIKF2HJvx/uZ5o/ps6bgDNOE=,tag:KNY2LKwmmnCdWqRnxSKctw==,type:str]
|
||||
minecraft_recpro_db_passwd: ENC[AES256_GCM,data:dPAkdEX0hBigo/lND2r3ShxnS4Jc5wTI2ShcKnvjig==,iv:WjPugYspUvhy6TAh5UF3etvxTZjAPe3bkgFxIkh6FDw=,tag:h9LGoxp2x8PHxcP8fEkSlA==,type:str]
|
||||
#ENC[AES256_GCM,data:nbB5Cd7i/KTMCjCzcX8o1sxREZQ/gLAG,iv:iyuO2erxdJM08WHJBjKuNIXYxVhH7rfyOLTcGCcGqNQ=,tag:UeDszimXv8kQUmDetLeFqg==,type:comment]
|
||||
mosquitto_hashed_passwd: ENC[AES256_GCM,data:k1Lnr8ZTDpzXMoRmRH61X41boX/D8Rm1KPh7x3/IHFo+XKIOUQns53iA+7e7Ohp8uWSthDlOk4SlRvTXdUNiEz7Zmw9LYwy7BHbwpNo2pFApAye1ORPrMrhMUkUfgBgc8oqPPyRXmmrOAFp6GBbRhg==,iv:D8wQL9iF0rqOte5X24kDTVjYUJXbZSLz0Ykbp0HqmYo=,tag:RUCgO1uKPIdumSo563cg1Q==,type:str]
|
||||
mosquitto_passwd.yaml: ENC[AES256_GCM,data:9xwHiUaQ6zG/4rkRemXtbRJ/KEV4yajqyYlcXRR1eAQ2XijYOzitPjt53h3FPqp5rxl6dJerXNH5CiZZK3t1l339NxNseJFGVmIHitWJxNmGJMlG3M8r8Q==,iv:C6WWZuVkYaasB2pol3uf4Mc3d/lDEgt2pKX+dHl/Cr4=,tag:jYTC6RKF2TzDSwSUh6D8zQ==,type:str]
|
||||
sops:
|
||||
age:
|
||||
- recipient: age14gfh682a7m7jfp3qrulql03x5rs7yedwmxwksxrrmgjsunstyuksqx93pz
|
||||
@@ -36,7 +37,7 @@ sops:
|
||||
U0tmdFBuZnJES3piOTZNV0VKQmQ0eVUKCWRQ/flLzmpC64WyLoipklZBmrkpYiUg
|
||||
PRu+itNolpPTHm96pe+P93g2iP0wgekG0cX21wkiU2xaLF3dY2FEIA==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-10-10T08:43:27Z"
|
||||
mac: ENC[AES256_GCM,data:3mH0+EY8MFLe78x38CFyWY7CzgkRftAAy25y6lWcqeY8U6XT9CCenaL6vsbZO5j1ypXMtYMlJOO2VFgM5SmbdEKY1rzZldNOoyeMpfV/hHRI6Gm1dD9IyXFFISb12MhO3kt/stWRs84ufGkKe/BpjcurnFlbCAy064cQd9Knu1Y=,iv:KZOlNj/WkbhwgY/OvuY+emTtYftaFZWi+CFIZwFfXiw=,tag:adndDqlpqiVx6VYqKLVETQ==,type:str]
|
||||
lastmodified: "2025-10-11T10:14:22Z"
|
||||
mac: ENC[AES256_GCM,data:80GGFasWeFt8D6clEJ8xO2xLQG+xRrekNeu2M7VMvFyPaigYPWz1oMTN4zmbWSX+MCpc/EZuP3rRm7o33embAY3z4qxKuXexTwn4a36xHr1aNCSE5JYXnc3d+e48MnOD284QTWJD1+SEQ2pt2OraDa73HGYckUXz0g9yduLx4tc=,iv:mFLSg+C6BbNu5cneSJZE6tdZGmxHDfHCeVscWZtHB8k=,tag:GP8wpdwstFtIFxuoUPi/3g==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.11.0
|
||||
|
||||
@@ -28,13 +28,14 @@ map ] half-down
|
||||
# files & archives
|
||||
map ad mkdir
|
||||
map af mkfile
|
||||
map ab mkbak
|
||||
map ae extract
|
||||
map aa archive
|
||||
|
||||
# trash
|
||||
map gt cd ~/.local/share/Trash/files
|
||||
map <delete> trash
|
||||
map <s-delete> $trash-restore
|
||||
map <s-delete> $trash restore
|
||||
|
||||
# --- functions ---
|
||||
|
||||
@@ -78,7 +79,7 @@ cmd archive %{{
|
||||
}}
|
||||
|
||||
# move files to trash
|
||||
cmd trash %IFS="$(printf '\n\t')"; trash-put $fx
|
||||
cmd trash %IFS="$(printf '\n\t')"; trash put $fx
|
||||
|
||||
# make a directory
|
||||
cmd mkdir %{{
|
||||
@@ -100,4 +101,10 @@ cmd mkfile %{{
|
||||
fi
|
||||
}}
|
||||
|
||||
# make backup
|
||||
cmd mkbak %{{
|
||||
for x in $fx; do
|
||||
cp $x $x.bak
|
||||
done
|
||||
|
||||
}}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
imagemagick
|
||||
sops
|
||||
usbutils
|
||||
trashy
|
||||
];
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user