208

I've noticed that the "preferred" method of setting the system hostname is fundamentally different between Red Hat/CentOS and Debian/Ubuntu systems.

CentOS documentation and the RHEL deployment guide say the hostname should be the FQDN:

HOSTNAME=<value>, where <value> should be the Fully Qualified Domain Name (FQDN), such as hostname.example.com, but can be whatever hostname is necessary.

The RHEL install guide is slightly more ambiguous:

Setup prompts you to supply a host name for this computer, either as a fully-qualified domain name (FQDN) in the format hostname.domainname or as a short host name in the format hostname.

The Debian reference says the hostname should not use the FQDN:

3.5.5. The hostname

The kernel maintains the system hostname. The init script in runlevel S which is symlinked to "/etc/init.d/hostname.sh" sets the system hostname at boot time (using the hostname command) to the name stored in "/etc/hostname". This file should contain only the system hostname, not a fully qualified domain name.

I haven't seen any specific recommendations from IBM about which to use, but some software seems to have a preference.

My questions:

  • In a heterogeneous environment, is it better to use the vendor recommendation, or choose one and be consistent across all hosts?
  • What software have you encountered which is sensitive to whether the hostname is set to the FQDN or short name?
Cakemox
  • 24,141
  • 6
  • 41
  • 67

8 Answers8

123

I would choose a consistent approach across the entire environment. Both solutions work fine and will remain compatible with most applications. There is a difference in manageability, though.

I go with the short name as the HOSTNAME setting, and set the FQDN as the first column in /etc/hosts for the server's IP, followed by the short name.

I have not encountered many software packages that enforce or display a preference between the two. I find the short name to be cleaner for some applications, specifically logging. Maybe I've been unlucky in seeing internal domains like server.northside.chicago.rizzomanufacturing.com. Who wants to see that in the logs or a shell prompt?

Sometimes, I'm involved in company acquisitions or restructuring where internal domains and/or subdomains change. I like using the short hostname in these cases because logging, kickstarts, printing, systems monitoring, etc. do not need full reconfiguration to account for the new domain names.

A typical RHEL/CentOS server setup for a server named "rizzo" with internal domain "ifp.com", would look like:

/etc/sysconfig/network:
HOSTNAME=rizzo
...

-

/etc/hosts:
127.0.0.1   localhost localhost.localdomain localhost4 localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

172.16.100.13   rizzo.ifp.com rizzo

-

[root@rizzo ~]# hostname 
rizzo

-

/var/log/messages snippet:
Dec 15 10:10:13 rizzo proftpd[19675]: 172.16.100.13 (::ffff:206.15.236.182[::ffff:206.15.236.182]) - Preparing to               
 chroot to directory '/app/upload/GREEK'
Dec 15 10:10:51 rizzo proftpd[20660]: 172.16.100.13 (::ffff:12.28.170.2[::ffff:12.28.170.2]) - FTP session opened.
Dec 15 10:10:51 rizzo proftpd[20660]: 172.16.100.13 (::ffff:12.28.170.2[::ffff:12.28.170.2]) - Preparing to chroot                
to directory '/app/upload/ftp/SRRID'
kubanczyk
  • 13,502
  • 5
  • 40
  • 55
ewwhite
  • 194,921
  • 91
  • 434
  • 799
  • 11
    Like you, I prefer the short name, however I discovered recently that some Oracle applications require the output of `hostname` to be the FQDN. Just having it in `/etc/hosts` isn't good enough. That messed with my consistency. – James O'Gorman Dec 20 '11 at 18:36
  • 4
    The difference in capitalization of the hostnames in this example is surely not a best practice ref: http://tools.ietf.org/search/rfc1178 – teknopaul Feb 17 '14 at 14:22
  • 2
    Shouldn't `/etc/sysconfig/network` contain lines like: `NETWORKING=yes`, `NETWORKING_IPV6=no`, `HOSTNAME=example.com`, `NISDOMAIN=example` ? – Jasmine Lognnes Nov 20 '14 at 14:50
  • @JasmineLognnes Right, I've corrected it. I hope ewwhite doesn't mind. – kubanczyk Apr 15 '15 at 11:14
  • 2
    It's not just about preference. See [`hostname(1)`](http://linux.die.net/man/1/hostname) on any Linux machine. –  Aug 23 '15 at 13:22
  • The only relevant example of Red Hat-related software I happen to have encountered that actually has a hard requirement for FQDNs in `hostname` is [IPA](https://access.redhat.com/documentation/en-US/Red_Hat_Enterprise_Linux/6/html-single/Identity_Management_Guide/#hostname-requirements), that is, [FreeIPA](http://www.freeipa.org/page/Quick_Start_Guide#DNS_Rules). – Josip Rodin May 27 '16 at 19:35
43

Pretty much all software is sensitive to correctly setting the hostname. While I was working at Digg I once brought the entire site down for 2 hours due to making a seemingly innocent change in /etc/hosts that affected the system's notion of hostname. Tread lightly. That said, you may be slightly confused here. I don't think the HOSTNAME= setting is directly equivalent to how Debian-based distributions use /etc/hostname.

What works for me in a heterogeneous environment is:

  1. Set the hostname in the vendor-recommended manner, using a conditional in your config management software.
  2. Use the hostname command to set the hostname used by the kernel, etc.
  3. In /etc/hosts:

    127.0.0.1    localhost
    10.0.0.1     hostname.example.com     hostname
    

This configuration has not failed me yet.

Anthony Geoghegan
  • 2,800
  • 1
  • 23
  • 34
Paul Lathrop
  • 1,568
  • 10
  • 10
  • This is pretty much the setup I use at work. The shortname should be fine as long as the domain name is in the DNA search path (/etc/resolv.conf) for the relevant machines in your environment – gWaldo Nov 25 '11 at 12:11
  • do you specifically recommend a local network IP as opposed to a public one? – code_monk Jan 05 '18 at 03:18
40

You will certainly have no problem finding references online which will tell you to definitely do it one way or another. It seems to me however that having a short name as the hostname, and have the fully qualified name in /etc/hosts is certainly much more prevalent. It seems like the more sensible way, as then services which need a fully qualified name can be adapted to call hostname --fqdn instead.

I've only come across one piece of software recently which rigidly requires a fqdn to be returned by hostname, which was ganeti. They document this here. I don't see any reason they cannot adapt to hostname --fqdn, however.

stew
  • 9,263
  • 1
  • 28
  • 43
  • 1
    "I don't see any reason they cannot adapt to `hostname --fqdn`" is answered in the first paragraph under "Why a fully qualified host name" -- it requires guesswork, and requires a working resolver. Asking the kernel is the safest and most reliable option. – womble Jan 23 '14 at 09:40
  • 4
    @womble - As long as the /etc/hosts file has an entry for the machine (`10.0.0.1 hostname.example.com hostname`) and /etc/nsswitch.conf specifies local resolution before DNS (`hosts: files dns`) then having a working resolver is fulfilled by the local hosts file. As such that argument for using an FQDN instead of a hostname rarely holds water. Also, another example of software that rigidly requires `hostname` to return an FQDN is the Zimbra mail server package. – crashmaxed Apr 23 '14 at 20:12
  • @crashmaxed: That's several extra requirements, any of which might not be possible in a given environment or screwed up by mistake. Having the FQDN in the kernel data structures is much simpler. – womble May 02 '14 at 02:11
16

Somewhat tangentially, while researching this question, I have been going crazy enough to check the source code of "hostname" and write a script to print investigative results (Fedora 19). What is missing is a look at "/etc/hosts", which in my humble opinion should be kept the hell out of all of this in the first place.

#!/bin/bash

function pad {
   if [[ $1 == '?' ]]; then
      printf "%-23s" "?"
   else
      printf "%-23s" "'$1'"
   fi
}

# ----- Kernel -----

# Two ways to configure the kernel values: 
# 1) Put FQDN into "kernel.hostname" and nothing into "kernel.domainname"
# 2) Put machine name into "kernel.hostname" and DNS domain name into "kernel.domainname" (makes more sense)

echo "== Kernel values =="
echo

H=`/sbin/sysctl -n kernel.hostname`
D=`/sbin/sysctl -n kernel.domainname`

echo "Kernel hostname: '$H'"
echo "Kernel domainname: '$D'"

# ----- What does bash say -----

echo
echo "== According to bash =="
echo

echo "HOSTNAME = '$HOSTNAME'"

# ----- Hostname config file ------

echo
echo "== Hostname config file =="
echo

ETCH="/etc/hostname"

if [[ -f $ETCH ]]; then
   CONTENTS=`cat $ETCH`
   echo "File '$ETCH' contains: '$CONTENTS'"
else
   echo "File '$ETCH' does not exist"
fi

# ----- Network config file ------

echo
echo "== Network config file =="
echo

SYSN="/etc/sysconfig/network"

if [[ -f $SYSN ]]; then
   LINE=`grep -e "^HOSTNAME=" $SYSN`
   if [[ -n $LINE ]]; then
      echo "File '$SYSN' contains: '$LINE'"
   else 
      echo "File '$SYSN' exists but does not contain a line for 'HOSTNAME'"
   fi
else
   echo "File '$SYSN' does not exist"
fi

# ----- Nodename -------

echo
echo "== Nodename =="
echo

UNAME=`uname --nodename` # On Linux, this is the hostname

echo "The 'nodename' given by 'uname --nodename' is: '$UNAME'"

# ----- The 'hostname' mess ------

THE_HOSTNAME=`hostname`
SHORT_NAME=`hostname --short`
NIS_DNAME=`domainname`     
YP_DNAME=`hostname --yp`    # Same as `nisdomainname` ; this may fail with "hostname: Local domain name not set"

if [[ $? != 0 ]]; then
   YP_DNAME="?"
fi

echo
echo "== 'hostname' directly obtained values =="
echo
echo "The result of gethostname();"
echo "...obtained by running 'hostname'"
echo "Hostname: $(pad $THE_HOSTNAME)"
echo
echo "The part before the first '.' of the value returned by gethostname();"
echo "...obtained by running 'hostname --short'"
echo "Short name: $(pad $SHORT_NAME)"
echo
echo "The result of getdomainname(); the code of 'hostname' seems to call this the 'NIS domain name';"
echo "...on Linux, this is the kernel-configured domainname;"
echo "...obtained by running 'domainname'"
echo "NIS domain name: $(pad $NIS_DNAME)"
echo
echo "The result of yp_get_default_domain(), which may fail;"
echo "...obtained by running 'ĥostname --yp'"
echo "YP default domain: $(pad $YP_DNAME)"

DNS_DNAME=`hostname --domain`  # Same as `dnsdomainname`'
FQDN_NAME=`hostname --fqdn`
ALIAS_NAME=`hostname --alias`

echo
echo "== 'hostname' values obtained via DNS =="
echo
echo "The part after the first '.' of the 'canonical name' value returned by getaddrinfo(gethostname());"
echo "...obtained by running 'hostname --domain'"
echo "DNS domain name: $(pad $DNS_DNAME)"
echo
echo "The 'canonical name' value returned by getaddrinfo(gethostname());"
echo "...obtained by running 'hostname --fqdn'"
echo "Fully qualified hostname: $(pad $FQDN_NAME)"
echo
echo "Alias obtained by gethostbyname(gethostname());"
echo "...obtained by running 'hostname --alias'"
echo "Hostname alias: $(pad $ALIAS_NAME)"

BY_IP_ADDR=`hostname --ip-address`
ALL_IP_ADDR=`hostname --all-ip-addresses`
ALL_FQDN_NAMES=`hostname --all-fqdn`

echo
echo "== 'hostname' values obtained by collecting configured network addresses =="
echo
echo "Collect the IP addresses from getaddrinfo(gethostname()), apply getnameinfo(ip) to all those addresses;"
echo "...obtained by running 'hostname --ip-address'"
echo "By IP address: $BY_IP_ADDR"
echo
echo "Call getnameinfo(NI_NUMERICHOST) on all addresses snarfed from active interfaces;"
echo "...obtained by running 'hostname --all-ip-addresses'"
echo "All IP addresses: $ALL_IP_ADDR"
echo
echo "Call getnameinfo(NI_NAMEREQD) on all addresses snarfed from active interfaces (involves lookup in /etc/hosts);"
echo "...obtained by running 'hostname --all-fqdn'"
echo "All fully qualified hostnames: $ALL_FQDN_NAMES"

The output on an Amazon EC2 VM running Fedora 19, after manually setting the kernel values and filling /etc/hostname, but with no changes to /etc/hosts might then be like this:

== Kernel values ==

Kernel hostname: 'kyubee'
Kernel domainname: 'homelinux.org'

== According to bash ==

HOSTNAME = 'ip-172-31-24-249.localdomain'

== Hostname config file ==

File '/etc/hostname' contains: 'kyubee.homelinux.org'

== Network config file ==

File '/etc/sysconfig/network' exists but does not contain a line for 'HOSTNAME'

== Nodename ==

The 'nodename' given by 'uname --nodename' is: 'kyubee'

== 'hostname' directly obtained values ==

The result of gethostname();
...obtained by running 'hostname'
Hostname: 'kyubee'

The part before the first '.' of the value returned by gethostname();
...obtained by running 'hostname --short'
Short name: 'kyubee'

The result of getdomainname(); the code of 'hostname' seems to call this the 'NIS domain name';
...on Linux, this is the kernel-configured domainname;
...obtained by running 'domainname'
NIS domain name: 'homelinux.org'

The result of yp_get_default_domain(), which may fail;
...obtained by running 'ĥostname --yp'
YP default domain: 'homelinux.org'

== 'hostname' values obtained via DNS ==

The part after the first '.' of the 'canonical name' value returned by getaddrinfo(gethostname());
...obtained by running 'hostname --domain'
DNS domain name: ''

The 'canonical name' value returned by getaddrinfo(gethostname());
...obtained by running 'hostname --fqdn'
Fully qualified hostname: 'kyubee'

Alias obtained by gethostbyname(gethostname());
...obtained by running 'hostname --alias'
Hostname alias: ''

== 'hostname' values obtained by collecting configured network addresses ==

Collect the IP addresses from getaddrinfo(gethostname()), apply getnameinfo(ip) to all those addresses;
...obtained by running 'hostname --ip-address'
By IP address: fe80::8f6:8eff:fe49:9e21%eth0 172.31.24.249

Call getnameinfo(NI_NUMERICHOST) on all addresses snarfed from active interfaces;
...obtained by running 'hostname --all-ip-addresses'
All IP addresses: 172.31.24.249

Call getnameinfo(NI_NAMEREQD) on all addresses snarfed from active interfaces (involves lookup in /etc/hosts);
...obtained by running 'hostname --all-fqdn'
All fully qualified hostnames: ip-172-31-24-249.eu-west-1.compute.internal

The resilient way to get the fully qualified hostname in perl would then be:

sub getHostname {

   my $hostname_short = `/bin/hostname --short`;
   if ($? != 0) { print STDERR "Could not execute 'hostname --short' -- exiting\n"; exit 1 }
   chomp $hostname_short;

   my $hostname_long  = `/bin/hostname`;
   if ($? != 0) { print STDERR "Could not execute 'hostname' -- exiting\n"; exit 1 }
   chomp $hostname_long;

   if ($hostname_long =~ /^${hostname_short}\..+$/) {
      # "hostname_long" is a qualified version of "hostname_short"
      return $hostname_long
   }
   else {
      # both hostnames are "short" (and are equal)
      die unless ($hostname_long eq $hostname_short);

      my $domainname = `/bin/domainname`;
      if ($? != 0) { print STDERR "Could not execute 'domainname' -- exiting\n"; exit 1 }
      chomp $domainname;

      if ($domainname eq "(none)") {
         # Change according to taste
         return "${hostname_short}.localdomain"
      }
      else {
         return "${hostname_short}.${domainname}"
      }
   }
}

and in bash it would be:

function getHostname {

   local hostname_short=`/bin/hostname --short`

   if [ $? -ne 0 ]; then
      echo "Could not execute 'hostname --short' -- exiting" >&2; exit 1
   fi

   local hostname_long=`/bin/hostname`

   if [ $? -ne 0 ]; then
      echo "Could not execute 'hostname' -- exiting" >&2; exit 1
   fi

   if [[ $hostname_long =~ ^"$hostname_short"\..+$ ]]; then
      # "hostname_long" is a qualified version of "hostname_short"
      echo $hostname_long
   else
      # both hostnames are "short" (and are equal)
      if [[ $hostname_long != $hostname_short ]]; then
         echo "Cannot happen: '$hostname_long' <> '$hostname_short' -- exiting" >&2; exit 1
      fi

      local domainname=`/bin/domainname`

      if [ $? -ne 0 ]; then
         echo "Could not execute 'domainname' -- exiting" >&2; exit 1
      fi

      if [[ domainname == '(none)' ]]; then
         # Change according to taste
         echo "${hostname_short}.localdomain"
      else
         echo "${hostname_short}.${domainname}"
      fi
   fi
}

Notes

Note 1: HOSTNAME is a shell variable that bash provides ("Automatically set to the name of the current host.") but there is no indication about bash arrives at that value.

Note 2: Never forget /etc/hostname in /boot/initrams-FOO.img ...

David Tonhofer
  • 910
  • 1
  • 9
  • 29
  • 4
    Sorry if this should be obvious, but what does any of this have to do with setting the hostname? – Chris S Oct 14 '13 at 02:34
  • Basically notes I made while researching setting the hostname on my Fedora 19 EC2 instances. As for the result: 1) Set the FQHN in /etc/hostname 2) Do not touch /etc/hosts 3) You may set the 'kernel hostname' either to the FQHN or the unqualified hostname, if unset the value is taken from /etc/hostname 4) You may set the 'kernel domainname' to the domainname, which is nicer than just '(none)'. – David Tonhofer Oct 14 '13 at 09:44
0

Short answer: I generally use the FQDN as the hostname (as recommended on RH6/7 docs). However, the more righteous approach would be to use a single-label name as the hostname, setting the FQDN via /etc/hosts. So, pick an approach and stick with it whenever possible.

Long answer: The main advantage of using the FQDN as the hostname is that the machine name intrinsically embeds domain information. This is very useful when receiving email alert and/or logs for multiple customers/domains, as it avoid duplicate hostnames (ie: hostnames are more-or-less guaranteed to be unique across multiple sites/customers/domains). For example, SNMP sysName show the hostname by default and, by using the FQDN, it simply conveys a more useful information. The same is true for zabbix-agent (and other monitor tools) or for bash $HOSTNAME. While you can configure such tools for using FQDNs even on machine with single-label hostname, or configure them in an hierarchical model which clearly shows the domain containing the machine, this is additional work.

Some application even require using a FQDN as the hostname, but they are quite the exception. Still, when the exception hits, the homogeneous use of single-label hostname is lost. This probably is the main reason behind RedHat's recommendation to use a FQDN as the hostname on RH6/7. More recent docs are more vague. On "Performing a standard RHEL 8 installation" one can read:

The host name can be either a fully-qualified domain name (FQDN) in the format hostname.domainname, or a short host name with no domain name. Many networks have a Dynamic Host Configuration Protocol (DHCP) service that automatically supplies connected systems with a domain name. To allow the DHCP service to assign the domain name to this machine, specify only the short host name

while "Performing an advanced RHEL 8 installation" states:

If your network does not provide a DHCP service, always use the FQDN as the system’s host name

In the years between the original question, user applications have learned to treat FQDN hostnames without the issue described in the previous answers. For example, bash PS1 prompt uses \h (the hostname up to the first '.') by default, and rsyslog does not preserve FQDN in logfiles by default. In other words, the usability drawback of a FQDN hostname are no more for many common tools. For these reasons, I generally set the system hostname as a FQDN, leaving the shortname on /etc/hosts as required.

The reason to not use a FQDN hostname is that, frankly, this is The Right Thing To Do. As respectively stated in the debian docs and hostname man page:

This file should contain only the system hostname, not a fully qualified domain name

and

It is recommended that this name contains only a single label, i.e. without any dots

So, while I do feel uneasy to use a FQDN hostname, it is easier using it in my environments.

Please note this is not an appeal against single-label hostname. If they work for you, continue using it. Otherwise, give the FQDN hostname a try.

shodanshok
  • 44,038
  • 6
  • 98
  • 162
-4

The /etc/hosts options works well.

But you want to make sure that all the proper files are updated run the setup tool

Riaan
  • 411
  • 5
  • 13
  • My distribution doesn't have a "setup" tool; which distribution are you using that has one? – nickgrim Nov 25 '11 at 14:33
  • any redhat based OS has the setup tool rhel/centos/fedora whar OS are you using? – Riaan Nov 25 '11 at 17:10
  • 3
    Since the question talks about differences between RHEL-based and Debian-based distros, we must assume the asker uses both. There is no 'setup' tool on Debian-based distros. – Martijn Heemels Apr 30 '12 at 14:15
-4

Hm... In the linux hosts, if you want change HOSTNAME and FQDN, you should solved 3 steps (for example, new host is rizzo.ifp.com):

Step #1 Change HOST value in the NETWORK properties config:

sudo vi /etc/sysconfig/network

Change or add string:

HOSTNAME=rizzo.ifp.com

Step #2 Edit your hosts config

sudo vim /etc/hosts
#IPv4
127.0.0.1       localhost localhost.localdomain localhost4 localhost4.localdomain4
[External IP]   rizzo rizzo.ifp.com

Step #3 Reboot your host Well done, just check new configuration

[rizzo@rizzo]# hostname -f
rizzo.ifp.com
sub
  • 18
  • 2
-4

The order is not right. It has to be:

1.2.3.4 full.example.com full

So the example could like this:

[External IP] rizzo.example.com rizzo 
Esa Jokinen
  • 43,252
  • 2
  • 75
  • 122