Nodal Pain

Although I’m not a fan of home automation nor an active part of the hobbyist IoT craze, I do have a few things I like to keep tabs on at home, so I’ve been doing relatively harmless (and definitely not @internetofshit-worthy) stuff in that field for a while.

For instance, most of my machines talk to each other in two ways:

  • By sending out UDP multicast packets with system stats
  • Using an MQTT broker to pass around the data required for assorted data processing stuff and a few alerts

A few years ago I tried doing all those things with Node-RED, but it was too slow on ARM6 hardware. Furthermore, building NodeJS and most of the interesting modules was extremely time-consuming, nigh on impossible or both.

I soon gave up and just used Python and Go instead, but now that ARM hardware is much faster and NodeJS has “matured”, I decided to have another go at it on two fronts:

Let’s just say that it hasn’t been a gratifying weekend.

Getting Node Up and Running

First off, NodeJS by itself is still a pain to deal with. Alpine Linux 3.5 ships with Node 6.9.2, which means building a container with it in armhf is trivial, but I had no such luck on the Zero W, since Raspbian ships with a hopelessly outdated version of Node and I couldn’t use the container on its ARM6 CPU.

So I had to go and grab a prebuilt ARM6 binary like so:

wget https://nodejs.org/dist/v6.9.2/node-v6.9.2-linux-armv6l.tar.xz
tar -xvf node-v6.9.2-linux-armv6l.tar.xz
cd node-v6.9.2-linux-armv6l
sudo cp -R bin/ /usr/local/
sudo cp -R include /usr/local/
sudo cp -R lib/ /usr/local/
sudo cp -R share/ /usr/local/
cd .. && rm -rf node-v6.9.2-linux-armv6l*

Building Pains

However, both building the container and deploying Node-RED was a chore. npm was unbearably slow even on an ODROID-U2 with EMMC storage, and watching it perform its travesti of dependency management by downloading 34 nearly identical copies of the same library quickly became old.

The worst part, however, was that multiple modules failed to install inside the container (and on the native hardware) either because they were written for outdated Node versions or (and this is the infuriating bit) because they relied on downloading x64 binaries or their own hard-coded dependencies (the sqlite module unaccountably failed to use the local libraries, for instance, and an apparently harmless module actually tried to download a prebuilt PhantomJS executable).

Given that even essential, bread-and butter stuff like bcrypt failed to compile on both ARM7 and ARM6, I have to keep rating the entire solution as brittle – but at least I finally got a container going, which means I can have reproducible deployments.

And, with luck, I might even be able to get something done with it next weekend…


See Also: