OMBRA

Installing Ombra

Three paths: import the prebuilt OVAs into Fusion (next section), run the guided build below, or build by hand (steps 1-7). A final section covers exporting the OVAs, for maintainers.

Guided build

curl -fsSL https://ombra-os.org/build.sh | bash

The script is scripts/build.sh. It checks the Mac, installs missing tools with Homebrew after asking, verifies the pinned downloads, builds, and creates and installs both VMs. --isos-only stops after the installer ISOs; --yes answers every prompt.

Quick start: requirements

Quick start: the release OVAs

  1. Download ombra-gateway-arm64-v1.0.0.ova, ombra-desktop-arm64-v1.0.0.ova and SHA256SUMS.txt from the download page into one folder, and verify what you downloaded:

    shasum -a 256 -c SHA256SUMS.txt --ignore-missing
    

    Every file you did download must report OK.

  2. Double-click each .ova (or use File > Import in Fusion) and import it. Accept the defaults; Fusion may warn that the OVA was not signed. Nothing needs changing in the VM settings.

  3. Power on the gateway first and pick a boot mode (below), let it reach its health report, then power on the desktop, pick a boot mode, and continue with First boot below.

Boot modes

Both VMs start at an Ombra boot menu with two entries and wait for your choice; nothing starts on its own.

Pick Persistent for the desktop's first boot. You can restart into either mode at any time.

Requirements (building from source)

Tor Browser ships from the alpha channel (16.0a13): it is the only channel that publishes linux-aarch64 builds.

1. Fetch the pinned Debian netinst

The exact ISO is pinned in build/pins/debian-netinst-arm64.txt — read it for the filename, size and sha256, and download it from the source listed there into build/isos/:

mkdir -p build/isos
curl -L -o build/isos/debian-13.7.0-arm64-netinst.iso \
  https://cdimage.debian.org/debian-cd/current/arm64/iso-cd/debian-13.7.0-arm64-netinst.iso
bash build/verify-iso.sh

If the current path no longer carries the pinned file (a newer Debian point release superseded it), fetch it from the archive instead: https://cdimage.debian.org/cdimage/archive/13.7.0/arm64/iso-cd/.

verify-iso.sh checks size and sha256 against the pin; it fails loud on any mismatch. Do not build from an unverified ISO.

2. Build the Rust binaries

cd core
bash build.sh

This cross-compiles aarch64 musl-static binaries into core/dist/aarch64/. Copy them into the desktop overlay (the ISO build refuses to run if the overlay binaries drift from dist/):

cp dist/aarch64/ombra-askpass dist/aarch64/ombra-welcome \
   ../desktop/rootfs/usr/local/libexec/ombra/
cp dist/aarch64/ombra dist/aarch64/ombra-statusd \
   ../desktop/rootfs/usr/local/bin/
cp dist/aarch64/ombra-torctl-filter \
   ../gateway/rootfs/usr/local/bin/
cd ..

3. Stage the pinned Tor Browser (desktop ISO only)

The desktop ISO carries the sha256-pinned Tor Browser tarball (alpha channel, the only one with linux-aarch64 builds); it is verified again inside the installer. Fetch the exact file named in build/pins/torbrowser.txt and place it in build/vendor/ (the directory is gitignored). Superseded alpha builds move to Tor's archive, so use the pin's archive_url:

mkdir -p build/vendor
curl -L -o build/vendor/tor-browser-linux-aarch64-16.0a13.tar.xz \
  https://archive.torproject.org/tor-package-archive/torbrowser/16.0a13/tor-browser-linux-aarch64-16.0a13.tar.xz
shasum -a 256 build/vendor/tor-browser-linux-aarch64-16.0a13.tar.xz

The hash must equal the pin's sha256= line; make-install-iso.sh re-checks it before staging.

4. Build the installer ISOs

bash build/make-install-iso.sh gateway
bash build/make-install-iso.sh desktop

Output: build/disks/ombra-install-gateway.iso and build/disks/ombra-install-desktop.iso. Each ISO is self-contained: preseed, overlay and pinned payload travel inside the netinst initrd.

5. Create the VMs

VMware Fusion must be installed; nothing else is needed on the host. Disconnect any VPN that intercepts DNS before installing; if installs cannot resolve Debian mirrors, restart Fusion's network daemons (vmnet-cli --stop / --start) and retry.

Install the gateway first, and leave it running: the desktop's real network (DNS, Tor) runs through it.

bash build/fusion/create-gateway-vm.sh

The script instantiates the VM from the proven template (pinned MACs, NVMe, no shared folders, clipboard/drag-and-drop/HGFS isolation keys), attaches the installer ISO and starts it. The install is unattended, ~5-15 minutes, and the VM powers itself off when done.

Then finish the gateway on the host side:

bash build/fusion/post-install-gateway.sh              # connect NIC2, detach CD, disk-first, start
bash build/fusion/post-install-gateway.sh --no-start   # same, leave it powered off

Same shape for the desktop, once the gateway is up:

bash build/fusion/create-desktop-vm.sh
# after the installer powers the VM off:
bash build/fusion/post-install-desktop.sh              # NIC to "Private to my Mac", detach CD, disk-first, start

Both post-install scripts accept an explicit vmx path, are idempotent, strip install-time debug keys, and refuse to run while the VM is powered on.

To audit an existing VM against the pinned shape (add --fix to repair what is fixable; the vmx is located by its display name, or pass its path):

bash build/fusion/create-gateway-vm.sh --verify --fix
bash build/fusion/create-desktop-vm.sh --verify --fix "$HOME/Virtual Machines.localized/ombra-desktop.vmwarevm/ombra-desktop.vmx"

6. The install

7. First boot

Updates

Export the release OVAs (maintainers)

Start from freshly installed VMs, both powered off, both post-installed. The desktop must never have been booted.

bash build/fusion/export-release-image.sh gateway
bash build/fusion/export-release-image.sh desktop
bash build/fusion/verify-ova.sh build/releases/ombra-gateway-arm64-v1.0.0.ova
bash build/fusion/verify-ova.sh build/releases/ombra-desktop-arm64-v1.0.0.ova

The export strips builder residue from a copy of the VM bundle, runs ovftool, and writes a single file per VM (the disk is compressed inside; an encrypted disk does not shrink further). Set OMBRA_SPLIT=1 to split into .ova.part-aa, .part-ab, ... under GitHub's 2 GiB release-asset cap for GitHub-only hosting. Output lands in build/releases/ with one SHA256SUMS.txt, rewritten on every run with a line per artifact present; downloaders filter it with --ignore-missing. verify-ova.sh imports the OVA into a scratch directory and asserts the shipped shape of the resulting VM.

Rendered from docs/INSTALL.md in the repository.