signal-cli on Raspberry Pi

This post is intended to be used as a guide by anyone who wants to compile and run signal-cli [2] on a Raspberry Pi [3] with an arm7 (x86) processor. Signal is a messenger application developed by the Signal Foundation [4].

Quoting the project README.md, signal-cli:

is primarily intended to be used on servers to notify admins of important events

These events may include monitoring both for system health and security related events.

The post is devided in the following sections, which show the actions that should be taken to build all the required components of signal-cli on a Raspberry Pi with a 32bit arm processor:

The information already exists in signal-cli’s wiki page [8], however this post provides further details on some certain aspects of the process.

Java SE OpenJDK arm7

To run signal-cli Java is required. Adaptium offers Eclipse Temurin, an open source Java SE (Standard Edition) build based upon OpenJDK [5].

Download the JDK (Java Development Kit) package for the arm architecture. At the time of this post, signal-cli requires Java Runtime Environment (JRE) 17.

Copy the relevant JDK release in /opt/java and extract it using the following command:

tar xzvf .tar.gz

The contents of the release you downloaded exist within a path with format similar to /opt/java/jdk-17.0.8+10. You may want to have multiple Java JDK version in your environment, so it’s a good practise to have each version in a directory named of the actualy JDK version.

To use this release as the main one for your system, create a link file that points to the java binary that exists in the directory where you extracted Java:

ln -s /opt/java/jdk-17.0.8+10/bin/java /usr/bin/java

If /usr/bin is in your PATH (you can check what is actually in your path by: echo $PATH), then any time you run the command java, the linked java binary runs.

To confirm that the link you just created actually works, run the command java –version and confirm the output is relevant with the version you downloaded. The output should look like:

openjdk 17.0.8
OpenJDK Runtime Environment Temurin-17.0.8+10 (build 17.0.8+10)
OpenJDK Server VM Temurin-17.0.8+10 (build 17.0.8+10, mixed mode, sharing)

Compile signal-cli on arm7

Next step is to build signal-cli for the specific processor we are working on. That is arm7.

Although instructions are published on the signal-cli’s README.md, these are re-iterated here.

Clone the project:

git clone https://github.com/AsamK/signal-cli.git

Navigate into the project directory:

cd signal-cli

Run Gradle:

./gradlew build

Create shell wrapper in build/install/signal-cli/bin:

./gradlew installDist

An addtional step is required at this point if you have followed the steps detailed in the previous section and confgured your environment to use the JDK from Adoptium. More specifically, you need to replace the last line of the bash script located in build/install/signal-cli/bin/signal-cli to provide the path of the Java libraries that will be required during the compilation. The following lines need to replace the aforementioned line:

JAVA_LIBRARY_PATH="-Djava.library.path=/opt/java/jdk-17.0.8+10/lib/"
exec "$JAVACMD" "$JAVA_LIBRARY_PATH" "$@"

If you have extracted Java in a different path, adjust the java.library.path accordingly.

Create the tar file in build/distributions. The file will include the required files to run signal-cli:

./gradlew distTar

Create a fat tar file in build/libs/signal-cli-fat:

Compile and run signal-cli:

./gradlew run –args=”–help”

After confirming that signal-cli was compiled successully and ran, copy the create .tar file from build/distributions to the location you will be running it from. Likewise what we did with Java, we can put it in /opt/signal-cli

Compile libsignal on arm7

signal-cli depends on libsignal [7]. libsignal is a rust library that needs to be compiled specifically for the arm7 processor. The following steps show the steps required to build libsignal.

The packages supported by the official operating system mirrors may be old and cause issues while compiling. One alternative is to install the latest version of rust, located in [9]. At the time of this post, the command is:

curl –proto ‘=https’ –tlsv1.2 -sSf https://sh.rustup.rs sh

Next, identify which libsignal version is required by the specific signal-cli release you are planning to build, by reviewing the version number on the file *libsignal-client-.jar* located in the path *lib/* of the signal-cli project.

As soon as you acquire this information, you then need to download the relevant release of libsignal.

Navigate in the java directory with the command:

cd java

Avoid building the android library as it won’t be of any use:

sed -i “s/include ‘:android’//” settings.gradle

And finally, build the library:

./build_jni.sh desktop

The compilation is made with cargo and requires additional packages such as cmake and clang. The process may fail in different steps if certain packages are missing. If that happens, identify which package is missing and start the process from a clean state.

The library that is created is named libsignal_jni.so and located in the path target/release within the libsignal directory. For signal-cli to work, we’ll need to place this library in a specific location. Details of this process are provided in the next section.

Update project to use libsignal

One more step in the chain is to instruct signal-cli to use the compiled libsignal library instead.

To do this, first decouple libsignal_jni.so with the command:

zip -d signal-cli/lib/libsignal-client-*.jar libsignal_jni.so

If zip is not available, you can install it using the following command:

apt install zip

Then copy the libsignal libary file (libsignal_jni.so) that was compiled in the previous step, into that Java library path /opt/java/jdk-17.0.8+10/lib.

Associate PATH with signal-cli

Finally, create a link file that will point to signal-cli like the link file we created for Java earlier:

ln -s /opt/signal-cli-0.11.7/bin/signal-cli /usr/bin/signal-cli

Linking devices

After the above steps are complete, next action is to link the raspberry with the primary device. The author of signal-cli provides details in the wiki [10]. Long story short, generate a QR code on raspberry, display it on the screen and scan it with the Signal app. This applies if the primary device is android.

To generate and display the QR code, use the following command:

signal-cli link -n “optional device name” tee >(xargs -L 1 qrencode -t utf8)

References

[1] https://signal.org

[2] https://github.com/AsamK/signal-cli

[3] https://www.raspberrypi.org

[4] https://signalfoundation.org

[5] https://adoptium.net/

[6] https://adoptium.net/temurin/releases/

[7] https://github.com/signalapp/libsignal

[8] https://github.com/AsamK/signal-cli/wiki

[9] https://rustup.rs

[10] https://github.com/AsamK/signal-cli/wiki/Linking-other-devices-(Provisioning)

tags: #random