DHCP#
Services → DHCP, at /dhcp. It owns service dhcp-server and, through its other
tabs, service dhcp-relay, service router-advert and service dhcpv6-server. Four
tabs: IPv4, Relay, IPv6 and CLI.
This page documents the IPv4 tab. Relay and IPv6 have pages of their own.
The IPv4 tab shows three things stacked: one panel per configured subnet, the static reservations as a table with an editor, and the live lease table. The reservations and the leases are joined, so a reservation that has never actually been used is visible as such.
Where the data comes from#
| Call | Polled | Returns |
|---|---|---|
GET /api/dhcp/reservations | on load and after each commit | the whole service dhcp-server configuration subtree |
GET /api/dhcp/leases | every 10 s | show dhcp server leases, parsed into rows, plus the raw text |
GET /api/config/commands?path=service dhcp-server | on load and after each commit | the subtree as commands, for the CLI tab |
The endpoint is named for reservations and returns the entire server subtree; the page
derives both the subnet panels and the reservation table from it —
agent/main.go (handleDhcpReservations),
agent/opmode.go (handleDhcpLeasesFixed).
The shape of the configuration#
VyOS nests the DHCP server two levels deep, and every command on this page reflects it:
service dhcp-server
shared-network-name <NETWORK>
subnet <CIDR>
lease <seconds>
range <id> start <address>
range <id> stop <address>
option default-router <address>
option name-server <address>
static-mapping <NAME>
ip-address <address>
mac <address>A shared network is a container with a name of your choosing; a subnet under it is the prefix being served. Most routers have one shared network per segment and one subnet in it. The page reads every subnet of every shared network.
The subnet panels#
One panel per subnet, titled <shared network> · <subnet>, each listing:
| Field | Read from |
|---|---|
| Lease time | lease, shown in seconds |
| Pools | every range as start – stop, comma separated |
| Reservations | the number of static-mapping entries in this subnet |
| (further rows) | every key under option, with its value |
The option rows are printed verbatim from the configuration, so whatever the subnet sets
— default-router, name-server, domain-name, ntp-server — appears with the name
VyOS uses for it.
The reservation table#
| Column | Read from |
|---|---|
| Hostname | the static-mapping tag name |
| IP address | ip-address |
| MAC | mac, falling back to mac-address |
| Subnet | the subnet the mapping lives in |
| Per-host options | the names of the keys under this mapping's option, or — |
| Lease | active when the live lease table holds a lease for this address |
The Lease column is the join. A reservation with no active badge is one no host has ever taken up — a typo in the MAC, a device that has not booted, or a mapping for a machine that has left.
The reservations table shares the Filter box with the lease table below it, so typing a MAC prefix narrows both at once.
The mapping name is the key in the configuration tree, so it has to be unique within its subnet and it is what a delete refers to. It is also, on most bases, what the DHCP server offers back as the host name.
Editing a reservation#
Clicking a row opens a side panel showing the shared network, subnet, address, MAC and option names, with two editable fields. Each stages one command:
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/16 static-mapping nas ip-address 10.0.2.10
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/16 static-mapping nas mac aa:bb:cc:dd:ee:ffDelete reservation stages the whole mapping:
delete service dhcp-server shared-network-name LAN subnet 10.0.0.0/16 static-mapping nasRenaming a reservation, moving it to another subnet, or giving it per-host options is not possible here — delete it and add it again, or use the CLI.
Adding a reservation#
+ Add reservation asks for four things, all required:
| Field | Hint |
|---|---|
| Subnet | a menu of every subnet the configuration declares |
| Hostname | becomes the mapping name in the config tree |
| IP address | must sit inside the subnet, ideally outside the pool |
| MAC address | — |
It stages exactly two commands:
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/16 static-mapping nas ip-address 10.0.2.10
set service dhcp-server shared-network-name LAN subnet 10.0.0.0/16 static-mapping nas mac aa:bb:cc:dd:ee:ffWith no subnets configured the menu is empty and nothing can be staged. Create the subnet first, from the CLI.
The live lease table#
show dhcp server leases, parsed on the column offsets the router printed. The columns
are the router's own headings:
| Column | What it is |
|---|---|
| IP address | the leased address |
| MAC | the client that holds it |
| Hostname | the name the client sent, when it sent one |
| State | active shows a green badge; anything else is grey |
| Remaining | how long the lease has left |
| Pool | which shared network it came from |
| Origin | how the lease was made |
An empty table is not an error — the empty state says No client has requested an address
yet and gives you show dhcp server leases to run yourself.
There are no buttons on this table. A lease cannot be released or deleted from this page, and there is no "convert this lease to a reservation" action: to pin an address, read the MAC here and type it into + Add reservation.
What breaks if you get it wrong#
- A reservation inside the pool range. Most servers cope, some hand the address to
another client first and then refuse the reservation. Put reservations outside every
range, which is what the field hint says. - A reservation outside its subnet. The commit succeeds and the server never offers the address.
- A duplicated address across two reservations. Nothing on this page checks. Two hosts get the same address at different times and the fault looks intermittent.
- A pool that overlaps a virtual address. A VRRP virtual address handed to a laptop is a bad afternoon. Keep them out of every range — see VRRP.
- A relay and a server on the same interface. They cannot share one; the relay tab says so — see DHCP relay.
- Deleting a subnet that has reservations under it. The reservations go with it. The commands are visible in the diff before you commit.
Worked example: pin the NAS to a fixed address#
The NAS currently has a lease of 10.0.1.87. It should be 10.0.2.10, which is outside
the pool.
- Services → DHCP, IPv4 tab. Find the NAS in the Live leases table and copy its MAC.
- + Add reservation. Subnet
LAN · 10.0.0.0/16, hostnamenas, IP address10.0.2.10, MAC from step 1. - The Commands block shows the two
setlines. Stage reservation. - Commit.
isDangerousPathmatches any path containing the wordaddress, andip-addresscounts, so the Commit Bar offers commit-confirm for this set as well. - The reservation appears in the table with no active badge, because the NAS still holds its old lease.
- Make the NAS renew — reboot it, or bounce its interface. Within a poll or two the
reservation shows active and the lease table shows
10.0.2.10.
Step 6 is the part people skip. A reservation does not move a host that already has a lease; the host keeps its address until the lease expires or it asks again.
App integrations#
Installed apps can offer configuration for this page — a DNS or ad-filtering container
suggesting itself as the subnet's name-server, for instance. The offers appear between
the page header and the tabs, and only when an app that declares a hint for the dhcp
page is installed. An offer may carry placeholders — the shared-network name and the
subnet among them — which are filled from this router's own configuration before the
offer is shown; the full list is on
Integration offers.
See also#
- DHCP relay — forwarding requests to a server somewhere else.
- DHCP and IPv6 — router advertisements and DHCPv6.
- DNS — the resolver whose address the pool usually hands out.
- Neighbours — the other list of who is on the segment.
- Addressing — the router's own address on the subnet being served.
Checked against ui/src/pages/Dhcp.tsx,
agent/main.go (handleDhcpReservations),
agent/opmode.go (handleDhcpLeasesFixed),
agent/parse.go (parseTable),
agent/apps.go (hintsForPage),
ui/src/lib/api.ts.