Wait for a Real Connection with nm-online
A systemd unit that fires before the network is actually up is a classic cause of flaky boots, and nm-online exists to stop that. It gives you a testable way to wait for NetworkManager to report an active connection, then use the result in a script. The examples use NetworkManager 1.46.0, installed here as Debian package network-manager 1.46.0-1ubuntu2.8.
The route
Jump straight to the step you need, or tick off Done means at the end.
Allow about ten minutes. You need a shell, NetworkManager and the nm-online command. This guide only observes connection state, it does not bring an interface up, change a profile or restart NetworkManager, so no elevated privileges are normally needed.
Checkpoint
The exit status is the result you actually need. Output can be suppressed with --quiet; do not build a script that treats printed text as the signal.
1. Check the installed command
Confirm the executable and package version with these ordinary read-only commands:
$ command -v nm-online
/usr/bin/nm-online
$ dpkg-query -W -f='${Package} ${Version}\n' network-manager
network-manager 1.46.0-1ubuntu2.8
$ nm-online --help
Usage:
nm-online [OPTION...]
Waits for NetworkManager to finish activating startup network connections.
The installed help also reports a maximum timeout of 2,073,600 seconds; this guide uses far shorter values. The local manual identifies the source as NetworkManager 1.46.0, so check installed help before applying these examples to another release.
2. Wait for an active connection
Run nm-online with its default behaviour when the next command genuinely needs NetworkManager to report an active connection:
$ nm-online
Connecting... [offline]
That progress line gets rewritten while the command waits, so the exact display varies by terminal and connection state. On success it returns status 0, and it waits up to 30 seconds by default. The printed text is not the interface your script should parse.
Use a shorter timeout for an interactive check or a bounded pre-flight step:
$ nm-online --quiet --timeout=5
$ printf 'nm-online status: %s\n' "$?"
nm-online status: 0
- Status 0 means NetworkManager reported a connection within the timeout.
- Status 1 means the host was offline or the timeout expired.
- Status 2 means an unknown or unspecified error occurred.
Keep those cases visible instead of letting later commands fail with a less useful message.
3. Put the status check in a script
Capture the status immediately, then branch on it. --quiet keeps normal operation free of diagnostic output:
if nm-online --quiet --timeout=15; then
printf '%s\n' 'NetworkManager reports an active connection'
/path/to/network-dependent-command
else
status=$?
case "$status" in
1) printf '%s\n' 'No active connection within 15 seconds' >&2 ;;
2) printf '%s\n' 'nm-online reported an unspecified error' >&2 ;;
*) printf 'nm-online failed with status %s\n' "$status" >&2 ;;
esac
exit "$status"
fi
Replace /path/to/network-dependent-command with the real command. This example passes the check's non-zero status straight through, so a calling service or job notices the failure. It does not retry forever, and it does not claim a connected host can reach any particular server.
Checkpoint
Test the failure path without changing network state, using a very short timeout on a host that is currently offline:
$ nm-online --quiet --timeout=1
$ printf 'nm-online status: %s\n' "$?"
nm-online status: 1
You will get 0 instead if a connection is already active. That still tests the command, it just does not exercise the timeout branch.
4. Understand the timeout setting
--timeout takes seconds. Omit it and nm-online honours the NM_ONLINE_TIMEOUT environment variable, then falls back to 30 seconds. A command-line value reads more clearly in a script because it sits right beside the check:
$ NM_ONLINE_TIMEOUT=2 nm-online --quiet
$ printf 'status: %s\n' "$?"
status: 1
That environment assignment affects only this one invocation. It does not change NetworkManager's configuration and does not persist after the shell command finishes. Do not set a huge timeout just to hide a disconnected host: a job that needs a usable network should also handle DNS, routing and the remote service failing after this check already passed.
5. Use startup mode only for boot ordering
--wait-for-startup, or -s, answers a different question entirely. It waits for NetworkManager startup to finish, after it has activated or attempted to activate the available auto-activate connections. It does not prove the network is connected right now. Once startup has finished, nm-online -s can return immediately even if the network later drops:
$ nm-online --wait-for-startup --quiet --timeout=30
$ printf 'startup status: %s\n' "$?"
startup status: 0
Use this mode for coordinating boot-time ordering, and the default mode for a command that needs an active connection right now. Mixing the two up is a common trap: a successful startup check is not a connectivity guarantee.
This command backs NetworkManager-wait-online.service with --wait-for-startup. If a boot target is taking too long, investigate that service and the connection profiles rather than bolting an unbounded nm-online call onto an unrelated script.
6. Know what online means here
nm-online asks NetworkManager about its own status. It does not make an HTTP request, resolve a hostname, or verify an application endpoint is reachable. Treat status 0 as "NetworkManager has an active connection", not as proof that an external service will accept the next request.
By default, NetworkManager can consider a connection activated once either IPv4 or IPv6 completes, because both ipv4.may-fail and ipv6.may-fail normally allow the other family to fail. If a boot workflow needs one address family specifically, configure that connection's matching may-fail property deliberately. That is a persistent configuration change, not a diagnostic one, so do not make it as a side effect of a check, and do not reach for sudo until you know exactly which profile should change.
7. Diagnose a failed check safely
- Rerun with
--quietand record the exit status immediately. - Ask NetworkManager directly.
nmcli general statusandnmcli connection show --activeare read-only diagnostics. - Check the timeout is realistic. Only lengthen it when the delay is expected and bounded.
- Test the real dependency separately, such as DNS or the remote endpoint. A successful
nm-onlineresult does not stand in for that test.
If NetworkManager itself is not running or is still connecting, --exit returns immediately instead of waiting. Use it when a caller needs a fast status check and has its own retry or recovery logic:
$ nm-online --exit --quiet
$ printf 'immediate status: %s\n' "$?"
immediate status: 1
There is no undo for anything in this guide: every command here either reads state or sets an environment variable for one process. Leave connection-profile edits and service restarts to a separate, reviewed change.
Done means
- Verified the installed
nm-onlineand NetworkManager versions. - Script checks the exit status, with a finite timeout and a clear failure path.
- Can tell apart an active connection from NetworkManager startup completion.
- Know that status 0 does not test DNS, routing or a particular remote service.
- Changed nothing persistent: no profile, service state or configuration was touched.