This is the source code for the NervesHub firmware update and device management server.
Important
The public NervesHub instance at nerves-hub.org
was turned off on March 31st,
2022. See NervesHub Sunset.
NervesHub is still actively developed and used. Many of us run NervesHub
instances internally at our companies and really like it.
If you haven't already, make sure that your development environment has Elixir >= 1.11, Erlang 22, and NodeJS.
You'll also need fwup
and can follow these installation instructions for your platform if needed.
Additionally you will need to install xdelta3.
The instructions below use asdf
which can be installed with the
instructions below (copied from asdf-vm.com)
git clone https://github.com/asdf-vm/asdf.git ~/.asdf --branch v0.11.0
# The following steps are for Bash, which is usually the default shell
# If you’re using something else, you probably know the equivalent thing you need to do echo -e '\n. $HOME/.asdf/asdf.sh' >> ~/.bashrc
echo -e '\n. $HOME/.asdf/completions/asdf.bash' >> ~/.bashrc
Here are steps for the NodeJS setup if you're using asdf
:
cd nerves_hub_web
asdf plugin-add nodejs
bash ~/.asdf/plugins/nodejs/bin/import-release-team-keyring # this requires gpg to be installed
asdf install $(cat .tool-versions | grep nodejs)
On Debian/Ubuntu, you will also need to install the following packages:
sudo apt install docker-compose inotify-tools
Local development uses the host nerves-hub.org
for connections and cert validation. To properly map to your local running server, you'll need to add a host record for it:
echo "127.0.0.1 nerves-hub.org" | sudo tee -a /etc/hosts
NervesHub is designed to run in conjunction with another application nerves_hub_ca.
This application runs on port 8443
and it handles user's certificates. It can also be used to create a suit of certificates that
is needed in order to run both applications. When you create certificates from nerves_hub_ca
place them in dir:
nerves_hub_web/test/fixtures/ssl
.
-
Setup database connection
NervesHub currently runs with Postgres 10.7. For development, you can use a local postgres or use the configured docker image:
Using Docker
- Create directory for local data storage:
mkdir ~/db
- Copy
dev.env
to.env
and customize as needed:cp dev.env .env
- Start the database (may require sudo):
docker-compose up -d
Using local postgres
- Make sure your postgres is running
- Copy
dev.env
to.env
withcp dev.env .env
- Change any of the
DB_*
variables as needed in your.env
. For local running postgres, you would typically use these settings:
DB_USER=postgres DB_PASSWORD="" # in some cases, this might not be blank DB_PORT=5432
- Create directory for local data storage:
-
Fetch dependencies:
mix do deps.get, compile
-
Initialize the database:
make reset-db
-
Compile web assets (this only needs to be done once and requires python2):
mix assets.install
make server
- start the server processmake iex-server
- start the server with the interactive shell
Note: The whole app may need to be compiled the first time you run this, so please be patient
- Make sure you've completed your database connection setup
- Fetch and compile
test
dependencies:MIX_ENV=test mix do deps.get, compile
- Initialize the test databases:
make reset-test-db
- Run tests:
make test
NervesHub uses Client-side SSL to authorize and identify connected devices. Devices are required to provide a valid certificate that was signed using the trusted certificate authority NervesHub certificate. This certificate should be generated and kept secret and private from Internet-connected servers.
For convenience, we use the pre-generated certificates for dev
and test
.
Production certificates can be generated by following the SSL certificate
instructions in test/fixtures/README.md
and setting the following environment
variables to point to the generated key and certificate paths on the server.
NERVESHUB_SSL_KEY
NERVESHUB_SSL_CERT
NERVESHUB_SSL_CACERT
Tags are arbitrary strings, such as "stable"
or "beta"
. They can be added to
Devices and Firmware.
For a Device to be considered eligible for a given Deployment, it must have all the tags in the Deployment's "tags" condition.
OTP > 24.2.2 switched to use TLS1.3 by default and made quite a few fixes/changes
to how it is implemented in the :ssl
module. This has affected the setup of
client authentication in a few different ways depending on how you have your
server and device configured:
Server | Client | Effect |
---|---|---|
TLS1.3 | TLS1.3 | certificate_required error (needs OTP 25.2 - see erlang/otp#6106) |
TLS1.3 | TLS1.2 | CLIENT ALERT: Fatal - Handshake Failure - :unacceptable_ecdsa_key - Happens because the client is attempting to sign with :she as the signature algorithm. The workaround is to specify ssl: [signature_algs: [{:sha256, :ecdsa},{:sha512, :ecdsa}]] , e.g. as config for :nerves_hub_link . |
TLS1.2 | TLS1.3 or TLS1.2 | Successful |