# docs / 03

Machines

A machine is an image plus everything you changed in it. This page covers daily use.

Create and open

chainboot run solinux                  # first time: download, create, open. Later: just open.
chainboot run solinux -- uname -a      # run one command instead of a shell
chainboot run solinux --name web       # another machine from the same image
chainboot run web                       # open a machine by its name

The machine is named after the image unless you choose a name. Inside, you are root. The shell starts in /root, like a fresh SSH session.

Options of run:

OptionMeaning
--name <machine>name of the machine to create or open
--arch <arch>take the image for another processor type (see "Other processor types")
--no-autosavecreate the machine with automatic saving turned off
--freshwhen signed in: do not bring back a saved machine with this name
-- <command>run this command instead of a shell; its exit status becomes chainboot's

Several terminals, one machine

Open a second terminal and run the same command: you are in the same machine, and both terminals see the same files and processes. The machine stops by itself a moment after the last terminal leaves.

Keep a machine running

For something that should stay up without an open terminal, such as a web server:

chainboot start web        # stays up until you stop it
chainboot run web -- service nginx start
chainboot stop web

Starting services automatically

An ordinary machine does not boot the way a physical computer does: there is no systemd running as the first process. (A machine can also boot for real: see Machines that boot below.) If a machine contains an executable file /etc/chainboot/start, chainboot runs it every time the machine starts. Put your service starts there:

cat > /etc/chainboot/start <<'SH'
#!/bin/sh
service nginx start
cd /srv/app && nohup ./my-server --port 8080 >/var/log/my-server.log 2>&1 &
SH
chmod +x /etc/chainboot/start

Its output goes to ~/.chainboot/machines/<name>/start.log on your computer.

What a machine is, exactly

What a machine is not:

Machines that boot

An ordinary machine starts with a shell and nothing else, which is fast and enough for most work. A machine that boots starts the image's own init system, systemd, as its first process, the way a server does:

chainboot run solinux --boot --name server
root@server:~# systemctl status                 # a whole system is up
root@server:~# apt install -y nginx             # the service starts by itself
root@server:~# systemctl status nginx
root@server:~# journalctl -u nginx

Services start in the right order, systemctl and journalctl work, timers run, and packages that bring a service have it running after installation. For an existing machine, chainboot boot <machine> on (or off) changes how it starts next time.

What is different from an ordinary machine:

What it needs: an image with an init system (Solinux has systemd; solinux-minimal and alpine do not), cgroup v2 (every current distribution), and, without administrator rights, a systemd user session, which a normal login gives you. Saving, restoring and exporting work the same; a restore stops the machine first.

Lazy machines: start before the download is done

Normally chainboot downloads a whole image and unpacks it before the first start. A lazy machine skips both. It gets only the list of the image's files, starts at once, and fetches a file's content from the chain when a program first opens it:

chainboot run solinux:lazy --lazy --name quick

How it works: beside the machine runs a small server process that shows the image as a file system (through the kernel's FUSE interface, which needs no extra software). When something reads a file, the server fetches the pack that holds it, checks it against the manifest and keeps it in the cache; from then on that file is read from disk. Nothing is unpacked, so a large system does not spend ten seconds writing thirty thousand files it may never use.

Measured on a computer that had nothing yet, from typing the command to the output of the first command inside the machine (devnet, a dozen endpoints):

ordinarylazy
Solinux (504 MB of files)15 s4 s
Solinux minimal (90 MB of files)4 s2.4 s
disk used after a shell, git, python and apt-get update (Solinux)665 MB76 MB

On a computer that has the image already, an ordinary machine starts in 0.2 s and a lazy one in under a second; lazy pays off on the first start, and for systems much larger than what you use of them.

Needs /dev/fuse, which every mainstream Linux has.

From a machine to the disk of a real computer

A machine borrows the kernel of the computer it runs on. A real computer, or a virtual machine, needs a disk with a kernel of its own, a boot loader and a partition table. chainboot disk writes a machine out as such a disk:

chainboot run solinux --name pc
root@pc:~# apt install -y linux-image-virtual systemd-boot-efi mtools dosfstools fdisk
root@pc:~# passwd                     # somebody must be able to log in on the new computer
root@pc:~# exit

chainboot disk pc pc.img              # about 20 seconds

pc.img is a complete disk: a GPT partition table, an EFI system partition with systemd-boot, the kernel and its initrd, and an ext4 partition with the machine's whole file system. It boots wherever there is UEFI firmware:

# in a virtual machine (QEMU; the package "ovmf" has the firmware)
qemu-system-x86_64 -m 2G -bios /usr/share/ovmf/OVMF.fd -drive file=pc.img,format=raw,if=virtio -nic user

# on a real computer: write it to a USB stick or a disk. This erases that device.
sudo dd if=pc.img of=/dev/sdX bs=4M conv=fsync status=progress

Good to know:

With or without administrator rights

Building a machine means mounting file systems and giving files their owners. On Linux there are two ways to be allowed to do that, and chainboot engine shows which one your computer uses:

chainboot engine              # show the current way
chainboot engine rootless     # run machines without administrator rights
chainboot engine sudo         # run machines through sudo

Without administrator rights ("rootless"). chainboot stays an ordinary program of yours and uses a Linux feature named *user namespaces*: inside the machine you are root and every user of the system (root, _apt, www-data, your own accounts) has its own files; outside, all of it belongs to you. No password is asked, and root inside the machine can do nothing on your computer that you cannot do yourself. A new installation chooses this way by itself when the computer has what it needs:

chainboot engine rootless checks these, tells you what is missing and adds it. That takes your administrator password once: to install the package, to reserve the IDs, or to add a small AppArmor profile that allows one program, chainboot's own copy of unshare in ~/.chainboot/bin/userns, to create user namespaces.

Two things differ from running through sudo: programs inside a machine cannot listen on ports below 1024 (use 8080 instead of 80, 2222 instead of 22), and a machine has the user IDs 0 to 65,536, which is all a normal system uses.

Through sudo. Every start and stop of a machine runs as the administrator. sudo asks for your password and remembers it for a few minutes. This works on every Linux system.

Switching. The two ways store file owners differently, so a home directory uses one of them. To switch, the home directory must hold no machines: save the ones you want to keep (chainboot save <machine>), remove them (chainboot rm <machine>), switch, and run them again. They come back from the chain exactly as they were, whichever way they were saved.

Other processor types

Images are published per processor type (amd64 for Intel/AMD, arm64 for ARM such as Apple silicon or Raspberry Pi). chainboot picks the one that fits your computer.

On Linux you can also run an image built for a different processor if QEMU user emulation is installed (sudo apt install qemu-user-static binfmt-support on Debian and Ubuntu):

chainboot run solinux-minimal --arch arm64 --name armbox

This is emulation, so it is much slower. It is useful for building and testing.

Housekeeping

chainboot machines              # all machines and whether they run
chainboot stop <machine>        # stop a running machine (open terminals in it are closed)
chainboot rm <machine>          # delete a machine and all its changes on this computer
chainboot images                # downloaded images and which machines use them
chainboot rmi <image>           # delete a downloaded image

Deleting a machine here does not touch its saves on chain. Two commands on the same machine never get in each other's way: a stop or rm waits for a start that is under way, two machines of the same image can be started at the same moment, and a command that arrives just as a machine is going away starts it again.

Turning a machine into an image

When a machine is set up the way you like it, you can make it an image and publish it:

chainboot export web web.tar
chainboot publish web.tar --name web --version 1.0 --reuse solinux --public --keypair me.json

export writes the machine's complete file system as a tar archive. It leaves out what must not be shared or is rebuilt anyway: SSH host keys, ~/.ssh, shell history, logs, the machine ID, temporary files and package caches. Details are in Publishing your own system.

Edit this page on GitHub