added experimental IPv6 compatible wgautomesh build
This commit is contained in:
parent
cdfd856296
commit
2165b8de9d
6 changed files with 327 additions and 56 deletions
153
flake.lock
153
flake.lock
|
@ -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": 1732925279,
|
||||
"narHash": "sha256-PzBduJ8SoOblgAfDdjBxPHQB1LhicTrB8WFmiMPBQig=",
|
||||
"owner": "lynatic1337",
|
||||
"repo": "lynpkgs",
|
||||
"rev": "2a4c109d07e45f027f04b6c812d562e484d17346",
|
||||
"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",
|
||||
|
|
10
flake.nix
10
flake.nix
|
@ -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 = [
|
||||
|
@ -24,6 +26,7 @@
|
|||
lanzaboote.nixosModules.lanzaboote
|
||||
inputs.microvm.nixosModules.host
|
||||
./hosts/network.nix
|
||||
./meta/wgautomesh.nix
|
||||
];
|
||||
};
|
||||
passInputs = {
|
||||
|
@ -41,6 +44,13 @@
|
|||
};
|
||||
};
|
||||
inherit (nixpkgs) lib;
|
||||
|
||||
pkgs = import nixpkgs {
|
||||
overlays = [
|
||||
lynpkgs.overlays.default
|
||||
];
|
||||
};
|
||||
|
||||
mkLocalMods = import ./meta/mkLocalMods.nix {inherit lib;};
|
||||
mkLocalModsInput = mkLocalMods {
|
||||
prefix = ["lyn"];
|
||||
|
|
|
@ -26,7 +26,7 @@ with config.lyn.lib; {
|
|||
|
||||
lyn.services.wgautomesh = {
|
||||
enable = true;
|
||||
useIPv6 = false;
|
||||
#useIPv6 = false;
|
||||
};
|
||||
|
||||
##1##3##3##7##
|
||||
|
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
lyn.services.wgautomesh = {
|
||||
enable = true;
|
||||
useIPv6 = false;
|
||||
#useIPv6 = false;
|
||||
};
|
||||
|
||||
networking.useDHCP = false;
|
||||
|
|
168
meta/wgautomesh.nix
Normal file
168
meta/wgautomesh.nix
Normal 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];
|
||||
};
|
||||
}
|
|
@ -5,6 +5,8 @@
|
|||
cfg,
|
||||
...
|
||||
}: let
|
||||
buildInputs = [pkgs.wgautomesh];
|
||||
|
||||
prefix = "lyn";
|
||||
|
||||
# decrypt gossip secret
|
||||
|
@ -20,11 +22,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 +40,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 +73,7 @@ in {
|
|||
else ["${currentHost.IPv4.internal}/24"];
|
||||
listenPort = wireguardPort;
|
||||
privateKeyFile = "/var/lib/wireguard-keys/private";
|
||||
mtu = 1200;
|
||||
mtu = 1280;
|
||||
};
|
||||
|
||||
services.wgautomesh = {
|
||||
|
|
Loading…
Reference in a new issue