nix-configs/nixos-modules/services/tailscale-openvpn.nix
2024-04-02 15:30:58 +02:00

93 lines
2.7 KiB
Nix

{ options, config, lib, pkgs, ... }:
with lib;
{
options.ragon.services.tailscale-openvpn = {
enable = mkEnableOption "Tailscale OpenVPN Bridge";
config = mkOption {
type = types.attrsOf types.str;
};
tsAuthKey = mkOption { type = types.str; };
};
config =
let
cfg = config.ragon.services.tailscale-openvpn;
bridgeExt = "br-ovpn-ext";
container = server: "ovpn-${server}";
bridge = server: "br-ovpn-${server}";
in
mkIf cfg.enable
{
networking.bridges = {
${bridgeExt}.interfaces = { };
} // (mapAttrs
(server: _: {
name = bridge server;
value = { ipv4.addresses = [ ]; };
})
cfg.config);
networking.interfaces = {
${bridgeExt}.ipv4.addresses = [{ address = "192.168.129.1"; prefixLength = 24; }];
} // (optionalAttrs cfg.bridges
(mapAttrs
(server: _: {
name = bridge server;
value = { ipv4.addresses = [ ]; };
})
cfg.config
)
);
networking.nat = {
enable = true;
internalInterfaces = [ bridgeExt ];
};
systemd.services = {
"container@".after = [ "network.target" ];
} // (mapListToAttrs
(server: _: {
name = "container@${container server}";
value = { requires = [ "network-addresses-${bridgeExt}.service" ]; };
})
cfg.config
);
containers = imap0
(i: v: {
name = v.name;
value = {
autoStart = true;
ephemeral = true;
enableTun = true;
privateNetwork = true;
hostBridge = bridgeExt;
localAddress = "192.168.129.${toString (i + 2)}/24";
bindMounts = {
"/host/run" = { hostPath = "/run"; isReadOnly = true; };
"/run/agenix.d" = { hostPath = "/run/agenix.d"; isReadOnly = true; };
};
config = {
services.openvpn.servers.${v.name} = {
config = ''
config ${v.value}
'';
up = "echo nameserver $nameserver | ${pkgs.openresolv}/sbin/resolvconf -m 0 -a $dev";
down = "${pkgs.openresolv}/sbin/resolvconf -d $dev";
};
services.tailscale = {
enable = true;
useRoutingFeatures = "server";
extraUpFlags = [ "--advertise-exit-node" ];
authKeyFile = cfg.tsAuthKey;
openFirewall = true;
};
};
};
})
(nameValuePair cfg.config);
};
}