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"
}
},
"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": {
"inputs": {
"systems": "systems"
@ -78,7 +96,7 @@
},
"flake-utils_2": {
"inputs": {
"systems": "systems_2"
"systems": "systems_3"
},
"locked": {
"lastModified": 1726560853,
@ -141,6 +159,27 @@
"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": {
"inputs": {
"flake-utils": "flake-utils_2",
@ -150,11 +189,11 @@
"spectrum": "spectrum"
},
"locked": {
"lastModified": 1730499294,
"narHash": "sha256-RxV89z3TwhQT0Wue42aSPh3O7hXGbAFYHHNSnW9h6P8=",
"lastModified": 1732633513,
"narHash": "sha256-6LmtOmeDpv9iHS8l0GNcppP11dKIJFMZLdFyxQ+qQBM=",
"owner": "astro",
"repo": "microvm.nix",
"rev": "93122446d6001f9789d05e565f73bebfa3f53b50",
"rev": "093ef734d3c37669860043a87dbf1c09fc6f5b38",
"type": "github"
},
"original": {
@ -179,6 +218,18 @@
"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": {
"locked": {
"lastModified": 1710695816,
@ -195,29 +246,13 @@
"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": {
"locked": {
"lastModified": 1730785428,
"narHash": "sha256-Zwl8YgTVJTEum+L+0zVAWvXAGbWAuXHax3KzuejaDyo=",
"lastModified": 1732521221,
"narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "4aa36568d413aca0ea84a1684d2d46f55dbabad7",
"rev": "4633a7c72337ea8fd23a4f2ba3972865e3ec685d",
"type": "github"
},
"original": {
@ -229,11 +264,27 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1730963269,
"narHash": "sha256-rz30HrFYCHiWEBCKHMffHbMdWJ35hEkcRVU0h7ms3x0=",
"lastModified": 1732521221,
"narHash": "sha256-2ThgXBUXAE1oFsVATK1ZX9IjPcS4nKFOAjhPNKuiMn0=",
"owner": "NixOS",
"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"
},
"original": {
@ -243,13 +294,13 @@
"type": "github"
}
},
"nixpkgs_3": {
"nixpkgs_4": {
"locked": {
"lastModified": 1730272153,
"narHash": "sha256-B5WRZYsRlJgwVHIV6DvidFN7VX7Fg9uuwkRW9Ha8z+w=",
"lastModified": 1731763621,
"narHash": "sha256-ddcX4lQL0X05AYkrkV2LMFgGdRvgap7Ho8kgon3iWZk=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "2d2a9ddbe3f2c00747398f3dc9b05f7f2ebb0f53",
"rev": "c69a9bffbecde46b4b939465422ddc59493d3e4d",
"type": "github"
},
"original": {
@ -259,6 +310,21 @@
"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": {
"inputs": {
"flake-compat": [
@ -289,8 +355,9 @@
"root": {
"inputs": {
"lanzaboote": "lanzaboote",
"lynpkgs": "lynpkgs",
"microvm": "microvm",
"nixpkgs": "nixpkgs_2",
"nixpkgs": "nixpkgs_3",
"nixpkgs-unstable": "nixpkgs-unstable",
"sops-nix": "sops-nix"
}
@ -322,15 +389,14 @@
},
"sops-nix": {
"inputs": {
"nixpkgs": "nixpkgs_3",
"nixpkgs-stable": "nixpkgs-stable_2"
"nixpkgs": "nixpkgs_4"
},
"locked": {
"lastModified": 1731047660,
"narHash": "sha256-iyp51lPWEQz4c5VH9bVbAuBcFP4crETU2QJYh5V0NYA=",
"lastModified": 1732575825,
"narHash": "sha256-xtt95+c7OUMoqZf4OvA/7AemiH3aVuWHQbErYQoPwFk=",
"owner": "Mic92",
"repo": "sops-nix",
"rev": "60e1bce1999f126e3b16ef45f89f72f0c3f8d16f",
"rev": "3433ea14fbd9e6671d0ff0dd45ed15ee4c156ffa",
"type": "github"
},
"original": {
@ -384,6 +450,21 @@
"repo": "default",
"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",

View file

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

View file

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

View file

@ -20,7 +20,7 @@
lyn.services.wgautomesh = {
enable = true;
useIPv6 = false;
#useIPv6 = 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,
...
}: 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";
# decrypt gossip secret
@ -20,11 +27,15 @@
in
lib.mapAttrsToList (name: host: {
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 =
if host.${version}.public == ""
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;
})
filteredHosts;
@ -34,24 +45,30 @@
currentHost = meshnetwork.hosts.${config.networking.hostName};
wireguardPort = currentHost.wg.port;
in {
opt.useIPv6 = lib.mkOption {
opt = {
useIPv6 = lib.mkOption {
type = lib.types.bool;
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 = {
networking.firewall = {
allowedUDPPorts = [
allowedUDPPorts =
[
wireguardPort
];
extraCommands = ''
# Allow UDP packets comming from port 1900 from a local address,
# these are necessary for UPnP/IGD
iptables -A INPUT -s 192.168.0.0/16 -p udp --sport 1900 -j ACCEPT
'';
extraStopCommands = ''
iptables -D INPUT -s 192.168.0.0/16 -p udp --sport 1900 -j ACCEPT
'';
]
# UPnP broadcast responses
++ (
if cfg.enable_upnp
then [1900]
else []
);
};
networking.wireguard.interfaces.wg0 = {
@ -61,7 +78,7 @@ in {
else ["${currentHost.IPv4.internal}/24"];
listenPort = wireguardPort;
privateKeyFile = "/var/lib/wireguard-keys/private";
mtu = 1200;
mtu = 1280;
};
services.wgautomesh = {