Skip to content

Brev base image's first-boot script renames the host without updating /etc/hosts; sudo / hostname -f hang for ~10s on every call #399

Description

@robobryce

What

Brev's first-boot /opt/setup.sh renames the host to brev-${BREV_ENV_ID} but doesn't add a matching /etc/hosts entry. The default Ubuntu NSS order (hosts: files dns ... in /etc/nsswitch.conf, with resolv.conf symlinked to systemd-resolved's stub) then sends every gethostbyname() on the local hostname to upstream DNS, which has no record for it. The lookup times out at ~10s before LLMNR / mDNS finally answers with a link-local IPv6 address.

Anything that resolves the local hostname pays that ~10s on every invocation:

  • sudo (it does a hostname lookup to match Defaults and host rules in sudoers — so sudo true itself is enough).
  • hostname -f.
  • mail, sendmail, cron, anything that calls Sys::Hostname from Perl, etc.

The user-visible symptom is "every sudo command on a fresh Brev VM takes ten seconds before it does anything." First-time users tend to attribute it to the VM still being slow / first-boot still finishing; the actual cause survives a reboot and never goes away on its own.

Reproducer

On any fresh Brev workspace immediately after brev create:

$ time sudo true

real	0m10.021s
user	0m0.004s
sys	0m0.006s

$ time sudo -n true     # non-interactive — no password prompt, still 10s

real	0m10.020s
user	0m0.003s
sys	0m0.006s

$ hostname
brev-gen8x2a9s

$ grep \"\$(hostname)\" /etc/hosts || echo \"hostname not in /etc/hosts\"
hostname not in /etc/hosts

$ time getent hosts \$(hostname)
fdd1:eccf:8581:6581:2894:2e00:ff7c:bdf5 brev-gen8x2a9s
fd7a:115c:a1e0::9b3b:1064 brev-gen8x2a9s
fe80::4001:aff:fe8a:527 brev-gen8x2a9s
fe80::83fd:9880:6452:8b5d brev-gen8x2a9s

real	0m10.010s
user	0m0.002s
sys	0m0.001s

The getent hosts block confirms the chain: NSS asks files (no entry), falls through to dns via systemd-resolved (10s timeout), then the only answers come from LLMNR / mDNS as link-local IPv6 / Tailscale ULA addresses — none of which are useful, and arrive only after the 10s the user already paid.

/etc/hosts on a fresh box looks like this:

127.0.0.1 localhost

# The following lines are desirable for IPv6 capable hosts
::1 ip6-localhost ip6-loopback
fe00::0 ip6-localnet
ff00::0 ip6-mcastprefix
ff02::1 ip6-allnodes
ff02::2 ip6-allrouters
ff02::3 ip6-allhosts
169.254.169.254 metadata.google.internal metadata

— note the absence of any line mapping the actual machine hostname (brev-<env_id>).

Suggested fix

In whichever stage of /opt/setup.sh performs the hostnamectl set-hostname brev-${BREV_ENV_ID} (or equivalent), append the matching loopback line to /etc/hosts. The Debian / Ubuntu convention is 127.0.1.1, distinct from 127.0.0.1 localhost:

hostnamectl set-hostname \"brev-${BREV_ENV_ID}\"
if ! awk -v h=\"brev-${BREV_ENV_ID}\" '
    !/^[[:space:]]*#/ { for (i=2; i<=NF; i++) if (\$i==h) { found=1; exit } }
    END { exit !found }
' /etc/hosts; then
    printf '127.0.1.1\t%s\n' \"brev-${BREV_ENV_ID}\" >>/etc/hosts
fi

This mirrors what cloud-init's update_etc_hosts module and most distros' /etc/hostname/etc/hosts linkage do automatically when a hostname is set at install time. The Brev base image diverges by setting the hostname later (after first boot, in /opt/setup.sh), so the standard tooling never closes the loop.

Impact

Cumulatively significant for any automation that runs many sudo calls on a Brev VM (CI runners, bootstrap scripts, anything ssh'ing in and shelling out): each sudo invocation eats 10s before doing real work. Interactive users feel it as the whole shell being sluggish. The fix is one line in the first-boot script and is invisible to users who never noticed the slowdown.

Workaround

Append 127.0.1.1 \$(hostname) to /etc/hosts once after the workspace boots:

echo \"127.0.1.1 \$(hostname)\" | sudo tee -a /etc/hosts >/dev/null

sudo true drops from ~10s to <50ms immediately.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions