From b6af89de85521aac6d79545f0f68d195183381e3 Mon Sep 17 00:00:00 2001 From: TriTacLe Date: Sun, 25 Oct 2026 21:52:21 +0200 Subject: [PATCH] Set the timezone from the public IP on NetworkManager connect --- .../NetworkManager/dispatcher.d/90-timezone | 58 +++++++++++++++++++ arch/install-arch.sh | 5 ++ 2 files changed, 63 insertions(+) create mode 100755 arch/etc/NetworkManager/dispatcher.d/90-timezone diff --git a/arch/etc/NetworkManager/dispatcher.d/90-timezone b/arch/etc/NetworkManager/dispatcher.d/90-timezone new file mode 100755 index 0000000..f809bef --- /dev/null +++ b/arch/etc/NetworkManager/dispatcher.d/90-timezone @@ -0,0 +1,58 @@ +#!/bin/sh +set -eu + +PATH=/usr/bin:/bin + +IFACE="${1:-}" +ACTION="${2:-}" + +case "$ACTION" in + up|connectivity-change) ;; + *) exit 0 ;; +esac + +if [ "$IFACE" = "lo" ]; then + exit 0 +fi + +STAMP=/var/lib/nm-timezone/last-attempt +MIN_INTERVAL=600 + +# Rate limit on attempts, not successes, so a flapping link cannot hammer the API. +if [ -f "$STAMP" ]; then + age=$(( $(date +%s) - $(stat -c %Y "$STAMP") )) + if [ "$age" -lt "$MIN_INTERVAL" ]; then + exit 0 + fi +fi +mkdir -p "$(dirname "$STAMP")" +: > "$STAMP" + +lookup() { + curl -fsS --max-time 5 "$1" 2>/dev/null | tr -d '[:space:]' +} + +tz=$(lookup https://ipapi.co/timezone) || tz="" +if [ -z "$tz" ]; then + tz=$(lookup https://ipinfo.io/timezone) || tz="" +fi + +# Reject anything that is not a bare Region/City before it reaches the filesystem. +case "$tz" in + */*) ;; + *) exit 0 ;; +esac +case "$tz" in + *[!A-Za-z0-9/_+-]* | /* | */ | */../*) exit 0 ;; +esac +if [ ! -f "/usr/share/zoneinfo/$tz" ]; then + exit 0 +fi + +current=$(timedatectl show -p Timezone --value) +if [ "$tz" = "$current" ]; then + exit 0 +fi + +timedatectl set-timezone "$tz" +logger -t nm-timezone "timezone $current -> $tz" diff --git a/arch/install-arch.sh b/arch/install-arch.sh index 917edc1..c6204e7 100755 --- a/arch/install-arch.sh +++ b/arch/install-arch.sh @@ -54,6 +54,11 @@ install_system_configs() { "$DOTFILES/arch/etc/udev/rules.d/90-backlight-on-power.rules" \ /etc/udev/rules.d/90-backlight-on-power.rules sudo udevadm control --reload-rules + # Follows the laptop across continents: resolves the public IP to a timezone + # on every NetworkManager connect and sets it only when it differs. + sudo install -D -m 0755 -o root -g root \ + "$DOTFILES/arch/etc/NetworkManager/dispatcher.d/90-timezone" \ + /etc/NetworkManager/dispatcher.d/90-timezone sudo install -D -m 0644 -o root -g root \ "$DOTFILES/arch/etc/tmpfiles.d/mglru.conf" \ /etc/tmpfiles.d/mglru.conf