Apache and Fully Qualified Domain Names

A deep dive into the truth behind the mystery
Created: 2017-05-04 Updated: 2022-02-27

Have you ever gotten this error when starting Apache on Linux?

httpd: Could not reliably determine the server's fully
qualified domain name, using 127.0.0.1 for ServerName

Most advice I’ve seen suggests that you simply set the ServerName value in your httpd.conf file. That will certainly work. But I find the answer very unsatisfying and even a little misleading.

The quest for a more satisfying answer

TODO: 2022-02-27 - Julia Evans recently posted Some things about getaddrinfo that surprised me which reminded me that I need to rework this article to be more universally correct (and re-order it so that the answers come first and the deep-dives supporting the answer come last).

This article is the result with my dissatisfaction with the answers I’d found online when I looked up this error. My goal is to really understand what causes the error and solve the underlying issue: having a fully-qualified domain name (FQDN) set on your Linux system that Apache can actually use!

Let’s begin our quest at the logical starting point:

Apache’s wiki has the typical advice (set ServerName and off you go.) But it also ends with the following paragraph:

The presence of this error message also indicates that Apache httpd was unable to obtain a fully-qualified hostname by doing a reverse lookup on your server’s IP address. While the above instructions will get rid of the warning in any case, it is also a good idea to fix your name resolution so that this reverse mapping works.

(Emphasis mine.)

The problem is, setting ServerName in httpd.conf will solve the problem for Apache, but you will not have solved this issue for (potentially) other applications. Furthermore, it is my personal feeling that having to set both /etc/hosts and httpd.conf with the same information is a violation of the single source of truth principle.

(Of course, there are tons of perfectly valid reasons to set the httpd server name to something (or multiple somethings in the case of virtual hosts) other than the machine’s canonical hostname. That’s not what this quest is about.)

I’ve done some researching and experimenting and I believe I have a fairly complete answer.

Let’s look at some Apache source!

The source for Apache can be viewed on Github.

First, the error message we’re getting ("Could not reliably determine the server’s fully qualified domain name…​") is coming from a function named ap_get_local_host():

To quote util.c:

ap_log_perror(APLOG_MARK, APLOG_ALERT|APLOG_STARTUP, 0, a, APLOGNO(00558)
    "%s: Could not reliably determine the server's fully qualified "
    "domain name, using %s. Set the 'ServerName' directive globally "
    "to suppress this message",
    ap_server_argv0, server_hostname);

To successfully get the FQDN for your system, it calls first apr_sockaddr_info_get() and then apr_getnameinfo() (both are part of the Apache Portable Runtime, see source for sockaddr.c here) to get the IP address and then the hostname for the address for your system.

On non-legacy POSIX systems, these functions call the C library functions getaddrinfo() and getnameinfo().

Someone please correct me if I’m wrong, but from my skimming of the Apache source and some man pages (links scattered below), it appears that the following occurs:

1. The hostname is requested

The hostname is retrieved with gethostname(). (See related man page.)

2. The IP address for the hostname is requested

The IP address for the hostname is retrieved with getaddrinfo(). (See related man page.)

3. The FQDN for the IP address is requested

The fully-qualified domain name for the hostname’s ip address is retrieved with getnameinfo(). (See related man page.)

It should be noted that getnameinfo() uses the settings in /etc/nsswitch.conf to determine the search order to use for resolving addresses to names. (See related man page.)

By default on most systems, /etc/nsswitch.conf will contain a line like

hosts: files dns

files specifically means /etc/hosts on most systems, so the ultimate meaning is that the contents of /etc/hosts will be checked before DNS.

What to do! (Two steps)

Let’s use wiggles as our example hostname.

First, set your hostname

Permanently setting the hostname seems to be distro-specific.

Second, edit /etc/hosts

Note: this might also be distro-specific. Check to see if you need to perform this step at all for your Linux distribution.

You’ll need an entry in your /etc/hosts file that resolves your hostname to an IP address AND resolves that IP address to an FQDN. (See related man page.)

IP_address     canonical_hostname     [aliases...]

Example:

192.0.2.16       wiggles.example.com     wiggles

It’s important that wiggles.example.com (the FQDN) comes before wiggles (the hostname). Why? Because gethostname() returns the canonical name, which is the first one.

Apache will not be impressed if it does not see a name with at least one . character. (See ap_get_local_host() in util.c linked above).

Testing at the command line!

To feel confident about the hostname setup, let’s test it.

We can pretty accurately replicate what is happening internally in Apache at the command line using the hostname and getent commands.

Getting the hostname

$ hostname -v
gethostname()=`wiggles'
wiggles

(The -v option is for 'verbose'.)

Getting the IP address for the hostname

$ hostname -i
192.0.2.16

(You can also add the -v option for more detail.)

Getting the FQDN for the IP address

$ getent hosts 192.0.2.16
192.0.2.16   wiggles.example.com  wiggles

getent hosts does specifically search in /etc/hosts. Check your /etc/nsswitch.conf to double-check the hosts lookup order (see previous information) or write your own Perl script to call the gethostbyaddr() function directly!

By incrementally checking each step on the command line, it should be clear what is happening and where any fixes would need to occur.

The final test is to start or restart Apache and see if it’s happy. Run your distro’s equivalent to this (restart Apache/httpd):

apachectl restart

As with all things on the Unix command line, no news is good news.