I’ve been searching for alternatives to Kafka for some time,
and found out that NATS and/or NATS Streaming server(a.k.a. STAN) would be a good fit for it.
Unlike Kafka, NATS and STAN are:
- not dependent on JVM
- not dependent on ZooKeeper
- and quite light-weight, even run on Raspberry Pis!
They are not that famous as Kafka yet,
but are known to be used by many large companies in their production environments,
so I made up my mind to try it on my Raspberry Pis.
This post was written and tested with:
I have Go development environments on all of my Pis, so installation is not a big thing.
1. Install nats-server
gnatsd will be installed as
2. Install nats-streaming-server
nats-streaming-server will be installed as
Configure & Run
There are two Pis in my house, connected behind a router:
- 3B+: running on an external HDD, being used as a file server
- Zero W: being used as an application server
And there is one at work, also behind a router:
- 3B: camera connected, being used as an application server (mostly for hobby projects)
I plan to build a NATS cluster made up of 3B+ and Zero W,
and run STAN cluster on all three: 3B+, Zero W, and 3B.
1. Generate self-signed certificates
My NATS servers will be exposed to the outer world,
so they should be run with TLS options.
For TLS support, I needed to generate some self-signed certificates.
I used this script:
myhostname.com is the domain name to my home router.
192.168.0.102 are internal IP addresses of my Pis: 3B++ and Zero W.
2. Build a NATS/STAN cluster with two Pis
As mentioned above, two Pis - 3B+ and Zero W - are in the same local area network.
I configured my router to port-forward these two through port 60100-60102 and 60200-60202.
A. 3B+: will work as STAN (with embedded NATS)
3B+ will work as a seed(primary) NATS cluster member,
and also as a boostrap node of STAN cluster.
Configuration file for both NATS and STAN is like following:
With this config, NATS will be run on port 60100 and 60101(for cluster),
and web interface for monitoring will be run on port 60102.
Now run it with the config file:
-sc option specifies a config file for STAN, and
-c for NATS,
so this STAN server (with an embedded NATS server) can be run with this one config file only.
B. Zero W: will work as STAN (with standalone NATS)
Zero W will work as a secondary NATS cluster member,
and also as a non-bootstrap node of STAN cluster.
I wanted to configure it up like 3B+ as one STAN instance,
but I couldn’t make it run properly due to this issue.
So I had to run NATS and STAN servers respectively.
Configuration files for NATS and STAN are:
With these config files, NATS will be run on port 60200 and 60201(for cluster),
and web interface will be run on port 60202.
They can be run with following commands:
3. Build a remote STAN cluster
3B is not in the same network, and not even exposed to the outer world,
but still can be a node of a STAN cluster.
A. 3B: will work as STAN node
Configuration file for STAN:
Now run it with:
then it will connect to the NATS server which is already configured on
myhostname.com, and start STAN.
Resulting Network Topology
You can make sure all servers are running well by looking into logs saved in
And also, you can connect to the web interfaces through
Run as services
Following files are systemd service files I made.
They can be enabled/started/stopped with commands like these:
1. STAN service file for 3B+
2. NATS and STAN service files for Zero W
STAN depends on NATS, so nats.service was added to After in
3. STAN service file for 3B
Test with a client
Create a sample client from this code:
and run it with:
Pings and pongs!
Now we have a tiny, but clustered message queue system on Raspberry Pis!
1. Bad certificates?
If you see errors about certificates, make sure there are all needed IP addresses and domain names in them.
You can see the contents of your certificates with:
2. Timeout Errors?
If you see any timeout error on server launches, increase the
timeout values in the config files and retry.
Some tasks may be too much for our little Raspberry Pis… :-(
NATS/STAN is a light-weight, but powerful message queue system that can be run even on Raspberry Pis.
Message queue system is often said to be the best infra structure for microservices,
so it would be a good start to play with our spare Raspberry Pis :-)