Declarative microservice-based linux distribution based on suckless principles for desktop and embedded systems. In short, lunix
- uses the nix package manager,
- tries it's very hardest to push all user-space information through a pubsub (NATS) (sort of like ROS),
- is minimalistic and opinionated
What can you achieve with lunix?
- Like nixos, it's got "fearless upgrades" with rollbacks and all that jazzy package management magic
- Like ROS, it's got amazing extendability, but due to the protocol choice, is easier to use than the XMLRPC that ROS uses
- It's opinionated, but opinionated in a way that favors choice - most parts of lunix can be switched out
- The NATS pubsub interface allows for some very neat stuff, for example:
Sending a notice to toast notification when a USB stick has been plugged in
nats.subscribe('hardware.usb.add', (msg) => {
nats.publish('toast.in', 'a USB stick was plugged in!');
});
Automounting said USB stick
nats.subscribe('hardware.usb.add', (msg) => {
mount(msg.something, '/myplace');
});
nats.subscribe('hardware.usb.remove', (msg) => {
umount('/myplace');
});
Creating a web page that displays your toasts over the interwebs:
nats.subscribe('toast.in', (msg) => {
websocket.send(msg);
});
When your phone is connected to your device over bluetooth, open a terminal on your desktop:
nats.subscribe('bluetooth.connected', (msg) => {
nats.publish('wm.something', 'xterm');
});
When your IoT temperature sensor reports a low temperature reading, and you're reading a book, spinlock to generate some heat
mqtt.subscribe('temperature0', (temp) => {
if (temp <= 18) {
nats.request('ps.calibre', (pid) => {
while (1) {
console.log('HEAT!');
}
}
}
});
- All of these could be written in any programming language you like; node, rust, c, python.
- You can use node-red to configure your computer!
Lunix consists of
- A bootloader (choose your own; syslinux, grub, uboot, systemd-boot, ...). Just get a linux kernel going.
- A linux kernel.
- An init. You can spin your own here; systemd, runit, s6, openrc, etc, but lunix has it's own init you can use which gives you some further NATS integrations you can use - e.g. notifications when a service has started up and resource usage queries.
- A NATS-compatible pubsub server. Many parts of lunix is bound to the procotol specification of NATS, so this part is hard to switch out, but there will be NATS-compatible servers that are better suited for embedded use then NATS itself.
- The nix package manager. This is no requirement; it's very possible to run lunix using the alpine package manager, or any other package manager, but nix is a very neat package manager.
- 'natsdev' - a new hotplug daemon, like udev/eudev/mdev/smdev/..., but it's connection to NATS
- A toast notification service
- A bluetooth notification service
- A network notification service,
- A NATS-connected PAM authentication module - sets readable and writeable topics for a user.
- An authentication service that
pam_nats
talks to - and other useful stuff.
We also have some neat stuff to extend your setup, such as
- An MQTT-NATS bridge,
- A websocket-nats bridge
- Design with embedded in mind. All parts of lunix are designed to allow to be run in a low-cpu, low-memory, low-diskspace environment. 64 MB of RAM and 8 MB NOR flash storage should be enough. Each package needs to be compatible with musl libc.
- No polling anywhere (in the base system), and no busy waiting/spinlocks. All lunix services are epoll based using proper linux fd-based primitives (sockets, timerfd, etc)
- Proper regular parsers everywhere - lots of extremely fast and secure ragel parsers.
- "Do one thing, and do it well"
- Polyglot environment - end-users can always integrate with lunix services using whatever language and tool he/she is comfortable using
- Automatic upgrades in the background and other "automatics" is just annoying. Be very transparent.
- Don't try to do everything over NATS. We still use regular old 'getty', 'login' and PAM. (Though we could provide a PAM module to give notifications that users have logged in). We still use X, optionally with a DM.
- Each part of lunix can be used on it's own, outside lunix.
- For really tight embedded environments, we're using buildroot instead of nix. We provide buildroot configuration for these packages.
- Be cloud-native. It should be easy to spin up lunix within a virtual machine, configure it to send syslogs somewhere useful, connect it to a larger NATS cluster, and push updates to it.
The init system borrows ideas from existing init systems; runit, s6, systemd, openrc and others. However, improves on them on some key points which merits the existance of a new init.
It's able to watch a directory for changes like runit and s6 and automatically starts/stops services that has been added/removed. This simplifies service management into a simple "create service in the correct place". No need for state resolving logic to figure out if a service needs to be restarted when updated. It also integrates extremely well with the nix package manager, because you can just create a new service directory, and every changed service will be automatically started/restarted/stopped.
Runit and s6 writes to the service directories which makes it hard to keep them in a read-only directory (like nix does). lunix-init does not.
lunix-init also provides service monitoring using NATS.
A design goal for lunix is to be cloud-ready. Thus, we want turn-key solutions for creating a cluster of lunix machines which behave as a unified organism. To do this, lunix provives easy (optional) mechanism to
- plug a lunix installation into an overlay network (slacks nebula or wireguard)
- manage floating storage (something like ceph or something based on a private ipfs + brig or dat
- update machines remotely (using
nix copy
) - plug in lunix into a NATS message cluster to manage
- easily spin up k8s on top of lunix
With this, it's easy to manage an extremely large fleet of machines, which can be desktops, laptops, virtual machines, bare-metal servers, iot devices, and everything else.
- Running lunix on an encrypted drive is easy
- Pre-configured stuff to provision PKI keys using HSMs
- Using Hashicorp Vault to provision keys should also be easy
- Using Yubikeys, PIV smartcards (any PKCS#11-capable device), GPG smartcards, or U2F keys to log into a lunix machine should be trivial. PIV support should be first-class so that companies managing lots and lots of machines can easily grant and revoke user access.
- It would be cool to try to integrate bedrock linux with lunix.