DEV Community

Cover image for Changing a hostname in Debian seems harder than necessary
Paul Cochrane 🇪🇺
Paul Cochrane 🇪🇺

Posted on • Originally published at peateasea.de on

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.

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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!

  1. … and probably Linux in general, but I didn’t check.

  2. The reason sudo looks up the host’s name is that /etc/sudoers is designed to be distributed across multiple servers. Hence, sudo needs to know which host it’s on to apply any host-specific rules.

  3. Although, to be honest, the ansible.builtin.hostname module docs do mention that the module doesn’t update /etc/hosts and that one has to do this it oneself. Perhaps I haven’t done this in a while and have forgotten the full story.

  4. I have a suspicion that my woes could be solved by using privileged: true and removing sudo from the script. However, I realised this after having written everything up, and yet still found my explanation useful.

  5. Of course, one could extract the script code into a file and run that via sudo. But where’s the fun in that?

  6. 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.

Top comments (0)