Can I make Apache only start once the system got its address from DHCP?
I am running Ubuntu in a VM for the purpose of having a local Wordpress installation, needed to do some local testing.
To this end I configured this machine's networking mode in VirtualBox to bridged, configured my home router to always lease the same IP address (192.168.0.101
) to the MAC address of this VM and configured Apache to listen on this address in etc/apache2/ports.conf
:
Listen 192.168.0.101:80
<IfModule ssl_module>
Listen 192.168.0.101:443
</IfModule>
<IfModule mod_gnutls.c>
Listen 192.168.0.101:443
</IfModule>
An unfortunate result of this is that Apache often refuses to start on system bootup:
m@m-VirtualBox:~$ sudo systemctl status apache2
[sudo] password for m:
× apache2.service - The Apache HTTP Server
Loaded: loaded (/lib/systemd/system/apache2.service; enabled; vendor preset: enabled)
Active: failed (Result: exit-code) since Fri 2021-10-22 16:12:19 CEST; 28s ago
Docs: https://httpd.apache.org/docs/2.4/
Process: 681 ExecStart=/usr/sbin/apachectl start (code=exited, status=1/FAILURE)
CPU: 19ms
paź 22 16:12:19 m-VirtualBox systemd[1]: Starting The Apache HTTP Server...
paź 22 16:12:19 m-VirtualBox apachectl[701]: (99)Cannot assign requested address: AH00072: make_sock: could not bind to address 192.168.0.101:80
paź 22 16:12:19 m-VirtualBox apachectl[701]: no listening sockets available, shutting down
paź 22 16:12:19 m-VirtualBox apachectl[701]: AH00015: Unable to open logs
paź 22 16:12:19 m-VirtualBox apachectl[681]: Action 'start' failed.
paź 22 16:12:19 m-VirtualBox apachectl[681]: The Apache error log may have more information.
paź 22 16:12:19 m-VirtualBox systemd[1]: apache2.service: Control process exited, code=exited, status=1/FAILURE
paź 22 16:12:19 m-VirtualBox systemd[1]: apache2.service: Failed with result 'exit-code'.
paź 22 16:12:19 m-VirtualBox systemd[1]: Failed to start The Apache HTTP Server.
I can always start Apache manually with sudo systemctl start apache2
and then Apache starts successfully.
Making Apache2 listen on 127.0.0.1
instead of 192.168.0.101
also makes Apache succesfully start on system bootup, without errors such as the one shown above.
Therefore I suspect that the problem may be that Apache tries to start before DHCP manages to finish its job. Apache tries to listen on 192.168.0.101
, but the machine is not assigned this address yet, so Apache is refused and errors out.
To try to resolve this issue and check if my guess is right I'd like to somehow set apache to only start once the DHCP client is finished. Is this possible and how?
Solution 1:
The previous (sadly, now deleted) answer by a helpful user whose nick slipped my mind already was almost correct.
It suggested to amend the /lib/systemd/system/apache2.service
file to make it depend on network-online.target
instead of the default network.target
or, better, to add a second file to /lib/systemd/system
called my-apache2.service
with this modification. As per the documentation this is the correct way to make sure that a service only starts when the network is really up.
While this works the problem here is that the contents of /lib
are not supposed to be edited and /etc/systemd/system
should be used for this purpose instead. (Yes, this answer I linked to deals with systems other than Ubuntu, but reading man 7 file-hierarchy
and man 5 systemd.unit
on Ubuntu shows the same thing).
The second problem is that, from my experience, trying to run Apache2 twice leads to problems.
To remedy both problems my answer previously recommended the creation of a conflicting service in /etc/systemd/system
. However, this was overly complicated and failed to solve some of the above problems, namely it was not future proof: changes to the original .service
file made by upstream authors would not automatically be incorporated into our new .service
file.
The correct solution is to create a drop-in file that adds a new After
dependency to the original apache2.service
, as documented by man 5 systemd.unit
. To do so one needs to enter the following command:
# systemctl edit apache2.service
(which is documented in man 1 systemctl
)
...and when the editor opens one needs to enter the following contents between the ### Anything between here and the comment below
... and ### Lines below this comment
... lines:
[Unit]
After=network-online.target
And save the new file.
Note that as per man 5 systemd.unit
this will not replace the original After dependencies of the service; rather, this will add a new dependency to the ones that are already present.
For reference, here are the original contents of /lib/systemd/system/apache2.service
:
[Unit]
Description=The Apache HTTP Server
After=network.target remote-fs.target nss-lookup.target
Documentation=https://httpd.apache.org/docs/2.4/
[Service]
Type=forking
Environment=APACHE_STARTED_BY_SYSTEMD=true
ExecStart=/usr/sbin/apachectl start
ExecStop=/usr/sbin/apachectl graceful-stop
ExecReload=/usr/sbin/apachectl graceful
KillMode=mixed
PrivateTmp=true
Restart=on-abort
[Install]
WantedBy=multi-user.target
From now on Apache2 should no longer fail to start on system boot.