The eggshell project is a TamaGo unikernel that implements the Linux ABI to run unmodified Linux executables: statically linked ones, such as C programs or Go programs (including the Go toolchain), and programs dynamically linked against the musl C library.
While TamaGo remains committed to promote pure Go unikernels, this project is an experiment to address uses cases where the need for a full operating environment is unavoidable, such as running the Go compiler.
Warning
This project is at its early stages and therefore experimental.
$ make qemu
eggshell microvm (2802 MHz) • tamago amd64 (go1.27.3) • 1264 MiB available
virtio-net 52:50:9a:89:c2:39 10.0.0.1/24 gw:10.0.0.2 gvisor
sshd: listening on port 22
___ ___ _ _ _
| __|__ _ __ _/ __| |_ ___| | |
| _|/ _` / _` \__ \ ' \/ -_) | |
|___\__, \__, |___/_||_\___|_|_|
|___/|___/
Linux ABI on bare-metal Go
root@yolk:~# uname -a
eggshell yolk tamago go1.27.3 x86_64 BusyBox/TamaGo
root@yolk:~# ps x
PID USER TIME COMMAND
1 root 0:00 /bin/bash --login
5 root 0:00 ps x
root@yolk:~# halt
init exited with status 138, powering off
Andrea Barisani
andrea@inversepath.com
The applications run unprivileged while the Go runtime, acting as operating system kernel, runs at the highest privilege level.
System calls trap into the Go runtime (in a manner similar to the GoTEE execution model) and are serviced following the Linux system call ABI.
Each user thread is a goroutine, blocking system calls map directly onto the Go scheduler.
┌────────────────────────────────────────────── User mode ─┐
│ bash redis-server busybox u-root go ... │ Linux ELF binaries
└──────────────┬──────────────────────▲────────────────────┘
│ │
syscall │ page fault, timer │ iretq
│ │
┌──────────────▼──────────────────────┴────── Kernel mode ─┐
│ monitor GoTEE-style exec/return switch │
│ │
│ kernel Linux ABI syscalls, processes, signals, VFS, │
│ TTY, pipes, epoll, futex, sockets │ TamaGo / Go runtime
│ │
│ board QEMU microvm │
│ │
│ network virtio-net (go-net) + gVisor │
└──────────────────────────────────────────────────────────┘
The TamaGo compiler is automatically
downloaded and compiled as a go tool by the Makefile.
Alternatively the TAMAGO environment variable can be overridden to use the
latest binary release:
wget https://github.com/usbarmory/tamago-go/archive/refs/tags/latest.zip
unzip latest.zip
cd tamago-go-latest/src && ./all.bash
cd ../bin && export TAMAGO=`pwd`/goThe example uses
nix-build for root
filesystem creation, and qemu for microvm execution.
go mod tidy
make rootfs
make kernel
make qemuAll TamaGo amd64 targets can be supported with minimal integration.
The kernel command line can be passed through the APPEND variable:
make qemu APPEND="ip=10.0.0.1/24 gw=10.0.0.2"
| option | description |
|---|---|
-- cmd args |
init process (default /sbin/init) |
init=/path |
init process without arguments |
strace |
trace system calls on the console |
quiet |
no kernel banner |
ip=10.0.0.1/24 |
IPv4 address of the virtio-net interface |
gw=10.0.0.2 |
default gateway |
hostname=name |
host name |
env=KEY=VALUE |
additional init environment variable |
ssh=22 |
SSH server port, 0 disables it |
The qemu target attaches the network device to the host tap0 interface if
available, otherwise user networking is used with a predefined list of
forwarded ports (see NETDEV_USER within the Makefile).
On Linux systems tap0 can be configured as follows:
ip tuntap add dev tap0 mode tap group <your user group>
ip addr add 10.0.0.2/24 dev tap0
ip link set tap0 upAny C program that builds with musl should run.
Dynamically linked executables work as well: the kernel maps the PT_INTERP
program interpreter, the rootfs ships musl's /lib/ld-musl-<arch>.so.1 (add
any other shared library under /lib or /usr/lib).
The userland is built using nix-build, see nix/README.md for instructions and options.
-
While TamaGo supports SMP operation, for now supervision of userspace code remains a single-core only affair.
-
Only single user support, no isolation among users and any identity operation is a no-op.
-
IPv4 only, no raw sockets, no
SCM_RIGHTS, noAF_UNIXdatagrams. -
EPOLLETis emulated as level triggered. -
Not implemented:
ptrace, SysV IPC,inotify,timerfd,signalfd, POSIX timers (timer_create), mounts, namespaces. -
The filesystem is in-memory and therefore all modifications are volatile across reboots.
eggshell | https://github.com/usbarmory/eggshell
Copyright (c) The eggshell Authors. All Rights Reserved.
These source files are distributed under the BSD-style license found in the LICENSE file.