cloudinit breaks connections from localhost to Plesk-operated web servers

I don’t know how or why it is even installed – perhaps part of the provided Ubuntu image from my VPS host – but cloud-init (a.k.a “cloud-config”) is a bit obnoxious. At [re]boot time (best I can tell), it resets /etc/hosts based on some random template it has (/etc/cloud/templates/hosts.debian.tmpl in my case, even though that makes no sense as I’m not using Debian). That template has a very weird entry:

127.0.1.1 {{fqdn}} {{hostname}}

I have no idea what it’s even trying to do with that.

What it does do is break a lot of things, because while 127.0.1.1 is a valid address (albeit weird to use instead of the canonical 127.0.0.1), in a standard Plesk system Nginx (that sits in front of Apache typically) is configured to listen only on the network interface(s) associated with your web server’s public IP address(es), not localhost1. So if you try e.g. curl mydomain.com from inside your server hosting that very domain, you get a connection refused error (or it just times out with no response, depending on firewall settings).

The way I found out about this was when WordPress’s “cron” system silently stopped running tasks (because I use a real cron job to trigger it periodically, rather than relying on WordPress’s flaky built-in system). I subsequently also noticed that Broken Link Checker mistakenly reported every link within my own site as broken.

The solution

…is fairly simple – modify the template to remove the offending line. You then have to either reboot or similarly manually modify /etc/hosts to actually apply the fix.

If for some reason you cannot do that, there are potentially workarounds. For example, for curl commands you can make curl navigate around the problem this like:

curl --header 'Host: mydomain.com' https://<your server's external IP>

☝️ If you have a CDN or similar in front of your server, e.g. Cloudflare, this will potentially behave differently to connecting from another host; it’ll bypass the CDN and connect directly to your web server (effectively the same as if you did connect to 127.0.0.1).

Depending on your needs, this could be desirable (e.g. no need to send WordPress cron invocations through a CDN) or undesirable (broken link checking probably should go through the CDN, just like all real traffic, to test that the CDN doesn’t cause a problem).

In a non-Plesk environment you might also be able to just change the Nginx configuration (somewhere under /etc/nginx). That’s ill-advised for Plesk-operated servers as Plesk will inevitably revert your changes (and as far as I can tell there is no configuration option, or workaround otherwise, to make Plesk configure Nginx to listen on localhost as well 😕).

  1. I suspect this is more a side-effect than intentional. Plesk chooses the interface only implicitly, when it specifies that it listens on specific addresses – those assigned to the website in question (Nginx can host multiple otherwise unrelated websites, and each is configured independently within its settings). Since Plesk supports hosting multiple websites, each with potentially different IP addresses, it makes sense that it would want to keep them separate. Otherwise, in a shared hosting situation you could connect to the IP address for somehost.com yet issue a HTTP request for unrelatedhost.com and actually get a response, which is weird, at least. ↩︎

Leave a Comment