Northstar is an open source technology for securely running self sufficient sandboxed containers in a ressource constraint environment. It offers a runtime that monitors isolated containers. In addition it provides tooling to create and manage those containers.
At its core, Northstar makes extensive use of sandboxing to isolate applications from the rest of the system while at the same time orchestrating efficient startup and secure update scenarios. Such applications run inside Northstar-containers and only rely on system services and ressource containers provided by the Northstar-platform. Similar sandboxing techniques were selected and used as are found in Docker and other containerization approaches to reach maximum isolation. To build the most efficient and robust solution, Northstar is completely developed in Rust, a language designed to afford the performance of C++ while at the same time guaranteeing memory safety.
Northstar is still under heavy development. While we already have implemented most of the basic building blocks, Northstar is not production ready.
So far we tested Northstar on
- aarch64-linux-android
- aarch64-unknown-linux-gnu
- x86_64-unknown-linux-gnu
- On-the-fly verification of container content
- Process supervision: memory control (using cgroups)
- Process supervision: cpu control (using cgroups)
- Limiting system calls (whitelist)
- Shared resource containers
- chroot environment - every process only sees it's own environment
- User-support of configuring and managing network-namespaces
- Dedicated UID for each container
- Management API of the runtime
- Signature Check of NPK #54
- PID Namespaces #51
- limited read/write access: a container can only access it's own data
- restrict memory usage of a container
- restrict CPU usage
- limitation of network communication
- containerized applications can only use whitelisted syscalls
- secure update of verified packages
- secure boot
- verification on each read access prevents manipulation
Similar as in the docker world, a Northstar image is the unit that gets deployed into a system. Once the runtime starts, all images in the repositiry will be loaded into containers. Containers are the entities that are managed by the Northstar runtime.
Images are packaged as Northstar Packages or NPKs. At it's outer layer, such an NPK is just a plain zip-archive. The content looks like this:
The manifest.yaml
contains essential information about the package like id and version.
This is what a typical manifest looks like (taken from the examples)
name: ferris_says_hello
version: 0.0.1
init: /bin/ferris
args:
- /message/hello
mounts:
/dev: full
/lib:
host: /lib
/lib64:
host: /lib64
/system:
host: /system
/bin:
resource: ferris:0.0.2/
/message:
resource: hello_message:0.1.2/
/data: persist
The signature.yaml
contains signatures that are used to verify the package and the included file system. It is automatically created by the tooling.
Now the actual content is the fs.img
file, which is a squashfs filesystem image that contains the actual content of what the user puts into a container.
The image is packed a an zip archive with zero compression. Compression takes place via the SquashFS
functionality. Not compression the outer package allows Northstar to access the content without
unpacking the image to disk.
A file system image of a Nortstar package is attached to a loopback device. The loopback device is used to setup a verity check block device with the dm-verity module. The verity hashes are appended to the file system image. The verity block device is finally mounted and used in operation.
In order to use an application in a northstar container, it needs to be packaged in a northstar package (NPK). The sextant
tool can be used to create and package npk files. Install sextant
with cargo install --path tools/sextant
.
Northstar CLI
USAGE:
sextant <SUBCOMMAND>
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
SUBCOMMANDS:
gen-key
help Prints this message or the help of the given subcommand(s)
inspect Print information about a Northstar container
pack Pack Northstar containers
unpack Unpack Northstar containers
In order to create your own northstar packages, you will also need to generate a keypair that subsequently will be used to generate and verify the signatures of your images.
Once the packages are created, they are stored in a repository directory. This repository needs to be configured later when starting the northstar runtime.
Northstar is designed to be running a modern linux environment. When the kernel has the required features, it is basically possible to use northstar. Required Kernel features are:
- device-mapper with dm-verity
- SquashFS
- loopback-blockdevice-support
- PID namespaces
- mount namespaces
The script in tools/check_conf.sh
can be used to check your running kernel for the correct configuration. The version provided is for Android, but can be adapted to any platform providing the shell on the platform supports arrays.
Open a terminal, clone the repository and build the solution and start the runtime:
$ git clone https://github.com/esrlabs/northstar.git
$ cargo build --release --bin northstar
$ cargo build --release --bin nstar
$ sudo ./target/release/northstar
The examples/build_examples.sh
script can be used got build all the example
containers inside the example
folder.
The containers are built for the host platform by default. The flag -t,--target
can be used to build the containers for a different platform.
$ ./examples/build_examples.sh --help
USAGE:
build_examples.sh [OPTIONS]
OPTIONS:
-t, --target <platform> Target platform
-c, --comp <algorithm> Compression algorithm used by squashfs
(gzip, lzma, lzo, xz, zstd)
-h, --help Prints help information
Open a second terminal navigate to the directory where the northstar source is located. Start nstar
to interact with the runtime.
Execute the following commands:
containers
to list all registered containersstart crashing
to start an example container which will crash within the next 10 seconds
$ ./target/release/nstar
$ >> containers
Name | Version | Type | PID | Uptime
-------------------+---------+----------+-----+--------
cpueater | 0.0.1 | App | |
crashing | 0.0.1 | App | |
datarw | 0.0.1 | App | |
ferris_says_hello | 0.0.3 | App | |
hello | 0.0.2 | App | |
memeater | 0.0.1 | App | |
ferris | 0.0.2 | Resource | |
hello_message | 0.1.2 | Resource | |
>> start crashing
crashing-0.0.1 was started
start succeeded
>> crashing-0.0.1 exited (Exited with code 101)
The Northstar runtime is an executable and usually run as a daemon started by your system manager of choice. It can be started with a config file.
Northstar
USAGE:
northstar [FLAGS] [OPTIONS]
FLAGS:
-h, --help Prints help information
-V, --version Prints version information
OPTIONS:
-c, --config <config> File that contains the northstar configuration [default: northstar.toml]
The configuration of the runtime is done with a *.toml
configuration file.
Here is an example:
log_level = "DEBUG"
console = "tcp:https://localhost:4200"
run_dir = "target/northstar/run"
data_dir = "target/northstar/data"
[repositories.default]
dir = "target/northstar/repository"
writable = true
key = "examples/keys/northstar.pub"
[cgroups]
memory = "northstar"
cpu = "northstar"
[devices]
loop_control = "/dev/loop-control"
loop_dev = "/dev/loop"
device_mapper = "/dev/mapper/control"
device_mapper_dev = "/dev/dm-"
The [repositories.default]
sections describes a container repository named default
.
Within it, the following options can be specified:
dir
-- The directory where to find*.npk
packages for the correct architecture.key
-- The path to the public signing key used to sign the containers.
Multiple [repositories.<name>]
sections can be specified for separate
repositories, where <name>
is the repository identifier.
The [cgroups
] optionally configures northstar applications CGroups settings.
Both memory
and cpu
will tell northstar where to mount the cgroup hierarchies.
[devices]
-section:
loop_control
-- Location of the loopback block device control fileloop_dev
-- Prefix of preconfigured loopback devices. Usually loopback devices are e.g /dev/block0device_mapper
-- Device mapper control file.device_mapper_dev
-- Prefix of device mapper mappings.run_dir
-- where the container content will be mounteddata_dir
-- In data_dir a directory for each container is created if a mount of type data is used in the manifest
The northstar runtime can be controlled our nstar
application or from a custom application. You can
- start and stop containers
- uninstall or upgrade containers
- query information about running processes and setttings
- ...
With
nstar
we include a commandline interface that can be used to issue commands to the runtime. Underneth all communication happends via protocol-buffer objects over sockets (see the runtime API README)
If you want to see how containers can look like, take a look at the examples in the examples directory. See our examples README
See HACKING for more on what you might need.