website/content/baguette/technical-choices/index.md

10 KiB

+++ title = "BaguetteOS: technical choices"

paginate_by = 5 +++

Base system

Linux kernel, but we are lurking on the OpenBSD one.
Linux is compatible with most hardware and software, it is fast and we can easily compile a custom version to remove most of the bloat for server usage. Still, we don't want to rely on Linux-specific components. At some point, our system will be kernel-agnostic and will be able to run on any BSD as well. OpenBSD has pledge and unveil syscalls, which is an elegant way to provide a guarantee on the software behavior.

Musl. reasonable libc for Linux
It has a reasonable amount of features, it is efficient, provides reasonable binary sizes and static compilation. Musl is simple, reliable and remove all glibc-specific functions. Others can be added easily, which is useful for compatibility and comparisons, through slotting.

Bootable system and rootfs available.
A bootable system to install in virtual machines or bare metal, a rootfs to use BaguetteOS from any other OS, including non-Linux ones.

SysV-style init + CRUX-like /etc/{rc,mdev.conf,...}. easy to read, easy to adapt
The init could come from toybox or another minimalist project. The rc script from CRUX is simple to understand and to adapt to any requirements, so we use it. We also provide some other scripts, like for profile so we can easily manage slotting. No systemd BS.

Toybox. the megabyte coreutils
Toybox combines common unix command line utilities together into a single BSD-licensed executable. It is designed to be simple even to read, and is standards-compliant. For the base system, that's all we need.

ksh and zsh. the first for scripts and root, the other for users
Ksh is a very stable and reliable shell from AT&T, trusted by the paranoid people of OpenBSD. That's a safe choice for a base system and the root account. On the other hand, we do use zsh daily, as for many users, so we may use it for development or build scripts but not in the base system.

Service for service management tokenized service description, templating and dumb cli tools for the win
See custom tools.

Package for package management simple-to-use, efficient, dead simple code
See custom tools.

OpenSSH. as we all know and love
This is required for almost all usages, and for debug. Let's try not to shoot ourselves in the foot.

That's all you need for starters. Web administrative interface will be added to the base when ready.

Development, build tools

Default building tools every tool needed to bootstrap
Clang (+ LLVM) is the default C (and C++) compiler. Libarchive is required for tarballs, packages, webhooks from packaging, and both bsdcpio and bsdtar (sane implementations of cpio and tar). Auto-tools are also required (for SysV init and libarchive). m4 and gnu-make are required for compatibility reasons.

Documentation.
A full hand-book like the OpenBSD FAQ. Our software man-pages are written with scdoc so anyone can contribute.

Packaging for packaging software and libraries. dead simple, intuitive
See custom tools.

Slotting. custom file system hierarchy
Our FS is not FHS-compliant, partially because of the origin-based slotting. There is a strict separation between core system and third party software.
See slotting.

  • /usr/baguette for core system programs
  • /usr/bad for non slot-able software
  • /usr/<third-party> for other software

Languages

We are reluctant to add new languages to the base system. We will limit the number of languages required for a system bootstrap. For now, bootstrapping requires: C, perl, m4, python (for stupid reasons) and crystal (used for our software).

However, we think that we can overcome C limitations, explore new possibilities. Now, more than ever, we have better alternatives for all non kernel-related tooling. That being said: we do not want dynamic languages. We need:

  • simple, small and efficient binaries
  • the fewest dependencies possible (not to download half cpan or pypi for any freaking software)

Crystal language for system tools. syntax and productivity of Ruby, the speed of C
It is as simple to learn as a dynamic (oriented object) language, while at the same time being almost as fast as C. Technically, Crystal is strongly typed so it catches errors at compilation-time, but with type inference so it is not cumbersome to use. Applications are compiled in a simple binary, easy to deploy. There is a good documentation, we have used it for long enough to tell. Technical choices are reasonable and documented. Finally, Crystal has a large library with all we need for our system components.

There is not much of a drawback here. Yes, this is a language you have to learn to work with us on a couple of projects, but you can learn it in about a few days to a week and it increases our productivity like crazy. We heard about nim and a ton of other languages, lots of them are great candidates, but choices needed to be made. This is the one reaching the sweet spot between these parameters:

  • productivity (the package manager was mostly done in a few days, and is just a few hundred lines long)
  • easy learning (a developer with basic notions of oriented-object can read our code, no black magic here)
  • good documentation
  • reasonably deployable (no host dependencies)
  • execution speed

We are also looking at Zig for low-level stuff. Wait & see.

BaguetteOS conventions

Documentation

Manual pages have to be provided for each software.

BaguetteOS tools have man-pages generated with scdoc, letting developers use the markdown format to create man-pages. Scdoc isn't perfect, it ignores meta-data of man-pages (dates, authors name, etc.) and only provides a way to create man-pages with titles and style. Scdoc should be seen as a way to encourage developers writing documentation, without the complexity of the roff format. Meta-data are ignored in most usage anyway, we should not let them be an obstacle to documentation.

Additional documentation will be provided on this website, for a more educational approach and informal details.

Service name, user and group names

Default name for a service instance is the name of the project: nginx, wordpress, etc. Arbitrary names may be given to service instances. Example:

# service add blog.example.com type=wordpress domain=blog.example.com

Default environment is root.

When a service is configured, we create a user (and a group) under which the service will run, providing a clean separation between all running services. User and group names for these services are:

user  = $environment.$service
group = $environment.$service

Example:

service = nginx
environment = root (the default environment)
user  = root.nginx
group = root.nginx

Package names

name = application name
version = application version
release = recipe version
$name-$version-r$release.pkg

Example:

firefox-79.0-r8.pkg

Next

See our tooling