{ config, lib, pkgs, options, ... }: # This module provides a container whose traffic is routed through Mullvad VPN. # Other modules may configure `containers.mullvad-vpn.config` to run their # services through the container. let cfg = config.sydnix.deertopia.mullvad; in { options.sydnix.deertopia.mullvad = { enable = lib.mkEnableOption "Mullvad VPN"; interface = lib.mkOption { description = '' The network interface to use. See the output of `ip addr show`. ''; type = lib.types.str; default = "eno1"; }; peer = lib.mkOption { default = "us-atl-wg-001"; type = lib.types.str; description = '' The name of a Wireguard configuration file in modules/nixos/deertopia/mullvad/, without the .conf suffix. Ideally, we would support multiple peers without rebuilding, but... ''; }; }; config = lib.mkIf cfg.enable { sydnix.sops.secrets.wireguard-mullvad-key = {}; networking.nat = { enable = true; internalInterfaces = [ "ve-mullvad-vpn" ]; externalInterface = cfg.interface; }; containers.mullvad-vpn = { # Impermanence-esque wiping of undeclared state. ephemeral = true; autoStart = true; privateNetwork = true; enableTun = true; # These IP choices are arbitrary. hostAddress = "192.168.100.10"; # Counter-intuitively (IMO), the host reaches the container at *this* # address. localAddress = "192.168.100.11"; # Bind these directories to their corresponding paths on the host as to # persist them through container reboots. bindMounts = { "/config/wg".hostPath = toString ./mullvad; "/run/secrets".hostPath = "/run/secrets"; }; config = { pkgs, ... }@args: lib.mkMerge [ { systemd.services."create-wireguard-config" = { script = '' if [ ! -e /wg.conf ]; then cp "/config/wg/${cfg.peer}.conf" /wg.conf ${pkgs.replace-secret}/bin/replace-secret \ '{{WG_PRIVATE_KEY}}' \ /run/secrets/wireguard-mullvad-key \ /wg.conf chmod 777 /wg.conf fi ''; # requiredBy = [ "wg-quick0-wg0.service" ]; requires = [ "tmp.mount" ]; }; # HACK: Make sure wg starts *after* its config exists. systemd.services."wg-quick-wg0".requires = [ "create-wireguard-config.service" ]; networking.wg-quick.interfaces.wg0.configFile = "/wg.conf"; system.stateVersion = "24.11"; } ]; }; }; }