Deployment
pydhcp is a pure-Python library, so deployment is mostly about running it with the right permissions and network layout. Packet parsing and structured packet tooling are portable; DHCP serving depends on the host OS allowing the needed UDP binds and broadcasts.
Production checklist
- Run the server under a dedicated service account.
- Make sure the host can bind the DHCP ports you expect to use.
- Confirm the selected interface has the address range you want to serve.
- Pass
--lease-file /var/lib/pydhcp/leases.jsonif you need stable client assignment across restarts. Without it the server keeps leases in memory only, and every client renumbers when the process restarts. - Implement address-pool policy in a
DHCPServersubclass or custom lease backend before serving a real network.
The built-in server is a base implementation, not a full IPAM system. It is useful for simple deployments, tests, and custom services, but production pools, reservations, and site policy should live in your own subclass or backend.
systemd
For Linux services, run the server from a unit that starts the CLI entry point directly.
[Unit]
Description=pydhcp server
After=network-online.target
[Service]
ExecStart=/opt/pydhcp/.venv/bin/pydhcp --config /etc/pydhcp/server.toml server
Restart=on-failure
User=pydhcp
Group=pydhcp
[Install]
WantedBy=multi-user.target
The CLI accepts JSON, TOML, YAML and INI settings files through --config (before the command name) or PYDHCP_CONFIG (TOML needs Python 3.11+ or duho[config], YAML duho[yaml]). The file is always named: there is no default location, so a daemon never starts from a file nobody chose. A setting comes from the option, else its PYDHCP_<COMMAND>_<OPTION> environment variable, else the file, else the default, so an explicit --listen overrides whatever the file says. A file with a misspelled or foreign section, an unknown key or a syntax error stops the service with status 2 and one line naming the file and the position, instead of starting on the defaults.
Port 67 is privileged: run the unit as root, or grant the interpreter the capability once with
sudo setcap 'cap_net_bind_service=+ep' /opt/pydhcp/.venv/bin/python3 and keep User=pydhcp. Without one of the two the service fails to bind, which pydhcp reports as a PermissionError naming the port.
Docker
The server can also run inside a container if the container is allowed to bind the needed UDP ports and see the host network.
- Prefer host networking for real DHCP service.
- Mount configuration and lease storage explicitly, and point
--lease-fileat the mounted path — a mounted volume stays empty unless the server is told to write to it. - Keep logs on stdout/stderr so orchestrators can collect them.
Operational notes
- Use the CLI
interfacescommand to confirm interface detection before serving traffic. - If you are debugging packet flow, raise the level (
-v, repeatable, or--loglevel pydhcp:DEBUG) and look for the transaction ID — every packet line carries[XID=...]. Components log underpydhcp.<module>, so--loglevel pydhcp.listener:DEBUGnarrows it to the receive path. - After a restart, check the lease file is being written:
FileLeaseBackendrewrites it on every mutation by default, and a deployment that raisesSAVE_INTERVAL_SECONDSto coalesce writes trades up to one interval of leases on a crash.