From 2ef00e2d5266887d9db59394d5028332622b3c7e Mon Sep 17 00:00:00 2001 From: Jared Dunbar Date: Sun, 4 Jan 2026 11:28:29 -0500 Subject: [PATCH] nixos/virtualization/ec2: Adds IPv6 IMDS fetch capability Updates the EC2 IMDS metadata fetcher script to support IPv6 endpoints. If you start an instance in an IPv6 subnet, if the EC2 instance gets an IPv6 address before the IPv4 address (extremely common), systemd will trigger the IMDS fetcher script and fail to fetch your NixOS configuration, leaving you with a useless unconfigured EC2 instance. This at least allows the NixOS configuration to be fetched and applied. --- .../virtualisation/ec2-metadata-fetcher.sh | 37 +++++++++++++++---- 1 file changed, 29 insertions(+), 8 deletions(-) diff --git a/nixos/modules/virtualisation/ec2-metadata-fetcher.sh b/nixos/modules/virtualisation/ec2-metadata-fetcher.sh index 7a8232d14865..5b4cdb44386a 100644 --- a/nixos/modules/virtualisation/ec2-metadata-fetcher.sh +++ b/nixos/modules/virtualisation/ec2-metadata-fetcher.sh @@ -3,7 +3,12 @@ mkdir -p "$metaDir" chmod 0755 "$metaDir" rm -f "$metaDir/*" +IMDS_ENDPOINTS="http://169.254.169.254 http://[fd00:ec2::254]" +IMDS_BASE_URL="http://169.254.169.254" +IMDS_TOKEN="" + get_imds_token() { + endpoint=$1 # retry-delay of 1 selected to give the system a second to get going, # but not add a lot to the bootup time curl \ @@ -15,10 +20,11 @@ get_imds_token() { -X PUT \ --connect-timeout 1 \ -H "X-aws-ec2-metadata-token-ttl-seconds: 600" \ - http://169.254.169.254/latest/api/token + "$endpoint/latest/api/token" } preflight_imds_token() { + endpoint=$1 # retry-delay of 1 selected to give the system a second to get going, # but not add a lot to the bootup time curl \ @@ -30,13 +36,18 @@ preflight_imds_token() { --connect-timeout 1 \ -H "X-aws-ec2-metadata-token: $IMDS_TOKEN" \ -o /dev/null \ - http://169.254.169.254/1.0/meta-data/instance-id + "$endpoint/1.0/meta-data/instance-id" } try=1 while [ $try -le 3 ]; do echo "(attempt $try/3) getting an EC2 instance metadata service v2 token..." - IMDS_TOKEN=$(get_imds_token) && break + for endpoint in $IMDS_ENDPOINTS; do + IMDS_TOKEN=$(get_imds_token "$endpoint") && IMDS_BASE_URL=$endpoint && break + done + if [ -n "$IMDS_TOKEN" ]; then + break + fi try=$((try + 1)) sleep 1 done @@ -48,7 +59,17 @@ fi try=1 while [ $try -le 10 ]; do echo "(attempt $try/10) validating the EC2 instance metadata service v2 token..." - preflight_imds_token && break + preflight_ok="" + for endpoint in $IMDS_ENDPOINTS; do + if preflight_imds_token "$endpoint"; then + IMDS_BASE_URL=$endpoint + preflight_ok=1 + break + fi + done + if [ -n "$preflight_ok" ]; then + break + fi try=$((try + 1)) sleep 1 done @@ -85,7 +106,7 @@ try_decompress() { fi } -get_imds -o "$metaDir/ami-manifest-path" http://169.254.169.254/1.0/meta-data/ami-manifest-path -(umask 077 && get_imds -o "$metaDir/user-data" http://169.254.169.254/1.0/user-data && try_decompress "$metaDir/user-data") -get_imds -o "$metaDir/hostname" http://169.254.169.254/1.0/meta-data/hostname -get_imds -o "$metaDir/public-keys-0-openssh-key" http://169.254.169.254/1.0/meta-data/public-keys/0/openssh-key +get_imds -o "$metaDir/ami-manifest-path" "$IMDS_BASE_URL/1.0/meta-data/ami-manifest-path" +(umask 077 && get_imds -o "$metaDir/user-data" "$IMDS_BASE_URL/1.0/user-data" && try_decompress "$metaDir/user-data") +get_imds -o "$metaDir/hostname" "$IMDS_BASE_URL/1.0/meta-data/hostname" +get_imds -o "$metaDir/public-keys-0-openssh-key" "$IMDS_BASE_URL/1.0/meta-data/public-keys/0/openssh-key"