mirror of
https://github.com/oddlama/nix-config.git
synced 2025-10-10 23:00:39 +02:00
feat(topology): extract more service info and add helper functions to define stuff
This commit is contained in:
parent
cc35dd599a
commit
30579a433e
12 changed files with 174 additions and 175 deletions
168
flake.nix
168
flake.nix
|
@ -183,151 +183,65 @@
|
|||
{
|
||||
inherit pkgs;
|
||||
modules = [
|
||||
{
|
||||
({config, ...}: let
|
||||
inherit
|
||||
(config.lib.helpers)
|
||||
mkInternet
|
||||
mkSwitch
|
||||
mkRouter
|
||||
mkConnection
|
||||
mkConnectionRev
|
||||
;
|
||||
in {
|
||||
renderer = "elk";
|
||||
nixosConfigurations = self.nodes;
|
||||
|
||||
nodes.internet = {
|
||||
name = "Internet";
|
||||
deviceType = "internet";
|
||||
hardware.image = ./cloud.svg;
|
||||
# interfaces.eth0.network = "internet";
|
||||
interfaces.eth0.physicalConnections = [
|
||||
{
|
||||
node = "fritzbox";
|
||||
interface = "wan0";
|
||||
}
|
||||
{
|
||||
node = "sentinel";
|
||||
interface = "wan";
|
||||
}
|
||||
];
|
||||
};
|
||||
nodes.internet = mkInternet {};
|
||||
nodes.sentinel.interfaces.wan.physicalConnections = [(mkConnectionRev "internet" "*")];
|
||||
|
||||
nodes.fritzbox = {
|
||||
name = "FritzBox";
|
||||
deviceType = "router";
|
||||
hardware.info = "FRITZ!Box 7520";
|
||||
hardware.image = ./fritzbox.png;
|
||||
# interfaces.wan0.network = "internet";
|
||||
interfaces.wan0 = {};
|
||||
interfaces.eth0.physicalConnections = [
|
||||
{
|
||||
node = "ward";
|
||||
interface = "wan";
|
||||
}
|
||||
nodes.fritzbox = mkRouter "FritzBox" {
|
||||
info = "FRITZ!Box 7520";
|
||||
image = ./fritzbox.png;
|
||||
interfaceGroups = [
|
||||
["eth1" "eth2" "eth3" "eth4"]
|
||||
["wan1"]
|
||||
];
|
||||
connections.eth1 = mkConnection "ward" "wan";
|
||||
connections.wan1 = mkConnectionRev "internet" "*";
|
||||
};
|
||||
|
||||
# TODO: extract from kea!
|
||||
networks.home-lan = {
|
||||
name = "Home LAN";
|
||||
cidrv4 = "192.168.1.0/24";
|
||||
#color = "#78dba9";
|
||||
};
|
||||
|
||||
networks.home-fritzbox = {
|
||||
name = "Home Fritzbox";
|
||||
cidrv4 = "192.168.178.0/24";
|
||||
#color = "#f1cf8a";
|
||||
};
|
||||
|
||||
nodes.switch-attic = mkSwitch "Switch Attic" {
|
||||
info = "D-Link DGS-1016D";
|
||||
image = ./dlink-dgs1016d.png;
|
||||
interfaceGroups = [["eth1" "eth2" "eth3" "eth4" "eth5" "eth6"]];
|
||||
connections.eth1 = mkConnection "ward" "lan";
|
||||
connections.eth2 = mkConnection "sire" "lan";
|
||||
connections.eth3 = [];
|
||||
};
|
||||
|
||||
nodes.switch-bedroom-1 = mkSwitch "Switch Bedroom 1" {
|
||||
info = "D-Link DGS-105";
|
||||
image = ./dlink-dgs105.png;
|
||||
interfaceGroups = [["eth1" "eth2" "eth3" "eth4" "eth5"]];
|
||||
connections.eth1 = mkConnection "switch-attic" "eth3";
|
||||
connections.eth2 = mkConnection "kroma" "lan1";
|
||||
connections.eth3 = mkConnection "nom" "lan1";
|
||||
};
|
||||
})
|
||||
{
|
||||
nodes.ward.interfaces.lan.network = "home-lan";
|
||||
nodes.fritzbox.interfaces.eth0.network = "home-fritzbox";
|
||||
|
||||
nodes.switch-attic = {
|
||||
name = "Switch Attic";
|
||||
deviceType = "switch";
|
||||
hardware.info = "D-Link DGS-1016D";
|
||||
hardware.image = ./dlink-dgs1016d.png;
|
||||
|
||||
interfaces.eth0.sharesNetworkWith = _: true;
|
||||
interfaces.eth1.sharesNetworkWith = _: true;
|
||||
interfaces.eth2.sharesNetworkWith = _: true;
|
||||
|
||||
interfaces.eth0.physicalConnections = [
|
||||
{
|
||||
node = "ward";
|
||||
interface = "lan";
|
||||
}
|
||||
];
|
||||
interfaces.eth1.physicalConnections = [
|
||||
{
|
||||
node = "sire";
|
||||
interface = "lan";
|
||||
}
|
||||
];
|
||||
interfaces.eth2 = {};
|
||||
};
|
||||
|
||||
nodes.switch-bedroom-1 = {
|
||||
name = "Switch Bedroom 1";
|
||||
deviceType = "switch";
|
||||
hardware.info = "D-Link DGS-105";
|
||||
hardware.image = ./dlink-dgs105.png;
|
||||
|
||||
interfaces.eth0.sharesNetworkWith = _: true;
|
||||
interfaces.eth1.sharesNetworkWith = _: true;
|
||||
interfaces.eth2.sharesNetworkWith = _: true;
|
||||
|
||||
interfaces.eth0.physicalConnections = [
|
||||
{
|
||||
node = "switch-attic";
|
||||
interface = "eth2";
|
||||
}
|
||||
];
|
||||
interfaces.eth1.physicalConnections = [
|
||||
{
|
||||
node = "kroma";
|
||||
interface = "lan1";
|
||||
}
|
||||
];
|
||||
interfaces.eth2.physicalConnections = [
|
||||
{
|
||||
node = "nom";
|
||||
interface = "lan1";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
#nodes.fritzbox-no-img = {
|
||||
# name = "FritzBox No HImg";
|
||||
# deviceType = "router";
|
||||
# interfaces.wan0.physicalConnections = [
|
||||
# {
|
||||
# node = "ward";
|
||||
# interface = "wan";
|
||||
# }
|
||||
# ];
|
||||
#};
|
||||
|
||||
#nodes.fritzbox-device-nd = {
|
||||
# name = "FritzBox No DImg";
|
||||
# deviceType = "device";
|
||||
# hardware.image = ./fritzbox.png;
|
||||
# interfaces.wan0.physicalConnections = [
|
||||
# {
|
||||
# node = "ward";
|
||||
# interface = "wan";
|
||||
# }
|
||||
# ];
|
||||
#};
|
||||
|
||||
#nodes.fritzbox-device = {
|
||||
# name = "FritzBox No D&HImg";
|
||||
# deviceType = "device";
|
||||
# interfaces.wan0.physicalConnections = [
|
||||
# {
|
||||
# node = "ward";
|
||||
# interface = "wan";
|
||||
# }
|
||||
# ];
|
||||
#};
|
||||
|
||||
# TODO:
|
||||
#nodes.fritzbox = config.lib.nodes.mkRouter {};
|
||||
#nodes.fritzbox = config.lib.nodes.mkSwitch {};
|
||||
#nodes.fritzbox = config.lib.nodes.mkWifiAP {};
|
||||
#nodes.printer = config.lib.nodes.mkWifiAP {};
|
||||
nodes.fritzbox.interfaces.eth1.network = "home-fritzbox";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
|
@ -20,6 +20,9 @@
|
|||
./net.nix
|
||||
];
|
||||
|
||||
topology.self.hardware.info = "AMD Ryzen Threadripper 1950X, 96GB RAM";
|
||||
topology.self.interfaces.lan.sharesNetworkWith = x: x == "lan-self";
|
||||
|
||||
boot.mode = "efi";
|
||||
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "e1000e" "alx"];
|
||||
|
||||
|
@ -81,6 +84,13 @@
|
|||
networking.nftables.firewall = {
|
||||
zones.untrusted.interfaces = [config.guests.${guestName}.networking.mainLinkName];
|
||||
};
|
||||
topology.self.interfaces.lan.physicalConnections = [
|
||||
{
|
||||
node = config.node.name;
|
||||
interface = "lan-self";
|
||||
renderer.reverse = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
|
@ -64,6 +64,7 @@ in {
|
|||
}
|
||||
];
|
||||
|
||||
topology.self.services.loki.info = "https://" + lokiDomain;
|
||||
services.loki = let
|
||||
lokiDir = "/var/lib/loki";
|
||||
in {
|
||||
|
|
|
@ -23,26 +23,7 @@
|
|||
|
||||
topology.self.hardware.image = ../../odroid-h3.png;
|
||||
topology.self.hardware.info = "ODROID H3, 64GB RAM";
|
||||
# TODO FIXME topology bogus
|
||||
topology.self.interfaces.lan-self.physicalConnections = [
|
||||
{
|
||||
node = config.node.name;
|
||||
interface = "lan";
|
||||
}
|
||||
];
|
||||
topology.self.interfaces.lan.physicalConnections =
|
||||
lib.flip map [
|
||||
"adguardhome"
|
||||
"forgejo"
|
||||
"kanidm"
|
||||
"radicale"
|
||||
"vaultwarden"
|
||||
] (
|
||||
x: {
|
||||
node = "ward-${x}";
|
||||
interface = "lan";
|
||||
}
|
||||
);
|
||||
topology.self.interfaces.lan.sharesNetworkWith = x: x == "lan-self";
|
||||
|
||||
boot.mode = "efi";
|
||||
boot.initrd.availableKernelModules = ["xhci_pci" "ahci" "nvme" "usbhid" "usb_storage" "sd_mod" "sdhci_pci" "r8169"];
|
||||
|
@ -87,6 +68,13 @@
|
|||
networking.nftables.firewall = {
|
||||
zones.untrusted.interfaces = [config.guests.${guestName}.networking.mainLinkName];
|
||||
};
|
||||
topology.self.interfaces.lan.physicalConnections = [
|
||||
{
|
||||
node = config.node.name;
|
||||
interface = "lan-self";
|
||||
renderer.reverse = true;
|
||||
}
|
||||
];
|
||||
}
|
||||
];
|
||||
};
|
||||
|
|
|
@ -48,6 +48,7 @@ in {
|
|||
allowedUDPPorts = [53];
|
||||
};
|
||||
|
||||
topology.self.services.adguardhome.info = "https://" + adguardhomeDomain;
|
||||
services.adguardhome = {
|
||||
enable = true;
|
||||
# TODO allow mutable settings, replace 123.123.123.123 with
|
||||
|
|
|
@ -43,6 +43,7 @@ in {
|
|||
}
|
||||
];
|
||||
|
||||
topology.self.services.radicale.info = "https://" + radicaleDomain;
|
||||
services.radicale = {
|
||||
enable = true;
|
||||
settings = {
|
||||
|
|
Before Width: | Height: | Size: 929 B After Width: | Height: | Size: 929 B |
|
@ -21,30 +21,57 @@ in {
|
|||
options.topology.extractors.services.enable = mkEnableOption "topology service extractor" // {default = true;};
|
||||
|
||||
config.topology.self.services = mkIf config.topology.extractors.services.enable {
|
||||
adguardhome = mkIf config.services.adguardhome.enable {
|
||||
name = "AdGuard Home";
|
||||
icon = "services.adguardhome";
|
||||
};
|
||||
adguardhome = let
|
||||
address = config.services.adguardhome.settings.bind_host or null;
|
||||
port = config.services.adguardhome.settings.bind_port or null;
|
||||
in
|
||||
mkIf config.services.adguardhome.enable {
|
||||
name = "AdGuard Home";
|
||||
icon = "services.adguardhome";
|
||||
details.listen = mkIf (address != null && port != null) {text = "${address}:${toString port}";};
|
||||
};
|
||||
|
||||
forgejo = mkIf config.services.forgejo.enable {
|
||||
name = "Forgejo";
|
||||
icon = "services.forgejo";
|
||||
};
|
||||
forgejo = let
|
||||
address = config.services.forgejo.settings.server.HTTP_ADDR or null;
|
||||
port = config.services.forgejo.settings.server.HTTP_PORT or null;
|
||||
in
|
||||
mkIf config.services.forgejo.enable {
|
||||
name =
|
||||
if config.services.forgejo.settings ? DEFAULT.APP_NAME
|
||||
then "Forgejo (${config.services.forgejo.settings.DEFAULT.APP_NAME})"
|
||||
else "Forgejo";
|
||||
icon = "services.forgejo";
|
||||
info = mkIf (config.services.forgejo.settings ? server.ROOT_URL) config.services.forgejo.settings.server.ROOT_URL;
|
||||
details.listen = mkIf (address != null && port != null) {text = "${address}:${toString port}";};
|
||||
};
|
||||
|
||||
grafana = mkIf config.services.grafana.enable {
|
||||
name = "Grafana";
|
||||
icon = "services.grafana";
|
||||
};
|
||||
grafana = let
|
||||
address = config.services.grafana.settings.server.http_addr or null;
|
||||
port = config.services.grafana.settings.server.http_port or null;
|
||||
in
|
||||
mkIf config.services.grafana.enable {
|
||||
name = "Grafana";
|
||||
icon = "services.grafana";
|
||||
info = config.services.grafana.settings.server.root_url;
|
||||
details.listen = mkIf (address != null && port != null) {text = "${address}:${toString port}";};
|
||||
};
|
||||
|
||||
kanidm = mkIf config.services.kanidm.enableServer {
|
||||
name = "Kanidm";
|
||||
icon = "services.kanidm";
|
||||
info = config.services.kanidm.serverSettings.origin;
|
||||
details.listen.text = config.services.kanidm.serverSettings.bindaddress;
|
||||
};
|
||||
|
||||
loki = mkIf config.services.loki.enable {
|
||||
name = "Loki";
|
||||
icon = "services.loki";
|
||||
};
|
||||
loki = let
|
||||
address = config.services.loki.configuration.server.http_listen_address or null;
|
||||
port = config.services.loki.configuration.server.http_listen_port or null;
|
||||
in
|
||||
mkIf config.services.loki.enable {
|
||||
name = "Loki";
|
||||
icon = "services.loki";
|
||||
details.listen = mkIf (address != null && port != null) {text = "${address}:${toString port}";};
|
||||
};
|
||||
|
||||
nginx = mkIf config.services.nginx.enable {
|
||||
name = "NGINX";
|
||||
|
@ -70,6 +97,7 @@ in {
|
|||
radicale = mkIf config.services.radicale.enable {
|
||||
name = "Radicale";
|
||||
icon = "services.radicale";
|
||||
details.listen = mkIf (config.services.radicale.settings ? server.hosts) {text = toString config.services.radicale.settings.server.hosts;};
|
||||
};
|
||||
|
||||
samba = mkIf config.services.samba.enable {
|
||||
|
|
|
@ -327,6 +327,11 @@ in
|
|||
icon = mkIf (config.topology.isMainModule && config.icons.interfaces ? ${submod.config.type}) (
|
||||
mkDefault ("interfaces." + submod.config.type)
|
||||
);
|
||||
|
||||
# For switches: Share the network with any other interface by default
|
||||
sharesNetworkWith = mkIf (config.topology.isMainModule && nodeSubmod.config.deviceType == "switch") (
|
||||
mkDefault (const true)
|
||||
);
|
||||
};
|
||||
}));
|
||||
};
|
||||
|
@ -335,9 +340,6 @@ in
|
|||
};
|
||||
|
||||
config = {
|
||||
lib.a.a = connections;
|
||||
lib.a.b = networkDefiningInterfaces;
|
||||
lib.a.c = propagatedNetworks;
|
||||
assertions = flatten (flip map (attrValues config.nodes) (
|
||||
node:
|
||||
flip map (attrValues node.interfaces) (
|
||||
|
|
|
@ -6,14 +6,17 @@ f: {
|
|||
inherit
|
||||
(lib)
|
||||
attrValues
|
||||
concatMap
|
||||
elem
|
||||
flatten
|
||||
flip
|
||||
literalExpression
|
||||
mapAttrsToList
|
||||
mkDefault
|
||||
mkIf
|
||||
mkMerge
|
||||
mkOption
|
||||
toList
|
||||
types
|
||||
;
|
||||
in
|
||||
|
@ -125,6 +128,56 @@ in
|
|||
};
|
||||
|
||||
config = {
|
||||
lib.helpers = rec {
|
||||
# Finally we found it, the one-and-only true cloud.
|
||||
mkInternet = {connections ? [], ...}: {
|
||||
name = "Internet";
|
||||
deviceType = "internet";
|
||||
hardware.image = ../icons/devices/cloud.svg;
|
||||
interfaces."*".physicalConnections = toList connections;
|
||||
};
|
||||
|
||||
mkConnection = node: interface: {inherit node interface;};
|
||||
mkConnectionRev = node: interface: {
|
||||
inherit node interface;
|
||||
renderer.reverse = true;
|
||||
};
|
||||
|
||||
mkSwitch = name: {
|
||||
info ? null,
|
||||
image ? null,
|
||||
interfaceGroups ? [],
|
||||
connections ? {},
|
||||
...
|
||||
}: {
|
||||
inherit name;
|
||||
deviceType = "switch";
|
||||
hardware = {
|
||||
info = mkIf (info != null) info;
|
||||
image = mkIf (image != null) image;
|
||||
};
|
||||
interfaces = mkMerge (
|
||||
flip mapAttrsToList connections (interface: conns: {
|
||||
${interface}.physicalConnections = toList conns;
|
||||
})
|
||||
++ flip concatMap interfaceGroups (
|
||||
group:
|
||||
flip map group (
|
||||
interface: {
|
||||
${interface}.sharesNetworkWith = x: elem x group;
|
||||
}
|
||||
)
|
||||
)
|
||||
);
|
||||
};
|
||||
|
||||
mkRouter = name: args:
|
||||
mkSwitch name args
|
||||
// {
|
||||
deviceType = "router";
|
||||
};
|
||||
};
|
||||
|
||||
assertions = flatten (
|
||||
flip map (attrValues config.nodes) (
|
||||
node: [
|
||||
|
|
|
@ -205,7 +205,7 @@
|
|||
"portLabels.placement" = "OUTSIDE";
|
||||
}
|
||||
// optionalAttrs (node.renderer.preferredType == "card") {
|
||||
"portConstraints" = "FIXED_SIDE";
|
||||
# "portConstraints" = "FIXED_SIDE";
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
# TODO:
|
||||
# - macvtap interface type svg with small link
|
||||
# - address port label render make newline capable (multiple port labels)
|
||||
# - NAT indication
|
||||
# - embed font globally, try removing satori embed?
|
||||
|
@ -115,9 +116,9 @@
|
|||
else net.style.secondaryColor;
|
||||
in
|
||||
{
|
||||
solid = ''<div tw="flex flex-none ${twAttrs} bg-[${net.style.primaryColor}] rounded-md"></div>'';
|
||||
dashed = ''<div tw="flex flex-none ${twAttrs} rounded-md" style="backgroundImage: linear-gradient(90deg, ${net.style.primaryColor} 0%, ${net.style.primaryColor} 50%, ${secondaryColor} 50.01%, ${secondaryColor} 100%);"></div>'';
|
||||
dotted = ''<div tw="flex flex-none ${twAttrs} rounded-md" style="backgroundImage: radial-gradient(circle, ${net.style.primaryColor} 30%, ${secondaryColor} 30.01%);"></div>'';
|
||||
solid = ''<div tw="flex flex-none ${twAttrs} bg-[${net.style.primaryColor}]"></div>'';
|
||||
dashed = ''<div tw="flex flex-none ${twAttrs}" style="backgroundImage: linear-gradient(90deg, ${net.style.primaryColor} 0%, ${net.style.primaryColor} 50%, ${secondaryColor} 50.01%, ${secondaryColor} 100%);"></div>'';
|
||||
dotted = ''<div tw="flex flex-none ${twAttrs}" style="backgroundImage: radial-gradient(circle, ${net.style.primaryColor} 30%, ${secondaryColor} 30.01%);"></div>'';
|
||||
}
|
||||
.${net.style.pattern};
|
||||
|
||||
|
@ -130,7 +131,7 @@
|
|||
*/
|
||||
''
|
||||
<div tw="flex flex-row mx-6 mt-2 items-center">
|
||||
${html.net.netStylePreview net "w-8 h-4 mr-4"}
|
||||
${html.net.netStylePreview net "w-12 h-4 mr-4 rounded-md"}
|
||||
<h2 tw="text-2xl font-bold">${net.name}</h2>
|
||||
<div tw="flex grow min-w-8"></div>
|
||||
${mkImageMaybe "w-12 h-12 ml-4" (config.lib.icons.get net.icon)}
|
||||
|
@ -160,12 +161,12 @@
|
|||
*/
|
||||
''
|
||||
<div tw="flex flex-col mx-4 mt-2 rounded-lg p-2">
|
||||
<div tw="flex flex-row items-center">
|
||||
${html.net.netStylePreview net "w-12 h-6 mr-4"}
|
||||
<div tw="flex flex-row">
|
||||
${html.net.netStylePreview net "w-12 h-4 mt-2 mr-4 rounded-md"}
|
||||
<div tw="flex flex-col grow">
|
||||
<h1 tw="text-lg font-bold m-0">${net.name}</h1>
|
||||
${optionalString (net.cidrv4 != null) ''<div tw="flex flex-row"><span tw="text-md m-0"><b>CIDRv4</b></span><span tw="text-md text-[${net.style.primaryColor}] m-0 ml-4">${net.cidrv4}</span></div>''}
|
||||
${optionalString (net.cidrv6 != null) ''<div tw="flex flex-row"><span tw="text-md m-0"><b>CIDRv6</b></span><span tw="text-md text-[${net.style.primaryColor}] m-0 ml-4">${net.cidrv6}</span></div>''}
|
||||
${optionalString (net.cidrv4 != null) ''<div tw="flex flex-row"><span tw="text-md text-[#7a899f] m-0"><b>CIDRv4</b></span><span tw="text-md text-[${net.style.primaryColor}] m-0 ml-4">${net.cidrv4}</span></div>''}
|
||||
${optionalString (net.cidrv6 != null) ''<div tw="flex flex-row"><span tw="text-md text-[#7a899f] m-0"><b>CIDRv6</b></span><span tw="text-md text-[${net.style.primaryColor}] m-0 ml-4">${net.cidrv6}</span></div>''}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue