staticDHCPd is an all-Python, RFC 2131-compliant DHCP server, with support for most common DHCP extensions and extensive site-specific customisation.
Work has begun on porting staticDHCPd to Python 3, as 3.0.0
The 3.0.0 branch will need to be tested; the remaining checklist follows (if you test a thing, respond to issue #89):
- staticDHCPd
- Long-term soak-test
- Stable memory usage
- memory may fluctuate a bit during operation, but it cannot grow indefinitely, regardless of network size
- if possible, give it a week in a moderately busy network and check in a couple of times each day, sharing your numbers
- No processing errors
- no unusual or inexplicable behaviour
- all errors must be handled sensibly
- Stable memory usage
- Databases
- custom
- I will be verifying its functionality
- custom
- Long-term soak-test
- Extensions
- statistics graph
- reimplemented browser-side using Chart.js
- needs to be tested in a non-lab context
- reimplemented browser-side using Chart.js
- dynamism
- must handle dynamic allocation
- must honour renewals and rebinds with the same address
- must support releases
- redis (static)
- it needs to work work
- redis (dynamic)
- it needs to work work
- statistics graph
- Documentation
- libpydhcpserver
- correctness check
- proofreading
- staticDHCPd
- correctness check
- proofreading
- libpydhcpserver
At this point, no new features will be added until the system is stable (but please submit ideas to the issue-tracker anyway). Any non-bugfix commits will be things to prepare for the Debian/RPM packages or minor formatting tweaks.
staticDHCPd is appropriate for a very wide range of applications. In particular, it's an excellent choice for the following:
- Sites with a need to centrally manage a potentially vast number of clients, all of which are known
- staticDHCPd was originally developed to meet the needs of a growing ISP, with relays and multiple subnets
- LAN parties
- You can use the dynamic module to assign guest leases, have people connect log in to a registration page, which provisions a static assignment, and then let them plug into the real network; you can have staticDHCPd do the layer-2-to-layer-3 bridging for the website with just a few lines of code, so your users don't need to check any addresses on their own
- Research and testing labs
- Simple setup and configuration, even for network-based booting (PXE, TFTP), so you can focus on what matters, not esoteric syntax and troubleshooting
- Home or small office environments where you'll have an always-on server
- All of the important stuff can be static, so you can quickly spot irregularities with device auto-configuration, while still offering a dynamic network for guests
- This is especially helpful for laptops that provide services, where you need to be able to auto-configure when you're out somewhere, but want everything to "just work" when you get home, without needing to change from DHCP to static addressing
- Any situation in which you've ever thought "this would be so much easier if only I could control this one thing"
- staticDHCPd has extensive scripting support
- It also lets you customise pretty much everything that a client sees
- And you can tie it into any database imaginable
On the other hand, it's the wrong choice in the following cases:
- Your environment is entirely dynamic
- Consider the ISC's server for this
- Your environment is large and mostly dynamic, with need for only a few static assignments
- Again, the ISC's server is a good choice
- You already have a solution that works well for your needs
- Why are you considering alternatives?
- Your employer won't let you run anything without an SLA
- You're probably looking for solutions in the wrong place
- You actually want to have a hard time upgrading from one version to the next
- staticDHCPd will let you take your config file and custom code from version 1.0 and drop it into 2.0 or 3.0 with no changes required, even though the codebase running it is entirely different
- The concept of a feature-rich server running with a 4MB footprint scares you
If you think it might be a good match for your needs, take a look at its five-minute quick-start guide.
staticDHCPd was originally created for an ISP, which, as you can imagine, requires that its provisioning tools offer full control over which MACs are allowed to learn about and gain access to its network. It was also necessary that the database of authorised clients be updatable with no delay and that it could be easily linked to other systems to streamline the provisioning process, both of which were factors in excluding the ISC's server as a candidate.
Its name comes from these circumstances, in which the only thing required of the system was that it could serve static "leases" and do it well. That's no longer the case, though, since it's matured quite a bit and picked up enough scriptable flexibility that dropping in a module to handle dynamic allocation can be done with five lines of customisation code (which is given its own, out-of-the-core-codebase home), only one of which is truly site-dependent.
Internally, staticDHCPd makes use of a forked version of Mathieu Ignacio's pydhcplib (though few traces of its ancestry remain) and is developed against Debian-based GNU/Linux distributions and has been shown to operate on FreeBSD and Apple Mac OS X, for which it was originally created. It should run on any Unix variant without issue, but is not supported on Microsoft Windows, due to a lack of familiarity with permissions, sockets, and signals on that platform (a patch would be welcome, but must be accompanied by a commitment of maintenance).
A rich, fully customisable and extensible web-management console is included (and reasonably secure, through optional use of DIGEST authentication), intended to make life easy for NOC staff or curious administrators. It, a statistics engine, and a host of other features are all optional and lazily loaded, so your server will never be unnecessarily bloated.
Comprehensive logging and reporting systems are built-in, from standard things like self-rotating files to in-memory web-dashboard reporting to Atom feeds for keeping an eye on the server while you stay up to date with the news to e-mail notification for emergencies.
All features tested against the ISC's dhclient and dhcrelay to ensure compatibility with the DHCP protocol in realistic contexts. Furthermore, its developer uses it for practical purposes: a single home server manages multiple networks, containing various consumer electronics (phones, tablets, game consoles, printers), dedicated servers, laptops, desktops, and guest devices.
All documentation found outside of the following resources is pre-2.0.0 and should be considered deprecated.
3.0.x is largely identical to 2.0.x, with the exception of any errata noted below.
libpydhcpserver: http://static.uguu.ca/projects/libpydhcpserver/doc/
staticDHCPd: http://static.uguu.ca/projects/staticDHCPd/doc/
- Owing to conflicts with Python's standard library and changes to how import-semantics work, extensions now live in
/etc/staticDHCPd/staticDHCPd_extensions
- To migrate, move any existing extensions from
/etc/staticDHCPd/extensions/
and change the correspondingimport
lines inconf.py
to beimport staticDHCPd_extensions.<extension>
- No other changes should be needed in the common case
- To migrate, move any existing extensions from
Stable releases of staticDHCPd are available from the releases page.
Debian packages for 3.0.x will be published as it approaches release.
The README contains a quick-start guide. It will walk you through creating a simple configuration database and running staticDHCPd without making any changes to your server.
Just run sudo sh install.sh
, or whatever equivalent is appropriate for your platform, and everything will be where it needs to go. You'll also receive some helpful (disclaimer: only as helpful as its users) text that will explain how to make the server run automatically on boot, specific to your platform.
You'll find a sample configuration file in /etc/staticDHCPd/
; copy it to the same directory, without the .sample
suffix, and you're ready for the next step. (If you're upgrading, just leave your old file alone; it'll work just fine)
The makedebs.sh
script will produce Debian packages, a path that is regularly tested and used in the development process.
With each stable release, these will be provided as official artifacts.
If you are on another OS, fpm
is available to generate packages.
With suitable assembly packages installed (such as rpm
to get access to rpmbuild
on Debian), these can be converted well-enough:
fpm -s deb -t rpm staticdhcpd_3.0.0_all.deb
fpm -s deb -t rpm python3-libpydhcpserver_3.0.0_all.deb
Additionally, packages can be built directly from source:
fpm -s python -t rpm staticDHCPd/
fpm -s python -t rpm libpydhcpserver/
These packages are functional and target deployment within /usr/local
, as they should, but are specific to the verion of Python running on the source system, potentially limiting portability.
No development bandwidth exists to support packages built in this manner, but they should generally work.
While SQLite or INI-files are fine for home users and small labs, most environments will want to use a multi-client database service, to allow for runtime updates. Full details on how to configure staticDHCPd to speak with a server, and many more options, are described in the configuration guide in the doc
directory.
For the server itself, specific schema-structuring is required, for which scripts and examples can be found in the samples
directory.
Additionally, some database engines require additional packages:
- Postgres support requires installation of the psycopg3 library (python3-psycopg3)
- Oracle support requires installation (and possibly compilation) of the python-oracledb library
- MySQL/MariaDB support requires installation of the MySQLdb library (python3-mysqldb)
- Connection-pooling requires eventlet (python3-eventlet)
While you're at it, you should also install python3-scapy if you intend to use dynamic provisioning. It'll allow your network to serve as a living database for reconstructing leases after a server restart. These libraries aren't necessary, though: the associated components will function in a limited capacity if they're absent.
Once everything's configured, you can launch the daemon with sudo staticDHCPd
. You'll need to start it with superuser permissions (or, better, CAP_NET_BIND_SERVICE
) because it needs to bind to restricted ports, but it'll switch to whatever permissions you specified in the config file once setup is complete.
If you're using caching (or INI) with your database, you can send SIGHUP to the process to cause it to reinitialise, clearing the cache (or re-reading the file), and invoking the reinitialisation behaviour of any custom modules that subscribe to the event. You can also, if enabled, access this functionality from the web interface.
To kill the server, you can ^C it in non-daemon mode, or send SIGTERM otherwise. It'll go down gracefully.
staticDHCPd is available under the GPLv3. Accordingly, its full source code and all assets are available for use by anyone who wants to learn how something was done or to create a derivative work, as long as the terms of this license are upheld, which basically just amounts to not telling others they can't do the same with anything you publish. (Giving credit in anything you produce, while not strictly necessary, would be nice)
Lending a hand is easy: just send a pull-request with explanations of what it addresses; if coding's not your thing, tell us what's not working the way it should and provide clear steps that describe how to reproduce the problem. As soon as we've had an opportunity to review your submission and make sure that it doesn't break anything, the code will be updated and you'll be credited.
All code is meticulously commented. If you find an under-documented section of code, please let us know.
This project is considered mature. Once its migration to Python 3 has been finalised, it is unlikely to see any major updates, but it will receive security and bugfix support indefinitely.
If staticDHCPd has helped you, please let us know. Conversely, if it exploded in your face and, after consulting the FAQ, you need help to get things working, also let us know.
Just don't contact Mathieu Ignacio with any complaints; he may have provided a crucial piece of this system, but he is not responsible for any mistakes we may have made.
- Architecture and implementation
Mathieu Ignacio
Matthew Boedicker
- Oracle support; sanity checking
Andrew Xuan
- Lots of constructive feedback
John Stowers
- Inspiration for making the database engine more flexible
- Ideas for several features that helped to define what 2.0 should be
Aleksandr Chusov
- Lots of 2.0.0 dev-branch testing: stepping on glass so nobody else had to
Ken Mitchell
- Identification and testing of the broadcast bit, meaning that every client should now be supported
Anthony Woods
- Suggestions that led to enabling site-specific metadata to be stored and easily accessed in databases ("definition.extra") and unifying Definition across the codebase
neil {dot} tallim {at} linux {dot} com