acha.ninja

Introducing hermes

This post is the first public announcement of my new package manager and deployment tool for linux - hermes.

Hermes provides features like:

  • Atomic deployments.
  • Atomic rollback.
  • Remote builds.
  • Sandboxed and reproducible builds.
  • Avoidance of version conflicts.
  • Avoidance of centralized infrastructure.
  • Build everything from source.
  • Shared caching to avoid excessive rebuilds.

Those familiar with Nix or Guix will feel right at home, or you could think of hermes a bit like docker, where instead of building images in layers, you are building software packages from source into directories that can reference each other.

Examples

The following are some simple and non comprehensive examples, designed to show what using hermes looks like…

Install a package directly from a git repository

$ git clone https://github.com/andrewchambers/hpkgs
$ hermes build ./hpkgs/community/python3.hpkg
$ ./result/bin/python3 

Install software directly from github

$ hermes build https://raw.githubusercontent.com/andrewchambers/hpkgs/f4393d/community/bash.hpkg
$ ./result/bin/bash

Remote builds

$ hermes build --build-host ssh://acha.ninja ...

Developer environments

$ hermes build ./dev-env.hpkg -o dev-env
$ ./dev-env/run make
$ ./dev-env/run bash

Remote atomic deployment

$ hermes build ./app.hpkg -o app
$ hermes cp ./app ssh://$SERVER/deployments/app

Uninstalling packages

$ hermes gc

Project Motivations

Hermes is an attempt at creating a simple but powerful package management tool where you maintain total control of your software dependencies.

You could also consider Hermes my attempt at simplifying some of the ideas and implementation behind Nix and Guix. These simplifications range from less code, fewer commands, no C++, no monads, no lazy functional programming, no glibc. Don’t worry if those don’t mean much to you, the point is you shouldn’t really need to know about them.

The following are some of my initial design goals:

Have a decentralized package ecosystem

Hermes is trying to keep things decentralized where it can.

It allows…

  • Installation of packages directly from https urls (including github git commits).
  • Forking package trees using version control like Git.
  • Install software on any linux distro.

Have a simplified package model

I’ve tried to simplify the model of packaging that Nixos and Guix have pioneered.

Hermes packages definitions are just functions, that when called, build software by running commands like ./configure and make. If the package is already installed, hermes doesn’t bother building it again.

The main difference from ‘traditional’ package managers, is each package has a unique install directory, so there doesn’t need to be any package conflict handling.

Be lean and small

Hermes itself is lean, it fits on a floppy disk when statically linked and compressed, and can be made even smaller when omitting certain features.

Hermes only has a few core commands, hermes build, hermes cp, and hermes gc, which so far are enough to build packages, do remote deployments and remove unwanted packages.

Being this lean opens some future possibilities for places other tools cannot reach.

Have no background server/daemon

I am not a fan of the docker daemon, or the nix and guix build daemons. Hermes does not use one, instead working via other mechanisms such as lock files and strategic setuid.

Writing packages

Packages are written in the Janet programming language with a small set of extra functions that make sense in the context of building software.

When you create a hermes package you write a small function for installing the package into the path pointed to by the dynamically scoped variable :pkg-out. All dependencies are automatically detected and built simply by referencing them.

Here is a package for the ‘ed’ text editor:

(use ../prelude)
(import ../core)

(defsrc ed-src
  :url
  "http://ftpmirror.gnu.org/ed/ed-1.16.tar.lz"
  :hash
  "sha256:cfc07a14ab048a758473ce222e784fbf031485bcd54a76f74acfee1f390d8b2c")

(defpkg ed
  :builder
  (fn []
    (core/link-/bin/sh)
    (os/setenv "PATH" (join-pkg-paths ":" "/bin" [core/coreutils core/sed core/grep
                                                  core/awk core/gcc core/make]))
    (os/setenv "CFLAGS" *default-cflags*)
    (os/setenv "LDFLAGS" *default-ldflags*)
    (unpack-src ed-src)
    (sh/$ ./configure --prefix= ^ (dyn :pkg-out))
    (sh/$ make -j (dyn :parallelism))
    (sh/$ make install)))

You should note that Janet itself is a small but powerful general purpose programming language, so the skills you learn using hermes are useful for writing all sorts of great software.

Want to learn more?

Head over to the project github hermes and check out our quickstart and man pages.

How can you help?

  • Give hermes and hpkgs a star on github.
  • If you are an experienced Nix or Guix user, feel free to give hermes a try, other users may wish to hold off until more ground work is in place.
  • Donate to the project to keep it sustainable and show interest.