Individual kuhbConfiguration Files

To “install firefox” and use it in unnamed DisposableVMs, the following steps would have to be taken:

  1. Clone the TemplateVM debian-minimal to tpl-firefox
  2. Execute scripts on the tpl-firefox, taken from kuhbs/firefox/tpl/scripts/*.sh
  3. Possibly restore backup on the tpl-firefox
  4. Create an AppVM app-firefox with tpl-firefox as TemplateVM
  5. Possibly restore a backup on the app-firefox, for example /home/user/.config/mozilla which contains bookmark data
  6. Create .desktop files for xfce and dmenu launchers for i3wm that start firefox with qvm-run --dispvm app-firefox /usr/bin/firefox-esr

A kuhb configuration directory defines the required variables required for creating VMs in Qubes OS, for example the name “firefox” and the scripts from kuhbs/<name>/tpl/scripts/ and so on.

kuhb/my-kuhb/config.sh

The following are all possible variables in the kuhbs/my-kuhb/config.sh file. As the file is BASH, variables start with declare -r to make them immutable.

KUHB_TYPE (mandatory)

The KUHB_TYPE variable is the only mandatory variable in the kuhbs/my-kuhb/config.sh file.

Each kuhb is assigned a specific type. The kuhb type is the type of Qubes OS VM you want your application to run in when you use it. For example you may want to run firefox in an Unnamed DisposableVM so it does not store any data, or in an AppVM so you can save bookmarks. The following kuhb types are available:

Qubes OS VM type kuhbs shortcode
StandaloneVM sta
TemplateVM tpl
AppVM app
Named DisposableVM ndp
Unnamed DisposableVM udp

Example:

declare -r KUHB_TYPE=app

TEMPLATE

The TemplateVM to use to build the TemplateVMs. By default debian-minimal is used, as kuhbs tries to have only relevant software installed in the TemplateVMs.

declare -r TEMPLATE=debian-12-minimal

LAUNCHERS

Launchers are .desktop files for xfce or bash scripts that can be executed using dmenu in i3wm. The syntax is:

linux user | i3wm identifier | run in Unnamed DisposableVM (1 to activate) | executable

declare -r LAUNCHERS=(
    # If you just specify "terminal" as executable it will launch /usr/bin/xfce4-terminal.
    "user terminal 0 terminal"
    # In this case it will launch firefox
    "user firefox 0 /usr/bin/firefox
    # This would launch firefox in an Unnamed DisposableVM "disp0123"
    "user firefox 0 /usr/bin/firefox
)

TPL, APP and STA_BACKUP_PATHS

Paths to backup on the respective kuh classes. kuhbs only backups explicitly specified paths.

# Paths to backup on the TemplateVM
declare -r TPL_BACKUP_PATHS=(
    "/home/user"
)
# Paths to backup on the AppVM
declare -r APP_BACKUP_PATHS=(
    "/home/user"
)
# Paths to backup on the StandaloneVM
declare -r STA_BACKUP_PATHS=(
    "/home/user"
)

TPL, APP, NDP and STA_PREFS

qvm-prefs to set on the respective kuh classes.

# qvm-prefs for the TemplateVM
declare -rA TPL_PREFS=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
# qvm-prefs for the AppVM
declare -rA APP_PREFS=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
# qvm-prefs for the StandaloneVM
declare -rA STA_PREFS=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
# qvm-prefs to set for the Named DisposableVM
declare -rA NDP_PREFS=(
    ["netvm"]=ndp-kuhbs-net-gateway
)

TPL, APP, NDP and STA_SERVICES

The same as above for qvm-service.

declare -rA TPL_SERVICES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA APP_SERVICES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA STA_SERVICES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA NDP_SERVICES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)

TPL, APP, NDP and STA_FEATURES

The same as above for qvm-features.

declare -rA TPL_FEATURES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA APP_FEATURES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA STA_FEATURES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)
declare -rA NDP_FEATURES=(
    ["netvm"]=ndp-kuhbs-net-gateway
)

I3_ASSIGN

Assign windows with the string “airgap” to workspace “1|AIR”. Use the tool xprop to determine the “class”. Irrelevant if you do not plan on using i3wm.

declare -r I3_ASSIGN='assign [class="airgap"] "1|AIR"'

The kuhbs/my-kuhb/{tpl,app,ndp,sta} Directories

The kuhbs/my-kuhb/ directory contains (at maximum) the config.sh file and (a maximum of) three directories - the example below assumes that the “example” kuhb has KUHB_TYPE=ndp defined in its config.sh. Each directory corresponds to the VM type that will be created in order to create the kuhb and contains configuration and scripts for that specific VM type.

ls kuhbs/example/
config.sh tpl/ app/ ndp/

For Standalone VMs, there is only a config.sh file and a sta/ directory:

ls kuhbs/example/
config.sh sta/

If you want to create a new AppVM to run the signal-desktop chat application, a simplified configuration structure looks like this:

tree kuhbs/signal/
├── config.sh
├── tpl
│    └── scripts
│        ├── 10-apt-update.sh -> ../../../../setup-scripts/apt-update.sh
│        └── 20-install-signal-packages.sh
└── app
    └── scripts
        └── 10-xmodmap-german-umlauts.sh -> /home/user/kuhbs/setup-scripts/xmodmap-german-umlauts.sh
            └── templates
                └── .Xmodmap

The kuhbs/my-kuhb/{tpl,app,sta}/scripts/ Directory

The scripts in the kuhbs/my-kuhb/{tpl,app,sta}/scripts/ directories are executed in alphanumerical order. For example when the scripts are executed in the TemplateVM tpl-signal, the following steps are taken:

1) kuhbs combines all scripts in kuhbs/my-kuhb/{tpl,app,sta}/scripts/ into one script via (simplified) cat kuhbs/signal/tpl/scripts/*sh > tempscript.sh. DO NOT begin scripts in this directory with #!/bin/bash! Because kuhbs has to copy the script to the VM, open a graphical terminal in the VM and execute the script each time it wants to run a script, combining all scripts into one is a lot faster when you want to execute 10 scripts, as each time a script finishes execution, kuhbs keeps the terminal open for 5 seconds so you can read the output. kuhbs also prepends set -e -x to the tempscript.sh - set -e causes scripts to abort on shell exit status != 0 and set -x causes BASH to print every command to the screen before executing it, example:

set -x
echo kuhbs
+ echo kuhbs
kuhbs

2) kuhbs copies the script to tpl-signal

3) kuhbs runs the script on the VM using (simplified) qvm-run --user root tpl-signal "xterm -c /home/user/QubesIncoming/dom0/tempscript.sh"

The kuhbs/my-kuhb/{tpl,app,sta}/scripts/templates/ Directory

This directory, if present, is copied to the VM before the scripts are executed. At the end of the scripts execution, a rm -rf /home/user/QubesIncoming is executed on the VM.

The kuhbs/my-kuhb/{tpl,app,ndp,sta}/hooks/ Directory

These directories can, when required, contain scripts with the following names. Scripts in the kuhbs/my-kuhb/{tpl,app,ndp,sta}/hooks/ directories are EXECUTED IN DOM0 AND NOT THE VM!!! and have to start with #!/bin/bash (or #!/usr/bin/env python3 or whatever else you prefer).

kuhbs/signal/{tpl,app,ndp,sta}/hooks/create-pre.sh

This script, if present and executable, is executed before the configuration scripts are executed.

kuhbs/signal/{tpl,app,ndp,sta}/hooks/create-post.sh

This script, if present and executable, is executed after the configuration scripts are executed.

kuhbs/signal/{tpl,app,ndp,sta}/hooks/remove-pre.sh

This script, if present and executable, is executed before a VM is deleted.

kuhbs/signal/{tpl,app,ndp,sta}/hooks/remove-post.sh

This script, if present and executable, is executed after a VM has been deleted.

kuhbs/signal/{tpl,app,ndp,sta}/hooks/backup-pre.sh

This script, if present and executable, is executed before a VM is backed up.

kuhbs/signal/{tpl,app,ndp,sta}/hooks/backup-post.sh

This script, if present and executable, is executed after a VM is backed up.

Example of All Possible kuhb Configuration Files and Directories

The following tree output contains all possible script locations:

tree kuhbs/superkuhb/
├── config.sh
├── tpl
│   ├── scripts
│   │   ├── 10-apt-update.sh -> ../../../../setup-scripts/apt-update.sh
│   │   └── 20-signal-packages.sh
│   ├── templates
│   │   └── somefile.txt
│   └── hooks
│       ├── create-pre.sh
│       ├── create-post.sh
│       ├── update-pre.sh
│       ├── update-post.sh
│       ├── backup-pre.sh
│       ├── backup-post.sh
│       └── remove.sh
├───app
│   ├── scripts
│   │   └── 10-install-flatpak-packages.sh
│   ├── templates
│   │   └── home
│   │       └── user
│   │           └── .foobar.conf
│   └── hooks  
│       ├── create-pre.sh
│       ├── create-post.sh
│       ├── update-pre.sh
│       ├── update-post.sh
│       ├── backup-pre.sh
│       ├── backup-post.sh
│       └── remove.sh
└── ndp
    └── hooks  
        ├── create-pre.sh
        ├── create-post.sh
        └── remove.sh

Named DisposableVMs do not store data persistently, hence backup hooks, update hooks, scripts/ and templates/ are not available.

An Unnamed DisposableVM udp only “consists” of launchers which start the Unnamed DisposableVM from an AppVM - its VMs only exist while running and are deleted immediately after shutdown. Hence, the “udp” does not have its own configuration directory in kuhbs.

A StandaloneVM would contain the following configuration files:

standalone-kuhb
├── config.sh
└── sta
    ├── scripts
    │   ├── 10-apt-update.sh -> ../../../../setup-scripts/apt-update.sh
    │   ├── 20-signal-packages.sh
    │   └── 30-launcher.sh
    ├── templates
    │   └── etc
    │       └── apt-cacher-ng
    │           └── acng.conf
    └── hooks
        ├── create-pre.sh
        ├── create-post.sh
        ├── update-pre.sh
        ├── update-post.sh
        ├── backup-pre.sh
        ├── backup-post.sh
        └── remove.sh

Windows kuhb

Windows is WIP.

Examples

Example kuhb’s can be found in the kuhbs-examples/ directory of this git repository.

A TODO is to put individual kuhb configurations into their own git repositories.