From 534f8199f31ac3f21fdc07f3287b52cdd910e9b6 Mon Sep 17 00:00:00 2001 From: fwastring Date: Sun, 29 Mar 2026 14:30:22 +0200 Subject: [PATCH] Added networking scripts for waybar --- moduler/programs/waybar/default.nix | 423 +++++++++++++++++++- moduler/programs/waybar/waybar-laptop.jsonc | 34 +- moduler/programs/waybar/waybar-mocha.css | 34 +- moduler/programs/waybar/waybar.jsonc | 32 ++ 4 files changed, 510 insertions(+), 13 deletions(-) diff --git a/moduler/programs/waybar/default.nix b/moduler/programs/waybar/default.nix index b986a7c..397ccb5 100644 --- a/moduler/programs/waybar/default.nix +++ b/moduler/programs/waybar/default.nix @@ -1,5 +1,5 @@ { - lib, + lib, config, inputs, pkgs, @@ -27,16 +27,417 @@ with lib; }; }; config = mkIf config.waybar.enable { - programs = { - waybar = { - enable = true; - systemd = { - enable = true; - }; - }; - }; - xdg.configFile."waybar/config.jsonc".source = config.waybar.configPath; - xdg.configFile."waybar/style.css".source = config.waybar.stylePath; + programs = { + waybar = { + enable = true; + systemd = { + enable = true; + }; + }; + }; + xdg.configFile."waybar/config.jsonc".source = config.waybar.configPath; + xdg.configFile."waybar/style.css".source = config.waybar.stylePath; + xdg.configFile."waybar/scripts/tailscale.sh" = { + text = '' + #!${pkgs.bash}/bin/bash + + PATH=${ + lib.makeBinPath [ + pkgs.coreutils + pkgs.jq + pkgs.tailscale + ] + } + + STATE_FILE="/tmp/waybar_tailscale_state" + CONNECTING_DURATION=2 # seconds to show transition states + + get_tailscale_status() { + local status_json + if status_json=$(tailscale status --json 2>/dev/null); then + local backend_state=$(echo "$status_json" | jq -r '.BackendState // "NoState"') + case "$backend_state" in + "Running") + echo "connected" + ;; + "Stopped"|"NoState"|"NeedsLogin") + echo "stopped" + ;; + *) + echo "stopped" + ;; + esac + else + echo "stopped" + fi + } + + get_tooltip() { + local status_json + if ! status_json=$(tailscale status --json 2>/dev/null); then + echo "" + return + fi + + local backend_state=$(echo "$status_json" | jq -r '.BackendState // "NoState"') + if [[ "$backend_state" != "Running" ]]; then + echo "" + return + fi + + local hostname=$(echo "$status_json" | jq -r '.Self.HostName // "Unknown"') + + local tooltip="Hostname: $hostname\n" + + tooltip+="\nPeers:\n" + + local peers=$(echo "$status_json" | jq -r '.Peer // {} | to_entries[] | "\(.value.HostName):\(.value.Online)"' | sort) + + if [[ -n "$peers" ]]; then + while IFS=: read -r peer_name peer_online; do + if [[ "$peer_online" == "true" ]]; then + tooltip+="\n $peer_name" + else + tooltip+="\n $peer_name" + fi + done <<< "$peers" + else + tooltip+="\nNo peers" + fi + + echo "$tooltip" + } + + show_status() { + local status=$(get_tailscale_status) + local text="" + local alt="" + local tooltip="" + + case $status in + "connected") + text="" + alt="connected" + tooltip=$(get_tooltip) + ;; + "stopped") + text="" + alt="stopped" + tooltip="Tailscale is turned off" + ;; + esac + + if [[ -n "$tooltip" ]]; then + echo "{\"text\":\"$text\",\"class\":\"$status\",\"alt\":\"$alt\",\"tooltip\":\"$tooltip\"}" + else + echo "{\"text\":\"$text\",\"class\":\"$status\",\"alt\":\"$alt\"}" + fi + } + + show_connecting() { + echo "{\"text\":\"\",\"class\":\"connecting\",\"alt\":\"connecting\",\"tooltip\":\"Connecting...\"}" + } + + show_disconnecting() { + echo "{\"text\":\"\",\"class\":\"disconnecting\",\"alt\":\"disconnecting\",\"tooltip\":\"Disconnecting...\"}" + } + + is_in_transition() { + if [[ -f "$STATE_FILE" ]]; then + local state_info=$(cat "$STATE_FILE") + local state_time=$(echo "$state_info" | cut -d: -f1) + local current_time=$(date +%s) + + if (( current_time - state_time < CONNECTING_DURATION )); then + return 0 + else + rm -f "$STATE_FILE" + return 1 + fi + fi + return 1 + } + + case "$1" in + --status) + if is_in_transition; then + state_info=$(cat "$STATE_FILE") + state_action=$(echo "$state_info" | cut -d: -f2) + + if [[ "$state_action" == "connecting" ]]; then + show_connecting + exit 0 + elif [[ "$state_action" == "disconnecting" ]]; then + show_disconnecting + exit 0 + fi + fi + + show_status + ;; + --toggle) + if is_in_transition; then + state_info=$(cat "$STATE_FILE") + state_action=$(echo "$state_info" | cut -d: -f2) + + if [[ "$state_action" == "connecting" ]]; then + show_connecting + elif [[ "$state_action" == "disconnecting" ]]; then + show_disconnecting + fi + exit 0 + fi + + current_status=$(get_tailscale_status) + if [[ "$current_status" == "connected" ]]; then + tailscale down + show_status + else + echo "$(date +%s):connecting" > "$STATE_FILE" + tailscale up + show_connecting + fi + ;; + *) + echo "Usage: $0 {--status|--toggle}" + exit 1 + ;; + esac + ''; + executable = true; + }; + xdg.configFile."waybar/scripts/netbird.sh" = { + text = '' + #!${pkgs.bash}/bin/bash + + PATH=${ + lib.makeBinPath [ + pkgs.coreutils + pkgs.netbird + ] + } + + STATE_FILE="/tmp/waybar_netbird_state" + CONNECTING_DURATION=2 # seconds to show transition states + + get_netbird_status() { + local status_output + local management_status="" + + if ! status_output=$(netbird status -d 2>/dev/null); then + echo "stopped" + return + fi + + while IFS= read -r line; do + case "$line" in + "Management:"*) + management_status="''${line#Management: }" + ;; + esac + done <<< "$status_output" + + case "$management_status" in + *Connected*) + echo "connected" + ;; + *) + echo "stopped" + ;; + esac + } + + get_tooltip() { + local status_output + local management_status="" + local signal_status="" + local relays_available=0 + local relays_total=0 + local nameservers_available=0 + local nameservers_total=0 + local netbird_ip="" + local peers_count="" + local interface_type="" + local section="" + + if ! status_output=$(netbird status -d 2>/dev/null); then + echo "" + return + fi + + while IFS= read -r line; do + case "$line" in + "Management:"*) + management_status="''${line#Management: }" + section="" + ;; + "Signal:"*) + signal_status="''${line#Signal: }" + section="" + ;; + "Relays:"*) + section="relays" + ;; + "Nameservers:"*) + section="nameservers" + ;; + "NetBird IP:"*) + netbird_ip="''${line#NetBird IP: }" + section="" + ;; + "Interface type:"*) + interface_type="''${line#Interface type: }" + section="" + ;; + "Peers count:"*) + peers_count="''${line#Peers count: }" + section="" + ;; + "Peers detail:"*) + section="" + ;; + " ["*) + if [[ "$section" == "relays" ]]; then + relays_total=$((relays_total + 1)) + if [[ "$line" == *"Available"* ]]; then + relays_available=$((relays_available + 1)) + fi + elif [[ "$section" == "nameservers" ]]; then + nameservers_total=$((nameservers_total + 1)) + if [[ "$line" == *"Available"* ]]; then + nameservers_available=$((nameservers_available + 1)) + fi + fi + ;; + esac + done <<< "$status_output" + + if [[ -z "$management_status" ]]; then + echo "" + return + fi + + local tooltip="Management: $management_status" + if [[ -n "$signal_status" ]]; then + tooltip+="\nSignal: $signal_status" + fi + if (( relays_total > 0 )); then + tooltip+="\nRelays: $relays_available/$relays_total Available" + fi + if (( nameservers_total > 0 )); then + tooltip+="\nNameservers: $nameservers_available/$nameservers_total Available" + fi + if [[ -n "$netbird_ip" ]]; then + tooltip+="\nNetBird IP: $netbird_ip" + fi + if [[ -n "$interface_type" ]]; then + tooltip+="\nInterface: $interface_type" + fi + if [[ -n "$peers_count" ]]; then + tooltip+="\nPeers: $peers_count" + fi + + echo "$tooltip" + } + + show_status() { + local status=$(get_netbird_status) + local text="" + local alt="" + local tooltip="" + + case $status in + "connected") + text="" + alt="connected" + tooltip=$(get_tooltip) + ;; + "stopped") + text="" + alt="stopped" + tooltip="NetBird is turned off" + ;; + esac + + if [[ -n "$tooltip" ]]; then + echo "{\"text\":\"$text\",\"class\":\"$status\",\"alt\":\"$alt\",\"tooltip\":\"$tooltip\"}" + else + echo "{\"text\":\"$text\",\"class\":\"$status\",\"alt\":\"$alt\"}" + fi + } + + show_connecting() { + echo "{\"text\":\"\",\"class\":\"connecting\",\"alt\":\"connecting\",\"tooltip\":\"Connecting...\"}" + } + + show_disconnecting() { + echo "{\"text\":\"\",\"class\":\"disconnecting\",\"alt\":\"disconnecting\",\"tooltip\":\"Disconnecting...\"}" + } + + is_in_transition() { + if [[ -f "$STATE_FILE" ]]; then + local state_info=$(cat "$STATE_FILE") + local state_time=$(echo "$state_info" | cut -d: -f1) + local current_time=$(date +%s) + + if (( current_time - state_time < CONNECTING_DURATION )); then + return 0 + else + rm -f "$STATE_FILE" + return 1 + fi + fi + return 1 + } + + case "$1" in + --status) + if is_in_transition; then + state_info=$(cat "$STATE_FILE") + state_action=$(echo "$state_info" | cut -d: -f2) + + if [[ "$state_action" == "connecting" ]]; then + show_connecting + exit 0 + elif [[ "$state_action" == "disconnecting" ]]; then + show_disconnecting + exit 0 + fi + fi + + show_status + ;; + --toggle) + if is_in_transition; then + state_info=$(cat "$STATE_FILE") + state_action=$(echo "$state_info" | cut -d: -f2) + + if [[ "$state_action" == "connecting" ]]; then + show_connecting + elif [[ "$state_action" == "disconnecting" ]]; then + show_disconnecting + fi + exit 0 + fi + + current_status=$(get_netbird_status) + if [[ "$current_status" == "connected" ]]; then + netbird down + show_status + else + echo "$(date +%s):connecting" > "$STATE_FILE" + netbird up + show_connecting + fi + ;; + *) + echo "Usage: $0 {--status|--toggle}" + exit 1 + ;; + esac + ''; + executable = true; + }; }; # catppuccin.waybar = { # enable = true; diff --git a/moduler/programs/waybar/waybar-laptop.jsonc b/moduler/programs/waybar/waybar-laptop.jsonc index bcea439..f47b3f9 100644 --- a/moduler/programs/waybar/waybar-laptop.jsonc +++ b/moduler/programs/waybar/waybar-laptop.jsonc @@ -13,6 +13,8 @@ "bluetooth", "pulseaudio", "upower", + "custom/tailscale", + "custom/netbird", "network", "clock" ], @@ -44,7 +46,7 @@ "on-click": "pgrep .blueman-manage && pkill .blueman-manage || blueman-manager &" }, "network": { - "interface": "wlp1s0", + "interface": "wlp0s20f3", "format": "{ifname}", "format-wifi": " {essid} ({signalStrength}%)", "format-ethernet": "{ifname} ", @@ -86,5 +88,35 @@ "tooltip": true, "tooltip-format": "{:%A, %d %B %Y}\n %H:%M:%S", "interval": 1 + }, + "custom/tailscale": { + "exec": "/home/fw/.config/waybar/scripts/tailscale.sh --status", + "on-click": "/home/fw/.config/waybar/scripts/tailscale.sh --toggle", + "exec-on-event": true, + "format": "{icon} {text}", + "format-icons": { + "connected": "", + "stopped": "", + "connecting": "", + "disconnecting": "" + }, + "tooltip": true, + "return-type": "json", + "interval": 5 + }, + "custom/netbird": { + "exec": "/home/fw/.config/waybar/scripts/netbird.sh --status", + "on-click": "/home/fw/.config/waybar/scripts/netbird.sh --toggle", + "exec-on-event": true, + "format": "{icon} {text}", + "format-icons": { + "connected": "", + "stopped": "", + "connecting": "", + "disconnecting": "" + }, + "tooltip": true, + "return-type": "json", + "interval": 5 } } diff --git a/moduler/programs/waybar/waybar-mocha.css b/moduler/programs/waybar/waybar-mocha.css index 71edc44..c54b43c 100644 --- a/moduler/programs/waybar/waybar-mocha.css +++ b/moduler/programs/waybar/waybar-mocha.css @@ -19,6 +19,22 @@ font-size: 15px; } +.connecting { + animation: pulse 0.8s ease-in-out infinite; +} + +@keyframes pulse { + 0% { + opacity: 1; + } + 50% { + opacity: 0.5; + } + 100% { + opacity: 1; + } +} + window#waybar { /* background: @base; */ background: transparent; @@ -32,7 +48,7 @@ window#waybar.termite { background: @base; } window#waybar.chromium { background: @base; border: none; } /* -------- Module “pill” look -------- */ -#workspaces, #clock, #mpris, #pulseaudio, #bluetooth, #upower, #network { +#workspaces, #clock, #mpris, #pulseaudio, #bluetooth, #upower, #network, #custom-tailscale, #custom-netbird { background: @base; border: none; border-radius: 5px; @@ -139,6 +155,22 @@ button:active { letter-spacing: 0.2px; } +/* -------- Upower -------- */ +#custom-tailscale { + background: @peach; + color: @base; + font-weight: 600; + letter-spacing: 0.2px; +} + +/* -------- Netbird -------- */ +#custom-netbird { + background: @peach; + color: @base; + font-weight: 600; + letter-spacing: 0.2px; +} + /* -------- Network -------- */ #network { background: @peach; diff --git a/moduler/programs/waybar/waybar.jsonc b/moduler/programs/waybar/waybar.jsonc index bb97f93..eca5509 100644 --- a/moduler/programs/waybar/waybar.jsonc +++ b/moduler/programs/waybar/waybar.jsonc @@ -12,6 +12,8 @@ "mpris", "pulseaudio", "bluetooth", + "custom/tailscale", + "custom/netbird", "network", "clock" ], @@ -80,5 +82,35 @@ "tooltip": true, "tooltip-format": "{:%A, %d %B %Y}\n %H:%M:%S", "interval": 1 + }, + "custom/tailscale": { + "exec": "/home/fw/.config/waybar/scripts/tailscale.sh --status", + "on-click": "/home/fw/.config/waybar/scripts/tailscale.sh --toggle", + "exec-on-event": true, + "format": "{icon} {text}", + "format-icons": { + "connected": "", + "stopped": "", + "connecting": "", + "disconnecting": "" + }, + "tooltip": true, + "return-type": "json", + "interval": 5 + }, + "custom/netbird": { + "exec": "/home/fw/.config/waybar/scripts/netbird.sh --status", + "on-click": "/home/fw/.config/waybar/scripts/netbird.sh --toggle", + "exec-on-event": true, + "format": "{icon} {text}", + "format-icons": { + "connected": "", + "stopped": "", + "connecting": "", + "disconnecting": "" + }, + "tooltip": true, + "return-type": "json", + "interval": 5 } }