-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
1 changed file
with
154 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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 |