Configure NervesHubLink

Configure the NervesHubLink device client: connection, authentication, remote IEx, update behavior, retries, CA certs, and proxies.

Written By Josh Kalderimis

Last updated About 2 months ago

nerves_hub_link is the device-side client that connects your Nerves device to NervesHub. This guide covers the configuration options you'll reach for most often.

All options go under config :nerves_hub_link in your target config (for example config/target.exs), unless noted otherwise.

Minimum connection config

At minimum, a device needs the platform host and a way to authenticate. Shared secret is the simplest:

config :nerves_hub_link,
  host: "devices.nervescloud.com",
  shared_secret: [
    product_key: "<product_key>",
    product_secret: "<product_secret>"
  ]

For the other authentication methods (NervesKey, TPM, and file-based certificates), see Device authentication & mTLS and Production setup with NervesKey.

Remote IEx access

Remote IEx is off by default. Turn it on to open a live console from the web UI:

config :nerves_hub_link, remote_iex: true

The IEx process starts on the first request and stops after 5 minutes of inactivity. Change the timeout (in seconds):

config :nerves_hub_link, remote_iex_timeout: 900

Users also need permission on NervesHub to use the console.

Control when updates apply

By default a device applies updates as soon as they're offered. To add your own logic, implement NervesHubLink.Client and point the config at it:

defmodule MyApp.NervesHubLinkClient do
  @behaviour NervesHubLink.Client

  @impl NervesHubLink.Client
  def update_available(data) do
    if MyApp.good_time_to_update?(data) do
      :apply
    else
      {:reschedule, 60_000}
    end
  end
end
config :nerves_hub_link, client: MyApp.NervesHubLinkClient

update_available/1 can return :apply, :ignore, or {:reschedule, milliseconds}.

Report update progress

The same client module can handle firmware progress and result messages:

def handle_fwup_message({:progress, percent}) do
  Logger.info("Update progress: #{percent}%")
  :ok
end

def handle_fwup_message({:error, _code, message}) do
  Logger.error("Update error: #{message}")
  :ok
end

Retry firmware downloads

Downloads recover from network drops automatically. Tune the behavior with :retry_config:

config :nerves_hub_link, :retry_config,
  max_disconnects: 20,
  idle_timeout: 75_000,
  max_timeout: 10_800_000

See NervesHubLink.Downloader.RetryConfig for all options.

CA certificates (self-hosted / self-signed)

The device uses its installed CA certificates by default, and picks up CAStore automatically if it's a dependency. If you run your own NervesHub with self-signed certificates, provide your own CA store:

config :nerves_hub_link, ca_store: MyModule

MyModule.ca_certs/0 must return a list of DER-encoded certificates. You can also set cacerts directly on :ssl (for the socket) or :downloader_ssl (for firmware downloads):

config :nerves_hub_link, ssl: [cacerts: my_der_list]

HTTP proxy

Route both the websocket and the downloader through a proxy. The value is passed to Mint.HTTP.connect/4:

proxy = {:http, "proxy.example.com", 8080, []}

config :nerves_hub_link,
  socket: [http_opts: [proxy: proxy]],
  downloader_http_opts: [proxy: proxy]

Extra fwup arguments

Pass additional fwup CLI arguments as a list of strings:

config :nerves_hub_link, fwup_extra_options: ["--unsafe"]

Wait for the network

Before its first connection, the client checks that host resolves, retrying every 2 seconds. Disable that check if you handle network readiness yourself:

config :nerves_hub_link, connect_wait_for_network: false

Custom configurator (advanced)

For full control, implement NervesHubLink.Configurator. It runs at startup with the default config and returns the config to connect with, which is useful for choosing a cert/key at runtime or reading a certificate from disk:

defmodule MyApp.Configurator do
  @behaviour NervesHubLink.Configurator

  @impl NervesHubLink.Configurator
  def build(config) do
    ssl = [certfile: "/root/ssl/cert.pem", keyfile: "/root/ssl/key.pem"]
    %{config | ssl: ssl}
  end
end
config :nerves_hub_link, configurator: MyApp.Configurator

Disable during tests

Stop the client from connecting in your test environment:

# config/test.exs
config :nerves_hub_link, connect: false

Extensions (Health, Geo, Local Shell)

Health and Geo reporting and the local shell are configured under nerves_hub_link too. See Device health, metrics & geo for metric sets, custom resolvers, and alarms.

Related