refactor(headscale): restructure headscale module and improve configuration

- Migrated headscale configuration to dedicated module file
- Added host configuration option for Headscale service
- Restructured settings configuration with nested options
- Improved type definitions for configuration parameters
- Added security headers in virtual host configuration
- Fixed formatting in vhost configuration
- Corrected typo in useACMEHost configuration
This commit is contained in:
Giulio De Pasquale 2025-05-06 12:55:27 +01:00
parent 4fa79d642f
commit e8afefea50
5 changed files with 123 additions and 116 deletions

View File

@ -1,49 +0,0 @@
{ config, pkgs, ... }:
let
domain = "vipienne.giugl.io";
headscalePkg = pkgs.headscale;
in
{
environment.systemPackages = [ headscalePkg ];
architect = {
firewall = {
openUDP = [ config.services.tailscale.port ];
};
vhost.${domain} = {
dnsInterfaces = [ "lan" "tailscale" ];
locations."/" = {
port = config.services.headscale.port;
allowWAN = true;
proxyWebsockets = true;
};
};
};
services.headscale = {
enable = true;
package = headscalePkg;
port = 1194;
settings = {
server_url = "https://${domain}";
# log.level = "debug";
dns = {
magic_dns = false;
# base_domain = domain;
override_local_dns = true;
global = [
config.architect.networks.tailscale.devices.architect.address
];
nameservers.global = [
config.architect.networks.tailscale.devices.architect.address
];
};
logtail.enabled = false;
prefixes.v4 = config.architect.networks.tailscale.net;
noise.private_key_path = "/var/lib/headscale/noise_private.key";
};
};
}

View File

@ -81,21 +81,24 @@ in
};
config = {
pepe.core.firewall.openTCP = [ 80 443 ];
# Configure DNS entries for vhosts when DNS is enabled
pepe.core.dns = mkIf config.pepe.core.dns.enable {
extraDomains = mapAttrs (domain: conf: {
dnsInterfaces =
(lib.optionals (lib.any (loc: loc.allowLAN) (lib.attrValues conf.locations))
config.pepe.core.network.interfacesByType.lan) ++
(lib.optionals (lib.any (loc: loc.allowVPN) (lib.attrValues conf.locations))
config.pepe.core.network.interfacesByType.vpn);
}) cfg.hosts;
extraDomains = mapAttrs
(domain: conf: {
dnsInterfaces =
(lib.optionals (lib.any (loc: loc.allowLAN) (lib.attrValues conf.locations))
config.pepe.core.network.interfacesByType.lan) ++
(lib.optionals (lib.any (loc: loc.allowVPN) (lib.attrValues conf.locations))
config.pepe.core.network.interfacesByType.vpn);
})
cfg.hosts;
};
services.nginx.virtualHosts = mapAttrs
(domain: conf: {
forceSSL = true;
useACMEHost= "giugl.io";
useACMEHost = "giugl.io";
locations = mapAttrs
(path: location: {
proxyPass = "http://${location.host}:${toString location.port}${location.path}";

View File

@ -15,5 +15,6 @@
./radarr
./redlib
./sonarr
./headscale
];
}

View File

@ -1,59 +0,0 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf;
cfg = config.pepe.services.headscale;
in
{
options.pepe.services.headscale = with lib; {
enable = mkEnableOption "Enable Headscale";
package = mkPackageOption pkgs "headscale" { };
domain = mkOption {
type = types.str;
default = null;
description = "Domain for the Headscale service.";
};
port = mkOption {
type = types.int;
default = 1194;
description = "Port for the Headscale service.";
};
settings = mkOption {
type = types.attrsOf types.str;
default = {
server_url = "https://${config.pepe.core.network.interfaces.tailscale.devices.architect.address}";
dns.magic_dns = false;
dns.override_local_dns = true;
dns.global = [ config.pepe.core.network.interfaces.tailscale.devices.architect.address ];
dns.nameservers.global = [ config.pepe.core.network.interfaces.tailscale.devices.architect.address ];
logtail.enabled = false;
prefixes.v4 = config.pepe.core.network.interfaces.tailscale.net;
noise.private_key_path = "/var/lib/headscale/noise_private.key";
};
description = "Configuration settings for Headscale.";
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
services.headscale = {
enable = true;
package = cfg.package;
port = cfg.port;
settings = cfg.settings;
};
pepe.core.vhost.hosts.${cfg.domain} = {
dnsInterfaces = [ "lan" "tailscale" ];
locations."/" = {
port = cfg.port;
allowWAN = true;
proxyWebsockets = true;
};
};
pepe.core.firewall.openUDP = [ cfg.port ];
};
}

View File

@ -0,0 +1,111 @@
{ config, lib, pkgs, ... }:
let
inherit (lib) mkIf;
cfg = config.pepe.services.headscale;
in
{
options.pepe.services.headscale = with lib; {
enable = mkEnableOption "Enable Headscale";
package = mkPackageOption pkgs "headscale" { };
domain = mkOption {
type = types.str;
default = null;
description = "Domain for the Headscale service.";
};
host = mkOption {
type = types.str;
default = "127.0.0.1";
description = "Host for the Headscale service.";
};
port = mkOption {
type = types.int;
default = 1194;
description = "Port for the Headscale service.";
};
settings = mkOption {
type = types.submodule {
freeformType = types.attrsOf types.anything;
options = {
server_url = mkOption {
type = types.str;
default = "https://${cfg.domain}";
};
dns = mkOption {
type = types.submodule {
options = {
magic_dns = mkOption {
type = types.bool;
default = false;
};
override_local_dns = mkOption {
type = types.bool;
default = true;
};
global = mkOption {
type = types.listOf types.str;
default = [ ];
};
nameservers = mkOption {
type = types.submodule {
options.global = mkOption {
type = types.listOf types.str;
default = [ ];
};
};
default = { };
};
};
};
default = { };
};
log.level = mkOption {
type = types.str;
default = "info";
};
logtail.enabled = mkOption {
type = types.bool;
default = false;
};
prefixes.v4 = mkOption {
type = types.str;
default = null;
};
noise.private_key_path = mkOption {
type = types.path;
default = "/var/lib/headscale/noise_private.key";
};
};
};
default = { };
description = "Configuration settings for Headscale.";
};
};
config = mkIf cfg.enable {
environment.systemPackages = [ cfg.package ];
services.headscale = {
enable = true;
package = cfg.package;
port = cfg.port;
settings = cfg.settings;
};
pepe.core = {
firewall.openUDP = [ cfg.port ];
vhost.hosts.${cfg.domain} = {
locations."/" = {
host = cfg.host;
port = cfg.port;
allowWAN = true;
proxyWebsockets = true;
extraConfig = ''
add_header Strict-Transport-Security "max-age=15552000; includeSubDomains" always;
proxy_buffering off;
'';
};
};
};
};
}