atuin server on a Raspberry PI - Cross compiling Rust
atuin server on a Raspberry PI - Cross compiling Rust
I’m a big fan of atuin, a shell history manager, which replaces the flat command history file with a local database, fully searcheable and with builtin synchronization support.
My setup of atuin, installation and configuration, can be seen in my dotfiles. But the documentation is excellent.
In case you are wondering why the sync configuration is not in my config: I try
to keep all specific configuration of stuff that is not publicly available and
might not be needed in all my environments outside of the dotfiles. I set
$ATUIN_SYNC_ADDRESS in my ~/.profile.local.
export ATUIN_SYNC_ADDRESS=http://raspberrypi.local:8888
Atuin offers a free synchronization server at https://api.atuin.sh. Yes, it’s not a good idea to show and open up your command history to everybody. Which is why the synchronization is completely end-to-end encrypted by atuin. The synchronization server only sees gibberish, and all your clients have to be set up with a passkey to enable sync.
If you, like me, still don’t want to trust that data to a sync service, you can also run your own synchronization server, which is pretty straightforward, assuming you know a bit about services and postgresql.
Of course that means that you have to run a server somewhere…
I happen to have a rasperry pi 3 in my home network, which mainly acts as an
always-on member of syncthing-synchronized
directories, and as a git repository server for private repositories with
gitolite. I don’t expose the Pi at
all to the public internet, it is only available internally, resolveable
through mDNS. I wanted to set it up as atuin synchronization server. It’s
already there, it is available for all devices in my local home network. This,
of course, means that I can only synchronize shell history with my machines at
home. But I don’t have a problem with this limitation at all.
The problem
Atuin is not installable through the raspbian package sources. This is also
true for Debian at the time of writing. On my machine, I install it with cargo,
orchestrated with tuning.
So, how do you install atuin on my raspberry pi, which uses an ARM CPU? Especially if you don’t want to compile it on the pi itself, wait for ages and fill your pi with stuff you don’t really need?
The solution
Atuin is a program written in Rust. This means that
- Programs are compiled to architecture specific binaries
- Programs can be built pretty easily with Rust’s awesome package manager
cargo - Cross compilation is pretty straightforward, thanks to Rust.
As usual, the devil is in the details, however.
The details
Setting up Rust for cross-compilation
With rustup as rust toolchain manager, it’s easy to install the rust specific
target and toolchain for the raspberry pi.
$ rustup target add armv7-unknown-linux-gnueabihf
This is not enough, however. For successful cross compilation, rust also needs the target specific gcc toolchain to link against C libraries and sysroot.
Setting up the system
You need gcc for cross-compilation with the armhf target, as well as the
armhf specific libraries for dynamic linking.
On a Debian system, this can be installed like so.
$ sudo apt-get install gcc-arm-linux-gnueabihf libgcc-13-dev-armhf-cross
The installation of gcc and the sysroot is on a system level, independent from the local rust setup. This means that cargo has to be set up correctly so that it uses the correct linker.
Configuring cargo
Target specific attributes can be configured in ~/.cargo/config.toml
[target.armv7-unknown-linux-gnueabihf]
linker = "arm-linux-gnueabihf-gcc"
Compilation
After everything has been set up, cargo can be built in the local directory with this command:
$ cargo install --target=armv7-unknown-linux-gnueabihf --target-dir=$(pwd) --root=$(pwd) atuin
This will download the sources of atuin and all dependencies, cross-compile
it and copy it to a bin subdirectory.
$ readelf -h bin/atuin
ELF Header:
Magic: 7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00
Class: ELF32
Data: 2's complement, little endian
Version: 1 (current)
OS/ABI: UNIX - System V
ABI Version: 0
Type: DYN (Position-Independent Executable file)
Machine: ARM
Version: 0x1
Entry point address: 0xd363d
Start of program headers: 52 (bytes into file)
Start of section headers: 32358908 (bytes into file)
Flags: 0x5000400, Version5 EABI, hard-float ABI
Size of this header: 52 (bytes)
Size of program headers: 32 (bytes)
Number of program headers: 10
Size of section headers: 40 (bytes)
Number of section headers: 44
Section header string table index: 43
Installation
Copy the binary onto your raspberry pi, e.g. to /usr/local/bin/atuin, and
you’re good to go!
tl;dr
- atuin is great to manage shell history
- atuin sync is great and pretty safe
- atuin sync on a raspberry pi under your control is even safer
- cross-compilation with Rust is relatively easy
- the devil is in the details
Leave a comment