added experimental IPv6 compatible wgautomesh build

This commit is contained in:
Lyn 2024-11-30 01:50:21 +01:00
parent cdfd856296
commit 91eda3a0ae
6 changed files with 331 additions and 56 deletions

View file

@ -58,6 +58,24 @@
"type": "github" "type": "github"
} }
}, },
"flake-parts_2": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1730504689,
"narHash": "sha256-hgmguH29K2fvs9szpq2r3pz2/8cJd2LPS+b4tfNFCwE=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "506278e768c2a08bec68eb62932193e341f55c90",
"type": "github"
},
"original": {
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": { "flake-utils": {
"inputs": { "inputs": {
"systems": "systems" "systems": "systems"
@ -78,7 +96,7 @@
}, },
"flake-utils_2": { "flake-utils_2": {
"inputs": { "inputs": {
"systems": "systems_2" "systems": "systems_3"
}, },
"locked": { "locked": {
"lastModified": 1726560853, "lastModified": 1726560853,
@ -141,6 +159,27 @@
"type": "github" "type": "github"
} }
}, },
"lynpkgs": {
"inputs": {
"flake-parts": "flake-parts_2",
"nixpkgs": "nixpkgs_2",
"pkgs-by-name-for-flake-parts": "pkgs-by-name-for-flake-parts",
"systems": "systems_2"
},
"locked": {
"lastModified": 1732934040,
"narHash": "sha256-3QuAM3OP8SbZyz1bXKajHBRQGW8sMXZ3vJDLV6MQCRg=",
"owner": "lynatic1337",
"repo": "lynpkgs",
"rev": "1bad540c69e36520fcab64b99cf7a1907e2c0f73",
"type": "github"
},
"original": {
"owner": "lynatic1337",
"repo": "lynpkgs",
"type": "github"
}
},
"microvm": { "microvm": {
"inputs": { "inputs": {
"flake-utils": "flake-utils_2", "flake-utils": "flake-utils_2",
@ -150,11 +189,11 @@
"spectrum": "spectrum" "spectrum": "spectrum"
}, },
"locked": { "locked": {
"lastModified": 1730499294, "lastModified": 1732633513,
"narHash": "sha256-RxV89z3TwhQT0Wue42aSPh3O7hXGbAFYHHNSnW9h6P8=", "narHash": "sha256-6LmtOmeDpv9iHS8l0GNcppP11dKIJFMZLdFyxQ+qQBM=",
"owner": "astro", "owner": "astro",
"repo": "microvm.nix", "repo": "microvm.nix",
"rev": "93122446d6001f9789d05e565f73bebfa3f53b50", "rev": "093ef734d3c37669860043a87dbf1c09fc6f5b38",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -179,6 +218,18 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-lib": {
"locked": {
"lastModified": 1730504152,
"narHash": "sha256-lXvH/vOfb4aGYyvFmZK/HlsNsr/0CVWlwYvo2rxJk3s=",
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz"
},
"original": {
"type": "tarball",
"url": "https://github.com/NixOS/nixpkgs/archive/cc2f28000298e1269cea6612cd06ec9979dd5d7f.tar.gz"
}
},
"nixpkgs-stable": { "nixpkgs-stable": {
"locked": { "locked": {
"lastModified": 1710695816, "lastModified": 1710695816,
@ -195,29 +246,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs-stable_2": {
"locked": {
"lastModified": 1730602179,
"narHash": "sha256-efgLzQAWSzJuCLiCaQUCDu4NudNlHdg2NzGLX5GYaEY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "3c2f1c4ca372622cb2f9de8016c9a0b1cbd0f37c",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "release-24.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": { "nixpkgs-unstable": {
"locked": { "locked": {
"lastModified": 1730785428, "lastModified": 1732521221,
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=", "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7", "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -229,11 +264,27 @@
}, },
"nixpkgs_2": { "nixpkgs_2": {
"locked": { "locked": {
"lastModified": 1730963269, "lastModified": 1732521221,
"narHash": "sha256-rz30HrFYCHiWEBCKHMffHbMdWJ35hEkcRVU0h7ms3x0=", "narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "83fb6c028368e465cd19bb127b86f971a5e41ebc", "rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1732749044,
"narHash": "sha256-T38FQOg0BV5M8FN1712fovzNakSOENEYs+CSkg31C9Y=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0c5b4ecbed5b155b705336aa96d878e55acd8685",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -243,13 +294,13 @@
"type": "github" "type": "github"
} }
}, },
"nixpkgs_3": { "nixpkgs_4": {
"locked": { "locked": {
"lastModified": 1730272153, "lastModified": 1731763621,
"narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=", "narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53", "rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -259,6 +310,21 @@
"type": "github" "type": "github"
} }
}, },
"pkgs-by-name-for-flake-parts": {
"locked": {
"lastModified": 1727519927,
"narHash": "sha256-3SNX6BuaisoX9PKYI+fh3geZ3jBgKKkAtHcWuHRU0+o=",
"owner": "drupol",
"repo": "pkgs-by-name-for-flake-parts",
"rev": "91debb07d81ff25b8e3b48914b6abd6f11dc26e2",
"type": "github"
},
"original": {
"owner": "drupol",
"repo": "pkgs-by-name-for-flake-parts",
"type": "github"
}
},
"pre-commit-hooks-nix": { "pre-commit-hooks-nix": {
"inputs": { "inputs": {
"flake-compat": [ "flake-compat": [
@ -289,8 +355,9 @@
"root": { "root": {
"inputs": { "inputs": {
"lanzaboote": "lanzaboote", "lanzaboote": "lanzaboote",
"lynpkgs": "lynpkgs",
"microvm": "microvm", "microvm": "microvm",
"nixpkgs": "nixpkgs_2", "nixpkgs": "nixpkgs_3",
"nixpkgs-unstable": "nixpkgs-unstable", "nixpkgs-unstable": "nixpkgs-unstable",
"sops-nix": "sops-nix" "sops-nix": "sops-nix"
} }
@ -322,15 +389,14 @@
}, },
"sops-nix": { "sops-nix": {
"inputs": { "inputs": {
"nixpkgs": "nixpkgs_3", "nixpkgs": "nixpkgs_4"
"nixpkgs-stable": "nixpkgs-stable_2"
}, },
"locked": { "locked": {
"lastModified": 1731047660, "lastModified": 1732575825,
"narHash": "sha256-iyp51lPWEQz4c5VH9bVbAuBcFP4crETU2QJYh5V0NYA=", "narHash": "sha256-xtt95+c7OUMoqZf4OvA/7AemiH3aVuWHQbErYQoPwFk=",
"owner": "Mic92", "owner": "Mic92",
"repo": "sops-nix", "repo": "sops-nix",
"rev": "60e1bce1999f126e3b16ef45f89f72f0c3f8d16f", "rev": "3433ea14fbd9e6671d0ff0dd45ed15ee4c156ffa",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -384,6 +450,21 @@
"repo": "default", "repo": "default",
"type": "github" "type": "github"
} }
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
} }
}, },
"root": "root", "root": "root",

View file

@ -7,6 +7,7 @@
nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05"; nixpkgs.url = "github:NixOS/nixpkgs/nixos-24.05";
sops-nix.url = "github:Mic92/sops-nix"; sops-nix.url = "github:Mic92/sops-nix";
nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable"; nixpkgs-unstable.url = "github:NixOS/nixpkgs/nixos-unstable";
lynpkgs.url = "github:lynatic1337/lynpkgs";
}; };
outputs = { outputs = {
self, self,
@ -15,6 +16,7 @@
sops-nix, sops-nix,
lanzaboote, lanzaboote,
microvm, microvm,
lynpkgs,
} @ inputs: let } @ inputs: let
imports = { imports = {
imports = [ imports = [
@ -41,6 +43,13 @@
}; };
}; };
inherit (nixpkgs) lib; inherit (nixpkgs) lib;
pkgs = import nixpkgs {
overlays = [
lynpkgs.overlays.default
];
};
mkLocalMods = import ./meta/mkLocalMods.nix {inherit lib;}; mkLocalMods = import ./meta/mkLocalMods.nix {inherit lib;};
mkLocalModsInput = mkLocalMods { mkLocalModsInput = mkLocalMods {
prefix = ["lyn"]; prefix = ["lyn"];

View file

@ -26,7 +26,7 @@ with config.lyn.lib; {
lyn.services.wgautomesh = { lyn.services.wgautomesh = {
enable = true; enable = true;
useIPv6 = false; #useIPv6 = false;
}; };
##1##3##3##7## ##1##3##3##7##

View file

@ -20,7 +20,7 @@
lyn.services.wgautomesh = { lyn.services.wgautomesh = {
enable = true; enable = true;
useIPv6 = false; #useIPv6 = false;
}; };
networking.useDHCP = false; networking.useDHCP = false;

168
meta/wgautomesh.nix Normal file
View file

@ -0,0 +1,168 @@
{
lib,
config,
pkgs,
...
}:
with lib; let
cfg = config.services.wgautomesh;
settingsFormat = pkgs.formats.toml {};
configFile =
# Have to remove nulls manually as TOML generator will not just skip key
# if value is null
settingsFormat.generate "wgautomesh-config.toml"
(filterAttrs (k: v: v != null)
(mapAttrs
(k: v:
if k == "peers"
then map (e: filterAttrs (k: v: v != null) e) v
else v)
cfg.settings));
runtimeConfigFile =
if cfg.enableGossipEncryption
then "/run/wgautomesh/wgautomesh.toml"
else configFile;
in {
options.services.wgautomesh = {
enable = mkEnableOption "the wgautomesh daemon";
logLevel = mkOption {
type = types.enum ["trace" "debug" "info" "warn" "error"];
default = "info";
description = "wgautomesh log level.";
};
enableGossipEncryption = mkOption {
type = types.bool;
default = true;
description = "Enable encryption of gossip traffic.";
};
gossipSecretFile = mkOption {
type = types.path;
description = ''
File containing the gossip secret, a shared secret key to use for gossip
encryption. Required if `enableGossipEncryption` is set. This file
may contain any arbitrary-length utf8 string. To generate a new gossip
secret, use a command such as `openssl rand -base64 32`.
'';
};
enablePersistence = mkOption {
type = types.bool;
default = true;
description = "Enable persistence of Wireguard peer info between restarts.";
};
openFirewall = mkOption {
type = types.bool;
default = true;
description = "Automatically open gossip port in firewall (recommended).";
};
settings = mkOption {
type = types.submodule {
freeformType = settingsFormat.type;
options = {
interface = mkOption {
type = types.str;
description = ''
Wireguard interface to manage (it is NOT created by wgautomesh, you
should use another NixOS option to create it such as
`networking.wireguard.interfaces.wg0 = {...};`).
'';
example = "wg0";
};
gossip_port = mkOption {
type = types.port;
description = ''
wgautomesh gossip port, this MUST be the same number on all nodes in
the wgautomesh network.
'';
default = 1666;
};
lan_discovery = mkOption {
type = types.bool;
default = true;
description = "Enable discovery of peers on the same LAN using UDP broadcast.";
};
ipv6 = mkOption {
type = types.bool;
default = true;
description = "Whether to use IPv6 or IPv4.";
};
upnp_forward_external_port = mkOption {
type = types.nullOr types.port;
default = null;
description = ''
Public port number to try to redirect to this machine's Wireguard
daemon using UPnP IGD.
'';
};
peers = mkOption {
type = types.listOf (types.submodule {
options = {
pubkey = mkOption {
type = types.str;
description = "Wireguard public key of this peer.";
};
address = mkOption {
type = types.str;
description = ''
Wireguard address of this peer (a single IP address, multiple
addresses or address ranges are not supported).
'';
example = "10.0.0.42";
};
endpoint = mkOption {
type = types.nullOr types.str;
description = ''
Bootstrap endpoint for connecting to this Wireguard peer if no
other address is known or none are working.
'';
default = null;
example = "wgnode.mydomain.example:51820";
};
};
});
default = [];
description = "wgautomesh peer list.";
};
};
};
default = {};
description = "Configuration for wgautomesh.";
};
};
config = mkIf cfg.enable {
services.wgautomesh.settings = {
gossip_secret_file = mkIf cfg.enableGossipEncryption "$CREDENTIALS_DIRECTORY/gossip_secret";
persist_file = mkIf cfg.enablePersistence "/var/lib/wgautomesh/state";
};
systemd.services.wgautomesh = {
path = [pkgs.wireguard-tools];
environment = {RUST_LOG = "wgautomesh=${cfg.logLevel}";};
description = "wgautomesh";
serviceConfig = {
Type = "simple";
ExecStart = "${getExe pkgs.wgautomesh} ${runtimeConfigFile}";
Restart = "always";
RestartSec = "30";
LoadCredential = mkIf cfg.enableGossipEncryption ["gossip_secret:${cfg.gossipSecretFile}"];
ExecStartPre = mkIf cfg.enableGossipEncryption [
'' ${pkgs.envsubst}/bin/envsubst \
-i ${configFile} \
-o ${runtimeConfigFile}''
];
DynamicUser = true;
StateDirectory = "wgautomesh";
StateDirectoryMode = "0700";
RuntimeDirectory = "wgautomesh";
AmbientCapabilities = "CAP_NET_ADMIN";
CapabilityBoundingSet = "CAP_NET_ADMIN";
};
wantedBy = ["multi-user.target"];
};
networking.firewall.allowedUDPPorts =
mkIf cfg.openFirewall [cfg.settings.gossip_port];
};
}

View file

@ -5,6 +5,13 @@
cfg, cfg,
... ...
}: let }: let
buildInputs = [pkgs.wgautomesh];
options.services.wgautomesh.settings.ipv6 = lib.mkOption {
type = lib.types.bool;
default = true;
description = "Whether to use IPv6 or IPv4.";
};
prefix = "lyn"; prefix = "lyn";
# decrypt gossip secret # decrypt gossip secret
@ -20,11 +27,15 @@
in in
lib.mapAttrsToList (name: host: { lib.mapAttrsToList (name: host: {
pubkey = host.wg.pubkey; pubkey = host.wg.pubkey;
#if there is no public IP, make endpoint null so wgautomesh knows it unknown #if there is no public IP, make endpoint null so wgautomesh knows it unknown. Else format it to a SocketAddr
endpoint = endpoint =
if host.${version}.public == "" if host.${version}.public == ""
then null then null
else "${host.${version}.public}:${toString host.wg.port}"; else "${
if version == "IPv6"
then "[${host.${version}.public}]"
else host.${version}.public
}:${toString host.wg.port}";
address = host.${version}.internal; address = host.${version}.internal;
}) })
filteredHosts; filteredHosts;
@ -34,24 +45,30 @@
currentHost = meshnetwork.hosts.${config.networking.hostName}; currentHost = meshnetwork.hosts.${config.networking.hostName};
wireguardPort = currentHost.wg.port; wireguardPort = currentHost.wg.port;
in { in {
opt.useIPv6 = lib.mkOption { opt = {
type = lib.types.bool; useIPv6 = lib.mkOption {
description = "Whether to use IPv6. Defaults to true"; type = lib.types.bool;
default = true; description = "Whether to use IPv6. Defaults to true";
default = true;
};
enable_upnp = lib.mkOption {
type = lib.types.bool;
description = "Whether to allow the wireguard port in the gateway using UPnP IGD. Necessary on some firewalls, might spam unnecessary debug messages on environments without IGD gateways.";
default = false;
};
}; };
config = { config = {
networking.firewall = { networking.firewall = {
allowedUDPPorts = [ allowedUDPPorts =
wireguardPort [
]; wireguardPort
extraCommands = '' ]
# Allow UDP packets comming from port 1900 from a local address, # UPnP broadcast responses
# these are necessary for UPnP/IGD ++ (
iptables -A INPUT -s 192.168.0.0/16 -p udp --sport 1900 -j ACCEPT if cfg.enable_upnp
''; then [1900]
extraStopCommands = '' else []
iptables -D INPUT -s 192.168.0.0/16 -p udp --sport 1900 -j ACCEPT );
'';
}; };
networking.wireguard.interfaces.wg0 = { networking.wireguard.interfaces.wg0 = {
@ -61,7 +78,7 @@ in {
else ["${currentHost.IPv4.internal}/24"]; else ["${currentHost.IPv4.internal}/24"];
listenPort = wireguardPort; listenPort = wireguardPort;
privateKeyFile = "/var/lib/wireguard-keys/private"; privateKeyFile = "/var/lib/wireguard-keys/private";
mtu = 1200; mtu = 1280;
}; };
services.wgautomesh = { services.wgautomesh = {