Building Erlang + ZX on Devuan Excalibur

With Ubuntu/Kubuntu out of the running for “works and is mostly sane”, we are having to shift once again over to Devuan, which we have been using for servers for several years now at Tsuriai and QPQ, but not as often on desktops (because Kubuntu was just so convenient and changing habits is annoying).

This post will cover Erlang and ZX, specifically, and I’ll do another one about how the app-level transition feels moving from Kubuntu for desktop to Devuan. (Migrating servers from Ubuntu to Devuan is really easy and a major relief: everything is just simpler, flatter, more boring, and works as any SysV init system should.)

TL;DR

As a pseudo script:

# To run the next stuff as root we 'su -'
su -
apt update
apt upgrade
# If installing on a non-graphical system, omit the libwxgtk dep
apt install \
    gcc curl g++ dpkg-dev build-essential automake autoconf \
    libncurses-dev libssl-dev flex xsltproc libwxgtk3.2-dev \
    wget vim git
# Get out of root now and run everything else as a normal user
exit

# Create directories we'll need
mkdir -p ~/vcs ~/bin
# Open a new terminal session for ~/bin to get into $PATH

cd ~/vcs
git clone https://github.com/kerl/kerl.git
cd ~
ln -s ~/vcs/kerl/kerl ~/bin/kerl
kerl update releases
# Pick any version in the list -- I'm working on R27 right now
ERL_VER=27.3.4.12
kerl build $ERL_VER $ERL_VER
kerl install $ERL_VER ~/.erts/$ERL_VER
echo ". \"\$HOME\"/.erts/$ERL_VER/activate" >> .bashrc
echo ". \"\$HOME\"/.erts/$ERL_VER/activate" >> .bash_profile
. ~/.erts/$ERL_VER/activate

# You already have Erlang, this will get you ZX
wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx

Discussion

The above scriptish version is the cut sheet for me to use later. I haven’t done a discussion explaining what is going on above in a while, and humans stopped reading (and writing) but AI sucks, so here we go, old school HOWTO blog style…

GUI vs TUI

The difference between the non-graphical and graphical build of Erlang in this context is simple:

  • For GUIs, include the libwxgtk3.2-dev dependency.
  • For TUIs, omit the libwxgtk3.2-dev dependency.

I’ll include it below for completeness, but that’s the only difference.

root vs sudo

On Devuan the default is to use a root account rather than sudo. I tend to log in as root using su - instead of actually logging in as root, but that’s mostly because I do this mostly over SSH, and login as root should always be disabled in the SSH config. If you add yourself to the sudoers file, though, you can do it the sudo way you may be familiar with from Ubuntu.

Installing the deps

Everything in this section will either have to be run as root or with sudo.

apt update
apt upgrade
apt install \
    gcc curl g++ dpkg-dev build-essential automake autoconf \
    libncurses-dev libssl-dev flex xsltproc libwxgtk3.2-dev \
    wget vim git

Setting up for, Building and Installing Erlang

First, we are going to be depending on the ~/bin directory being in our path for a bit of this, so create it if it doesn’t already exist. We’ll also use a directory ~/vcs to keep version controlled stuff in one place (so if you have sync scripts for your $HOME, omit both of those from it):

mkdir -p ~/vcs ~/bin

If ~/bin didn’t exist previously, close your terminal and open a new one — this should show up in your default $PATH now. If it doesn’t take because you have chosen a funky window manager, just log out and log back in to force it to take effect.

Once ~bin exists and is in our $PATH we’re going to jump through the following steps:

cd ~/vcs
git clone https://github.com/kerl/kerl.git
ln -s ~/vcs/kerl/kerl ~/bin/kerl
cd ~
kerl update releases
ERL_VER=27.3.4.12
kerl build $ERL_VER $ERL_VER
kerl install $ERL_VER ~/.erts/$ERL_VER
echo ". \"\$HOME\"/.erts/$ERL_VER/activate" >> .bashrc
echo ". \"\$HOME\"/.erts/$ERL_VER/activate" >> .bash_profile
. ~/.erts/$ERL_VER/activate

I installed 27.3.4.12 in the example above because I’m working on something that still uses it, but you can substitute any current version and it should just work. The current latest stable is 28.5.

At this point you have Erlang. Try running erl at your terminal and it should pop up:

ceverett@soba:~$ erl
Erlang/OTP 27 [erts-15.2.7.8] [source] [64-bit] [smp:16:16] [ds:16:16:10] [async-threads:1] [jit:ns]

Eshell V15.2.7.8 (press Ctrl+G to abort, type help(). for help)
1>

Installing ZX

This is the easiest part:

wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx

You should see roughly this output:

ceverett@soba:~$ wget -q https://zxq9.com/projects/zomp/get_zx && bash get_zx
2026-06-08 17:37:47 URL:https://zxq9.com/projects/zomp/zx-0.14.0.tar.gz [151486/151486] -> "zx-0.14.0.tar.gz" [1]
Erlang found at /home/ceverett/.erts/27.3.4.12/bin/erl
/home/ceverett/bin was found in $PATH. Good to go.
zx found at /home/ceverett/bin/zx. Checking for upgrade.
Running `zx upgrade`...
Recompile: src/zx_zsp
Recompile: src/zx_userconf
Recompile: src/zx_tty
Recompile: src/zx_sup
Recompile: src/zx_proxy
Recompile: src/zx_peers
Recompile: src/zx_peer_sup
Recompile: src/zx_peer_man
Recompile: src/zx_peer
Recompile: src/zx_net
Recompile: src/zx_local
Recompile: src/zx_lib
Recompile: src/zx_key
Recompile: src/zx_daemon
Recompile: src/zx_conn_sup
Recompile: src/zx_conn
Recompile: src/zx_auth
Recompile: src/zx
Current version: otpr-zx-0.14.0
Running latest version.

Now try a zx command, like zx describe gajudesk:

ceverett@soba:~$ zx describe gajudesk
Package : otpr-gajudesk-0.9.0
Name    : GajuDesk
Type    : gui
Desc    : A desktop client for the Gajumaru network of blockchain networks
Author  : Craig Everett <craigeverett@qpq.swiss>
Web     : https://gajumaru.io
Repo    : https://git.qpq.swiss/QPQ-AG/GajuDesk
Tags    : ["gaju","gm","gajumaru","wallet","blockchain","cryptocurrency",
           "crypto","puck"]

Yay! And now you’re all set.

A note on other systems (MacOS and Windows)…

There are signed one-shot installers for Windows and MacOS that will bring in Erlang R27 and ZX with integrated shortcuts available at the ZX/Zomp downloads page.

If you came here to get GajuDesk, there are installers for GajuDesk and GajuDesk + GajuMine that integrate those apps with the desktop for Windows and MacOS (clicky icons and launchers and so on) available here: GajuMining Downloads

A note on GajuMining…

If you came here to run GajuMining on Linux, the above steps all still apply, but there are a handful of additional steps needed, such as adding the qpq and uwiger code realms. The community setup scripts are maintained at Shane Preater’s repo here: https://github.com/shanepreater/gajumaru

But if you already have zx installed by following the steps above, you can shortcut this with:

wget -q https://github.com/shanepreater/gajumaru/raw/refs/heads/main/qpq.zrf
wget -q https://github.com/shanepreater/gajumaru/raw/refs/heads/main/uwiger.zrf
zx import realm qpq.zrf
zx import realm uwiger.zrf
rm uwiger.zrf qpq.zrf

This is how things should go:

ceverett@soba:~$ wget -q https://github.com/shanepreater/gajumaru/raw/refs/heads/main/qpq.zrf
ceverett@soba:~$ wget -q https://github.com/shanepreater/gajumaru/raw/refs/heads/main/uwiger.zrf
ceverett@soba:~$ zx import realm qpq.zrf 
SHA-512 of qpq.zrf: 59082251ED81C63DFC6C3678926DF503CB42118291B3271D3612BD1E7F63AEBDEB296D81AF7446451555B7085E726B6B9C1EC8DBBF3C4C6EDB296B9C257E3AD4
Imported record locally, including a public key.
Added realm qpq.
ceverett@soba:~$ zx import realm uwiger.zrf 
SHA-512 of uwiger.zrf: 704530801DF3E54D069FACD93F772FCAC8A6E776389CDE8F4F034DE1A0A516B0D44FFB3DDD88C2A82C015CB14218C17172099E477E28B3A5E293D2CC08F20000
Imported record locally, including a public key.
Added realm uwiger.
ceverett@soba:~$ zx list realms
otpr
qpq
uwiger
ceverett@soba:~$ zx describe qpq-gajumine
Package : qpq-gajumine-0.4.2
Name    : GajuMine
Type    : gui
Desc    : Mining client for the Gajumaru Root
Author  : Craig Everett <craigeverett@qpq.swiss>
Web     : https://gajumining.com
Repo    : https://git.qpq.swiss/zxq9/GajuMine
Tags    : ["qpq","gaju","gajumaru","hive","mining","crypto"]

And that’s it. You can do CPU mining with the GUI client by running zx run qpq-gajumine or headless with a GPU setup by following the advice on Shane’s repo.

Permalink

Erlang/OTP 29.0

OTP 29.0

Erlang/OTP 29 is a new major release with new features, improvements as well as a few incompatibilities. Some of the new features are highlighted below.

Many thanks to all contributors!

Highlights

  • Added support for -unsafe attributes for marking functions as unsafe to use. The compiler will by default now generate warnings for calls to functions in Erlang/OTP known to be always unsafe. Furthermore, xref can now be used to find calls to unsafe functions and functions that lack documentation.

  • The SSH daemon now defaults to disabled for shell and exec services, implementing the “secure by default” principle. This prevents authenticated users from executing arbitrary Erlang code unless explicitly configured.

  • The SFTP subsystem is no longer enabled by default when starting an SSH daemon.

  • In SSL, the post quantum hybrid algorithm x25519mlkem768 is now the most preferred key exchange group in the default configuration.

  • The module io_ansi allows the user to emit Virtual Terminal Sequences (also known as ANSI sequences) to the terminal in order to add colors/styling to text or to create fully fledged terminal applications.

  • The new ct_doctest module allows the user to test documentation examples in Erlang module docs and documentation files.

  • The ignore_xref attribute has been handled as a post-analysis filter by build tools such as Rebar3. In this release, [xref] itself does the filtering, ensuring that all tooling that calls xref for any purpose can rely on these declarations to just work.

General

  • In the default code path for the Erlang system, the current working directory (.) is now in the last position instead of the first.

  • There is no longer a 32-bit Erlang/OTP build for Windows.

New language features

  • Native records as described in EEP-79 has been implemented. A native record is a data structure similar to the traditional tuple-based records, except that is a true data type. Native records are considered experimental in Erlang/OTP 29 and possibly also in Erlang/OTP 30.

  • The new is_integer/3 guard BIF makes it possible to easily verify that a value is both an integer and within a certain range. For example: is_integer(I, 0, 100)

  • Multi-valued comprehensions according to EEP 78 are now supported. For example, [-I, I || I <- [1, 2, 3]] will produce [-1,1,-2,2,-3,3].

  • By enabling the compr_assign feature, it is now possible to bind variables in a comprehensions. For example: [H || E <- List, H = erlang:phash2(E), H rem 10 =:= 0]

Compiler and JIT improvements

  • In the documentation for the [compile] module, there is now a section with recommendations for implementors of languages running on the BEAM.

  • The JIT now generates better code for matching or creating binaries with multiple little-endian segments.

  • The compiler will generate more efficient code for map comprehensions with constant values that don’t depend on the generator. Example: #{K => 42 || K <- List}

Compiler warnings

There are several new compiler warnings enabled by default. For each such warning, there is an option to disable it.

  • There will now be a warning when using the catch operator, which has been deprecated for a long time. It is recommended to instead use trycatch but is also possible to disable the warning by using the nowarn_deprecated_catch option.

  • There will now be a warning when exporting variables out of a subexpression. For example: file:open(File, AllOpts = [write, {encoding,utf8}]). This warning can be disabled using the nowarn_export_var_subexpr compiler option.

  • The compiler will now warn for uses of the and and or operators. This warning can be disabled using the nowarn_obsolete_bool_op compiler option.

  • The compiler will now warn for matches such as {a,B} = {X,Y}, which is better written as {a=X,B=Y}. This warning can be disabled using the nowarn_match_alias_pats option.

For a long time, there has been a warning for using the obsolete guard tests (such as list(L) instead of is_list(L). In Erlang/OTP 30, the old guards will be removed from the language.

STDLIB

  • There are new functions for randomly permutating a list: rand:shuffle/1 and rand:shuffle_s/2.

SSH

  • The default key exchange algorithm is now mlkem768x25519-sha256, a hybrid quantum-resistant algorithm combining ML-KEM-768 with X25519. This provides protection against both classical and quantum computer attacks while maintaining backward compatibility through automatic fallback to other algorithms when peers don’t support it.

For a full list and more details about new features and potential incompatibilities see the README.

Permalink

Copyright © 2016, Planet Erlang. No rights reserved.
Planet Erlang is maintained by Proctor.