refactor: Migrate network, vhost, and firewall configurations to new pepe.core namespace

This commit is contained in:
Giulio De Pasquale (aider) 2025-04-26 16:55:36 +01:00
parent 8c72ff433c
commit 08ae792712
16 changed files with 200 additions and 150 deletions

View File

@ -1,148 +1,21 @@
{ config, lib, ... }:
with lib;
{
# Legacy compatibility layer
options.architect = {
firewall = {
openTCP = mkOption {
type = types.listOf types.int;
default = [ ];
};
openUDP = mkOption {
type = types.listOf types.int;
default = [ ];
};
firewall = lib.mkOption {
internal = true;
default = config.pepe.core.firewall;
};
networks = mkOption {
type = types.attrsOf (types.submodule {
options = {
interface = mkOption {
type = types.str;
description = "The network interface name.";
};
net = mkOption {
type = types.str;
description = "The network address in CIDR format.";
};
devices = mkOption {
type = types.attrsOf (types.submodule {
options = {
address = mkOption {
type = types.str;
description = "The IP address of the device.";
};
hostname = mkOption {
type = types.str;
description = "The hostname of the device.";
};
};
});
default = { };
description = "An attribute set of devices with their configurations.";
};
};
});
default = { };
description = "An attribute set of networks with their configurations.";
networks = lib.mkOption {
internal = true;
default = config.pepe.core.network.interfaces;
};
vhost = mkOption {
type = types.attrsOf (types.submodule {
options = {
dnsInterfaces = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of interfaces to add extra DNS hosts for this vhost.";
};
locations = mkOption {
type = types.attrsOf (types.submodule {
options = {
extraConfig = mkOption {
type = types.str;
description = "Extra configuration for the location.";
default = "";
};
allowLan = mkOption {
type = types.bool;
default = false;
};
proxyWebsockets = mkOption {
type = types.bool;
default = false;
};
host = mkOption {
type = types.str;
description = "The host for the location.";
default = "127.0.0.1";
};
port = mkOption {
type = types.int;
description = "The port number for the location.";
};
allow = mkOption {
type = types.listOf types.str;
default = [ ];
description = "IP address or CIDR block to allow.";
};
path = mkOption {
type = types.str;
default = "";
};
recommendedProxySettings = mkOption {
type = types.bool;
default = true;
description = "Force the use of recommended proxy configuration.";
};
allowWAN = mkOption {
type = types.bool;
default = false;
description = "If set to false, deny all WAN traffic.";
};
};
});
default = { };
description = "An attribute set of location configurations.";
};
};
});
default = { };
description = "An attribute set of domain configurations.";
vhost = lib.mkOption {
internal = true;
default = config.pepe.core.vhost.hosts;
};
};
# TODO: move to nginx
config = {
services.nginx.virtualHosts = mapAttrs
(domain: conf: {
forceSSL = true;
useACMEHost= "giugl.io";
locations = mapAttrs
(path: location: {
proxyPass = "http://${location.host}:${toString location.port}${location.path}";
proxyWebsockets = location.proxyWebsockets;
recommendedProxySettings = location.recommendedProxySettings;
extraConfig = ''
${concatMapStringsSep "\n" (allowCIDR: "allow ${allowCIDR};") location.allow}
${optionalString location.allowLan ''allow ${config.architect.networks."lan".net};''}
${optionalString (!location.allowWAN) "deny all;"}
'' + location.extraConfig;
})
conf.locations;
})
config.architect.vhost;
};
}

View File

@ -2,5 +2,8 @@
imports = [
./media.nix
./graphics.nix
./network.nix
./vhost.nix
./firewall.nix
];
}

27
modules/core/firewall.nix Normal file
View File

@ -0,0 +1,27 @@
{ config, lib, ... }:
let
inherit (lib) mkOption types;
cfg = config.pepe.core.firewall;
in
{
options.pepe.core.firewall = {
openTCP = mkOption {
type = types.listOf types.int;
default = [ ];
description = "TCP ports to open in the firewall";
};
openUDP = mkOption {
type = types.listOf types.int;
default = [ ];
description = "UDP ports to open in the firewall";
};
};
config = {
networking.firewall = {
allowedTCPPorts = cfg.openTCP;
allowedUDPPorts = cfg.openUDP;
};
};
}

45
modules/core/network.nix Normal file
View File

@ -0,0 +1,45 @@
{ config, lib, ... }:
let
inherit (lib) mkOption types;
cfg = config.pepe.core.network;
in
{
options.pepe.core.network = {
interfaces = mkOption {
type = types.attrsOf (types.submodule {
options = {
interface = mkOption {
type = types.str;
description = "The network interface name.";
};
net = mkOption {
type = types.str;
description = "The network address in CIDR format.";
};
devices = mkOption {
type = types.attrsOf (types.submodule {
options = {
address = mkOption {
type = types.str;
description = "The IP address of the device.";
};
hostname = mkOption {
type = types.str;
description = "The hostname of the device.";
};
};
});
default = { };
description = "An attribute set of devices with their configurations.";
};
};
});
default = { };
description = "An attribute set of networks with their configurations.";
};
};
}

102
modules/core/vhost.nix Normal file
View File

@ -0,0 +1,102 @@
{ config, lib, ... }:
let
inherit (lib) mkOption types mapAttrs concatMapStringsSep optionalString;
cfg = config.pepe.core.vhost;
in
{
options.pepe.core.vhost = {
hosts = mkOption {
type = types.attrsOf (types.submodule {
options = {
dnsInterfaces = mkOption {
type = types.listOf types.str;
default = [ ];
description = "List of interfaces to add extra DNS hosts for this vhost.";
};
locations = mkOption {
type = types.attrsOf (types.submodule {
options = {
extraConfig = mkOption {
type = types.str;
description = "Extra configuration for the location.";
default = "";
};
allowLan = mkOption {
type = types.bool;
default = false;
};
proxyWebsockets = mkOption {
type = types.bool;
default = false;
};
host = mkOption {
type = types.str;
description = "The host for the location.";
default = "127.0.0.1";
};
port = mkOption {
type = types.int;
description = "The port number for the location.";
};
allow = mkOption {
type = types.listOf types.str;
default = [ ];
description = "IP address or CIDR block to allow.";
};
path = mkOption {
type = types.str;
default = "";
};
recommendedProxySettings = mkOption {
type = types.bool;
default = true;
description = "Force the use of recommended proxy configuration.";
};
allowWAN = mkOption {
type = types.bool;
default = false;
description = "If set to false, deny all WAN traffic.";
};
};
});
default = { };
description = "An attribute set of location configurations.";
};
};
});
default = { };
description = "An attribute set of domain configurations.";
};
};
config = {
services.nginx.virtualHosts = mapAttrs
(domain: conf: {
forceSSL = true;
useACMEHost= "giugl.io";
locations = mapAttrs
(path: location: {
proxyPass = "http://${location.host}:${toString location.port}${location.path}";
proxyWebsockets = location.proxyWebsockets;
recommendedProxySettings = location.recommendedProxySettings;
extraConfig = ''
${concatMapStringsSep "\n" (allowCIDR: "allow ${allowCIDR};") location.allow}
${optionalString location.allowLan ''allow ${config.pepe.core.network.interfaces."lan".net};''}
${optionalString (!location.allowWAN) "deny all;"}
'' + location.extraConfig;
})
conf.locations;
})
cfg.hosts;
};
}

View File

@ -22,7 +22,7 @@ in
group = "media";
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" ];
locations."/" = {
port = 6767;

View File

@ -16,9 +16,9 @@ in
};
config = mkIf cfg.enable {
architect = {
pepe.core = {
firewall.openTCP = [ config.services.gitea.settings.server.SSH_PORT ];
vhost.${cfg.domain} = {
vhost.hosts.${cfg.domain} = {
dnsInterfaces = [ "lan" "tailscale" ];
locations."/" = {
port = config.services.gitea.settings.server.HTTP_PORT;

View File

@ -22,14 +22,14 @@ in
};
};
architect.vhost.${cfg.domain} = {
pepe.core.vhost.hosts.${cfg.domain} = {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
host = "[::1]";
port = config.services.immich.port;
allowLan = true;
allowWAN = true;
allow = [ config.architect.networks."tailscale".net ];
allow = [ config.pepe.core.network.interfaces."tailscale".net ];
proxyWebsockets = true;
extraConfig = ''
# allow large file uploads

View File

@ -24,7 +24,7 @@ in
# needed since StateDirectory does not accept symlinks
systemd.services.jellyfin.serviceConfig.StateDirectory = mkForce "";
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "lan" "tailscale" ];
locations = {
"/" = {

View File

@ -21,7 +21,7 @@ in
package = cfg.package;
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
port = config.services.jellyseerr.port;

View File

@ -22,7 +22,7 @@ in
group = "media";
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "lan" "tailscale" ];
locations."/" = {
port = 8686;

View File

@ -46,7 +46,7 @@ in
} // cfg.settings;
};
architect.vhost.${cfg.domain} = {
pepe.core.vhost.hosts.${cfg.domain} = {
dnsInterfaces = [ "lan" "tailscale" ];
locations."/" = {
port = 4533;

View File

@ -22,7 +22,7 @@ in
group = "media";
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
port = 6789;

View File

@ -21,7 +21,7 @@ in
package = cfg.package;
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
port = 9696;

View File

@ -21,7 +21,7 @@ in
package = cfg.package;
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
port = 7878;

View File

@ -21,7 +21,7 @@ in
package = cfg.package;
};
architect.vhost.${cfg.domain} = with config.architect.networks; {
pepe.core.vhost.hosts.${cfg.domain} = with config.pepe.core.network.interfaces; {
dnsInterfaces = [ "tailscale" "lan" ];
locations."/" = {
port = 8989;