Skip to content

freebsd_vm

Jesús Daniel Colmenares Oviedo edited this page Apr 11, 2026 · 2 revisions

Deploying FreeBSD VMs

A virtual machine with FreeBSD as the guest OS is very useful for further isolating applications. Overlord can deploy this type of deployment.

This deployment works as follows: A director file is created (overlord does this internally), which is used to further create a jail that represents the environment that must have vm-bhyve installed, must be configured to use the firewall (one supported by FreeBSD) and must be configured with the bridge used by the VMs. This sounds really complicated, but there is a Makejail that does it, so take a look at it for details. The Makejail mentioned above creates the environment with vm-bhyve-devel installed, configures pf(4) and creates a bridge with an assigned IPv4 (192.168.8.1/24), so we must assign our VM an IPv4 between that range. pf(4) is not configured to isolate further connections, so an application inside the VM can "escape" to other services, which may or may not be desirable depending on what it is doing.

  1. Create a deployment file.

    kind: vmJail
    datacenters:
      main:
        entrypoint: 'http://127.0.0.1:8888'
        access_token: '<access token>'
    deployIn:
      labels:
        - desktop
    vmName: 'myvm'
    makejail: 'gh+DtxdF/vm-makejail'
    template:
      loader: 'bhyveload'
      cpu: '4'
      memory: '2G'
      network0_type: 'virtio-net'
      network0_switch: 'public'
      wired_memory: 'YES'
    diskLayout:
      driver: 'nvme'
      size: '40G'
      from:
        type: 'components'
        components:
          - base.txz
          - kernel.txz
        osArch: amd64
        osVersion: 14.2-RELEASE
      disk:
        scheme: 'gpt'
        partitions:
          - type: 'freebsd-boot'
            size: '512k'
            alignment: '1m'
          - type: 'freebsd-swap'
            size: '2g'
            alignment: '1m'
          - type: 'freebsd-ufs'
            size: '20g'
            alignment: '1m'
            format:
              flags: '-Uj'
          - 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: |
      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 hostname=myvm
    
      cat << EOF > /mnt/etc/resolv.conf
      nameserver 172.16.0.1
      EOF
    
      mkdir -p /mnt/usr/local/etc/pkg/repos
    
      cat << "EOF" > /mnt/usr/local/etc/pkg/repos/Latest.conf
      FreeBSD: {
        url: "pkg+https://pkg.FreeBSD.org/${ABI}/latest",
        mirror_type: "srv",
        signature_type: "fingerprints",
        fingerprints: "/usr/share/keys/pkg",
        enabled: yes
      }
      EOF
  2. Deploy.

    overlord apply -f myvm.yml
  3. Check status.

    $ overlord get-info -f myvm.yml -t vm --filter-per-project
    datacenter: http://127.0.0.1:8888
      entrypoint: main
      chain: None
      labels:
        - all
        - desktop
        - vm-only
      projects:
        myvm:
          virtual-machines:
              operation: RUNNING
              last_update: 19.08 seconds
              job_id: 5
    $ overlord get-info -f myvm.yml -t projects --filter-per-project
    datacenter: http://127.0.0.1:8888
      entrypoint: main
      chain: None
      labels:
        - all
        - desktop
        - vm-only
      projects:
        myvm:
          state: UNFINISHED
          last_log: 2025-03-03_14h32m37s
          locked: True
          services:
            - {'name': 'vm', 'status': 0, 'jail': 'myvm'}
          up:
            operation: RUNNING
            last_update: 24.05 seconds
            job_id: 5

    A VM takes longer in most cases, so wait a moment and you will see the result.

    $ overlord get-info -f myvm.yml -t vm --filter-per-project
    datacenter: http://127.0.0.1:8888
      entrypoint: main
      chain: None
      labels:
        - all
        - desktop
        - vm-only
      projects:
        myvm:
          virtual-machines:
              operation: COMPLETED
              output: |
                md0 created
                md0p1 added
                md0p2 added
                md0p3 added
                /dev/md0p3: 20480.0MB (41943040 sectors) block size 32768, fragment size 4096
                    using 33 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, 17926464, 19206912,
                 20487360, 21767808, 23048256, 24328704, 25609152, 26889600, 28170048,
                 29450496, 30730944, 32011392, 33291840, 34572288, 35852736, 37133184,
                 38413632, 39694080, 40974528
                Using inode 4 in cg 0 for 167772160 byte journal
                md0p4 added
                /dev/md0p4: 18430.0MB (37744640 sectors) block size 32768, fragment size 4096
                    using 30 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, 17926464, 19206912,
                 20487360, 21767808, 23048256, 24328704, 25609152, 26889600, 28170048,
                 29450496, 30730944, 32011392, 33291840, 34572288, 35852736, 37133184
                Using inode 4 in cg 0 for 150994944 byte journal
                bootcode written to md0
                partcode written to md0p1
                ifconfig_vtnet0:  -> inet 192.168.8.2/24
                defaultrouter: NO -> 192.168.8.1
                hostname:  -> myvm
                vm_list:  -> myvm
                Starting myvm
                  * found guest in /vm/myvm
                  * booting...
                newfs: soft updates journaling set
                newfs: soft updates journaling set
              last_update: 3 minutes and 59.39 seconds
              job_id: 5
    $ overlord get-info -f myvm.yml -t projects --filter-per-project
    datacenter: http://127.0.0.1:8888
      entrypoint: main
      chain: None
      labels:
        - all
        - desktop
        - vm-only
      projects:
        myvm:
          state: DONE
          last_log: 2025-03-03_14h32m37s
          locked: False
          services:
            - {'name': 'vm', 'status': 0, 'jail': 'myvm'}
          up:
            operation: COMPLETED
            output:
             rc: 0
             stdout: {'errlevel': 0, 'message': None, 'failed': []}
            last_update: 6 minutes and 6.44 seconds
            job_id: 5
  4. If your virtual machine was installed on a remote system, you will need to SSH into that system and run the following command:

    appjail cmd jexec myvm vm console myvm
  5. Destroy VM.

    overlord destroy -f myvm.yml

Notes

  1. In order to work with vm-bhyve you probably need to put in your loader.conf(5) file the following:

    vmm_load="YES"
    nmdm_load="YES"
    

    Of course, load them at runtime using kldload(8).

Clone this wiki locally