A systemd service that needs a configured IP address at startup declares After=network.target, yet at boot it still fails with "cannot assign requested address". What does network.target actually guarantee, and what should the unit declare instead?
answer
- the name promises more than it delivers
- stack started, not address configured
- the target needs pulling in, not just ordering
- something must actually block on your behalf
- the durable fix is retrying
basics
~20 snetwork.target only means the network management stack has started, not that any interface is configured. A unit that needs real connectivity must declare both Wants=network-online.target and After=network-online.target, and a wait-online service must be enabled to make that target mean anything.
solid answer
~40 s`network.target` is a synchronisation point, not a connectivity promise: reaching it says the network management software has been started and, at shutdown, that the network is about to go away. Addresses may still be unconfigured, DHCP may still be in flight. The target that means "at least one interface is up and configured" is `network-online.target`, and it has two requirements. First, ordering alone is not enough — nothing pulls that target in by default, so the unit needs `Wants=network-online.target` as well as `After=network-online.target`. Second, the target is only as good as the wait-online service behind it: `systemd-networkd-wait-online.service` or `NetworkManager-wait-online.service` must actually be enabled, otherwise the target activates instantly and you are back where you started. Even then it is a best-effort approximation of connectivity, so a service that can retry should still retry.
code
ini · 12 lines[Unit]
Description=Metrics shipper
Wants=network-online.target
After=network-online.target
[Service]
ExecStart=/usr/local/bin/shipper
Restart=on-failure
RestartSec=5s
[Install]
WantedBy=multi-user.targetgo deeper
Know that there are two different network targets and that network.target does not mean the machine is on the network. If a service needs an address at startup, network-online.target is the one to look up.
Explain the mechanics: network-online.target is passive, needs Wants= as well as After= to be pulled into the transaction, and only blocks because a wait-online service is enabled and ordered before it.
Show the operational judgment — that waiting serialises boot, that the guarantee is a best-effort approximation on multi-homed hosts, and that a service which can retry should retry instead of gating on a target.
Own the fleet-level position: gating startup on connectivity trades boot time and a fragile assumption for a fix the application should carry. Set the expectation that services tolerate an absent network, and reserve the target for the few that genuinely cannot.
## Why network.target disappoints people The name reads like a promise about the network. It is not. `network.target` is a passive synchronisation point with two documented meanings, and neither is "you have an address": - **At boot**, units ordered `After=network.target` are started after the network management stack has been started. The manager is running; it has not necessarily finished doing anything. - **At shutdown**, the ordering is reversed, so `Before=network.target` on the teardown side is how a unit gets stopped while the network still exists. This is arguably the more important of the two uses, and it is why the target exists at all. So `After=network.target` on a service that binds to a specific address, or that dials out on startup, buys you very little. DHCP may not have returned, IPv6 may still be in duplicate-address detection, the interface may be enumerated but unconfigured. The failure is timing-dependent, which is why it shows up on one host in twenty and "goes away" when you add a sleep. ## network-online.target and the wait-online services `network-online.target` exists for the case where the unit genuinely cannot proceed without connectivity. It is also passive — it does nothing by itself. What gives it meaning is a *wait-online* service that is ordered before it and blocks until the network manager reports that configuration is done: - `systemd-networkd-wait-online.service` when the host uses systemd-networkd - `NetworkManager-wait-online.service` when the host uses NetworkManager Whichever is appropriate must be **enabled**. If neither is, `network-online.target` activates immediately and your ordering is decorative. Check it: ```bash systemctl is-enabled NetworkManager-wait-online.service systemctl status systemd-networkd-wait-online.service ``` ## The correct unit stanza ```ini [Unit] Description=Metrics shipper Wants=network-online.target After=network-online.target [Service] ExecStart=/usr/local/bin/shipper Restart=on-failure RestartSec=5s [Install] WantedBy=multi-user.target ``` Both lines matter, for different reasons. `After=` supplies the ordering. `Wants=` supplies the *pull* — ordering against a unit that is not in the transaction is a no-op, and nothing else on a typical host pulls `network-online.target` in. Writing only `After=network-online.target` is the single most common way to get this wrong while believing it is fixed. ## What "online" actually means Even with everything wired correctly, the guarantee is weaker than the name suggests. The wait-online implementations decide when *their* notion of configuration is complete — by default something like "all managed interfaces that are expected to come up have done so". They cannot know whether your VPN is established, whether the route to the specific peer you need exists, or whether DNS resolves. On a multi-homed host the interface that came up may not be the one you care about; `systemd-networkd-wait-online` accepts options to wait for particular interfaces, which is worth reaching for when the default is too loose. And none of it helps after boot. A DHCP lease change, a link flap or a firewall reload can drop connectivity at 3 a.m., long after any target has been reached. Boot ordering has nothing to say about that. ## The judgment an interviewer is listening for The strong answer has two halves: 1. **Order correctly** — `Wants=` plus `After=network-online.target`, with the wait-online service enabled, for units that genuinely cannot start without an address (a daemon that binds one specific IP, a mount of a remote filesystem, a one-shot registration). 2. **Prefer not to need it** — a long-running service should tolerate a network that is not there yet. Retrying with backoff, or letting `Restart=on-failure` with a sensible `RestartSec=` do the retrying, makes the service correct at boot *and* correct at 3 a.m., and it does not extend the boot by however long the wait-online service blocks. Every unit that waits for the target serialises part of the boot behind it, so adding it to everything is a real cost. That second half is what separates someone repeating a recipe from someone who has operated fleets: `network-online.target` is a crutch for software that cannot retry, and a lot of software can. ## Related synchronisation points `nss-lookup.target` is the ordering point for name resolution being available and is what a unit needing DNS at startup should order against. `network-pre.target` runs *before* the network comes up, which is where firewall rule loading belongs so that no packet is accepted before the policy exists. Like the others, these are passive: they mean whatever the units around them have agreed, so verify rather than assume.
- You add the Wants= and After= lines correctly and the service still starts before the address exists. What do you check next?Whether a wait-online service is enabled. `network-online.target` is passive — it blocks only because `systemd-networkd-wait-online.service` or `NetworkManager-wait-online.service` is ordered before it and holds the transaction. Run `systemctl is-enabled` on the one matching your network manager; if it is disabled, the target activates instantly. Confirm afterwards with `systemd-analyze critical-chain` that the wait actually appears in the boot chain.
- Where should firewall rules be loaded relative to these targets, and why?Before the network comes up, ordered against `network-pre.target`. If rules load after interfaces are configured there is a window in which the host is addressable with no policy in place, which is a real exposure on a public network. The firewall unit declares `Wants=network-pre.target` and `Before=network-pre.target`, so the network management stack is ordered behind it.
- Why is gating many services on network-online.target discouraged?Each one serialises part of the boot behind however long the wait-online service blocks — often several seconds, longer on a host waiting for DHCP on an unplugged interface. It also encodes a boot-time-only assumption: the target says nothing about connectivity ten minutes later. A service with retry and backoff, or `Restart=on-failure` with a `RestartSec=`, is correct in both situations and costs no boot time.
saying these in an interview costs you the question
- Believes network.target means connectivity is available
- Adds only After=network-online.target and omits the Wants=
- Assumes network-online.target works without a wait-online service enabled
- Fixes it with sleep in ExecStart or ExecStartPre
- Thinks reaching the target guarantees the network stays up