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.
manage.nervescloud.com as the host. Swap in your own if self-hosting.
1
Install the NervesHub CLI
The After installing, authenticate with your NervesCloud account:This opens a browser window to complete authentication and stores a token locally for subsequent CLI commands.
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.- macOS (Homebrew)
- Linux / macOS (curl)
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.3
Create the project
4
Create a product and shared secret
In the web UI:
- Create or choose an organization.
- Create a product (name it
my_appto match, for convenience). - 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 Replace
config/target.exs: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.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
PATH.Self-hosting? Point it at your instance first: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 The
@version field in mix.exs to "0.2.0"), then build and upload the firmware: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.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 Replace
main, then activate it:<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:
- Download the new firmware.
- Verify the signature against the embedded public key.
- Apply the update using fwup.
- Reboot into the new firmware.
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 Or upload in the web UI under Firmware → Upload.
mix.exs, then:16
Create a deployment group
Web UI → Deployment Groups → New:
- Select the firmware you just published as the release.
- Set targeting conditions (version + tags). Leave tags empty for now so it matches your device.
- Save and mark it active.
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.

