nixos/nebula: enable reloadable configuration (#460779)
This commit is contained in:
@@ -446,6 +446,8 @@ and [release notes for v18](https://goteleport.com/docs/changelog/#1800-070325).
|
||||
|
||||
- `linux_libre` & `linux_latest_libre` have been removed due to a lack of maintenance.
|
||||
|
||||
- `services.nebula.networks.<name>` will now store configuration files in `/etc/nebula/<name>.yml` and supports config reloading.
|
||||
|
||||
- `services.pds` has been renamed to `services.bluesky-pds`.
|
||||
|
||||
- `services.xserver.desktopManager.deepin` and associated packages have been removed due to being unmaintained. See issue [#422090](https://github.com/NixOS/nixpkgs/issues/422090) for more details.
|
||||
|
||||
@@ -9,8 +9,54 @@ let
|
||||
cfg = config.services.nebula;
|
||||
enabledNetworks = lib.filterAttrs (n: v: v.enable) cfg.networks;
|
||||
|
||||
genSettings =
|
||||
netName: netCfg:
|
||||
lib.recursiveUpdate {
|
||||
pki = {
|
||||
ca = netCfg.ca;
|
||||
cert = netCfg.cert;
|
||||
key = netCfg.key;
|
||||
};
|
||||
static_host_map = netCfg.staticHostMap;
|
||||
lighthouse = {
|
||||
am_lighthouse = netCfg.isLighthouse;
|
||||
hosts = netCfg.lighthouses;
|
||||
serve_dns = netCfg.lighthouse.dns.enable;
|
||||
dns.host = netCfg.lighthouse.dns.host;
|
||||
dns.port = netCfg.lighthouse.dns.port;
|
||||
};
|
||||
relay = {
|
||||
am_relay = netCfg.isRelay;
|
||||
relays = netCfg.relays;
|
||||
use_relays = true;
|
||||
};
|
||||
listen = {
|
||||
host = netCfg.listen.host;
|
||||
port = resolveFinalPort netCfg;
|
||||
};
|
||||
tun = {
|
||||
disabled = netCfg.tun.disable;
|
||||
dev = if (netCfg.tun.device != null) then netCfg.tun.device else "nebula.${netName}";
|
||||
};
|
||||
firewall = {
|
||||
inbound = netCfg.firewall.inbound;
|
||||
outbound = netCfg.firewall.outbound;
|
||||
};
|
||||
} netCfg.settings;
|
||||
format = pkgs.formats.yaml { };
|
||||
|
||||
genConfigFile =
|
||||
netName: settings:
|
||||
format.generate "nebula-config-${netName}.yml" (
|
||||
lib.warnIf
|
||||
((settings.lighthouse.am_lighthouse || settings.relay.am_relay) && settings.listen.port == 0)
|
||||
''
|
||||
Nebula network '${netName}' is configured as a lighthouse or relay, and its port is ${builtins.toString settings.listen.port}.
|
||||
You will likely experience connectivity issues: https://nebula.defined.net/docs/config/listen/#listenport
|
||||
''
|
||||
settings
|
||||
);
|
||||
|
||||
nameToId = netName: "nebula-${netName}";
|
||||
|
||||
resolveFinalPort =
|
||||
@@ -60,6 +106,16 @@ in
|
||||
example = "/etc/nebula/host.key";
|
||||
};
|
||||
|
||||
enableReload = lib.mkOption {
|
||||
type = lib.types.bool;
|
||||
default = false;
|
||||
description = ''
|
||||
Enable automatic config reload on config change.
|
||||
This setting is not enabled by default as nix cannot determine if the config change is reloadable.
|
||||
Please refer to the [config reference](https://nebula.defined.net/docs/config/) for documentation on reloadable changes.
|
||||
'';
|
||||
};
|
||||
|
||||
staticHostMap = lib.mkOption {
|
||||
type = lib.types.attrsOf (lib.types.listOf (lib.types.str));
|
||||
default = { };
|
||||
@@ -212,47 +268,13 @@ in
|
||||
netName: netCfg:
|
||||
let
|
||||
networkId = nameToId netName;
|
||||
settings = lib.recursiveUpdate {
|
||||
pki = {
|
||||
ca = netCfg.ca;
|
||||
cert = netCfg.cert;
|
||||
key = netCfg.key;
|
||||
};
|
||||
static_host_map = netCfg.staticHostMap;
|
||||
lighthouse = {
|
||||
am_lighthouse = netCfg.isLighthouse;
|
||||
hosts = netCfg.lighthouses;
|
||||
serve_dns = netCfg.lighthouse.dns.enable;
|
||||
dns.host = netCfg.lighthouse.dns.host;
|
||||
dns.port = netCfg.lighthouse.dns.port;
|
||||
};
|
||||
relay = {
|
||||
am_relay = netCfg.isRelay;
|
||||
relays = netCfg.relays;
|
||||
use_relays = true;
|
||||
};
|
||||
listen = {
|
||||
host = netCfg.listen.host;
|
||||
port = resolveFinalPort netCfg;
|
||||
};
|
||||
tun = {
|
||||
disabled = netCfg.tun.disable;
|
||||
dev = if (netCfg.tun.device != null) then netCfg.tun.device else "nebula.${netName}";
|
||||
};
|
||||
firewall = {
|
||||
inbound = netCfg.firewall.inbound;
|
||||
outbound = netCfg.firewall.outbound;
|
||||
};
|
||||
} netCfg.settings;
|
||||
configFile = format.generate "nebula-config-${netName}.yml" (
|
||||
lib.warnIf
|
||||
((settings.lighthouse.am_lighthouse || settings.relay.am_relay) && settings.listen.port == 0)
|
||||
''
|
||||
Nebula network '${netName}' is configured as a lighthouse or relay, and its port is ${builtins.toString settings.listen.port}.
|
||||
You will likely experience connectivity issues: https://nebula.defined.net/docs/config/listen/#listenport
|
||||
''
|
||||
settings
|
||||
);
|
||||
settings = genSettings netName netCfg;
|
||||
generatedConfigFile = genConfigFile netName settings;
|
||||
configFile =
|
||||
if ((lib.versionAtLeast config.system.stateVersion "25.11") || netCfg.enableReload) then
|
||||
"/etc/nebula/${netName}.yml"
|
||||
else
|
||||
generatedConfigFile;
|
||||
capabilities =
|
||||
let
|
||||
nebulaPort = if !settings.tun.disabled then settings.listen.port else 0;
|
||||
@@ -278,6 +300,8 @@ in
|
||||
];
|
||||
before = [ "sshd.service" ];
|
||||
wantedBy = [ "multi-user.target" ];
|
||||
restartTriggers = lib.optional (!netCfg.enableReload) generatedConfigFile;
|
||||
reloadTriggers = lib.optional netCfg.enableReload generatedConfigFile;
|
||||
serviceConfig = {
|
||||
Type = "notify";
|
||||
Restart = "always";
|
||||
@@ -313,6 +337,22 @@ in
|
||||
) enabledNetworks
|
||||
);
|
||||
|
||||
environment.etc = lib.mkMerge (
|
||||
lib.mapAttrsToList
|
||||
(netName: netCfg: {
|
||||
"nebula/${netName}.yml" = {
|
||||
source = genConfigFile netName (genSettings netName netCfg);
|
||||
mode = "0440";
|
||||
user = nameToId netName;
|
||||
};
|
||||
})
|
||||
(
|
||||
lib.filterAttrs (
|
||||
_: netCfg: netCfg.enableReload || (lib.versionAtLeast config.system.stateVersion "25.11")
|
||||
) enabledNetworks
|
||||
)
|
||||
);
|
||||
|
||||
# Open the chosen ports for UDP.
|
||||
networking.firewall.allowedUDPPorts = lib.unique (
|
||||
lib.filter (port: port > 0) (
|
||||
|
||||
@@ -1011,7 +1011,8 @@ in
|
||||
defaults.services.ncps.cache.dataPath = "/path/to/ncps";
|
||||
};
|
||||
ndppd = runTest ./ndppd.nix;
|
||||
nebula = runTest ./nebula.nix;
|
||||
nebula.connectivity = runTest ./nebula/connectivity.nix;
|
||||
nebula.reload = runTest ./nebula/reload.nix;
|
||||
neo4j = runTest ./neo4j.nix;
|
||||
netbird = runTest ./netbird.nix;
|
||||
netbox-upgrade = runTest ./web-apps/netbox-upgrade.nix;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
let
|
||||
|
||||
# We'll need to be able to trade cert files between nodes via scp.
|
||||
inherit (import ./ssh-keys.nix pkgs)
|
||||
inherit (import ../ssh-keys.nix pkgs)
|
||||
snakeOilPrivateKey
|
||||
snakeOilPublicKey
|
||||
;
|
||||
@@ -0,0 +1,92 @@
|
||||
{ pkgs, lib, ... }:
|
||||
let
|
||||
|
||||
inherit (import ../ssh-keys.nix pkgs)
|
||||
snakeOilPrivateKey
|
||||
snakeOilPublicKey
|
||||
;
|
||||
|
||||
in
|
||||
{
|
||||
name = "nebula";
|
||||
|
||||
nodes = {
|
||||
lighthouse =
|
||||
{
|
||||
pkgs,
|
||||
lib,
|
||||
config,
|
||||
...
|
||||
}:
|
||||
{
|
||||
environment.systemPackages = [ pkgs.nebula ];
|
||||
environment.etc."nebula-key" = {
|
||||
user = "nebula-smoke";
|
||||
group = "nebula-smoke";
|
||||
source = snakeOilPrivateKey;
|
||||
mode = "0600";
|
||||
};
|
||||
|
||||
services.nebula.networks.smoke = {
|
||||
# Note that these paths won't exist when the machine is first booted.
|
||||
ca = "/etc/nebula/ca.crt";
|
||||
cert = "/etc/nebula/lighthouse.crt";
|
||||
key = "/etc/nebula/lighthouse.key";
|
||||
isLighthouse = true;
|
||||
listen = {
|
||||
host = "0.0.0.0";
|
||||
port = 4242;
|
||||
};
|
||||
enableReload = true;
|
||||
settings.sshd = {
|
||||
enabled = true;
|
||||
listen = "127.0.0.1:2222";
|
||||
host_key = "/etc/nebula-key";
|
||||
};
|
||||
};
|
||||
|
||||
# We will test that nebula is reloaded by switching specialisations.
|
||||
specialisation.sshd-off.configuration = {
|
||||
services.nebula.networks.smoke.settings.sshd.enabled = lib.mkForce false;
|
||||
};
|
||||
specialisation.sshd-on.configuration = {
|
||||
services.nebula.networks.smoke.settings.sshd.enabled = lib.mkForce true;
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
testScript =
|
||||
{ nodes, ... }:
|
||||
let
|
||||
sshd-on = "${nodes.lighthouse.system.build.toplevel}/specialisation/sshd-on";
|
||||
sshd-off = "${nodes.lighthouse.system.build.toplevel}/specialisation/sshd-off";
|
||||
in
|
||||
''
|
||||
# Create the certificate and sign the lighthouse's keys.
|
||||
lighthouse.succeed(
|
||||
"mkdir -p /etc/nebula",
|
||||
'nebula-cert ca -duration $((10*365*24*60))m -name "Smoke Test" -out-crt /etc/nebula/ca.crt -out-key /etc/nebula/ca.key',
|
||||
'nebula-cert sign -duration $((365*24*60))m -ca-crt /etc/nebula/ca.crt -ca-key /etc/nebula/ca.key -name "lighthouse" -groups "lighthouse" -ip "10.0.100.1/24" -out-crt /etc/nebula/lighthouse.crt -out-key /etc/nebula/lighthouse.key',
|
||||
'chown -R nebula-smoke:nebula-smoke /etc/nebula'
|
||||
)
|
||||
|
||||
# Restart nebula to pick up the keys.
|
||||
lighthouse.systemctl("restart nebula@smoke.service")
|
||||
lighthouse.succeed("ping -c5 10.0.100.1")
|
||||
|
||||
# Verify that nebula's ssh interface is up.
|
||||
lighthouse.succeed("${pkgs.nmap}/bin/nmap 127.0.0.1 | grep 2222/tcp")
|
||||
|
||||
# Switch configuration, verify nebula was reloaded and not restarted.
|
||||
lighthouse.succeed("${sshd-off}/bin/switch-to-configuration test 2>&1 | grep 'nebula' | grep 'reload'")
|
||||
|
||||
# Verify that nebula's ssh interface is no longer up.
|
||||
lighthouse.fail("${pkgs.nmap}/bin/nmap 127.0.0.1 | grep 2222/tcp")
|
||||
|
||||
# Switch configuration, verify reload again.
|
||||
lighthouse.succeed("${sshd-on}/bin/switch-to-configuration test 2>&1 | grep 'nebula' | grep 'reload'")
|
||||
|
||||
# Verify that ssh is back.
|
||||
lighthouse.succeed("${pkgs.nmap}/bin/nmap 127.0.0.1 | grep 2222/tcp")
|
||||
'';
|
||||
}
|
||||
@@ -26,7 +26,10 @@ buildGoModule rec {
|
||||
ldflags = [ "-X main.Build=${version}" ];
|
||||
|
||||
passthru.tests = {
|
||||
inherit (nixosTests) nebula;
|
||||
inherit (nixosTests.nebula)
|
||||
connectivity
|
||||
reload
|
||||
;
|
||||
};
|
||||
|
||||
meta = {
|
||||
|
||||
Reference in New Issue
Block a user