Dynamic Boot Config

Introduction

ⓘ Note

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:

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”.