Skip to content

Commit

Permalink
atuin cross-compilation
Browse files Browse the repository at this point in the history
  • Loading branch information
gierdo committed Jul 7, 2024
1 parent 27b527c commit f289091
Showing 1 changed file with 154 additions and 0 deletions.
154 changes: 154 additions & 0 deletions _posts/2024-07-07-atuin-pi.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@
---
title: atuin server on a Raspberry PI - Cross compiling Rust
categories:
- programming
- linux
tags:
- rust
- build
- atuin
---

# atuin server on a Raspberry PI - Cross compiling Rust

I'm a big fan of [atuin](https://docs.atuin.sh/), 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](https://github.com/gierdo/dotfiles/blob/master/tuning/programs.toml#L162)
and
[configuration](https://github.com/gierdo/dotfiles/blob/master/.config/atuin/config.toml),
can be seen in my [dotfiles](https://github.com/gierdo/dotfiles). But the
[documentation](https://docs.atuin.sh/guide/installation/) is excellent.

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](https://docs.atuin.sh/self-hosting/server-setup/), 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](https://syncthing.net/)-synchronized
directories, and as a git repository server for private repositories with
[gitolite](https://gitolite.com/gitolite/index.html). 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?

## The solution

[Atuin](https://github.com/atuinsh/atuin) is a program written in Rust. This
means that

1. Programs are compiled to architecture specific binaries
2. Programs can be built pretty easily with Rust's awesome package manager
[`cargo`](https://doc.rust-lang.org/cargo/)
3. [Cross
compilation](https://rust-lang.github.io/rustup/cross-compilation.html) 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.

```text
$ 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.

```text
$ 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`

```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:

```text
$ cargo install --force --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.

```text
$ 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

0 comments on commit f289091

Please sign in to comment.