Google Omaha Tutorial

Google Omaha is the technology which implements Chrome's update mechanism. It is open source but difficult to set up. This tutorial gives an overview how it works. You will even learn how you can integrate Omaha to update your own applications.

How the Chrome updater works

When you install Chrome, you are actually running a binary built with Omaha. This binary contacts Google's servers and asks "what's the latest version of Chrome?" The server responds with the URL of a .exe file that can be used to install Chrome. Omaha downloads this file and runs it. It also displays a simple GUI with progress information:

The .exe which was downloaded by Omaha installs Chrome into C:\Program Files (x86)\Google\Chrome. It also creates registry keys at HKLM\Software\Wow6432Node\Google\Update\Clients:

If you're wondering about Program Files (x86) and Wow6432Node, that's because Omaha is still a 32-bit application, probably for maximum compatibility with existing systems.

The registry keys in the screenshot are a vital point of communication between Omaha and the applications it manages. Each application that wants to be kept up to date by Omaha needs to have a registry key under Software\​Wow6432Node\​Google\​Update\​Clients. Chrome is registered there under the globally constant id {8A69D345-D564-463c-AFF1-A69D9E530F96}. You can see in the screenshot that its version is 52.0.2743.116. Another interesting id is {430FD4D0-...}. This is the key Omaha uses to update itself! ;-)

Omaha also sets up two tasks in the Windows Task Scheduler:

You sometimes see them as GoogleUpdate.exe in the Task Manager:

When the update tasks run, Omaha looks at the registry keys shown above to see which applications need to be updated, and what versions they are at. It sends this information to the update server. If a new version is available, the server responds with the URL of an .exe file which can be used to update the respective application.

A nice feature of this binary-based approach is that Omaha and the update server are completely agnostic of the applications they manage. The only thing the two components need are executables which perform the application-specific update/installation steps.

Another important feature of Omaha is that it handles permission issues. For example, Chrome may be installed with an administrator account, but then run under a normal user account without permissions to perform updates. Omaha performs all update and installation tasks with the same privileges as the original installation. This for instance allows a non-privileged user to "check for updates" in a system-wide installation.

Using Omaha in your own projects

The rest of the tutorial will now give you first-hand experience with using Omaha. You will create a very basic application, upload it to an update server, then use Omaha to release a new version.

To continue, you need to be on a Windows computer with administrator privileges. We also strongly recommend you install the Go programming language to follow the examples in this tutorial. Even if you prefer another language, you will get through this tutorial faster by installing Go, following the examples, and uninstalling Go again. And then you can still apply the lessons you learned here in your favorite language. So again, just install Go ;-)

Finally, you need an update server. You can get immediate access to a test server by entering your email address below:

Build an installer

As explained above, Omaha always receives executable files in response to install/update requests. For instance, the client says "I would like to install app XYZ" and the server answers "You can do this with https://.../install.exe". Likewise for updates: The client says "I have version 1.0 of XYZ, is there an update?" and the server responds "Yes, there's 1.1. You can use https://.../update.exe to update."

We will now build the most basic installer.exe. We use Go in this tutorial. In your own projects, you can also use any other programming language or installer technology. The only requirement is that you create a self-contained .exe or .msi that supports silent installation.

Please create the file install.go with the following contents:

package main

import "golang.org/x/sys/windows/registry"

func check(e error) {
   if e != nil {
       panic(e)
   }
}

func main() {
   const company = `OmahaTutorial`
   const product = `SampleApp`
   const productId = `{9B01C5D1-7F78-4A4E-A89B-0415F6466BC7}`
   const version = `0.0.1.0`

   regKey := `SOFTWARE\` + company + `\Update\Clients\` + productId
   k, _, err := registry.CreateKey(registry.LOCAL_MACHINE, regKey, registry.WRITE | registry.WOW64_32KEY)
   check(err)
   defer k.Close()
   check(k.SetStringValue("pv", version))
   check(k.SetStringValue("name", product))
}

All this code does is set two registry keys at HKLM\Software\Wow6432Node\OmahaTutorial\Update\Clients\{9B...}:

Compare this to Chrome's keys at the beginning of this tutorial: We now have ...\OmahaTutorial\Update\... while Google's keys were at ...\Google\Update\... . Extending this to your own projects, your registry keys will likely live in ...\YourCompany\Update. The final path component {9B...} in the screenshot is a randomly selected id for our application.

Assuming Go is on your PATH, you should be able to build install.go from the directory containing it:

set GOPATH=%cd%
go get golang.org/x/sys/windows/registry
go build install.go

When you run the generated install.exe from a command prompt with administrative privileges, the registry key in the screenshot should be created.

You may wonder why we are setting these strange registry keys. The reason is that if we don't, then Omaha believes that the installation of our application failed. The registry is thus a crucial point of contact between our app and Omaha.

Upload the installer to the server

Log in to /admin on your update server. Click on Omaha/Applications on the left-hand side. Add an application with Id the same value as the productId above and name the value from product. Do include the curly braces {} in the id:

Click on Versions on the left. Add a version for your app, in the stable channel, with number the same as version in the install script. Upload install.exe from the previous step as the file. Click "Add another Action" at the bottom. Select install as Event and enter install.exe into Run. Click Save.

Install your app with Omaha!

We can now use Omaha to install our sample application. Do you remember from above that our registry keys were at ...\OmahaTutorial\Update instead of ...\Google\Update? In your own projects, you will likely have ...\YourCompany\Update. But you will have further changes: In particular, you will use your own update server, not Google's, for distributing updates.

Omaha hard-codes values such as the update server URL and registry key names in its C++ implementation. To prevent you from having to dig into C++ for this tutorial, we will use a trick to make Omaha fetch updates from your server: Set the registry value HKLM\Software\Wow6432Node\OmahaTutorial\UpdateDev\url to your update server domain plus /service/update2 as in this screenshot:

Omaha respects this key as an override for its hard-coded values.

Now delete the OmahaTutorial\Update registry key again. It will be re-created when Omaha executes our install.exe from above.

To make Omaha install our application, download and run SampleAppSetup.exe. This is our equivalent of ChromeSetup.exe: It is an online installer built with Omaha that is configured to use registry keys in OmahaTutorial\Update and install the application with our id {9B...} from the server. If all went well, you should eventually see the following window:

You should also have the OmahaTutorial\Update\Clients\{9B...} registry key again. This proves that Omaha downloaded and executed our install.exe. If that is the case, then congratulations! You just installed your first application with Omaha. If not, please see the Troubleshooting section at the end.

Releasing a new version

To release a new version of our application, change the version variable in install.go to 0.0.2.0, then re-compile to get a new copy of install.exe. Log into the update server's admin interface, and create a new Version for your app. Ensure you use the new version number 0.0.2.0. Upload the newly generated install.exe. Click Add another Action at the bottom. This time however, select update as event. Enter install.exe into Run. Finally, click Save.

By default, Omaha checks for updates every 24 hours in the background. To force an immediate update check, perform the following steps:

1. Open a command prompt as Administrator and type the following command:

taskkill /IM OmahaTutorialUpdate.exe /F

This shuts down all running instances of Omaha.

2. Delete the registry value HKLM\Software\Wow6432Node\OmahaTutorial\Update\LastChecked (if it exists).

3. Open the Windows Task Scheduler and run OmahaTutorialUpdateTaskMachineUA. Note how it appears next to Google's update tasks. Pretty cool, right? ;-)

The task executes at a very low priority, so can take several minutes to run. Keep refreshing in the Window Task Scheduler with F5 until the task state switches from Running back to Ready.

Once the task has finished running, check the version of your application in the registry at ...\OmahaTutorial\Update\Clients\{9B...}\pv. It should say 0.0.2.0:

This proves that Omaha successfully applied your update by running the new copy of install.exe, which we uploaded to the server. If you see this value, then congratulations! You have completed this tutorial. If not, please see Troubleshooting below.

Uninstalling Omaha

Omaha uninstalls itself when it sees that there are no more clients (besides itself) in the Update\Clients registry key. So to uninstall our copy, delete Update\Clients\{9B...}. Then force an update check per the instructions above. After few minutes, Omaha should have disappeared from your system.

Where to go from here

You will now likely be keen to update an actual application of yours. Here are some pointers to get you started.

On the client side, using Omaha requires creating a fork of Google's C++ implementation. As described above, this is necessary to change the update server URL, but also the names of binaries and registry keys ("YourCompany Update" instead of "Google Update").

On the server side, you need an update server that speaks the Omaha protocol. We open sourced the old Python 2 version of our implementation, but it no longer receives security fixes. If you would like access to the Python 3 implementation with the latest fixes, please get in touch. This version of the server is what you used above.

When you work on the C++ client, you will likely find that customizing it for use in your project or organization is very difficult. If you need help with this, or any other Omaha-related question, also do get in touch with us. As an agency, we specialize in helping other companies integrate Omaha into their projects. Thank you for taking our tutorial!

Appendix: Troubleshooting

If the installation with Omaha was unsuccessful with message "Unable to connect to the Internet":

Then you may not have set the UpdateDev registry key correctly. Please go back over the instructions above and check all details.

For this, and any other problems with Omaha, it can be very useful to turn on logging. You can do this by creating the file C:\OmahaTutorialUpdate.ini with the following contents:

[LoggingLevel]
LC_CORE=5
LC_NET=4
LC_PLUGIN=3
LC_SERVICE=3
LC_SETUP=3
LC_SHELL=3
LC_UTIL=3

LC_OPT=3
LC_REPORT=3

[LoggingSettings]
EnableLogging=1
LogFilePath="C:\Omaha log.txt"
MaxLogFileSize=10000000

ShowTime=1
LogToFile=1
AppendToFile=1
LogToStdOut=0
LogToOutputDebug=1

[DebugSettings]
SkipServerReport=1
NoSendDumpToServer=1
NoSendStackToServer=1

This snippet is from Omaha's documentation. It works if you are running a debug build of Omaha. It produces c:\Omaha log.txt, which you can inspect for any glaring error messages. What may further be enlightening is to search for <request> / <response> in the log and compare this with the protocol specification. Of course, you can always also just get in touch with us for help: