Dynamic Boot Config
Introduction
This feature is only available in certain products and to selected customers.
In this guide we show how to generate a running-config using an application container. One possible use case for this is if you have configuration stored in some non native format. The configuration could be read inside the application container, converted to OS native format, and then served back to the host via DHCP/TFTP.
We rely mainly on two features in this guide:
- Application Hosting - for running the app that will host the custom configuration
- Network Boot Config - for transferring the configuration created by the app back to the host
Host # Configuration Application
# .-------------. .-------------.
# | DHCP-server | | TFTP-server |
# '------+------' '------+------'
.------------. # '------. .------'
| cfg | # .-+--+-.
| inet: dhcp | # | eth0 |
'------+-----' # '--+---'
| # |
'--------------------------'
Our application container will be connected to the host via a VETH pair: cfg/eth0. The DHCP-server will let the host know that there is a configuration file available on an IP address assigned to eth0. The host will download this file using TFTP, and use it as it’s new running-config. The only thing special in this scenario, compared to an ordinary network boot scenario, is that the DHCP/TFTP-server is hosted on the same device that is receiving the config. This enables the device to have a user defined application generating the config, while still keeping that application isolated and independent from the OS.
For this guide we use a NetBox application image built with default configuration. This is not a guide to building custom app images so we will keep all customization on external media, but in a real world scenario it might be preferable to build this in to the app image.
Configuration
Prepare External Media
It is important that the USB media is formatted as ext2, ext3 or ext4. We also need to create four files on the USB media:
dnsmasq.conf
: Configuration for Dnsmasq, which will serve as both DHCP server and TFTP server in the container.cfg-provider.sh
: A script that will serve as an entry point for the container. Any modification could be instrumented from here. Responsible for starting Dnsmasq.dynamic-config.cfg
: The “dynamic” config that Dnsmasq will serve. Note that you can give this file whatever name you want. It needs to be consistent with what is set as DHCP option 67 in Dnsmasq though.config/net-config.cfg
: The bootstrap config that will carry the configuration for our application container.
Prepare the USB media by creating the first two files:
dnsmasq.conf
log-facility=-
no-daemon
enable-tftp
tftp-root=/mnt
interface=eth0
dhcp-option=66,"10.0.0.89"
dhcp-option=67,"dynamic-config.cfg"
dhcp-range=tag:eth0,10.0.0.1,10.0.0.40,1h
cfg-provider.sh
#!/bin/sh
# Set up the default interface
ip link set dev eth0 up
ip addr add 10.0.0.89/24 dev eth0
# Here is were we could start a program that would
# modify /mnt/dynamic-config.cfg, or even generate it from scratch.
# Start our DHCP/TFTP server Dnsmasq
exec dnsmasq -C /etc/dnsmasq.conf
Note cfg-provider.sh
needs to have the executable bit set.
The rest of the files will be created from within the OS in the next steps.
dynamic-config.cfg
In our example dynamic-config.cfg
will be rather static, but it could of
course be generated or modified by the app itself. Some program could be run
to generate dynamic-config.cfg
inside cfg-provider.sh
before starting
Dnsmasq. Here we are simply using the OS’s own CLI to create the config for us:
example:/#> copy factory-config running-config Applying configuration. example:/#> configure system example:/config/system/#> hostname hostname-from-container example:/config/system/#> leave Applying configuration. Configuration activated. Remember "copy run start" to save to flash (NVRAM). hostname-from-container:/#> cp running-config usb://dynamic-config.cfg Copying running-config to /usb/dynamic-config.cfg ... Done. hostname-from-container:/#> copy factory-config running-config Applying configuration.
We modify hostname
only to have something that easily can tell us that the
running-config is coming from the container after we reboot.
config/net-config.cfg
net-config can be stored either on internal flash or on external media. In this guide we keep all configuration on USB media.
In the net-config, we want all physical ports to be disabled so that we are sure that no external DHCP server is reached.
Important: Any ssh connection to the device will stop working after this step!
example:/#> configure port ALL example:/config/port-ALL/#> no enable example:/config/port-ALL/#> leave All ports in the system have been disabled. This will likely result in a non-functional system, are you sure you want to continue (y/N)?y Applying configuration. Configuration activated. Remember "copy run start" to save to flash (NVRAM).
Configure the app that will host/run the files we have created:
example:/#> configure app cfg netbox example:/config/app-cfg/#> initcmd cfg-provider.sh example:/config/app-cfg/#> share path /usb/cfg-provider.sh as /bin/cfg-provider.sh create example:/config/app-cfg/#> share path /usb/dnsmasq.conf as /etc/dnsmasq.conf create example:/config/app-cfg/#> share path /usb/ as /mnt example:/config/app-cfg/#> end
Along with the app, a VETH pair is created by default. Per default it will
have the same name as the app on the host side, and eth0
on the container
side. We need to configure DHCP for the host side interface:
example:/config/#> iface cfg example:/config/iface-cfg/#> inet dhcp example:/config/iface-cfg/inet-dhcp/#> option 66, 67 example:/config/iface-cfg/inet-dhcp/#> leave
The net-config is now complete. Copy it to the external media and reset the running-config:
example:/#> shell example:/#> copy running-config usb://config/net-config.cfg example:/#> copy factory-config running-config Applying configuration.
Finally we configure our system to use net-config on external media to boot the system, and reboot:
example:/#> boot example:/boot/#> config-order ext:net example:/boot/#> leave example:/#> reboot
After reboot the container application starts up, the host fetches the new
running-config from the container, and that config is applied, resulting in
the hostname
changing to “hostname-from-container”.