LogoLogo
1.0.0
1.0.0
  • Introduction
  • High level architecture
  • Public key infrastructure
  • Terminology
  • Tutorials
    • Quickstart
    • Production Setup with NervesKey
  • Nerves Hub
    • Setup
      • Add NervesHub to your project
      • Connecting to your environment
      • Firmware signing keys
      • Products
      • Devices
      • Firmware
      • Deployments
    • Command-line tools
    • Managing organizations and products
    • Device management
    • HTTP API
    • Device WebSocket
  • Nerves Key
    • Introduction
    • NervesKey for Raspberry Pi
    • Private keys and certificates
    • General NervesKey storage
    • Provisioning in Elixir
    • Nerves integration
    • NervesHubLink integration
    • MQTT integration
Powered by GitBook
On this page
  • Connection Setup
  • Using your own Signer CA
  • Runtime Configuration
  • Client Setup
  • Example

Was this helpful?

  1. Nerves Hub
  2. Setup

Add NervesHub to your project

PreviousSetupNextConnecting to your environment

Last updated 9 months ago

Was this helpful?

The first step is to add to your target dependencies in your project's mix.exs. Since NervesHub uses SSL certificates, the time must be set on the device or certificate validity checks will fail. If you're not already setting the time, add to your dependencies. For example:

  defp deps(target) do
    [
      {:nerves_runtime, "~> 0.9"},
      {:nerves_hub_link, "~> 2.0"},
      {:nerves_hub_cli, "2.0.0-dev"},
      {:nerves_time, "~> 0.2"},
      ...
    ] ++ system(target)
  end

Next, update your config.exs so that the library can help provision devices. Do this by adding provisioning: :nerves_hub_link to the :nerves, :firmware option like this:

config :nerves, :firmware,
  provisioning: :nerves_hub_link

Adding this library will start a long-lived websocket connection with NervesHub for communicating device updates.

Connection Setup

See the section for connection setup if you are using NervesKey

If you aren't using NervesKey, you can also provide your own options to use for the NervesHub socket connection via the :socketand :ssl keys, which are forwarded on to slipstream when creating the socket connection.

Any can go in the :ssl key.

config :nerves_hub_link,
  socket: [
    json_library: Jason,
    heartbeat_interval: 45_000
  ],
  ssl: [
    cert: "some_cert_der",
    keyfile: "path/to/keyfile"
  ]

Using your own Signer CA

In some cases you may opt to use your own device signer CA when creating device certificates. If you do, there a few things needed for a successful connection:

  1. Your signer CA must be uploaded to NervesHub. You can do this a couple ways

  • From the web UI at https://www.nerves-hub.org/settings/{YOUR_ORG}/certificates/new

  • Via CLI with mix nerves_hub.ca_certificate register /path/to/signer-ca.pem

signer_cert =
  File.read!("/path/to/signer.pem")
  |> NervesHubLink.Certificate.pem_to_der()

cacerts = [signer_cert | NervesHubLink.Certificate.ca_certs()]

Runtime Configuration

Some cases require that connection configuration happens at runtime like selectively choosing which cert/key to use based on device, or reading a file stored on device which isn't available during compilation.

For example:

defmodule MyApp.Configurator do
  @behaviour NervesHubLink.Configurator

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

Then you specify which configurator NervesHubLink should use in config.exs:

config :nerves_hub_link, configurator: MyApp.Configurator

Client Setup

This let's devices hook into the decision making process and monitor the update's progress.

Example

defmodule MyApp.NervesHubLinkClient do
  @behaviour NervesHubLink.Client
  # May return:
  #  * `:apply` - apply the action immediately
  #  * `:ignore` - don't apply the action, don't ask again.
  #  * `{:reschedule, timeout_in_milliseconds}` - call this function again later.
  @impl NervesHubLink.Client
  def update_available(data) do
    if SomeInternalAPI.is_now_a_good_time_to_update?(data) do
      :apply
    else
      {:reschedule, 60_000}
    end
  end
end

To have NervesHubLink invoke it, add the following to your config.exs:

config :nerves_hub_link, client: MyApp.NervesHubLinkClient

Note: The Application config is evaluated at compile time. Extra caution is needed when using file paths in the config as they might be referencing host paths instead of device paths. Another option would be to configure at runtime (see )

The signer CA must be included in the connection request alongside the NervesHub intermediate CAs. If you're using , then this is typically handled for you. If managing certificates more manually, it is usually best to read at runtime and appened to the CA list. Here's a basically example of what that step might look like:

Whatever the reason, NervesHubLink also supports runtime configuration via the behavior. This is called during application startup to build the configuration that is to be used for the connection. When implementing the behavior, you'll receive the initial default config read in from the application environment and you can modify it however you need.

By default NervesHubLink applies updates as soon as it knows about them from the NervesHubLink server and doesn't give warning before rebooting. Optionally, you can override this behavior if desired by implementing the behaviour.

NervesKey
NervesHubLink.Configurator
NervesHubLink.Client
Runtime Configuration
nerves_hub_link
nerves_time
nerves_hub_link
valid Erlang ssl socket option
NervesKey: NervesHubLink Integration