feat(dashy): broken
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
{ config, ... }:
|
{config, ...}: {
|
||||||
{
|
|
||||||
server = {
|
server = {
|
||||||
enable = true;
|
enable = true;
|
||||||
email = "adam@cnst.dev";
|
email = "adam@cnst.dev";
|
||||||
@@ -9,11 +8,6 @@
|
|||||||
uid = 994;
|
uid = 994;
|
||||||
gid = 993;
|
gid = 993;
|
||||||
|
|
||||||
mounts = {
|
|
||||||
fast = "/mnt/user";
|
|
||||||
config = "/persist/opt/services";
|
|
||||||
};
|
|
||||||
|
|
||||||
unbound = {
|
unbound = {
|
||||||
enable = true;
|
enable = true;
|
||||||
};
|
};
|
||||||
@@ -73,6 +67,7 @@
|
|||||||
podman = {
|
podman = {
|
||||||
enable = true;
|
enable = true;
|
||||||
gluetun.enable = true;
|
gluetun.enable = true;
|
||||||
|
dashy.enable = true;
|
||||||
qbittorrent = {
|
qbittorrent = {
|
||||||
enable = true;
|
enable = true;
|
||||||
port = 8080;
|
port = 8080;
|
||||||
|
|||||||
@@ -2,43 +2,37 @@
|
|||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
inherit (lib) mkIf mkEnableOption;
|
inherit (lib) mkIf mkEnableOption;
|
||||||
cfg = config.server.caddy;
|
cfg = config.server.caddy;
|
||||||
|
|
||||||
getCloudflareCredentials =
|
getCloudflareCredentials = hostname:
|
||||||
hostname:
|
if hostname == "ziggy"
|
||||||
if hostname == "ziggy" then
|
then config.age.secrets.cloudflareDnsCredentialsZiggy.path
|
||||||
config.age.secrets.cloudflareDnsCredentialsZiggy.path
|
else if hostname == "sobotka"
|
||||||
else if hostname == "sobotka" then
|
then config.age.secrets.cloudflareDnsCredentials.path
|
||||||
config.age.secrets.cloudflareDnsCredentials.path
|
else throw "Unknown hostname: ${hostname}";
|
||||||
else
|
in {
|
||||||
throw "Unknown hostname: ${hostname}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options = {
|
options = {
|
||||||
server.caddy.enable = mkEnableOption "Enables caddy";
|
server.caddy.enable = mkEnableOption "Enables caddy";
|
||||||
};
|
};
|
||||||
config = mkIf cfg.enable {
|
config = mkIf cfg.enable {
|
||||||
networking.firewall =
|
networking.firewall = let
|
||||||
let
|
ports = [
|
||||||
ports = [
|
80
|
||||||
80
|
443
|
||||||
443
|
];
|
||||||
];
|
in {
|
||||||
in
|
allowedTCPPorts = ports;
|
||||||
{
|
};
|
||||||
allowedTCPPorts = ports;
|
|
||||||
};
|
|
||||||
|
|
||||||
security.acme = {
|
security.acme = {
|
||||||
acceptTerms = true;
|
acceptTerms = true;
|
||||||
defaults.email = config.server.email;
|
defaults.email = config.server.email;
|
||||||
certs.${config.server.domain} = {
|
certs.${config.server.domain} = {
|
||||||
reloadServices = [ "caddy.service" ];
|
reloadServices = ["caddy.service"];
|
||||||
domain = "${config.server.domain}";
|
domain = "${config.server.domain}";
|
||||||
extraDomainNames = [ "*.${config.server.domain}" ];
|
extraDomainNames = ["*.${config.server.domain}"];
|
||||||
dnsProvider = "cloudflare";
|
dnsProvider = "cloudflare";
|
||||||
dnsResolver = "1.1.1.1:53";
|
dnsResolver = "1.1.1.1:53";
|
||||||
dnsPropagationCheck = true;
|
dnsPropagationCheck = true;
|
||||||
|
|||||||
@@ -1,11 +1,15 @@
|
|||||||
{ config, lib, ... }:
|
{
|
||||||
let
|
pkgs,
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
unit = "dashy";
|
unit = "dashy";
|
||||||
cfg = config.server.${unit};
|
cfg = config.server.${unit};
|
||||||
srv = config.server;
|
srv = config.server;
|
||||||
|
|
||||||
hl = config.server;
|
hl = config.server;
|
||||||
mergedServices = hl // (hl.podman or { });
|
mergedServices = hl // (hl.podman or {});
|
||||||
|
|
||||||
dashyCategories = [
|
dashyCategories = [
|
||||||
"Arr"
|
"Arr"
|
||||||
@@ -15,42 +19,70 @@ let
|
|||||||
"Smart Home"
|
"Smart Home"
|
||||||
];
|
];
|
||||||
|
|
||||||
getServicesByCategory =
|
getServicesByCategory = cat:
|
||||||
cat:
|
|
||||||
lib.attrsets.filterAttrs (name: value: (value ? category && value.category == cat)) mergedServices;
|
lib.attrsets.filterAttrs (name: value: (value ? category && value.category == cat)) mergedServices;
|
||||||
|
|
||||||
mkItems =
|
# This function was missing its 'services' argument at the end of the call.
|
||||||
services:
|
mkItems = services:
|
||||||
lib.attrsets.mapAttrsToList (name: value: {
|
lib.attrsets.mapAttrsToList (name: value: {
|
||||||
title = value.name or name;
|
title = value.name or name;
|
||||||
description = value.description or "";
|
description = value.description or "";
|
||||||
url =
|
url =
|
||||||
if value ? href then
|
if value ? href
|
||||||
value.href
|
then value.href
|
||||||
else
|
else if value ? url
|
||||||
(if value ? url then "https://${value.url}${value.path or ""}" else "");
|
then "https://${value.url}${value.path or ""}"
|
||||||
|
else "";
|
||||||
icon = value.icon or "";
|
icon = value.icon or "";
|
||||||
}) services;
|
})
|
||||||
in
|
services; # <-- FIX: Added the 'services' argument here.
|
||||||
{
|
|
||||||
|
esc = s: lib.replaceStrings ["\""] ["\\\""] (toString s);
|
||||||
|
|
||||||
|
renderSection = {
|
||||||
|
name,
|
||||||
|
icon,
|
||||||
|
items,
|
||||||
|
}: ''
|
||||||
|
- name: "${esc name}"
|
||||||
|
icon: "${esc icon}"
|
||||||
|
items:
|
||||||
|
${lib.concatStringsSep "\n" (
|
||||||
|
lib.lists.map (item: ''
|
||||||
|
- title: "${esc item.title}"
|
||||||
|
description: "${esc item.description}"
|
||||||
|
url: "${esc item.url}"
|
||||||
|
icon: "${esc item.icon}"
|
||||||
|
'')
|
||||||
|
items
|
||||||
|
)}
|
||||||
|
'';
|
||||||
|
in {
|
||||||
options.server.${unit} = {
|
options.server.${unit} = {
|
||||||
enable = lib.mkEnableOption {
|
enable = lib.mkEnableOption {
|
||||||
description = "Enable ${unit}";
|
description = "Enable ${unit}";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
configFile = lib.mkOption {
|
||||||
|
type = lib.types.path;
|
||||||
|
readOnly = true;
|
||||||
|
internal = true;
|
||||||
|
description = "Path to the generated Dashy config file.";
|
||||||
|
};
|
||||||
|
|
||||||
misc = lib.mkOption {
|
misc = lib.mkOption {
|
||||||
default = [ ];
|
default = [];
|
||||||
type = lib.types.listOf (
|
type = lib.types.listOf (
|
||||||
lib.types.attrsOf (
|
lib.types.attrsOf (
|
||||||
lib.types.submodule {
|
lib.types.submodule {
|
||||||
options = {
|
options = {
|
||||||
name = lib.mkOption { type = lib.types.str; };
|
name = lib.mkOption {type = lib.types.str;};
|
||||||
description = lib.mkOption {
|
description = lib.mkOption {
|
||||||
type = lib.types.str;
|
type = lib.types.str;
|
||||||
default = "";
|
default = "";
|
||||||
};
|
};
|
||||||
href = lib.mkOption { type = lib.types.str; };
|
href = lib.mkOption {type = lib.types.str;};
|
||||||
icon = lib.mkOption { type = lib.types.str; };
|
icon = lib.mkOption {type = lib.types.str;};
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
@@ -61,72 +93,59 @@ in
|
|||||||
config = lib.mkIf cfg.enable {
|
config = lib.mkIf cfg.enable {
|
||||||
services.glances.enable = true;
|
services.glances.enable = true;
|
||||||
|
|
||||||
services.${unit} = {
|
server.dashy.configFile = pkgs.writeText "conf.yml" ''
|
||||||
enable = true;
|
pageInfo:
|
||||||
port = cfg.port or 8081;
|
title: "${esc "${srv.domain} Homelab"}"
|
||||||
extraOptions = [
|
description: "${esc "Homelab made with NixOS"}"
|
||||||
"-p"
|
navLinks:
|
||||||
"${toString config.services.${unit}.port}:80"
|
- title: "GitHub"
|
||||||
];
|
path: "https://github.com/cnsta/cnix"
|
||||||
|
|
||||||
settings = {
|
appConfig:
|
||||||
pageInfo = {
|
theme: "material-dark"
|
||||||
title = "${srv.domain} Homelab";
|
layout: "auto"
|
||||||
description = "Homelab made with NixOS";
|
iconSize: "medium"
|
||||||
navLinks = [
|
language: "en"
|
||||||
{
|
statusCheck: true
|
||||||
title = "GitHub";
|
hideComponents:
|
||||||
path = "https://github.com/cnsta/cnix";
|
hideSettings: false
|
||||||
|
|
||||||
|
sections:
|
||||||
|
${lib.concatStringsSep "\n" (
|
||||||
|
lib.lists.map (
|
||||||
|
cat:
|
||||||
|
renderSection {
|
||||||
|
name = cat;
|
||||||
|
icon = "fas fa-box";
|
||||||
|
items = mkItems (getServicesByCategory cat);
|
||||||
}
|
}
|
||||||
];
|
)
|
||||||
};
|
dashyCategories
|
||||||
|
)}
|
||||||
appConfig = {
|
${renderSection {
|
||||||
theme = "material-dark";
|
name = "Misc";
|
||||||
layout = "auto";
|
icon = "fas fa-ellipsis-h";
|
||||||
iconSize = "medium";
|
items =
|
||||||
language = "en";
|
lib.lists.map (x: {
|
||||||
statusCheck = true;
|
title = x.name;
|
||||||
hideComponents.hideSettings = false;
|
description = x.description or "";
|
||||||
};
|
url = x.href or "";
|
||||||
|
icon = x.icon or "";
|
||||||
sections =
|
})
|
||||||
(lib.lists.forEach dashyCategories (cat: {
|
cfg.misc;
|
||||||
name = cat;
|
}}
|
||||||
icon = "fas fa-box"; # adjust per category
|
${renderSection {
|
||||||
items = mkItems (getServicesByCategory cat);
|
name = "Monitoring";
|
||||||
}))
|
icon = "fas fa-monitor-heart-rate";
|
||||||
++ [
|
items = [
|
||||||
{
|
{
|
||||||
name = "Misc";
|
title = "Glances";
|
||||||
icon = "fas fa-ellipsis-h";
|
description = "System Monitoring";
|
||||||
items = lib.lists.map (x: {
|
url = "http://localhost:${toString config.services.glances.port}";
|
||||||
title = x.name;
|
icon = "hl-glances";
|
||||||
description = x.description or "";
|
}
|
||||||
url = x.href or "";
|
];
|
||||||
icon = x.icon or "";
|
}}
|
||||||
}) cfg.misc;
|
'';
|
||||||
}
|
|
||||||
{
|
|
||||||
name = "Monitoring";
|
|
||||||
icon = "fas fa-monitor-heart-rate";
|
|
||||||
items = [
|
|
||||||
{
|
|
||||||
title = "Glances";
|
|
||||||
url = "http://localhost:${toString config.services.glances.port}";
|
|
||||||
icon = "hl-glances";
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
services.caddy.virtualHosts."${srv.domain}" = {
|
|
||||||
useACMEHost = srv.domain;
|
|
||||||
extraConfig = ''
|
|
||||||
reverse_proxy http://127.0.0.1:${toString config.services.${unit}.port}
|
|
||||||
'';
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,32 +2,40 @@
|
|||||||
config,
|
config,
|
||||||
lib,
|
lib,
|
||||||
...
|
...
|
||||||
}:
|
}: let
|
||||||
let
|
|
||||||
srv = config.server;
|
srv = config.server;
|
||||||
cfg = config.server.podman;
|
cfg = config.server.podman;
|
||||||
|
|
||||||
piholeUrl =
|
piholeUrl =
|
||||||
if config.networking.hostName == "sobotka" then
|
if config.networking.hostName == "sobotka"
|
||||||
"pihole0"
|
then "pihole0"
|
||||||
else if config.networking.hostName == "ziggy" then
|
else if config.networking.hostName == "ziggy"
|
||||||
"pihole1"
|
then "pihole1"
|
||||||
else
|
else throw "Unknown hostname";
|
||||||
throw "Unknown hostname";
|
|
||||||
|
|
||||||
getPiholeSecret =
|
getPiholeSecret = hostname:
|
||||||
hostname:
|
if hostname == "ziggy"
|
||||||
if hostname == "ziggy" then
|
then [config.age.secrets.piholeZiggy.path]
|
||||||
[ config.age.secrets.piholeZiggy.path ]
|
else if hostname == "sobotka"
|
||||||
else if hostname == "sobotka" then
|
then [config.age.secrets.pihole.path]
|
||||||
[ config.age.secrets.pihole.path ]
|
else throw "Unknown hostname: ${hostname}";
|
||||||
else
|
in {
|
||||||
throw "Unknown hostname: ${hostname}";
|
|
||||||
in
|
|
||||||
{
|
|
||||||
options.server.podman = {
|
options.server.podman = {
|
||||||
enable = lib.mkEnableOption "Enables Podman";
|
enable = lib.mkEnableOption "Enables Podman";
|
||||||
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
gluetun.enable = lib.mkEnableOption "Enables gluetun";
|
||||||
|
dashy = {
|
||||||
|
enable = lib.mkEnableOption "Enable dashy";
|
||||||
|
port = lib.mkOption {
|
||||||
|
type = lib.types.int;
|
||||||
|
default = 8081;
|
||||||
|
description = "The port to host Dashy on.";
|
||||||
|
};
|
||||||
|
url = lib.mkOption {
|
||||||
|
type = lib.types.str;
|
||||||
|
default = "dashy.${srv.domain}";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
qbittorrent = {
|
qbittorrent = {
|
||||||
enable = lib.mkEnableOption "Enable qBittorrent";
|
enable = lib.mkEnableOption "Enable qBittorrent";
|
||||||
url = lib.mkOption {
|
url = lib.mkOption {
|
||||||
@@ -141,6 +149,15 @@ in
|
|||||||
};
|
};
|
||||||
|
|
||||||
services.caddy.virtualHosts = lib.mkMerge [
|
services.caddy.virtualHosts = lib.mkMerge [
|
||||||
|
(lib.mkIf cfg.dashy.enable {
|
||||||
|
"${cfg.dashy.url}" = {
|
||||||
|
useACMEHost = srv.domain;
|
||||||
|
extraConfig = ''
|
||||||
|
reverse_proxy http://127.0.0.1:${toString cfg.dashy.port}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
(lib.mkIf cfg.qbittorrent.enable {
|
(lib.mkIf cfg.qbittorrent.enable {
|
||||||
"${cfg.qbittorrent.url}" = {
|
"${cfg.qbittorrent.url}" = {
|
||||||
useACMEHost = srv.domain;
|
useACMEHost = srv.domain;
|
||||||
@@ -181,12 +198,12 @@ in
|
|||||||
"5031:5031"
|
"5031:5031"
|
||||||
"50300:50300"
|
"50300:50300"
|
||||||
];
|
];
|
||||||
devices = [ "/dev/net/tun:/dev/net/tun" ];
|
devices = ["/dev/net/tun:/dev/net/tun"];
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
extraOptions = [
|
extraOptions = [
|
||||||
"--cap-add=NET_ADMIN"
|
"--cap-add=NET_ADMIN"
|
||||||
];
|
];
|
||||||
volumes = [ "/var:/gluetun" ];
|
volumes = ["/var:/gluetun"];
|
||||||
environmentFiles = [
|
environmentFiles = [
|
||||||
config.age.secrets.gluetunEnvironment.path
|
config.age.secrets.gluetunEnvironment.path
|
||||||
];
|
];
|
||||||
@@ -199,11 +216,22 @@ in
|
|||||||
};
|
};
|
||||||
})
|
})
|
||||||
|
|
||||||
|
(lib.mkIf cfg.dashy.enable {
|
||||||
|
dashy = {
|
||||||
|
image = "lissy93/dashy:latest";
|
||||||
|
autoStart = true;
|
||||||
|
ports = ["${toString cfg.dashy.port}:80"];
|
||||||
|
volumes = [
|
||||||
|
"${srv.dashy.configFile}:/app/user-data/conf.yml"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
})
|
||||||
|
|
||||||
(lib.mkIf cfg.qbittorrent.enable {
|
(lib.mkIf cfg.qbittorrent.enable {
|
||||||
qbittorrent = {
|
qbittorrent = {
|
||||||
image = "ghcr.io/hotio/qbittorrent:latest";
|
image = "ghcr.io/hotio/qbittorrent:latest";
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
dependsOn = [ "gluetun" ];
|
dependsOn = ["gluetun"];
|
||||||
ports = [
|
ports = [
|
||||||
"8080:8080"
|
"8080:8080"
|
||||||
"58846:58846"
|
"58846:58846"
|
||||||
@@ -231,7 +259,7 @@ in
|
|||||||
slskd = {
|
slskd = {
|
||||||
image = "slskd/slskd:latest";
|
image = "slskd/slskd:latest";
|
||||||
autoStart = true;
|
autoStart = true;
|
||||||
dependsOn = [ "gluetun" ];
|
dependsOn = ["gluetun"];
|
||||||
ports = [
|
ports = [
|
||||||
"5030:5030"
|
"5030:5030"
|
||||||
"5031:5031"
|
"5031:5031"
|
||||||
|
|||||||
Reference in New Issue
Block a user