forked from mirrors_public/oddlama_nix-config
feat(wireguard): generate psks only if needed; add most of the qr code generator
This commit is contained in:
parent
925d3856e0
commit
d5f2880457
13 changed files with 225 additions and 108 deletions
|
@ -52,6 +52,8 @@
|
|||
...
|
||||
} @ inputs:
|
||||
{
|
||||
extraLib = import ./nix/lib.nix inputs;
|
||||
|
||||
# The identities that are used to rekey agenix secrets and to
|
||||
# decrypt all repository-wide secrets.
|
||||
secrets = {
|
||||
|
|
|
@ -21,5 +21,8 @@
|
|||
};
|
||||
};
|
||||
|
||||
extra.wireguard.vms.address = ["10.0.0.10/32"];
|
||||
extra.wireguard.vms = {
|
||||
via = "ward";
|
||||
addresses = ["10.0.0.10/32"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -27,12 +27,12 @@
|
|||
enable = true;
|
||||
port = 51822;
|
||||
openFirewall = true;
|
||||
externalPeers = {
|
||||
test1 = ["10.0.0.91/32"];
|
||||
test2 = ["10.0.0.92/32"];
|
||||
test3 = ["10.0.0.93/32"];
|
||||
};
|
||||
};
|
||||
address = ["10.0.0.1/24"];
|
||||
externalPeers = {
|
||||
test1 = ["10.0.0.91/32"];
|
||||
test2 = ["10.0.0.92/32"];
|
||||
test3 = ["10.0.0.93/32"];
|
||||
};
|
||||
addresses = ["10.0.0.1/24"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -23,10 +23,10 @@
|
|||
enable = true;
|
||||
port = 51822;
|
||||
openFirewall = true;
|
||||
externalPeers = {
|
||||
zack1 = ["10.0.0.90/32"];
|
||||
};
|
||||
};
|
||||
address = ["10.0.0.2/24"];
|
||||
externalPeers = {
|
||||
zack1 = ["10.0.0.90/32"];
|
||||
};
|
||||
addresses = ["10.0.0.2/24"];
|
||||
};
|
||||
}
|
||||
|
|
|
@ -11,9 +11,11 @@
|
|||
(lib)
|
||||
any
|
||||
attrNames
|
||||
attrValues
|
||||
concatMap
|
||||
concatMapStrings
|
||||
concatStringsSep
|
||||
filter
|
||||
filterAttrs
|
||||
head
|
||||
mapAttrsToList
|
||||
|
@ -23,6 +25,7 @@
|
|||
mkOption
|
||||
mkEnableOption
|
||||
optionalAttrs
|
||||
optionals
|
||||
splitString
|
||||
types
|
||||
;
|
||||
|
@ -35,10 +38,12 @@
|
|||
|
||||
cfg = config.extra.wireguard;
|
||||
|
||||
configForNetwork = wgName: wg: let
|
||||
configForNetwork = wgName: wgCfg: let
|
||||
inherit
|
||||
(extraLib.wireguard wgName nodes)
|
||||
allPeers
|
||||
(extraLib.wireguard wgName)
|
||||
associatedServerNodes
|
||||
associatedClientNodes
|
||||
externalPeerName
|
||||
peerPresharedKeyPath
|
||||
peerPresharedKeySecret
|
||||
peerPrivateKeyPath
|
||||
|
@ -46,17 +51,32 @@
|
|||
peerPublicKeyPath
|
||||
;
|
||||
|
||||
otherPeers = filterAttrs (n: _: n != nodeName) allPeers;
|
||||
filterSelf = filter (x: x != nodeName);
|
||||
wgCfgOf = node: nodes.${node}.config.extra.wireguard.${wgName};
|
||||
|
||||
ourClientNodes =
|
||||
optionals wgCfg.server.enable
|
||||
(filter (n: (wgCfgOf n).via == nodeName) associatedClientNodes);
|
||||
|
||||
# The list of peers that we have to know the psk to.
|
||||
neededPeers =
|
||||
if wgCfg.server.enable
|
||||
then
|
||||
filterSelf associatedServerNodes
|
||||
++ map externalPeerName (attrNames wgCfg.server.externalPeers)
|
||||
++ ourClientNodes
|
||||
else [wgCfg.via];
|
||||
in {
|
||||
secrets =
|
||||
concatAttrs (map (other: {
|
||||
${peerPresharedKeySecret nodeName other}.file = peerPresharedKeyPath nodeName other;
|
||||
}) (attrNames otherPeers))
|
||||
${peerPresharedKeySecret nodeName other}.file = peerPresharedKeyPath nodeName other;
|
||||
})
|
||||
neededPeers)
|
||||
// {
|
||||
${peerPrivateKeySecret nodeName}.file = peerPrivateKeyPath nodeName;
|
||||
};
|
||||
|
||||
netdevs."${wg.priority}-${wgName}" = {
|
||||
netdevs."${wgCfg.priority}-${wgName}" = {
|
||||
netdevConfig = {
|
||||
Kind = "wireguard";
|
||||
Name = "${wgName}";
|
||||
|
@ -66,27 +86,64 @@
|
|||
{
|
||||
PrivateKeyFile = config.rekey.secrets.${peerPrivateKeySecret nodeName}.path;
|
||||
}
|
||||
// optionalAttrs wg.server.enable {
|
||||
ListenPort = wg.server.port;
|
||||
// optionalAttrs wgCfg.server.enable {
|
||||
ListenPort = wgCfg.server.port;
|
||||
};
|
||||
wireguardPeers =
|
||||
mapAttrsToList (peerName: peerAllowedIPs: {
|
||||
wireguardPeerConfig =
|
||||
{
|
||||
if wgCfg.server.enable
|
||||
then
|
||||
# Always include all other server nodes.
|
||||
map (serverNode: {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = builtins.readFile (peerPublicKeyPath serverNode);
|
||||
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName serverNode}.path;
|
||||
# The allowed ips of a server node are it's own addreses,
|
||||
# plus each external peer's addresses,
|
||||
# plus each client's addresses that is connected via this node.
|
||||
AllowedIPs =
|
||||
(wgCfgOf serverNode).addresses
|
||||
++ attrValues (wgCfgOf serverNode).server.externalPeers
|
||||
++ map (n: (wgCfgOf n).addresses) ourClientNodes;
|
||||
};
|
||||
}) (filterSelf associatedServerNodes)
|
||||
# All our external peers
|
||||
++ mapAttrsToList (extPeer: allowedIPs: let
|
||||
peerName = externalPeerName extPeer;
|
||||
in {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = builtins.readFile (peerPublicKeyPath peerName);
|
||||
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName peerName}.path;
|
||||
AllowedIPs = peerAllowedIPs;
|
||||
}
|
||||
// optionalAttrs wg.server.enable {
|
||||
AllowedIPs = allowedIPs;
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
})
|
||||
otherPeers;
|
||||
})
|
||||
wgCfg.server.externalPeers
|
||||
# All client nodes that have their via set to us.
|
||||
++ mapAttrsToList (clientNode: {
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = builtins.readFile (peerPublicKeyPath clientNode);
|
||||
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName clientNode}.path;
|
||||
AllowedIPs = (wgCfgOf clientNode).addresses;
|
||||
PersistentKeepalive = 25;
|
||||
};
|
||||
})
|
||||
ourClientNodes
|
||||
else
|
||||
# We are a client node, so only include our via server.
|
||||
[
|
||||
{
|
||||
wireguardPeerConfig = {
|
||||
PublicKey = builtins.readFile (peerPublicKeyPath wgCfg.via);
|
||||
PresharedKeyFile = config.rekey.secrets.${peerPresharedKeySecret nodeName wgCfg.via}.path;
|
||||
AllowedIPs = (wgCfgOf wgCfg.via).addresses;
|
||||
};
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
networks."${wg.priority}-${wgName}" = {
|
||||
networks."${wgCfg.priority}-${wgName}" = {
|
||||
matchConfig.Name = wgName;
|
||||
networkConfig.Address = wg.address;
|
||||
networkConfig.Address = wgCfg.addresses;
|
||||
};
|
||||
};
|
||||
in {
|
||||
|
@ -109,6 +166,20 @@ in {
|
|||
type = types.bool;
|
||||
description = mdDoc "Whether to open the firewall for the specified `listenPort`, if {option}`listen` is `true`.";
|
||||
};
|
||||
|
||||
externalPeers = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
default = {};
|
||||
example = {my-android-phone = ["10.0.0.97/32"];};
|
||||
description = mdDoc ''
|
||||
Allows defining an extra set of peers that should be added to this wireguard network,
|
||||
but will not be managed by this flake. (e.g. phones)
|
||||
|
||||
These external peers will only know this node as a peer, which will forward
|
||||
their traffic to other members of the network if required. This requires
|
||||
this node to act as a server.
|
||||
'';
|
||||
};
|
||||
};
|
||||
|
||||
priority = mkOption {
|
||||
|
@ -117,27 +188,22 @@ in {
|
|||
description = mdDoc "The order priority used when creating systemd netdev and network files.";
|
||||
};
|
||||
|
||||
address = mkOption {
|
||||
via = mkOption {
|
||||
default = null;
|
||||
type = types.uniq (types.nullOr types.str);
|
||||
description = mdDoc ''
|
||||
The server node via which to connect to the network.
|
||||
This must defined if and only if this node is not a server.
|
||||
'';
|
||||
};
|
||||
|
||||
addresses = mkOption {
|
||||
type = types.listOf types.str;
|
||||
description = mdDoc ''
|
||||
The addresses to configure for this interface. Will automatically be added
|
||||
as this peer's allowed addresses to all other peers.
|
||||
'';
|
||||
};
|
||||
|
||||
externalPeers = mkOption {
|
||||
type = types.attrsOf (types.listOf types.str);
|
||||
default = {};
|
||||
example = {my-android-phone = ["10.0.0.97/32"];};
|
||||
description = mdDoc ''
|
||||
Allows defining an extra set of peers that should be added to this wireguard network,
|
||||
but will not be managed by this flake. (e.g. phones)
|
||||
|
||||
These external peers will only know this node as a peer, which will forward
|
||||
their traffic to other members of the network if required. This requires
|
||||
this node to act as a server.
|
||||
'';
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
@ -148,12 +214,14 @@ in {
|
|||
in {
|
||||
assertions = concatMap (wgName: let
|
||||
inherit
|
||||
(extraLib.wireguard wgName nodes)
|
||||
(extraLib.wireguard wgName)
|
||||
externalPeerNamesRaw
|
||||
usedAddresses
|
||||
associatedNodes
|
||||
;
|
||||
|
||||
wgCfg = cfg.${wgName};
|
||||
wgCfgOf = node: nodes.${node}.config.extra.wireguard.${wgName};
|
||||
duplicatePeers = duplicates externalPeerNamesRaw;
|
||||
duplicateAddrs = duplicates (map (x: head (splitString "/" x)) usedAddresses);
|
||||
in [
|
||||
|
@ -169,9 +237,19 @@ in {
|
|||
assertion = duplicateAddrs == [];
|
||||
message = "Wireguard network '${wgName}': Addresses used multiple times: ${concatStringsSep ", " duplicateAddrs}";
|
||||
}
|
||||
# TODO externalPeers != [] -> server.listen
|
||||
# TODO externalPeers != [] -> ip forwarding
|
||||
# TODO psks only between all nodes and each node-externalpeer pair
|
||||
{
|
||||
assertion = wgCfg.server.externalPeers != {} -> wgCfg.server.enable;
|
||||
message = "Wireguard network '${wgName}': Defining external peers requires server.enable = true.";
|
||||
}
|
||||
{
|
||||
assertion = wgCfg.server.enable == (wgCfg.via == null);
|
||||
message = "Wireguard network '${wgName}': A via server must be defined exactly iff this isn't a server node.";
|
||||
}
|
||||
{
|
||||
assertion = wgCfg.via != null -> (wgCfgOf wgCfg.via).server.enable;
|
||||
message = "Wireguard network '${wgName}': The specified via node '${wgCfg.via}' must be a wireguard server.";
|
||||
}
|
||||
# TODO externalPeers != {} -> ip forwarding
|
||||
# TODO no overlapping allowed ip range? 0.0.0.0 would be ok to overlap though
|
||||
]) (attrNames cfg);
|
||||
|
||||
|
|
|
@ -1,36 +1,22 @@
|
|||
{
|
||||
self,
|
||||
pkgs,
|
||||
nixpkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(pkgs.lib)
|
||||
concatMapStrings
|
||||
concatStringsSep
|
||||
escapeShellArg
|
||||
substring
|
||||
;
|
||||
isAbsolutePath = x: substring 0 1 x == "/";
|
||||
masterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
|
||||
extraEncryptionPubkeys =
|
||||
concatMapStrings (
|
||||
x:
|
||||
if isAbsolutePath x
|
||||
then ''-R ${escapeShellArg x} ''
|
||||
else ''-r ${escapeShellArg x} ''
|
||||
)
|
||||
self.secrets.extraEncryptionPubkeys;
|
||||
inherit (nixpkgs.lib) concatStringsSep;
|
||||
inherit (extraLib) rageEncryptArgs;
|
||||
in
|
||||
pkgs.writeShellScript "format-secrets" ''
|
||||
set -euo pipefail
|
||||
[[ -d .git ]] && [[ -f flake.nix ]] || { echo "[1;31merror:[m Please execute this from the project's root folder (the folder with flake.nix)" >&2; exit 1; }
|
||||
for f in $(find . -type f -name '*.nix.age'); do
|
||||
echo "Formatting $f ..."
|
||||
decrypted=$(${../rage-decrypt.sh} --print-out-path "$f" ${concatStringsSep " " self.secrets.masterIdentities}) \
|
||||
decrypted=$(${../rage-decrypt-and-cache.sh} --print-out-path "$f" ${concatStringsSep " " self.secrets.masterIdentities}) \
|
||||
|| { echo "[1;31merror:[m Failed to decrypt!" >&2; exit 1; }
|
||||
formatted=$(${pkgs.alejandra}/bin/alejandra --quiet < "$decrypted") \
|
||||
|| { echo "[1;31merror:[m Failed to format $decrypted!" >&2; exit 1; }
|
||||
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$formatted" > "$f" \
|
||||
${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$formatted" > "$f" \
|
||||
|| { echo "[1;31merror:[m Failed to re-encrypt!" >&2; exit 1; }
|
||||
done
|
||||
''
|
||||
|
|
|
@ -17,24 +17,14 @@
|
|||
unique
|
||||
;
|
||||
|
||||
extraLib = import ../lib.nix inputs;
|
||||
isAbsolutePath = x: substring 0 1 x == "/";
|
||||
masterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
|
||||
extraEncryptionPubkeys =
|
||||
concatMapStrings (
|
||||
x:
|
||||
if isAbsolutePath x
|
||||
then ''-R ${escapeShellArg x} ''
|
||||
else ''-r ${escapeShellArg x} ''
|
||||
)
|
||||
self.secrets.extraEncryptionPubkeys;
|
||||
inherit (self.extraLib) rageEncryptArgs;
|
||||
|
||||
nodeNames = attrNames self.nodes;
|
||||
wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames);
|
||||
|
||||
generateNetworkKeys = wgName: let
|
||||
inherit
|
||||
(extraLib.wireguard wgName self.nodes)
|
||||
(self.extraLib.wireguard wgName)
|
||||
allPeers
|
||||
associatedNodes
|
||||
associatedServerNodes
|
||||
|
@ -57,7 +47,7 @@
|
|||
echo "Generating [34m"${keyBasename}".{[31mage[34m,[32mpub[34m}[m"
|
||||
privkey=$(${pkgs.wireguard-tools}/bin/wg genkey)
|
||||
echo "$privkey" | ${pkgs.wireguard-tools}/bin/wg pubkey > ${pubkeyFile}
|
||||
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$privkey" > ${privkeyFile} \
|
||||
${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$privkey" > ${privkeyFile} \
|
||||
|| { echo "[1;31merror:[m Failed to encrypt wireguard private key for peer ${peerName} on network ${wgName}!" >&2; exit 1; }
|
||||
fi
|
||||
'';
|
||||
|
@ -73,7 +63,7 @@
|
|||
mkdir -p $(dirname ${pskFile})
|
||||
echo "Generating [33m"${pskFile}"[m"
|
||||
psk=$(${pkgs.wireguard-tools}/bin/wg genpsk)
|
||||
${pkgs.rage}/bin/rage -e ${masterIdentityArgs} ${extraEncryptionPubkeys} <<< "$psk" > ${pskFile} \
|
||||
${pkgs.rage}/bin/rage -e ${rageEncryptArgs} <<< "$psk" > ${pskFile} \
|
||||
|| { echo "[1;31merror:[m Failed to encrypt wireguard psk for peers ${peer1} and ${peer2} on network ${wgName}!" >&2; exit 1; }
|
||||
fi
|
||||
'';
|
||||
|
|
|
@ -9,22 +9,57 @@
|
|||
concatMap
|
||||
concatStringsSep
|
||||
escapeShellArg
|
||||
filter
|
||||
unique
|
||||
;
|
||||
|
||||
extraLib = import ../lib.nix inputs;
|
||||
inherit (self.extraLib) rageDecryptArgs;
|
||||
|
||||
nodeNames = attrNames self.nodes;
|
||||
wireguardNetworks = unique (concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard) nodeNames);
|
||||
|
||||
externalPeersForNet = wgName:
|
||||
map (peer: {inherit wgName peer;})
|
||||
(attrNames (extraLib.wireguard wgName self.nodes).allExternalPeers);
|
||||
concatMap (serverNode:
|
||||
map
|
||||
(peer: {inherit wgName serverNode peer;})
|
||||
(attrNames self.nodes.${serverNode}.config.extra.wireguard.${wgName}.server.externalPeers))
|
||||
(self.extraLib.wireguard wgName).associatedServerNodes;
|
||||
allExternalPeers = concatMap externalPeersForNet wireguardNetworks;
|
||||
in
|
||||
# TODO generate "classic" config and run qrencode
|
||||
pkgs.writeShellScript "show-wireguard-qr" ''
|
||||
set -euo pipefail
|
||||
echo ${escapeShellArg (concatStringsSep "\n" (map (x: "${x.wgName}.${x.peer}") allExternalPeers))} | ${pkgs.fzf}/bin/fzf
|
||||
json_sel=$(echo ${escapeShellArg (concatStringsSep "\n" (map (x: "${builtins.toJSON x}\t[33m${x.wgName}[m.[34m${x.serverNode}[m.[32m${x.peer}[m") allExternalPeers))} \
|
||||
| ${pkgs.fzf}/bin/fzf --delimiter='\t' --ansi --multi --query="''${1-}" --tiebreak=end --bind=tab:down,btab:up,change:top,ctrl-space:toggle --with-nth=2.. --height='~50%' --tac \
|
||||
| ${pkgs.coreutils}/bin/cut -d$'\t' -f1)
|
||||
[[ -n "$json_sel" ]] || exit 1
|
||||
|
||||
# TODO for each output line
|
||||
# TODO maybe just call a json -> make script that gives wireguard config to make this easier
|
||||
|
||||
wgName=$(${pkgs.jq}/bin/jq -r .wgName <<< "$json_sel")
|
||||
serverNode=$(${pkgs.jq}/bin/jq -r .serverNode <<< "$json_sel")
|
||||
peer=$(${pkgs.jq}/bin/jq -r .peer <<< "$json_sel")
|
||||
|
||||
serverPubkey=$(nix eval --raw ".#extraLib" \
|
||||
--apply 'extraLib: builtins.readFile ((extraLib.wireguard "'"$wgName"'").peerPublicKeyPath "'"$serverNode"'")')
|
||||
privKeyPath=$(nix eval --raw ".#extraLib" \
|
||||
--apply 'extraLib: (extraLib.wireguard "'"$wgName"'").peerPrivateKeyPath "'"$peer"'"')
|
||||
serverPskPath=$(nix eval --raw ".#extraLib" \
|
||||
--apply 'extraLib: (extraLib.wireguard "'"$wgName"'").peerPresharedKeyPath "'"$serverNode"'" "'"$peer"'"')
|
||||
|
||||
privKey=$(${pkgs.rage}/bin/rage -d ${rageDecryptArgs} "$privKeyPath") \
|
||||
|| { echo "[1;31merror:[m Failed to decrypt!" >&2; exit 1; }
|
||||
serverPsk=$(${pkgs.rage}/bin/rage -d ${rageDecryptArgs} "$serverPskPath") \
|
||||
|| { echo "[1;31merror:[m Failed to decrypt!" >&2; exit 1; }
|
||||
|
||||
cat <<EOF | tee /dev/tty | ${pkgs.qrencode}/bin/qrencode -t ansiutf8
|
||||
[Interface]
|
||||
Address =
|
||||
PrivateKey = $privKey
|
||||
|
||||
[Peer]
|
||||
PublicKey = $serverPubkey
|
||||
PresharedKey = $serverPsk
|
||||
AllowedIPs =
|
||||
Endpoint =
|
||||
EOF
|
||||
''
|
||||
|
|
|
@ -28,5 +28,5 @@ in {
|
|||
rageImportEncrypted = identities: nixFile:
|
||||
assert assertMsg (builtins.isPath nixFile) "The file to decrypt must be given as a path to prevent impurity.";
|
||||
assert assertMsg (hasSuffix ".nix.age" nixFile) "The content of the decrypted file must be a nix expression and should therefore end in .nix.age";
|
||||
exec ([./rage-decrypt.sh nixFile] ++ identities);
|
||||
exec ([./rage-decrypt-and-cache.sh nixFile] ++ identities);
|
||||
}
|
||||
|
|
|
@ -10,19 +10,14 @@
|
|||
agenix-rekey,
|
||||
...
|
||||
} @ inputs: let
|
||||
inherit
|
||||
(nixpkgs.lib)
|
||||
optionals
|
||||
;
|
||||
|
||||
extraLib = import ./lib.nix inputs;
|
||||
inherit (nixpkgs.lib) optionals;
|
||||
in
|
||||
nodeName: nodeMeta: {
|
||||
inherit (nodeMeta) system;
|
||||
pkgs = self.pkgs.${nodeMeta.system};
|
||||
specialArgs = {
|
||||
inherit (nixpkgs) lib;
|
||||
inherit extraLib;
|
||||
inherit (self) extraLib;
|
||||
inherit inputs;
|
||||
inherit nodeName;
|
||||
inherit nodeMeta;
|
||||
|
|
45
nix/lib.nix
45
nix/lib.nix
|
@ -1,9 +1,15 @@
|
|||
{nixpkgs, ...}: let
|
||||
{
|
||||
self,
|
||||
nixpkgs,
|
||||
...
|
||||
}: let
|
||||
inherit
|
||||
(nixpkgs.lib)
|
||||
attrNames
|
||||
attrValues
|
||||
concatMap
|
||||
concatMapStrings
|
||||
escapeShellArg
|
||||
filter
|
||||
flatten
|
||||
foldl'
|
||||
|
@ -12,6 +18,7 @@
|
|||
mergeAttrs
|
||||
nameValuePair
|
||||
partition
|
||||
substring
|
||||
unique
|
||||
;
|
||||
in rec {
|
||||
|
@ -33,8 +40,24 @@ in rec {
|
|||
# Concatenates all given attrsets as if calling a // b in order.
|
||||
concatAttrs = foldl' mergeAttrs {};
|
||||
|
||||
# True if the path or string starts with /
|
||||
isAbsolutePath = x: substring 0 1 x == "/";
|
||||
|
||||
rageMasterIdentityArgs = concatMapStrings (x: ''-i ${escapeShellArg x} '') self.secrets.masterIdentities;
|
||||
rageExtraEncryptionPubkeys =
|
||||
concatMapStrings (
|
||||
x:
|
||||
if isAbsolutePath x
|
||||
then ''-R ${escapeShellArg x} ''
|
||||
else ''-r ${escapeShellArg x} ''
|
||||
)
|
||||
self.secrets.extraEncryptionPubkeys;
|
||||
# The arguments required to de-/encrypt a secret in this repository
|
||||
rageDecryptArgs = "${rageMasterIdentityArgs}";
|
||||
rageEncryptArgs = "${rageMasterIdentityArgs} ${rageExtraEncryptionPubkeys}";
|
||||
|
||||
# Wireguard related functions that are reused in several files of this flake
|
||||
wireguard = wgName: nodes: rec {
|
||||
wireguard = wgName: rec {
|
||||
sortedPeers = peerA: peerB:
|
||||
if peerA < peerB
|
||||
then {
|
||||
|
@ -64,25 +87,27 @@ in rec {
|
|||
# All nodes that are part of this network
|
||||
associatedNodes =
|
||||
filter
|
||||
(n: builtins.hasAttr wgName nodes.${n}.config.extra.wireguard)
|
||||
(attrNames nodes);
|
||||
(n: builtins.hasAttr wgName self.nodes.${n}.config.extra.wireguard)
|
||||
(attrNames self.nodes);
|
||||
|
||||
# Partition nodes by whether they are servers
|
||||
_associatedNodes_isServerPartition =
|
||||
partition
|
||||
(n: nodes.${n}.config.extra.wireguard.${wgName}.server.enable)
|
||||
(n: self.nodes.${n}.config.extra.wireguard.${wgName}.server.enable)
|
||||
associatedNodes;
|
||||
|
||||
associatedServerNodes = _associatedNodes_isServerPartition.right;
|
||||
associatedClientNodes = _associatedNodes_isServerPartition.wrong;
|
||||
|
||||
# Maps all nodes that are part of this network to their addresses
|
||||
nodePeers = genAttrs associatedNodes (n: nodes.${n}.config.extra.wireguard.${wgName}.address);
|
||||
nodePeers = genAttrs associatedNodes (n: self.nodes.${n}.config.extra.wireguard.${wgName}.addresses);
|
||||
|
||||
externalPeerName = p: "external-${p}";
|
||||
|
||||
# Only peers that are defined as externalPeers on the given node.
|
||||
# Prepends "external-" to their name.
|
||||
externalPeersForNode = node:
|
||||
mapAttrs' (p: nameValuePair "external-${p}") nodes.${node}.config.extra.wireguard.${wgName}.externalPeers;
|
||||
mapAttrs' (p: nameValuePair (externalPeerName p)) self.nodes.${node}.config.extra.wireguard.${wgName}.server.externalPeers;
|
||||
|
||||
# All peers that are defined as externalPeers on any node.
|
||||
# Prepends "external-" to their name.
|
||||
|
@ -92,11 +117,11 @@ in rec {
|
|||
allPeers = nodePeers // allExternalPeers;
|
||||
|
||||
# Concatenation of all external peer names names without any transformations.
|
||||
externalPeerNamesRaw = concatMap (n: attrNames nodes.${n}.config.extra.wireguard.${wgName}.externalPeers) associatedNodes;
|
||||
externalPeerNamesRaw = concatMap (n: attrNames self.nodes.${n}.config.extra.wireguard.${wgName}.server.externalPeers) associatedNodes;
|
||||
|
||||
# A list of all occurring addresses.
|
||||
usedAddresses =
|
||||
concatMap (n: nodes.${n}.config.extra.wireguard.${wgName}.address) associatedNodes
|
||||
++ flatten (concatMap (n: attrValues nodes.${n}.config.extra.wireguard.${wgName}.externalPeers) associatedNodes);
|
||||
concatMap (n: self.nodes.${n}.config.extra.wireguard.${wgName}.addresses) associatedNodes
|
||||
++ flatten (concatMap (n: attrValues self.nodes.${n}.config.extra.wireguard.${wgName}.server.externalPeers) associatedNodes);
|
||||
};
|
||||
}
|
||||
|
|
|
@ -15,8 +15,11 @@
|
|||
self,
|
||||
nixpkgs,
|
||||
...
|
||||
} @ inputs:
|
||||
with nixpkgs.lib; let
|
||||
} @ inputs: let
|
||||
inherit
|
||||
(nixpkgs.lib)
|
||||
mapAttrs
|
||||
;
|
||||
# If the given expression is a bare set, it will be wrapped in a function,
|
||||
# so that the imported file can always be applied to the inputs, similar to
|
||||
# how modules can be functions or sets.
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue