Compare commits
200
Commits
| 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 ];
|
||||
# add to backups
|
||||
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 backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -83,7 +83,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -86,7 +86,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -84,7 +84,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.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}";
|
||||
@@ -102,7 +121,9 @@ in
|
||||
# };
|
||||
# };
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
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}";
|
||||
@@ -115,7 +123,9 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# add to backups
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -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 ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -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 backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir "/var/lib/redis-immich" ];
|
||||
# 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.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 ];
|
||||
# add to backups
|
||||
modules.system.backups.baks = {
|
||||
${service} = { paths = [ cfg.data_dir ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
@@ -119,7 +119,17 @@ in
|
||||
};
|
||||
};
|
||||
|
||||
# add to backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.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"
|
||||
];
|
||||
# imperative config
|
||||
# config = null;
|
||||
# lovelaceConfig = null;
|
||||
# configDir = cfg.data_dir;
|
||||
# declartive poggers!
|
||||
config = {
|
||||
# Includes dependencies for a basic setup
|
||||
default_config = {};
|
||||
# still suss as fuck bro man fuck
|
||||
virtualisation.oci-containers.containers = {
|
||||
hass = {
|
||||
image = "homeassistant/home-assistant:stable";
|
||||
autoStart = true;
|
||||
extraOptions = [
|
||||
"--pull=newer"
|
||||
"--network=host"
|
||||
];
|
||||
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 ];
|
||||
# add to backups
|
||||
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 ];
|
||||
# add to backups
|
||||
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 backups
|
||||
modules.system.backups.paths = lib.mkIf cfg.backup [ cfg.data_dir ];
|
||||
# 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.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 ]; };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
+82
-38
@@ -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 != []) {
|
||||
config = lib.mkIf (cfg.enable && cfg.baks != {}) {
|
||||
|
||||
# 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;
|
||||
# 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 create \
|
||||
--verbose \
|
||||
--filter AME \
|
||||
--list \
|
||||
--stats \
|
||||
--show-rc \
|
||||
--compression lz4 \
|
||||
"$BORG_REPO::${toString config.networking.hostName}-$timestamp" \
|
||||
${lib.concatStringsSep " " cfg.paths}
|
||||
borg break-lock "$BORG_REPO" || true
|
||||
|
||||
# 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 "starting backup at $timestamp"
|
||||
|
||||
echo "$timestamp - backup completed successfully."
|
||||
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 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 "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> ];
|
||||
|
||||
@@ -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 ]; };
|
||||
# };
|
||||
}
|
||||
|
||||
@@ -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