WeOS
5.20.1

# 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:

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