Created
February 10, 2026 18:06
-
-
Save klutchell/1649e2b95ca703c4348ffc184ad3ceac to your computer and use it in GitHub Desktop.
Generate NetworkManager .nmconnection keyfile for Leaseweb dedicated servers (queries Leaseweb API, outputs to stdout)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env bash | |
| # Generate a NetworkManager .nmconnection keyfile for a Leaseweb dedicated server. | |
| # Queries the Leaseweb API for network details and writes keyfile to stdout. | |
| # | |
| # Usage: LSW_API_KEY=xxx ./leaseweb-nmconnection.sh <server-id> | |
| # | |
| # Dependencies: curl, jq | |
| # Output: .nmconnection keyfile on stdout; progress/errors on stderr | |
| set -euo pipefail | |
| die() { echo "error: $*" >&2; exit 1; } | |
| log() { echo ":: $*" >&2; } | |
| # -- deps -- | |
| for cmd in curl jq; do | |
| command -v "$cmd" >/dev/null 2>&1 || die "$cmd not found (apt-get install -y $cmd)" | |
| done | |
| # -- inputs -- | |
| [[ ${1:-} ]] || die "usage: $0 <server-id>" | |
| SERVER_ID="$1" | |
| : "${LSW_API_KEY:?set LSW_API_KEY}" | |
| LSW_API="https://api.leaseweb.com/bareMetals/v2/servers" | |
| lsw_get() { | |
| local url="$1" | |
| log "GET $url" | |
| curl -sf -H "X-Lsw-Auth: ${LSW_API_KEY}" "$url" | |
| } | |
| # -- fetch server info -- | |
| server_json=$(lsw_get "${LSW_API}/${SERVER_ID}") | |
| server_mac=$(jq -r '.networkInterfaces.public.mac // empty' <<<"$server_json") | |
| # fall back to MAC of the default route interface on this host | |
| if [[ -z $server_mac ]]; then | |
| default_iface=$(ip route show default 2>/dev/null | awk '{print $5; exit}') | |
| if [[ -n ${default_iface:-} ]]; then | |
| server_mac=$(ip link show "$default_iface" 2>/dev/null | awk '/ether/ {print $2; exit}') | |
| log "mac from local interface ${default_iface}=${server_mac}" | |
| fi | |
| fi | |
| log "mac=${server_mac:-none}" | |
| # -- fetch IPs -- | |
| ips_json=$(lsw_get "${LSW_API}/${SERVER_ID}/ips") | |
| # primary IPv4: mainIp=true, version=4, networkType=PUBLIC | |
| ipv4_entry=$(jq -r '[.ips[] | select(.version==4 and .mainIp==true and .networkType=="PUBLIC")] | first' <<<"$ips_json") | |
| [[ $ipv4_entry != "null" ]] || die "no primary public IPv4 found" | |
| ipv4_cidr=$(jq -r '.ip' <<<"$ipv4_entry") | |
| ipv4_gw=$(jq -r '.gateway' <<<"$ipv4_entry") | |
| ipv4_addr="${ipv4_cidr%/*}" | |
| ipv4_mask="${ipv4_cidr#*/}" | |
| log "ipv4=${ipv4_addr}/${ipv4_mask} gw=${ipv4_gw}" | |
| # IPv6: version=6, networkType=PUBLIC (may not exist) | |
| ipv6_entry=$(jq -r '[.ips[] | select(.version==6 and .networkType=="PUBLIC")] | first // empty' <<<"$ips_json") | |
| if [[ -n $ipv6_entry ]]; then | |
| ipv6_cidr=$(jq -r '.ip' <<<"$ipv6_entry") | |
| ipv6_gw=$(jq -r '.gateway' <<<"$ipv6_entry") | |
| # strip underscores that Leaseweb sometimes includes in IPv6 addresses | |
| ipv6_cidr="${ipv6_cidr//_/}" | |
| ipv6_gw="${ipv6_gw//_/}" | |
| ipv6_addr="${ipv6_cidr%/*}" | |
| ipv6_mask="${ipv6_cidr#*/}" | |
| log "ipv6=${ipv6_addr}/${ipv6_mask} gw=${ipv6_gw}" | |
| else | |
| log "warning: no IPv6 address found — request one via the Leaseweb dashboard" | |
| fi | |
| # -- generate keyfile -- | |
| log "generating keyfile" | |
| cat <<EOF | |
| [connection] | |
| id=static | |
| type=ethernet | |
| autoconnect-priority=1 | |
| [ipv4] | |
| method=manual | |
| address1=${ipv4_addr}/${ipv4_mask},${ipv4_gw} | |
| dns=1.1.1.1;1.0.0.1; | |
| EOF | |
| if [[ -n ${ipv6_entry:-} ]]; then | |
| cat <<EOF | |
| [ipv6] | |
| method=manual | |
| address1=${ipv6_addr}/${ipv6_mask},${ipv6_gw} | |
| dns=2606:4700:4700::1111;2606:4700:4700::1001; | |
| EOF | |
| else | |
| cat <<EOF | |
| [ipv6] | |
| method=disabled | |
| EOF | |
| fi | |
| if [[ -n ${server_mac:-} ]]; then | |
| cat <<EOF | |
| [ethernet] | |
| mac-address=${server_mac} | |
| EOF | |
| else | |
| cat <<EOF | |
| [ethernet] | |
| EOF | |
| fi | |
| log "done" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment