Skip to content

appconfig

Jesús Daniel Colmenares Oviedo edited this page May 22, 2025 · 2 revisions

Deploying an appConfig deployment

Templates are used in many systems, especially at scale, because it is the way to deploy the same application with subtle changes. Overlord includes a template system thanks to the Mako template engine. You can create a metadata that includes the template and with an appConfig deployment you can specify simple parameters, effectively creating something like a configuration, or in this case an appConfig.

metadata.yml:

kind: metadata
datacenters:
  main:
    entrypoint: !ENV '${ENTRYPOINT}'
    access_token: !ENV '${TOKEN}'
deployIn:
  labels:
    - vm-only
metadata:
  ts_auth_key: !ENV '${TS_AUTH_KEY}'
  resolv.conf: |
    nameserver 1.1.1.1
    nameserver 1.0.0.1
  timezone: !ENV '${TIMEZONE}'
  loader.conf: |
    nvme_load="YES"
    if_bridge_load="YES"
    bridgestp_load="YES"
    if_wg_load="YES"
    kern.racct.enable=1
  ssh_key: !ENV '${SSH_KEY}'
  sshd_config: |
    # Ports
    Port 22

    # Authentication
    PubkeyAuthentication yes
    AuthenticationMethods publickey
    PermitRootLogin prohibit-password
    PrintMotd no

    # Forwarding
    X11Forwarding no
    AllowAgentForwarding yes

    # Connection checks
    ClientAliveCountMax 3
    ClientAliveInterval 15

    # Compression
    Compression no

    # Limits
    LoginGraceTime 40

    # Public keys
    AuthorizedKeysFile      /etc/ssh/authorized_keys

    # SFTP
    Subsystem sftp internal-sftp
  sysctl.conf: |
    # A bit of hardening
    security.bsd.see_other_uids=0
    security.bsd.see_other_gids=0
    security.bsd.see_jail_proc=0
    kern.randompid=1

    # Allow packet filtering in if_bridge(4)
    net.link.bridge.pfil_member=1
    net.link.bridge.pfil_bridge=1
  pkg.conf: |
    FreeBSD: {
      url: "pkg+http://pkg.FreeBSD.org/${ABI}/latest",
      mirror_type: "srv",
      signature_type: "fingerprints",
      fingerprints: "/usr/share/keys/pkg",
      enabled: yes
    }
  appVM.appConfig: |
    <%page args="appvm_use_pkgbase='0'"/>

    kind: 'vmJail'
    vmName: ${appName}
    makejail: 'gh+DtxdF/vm-makejail'
    template:
      loader: 'bhyveload'
      cpu: '${ncpu}'
      memory: '${memory}'
      network0_type: 'virtio-net'
      network0_switch: 'public'
      wired_memory: 'YES'
    diskLayout:
      driver: 'nvme'
      size: '${disk}'
      from:
        % if appvm_use_pkgbase == "0":
        type: 'components'
        components:
          - base.txz
          - kernel.txz
        osArch: amd64
        osVersion: '${fbsdver}'
        % else:
        type: 'appjailImage'
        entrypoint: 'gh+AppJail-makejails/pkgbase'
        imageName: 'pkgbase'
        imageArch: 'amd64'
        imageTag: '${fbsdver}'
        % endif
      disk:
        scheme: 'gpt'
        partitions:
          - type: 'freebsd-boot'
            size: '512k'
            alignment: '1m'
          - type: 'freebsd-swap'
            size: '${swap}'
            alignment: '1m'
          - type: 'freebsd-ufs'
            alignment: '1m'
            format:
              flags: '-Uj'
        bootcode:
          bootcode: '/boot/pmbr'
          partcode: '/boot/gptboot'
          index: 1
      fstab:
        - device: '/dev/nda0p3'
          mountpoint: '/'
          type: 'ufs'
          options: 'rw,sync'
          dump: 1
          pass: 1
        - device: '/dev/nda0p2'
          mountpoint: 'none'
          type: 'swap'
          options: 'sw'
          dump: 0
          pass: 0
    script-environment:
    - HOSTNAME: '${hostname}'
    script: |
      <%text filter="n">
        set -xe
        set -o pipefail

        . "/metadata/environment"

        sysrc -f /mnt/etc/rc.conf ifconfig_vtnet0="inet 192.168.8.2/24"
        sysrc -f /mnt/etc/rc.conf defaultrouter="192.168.8.1"
        sysrc -f /mnt/etc/rc.conf fsck_y_enable="YES"
        sysrc -f /mnt/etc/rc.conf clear_tmp_enable="YES"
        sysrc -f /mnt/etc/rc.conf dumpdev="NO"
        sysrc -f /mnt/etc/rc.conf moused_nondefault_enable="NO"
        sysrc -f /mnt/etc/rc.conf hostname="${HOSTNAME}"

        if [ -f "/metadata/resolv.conf" ]; then
          cp -a /metadata/resolv.conf /mnt/etc/resolv.conf
        fi

        if [ -f "/metadata/loader.conf" ]; then
          cp /metadata/loader.conf /mnt/boot/loader.conf
        fi

        if [ -f "/metadata/zerotier_network" ]; then
          pkg -c /mnt install -y zerotier

          zerotier_network=`head -1 -- "/metadata/zerotier_network"`

          cat << EOF > /mnt/etc/rc.local
          while :; do
            if ! /usr/local/bin/zerotier-cli join ${zerotier_network}; then
              sleep 1
              continue
            fi

            break
          done

          rm -f /etc/rc.local
        EOF

          sysrc -f /mnt/etc/rc.conf zerotier_enable="YES"
        elif [ -f "/metadata/ts_auth_key" ]; then
          pkg -c /mnt install -y tailscale

          ts_auth_key=`head -1 -- "/metadata/ts_auth_key"`

          echo "/usr/local/bin/tailscale up --accept-dns=false --auth-key=\"${ts_auth_key}\" && rm -f /etc/rc.local" > /mnt/etc/rc.local

          sysrc -f /mnt/etc/rc.conf tailscaled_enable="YES"
        fi

        if [ -f "/metadata/timezone" ]; then
          timezone=`head -1 -- "/metadata/timezone"`

          ln -fs "/usr/share/zoneinfo/${timezone}" /mnt/etc/localtime
        fi

        if [ -f "/metadata/sshd_config" ]; then
          sysrc -f /mnt/etc/rc.conf sshd_enable="YES"
          cp /metadata/sshd_config /mnt/etc/ssh/sshd_config
        fi

        if [ -f "/metadata/ssh_key" ]; then
          cp /metadata/ssh_key /mnt/etc/ssh/authorized_keys
        fi

        if [ -f "/metadata/sysctl.conf" ]; then
          cp /metadata/sysctl.conf /mnt/etc/sysctl.conf
        fi

        if [ -f "/metadata/pkg.conf" ]; then
          mkdir -p /mnt/usr/local/etc/pkg/repos
          cp /metadata/pkg.conf /mnt/usr/local/etc/pkg/repos/Latest.conf
        fi
      </%text>
    metadata:
      - resolv.conf
      - loader.conf
      - timezone
      - sshd_config
      - ssh_key
      - sysctl.conf
      - pkg.conf
      - ts_auth_key

app-components.yml:

kind: appConfig
datacenters:
  main:
    entrypoint: !ENV '${ENTRYPOINT}'
    access_token: !ENV '${TOKEN}'
deployIn:
  labels:
    - desktop
appName: 'vmtest001'
appFrom: 'appVM.appConfig'
appConfig:
  ncpu: '2'
  memory: '1G'
  disk: '10G'
  fbsdver: '14.2-RELEASE'
  swap: '2G'
  hostname: 'vmtest001'

app-pkgbase.yml:

kind: appConfig
datacenters:
  main:
    entrypoint: !ENV '${ENTRYPOINT}'
    access_token: !ENV '${TOKEN}'
deployIn:
  labels:
    - desktop
appName: 'vmtest002'
appFrom: 'appVM.appConfig'
appConfig:
  ncpu: '2'
  memory: '1G'
  disk: '10G'
  fbsdver: '14.2-full'
  swap: '2G'
  hostname: 'vmtest002'
  appvm_use_pkgbase: '1'

.env:

ENTRYPOINT=http://127.0.0.1:8888
TOKEN=<access token>
TS_AUTH_KEY=<tailscale auth key>
TIMEZONE=America/Caracas
SSH_KEY=<SSH public key>

The template has a few dozen lines but the appConfig is only a couple of lines and little effort to write such a thing is evident, but here's the point, you just focus on those subtle changes and nothing else.

Notice those subtle changes between each appConfig deployment. In the case of app-components.yml it is a deployment that uses FreeBSD components from the 14.2-RELEASE version and in the case of app-pkgbase.yml it uses an AppJail image tagged 14-full.

$ overlord apply -f metadata.yml
$ overlord apply -f app-components.yml
$ overlord apply -f app-pkgbase.yml
$ overlord get-info -f app-components.yml -t projects --filter-per-project
datacenter: http://127.0.0.1:8888
  entrypoint: main
  chain: None
  labels:
    - all
    - desktop
    - services
    - vm-only
  projects:
    vmtest001:
      state: DONE
      last_log: 2025-05-02_20h35m10s
      locked: False
      services:
        - {'name': 'vm', 'status': 0, 'jail': 'vmtest001'}
      up:
        operation: COMPLETED
        output:
         rc: 0
         stdout: {'errlevel': 0, 'message': None, 'failed': []}
        last_update: 1 minute and 50.25 seconds
        job_id: 5
        restarted: False
$ overlord get-info -f app-components.yml -t vm --filter-per-project
datacenter: http://127.0.0.1:8888
  entrypoint: main
  chain: None
  labels:
    - all
    - desktop
    - services
    - vm-only
  projects:
    vmtest002:
      virtual-machines:
          operation: COMPLETED
          output: |
            md0 created
             md0p1 added
             md0p2 added
             md0p3 added
             /dev/md0p3: 8190.0MB (16773120 sectors) block size 32768, fragment size 4096
             	using 14 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
             	with soft updates
             super-block backups (for fsck_ffs -b #) at:
              192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776,
              11524224, 12804672, 14085120, 15365568, 16646016
             Using inode 4 in cg 0 for 67108864 byte journal
             bootcode written to md0
             partcode written to md0p1
             ifconfig_vtnet0:  -> inet 192.168.8.2/24
             defaultrouter: NO -> 192.168.8.1
             fsck_y_enable: NO -> YES
             clear_tmp_enable: NO -> YES
             dumpdev: NO -> NO
             moused_nondefault_enable: YES -> NO
             hostname:  -> vmtest002
             [vmtest002.appjail] Installing pkg-2.1.2...
             [vmtest002.appjail] Extracting pkg-2.1.2: .......... done
             Updating FreeBSD repository catalogue...
             [vmtest002.appjail] Fetching data.pkg: .......... done
             Processing entries: .......... done
             FreeBSD repository update completed. 35977 packages processed.
             Updating FreeBSD-base repository catalogue...
             [vmtest002.appjail] Fetching data.pkg: ... done
             Processing entries: 
             Processing entries............. done
             FreeBSD-base repository update completed. 525 packages processed.
             All repositories are up to date.
             The following 2 package(s) will be affected (of 0 checked):
             
             New packages to be INSTALLED:
             	ca_root_nss: 3.108 [FreeBSD]
             	tailscale: 1.82.5 [FreeBSD]
             
             Number of packages to be installed: 2
             
             The process will require 35 MiB more space.
             11 MiB to be downloaded.
             [vmtest002.appjail] [1/2] Fetching tailscale-1.82.5.pkg: .......... done
             [vmtest002.appjail] [2/2] Fetching ca_root_nss-3.108.pkg: .......... done
             Checking integrity... done (0 conflicting)
             [vmtest002.appjail] [1/2] Installing ca_root_nss-3.108...
             [vmtest002.appjail] [1/2] Extracting ca_root_nss-3.108: ....... done
             [vmtest002.appjail] [2/2] Installing tailscale-1.82.5...
             [vmtest002.appjail] [2/2] Extracting tailscale-1.82.5: ...... done
             =====
             Message from ca_root_nss-3.108:
             
             --
             FreeBSD does not, and can not warrant that the certification authorities
             whose certificates are included in this package have in any way been
             audited for trustworthiness or RFC 3647 compliance.
             
             Assessment and verification of trust is the complete responsibility of
             the system administrator.
             
             This package installs symlinks to support root certificate discovery
             for software that either uses other cryptographic libraries than
             OpenSSL, or use OpenSSL but do not follow recommended practice.
             
             If you prefer to do this manually, replace the following symlinks with
             either an empty file or your site-local certificate bundle.
             
               * /etc/ssl/cert.pem
               * /usr/local/etc/ssl/cert.pem
               * /usr/local/openssl/cert.pem
             tailscaled_enable:  -> YES
             sshd_enable: NO -> YES
             vm_list:  -> vmtest002
             Starting vmtest002
               * found guest in /vm/vmtest002
               * booting...
            newfs: soft updates journaling set
             [00:00:01] [ info  ] [pkgbase] pkgbase (arch:amd64, tag:14-full): already up to date.
             + set -o pipefail
             + . /metadata/environment
             + export 'HOSTNAME=vmtest002'
             + sysrc -f /mnt/etc/rc.conf 'ifconfig_vtnet0=inet 192.168.8.2/24'
             + sysrc -f /mnt/etc/rc.conf 'defaultrouter=192.168.8.1'
             + sysrc -f /mnt/etc/rc.conf 'fsck_y_enable=YES'
             + sysrc -f /mnt/etc/rc.conf 'clear_tmp_enable=YES'
             + sysrc -f /mnt/etc/rc.conf 'dumpdev=NO'
             + sysrc -f /mnt/etc/rc.conf 'moused_nondefault_enable=NO'
             + sysrc -f /mnt/etc/rc.conf 'hostname=vmtest002'
             + [ -f /metadata/resolv.conf ]
             + cp -a /metadata/resolv.conf /mnt/etc/resolv.conf
             + [ -f /metadata/loader.conf ]
             + cp /metadata/loader.conf /mnt/boot/loader.conf
             + [ -f /metadata/zerotier_network ]
             + [ -f /metadata/ts_auth_key ]
             + pkg -c /mnt install -y tailscale
             certctl: Scanning /usr/share/certs/untrusted for certificates...
             certctl: Scanning /usr/share/certs/trusted for certificates...
             certctl: Scanning /usr/local/share/certs for certificates...
             + head -1 -- /metadata/ts_auth_key
             + ts_auth_key=[REDACTED]
             + echo '/usr/local/bin/tailscale up --accept-dns=false --auth-key="[REDACTED]" && rm -f /etc/rc.local'
             + sysrc -f /mnt/etc/rc.conf 'tailscaled_enable=YES'
             + [ -f /metadata/timezone ]
             + head -1 -- /metadata/timezone
             + timezone=America/Caracas
             + ln -fs /usr/share/zoneinfo/America/Caracas /mnt/etc/localtime
             + [ -f /metadata/sshd_config ]
             + sysrc -f /mnt/etc/rc.conf 'sshd_enable=YES'
             + cp /metadata/sshd_config /mnt/etc/ssh/sshd_config
             + [ -f /metadata/ssh_key ]
             + cp /metadata/ssh_key /mnt/etc/ssh/authorized_keys
             + [ -f /metadata/sysctl.conf ]
             + cp /metadata/sysctl.conf /mnt/etc/sysctl.conf
             + [ -f /metadata/pkg.conf ]
             + mkdir -p /mnt/usr/local/etc/pkg/repos
             + cp /metadata/pkg.conf /mnt/usr/local/etc/pkg/repos/Latest.conf
          last_update: 12 minutes and 34.79 seconds
          job_id: 3
$ overlord get-info -f app-pkgbase.yml -t projects --filter-per-project
datacenter: http://127.0.0.1:8888
  entrypoint: main
  chain: None
  labels:
    - all
    - desktop
    - services
    - vm-only
  projects:
    vmtest002:
      state: DONE
      last_log: 2025-05-02_20h23m33s
      locked: False
      services:
        - {'name': 'vm', 'status': 0, 'jail': 'vmtest002'}
      up:
        operation: COMPLETED
        output:
         rc: 0
         stdout: {'errlevel': 0, 'message': None, 'failed': []}
        last_update: 13 minutes and 21.73 seconds
        job_id: 3
        restarted: False
$ overlord get-info -f app-pkgbase.yml -t vm --filter-per-project
datacenter: http://127.0.0.1:8888
  entrypoint: main
  chain: None
  labels:
    - all
    - desktop
    - services
    - vm-only
  projects:
    vmtest002:
      virtual-machines:
          operation: COMPLETED
          output: |
            md0 created
             md0p1 added
             md0p2 added
             md0p3 added
             /dev/md0p3: 8190.0MB (16773120 sectors) block size 32768, fragment size 4096
             	using 14 cylinder groups of 625.22MB, 20007 blks, 80128 inodes.
             	with soft updates
             super-block backups (for fsck_ffs -b #) at:
              192, 1280640, 2561088, 3841536, 5121984, 6402432, 7682880, 8963328, 10243776,
              11524224, 12804672, 14085120, 15365568, 16646016
             Using inode 4 in cg 0 for 67108864 byte journal
             bootcode written to md0
             partcode written to md0p1
             ifconfig_vtnet0:  -> inet 192.168.8.2/24
             defaultrouter: NO -> 192.168.8.1
             fsck_y_enable: NO -> YES
             clear_tmp_enable: NO -> YES
             dumpdev: NO -> NO
             moused_nondefault_enable: YES -> NO
             hostname:  -> vmtest002
             [vmtest002.appjail] Installing pkg-2.1.2...
             [vmtest002.appjail] Extracting pkg-2.1.2: .......... done
             Updating FreeBSD repository catalogue...
             [vmtest002.appjail] Fetching data.pkg: .......... done
             Processing entries: .......... done
             FreeBSD repository update completed. 35977 packages processed.
             Updating FreeBSD-base repository catalogue...
             [vmtest002.appjail] Fetching data.pkg: ... done
             Processing entries: 
             Processing entries............. done
             FreeBSD-base repository update completed. 525 packages processed.
             All repositories are up to date.
             The following 2 package(s) will be affected (of 0 checked):
             
             New packages to be INSTALLED:
             	ca_root_nss: 3.108 [FreeBSD]
             	tailscale: 1.82.5 [FreeBSD]
             
             Number of packages to be installed: 2
             
             The process will require 35 MiB more space.
             11 MiB to be downloaded.
             [vmtest002.appjail] [1/2] Fetching tailscale-1.82.5.pkg: .......... done
             [vmtest002.appjail] [2/2] Fetching ca_root_nss-3.108.pkg: .......... done
             Checking integrity... done (0 conflicting)
             [vmtest002.appjail] [1/2] Installing ca_root_nss-3.108...
             [vmtest002.appjail] [1/2] Extracting ca_root_nss-3.108: ....... done
             [vmtest002.appjail] [2/2] Installing tailscale-1.82.5...
             [vmtest002.appjail] [2/2] Extracting tailscale-1.82.5: ...... done
             =====
             Message from ca_root_nss-3.108:
             
             --
             FreeBSD does not, and can not warrant that the certification authorities
             whose certificates are included in this package have in any way been
             audited for trustworthiness or RFC 3647 compliance.
             
             Assessment and verification of trust is the complete responsibility of
             the system administrator.
             
             This package installs symlinks to support root certificate discovery
             for software that either uses other cryptographic libraries than
             OpenSSL, or use OpenSSL but do not follow recommended practice.
             
             If you prefer to do this manually, replace the following symlinks with
             either an empty file or your site-local certificate bundle.
             
               * /etc/ssl/cert.pem
               * /usr/local/etc/ssl/cert.pem
               * /usr/local/openssl/cert.pem
             tailscaled_enable:  -> YES
             sshd_enable: NO -> YES
             vm_list:  -> vmtest002
             Starting vmtest002
               * found guest in /vm/vmtest002
               * booting...
            newfs: soft updates journaling set
             [00:00:01] [ info  ] [pkgbase] pkgbase (arch:amd64, tag:14-full): already up to date.
             + set -o pipefail
             + . /metadata/environment
             + export 'HOSTNAME=vmtest002'
             + sysrc -f /mnt/etc/rc.conf 'ifconfig_vtnet0=inet 192.168.8.2/24'
             + sysrc -f /mnt/etc/rc.conf 'defaultrouter=192.168.8.1'
             + sysrc -f /mnt/etc/rc.conf 'fsck_y_enable=YES'
             + sysrc -f /mnt/etc/rc.conf 'clear_tmp_enable=YES'
             + sysrc -f /mnt/etc/rc.conf 'dumpdev=NO'
             + sysrc -f /mnt/etc/rc.conf 'moused_nondefault_enable=NO'
             + sysrc -f /mnt/etc/rc.conf 'hostname=vmtest002'
             + [ -f /metadata/resolv.conf ]
             + cp -a /metadata/resolv.conf /mnt/etc/resolv.conf
             + [ -f /metadata/loader.conf ]
             + cp /metadata/loader.conf /mnt/boot/loader.conf
             + [ -f /metadata/zerotier_network ]
             + [ -f /metadata/ts_auth_key ]
             + pkg -c /mnt install -y tailscale
             certctl: Scanning /usr/share/certs/untrusted for certificates...
             certctl: Scanning /usr/share/certs/trusted for certificates...
             certctl: Scanning /usr/local/share/certs for certificates...
             + head -1 -- /metadata/ts_auth_key
             + ts_auth_key=[REDACTED]
             + echo '/usr/local/bin/tailscale up --accept-dns=false --auth-key="[REDACTED]" && rm -f /etc/rc.local'
             + sysrc -f /mnt/etc/rc.conf 'tailscaled_enable=YES'
             + [ -f /metadata/timezone ]
             + head -1 -- /metadata/timezone
             + timezone=America/Caracas
             + ln -fs /usr/share/zoneinfo/America/Caracas /mnt/etc/localtime
             + [ -f /metadata/sshd_config ]
             + sysrc -f /mnt/etc/rc.conf 'sshd_enable=YES'
             + cp /metadata/sshd_config /mnt/etc/ssh/sshd_config
             + [ -f /metadata/ssh_key ]
             + cp /metadata/ssh_key /mnt/etc/ssh/authorized_keys
             + [ -f /metadata/sysctl.conf ]
             + cp /metadata/sysctl.conf /mnt/etc/sysctl.conf
             + [ -f /metadata/pkg.conf ]
             + mkdir -p /mnt/usr/local/etc/pkg/repos
             + cp /metadata/pkg.conf /mnt/usr/local/etc/pkg/repos/Latest.conf
          last_update: 10 minutes and 41.07 seconds
          job_id: 3
$ tailscale status
...
100.103.230.7   vmtest001            [REDACTED]@    freebsd -
100.115.122.94  vmtest002            [REDACTED]@    freebsd -
$ ssh root@100.103.230.7 freebsd-version
The authenticity of host '100.103.230.7 (100.103.230.7)' can't be established.
ED25519 key fingerprint is SHA256:YcOzEGoc2Gcln6ovJ+ea/13zquuNOciGSMXKMdXfRgA.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '100.103.230.7' (ED25519) to the list of known hosts.
14.2-RELEASE
$ ssh root@100.115.122.94 freebsd-version                                                                                                     
The authenticity of host '100.115.122.94 (100.115.122.94)' can't be established.
ED25519 key fingerprint is SHA256:2UW4e2O3hPCDZhTz1UwF323KvAeZuJPHvK1I7gRha+Y.
This key is not known by any other names.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '100.115.122.94' (ED25519) to the list of known hosts.
14.2-RELEASE

An interesting fact about appConfig is that although you deploy the template in multiple chains, only the first matching one is used. Obviously, this is for redundancy in case a chain is down.

Clone this wiki locally