Context
I have a Fedora 20 cloud image running on Amazon EC2 (henceforth called the "instance"). And I have some uncertainty about persistently setting its hostname.
Goal
In this case, let's say I want to set the instance's hostname to penpen.homelinux.org. (This name will also be registered at DynDNS using ddclient
, but that is another aspect which we are not interested in here.)
The hostname can of course be set manually after boot completes (using hostnamectl
among others). But we want to have the correct hostname set before the first login.
Traditionally, to persistently configure the hostname, one would modify the contents of /etc/hostname
. Unfortunately this does not work here.
Default system behaviour
By default, the instance sets its hostname to an internal EC2 name. After boot, we can look at all the little different places that yield the hostname, and we find:
Kernel hostname via 'sysctl' : ip-10-164-65-105.ec2.internal
Kernel domainname via 'sysctl' : (none)
File '/etc/hostname' : contains 'ip-10-164-65-105.ec2.internal'
File '/etc/sysconfig/network' : exists but has no 'HOSTNAME' line
According to the shell : HOSTNAME = ip-10-164-65-105.ec2.internal
Nodename given by 'uname --nodename' : ip-10-164-65-105.ec2.internal
Hostname ('hostname') : ip-10-164-65-105.ec2.internal
Short hostname ('hostname --short') : ip-10-164-65-105
NIS domain name ('domainname') : (none)
YP default domain ('hostname --yp') : [hostname --yp failed]
DNS domain name ('hostname --domain') : ec2.internal
Fully qualified hostname ('hostname --fqdn') : ip-10-164-65-105.ec2.internal
Hostname alias ('hostname --alias') :
By IP address ('hostname --ip-address') : 10.164.65.105
All IPs ('hostname --all-ip-addresses') : 10.164.65.105
All FQHNs via IPs ('hostname --all-ip-addresses') : ip-10-164-65-105.ec2.internal
Static hostname via 'hostnamectl' : ip-10-164-65-105.ec2.internal
Transient hostname via 'hostnamectl' : ip-10-164-65-105.ec2.internal
Pretty hostname via 'hostnamectl' :
So let's try to write to /etc/hostname ...
If one writes the desired hostname to /etc/hostname
, this change is lost again at the next boot. Let's examine the boot process, which is performed by systemd
.
Example run
Write rorororoor.homelinux.org
to /etc/hostname
, then reboot.
Using journald we find (Note that the log lines are not entirely orderd by time):
The boot process starts off with hostname as localhost then switches root, at which point the hostname becomes rorororoor.homelinux.org.
Dec 26 15:12:08 localhost systemd[1]: Starting Cleanup udevd DB...
Dec 26 15:12:08 localhost systemd[1]: Started Cleanup udevd DB.
Dec 26 15:12:08 localhost systemd[1]: Starting Switch Root.
Dec 26 15:12:08 localhost systemd[1]: Reached target Switch Root.
Dec 26 15:12:08 localhost systemd[1]: Starting Switch Root...
Dec 26 15:12:08 localhost systemd[1]: Switching root.
Dec 26 15:12:08 localhost systemd-journal[67]: Journal stopped
Dec 26 15:12:12 rorororoor.homelinux.org systemd-journal[155]: Runtime journal is using 8.0M
Dec 26 15:12:12 rorororoor.homelinux.org systemd-journal[155]: Runtime journal is using 8.0M
Dec 26 15:12:12 rorororoor.homelinux.org systemd-journald[67]: Received SIGTERM
...........
Dec 26 15:12:12 rorororoor.homelinux.org kernel: SELinux: initialized
Dec 26 15:12:12 rorororoor.homelinux.org systemd-journal[155]: Journal started
Dec 26 15:12:08 rorororoor.homelinux.org systemd-cgroups-agent[128]: Failed to get D-Bus connection: Failed to connect to socket /run/systemd/private: No such file or directory
Dec 26 15:12:10 rorororoor.homelinux.org systemd[1]: systemd 208 running in system mode.
Dec 26 15:12:10 rorororoor.homelinux.org systemd[1]: Detected virtualization 'xen'.
Dec 26 15:12:10 rorororoor.homelinux.org systemd[1]: Set hostname to <rorororoor.homelinux.org>.
Dec 26 15:12:10 rorororoor.homelinux.org systemd[1]: Failed to open private bus connection: Failed to connect to socket /var/run/dbus/system_bus_socket: No such file or directory
Dec 26 15:12:11 rorororoor.homelinux.org systemd[1]: Mounted Debug File System.
We see that systemd
sets the hostname to rorororoor.homelinux.org, evidently successfully as the log's host column changes. Some errors are issued, possibly because hostnamectl
cannot contact DBus at this point in time.
I am not sure who does the namesetting here; some internal part of systemd? Anyway, continuing through the journal, we find that the hostname is set back to the EC2 internal name pretty soon:
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] util.py[DEBUG]: Running command ('resize2fs', '/dev/xvda1') with allowed return codes [0] (shell=False, capture=True)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] cc_resizefs.py[DEBUG]: Resizing took 0.067 seconds
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] cc_resizefs.py[DEBUG]: Resized root filesystem (type=ext4, val=True)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] helpers.py[DEBUG]: config-set_hostname already ran (freq=once-per-instance)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] helpers.py[DEBUG]: Running config-update_hostname using lock (<cloudinit.helpers.DummyLock object at 0x2559210>)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] cc_update_hostname.py[DEBUG]: Updating hostname to ip-10-164-65-105.ec2.internal (ip-10-164-65-105)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] util.py[DEBUG]: Running command ['hostname'] with allowed return codes [0] (shell=False, capture=True)
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] __init__.py[DEBUG]: Attempting to update hostname to ip-10-164-65-105.ec2.internal in 1 files
Dec 26 15:12:33 rorororoor.homelinux.org cloud-init[485]: [CLOUDINIT] util.py[DEBUG]: Running command ['hostnamectl', 'set-hostname', 'ip-10-164-65-105.ec2.internal'] with allowed return codes [0] (shell=False, capture=True)
Dec 26 15:12:33 rorororoor.homelinux.org dbus-daemon[226]: dbus[226]: [system] Activating via systemd: service name='org.freedesktop.hostname1' unit='dbus-org.freedesktop.hostname1.service'
Dec 26 15:12:33 rorororoor.homelinux.org dbus[226]: [system] Activating via systemd: service name='org.freedesktop.hostname1' unit='dbus-org.freedesktop.hostname1.service'
Dec 26 15:12:34 rorororoor.homelinux.org systemd[1]: Starting Hostname Service...
Dec 26 15:12:34 rorororoor.homelinux.org dbus-daemon[226]: dbus[226]: [system] Successfully activated service 'org.freedesktop.hostname1'
Dec 26 15:12:34 rorororoor.homelinux.org dbus[226]: [system] Successfully activated service 'org.freedesktop.hostname1'
Dec 26 15:12:34 rorororoor.homelinux.org systemd[1]: Started Hostname Service.
Dec 26 15:12:34 rorororoor.homelinux.org systemd-hostnamed[598]: Changed static host name to 'ip-10-164-65-105.ec2.internal'
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal systemd-hostnamed[598]: Changed host name to 'ip-10-164-65-105.ec2.internal'
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal systemd[1]: Started Initial cloud-init job (metadata service crawler).
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal systemd[1]: Starting Cloud-config availability.
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal systemd[1]: Reached target Cloud-config availability.
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal systemd[1]: Starting Apply the settings specified in cloud-config...
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal [485]: [CLOUDINIT] helpers.py[DEBUG]: Running config-update_etc_hosts using lock (<cloudinit.helpers.DummyLock object at 0x2559350>)
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal [485]: [CLOUDINIT] cc_update_etc_hosts.py[DEBUG]: Configuration option 'manage_etc_hosts' is not set, not managing /etc/hosts in module update_etc_hosts
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal [485]: [CLOUDINIT] helpers.py[DEBUG]: config-rsyslog already ran (freq=once-per-instance)
Dec 26 15:12:34 ip-10-164-65-105.ec2.internal [485]: [CLOUDINIT] helpers.py[DEBUG]: config-users-groups already ran (freq=once-per-instance)
Hostname setting here is done via the unit "systemd-hostnamed". The "unit file" for "systemd-hostnamed" is /usr/lib/systemd/system/systemd-hostnamed.service
and contains:
[Unit]
Description=Hostname Service
Documentation=man:systemd-hostnamed.service(8) man:hostname(5) man:machine-info(5)
Documentation=http://www.freedesktop.org/wiki/Software/systemd/hostnamed
[Service]
ExecStart=/usr/lib/systemd/systemd-hostnamed
BusName=org.freedesktop.hostname1
CapabilityBoundingSet=CAP_SYS_ADMIN CAP_DAC_OVERRIDE CAP_SYS_PTRACE
The program invoked by the above /usr/lib/systemd/systemd-hostnamed
is actually a binary (WHY!). However source code can be found.
The point is that we are back at ip-10-164-65-105.ec2.internal
WHAT DO?
You need to do two things (but have only done one of them):
/etc/hostname
./etc/cloud/cloud.cfg
and setpreserve_hostname
toTrue
. (You can also pass this option in with your user data.)The second step is required because Fedora uses
cloud-init
to bring in user data from the EC2 environment to provision the instance, andcloud-init
needs to be told that the hostname should persist.Another option is to set the hostname via user data
e.g.
This will set the hostname on boot, however I'm unsure if that would always happen before the first login.
It looks like the answer is in the hostnamectl man page there are now 3 hostnames, the static, transient and pretty hostnames.
To set the static hostname which I think is the one you want,
You can set them all to be the same with
Solve using an additional unit file
The following does not really work:
Create a system unit file
/usr/lib/systemd/system/penpen-naming.service
to be started aftersystemd-hostnamed.service
(and possibly only afterdbus.service
).(I had to perform quiet a few trials to find the "right place" so that
systemd
would not simple deactivate the new unit because "a cycle was detected". Note that you can graph the unit file dependency graph withsystemd-analyze dot
, which creates a "dot" file to be passed to the "graphviz"dot
program, but the result is just a large confusing graph, unless you prefilter it)Contents of unit file
/usr/lib/systemd/system/penpen-naming.service
:Activate it using
systemctl enable penpen-naming
What does
/usr/local/toolbox/setting_hostnames/penpen
do? If writes penpen.homelinux.org to/etc/hostname
. But that is actually not enough, one also has to set the hostname usinghostnamectl
.Even then, the unit has to be run so late
(After=default.target)
that the login shell still displays the EC2 internal hostname. And there are still problems connecting to DBus.So this is not a good solution, or at least it needs a fix for "position in unit file dependency tree" and "what the hell is up with dbus"
The hostnames after this are:
This is actually a bug in cloud-init on RHEL-like distros using SystemD. There is a patch available at https://bugs.launchpad.net/cloud-init/+bug/1424710