| |

LFCE 15 ๐Ÿง Static Routes โ€” Configuration

โฑ๏ธ Estimated read: 13 min | |

Configuration is where static routing theory becomes kernel state. The previous chapter established why static routes exist and how the kernel selects them by longest prefix match. This chapter is the operational counterpart: the exact commands to add, verify, replace, and remove routes, the flags that handle gateways outside connected subnets, and the persistence mechanisms that survive a reboot. Every command here modifies the running kernel immediately, but none of them persist by default. The gap between a route that works in a lab session and a route that works after a production restart is the central concern of this chapter.

Key point: ip route add creates a route in the running kernel only. Reboot removes it. Persistence requires the distribution’s network managerโ€”Netplan on Ubuntu, nmcli on RHEL and NetworkManager-managed systems, or systemd-networkdโ€”and the persistent configuration must be verified separately from the running configuration.


Why configuration is a separate discipline from concepts

The immediate-versus-persistent problem.

The ip route add command is satisfying because it works instantly. The route appears in ip route show, and ip route get confirms the kernel selects it. This immediate feedback creates a false sense of completion. The route exists in volatile kernel memory, not in any configuration file. A reboot, a network service restart, or a systemctl restart NetworkManager can erase it without warning. Production configuration requires two separate operations: add the route to the running kernel for immediate effect, and write it to the persistent configuration for survival. The two must produce the same result, and the persistent configuration must be tested by rebooting or restarting the network service, not by inspecting the file.

The gateway reachability problem.

The kernel validates that a gateway is reachable before accepting a route through it. If the gateway address does not fall within a directly connected subnet, ip route add fails with “Nexthop has invalid gateway” or “Network is unreachable.” This validation prevents routes that point to nonexistent gateways, but it blocks legitimate configurations: VPN tunnels where the gateway is inside the tunnel, dummy interfaces used for testing, and point-to-point links where the neighbor address is outside the configured subnet. The onlink flag overrides the validation, telling the kernel to trust the administrator’s assertion that the gateway is reachable through the specified interface .

The verification problem.

A route in the table is not proof that traffic flows. The kernel might select a different route due to a longer prefix, the gateway might be unreachable at layer 2, or a firewall might drop the forwarded packets. Configuration is complete only when ip route get shows the intended route and an actual packetโ€”a ping or tracerouteโ€”confirms delivery. The commands in this chapter modify state; the verification commands confirm that the modification achieved its purpose.


a. Adding and verifying routes

The ip route add command is the primary tool for creating static routes. It accepts a destination prefix, a gateway (via), an outgoing interface (dev), or both .

# Add a route to a remote network through a gateway
ip route add 192.168.2.0/24 via 10.0.0.1

# Add a route through an interface without a gateway
ip route add 192.168.2.0/24 dev eth0

# Add a route specifying both gateway and interface
ip route add 192.168.2.0/24 via 10.0.0.1 dev eth0

# Add a host route for a single destination
ip route add 10.10.10.1/32 via 192.168.1.1

The via keyword is used when the destination is not directly connected and must be reached through a next-hop router. The dev keyword specifies the interface. When both are present, the kernel sends the packet out the named interface to the gateway’s MAC address. When only dev is specified, the kernel treats the destination as directly reachable on that link, which is appropriate for point-to-point links .

# Verify the route was added
ip route show 192.168.2.0/24
# Output: 192.168.2.0/24 via 10.0.0.1 dev eth0

# Ask the kernel which route it will use for a specific destination
ip route get 192.168.2.100
# Output: 192.168.2.100 via 10.0.0.1 dev eth0 src 10.0.0.2 uid 0

ip route get is the definitive verification. It shows the selected route, the outgoing interface, and the source address the kernel will use. A route that exists in the table but is not selected for the intended destination is not functioning as configured .


b. Replacing, deleting, and handling special cases

The add command fails if an identical route already exists. The replace command creates the route if absent and overwrites it if present, avoiding the “File exists” error .

# Replace an existing route without deleting it first
ip route replace 192.168.2.0/24 via 10.0.0.2

# Delete a route
ip route del 192.168.2.0/24

# Delete a route with a specific gateway when multiple routes share the prefix
ip route del 192.168.2.0/24 via 10.0.0.1

The onlink flag is required when the gateway is not reachable through a connected route. Without it, the kernel rejects the route .

# Add a route where the gateway is only reachable through the interface
# The onlink flag bypasses the gateway reachability check
ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink

This configuration is common in lab environments using dummy interfaces, in VPN scenarios where the gateway is inside the tunnel, and in point-to-point links where the neighbor address does not fall within the configured subnet. The kernel normally validates that the gateway is on a directly connected subnet; onlink tells it to accept the administrator’s assertion that the gateway is reachable through the interface.

The metric field influences route selection when multiple routes match the same prefix. A lower metric is preferred. NetworkManager assigns default metrics based on connection type: Ethernet is preferred over Wi-Fi, which is preferred over WWAN .


c. Persistence across reboots

Routes added with ip route are lost on reboot. Persistence depends on the distribution’s network management system. The three most common mechanisms are Netplan on Ubuntu, nmcli on RHEL and NetworkManager-managed systems, and systemd-networkd.

# Ubuntu / Netplan: edit or create a YAML file under /etc/netplan/
# network:
#   version: 2
#   ethernets:
#     eth0:
#       routes:
#         - to: 192.168.2.0/24
#           via: 10.0.0.1
# Apply with:
netplan apply

The Netplan configuration nests the route under the interface definition. The to field is the destination prefix, and via is the gateway. The netplan apply command applies the configuration to the running system; the configuration is automatically applied at boot by the backend network manager .

# RHEL / NetworkManager: add the route to the connection profile
nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"

# Reactivate the connection to apply the change
nmcli connection up "eth0"

The + modifier appends the route to the existing list. Without it, ipv4.routes replaces the entire route list . The connection must be reactivated for the change to take effect on the running interface. The connection profile IDโ€”not necessarily the interface nameโ€”is the target of the modify command .

# systemd-networkd: add a [Route] section to the .network file
# [Route]
# Destination=192.168.2.0/24
# Gateway=10.0.0.1

# Restart the service to apply
systemctl restart systemd-networkd

For any persistence method, the running configuration and the persistent configuration must be verified independently. ip route show confirms the running state. The persistent state is verified by rebooting or restarting the network service and checking that the route reappears.


Complete Example Session

# ============================================
# PART 1: INSPECT THE CURRENT ROUTING TABLE
# ============================================
# Before adding a route, understand the existing paths
ip route show
# Output shows the default route and connected networks

# ============================================
# PART 2: CHECK THE CURRENT PATH FOR A DESTINATION
# ============================================
ip route get 203.0.113.10
# Before the static route, this follows the default route

# ============================================
# PART 3: CREATE A DUMMY INTERFACE FOR TESTING
# ============================================
# A dummy interface provides a safe local interface without altering the real network path
ip link add lfcsroute0 type dummy
ip addr add 198.51.100.1/24 dev lfcsroute0
ip link set lfcsroute0 up
ip -brief address show lfcsroute0
# Output: lfcsroute0 UP 198.51.100.1/24

# ============================================
# PART 4: ADD THE STATIC ROUTE WITH ONLINK
# ============================================
# The gateway is in the dummy interface's subnet but no real neighbor exists
# The onlink flag tells the kernel to accept the gateway anyway
ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink

# ============================================
# PART 5: VERIFY THE ROUTE EXISTS
# ============================================
ip route show 203.0.113.0/24
# Output: 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0

# ============================================
# PART 6: VERIFY THE KERNEL SELECTS THE ROUTE
# ============================================
ip route get 203.0.113.10
# Output: 203.0.113.10 via 198.51.100.254 dev lfcsroute0
# The static route is selected instead of the default route

# ============================================
# PART 7: TEST A DESTINATION OUTSIDE THE ROUTE
# ============================================
ip route get 8.8.8.8
# Output: 8.8.8.8 via <default-gateway> dev eth0
# The default route is still used for other destinations

# ============================================
# PART 8: REPLACE THE ROUTE
# ============================================
# Change the gateway without deleting and re-adding
ip route replace 203.0.113.0/24 via 198.51.100.253 dev lfcsroute0 onlink
ip route get 203.0.113.10
# Output confirms the new gateway is selected

# ============================================
# PART 9: DELETE THE ROUTE
# ============================================
ip route del 203.0.113.0/24
ip route get 203.0.113.10
# Output reverts to the default route

# ============================================
# PART 10: PERSIST THE CONFIGURATION
# ============================================
# On a NetworkManager system, add the route to the connection profile
nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"
nmcli connection up "eth0"
# Verify the route survives a connection restart
ip route show 192.168.2.0/24

The ten parts demonstrate the complete lifecycle: inspect, test, add with onlink, verify selection, replace, delete, and persist. The critical verification steps are Part 6 (ip route get confirms selection) and Part 10 (the persistent configuration produces the same running state after reactivation).


Quick Reference

Route Configuration Commands

TaskCommand
Add route via gatewayip route add <net>/<prefix> via <gw>
Add route via interfaceip route add <net>/<prefix> dev <if>
Add route with bothip route add <net>/<prefix> via <gw> dev <if>
Add with onlink... dev <if> onlink
Replace routeip route replace <net>/<prefix> via <gw>
Delete routeip route del <net>/<prefix>
Show routesip route show
Verify selectionip route get <dest>

Persistence Methods

SystemConfiguration MethodApply Command
Ubuntu/NetplanYAML routes: under interfacenetplan apply
RHEL/NMnmcli connection modify +ipv4.routesnmcli connection up
systemd-networkd[Route] in .network filesystemctl restart systemd-networkd

Key Flags

FlagPurpose
viaGateway for the route
devOutgoing interface
onlinkAccept gateway outside connected subnet
metricRoute preference; lower wins

Best Practices

โœ… Do This:

# Verify the current path before adding a route
ip route get <dest>                                          # โœ…

# Use onlink when the gateway is not on a connected subnet
ip route add <net> via <gw> dev <if> onlink                  # โœ…

# Use replace when the route may already exist
ip route replace <net> via <gw>                              # โœ…

# Persist through the distribution's network manager
nmcli connection modify "eth0" +ipv4.routes "..."            # โœ…

# Reactivate the connection after nmcli changes
nmcli connection up "eth0"                                   # โœ…

# Verify both running state and persistent state
ip route show; reboot; ip route show                         # โœ…

โŒ Don’t Do This:

# Assume a route works because it appears in ip route show
# Verify with ip route get and a ping                           # โŒ

# Use ip route add when the route might exist
# add fails with "File exists"; use replace                     # โŒ

# Omit onlink when the gateway is unreachable
# The kernel rejects the route                                  # โŒ

# Expect ip route add to survive reboot
# It modifies volatile kernel state only                        # โŒ

# Forget to reactivate the connection after nmcli modify
# The change is saved but not applied to the running interface  # โŒ

# Overwrite existing routes without the + modifier in nmcli
# ipv4.routes without + replaces the entire route list          # โŒ

Common Pitfalls

PitfallWhy It HappensFix
“Nexthop has invalid gateway”Gateway not on connected subnetAdd onlink flag
Route lost after rebootip route add is not persistentConfigure through network manager
“File exists” errorRoute already presentUse ip route replace
nmcli change not appliedConnection not reactivatednmcli connection up
nmcli replaced all routesUsed ipv4.routes without +Use +ipv4.routes to append
Route selected but no trafficFirewall or gateway issueCheck ip6tables/iptables and gateway reachability
Persistent config not loadedService not restarted after editnetplan apply or restart service

Real-World Examples

1. Basic route via gateway

ip route add 192.168.2.0/24 via 10.0.0.1

2. Route via interface only

ip route add 192.168.2.0/24 dev eth0

3. Onlink route for dummy interface

ip route add 203.0.113.0/24 via 198.51.100.254 dev lfcsroute0 onlink

4. Host route

ip route add 10.10.10.1/32 via 192.168.1.1

5. Replace an existing route

ip route replace 192.168.2.0/24 via 10.0.0.2

6. Delete a route

ip route del 192.168.2.0/24

7. Verify selection

ip route get 192.168.2.100

8. Persist with nmcli

nmcli connection modify "eth0" +ipv4.routes "192.168.2.0/24 10.0.0.1"
nmcli connection up "eth0"

9. Persist with Netplan

# /etc/netplan/01-routes.yaml
network:
  version: 2
  ethernets:
    eth0:
      routes:
        - to: 192.168.2.0/24
          via: 10.0.0.1

10. Verify persistent route after reboot

ip route show 192.168.2.0/24
# Route should reappear after reboot if persistence is configured correctly

Visual

The Two-Layer Configuration Model

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  RUNNING CONFIGURATION vs PERSISTENT CONFIGURATION           โ”‚
โ”‚                                                              โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ RUNNING KERNEL STATE                                   โ”‚  โ”‚
โ”‚  โ”‚                                                        โ”‚  โ”‚
โ”‚  โ”‚ ip route add 192.168.2.0/24 via 10.0.0.1               โ”‚  โ”‚
โ”‚  โ”‚       โ”‚                                                โ”‚  โ”‚
โ”‚  โ”‚       โ–ผ                                                โ”‚  โ”‚
โ”‚  โ”‚ ip route show โ†’ route appears immediately              โ”‚  โ”‚
โ”‚  โ”‚ ip route get 192.168.2.5 โ†’ route is selected           โ”‚  โ”‚
โ”‚  โ”‚                                                        โ”‚  โ”‚
โ”‚  โ”‚ โš  LOST ON REBOOT                                       โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                           โ”‚                                  โ”‚
โ”‚                           โ”‚ Must match                       โ”‚
โ”‚                           โ–ผ                                  โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ PERSISTENT CONFIGURATION                               โ”‚  โ”‚
โ”‚  โ”‚                                                        โ”‚  โ”‚
โ”‚  โ”‚ Netplan YAML  OR  nmcli connection profile             โ”‚  โ”‚
โ”‚  โ”‚       โ”‚                    โ”‚                           โ”‚  โ”‚
โ”‚  โ”‚       โ–ผ                    โ–ผ                           โ”‚  โ”‚
โ”‚  โ”‚ netplan apply         nmcli connection up              โ”‚  โ”‚
โ”‚  โ”‚       โ”‚                    โ”‚                           โ”‚  โ”‚
โ”‚  โ”‚       โ–ผ                    โ–ผ                           โ”‚  โ”‚
โ”‚  โ”‚ Route applied at boot  Route applied on reactivation   โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  Verification: reboot, then ip route show.                   โ”‚
โ”‚  If the route is absent, persistence failed.                 โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

The onlink Flag Decision

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  WHEN IS onlink REQUIRED?                                    โ”‚
โ”‚                                                              โ”‚
โ”‚  Question: Is the gateway address within a directly          โ”‚
โ”‚  connected subnet?                                           โ”‚
โ”‚                                                              โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ”œโ”€โ”€ YES โ†’ No onlink needed                             โ”‚
โ”‚       โ”‚         ip route add <net> via <gw>                  โ”‚
โ”‚       โ”‚                                                      โ”‚
โ”‚       โ””โ”€โ”€ NO  โ†’ onlink required                              โ”‚
โ”‚                 ip route add <net> via <gw> dev <if> onlink  โ”‚
โ”‚                                                              โ”‚
โ”‚  Examples where onlink is needed:                            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ Dummy interface: gateway address is fictional          โ”‚  โ”‚
โ”‚  โ”‚ VPN tunnel: gateway is inside the tunnel               โ”‚  โ”‚
โ”‚  โ”‚ Point-to-point: neighbor is outside configured subnet  โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                                                              โ”‚
โ”‚  Without onlink, the kernel rejects the route:               โ”‚
โ”‚  "Nexthop has invalid gateway"                               โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

nmcli Route Persistence Flow

โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
โ”‚  nmcli CONNECTION MODIFY AND REACTIVATION                    โ”‚
โ”‚                                                              โ”‚
โ”‚  Step 1: Add route to connection profile                     โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ nmcli connection modify "eth0"                         โ”‚  โ”‚
โ”‚  โ”‚   +ipv4.routes "192.168.2.0/24 10.0.0.1"               โ”‚  โ”‚
โ”‚  โ”‚                                                        โ”‚  โ”‚
โ”‚  โ”‚ The + modifier APPENDS.                                 โ”‚  โ”‚
โ”‚  โ”‚ Without +, ipv4.routes REPLACES all existing routes.   โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                           โ”‚                                  โ”‚
โ”‚                           โ–ผ                                  โ”‚
โ”‚  Step 2: The profile is saved but NOT yet applied            โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ ip route show โ†’ route may NOT appear yet               โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                           โ”‚                                  โ”‚
โ”‚                           โ–ผ                                  โ”‚
โ”‚  Step 3: Reactivate the connection                           โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ nmcli connection up "eth0"                             โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ”‚                           โ”‚                                  โ”‚
โ”‚                           โ–ผ                                  โ”‚
โ”‚  Step 4: Verify                                             โ”‚
โ”‚  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”  โ”‚
โ”‚  โ”‚ ip route show 192.168.2.0/24 โ†’ route appears           โ”‚  โ”‚
โ”‚  โ”‚ Route is now persistent across reboots                 โ”‚  โ”‚
โ”‚  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜  โ”‚
โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜

Summary

ItemValue
Primary commandip route (iproute2)
Add routeip route add <net>/<prefix> via <gw>
Replace routeip route replace
Delete routeip route del
Verify selectionip route get <dest>
onlink flagFor gateways outside connected subnets
Default metric ruleLower metric preferred
Ubuntu persistenceNetplan YAML + netplan apply
RHEL persistencenmcli connection modify +ipv4.routes + connection up
systemd-networkd[Route] in .network file
Volatilityip route add does not persist

Key takeaways:

  • ip route add modifies the running kernel, not the configuration. The route works immediately and disappears on reboot. Persistence is a separate operation through the network manager .
  • onlink is required when the gateway is not on a connected subnet. Without it, the kernel rejects the route with “Nexthop has invalid gateway.” Use it for dummy interfaces, VPN tunnels, and point-to-point links .
  • replace avoids the “File exists” error. When a route might already be present, replace creates it if absent and overwrites it if present. add fails in both cases.
  • ip route get is the verification tool. A route in the table is not necessarily the route selected. ip route get shows the kernel’s actual decision for a specific destination .
  • nmcli requires reactivation. The connection modify command saves the route to the profile but does not apply it to the running interface. connection up applies it .
  • The + modifier in nmcli appends. Without it, ipv4.routes replaces the entire route list, potentially removing routes that were already configured .
  • Persistence must be tested by reboot. A configuration file that looks correct but is not applied at boot is not persistence. The only verification is a reboot followed by ip route show.

Remember: Static route configuration is two operations that must produce one result. The first operation modifies the running kernel: ip route add, ip route replace, or ip route del. The second operation writes the same intent to the persistent configuration: a Netplan YAML file, an nmcli connection profile, or a systemd-networkd .network file. The running operation is verified with ip route get. The persistent operation is verified with a reboot. A route that works in one layer but not the other is half-configured, and the half that disappears on restart is the one that matters least in a lab and most in production.


Was this helpful?


Stop using slow, ad-bloated tool sites! ๐Ÿคฎ

๐Ÿ”Ž Search “KandZ Tools” on Google to use many professional utilities for free.

KandZ.me is the ultimate minimalist hub for:
โœ… Finance (Mortgage, Interest, Inflation)
โœ… Tech (Base64, JSON, Dev Suite, IP)
โœ… Health (BMI, BMR, TDEE)
โœ… Productivity (Timer, Workspace, QR)

โšก๏ธ Fast & Private
๐Ÿ”’ No data leaves your device
๐Ÿ’Ž 100% Free

๐Ÿ”— Use it now: https://tools.kandz.me
๐Ÿ”– Bookmark itโ€”youโ€™ll need it later!