mirror of
https://github.com/systemd/systemd.git
synced 2024-12-25 01:34:28 +03:00
8e3fee33af
This reverts commit 5e8ff010a1
.
This broke all the URLs, we can't have that. (And actually, we probably don't
_want_ to make the change either. It's nicer to have all the pages in one
directory, so one doesn't have to figure out to which collection the page
belongs.)
264 lines
14 KiB
Markdown
264 lines
14 KiB
Markdown
---
|
|
title: Running Services After the Network Is Up
|
|
category: Networking
|
|
layout: default
|
|
SPDX-License-Identifier: LGPL-2.1-or-later
|
|
---
|
|
|
|
# Network Configuration Synchronization Points
|
|
|
|
systemd provides three target units related to network configuration:
|
|
|
|
## Network pre-configuration: `network-pre.target`
|
|
|
|
`network-pre.target` is used to order services before any network interfaces
|
|
start to be configured. Its primary purpose is for usage with firewall services
|
|
that want to establish a firewall *before* any network interface is up.
|
|
|
|
`network-pre.target` is a passive unit: it cannot be started directly and it is
|
|
not pulled in by the network management service, but instead a service that
|
|
wants to run before it must pull it in. Network management services hence
|
|
should set `After=network-pre.target`, but not `Wants=network-pre.target` or
|
|
`Requires=network-pre.target`. Services that want to be run before the network
|
|
is configured should use `Before=network-pre.target` and
|
|
`Wants=network-pre.target`. This way, unless there's actually a service that
|
|
needs to be ordered before the network is up, this target is not pulled in,
|
|
avoiding an unnecessary synchronization point.
|
|
|
|
## Network management services: `network.target`
|
|
|
|
`network.target` indicates that the network management stack has been started.
|
|
Ordering after it has little meaning during start-up: whether any network
|
|
interfaces are already configured when it is reached is not defined.
|
|
|
|
Its primary purpose is for ordering things properly at shutdown: since the
|
|
shutdown ordering of units in systemd is the reverse of the startup ordering,
|
|
any unit that has `After=network.target` can be sure that it is *stopped*
|
|
before the network is shut down when the system is going down. This allows
|
|
services to cleanly terminate connections before going down, instead of losing
|
|
ongoing connections leaving the other side in an undefined state.
|
|
|
|
Note that `network.target` is a passive unit: you cannot start it directly and
|
|
it is not pulled in by any services that want to make use of the network.
|
|
Instead, it is pulled in by the network management services
|
|
themselves. Services using the network should hence simply place an
|
|
`After=network.target` stanza in their unit files, without
|
|
`Wants=network.target` or `Requires=network.target`.
|
|
|
|
## Network connectivity has been established: `network-online.target`
|
|
|
|
`network-online.target` is a target that actively waits until the network is
|
|
"up", where the definition of "up" is defined by the network management
|
|
software. Usually it indicates a configured, routable IP address of some
|
|
kind. Its primary purpose is to actively delay activation of services until the
|
|
network has been set up.
|
|
|
|
It is an active target, meaning that it may be pulled in by the services
|
|
requiring the network to be up, but is not pulled in by the network management
|
|
service itself. By default all remote mounts defined in `/etc/fstab` make use
|
|
of this service, in order to make sure the network is up before attempts to
|
|
connect to a network share are made. Note that normally, if no service requires
|
|
it and if no remote mount point is configured, this target is not pulled into
|
|
the boot, thus avoiding any delays during boot should the network not be
|
|
available. It is strongly recommended not to make use of this target too
|
|
liberally: for example network server software should generally not pull this
|
|
in (since server software generally is happy to accept local connections even
|
|
before any routable network interface is up). Its primary purpose is network
|
|
client software that cannot operate without network.
|
|
|
|
For more details about those targets, see the
|
|
[systemd.special(7)](https://www.freedesktop.org/software/systemd/man/systemd.special.html)
|
|
man page.
|
|
|
|
## Compatibility with SysV init
|
|
|
|
LSB defines a `$network` dependency for legacy init scripts. Whenever systemd
|
|
encounters a `$network` dependency in LSB headers of init scripts it will
|
|
translate this to `Wants=` and `After=` dependencies on
|
|
`network-online.target`, staying relatively close to traditional LSB behaviour.
|
|
|
|
# Discussion
|
|
|
|
The meaning of `$network` is defined [only very
|
|
unprecisely](http://refspecs.linuxbase.org/LSB_3.1.1/LSB-Core-generic/LSB-Core-generic/facilname.html)
|
|
and people tend to have different ideas what it is supposed to mean. Here are a
|
|
couple of ideas people came up with so far:
|
|
|
|
* The network management software is up.
|
|
* All "configured" network interfaces are up and an IP address has been assigned to each.
|
|
* All discovered local hardware interfaces that have a link beat have an IP address assigned, independently whether there is actually any explicit local configuration for them.
|
|
* The network has been set up precisely to the level that a DNS server is reachable.
|
|
* Same, but some specific site-specific server is reachable.
|
|
* Same, but "the Internet" is reachable.
|
|
* All "configured" ethernet devices are up, but all "configured" PPP links which are supposed to also start at boot don't have to be yet.
|
|
* A certain "profile" is enabled and some condition of the above holds. If another "profile" is enabled a different condition would have to be checked.
|
|
* Based on the location of the system a different set of configuration should be up or checked for.
|
|
* At least one global IPv4 address is configured.
|
|
* At least one global IPv6 address is configured.
|
|
* At least one global IPv4 or IPv6 address is configured.
|
|
* And so on and so on.
|
|
|
|
All these are valid approaches to the question "When is the network up?", but
|
|
none of them would be useful to be good as generic default.
|
|
|
|
Modern networking tends to be highly dynamic: machines are moved between
|
|
networks, network configuration changes, hardware is added and removed, virtual
|
|
networks are set up, reconfigured, and shut down again. Network connectivity is
|
|
not unconditionally and continuously available, and a machine is connected to
|
|
different networks at different times. This is particularly true for mobile
|
|
hardware such as handsets, tablets, and laptops, but also for embedded and
|
|
servers. Software that is written under the assumption that network
|
|
connectivity is available continuously and never changes is hence not
|
|
up-to-date with reality. Well-written software should be able to handle dynamic
|
|
configuration changes. It should react to changing network configuration and
|
|
make the best of it. If it cannot reach a server it must retry. If network
|
|
configuration connectivity is lost it must not fail catastrophically. Reacting
|
|
to local network configuration changes in daemon code is not particularly
|
|
hard. In fact many well-known network-facing services running on Linux have
|
|
been doing this for decades. A service written like this is robust, can be
|
|
started at any time, and will always do the best of the circumstances it is
|
|
running in.
|
|
|
|
`$network` / `network-online.target` is a mechanism that is required only to
|
|
deal with software that assumes continuous network is available (i.e. of the
|
|
simple not-well-written kind). Which facet of it it requires is undefined. An
|
|
IMAP server might just require a certain IP to be assigned so that it can
|
|
listen on it. OTOH a network file system client might need DNS up, and the
|
|
service to contact up, as well. What precisely is required is not obvious and
|
|
can be different things depending on local configuration.
|
|
|
|
A robust system boots up independently of external services. More specifically,
|
|
if a network DHCP server does not react, this should not slow down boot on most
|
|
setups, but only for those where network connectivity is strictly needed (for
|
|
example, because the host actually boots from the network).
|
|
|
|
# FAQ
|
|
|
|
## How do I make sure that my service starts after the network is *really* online?
|
|
|
|
That depends on your setup and the services you plan to run after it (see
|
|
above). If you need to delay you service after network connectivity has been
|
|
established, include
|
|
|
|
```ini
|
|
After=network-online.target
|
|
Wants=network-online.target
|
|
```
|
|
|
|
in the `.service` file.
|
|
|
|
This will delay boot until the network management software says the network is "up".
|
|
For details, see the next question.
|
|
|
|
## What does "up" actually mean?
|
|
|
|
The services that are ordered before `network-online.target` define its
|
|
meaning. *Usually* means that all configured network devices are up and have an
|
|
IP address assigned, but details may vary. In particular, configuration may
|
|
affect which interfaces are taken into account.
|
|
|
|
`network-online.target` will time out after 90s. Enabling this might
|
|
considerably delay your boot even if the timeout is not reached.
|
|
|
|
The right "wait" service must be enabled:
|
|
`NetworkManager-wait-online.service` if `NetworkManager` is used to configure
|
|
the network, `systemd-networkd-wait-online.service` if `systemd-networkd` is
|
|
used, etc. `systemd-networkd.service` has
|
|
`Also=systemd-networkd-wait-online.service` in its `[Install]` section, so when
|
|
`systemd-networkd.service` is enabled, `systemd-networkd-wait-online.service`
|
|
will be enabled too, which means that `network-online.target` will include
|
|
`systemd-networkd-wait-online.service` when and only when
|
|
`systemd-networkd.service` is enabled. `NetworkManager-wait-online.service` is
|
|
set up similarly. This means that the "wait" services do not need to be enabled
|
|
explicitly. They will be enabled automatically when the "main" service is
|
|
enabled, though they will not be *used* unless something else pulls in
|
|
`network-online.target`.
|
|
|
|
To verify that the right service is enabled (usually only one should be):
|
|
```console
|
|
$ systemctl is-enabled NetworkManager-wait-online.service systemd-networkd-wait-online.service
|
|
disabled
|
|
enabled
|
|
```
|
|
|
|
## Should `network-online.target` be used?
|
|
|
|
Please note that `network-online.target` means that the network connectivity
|
|
*has been* reached, not that it is currently available. By the very nature and
|
|
design of the network, connectivity may briefly or permanently disappear, so
|
|
for reasonable user experience, services need to handle temporary lack of
|
|
connectivity.
|
|
|
|
If you are a developer, instead of wondering what to do about `network.target`,
|
|
please just fix your program to be friendly to dynamically changing network
|
|
configuration. That way you will make your users happy because things just
|
|
start to work, and you will get fewer bug reports. You also make the boot
|
|
faster by not delaying services until network connectivity has been
|
|
established. This is particularly important for folks with slow address
|
|
assignment replies from a DHCP server.
|
|
|
|
Here are a couple of possible approaches:
|
|
|
|
1. Watch rtnetlink and react to network configuration changes as they
|
|
happen. This is usually the nicest solution, but not always the easiest.
|
|
2. If you write a server: listen on `[::]`, `[::1]`, `0.0.0.0`, and `127.0.0.1`
|
|
only. These pseudo-addresses are unconditionally available. If you always
|
|
bind to these addresses you will have code that doesn't have to react to
|
|
network changes, as all you listen on is catch-all and private addresses.
|
|
3. If you write a server: if you want to listen on other, explicitly configured
|
|
addresses, consider using the `IP_FREEBIND` sockopt functionality of the
|
|
Linux kernel. This allows your code to bind to an address even if it is not
|
|
actually (yet or ever) configured locally. This also makes your code robust
|
|
towards network configuration changes. This is provided as `FreeBind=`
|
|
for systemd services, see
|
|
[systemd.socket(5)](https://www.freedesktop.org/software/systemd/man/systemd.socket.html).
|
|
|
|
An exception to the above recommendations is services which require network
|
|
connectivity, but do not delay system startup. An example may be a service
|
|
which downloads package updates into a cache (to be used at some point in the
|
|
future by the package management software). Such a service may even start
|
|
during boot, and pull in and be ordered after `network-online.target`, but as
|
|
long as it is not ordered before any unit that is part of the default target,
|
|
it does not delay boot. It is usually easier to write such a service in a
|
|
"simplistic" way, where it doesn't try to wait for the network connectivity to
|
|
be (re-)established, but is instead started when the network has connectivity,
|
|
and if the network goes away, it fails and relies on the system manager to
|
|
restart it if appropriate.
|
|
|
|
## Modyfing the meaning of `network-online.target`
|
|
|
|
As described above, the meaning of this target is defined first by which
|
|
implementing services are enabled (`NetworkManager-wait-online.service`,
|
|
`systemd-networkd-wait-online.service`, …), and second by the configuration
|
|
specific to those services.
|
|
|
|
For example, `systemd-networkd-wait-online.service` will wait until all
|
|
interfaces that are present and managed by
|
|
[systemd-networkd.service(8)](https://www.freedesktop.org/software/systemd/man/systemd-networkd.service.html).
|
|
are fully configured or failed and at least one link is online; see
|
|
[systemd-networkd-wait-online.service(8)](https://www.freedesktop.org/software/systemd/man/systemd-networkd-wait-online.service.html)
|
|
for details. Those conditions are affected by the presence of configuration
|
|
that matches various links, but also by settings like
|
|
`Unmanaged=`, `RequiredForOnline=`, `RequiredFamilyForOnline=`; see
|
|
[systemd.network(5)](https://www.freedesktop.org/software/systemd/man/systemd.network.html).
|
|
|
|
It is also possible to plug in additional checks for network state. For
|
|
example, to delay `network-online.target` until some a specific host is
|
|
reachable (the name can be resolved over DNS and the appropriate route has been
|
|
established), the following simple service could be used:
|
|
|
|
```ini
|
|
[Unit]
|
|
DefaultDependencies=no
|
|
After=nss-lookup.target
|
|
Before=network-online.target
|
|
|
|
[Service]
|
|
Type=oneshot
|
|
RemainAfterExit=yes
|
|
ExecStart=sh -c 'until ping -c 1 example.com; do sleep 1; done'
|
|
|
|
[Install]
|
|
WantedBy=network-online.target
|
|
```
|