Build environment

Deityguard has been tested to build correctly under DeityGuard itself (i.e., basically Gentoo), under Ubuntu (via Third Idea), and under Void Linux. The use of a Third Idea setup is highly recommended. The sample script for running DeityGuard behind Third Idea contains bash -i stops in the 1-gengen and 2-fingen directories where you can run the dg_locally_gengen_* commands and ./fingen.sh commands as shown below.

On a Ubuntu LiveCD system, or on a DeityGuard system, all build dependencies of DeityGuard should already be installed.

On a Void Linux LiveCD system, the following command should suffice to install all the build dependencies of DeityGuard:

xbps-install -y -S btrfs-progs psmisc lsof wget cpio bc time gnupg2

Unpack DeityGuard

First, unpack deityguard.tar.xz (see Download) somewhere and cd to the deityguard directory:

cd path/to/somewhere
tar -xf path/to/deityguard.tar.xz
cd ./deityguard

DeityGuard has 2 major scripts:

  • 1-gengen: Builds everything, in the sense of doing all the heavy-duty compiling work.

  • 2-fingen: Configures everything; i.e., takes the output for gengen and wires it up so that it boots and does something useful. This is where all the configuration is applied to produce flash ROM images that eventually load the operating system and then do useful stuff.

Module 1: gengen

First, enter 1-gengen:

cd ./1-gengen

The gengen script uses the directory ./local/offload for scratch space, which is expected to exist. In this guide we will just create regular directories for ./local/offload, but you can also create a directory on a different filesystem and set up local or offload as a symbolic link.

mkdir -p ./local/offload

It is possible to invoke ./gengen.sh directly, but it is usually more convenient to work with a set of helper functions loaded from ./aliases.sh, so let’s load the functions (your shell must be bash for this to work):

. ./aliases.sh

Now, if you are bootstrapping from a non-DeityGuard system, set GENGEN_NETESC to the empty string:

export GENGEN_NETESC=""

Or, if you are working with gengen from within an existing DeityGuard system, set GENGEN_NETESC to the command prefix that allows outbound Internet access:

export GENGEN_NETESC="sudo -g netwild"

Now we’re ready to actually invoke gengen. First, we run the stage3 command, which, in turn, runs the portage and world commands. We add the world-libressl flag which enables using libressl as the SSL implementation (rather than the default openssl, which is currently thought of as being somewhat less secure than libressl):

dg_locally_gengen_gentoo_stage3 world-libressl
# build time about 2 hours and 30 minutes

Having built the base OS for x86_64, we run the brarm command which builds the buildroot-based OS for ARM platforms:

dg_locally_gengen_brarm
# build time about 2 hours and 40 minutes

Next, we build the linux kernel for x86_64:

dg_locally_gengen_linux
# build time about 20 minutes

Next, we build the linux kernel for the bpi platform:

dg_locally_gengen_arm_linux_bpi
# build time about 4 minutes

Next, we build the linux kernel for the rok platform:

dg_locally_gengen_arm_linux_rok
# build time about 5 minutes

Next, we build coreboot (this takes longer than you would assume because coreboot builds another gcc toolchain; DeityGuard will cache the built toolchain to speed up subsequent builds):

dg_locally_gengen_coreboot
# build time about 45 minutes

Next, we build U-Boot for ARM:

dg_locally_gengen_arm_u_boot
# build time under one minute

Next, we build various tools specific to DeityGuard:

dg_locally_gengen_tools
# build time under one minute

Next, we build flashpagan, the DeityGuard-specific flashing tool (this is done separately from the other tools because flashpagan has dynamic library dependencies, so it may need to be rebuilt sometimes when the other libaboon-based tools might not need to be):

dg_locally_gengen_flashpagan
# build time under one minute

Next, we enable building the unikit when anything else is built. This has been suppressed so far because not all the components that need to be included in the unikit were available, but now they are so we enable building the unikit:

touch ./local/unikitmaybeyes

Now, we can explicitly build the unikit, or leave it to be built automatically as part of the next command.

dg_locally_gengen_unikit
# build time about 1.5 minutes

Next, we add additional packages to the world set. By default, gengen only builds those Gentoo packages that are needed to complete the build (most of the building is done from within the gentoo chroot so as not to depend on binaries from the host system more than necessary). To get additional features, you have to add wunst keywords to the command. They are called wunst keywords because you only have to specify them once, and the world target remembers them for future invocations so that your package selection will not be dropped by default. However, world-purge can be specified to drop any wunst keywords not specified on the current command line. Here is list of supported wunst keywords (all must be prefixed with world- when specified on the command line):

wunst keyword effect
purge drops any remembered wunst keywords
libressl enables using libressl rather than the default openssl
selfhost adds packages necessary to run all features of gengen/fingen on the target system
anybase adds packages necessary to run all features of the dg-any-base overlay of fingen
netsurf adds a minimalistic browser (without JS support, so YMMV)
firefox adds a popular browser called firefox
chromium adds a popular browser called chromium
workstation adds packages necessary to host remote VNC sessions
misc adds miscellaneous packages that I like to use; you should probably replace this list with your own

Even if you don’t add any additional packages you will not be wedged out of running gengen/fingen to add more packages, because you can always emerge any missing dependencies on the target system (as long as it has an Internet connection). That being said, it’s strongly recommended to avoid additional troubles by specifying at least selfhost, anybase, and at least one of the web browsers. To include everything, run:

dg_locally_gengen_gentoo_world world-{purge,libressl,selfhost,anybase,netsurf,workstation,misc,firefox,chromium}
# build time about 6 hours

To reduce the build time, you can drop one of firefox or chromium.

To add your own packages, you must modify the gengen scripts a bit. How to edit the mapping from wunst keywords to lists of selected packages is described on the the Internals page.

Module 2: fingen

For starters, let’s change to the 2-fingen directory:

cd ./../2-fingen

fingen requires a symlink in ./local to a directory in the gengen build tree. Here we set this up assuming that gengen was run locally, but one could also use sshfs to access a remote gengen build tree, or update a local copy with rsync. Also, a symlink to unikit.tzo is required.

mkdir -p ./local
ln -vsf -T ./../../1-gengen/build/btrfs/gentoo/builds/rootfs-mirror/ ./local/gengen-build-btrfs-gentoo-builds-rootfs-mirror
ln -vsf -T ./../../1-gengen/build/btrfs/gentoo/builds/unikit.tzo ./local/gengen-build-btrfs-gentoo-builds-unikit.tzo

Also, fingen requires a directory ./local/output to exist. This is for ISO image functionality that doesn’t work at present, but the directory is required to exist nevertheless. Let’s create it:

mkdir -p ./local/output

Before you can run fingen, you need a configuration file. Template configurations are available in the script in the 4-sample directory of the DeityGuard source archive.

Depending on which object API your configuration selects, you may need to set an appropriate NETESC environment variable. FINGEN_OBJ_API_*_NETESC must be set to a command prefix that enables outbound Internet access (usually the empty string for non-DeityGuard hosts and sudo -g netwild for DeityGuard hosts. Here are the examples for the scp object API backend:

export FINGEN_OBJ_API_SCP_NETESC=

Or:

export FINGEN_OBJ_API_SCP_NETESC="sudo -g netwild"

The “none” object API does not require a NETESC setting as it does not access the network; instead, it drops the files in ./local/obj_api_none. If you use it, you will have to transfer the files to the HTTP server somehow else. Optical media (e.g., rewritable DVD) is ideal for this purpose, as it is harder for an attacker to bypass an air gap through optical media than through media that has active electronic components in it. It is also possible to use another Third Idea unidirectional link from the build host to the HTTP server.

Before running fingen, you must inform it of the host architecture (that is, the architecture of the machine you are running fingen on). Usually, this will be:

echo x64 >./local/hostarch

Or, if you are running fingen on the bpi platform:

echo ca7 >./local/hostarch

Or, if you are running fingen on the rok platform:

echo ca17 >./local/hostarch

Finally, supply the name of your configuration file to ./fingen.sh. It will work whether you use the bare machine name or the full file path:

./fingen.sh your_machine_name

Or:

./fingen.sh ./config/your_machine_name.sh

By default, fingen.sh prepares the network-loadable stage2 image and uploads it the object store specified by the configuration (the rootfs image is also uploaded if it hasn’t been already or it has changed). Specifying the additional argument flash will also upload the stage1 image and attempt to flash a BIOS chip connected by a UM232H board. The boot ROM will only work in conjunction with the specific stage1 image built in the same run of fingen.sh. For the purpose of flashing with a different program, the boot ROM is in ./build/boot.rom. You can specify flash inhibit to have fingen upload the stage1 image without flashing. If you don’t specify flash, only the upgradeable stage2 and rootfs components are uploaded.

The idea is that you should only need to flash once, as you typically won’t need to upgrade stage1. The first boot after flashing must have network access to load stage2 over the network. After the first boot, DeityGuard can save the stage data to local storage to allow booting while not connected to the network. Additionally, the entire rootfs can be cached to local storage by running the dg-prefault tool from within a DeityGuard system.