Install FRR, addresses and forwarding
Debian 13 ships FRR 10.3 in its own repository, so installing it is one command: apt install frr. (FRR also publishes newer releases in its own Debian repository; the configuration in this lesson works on both.)
What you get straight after installing
The frr service is enabled and running, but it isn't routing anything yet. systemctl status shows what's running: watchfrr, which starts the other daemons and restarts any that crash; zebra, which owns the kernel's routing table and interfaces on FRR's behalf; mgmtd, the configuration manager; and staticd for static routes. Each routing protocol is a separate daemon, and every one of them is off in /etc/frr/daemons. You turn on only the ones you use.
Addresses and forwarding
FRR doesn't need to own the interface addresses. On Debian, systemd-networkd is a good way to set them: one small .network file per interface, read at boot. The router also gets a loopback address for its router IDs. A real Debian install already has udev, which networkd waits for; minimal container images don't, and there every link sits in pending until you install it.
The machine must also be allowed to route. Debian ships with IP forwarding off, and the lab's container starts that way too; a file in /etc/sysctl.d/ turns it on now and at every boot.
root@edge:~# cat /etc/debian_version; dpkg-query -W frr nftables systemd; uname -r
13.7
frr 10.3-3+deb13u1
nftables 1.1.3-1
systemd 257.13-1~deb13u1
7.0.14-linuxkit- Line 3: FRR 10.3, straight from Debian 13's own repository.
- Line 5: systemd 257: networkd sets the addresses, and services start the router at boot.
root@edge:~# systemctl status frr --no-pager | head -17
● frr.service - FRRouting
Loaded: loaded (/usr/lib/systemd/system/frr.service; enabled; preset: enabled)
Active: active (running) since Wed 2026-11-04 22:02:01 UTC; 16s ago
Invocation: 6cb8de65d13345c89e10cdd043cf15e3
Docs: https://frrouting.readthedocs.io/en/latest/setup.html
Process: 135 ExecStart=/usr/lib/frr/frrinit.sh start (code=exited, status=0/SUCCESS)
Main PID: 146 (watchfrr)
Status: "FRR Operational"
Tasks: 8 (limit: 9562)
Memory: 19M (peak: 35.3M)
CPU: 130ms
CGroup: /docker/68dabd70d05c7d5877f2dde6ce7bac3e44adce867fa60f2035d700237fbdaeae/system.slice/frr.service
├─146 /usr/lib/frr/watchfrr -d -F traditional zebra mgmtd staticd
├─156 /usr/lib/frr/zebra -d -F traditional -A 127.0.0.1 -s 90000000
├─161 /usr/lib/frr/mgmtd -d -F traditional -A 127.0.0.1
└─163 /usr/lib/frr/staticd -d -F traditional -A 127.0.0.1
root@edge:~# grep -E "^[a-z0-9]+d=" /etc/frr/daemons
bgpd=no
ospfd=no
ospf6d=no
ripd=no
ripngd=no
isisd=no
pimd=no
pim6d=no
ldpd=no
nhrpd=no
eigrpd=no
babeld=no
sharpd=no
pbrd=no
bfdd=no
fabricd=no
vrrpd=no
pathd=no- Line 3: Enabled and running from the moment it's installed…
- Lines 14–17: …but only watchfrr, zebra, mgmtd and staticd. No routing protocol yet.
- Lines 21–38: Every routing daemon is off until you turn it on.
# /etc/systemd/network/10-isp1.network: the link to ISP 1 (primary).
[Match]
Name=eth0
[Network]
Address=192.0.2.1/31
LinkLocalAddressing=no
IPv6AcceptRA=no- Lines 2–3: Matches the interface by name.
- Lines 6–8: A fixed address on the /31 link to ISP 1, and no IPv6 on this link.
# /etc/systemd/network/11-isp2.network: the link to ISP 2 (backup).
[Match]
Name=eth1
[Network]
Address=192.0.2.3/31
LinkLocalAddressing=no
IPv6AcceptRA=no# /etc/systemd/network/12-core.network: the link to the office's core router.
[Match]
Name=eth2
[Network]
Address=10.0.0.1/30
LinkLocalAddressing=no
IPv6AcceptRA=no# /etc/systemd/network/13-lo.network: a loopback address for the router ID.
[Match]
Name=lo
[Network]
Address=10.255.0.1/32- Line 6: A loopback address, used as the BGP and OSPF router ID.
# /etc/sysctl.d/99-forwarding.conf: this machine is a router.
net.ipv4.ip_forward = 1root@edge:~# ls /etc/systemd/network/ && systemctl enable --now systemd-networkd 2>&1 | grep -c "Created symlink"
10-isp1.network
11-isp2.network
12-core.network
13-lo.network
5
root@edge:~# networkctl list --no-pager | grep -E "IDX|eth|lo "; ip -br -4 addr
IDX LINK TYPE OPERATIONAL SETUP
1 lo loopback routable configured
4 gretap0 ether off unmanaged
5 erspan0 ether off unmanaged
11 eth2 ether routable configured
12 eth0 ether routable configured
13 eth1 ether routable configured
lo UNKNOWN 127.0.0.1/8 10.255.0.1/32
eth2@if5311 UP 10.0.0.1/30
eth0@if5312 UP 192.0.2.1/31
eth1@if5313 UP 192.0.2.3/31
root@edge:~# sysctl net.ipv4.ip_forward; sysctl --system | grep ip_forward
net.ipv4.ip_forward = 0
net.ipv4.ip_forward = 1
root@edge:~# ping -c 1 -W 1 192.0.2.0 | tail -2; ping -c 1 -W 1 192.0.2.2 | tail -2; ping -c 1 -W 1 10.0.0.2 | tail -2
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.071/0.071/0.071/0.000 ms
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.047/0.047/0.047/0.000 ms
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.062/0.062/0.062/0.000 ms- Lines 1–6: Four files, one per interface, and networkd enabled at every boot.
- Lines 9–15: Every link
configured: networkd applied the files. - Lines 16–19: The addresses, including the router ID on the loopback.
- Lines 21–23: Forwarding was off, as on a fresh install; the sysctl.d file turns it on.
- Lines 25–31: Both ISPs and the core router answer.
Check your understanding
Right after apt install frr, why doesn't the router speak BGP yet?
- bgpd is off in /etc/frr/daemons until you turn it on.
- The frr service is disabled until you enable it.
- BGP needs a licence key.
- Debian's FRR doesn't include BGP.