This article will go through the steps to setup a simple development environment for the Onion Omega. With the help of some simple scripts and trivial configuration it is possible to increase the speed of the development cycle. Instead of ssh-ing into the device and using vi(m), after completion of the setup, you will be able to develop with the tools you are used to, test the code, and deploy to the Onion Omega in one fluent motion.
To have some code to deploy, first create a project folder and add a couple of directories to it to keep things organized.
$ mkdir myproject
You can name the project root directory to your liking, but the rest of the article will assume
myproject to be the name of the project.
./src create the file
sensor.js with the following content
var net = require('net');
This node script will attempt to connect to a server and periodically send a message.
Deployment should be as smooth as possible so we do not want to type credentials on every deploy. However, we most probably want to secure the device so that it is not that trivial to deploy to it.
First, let’s create and copy a public ssh key
This will ask you for some information, and then creates and saves a public key in
Next, we need to upload this public key to the omega
$ ssh-copy-id -i ~/.ssh/id_rsa.pub remote-host
When you started out with a factory onion remote-host is something like
For the key to work on the omega we need one extra step. OpenWRT looks for the keys in
/etc/dropbear/authorized_keys so we need to copy/move the authorized_key file
$ mv .ssh/authorized_keys /etc/dropbear/authorized_keys
To check if it works, just try to ssh into the omega
$ ssh [email protected]
This should let you login to the omega without asking you for credentials, if however a passphrase was set on the ssh key this would still have to be typed at least once.
Even though this work fine, we still are able to login with the credentials, this might be a security risk, therefore we’ll disable password login by executing
$ uci export dropbear
Create deploy script
With the example project and ssh keys set up we can now look at deployment. The deployment will be done with the help of a script which leverages rsync to sync our project source to a dedicated path on the onion.
deploy.sh file in the scripts directory with the following content
The script enable us to do a couple of things. The first is a deployment dry run. Running the script without only the host argument will give information about what would be done on this deploy but not do the actual deploy.
$ ./scripts/deploy.sh [email protected]
The script will only sync the content of the src directory to /var/sensor on the Omega.
To make a real deploy, a second argument must be passed.
$ ./scripts/deploy.sh [email protected] production
The actual value of the second argument doesn’t matter at this point, but could be used to enable extra options on deploy, such as minifying or generating documentation. The source can now be found on the Omega in the /var/sensor directory. Note that this directory is actually a symlink to /tmp on the device.
Possible enhancements to the script that I’ll leave to the reader are e.g
- checking space on device before deploy
- check if node is installed before deploy
We can deploy now, but you might notice that while the source gets updated automatically we still need to restart the node process by hand. To fix this we can create an init script. A basic init script looks like
This script should be placed on the Omage at
/etc/init.d/sensor, where sensor is our made up service name. To enable the script we first need to run
$ /etc/init.d/sensor enable
The service can now be started with
$ /etc/init.d/sensor start
To restart the service after each deploy we could add the following lines to the deploy script directly after line 10.
ssh $1 -t /etc/init.d/sensor stop;
See it in action
To see it all in action first figure out your development machines ip with
nmap -sn 192.168.x.0/24.
Your ip may vary. Run a tcp server on your dev machine for quick verification with
nc -l 13370, where the last number is the port that the client expects to send its data to. This will in run a simple tcp server that can be reached by
Now deploy your latest changes with the deploy script, this should start the client. Make sure the
PORT and HOST variables are set to match the tcp server you just started.
The TCP server output should now show the data that is send periodically by the client.
I’ll leave the testing part as an exercise to the user. The test do not need to be deployed to the device, but they would need to be run before deployment. A simple line could be added to both the dry run and actual deployment blocks. For example when adding a package.json (with
npm init) to the project you’d run the tests with
$ npm test
Which would then run whatever you configured in the package.json test script.
As the storage is limited on the Omega (when not using external storage) I do not install any node modules on the Omega and only use the features that are listed in the Node.js documentation. The test however do probably depend on testing modules such as mocha, but these would be defined in the package.json as devDependencies and would be run on the host (development machine).
- Onion, Invention Platform for IoT.
- OpenWrt, an embedded operating system based on Linux.
- Secure Shell (SSH), a cryptographic network protocol.
- rsync, a utility for efficiently transferring and synchronizing files across computer systems.
- Unified Configuration Interface (UCI), intended to centralize the configuration of OpenWrt.