network/nix/nixos-module/container/anon.nix

102 lines
2.7 KiB
Nix

{ hostName, config, lib, pkgs, ... }:
let
gateway = "upstream1";
tunnels = lib.filterAttrs (_: wireguard:
wireguard != null
) config.site.hosts.${hostName}.wireguard;
firstTunnel =
if builtins.length (builtins.attrNames tunnels) > 0
then builtins.head (builtins.attrNames tunnels)
else null;
enabled = firstTunnel != null;
privateKeyFile = ifName:
"/run/wireguard-keys/${ifName}.key";
in
{
systemd.services = builtins.foldl' (services: ifName: services // {
"wireguard-key-${ifName}" = {
description = "Create key file for wireguard interface '${ifName}'";
requiredBy = [ "systemd-networkd.service" ];
before = [ "systemd-networkd.service" ];
serviceConfig.Type = "oneshot";
script = ''
#! ${pkgs.runtimeShell} -e
F=${privateKeyFile ifName}
mkdir -p -m 0700 $(dirname $F)
chown systemd-network:systemd-network $(dirname $F)
rm -f $F
cat >$F <<EOF
${tunnels.${ifName}.privateKey}
EOF
chmod 0400 $F
chown systemd-network:systemd-network $F
'';
};
}) {} (builtins.attrNames tunnels);
environment.systemPackages = lib.optionals enabled [
pkgs.wireguard-tools
];
systemd.network.netdevs = builtins.mapAttrs (ifName: wireguard: {
netdevConfig = {
Name = ifName;
Kind = "wireguard";
};
wireguardConfig.PrivateKeyFile = privateKeyFile ifName;
wireguardPeers = [ {
wireguardPeerConfig = {
PublicKey = wireguard.publicKey;
Endpoint = wireguard.endpoint;
AllowedIPs = "0.0.0.0/0, ::/0";
};
} ];
}) tunnels;
systemd.network.networks = {
# Endpoint host-routes
core.routes = map (wireguard: {
routeConfig = {
Destination = builtins.head (builtins.match "(.+):.*" wireguard.endpoint) + "/32";
Gateway = config.site.net.core.hosts4.${gateway};
};
}) (builtins.attrValues tunnels);
} // builtins.mapAttrs (ifName: wireguard: {
# Wireguard interfaces
matchConfig.Name = ifName;
addresses = map (addr: {
addressConfig.Address = addr;
}) wireguard.addresses;
# IPv4 default route
networkConfig.DefaultRouteOnDevice = true;
# IPv6 default route
routes = [ {
routeConfig.Destination = "::/0";
} ];
extraConfig = ''
[CAKE]
Parent = root
# DOCSIS overhead
OverheadBytes = 18
Bandwidth = ${toString wireguard.upBandwidth}K
'';
}) tunnels;
networking.nat = lib.optionalAttrs enabled {
enable = true;
enableIPv6 = true;
internalInterfaces = [ "core" ];
externalInterface = firstTunnel;
inherit (config.site.hosts.${hostName}) forwardPorts;
};
# TODO: firewall
}