Changing a hostname in Debian seems harder than necessary
Changing a host’s name in Debian1 is a two-step
process, and there doesn’t appear to be a more direct method. This seems
odd to me, somehow. Because I stumbled upon this issue and a confusing
error while relying solely on sudo, I thought I’d write up how I worked
around it.

/etc/hosts hostname mismatch error.Image credits: Noto-Emoji project
It feels like I missed something obvious here. I mean, changing the hostname should be a one-liner, right? Perhaps someone knows of a better solution.
System setup stumbling-block
Ok, so here’s the situation: I wanted to create a new Vagrant VM and run some basic provisioning steps. Since the use case wasn’t very involved, I didn’t want to use something like Ansible: a simple set of bash commands was sufficient.
One step changes the hostname from the default to something more
descriptive. Sounds simple, right? Technically, it is simple. The thing
is, two steps are required, which I found strange. And if you’re using
sudo, you’ll likely be surprised by a name resolution error:
sudo: unable to resolve host <new-hostname>: Temporary failure in name resolution
What gives?
The name resolution failure appears because the new hostname doesn’t match
the entry in /etc/hosts. Thus, any sudo call thereafter is unable to
find the host it’s running on. The hostname lookup within sudo times out,
and we get the name resolution failure message I mentioned above.
I must admit, this tripped me up. I don’t remember having had this
stumbling block previously. I ended up wondering how I’d done this before.
Wasn’t this a single command in the past? And what’s with name resolution
being needed as part of sudo?2 Once upon a time,
I’d have opened a root session and hence wouldn’t have run into this
problem, but those days are long over. I now almost exclusively use sudo
for admin tasks.
More recently, I use Ansible when provisioning new hosts, and hence haven’t spotted this issue.3 At least, not for a while. Maybe I’ve just forgotten? Dunno.
Anyhow, back to the story. The problem manifests itself if you run these commands:
# either use the "old" way to set a hostname
$ sudo hostname <new-hostname>
# ... or use the new-fangled, strangely repetitive way to set a hostname
$ sudo hostnamectl set-hostname <new-hostname>
# now open /etc/hosts to fix hostname entry in there
$ sudo vim /etc/hosts
# ... wait until the name resolution times out ...
# get the name resolution error message
sudo: unable to resolve host <new-hostname>: Temporary failure in name resolution
# now vim will open /etc/hosts
All online resources I looked at–such as
nixCraft,
which is usually a good source of info–recommend this two-step process.
And to do it within a root session.
But what if you don’t want to do that as root directly? What if you
want to script this and are restricted to using sudo? That’s the issue I
was trying to solve, and here’s my solution.
Wonky workflow workaround
The approach first adds the new hostname to /etc/hosts. That way, the
name is able to be resolved after changing the hostname. Then I change the
hostname in the usual way. Afterwards, I delete the old /etc/hosts entry
to remove unnecessary cruft.
Putting this all together as a shell script in a Vagrantfile provisioning
step, we get (by way of example):4
bookworm_new.vm.provision "shell", privileged: false, inline: <<-SHELL
sudo DEBIAN_FRONTEND=noninteractive apt update
sudo DEBIAN_FRONTEND=noninteractive apt -y upgrade
sudo DEBIAN_FRONTEND=noninteractive apt install -y vim
# add new hostname to /etc/hosts; keep old one for now
# avoids `sudo: unable to resolve host <hostname>: Temporary failure in name resolution`
# errors when running `sudo` after changing the hostname
sudo sed -i 's/bookworm/bookworm bookworm-new/g' /etc/hosts
sudo hostnamectl set-hostname bookworm-new
# remove the old hostname
sudo sed -i 's/bookworm //g' /etc/hosts
SHELL
The provisioning commands appear in a here
doc called
SHELL.5 The first few lines are standard update
commands I use when setting up a new VM. I find it’s a good idea to ensure
everything’s up to date before proceeding, even if the base image is recent.
You’ll note that I install vim as well. Basically, my muscle memory won’t
think of another editor, and this saves friction for me when modifying
config files or viewing logs.
The lines after that are the important ones for the hostname updating process:
# add new hostname; keep old one temporarily
# avoids `sudo: unable to resolve host <hostname>: Temporary failure in name resolution`
# errors when running `sudo` after changing the hostname
sudo sed -i 's/bookworm/bookworm bookworm-new/g' /etc/hosts
sudo hostnamectl set-hostname bookworm-new
# remove the old hostname
sudo sed -i 's/bookworm //g' /etc/hosts
The first non-comment line uses sed to edit /etc/hosts in-place (hence
the -i option). The example system used here is Debian
bookworm, hence the default
hostname is set to bookworm. I want to set the new hostname to be
(unimaginatively) bookworm-new, so the sed command replaces bookworm
with the text bookworm bookworm-new. Now the new hostname is available,
and the old hostname is still there, but with a space after it, which will
come in handy when removing that entry later.
Next, I use hostnamectl to set the hostname. The old-fashioned hostname
command still works, but hostnamectl seems to be what all the cool kids
use.
Now it’s just a matter of removing the old hostname from /etc/hosts. Here
I use sed with the -i option again, and replace the string 'bookworm '
(note the space after the name)6 with the empty string, thus
removing the old hostname from /etc/hosts.
Now the change is complete, and there aren’t any “Temporary failure in name
resolution” errors. Yay! ![]()
Wrapping up
For some reason, I still expect the hostname and /etc/hosts changes to be
coupled so that they occur as part of a single command. Oh well. Ya get
that, I guess.
Anyway, if you run across the Temporary failure in name resolution error
when running sudo in the future, now you know why and can work around it.
Enjoy!
-
… and probably Linux in general, but I didn’t check. ↩
-
The reason
sudolooks up the host’s name is that/etc/sudoersis designed to be distributed across multiple servers. Hence,sudoneeds to know which host it’s on to apply any host-specific rules. ↩ -
Although, to be honest, the
ansible.builtin.hostnamemodule docs do mention that the module doesn’t update/etc/hostsand that one has to do this it oneself. Perhaps I haven’t done this in a while and have forgotten the full story. ↩ -
I have a suspicion that my woes could be solved by using
privileged: trueand removingsudofrom the script. However, I realised this after having written everything up, and yet still found my explanation useful. ↩ -
Of course, one could extract the script code into a file and run that via
sudo. But where’s the fun in that? ↩ -
Yes, I could have used a better regex here, e.g. something like
bookworm\s\+, but then I’d need to use extended regular expressions and, well, this did the job. ↩
Support
If you liked this post, please buy me a coffee!