How Omnihorn works

Updated · 6 min read · For developers, release managers, QA, IT and security

This page explains the few ideas everything in Omnihorn is built on: apps, builds, channels, the signed manifest, the installer and the update loop. Read it once before you plan releases. It is written for developers, release managers, QA and IT who need to know what happens between an upload and an installed copy.

The short version

You upload a build of your app. Omnihorn scans it, signs a list of its files and stores it. A channel points at one build. Installed copies of your app ask their channel whether there is something newer, check the signature, download only the files that changed, verify each one and swap them in. The installer your users download is small: it carries no app files, and on first run it fetches them through the same path every later update uses.

From upload to installed copy

  1. You upload a folder or archive from the Builds tab, or from CI with an API key. Your browser hashes every file first, and files Omnihorn already has from your earlier uploads are not uploaded again.
  2. Omnihorn processes the build. Every new file’s hash and size are checked, and files are scanned for malware where the platform has scanning switched on. Omnihorn then writes the build’s manifest (every file path, size and SHA-256 hash) and signs it with your app’s private key. The build becomes active.
  3. A channel points at the build. You choose it on the channel page, or a channel that follows a Git branch takes it from CI. Until a channel points at a build, no user receives it.
  4. An installed copy checks its channel. It gets the signed manifest and verifies the signature against the public key built into its installer. A manifest that fails the check is refused.
  5. It downloads only what changed. Files whose hash already matches the disk are skipped. Each downloaded file is checked against its SHA-256 hash from the manifest.
  6. It applies the update atomically. The old files are kept until the new ones are in place; if anything fails, the previous version is restored. Then the program you chose as the launch target starts.

Apps

An app is one product you ship, such as your editor or your launcher. It owns its builds, channels, installer designs and CI keys. When you create an app, Omnihorn creates an Ed25519 key pair for it. The private key stays on the server and signs every manifest; the public key is built into the app’s installer. Each app also starts with a channel named production.

Builds

A build is one upload of your app’s files, with a version. You type a base version such as 1.4.0 and Omnihorn adds its own counter, so the stored version is 1.4.0+build.42. The counter only goes up, per app. A build’s files never change after upload. To fix something, you upload a new build. Only its release notes (“What’s new”) can be edited later.

A build moves through processing to active, or to failed with a reason. Only active builds can be assigned to a channel. Details are in Upload builds.

Channels

A channel is a named track that installed copies follow, such as production or beta. It points at exactly one build at a time. Moving the pointer is how you release, and moving it back to an older build is how you roll back. Each installed copy follows one channel, chosen by the installer it came from.

A channel is either public, protected by a password, or open only to holders of a channel token. Each channel also sets how often installed copies may check for updates. See Channels and rollouts.

The signed manifest

The manifest is the list of every file in a build with its path, size and SHA-256 hash, signed with your app’s private key. Installers verify the signature over the exact bytes they receive, then check each path is safe (no absolute paths, no .., no Windows device names) before anything is downloaded or written. Download links are not part of the signed data: they are requested separately, just before a download starts, and expire after a few hours. More in Security.

The installer

The installer is one standalone setup.exe that Omnihorn builds for you. Its look, its launch target and its start-up and shortcut options come from an installer design on the Installer tab. Each channel ships one design, and each channel gets its own installer. You build it on request with Create installer or Build installer; it is not rebuilt on every upload, because it does not contain your files.

Installers are not code-signed by default, so Windows SmartScreen shows an “Unknown publisher” warning until a certificate is in place. See Installer Studio.

The update loop

After the first install, the installer registers a small background check that runs once per Windows start-up. It does nothing if the channel’s check interval has not passed. Otherwise it waits a random few minutes, asks the channel, and applies any update without a window. It is not a service that stays running. The interval can be a number of hours, every start-up, or manual only. See Updates on user machines.

Glossary

TermMeaning
WorkspaceYour account’s container for apps, members and the plan.
AppOne product you ship. Owns builds, channels, installer designs and CI keys.
BuildOne upload of the app’s files with a version, such as 1.4.0+build.42. Never changes after upload.
ActiveA build that passed scanning and verification and has a signed manifest. Only active builds can be assigned.
ChannelA named track (production, beta) that points at one build. Installed copies follow one channel.
Assigned buildThe build a channel currently offers. Changing it releases or rolls back.
ManifestThe signed list of a build’s files with sizes and SHA-256 hashes.
Channel tokenA secret that lets an installer use a channel that is not public.
Installer designThe look, launch target and shortcut options of an installer, edited in Installer Studio.
Launch targetWhat the installer starts after install and after each update.
Check intervalHow often installed copies on a channel may look for updates.
API keyA per-app key that lets CI upload builds. Shown once when created.
›Does uploading a build release it to users?

Not by itself. A build reaches users only when a channel points at it. The first build in the app wizard goes live on production, and a channel that follows a Git branch takes matching CI builds automatically.

›What stops someone from serving my users a fake update?

Every manifest is signed with your app’s private key, and the installer checks that signature with the public key it was built with. Each downloaded file must also match its SHA-256 hash from the manifest.

›Do users download the whole app on every update?

No. Files whose hash already matches the installed copy are skipped, so an update downloads only the files that changed.

›Why is the installer so small?

It does not contain your app. On first run it downloads your files from its channel, the same way it downloads later updates.

Something wrong or missing? Tell us.