From 7cf6867eced638a282f4a6a3bbb1fb02d188f038 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20Rivera?= Date: Sat, 15 Aug 2026 20:07:26 +0200 Subject: [PATCH] custom-vpn-picker: init --- README.md | 3 + modules/applications/hyprland.nix | 3 +- modules/applications/mullvad.nix | 13 ---- modules/hosts/desktop.nix | 3 +- modules/hosts/laptop.nix | 3 +- modules/other/user.nix | 12 ++++ modules/utilities/agenix.nix | 6 ++ modules/utilities/vpn.nix | 100 ++++++++++++++++++++++++++++++ other/hyprland/hyprland.lua | 9 ++- secrets/epfl.age | 7 +++ secrets/secrets.nix | 4 ++ 11 files changed, 144 insertions(+), 19 deletions(-) delete mode 100644 modules/applications/mullvad.nix create mode 100644 modules/utilities/vpn.nix create mode 100644 secrets/epfl.age diff --git a/README.md b/README.md index 1c97976..54197f8 100644 --- a/README.md +++ b/README.md @@ -569,6 +569,9 @@ secrets/ Encrypted secrets should remain encrypted in Git. Decrypted secret contents and private keys should not be committed. +* To edit a secret use `agenix -e .age -i /etc/ssh/ssh_host_ed25519_key`. +* To decrypt a secret use `sudo agenix -d .age -i /etc/ssh/ssh_host_ed25519_key`. + --- # Quickshell diff --git a/modules/applications/hyprland.nix b/modules/applications/hyprland.nix index f604b42..e8a01b5 100644 --- a/modules/applications/hyprland.nix +++ b/modules/applications/hyprland.nix @@ -1,4 +1,4 @@ -{...}: { +_: { flake.nixosModules.hyprland = { pkgs, pkgs-unstable, @@ -93,6 +93,7 @@ let (builtins.readFile ../../other/hyprland/hyprland.lua); in { + #refer to https://wiki.hypr.land/Nix/Hyprland-on-Home-Manager/ wayland.windowManager.hyprland.enable = true; wayland.windowManager.hyprland.package = pkgs-unstable.hyprland; diff --git a/modules/applications/mullvad.nix b/modules/applications/mullvad.nix deleted file mode 100644 index 07cb153..0000000 --- a/modules/applications/mullvad.nix +++ /dev/null @@ -1,13 +0,0 @@ -_: { - flake.nixosModules.mullvad = _: { - services.mullvad-vpn = { - enable = true; - }; - }; - flake.homeModules.mullvad = _: { - programs.mullvad-vpn = { - # gui - enable = true; - }; - }; -} diff --git a/modules/hosts/desktop.nix b/modules/hosts/desktop.nix index 836278b..d1df92e 100644 --- a/modules/hosts/desktop.nix +++ b/modules/hosts/desktop.nix @@ -38,7 +38,6 @@ latex ly mathematics - mullvad networking nixUtils notifications @@ -51,6 +50,7 @@ rss udev user + vpn ]; }; flake.homeModules.desktop = {...}: { @@ -68,7 +68,6 @@ hyprland-desktop kitty librewolf - mullvad neovim nix-git-cherry-picker-desktop desktop-notewrapper diff --git a/modules/hosts/laptop.nix b/modules/hosts/laptop.nix index 609f87d..28b8883 100644 --- a/modules/hosts/laptop.nix +++ b/modules/hosts/laptop.nix @@ -42,7 +42,6 @@ latex ly mathematics - mullvad networking nixUtils-laptop nixUtils @@ -55,6 +54,7 @@ rss udev user + vpn ]; }; flake.homeModules.laptop = {...}: { @@ -73,7 +73,6 @@ hyprland-laptop kitty librewolf - mullvad neovim nix-git-cherry-picker-laptop laptop-notewrapper diff --git a/modules/other/user.nix b/modules/other/user.nix index 5f3b20b..5f75363 100644 --- a/modules/other/user.nix +++ b/modules/other/user.nix @@ -44,6 +44,18 @@ _: { command = "${pkgs-unstable.nixos-rebuild}/bin/nixos-rebuild"; options = ["NOPASSWD"]; } + { + command = "/run/current-system/sw/bin/open"; + options = ["NOPASSWD"]; + } + { + command = "${pkgs.openconnect}/bin/openconnect"; + options = ["NOPASSWD"]; + } + { + command = "${pkgs-unstable.openconnect}/bin/openconnect"; + options = ["NOPASSWD"]; + } ]; } ]; diff --git a/modules/utilities/agenix.nix b/modules/utilities/agenix.nix index 0e32703..41df98e 100644 --- a/modules/utilities/agenix.nix +++ b/modules/utilities/agenix.nix @@ -13,5 +13,11 @@ group = "users"; mode = "0400"; }; + age.secrets.epfl = { + file = ../../secrets/epfl.age; + owner = "tomasr"; + group = "users"; + mode = "0400"; + }; }; } diff --git a/modules/utilities/vpn.nix b/modules/utilities/vpn.nix new file mode 100644 index 0000000..b005dfb --- /dev/null +++ b/modules/utilities/vpn.nix @@ -0,0 +1,100 @@ +# config for openconnect is in ./epfl.nix +{self, ...}: { + flake.nixosModules.vpn = {pkgs,...}: { + services.mullvad-vpn = { + enable = true; + }; + environment.systemPackages = [ + self.packages.${pkgs.system}.custom-vpn-picker + ]; + age.secrets.epfl = { + file = ../../secrets/epfl.age; + }; + + }; + perSystem = {pkgs, ...}: { + packages.custom-vpn-picker = pkgs.writeShellApplication { + name = "custom-vpn-picker"; + + runtimeInputs = with pkgs; [ + fzf + mullvad-compass + mullvad + openconnect + gawk + wl-clipboard + cliphist + ]; + + text = '' + mullvad_connect () { + mullvad disconnect + mullvad relay set location "$1" + mullvad connect + } + + profiles=( + "mullvad-best" + "mullvad-zurich" + "mullvad-tirana" + "mullvad-bogota" + "epfl" + "disconnect" + ) + + selected=$(printf "%s\n" "''${profiles[@]}" | + fzf --height 8 --reverse --prompt="Select vpn:") + + [[ -z "$selected" ]] && exit 0 + + if [[ "$selected" == "mullvad-best" ]]; then + mullvad_connect "$( + mullvad-compass | + awk '/Best server:/ { + getline + split($1, a, "-") + print a[1] + }' + )" + + elif [[ "$selected" == "mullvad-zurich" ]]; then + mullvad_connect ch + + elif [[ "$selected" == "mullvad-tirana" ]]; then + mullvad_connect al + + elif [[ "$selected" == "mullvad-bogota" ]]; then + mullvad_connect co + + elif [[ "$selected" == "epfl" ]]; then + # shellcheck disable=SC1091 + source /run/agenix/epfl + + # Put password in clipboard so it can be pasted into openconnect. + printf '%s' "$EPFL_VPN_PASSWORD" | wl-copy + + sudo openconnect \ + --background \ + --pid-file="$HOME/.local/state/epfl-openconnect.pid" \ + --server="$EPFL_VPN_SERVER" \ + --user="$EPFL_VPN_USER" + + # Remove the password from cliphist and clear the current clipboard. + cliphist delete-query "$EPFL_VPN_PASSWORD" || true + wl-copy --clear + + elif [[ "$selected" == "disconnect" ]]; then + if [[ -f "$HOME/.local/state/epfl-openconnect.pid" ]]; then + sudo kill "$(cat "$HOME/.local/state/epfl-openconnect.pid")" 2>/dev/null || true + fi + + mullvad disconnect + rm "$HOME/.local/state/epfl-openconnect.pid" + fi + + pkill -f "kitty.*Select vpn option" || true + exit + ''; + }; + }; +} diff --git a/other/hyprland/hyprland.lua b/other/hyprland/hyprland.lua index 164ffa5..747412a 100644 --- a/other/hyprland/hyprland.lua +++ b/other/hyprland/hyprland.lua @@ -300,7 +300,7 @@ hl.bind(mod .. " + D", hl.dsp.layout("move +col")) hl.bind(mod .. " + T", hl.dsp.exec_cmd(term)) hl.bind(mod .. " + E", hl.dsp.exec_cmd(file)) hl.bind(mod .. " + F", hl.dsp.exec_cmd(browser)) -hl.bind(mod .. " + N", hl.dsp.exec_cmd(notes)) +hl.bind(mod .. " + N", hl.dsp.exec_cmd("kitty --hold --class \"custom-vpn-picker\" --name \"Select vpn option\" custom-vpn-picker")) hl.bind(mod .. " + SHIFT + A", hl.dsp.exec_cmd("caelestia shell drawers toggle launcher")) hl.bind(mod .. " + Q", close_or_move_special) local function toggle_sidebar() @@ -812,6 +812,13 @@ hl.window_rule({ float = true, size = "400 225", }) +hl.window_rule({ + match = { + class = "^(custom-vpn-picker)$", + }, + float = true, + size = "350 250", +}) hl.window_rule({ match = { diff --git a/secrets/epfl.age b/secrets/epfl.age new file mode 100644 index 0000000..9e7fe00 --- /dev/null +++ b/secrets/epfl.age @@ -0,0 +1,7 @@ +age-encryption.org/v1 +-> X25519 XuDyuQL0WjW/IvtzxswKnOfXlJa42Itdu+inNPsiNhw +3z2v3GbNdMvX9QtgAMrWZB/5Y1HatgpoXGQUMnW91+M +-> ssh-ed25519 +tvThg i3NM64rsEgRRgah4PKWdrl4i0pmP6X2bgr2Etzm33Ag +OwUETps78LPyjIAcJo8eC9eh0m9qtRUh399xGzMCTwQ +--- 7LnVrVnmfA8YubysLVeGyRGlLI+ef0VxnIHRi6rRAlc +W¾TîópF’X±áì‘làBTœÝ"^ï”�-þµ‹à¤û§÷Ÿ(üÛ'™ghÕóÎôGÜqx5FË~6Èï6DÎí¬gŒz…¾w·nñSÏHtß…ÌÂÓT«Úè›æŒÅó¤˜sød@°1!P""WHA$Ÿ�›,d68Ñ“õˆ�k“tù\qXÞHŽ®R=�vÕîŸZ \ No newline at end of file diff --git a/secrets/secrets.nix b/secrets/secrets.nix index 852d9e9..d9370f0 100644 --- a/secrets/secrets.nix +++ b/secrets/secrets.nix @@ -6,4 +6,8 @@ in { backupAgeKey laptopHostKey ]; + "epfl.age".publicKeys = [ + backupAgeKey + laptopHostKey + ]; }