Context
I’m following the official tutorial to bring up a minimal Nerves app and connect it to NervesCloud using Shared Secret auth (no Phoenix, no extras). The device boots fine and has network, but the NervesHubLink fails the WebSocket upgrade with 401 even though TLS handshake succeeds.
Environment
- Device: Raspberry Pi 5 (target
rpi5) - Nerves:
1.11.3 - nerves_hub_link:
2.7.3 - VintageNet:
0.13.7 - Host CLI:
nh config set uri "https://manage.nervescloud.com/"nh user auth- Org:
***, Product:my_pi(empty list of devices so far)
What I did (repro)
- New project per tutorial (minimal app, no Phoenix).
target.exs:
config :nerves_hub_link,
host: "devices.nervescloud.com",
remote_iex: true,
shared_secret: [
product_key: "NHP_...REDACTED...", # freshly rotated in UI
product_secret: "...REDACTED..."
]
- Built for
MIX_TARGET=rpi5, burned, booted. - SSH device console:
Nerves.Runtime.serial_number()
"9e5**********" # <- non-empty
:application.get_all_env(:nerves_hub_link)
[
host: "devices.nervescloud.com",
shared_secret: [
product_key: "nhp_............******....",
product_secret: "............******...."
],
remote_iex: true,
fwup_public_keys: []
]
iex(8)> :ssl.connect('devices.nervescloud.com', 443,
...(8)> [verify: :verify_peer, cacerts: :public_key.cacerts_get()], 5000)
{:ok,
{:sslsocket, {:gen_tcp, #Port<0.196>, :tls_connection, :undefined},
[#PID<0.1633.0>, #PID<0.1632.0>]}}
Application.get_env(:nerves_hub_link, :host)
"devices.nervescloud.com"
Error reapeted:
[NervesHubLink] error: {:error, {:upgrade_failure,
%{reason: %Mint.WebSocket.UpgradeFailureError{
status_code: 401,
headers: [
{"date","Thu, 14 Aug 2025 14:11:08 GMT"},
{"content-length","0"},
{"cache-control","max-age=0, private, must-revalidate"}]},
status_code: 401}}}
:alarm_handler: {:set, {NervesHubLink.Disconnected, [...]}}
I did setup secret keys few times, it is valid
The issue is in something else, I cant figure out it what
Does anyone have a clue what it can be?






















