propeller logo

Developer's Guide

Guide for building and contributing to Propeller

Getting Propeller

Propeller source can be found in the official Propeller GitHub repository. You should fork this repository in order to make changes to the project. The forked version of the repository should be cloned using the following:

git clone https://github.com/your-github-username/propeller.git $SOMEPATH/propeller
cd $SOMEPATH/propeller
git remote add upstream https://github.com/absmach/propeller.git

Building Propeller

Prerequisites

To build Propeller, you will need the following:

Building

Use the GNU Make tool to build all Propeller services:

make all

This will build Propeller for your platforms.

To build Propeller for other platforms, use the following:

OSArchitectureCommand
Linuxamd64GOOS=linux GOARCH=amd64 make all
Linuxarm64GOOS=linux GOARCH=arm64 make all
Windowsamd64GOOS=windows GOARCH=amd64 make all
Darwinamd64GOOS=darwin GOARCH=amd64 make all

Building an individual service

You can build individual services using the following:

make <service>

For example, to build the manager service, use the following:

make manager

The built binaries will be located in the build directory.

Building examples

You can build examples using the following:

make <example>

For example, to build the addition example, use the following:

make addition

This compiles the addition example to wasm and can be located in the build directory.

To test the addition example, use the following:

wasmtime --invoke add ./build/addition.wasm 1 2

This will output something like:

warning: using `--invoke` with a function that takes arguments is experimental and may break in the future
warning: using `--invoke` with a function that returns values is experimental and may break in the future
3

Installing

Once you have built Propeller, you can install it using the following:

make install

This will install Propeller to the GOBIN directory.

export GOBIN=~/go/bin
export PATH=$GOBIN:$PATH
make install

Linter

Propeller uses golangci-lint to lint the code. You can run the linter using the following:

make lint

SuperMQ

Starting SuperMQ

To start SuperMQ, use the following:

make start-supermq

This will in the background run docker compose -f docker/compose.yaml up -d which will start the SuperMQ services.

You can override the configuration or add some extra parameters to the docker compose configuration.

After this is done, you will need to provision propeller using the following command

propeller-cli provision

asciicast

After this is done, config.toml file will be created for easier setup, we can copy it to the docker folder and uncomment config.toml configuration for manager, proplet and proxy.

cp config.toml docker

The changes on the docker compose file looks like this

diff --git a/docker/compose.yaml b/docker/compose.yaml
index 46302ea..e872f29 100644
--- a/docker/compose.yaml
+++ b/docker/compose.yaml
@@ -1607,8 +1607,8 @@ services:
       - supermq-base-net
     # To use a custom config.toml, uncomment the following line and ensure ./config.toml exists.
     # If you are using environment variables for configuration, leave this commented out.
-    # volumes:
-    #   - ./config.toml:/config.toml
+    volumes:
+      - ./config.toml:/config.toml

   proplet:
     image: ghcr.io/absmach/propeller/proplet:${PROP_RELEASE_TAG}
@@ -1642,8 +1642,8 @@ services:
       - supermq-base-net
     # To use a custom config.toml, uncomment the following line and ensure ./config.toml exists.
     # If you are using environment variables for configuration, leave this commented out.
-    # volumes:
-    #   - ./config.toml:/home/proplet/config.toml
+    volumes:
+      - ./config.toml:/home/proplet/config.toml

   proxy:
     image: ghcr.io/absmach/propeller/proxy:${PROP_RELEASE_TAG}
@@ -1671,5 +1671,5 @@ services:
       - supermq-base-net
     # To use a custom config.toml, uncomment the following line and ensure ./config.toml exists.
     # If you are using environment variables for configuration, leave this commented out.
-    # volumes:
-    #   - ./config.toml:/config.toml
+    volumes:
+      - ./config.toml:/config.toml

Then run make start-supermq again to start SuperMQ.

The logs from then manager should look like this:

{"time":"2026-02-11T16:57:43.822945669Z","level":"INFO","msg":"MQTT connection lost"}
{"time":"2026-02-11T16:57:43.883167345Z","level":"INFO","msg":"Subscribe to MQTT topic completed successfully","duration":"60.157736ms"}
{"time":"2026-02-11T16:57:43.883519119Z","level":"INFO","msg":"manager service http server listening at manager:7070 without TLS"}

The logs from the proplet should look like this:

2026-02-11T17:34:32.841840Z  INFO Starting Proplet (Rust) - Instance ID: f34cddff-2855-4e3f-9b55-9d83b982b315
2026-02-11T17:34:32.841888Z  INFO MQTT client created (TLS: false)
2026-02-11T17:34:32.841931Z  INFO Using external Wasm runtime: wasmtime
2026-02-11T17:34:32.842001Z  INFO Starting MQTT event loop
2026-02-11T17:34:32.846168Z DEBUG Received MQTT packet: ConnAck(ConnAck { session_present: false, code: Success })
2026-02-11T17:34:32.877390Z  INFO Starting PropletService
2026-02-11T17:34:32.877439Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/create
2026-02-11T17:34:32.877443Z  INFO Published discovery message
2026-02-11T17:34:32.877463Z  INFO Subscribed to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/manager/start
2026-02-11T17:34:32.877467Z  INFO Subscribed to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/manager/stop
2026-02-11T17:34:32.877472Z  INFO Subscribed to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/registry/server
2026-02-11T17:34:32.878594Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/alive
2026-02-11T17:34:32.878615Z DEBUG Published liveliness update
2026-02-11T17:34:32.879956Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/metrics
2026-02-11T17:34:32.880019Z DEBUG Published proplet metrics
2026-02-11T17:34:32.882250Z DEBUG Received MQTT packet: PubAck(PubAck { pkid: 1 })
2026-02-11T17:34:32.897028Z DEBUG Received MQTT packet: SubAck(SubAck { pkid: 2, return_codes: [Success(AtLeastOnce)] })
2026-02-11T17:34:32.902466Z DEBUG Received MQTT packet: SubAck(SubAck { pkid: 3, return_codes: [Success(AtLeastOnce)] })
2026-02-11T17:34:32.908233Z DEBUG Received MQTT packet: SubAck(SubAck { pkid: 4, return_codes: [Success(AtLeastOnce)] })
2026-02-11T17:34:32.909485Z DEBUG Received MQTT packet: PubAck(PubAck { pkid: 5 })
2026-02-11T17:34:32.909510Z DEBUG Received MQTT packet: PubAck(PubAck { pkid: 6 })
2026-02-11T17:34:42.878374Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/alive
2026-02-11T17:34:42.878387Z DEBUG Published liveliness update
2026-02-11T17:34:42.879526Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/metrics
2026-02-11T17:34:42.879540Z DEBUG Published proplet metrics
2026-02-11T17:34:42.881430Z DEBUG Received MQTT packet: PubAck(PubAck { pkid: 7 })
2026-02-11T17:34:42.883416Z DEBUG Received MQTT packet: PubAck(PubAck { pkid: 8 })
2026-02-11T17:34:52.878418Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/alive
2026-02-11T17:34:52.878441Z DEBUG Published liveliness update
2026-02-11T17:34:52.880337Z DEBUG Published to topic: m/fcf50e58-a080-4179-a260-e91cdf8fc1c2/c/8259a673-ab09-4b97-8c09-e1f9e60c7c2c/control/proplet/metrics
2026-02-11T17:34:52.880366Z DEBUG Published proplet metrics

Stopping SuperMQ

SuperMQ can be stopped using the following:

make stop-supermq

On this page