diff --git a/flake.nix b/flake.nix index 5d1fcde..77d2c4f 100644 --- a/flake.nix +++ b/flake.nix @@ -57,6 +57,7 @@ mkSharedModules = pkgs: pkgs-unstable: [ ./nixos/modules/base.nix + ./nixos/modules/services/wireguard-peer.nix inputs.home-manager.nixosModules.home-manager ({ ... }: { home-manager.useGlobalPkgs = true; diff --git a/home/modules/programs/waybar/default.nix b/home/modules/programs/waybar/default.nix index 5889e60..e475dc7 100644 --- a/home/modules/programs/waybar/default.nix +++ b/home/modules/programs/waybar/default.nix @@ -1,8 +1,9 @@ -{ pkgs, ... }: +{ pkgs, repoRoot, ... }: let commands = import ../../../../lib/commands.nix { inherit pkgs; }; inherit (commands) uwsm term; height = 20; + wireguardToggle = "${pkgs.xonsh}/bin/xonsh ${repoRoot}/util/toggle_wg.xsh"; in { imports = [ @@ -37,6 +38,7 @@ in "clock" "sway/language" "network" + "custom/wireguard" "bluetooth" "pulseaudio" "idle_inhibitor" @@ -53,7 +55,7 @@ in spacing = 8; }; idle_inhibitor = { - format = "| {icon}"; + format = "| {icon} "; start-activated = true; format-icons = { activated = "🫨"; @@ -61,7 +63,7 @@ in }; }; "sway/language" = { - format = "| {short}"; + format = "| {short} "; tooltip-format = "{long}"; }; clock = { @@ -72,29 +74,36 @@ in }; battery = { interval = 60; - format = "| {capacity}%"; + format = "| {capacity}% "; format-charging = "| ch:{capacity}%"; }; network = { tooltip-format = "{ifname} = {ipaddr}/{cidr}"; - format-wifi = "| w:{ipaddr}"; - format-ethernet = "| e:{ipaddr}"; - format-linked = "| l:{ipaddr}"; - format-disconnected = "| d"; + format-wifi = "| w:{essid} "; + format-ethernet = "| e:{ipaddr} "; + format-linked = "| l:{ipaddr} "; + format-disconnected = "| d "; interval = 15; on-click = "${uwsm} ${term} -e nmtui"; }; + "custom/wireguard" = { + exec = "${wireguardToggle} status"; + on-click = "${wireguardToggle} toggle"; + format = "| wg:{text} "; + interval = 15; + tooltip = false; + }; bluetooth = { - format = "| bt:{num_connections}"; + format = "| bt:{num_connections} "; format-disabled = ""; format-no-controller = ""; interval = 15; on-click = "${uwsm} ${term} -e bluetui"; }; pulseaudio = { - format = "| snd{volume}%"; - format-muted = "| snd:-"; - format-bluetooth = "| snd(bt):{volume}%"; + format = "| snd{volume}% "; + format-muted = "| snd:- "; + format-bluetooth = "| snd(bt):{volume}% "; on-click = "${uwsm} pavucontrol"; }; }; diff --git a/nixos/modules/profiles/workstation.nix b/nixos/modules/profiles/workstation.nix index d39d714..2fadb28 100644 --- a/nixos/modules/profiles/workstation.nix +++ b/nixos/modules/profiles/workstation.nix @@ -24,6 +24,8 @@ in security.sudo.wheelNeedsPassword = false; + alisceon.wireguardPeer.enable = true; + services = { printing.enable = true; pulseaudio.enable = false; diff --git a/nixos/modules/services/wireguard-peer.nix b/nixos/modules/services/wireguard-peer.nix new file mode 100644 index 0000000..65d07a1 --- /dev/null +++ b/nixos/modules/services/wireguard-peer.nix @@ -0,0 +1,57 @@ +{ config, lib, pkgs, repoLocalPath, ... }: + +let + cfg = config.alisceon.wireguardPeer; +in +{ + options.alisceon.wireguardPeer = { + enable = lib.mkEnableOption "a single WireGuard peer managed by wg-quick"; + + interface = lib.mkOption { + type = lib.types.str; + default = "wg0"; + description = "WireGuard interface name."; + }; + + configFile = lib.mkOption { + type = lib.types.str; + default = "/etc/wireguard/${cfg.interface}.conf"; + defaultText = "/etc/wireguard/.conf"; + description = '' + Path to an external wg-quick config file. Keep it root-owned and mode + 0600 so private keys and peer material stay outside Git and the Nix store. + ''; + }; + + autostart = lib.mkOption { + type = lib.types.bool; + default = true; + description = "Whether to bring the WireGuard interface up at boot."; + }; + }; + + config = lib.mkIf cfg.enable { + assertions = [ + { + assertion = lib.hasPrefix "/" cfg.configFile; + message = "alisceon.wireguardPeer.configFile must be an absolute path outside the repo."; + } + { + assertion = !(lib.hasPrefix repoLocalPath cfg.configFile); + message = "alisceon.wireguardPeer.configFile must be outside ${repoLocalPath}."; + } + ]; + + networking.wg-quick.interfaces.${cfg.interface} = { + inherit (cfg) autostart configFile; + }; + + systemd.services."wg-quick-${cfg.interface}".unitConfig.ConditionPathExists = cfg.configFile; + + environment.systemPackages = [ pkgs.wireguard-tools ]; + + systemd.tmpfiles.rules = [ + "d /etc/wireguard 0700 root root -" + ]; + }; +} diff --git a/util/toggle_wg.xsh b/util/toggle_wg.xsh new file mode 100755 index 0000000..bc88bc4 --- /dev/null +++ b/util/toggle_wg.xsh @@ -0,0 +1,25 @@ +import sys + +isup = "does not exist." not in $(ip link show dev wg0 2>&1) + +try: + match sys.argv[1]: + case "toggle": + if isup: + footclient wg-quick down wg0 + else: + footclient wg-quick up wg0 + case "status": + if isup: + print("u") + else: + print("d") + case _: + raise RuntimeError + +except (RuntimeError, IndexError): + print('"toggle" or "status" must be provided') + exit(1) + +exit(0) +