Skip to main content
This quickstart gets a Nerves device receiving an OTA update from NervesCloud using the simplest setup: shared-secret auth. The end result is a Nerves project connected to NervesHub, a device visible in the web UI, signed firmware uploaded, and a deployment group that ships the update.
Shared secrets suit hobby and R&D projects. For production, use certificate auth. See X.509 device certificates.

Prerequisites

  • A working Nerves setup (Elixir, Nerves bootstrap, fwup).
  • A supported target (e.g. Raspberry Pi) and an SD card.
  • An account on NervesCloud or a self-hosted instance.
This guide uses manage.nervescloud.com as the host. Swap in your own if self-hosting.
1

Install the NervesHub CLI

The nh CLI is the primary tool for uploading firmware and managing rollouts from your terminal or CI pipeline. Install it now so you can create a signing key before building your first firmware image.
After installing, authenticate with your NervesCloud account:
This opens a browser window to complete authentication and stores a token locally for subsequent CLI commands.
2

Create a Firmware Signing Key

NervesHub requires firmware to be signed before it can be uploaded. Create a signing key pair with the CLI:
This generates a key pair and registers the public key with NervesCloud. The private key is stored locally and is never transmitted.Next, retrieve the base64-encoded public key so you can embed it in your firmware image. Devices use this key to independently verify every OTA update before applying it:
Copy the Public Key value shown for my-key — you’ll add it to your project configuration in the next step.
Back up your signing key’s private key material. If you lose it, you cannot sign future firmware updates with the same key, and you may need to provision a new key to your devices out-of-band.
3

Create the project

4

Create a product and shared secret

In the web UI:
  1. Create or choose an organization.
  2. Create a product (name it my_app to match, for convenience).
  3. Settings → Shared Secrets → New. Copy the product key and product secret.
5

Add NervesHubLink

In mix.exs, add it to your target deps:
6

Configure the shared secret

In config/target.exs:
Replace YOUR_BASE64_PUBLIC_KEY with the public key value from nh key list, and replace YOUR_PRODUCT_KEY / YOUR_PRODUCT_SECRET with the values you copied from NervesCloud.The fwup_public_keys list tells the device which signing keys to trust when verifying OTA firmware. A device will reject any firmware update whose signature does not match a key in this list.
Keep real secrets out of version control. Read them from the environment for anything beyond a quick test.
7

Build and burn

mix firmware compiles your project and packages it as a signed .fw file using fwup. mix burn writes the image to your connected storage device. The public key you embedded in fwup_public_keys is now compiled into the device’s firmware, enabling it to verify all future OTA updates.Insert the SD card, power on. The device boots, connects, and opens a websocket to NervesHub.
8

Confirm the device connected

Web UI → your product → Devices. The device appears and shows as connected within a few moments.
9

Install the CLI

Or grab a prebuilt binary from the latest release and put it on your PATH.Self-hosting? Point it at your instance first:
Then authenticate:
10

Create firmware signing keys

Firmware must be signed. Create a key pair:
This registers the public key with your org so NervesHub can verify signatures. Keep the private key safe: you need it to sign every image. (You can also manage keys in the web UI under Settings → Signing Keys.)
11

Build, Sign, and Upload Updated Firmware

Make a visible change to your project (for example, update the @version field in mix.exs to "0.2.0"), then build and upload the firmware:
The nh firmware upload command signs the .fw file with my-key, uploads it to NervesCloud object storage, and registers it as a new firmware artifact. You’ll receive a firmware UUID in the output — note it for the next step.
Use the --deploy flag to combine uploading and shipping in a single command — ideal for CI pipelines:
12

Create and Activate a Deployment Group

A deployment group tells NervesHub which devices should receive a firmware update and under what conditions. Create one targeting devices tagged main, then activate it:
Replace <UUID> with the firmware UUID from the previous step. The group will target all devices in the product that carry the main tag.
The web console calls these deployment groups, while the nh CLI still uses the deployment command name. They are the same object.
13

Watch Your Device Auto-Update

With the group active, your online device will receive the update notification over its WebSocket connection to NervesCloud. It will:
  1. Download the new firmware.
  2. Verify the signature against the embedded public key.
  3. Apply the update using fwup.
  4. Reboot into the new firmware.
Monitor the update progress from the Devices view in NervesCloud — you’ll see the device go offline briefly during the reboot and come back online running the new firmware version.
14

Point your project at the signing key

Provide the keys via environment variables:
Paths and variable names vary by CLI version and platform. See the CLI reference. The NERVES_HUB_* equivalents also work.
15

Build and publish signed firmware

Make a visible change (e.g. a log line) and bump the version in mix.exs, then:
Or upload in the web UI under Firmware → Upload.
16

Create a deployment group

Web UI → Deployment Groups → New:
  1. Select the firmware you just published as the release.
  2. Set targeting conditions (version + tags). Leave tags empty for now so it matches your device.
  3. Save and mark it active.
Full options: Deployment groups, including staged rollouts with workflows.
17

Watch it update

With an active group pointing at newer firmware, NervesHub offers the update. The device downloads it, verifies the signature, applies it, and reboots into the new version. Track progress on the device’s page.That’s the full round trip: build → sign → publish → deploy → update. 🎉

Next steps

Device Certificates

Upgrade from Shared Secret to X.509 mTLS device certificates for production-grade security.

Delta Updates

Reduce update bandwidth dramatically by sending only the binary diff between firmware versions.

Deployment Groups

Learn how to configure concurrency limits, failure thresholds, and staged rollouts.

Remote Console

Access a live IEx session on any connected device directly from the NervesCloud UI.