9.3. dinit service setup

Create the first dinit service descriptions so the target system can mount its runtime filesystems and present a local console login.

Goal: install a minimal dinit service tree with a boot target, early runtime mounts, a writable root transition, and a supervised tty1 login prompt.

Upstream service note: dinit looks for a service named boot by default, reads plain-text service description files, and uses /etc/dinit.d as the default system service directory.

This section creates the smallest useful service graph for the first boot. It is not a full distribution policy yet. It is the point where the machine can become interactive under dinit supervision, which makes later boot services easier to add and debug from the system itself.

The login prompt uses getty from ubase. That package is already part of the book, is permissively licensed, and provides a local Linux getty that opens a tty, prompts for a login name, and then invokes /bin/login.

Create the service directories

install -d /system/configuration/dinit.d/scripts

The /etc compatibility link points at /system/configuration, so these files appear to dinit at /etc/dinit.d.

Create the boot service

The boot service is an internal grouping service. dinit starts it by default, and its dependencies pull in the actual boot work.

cat > /system/configuration/dinit.d/boot <<'EOF'
type = internal
depends-on: early-filesystems
depends-on: rootrw
depends-on: loginready
depends-ms: tty1
EOF

tty1 is a milestone dependency because a login prompt should be started during boot, but the whole boot target should not be torn down just because a getty process later exits and is restarted.

Create the early filesystem script

This script mounts the kernel-backed filesystems needed by the rest of early userspace. If an initramfs or kernel setup already mounted one of them, the script leaves it alone.

cat > /system/configuration/dinit.d/scripts/early-filesystems <<'EOF'
#!/system/binaries/sh
set -eu

mounted() {
    [ -r /system/processes/mounts ] || return 1

    while read -r device target type options rest
    do
        [ "$target" = "$1" ] && return 0
    done < /system/processes/mounts

    return 1
}

mkdir -p /proc /sys /dev /run

mounted /proc || mount -t proc proc /system/processes/
mounted /sys || mount -t sysfs sysfs /system/system
mounted /dev || mount -t devtmpfs devtmpfs /system/devices

mkdir -p /dev/pts /dev/shm /run

mounted /dev/pts || mount -t devpts devpts /system/devices/pts -o gid=5,mode=0620
mounted /run || mount -t tmpfs tmpfs /system/run

if [ -h /dev/shm ]; then
    install -d -m 1777 /system/run/shm
else
    mounted /dev/shm || mount -t tmpfs -o nosuid,nodev tmpfs /system/devices/shm
fi
EOF

chmod 755 /system/configuration/dinit.d/scripts/early-filesystems

Create the early filesystem service

cat > /system/configuration/dinit.d/early-filesystems <<'EOF'
type = scripted
command = /system/binaries/sh /system/configuration/dinit.d/scripts/early-filesystems
restart = false
options: starts-on-console
EOF

starts-on-console keeps early mount failures visible during boot, then releases the console once the script finishes.

Create the writable-root service

cat > /system/configuration/dinit.d/rootrw <<'EOF'
type = scripted
command = /system/binaries/mount -o remount,rw /
restart = false
depends-on: early-filesystems
options: starts-on-console starts-rwfs
EOF

The starts-rwfs option tells dinit that writable filesystems are now available. With this book's dinit build, that also gives dinit another opportunity to create its control socket at /run/dinitctl.

Create the login readiness service

cat > /system/configuration/dinit.d/loginready <<'EOF'
type = internal
depends-on: rootrw
options: runs-on-console
EOF

This service marks the point where the system can accept local logins. Holding the console here also keeps dinit's own service-status output from competing with the login prompt after startup reaches this point.

Create the tty1 getty service

cat > /system/configuration/dinit.d/tty1 <<'EOF'
type = process
command = /system/binaries/getty /devices/tty1 linux
restart = true
depends-on: loginready
EOF

ubase getty expects an absolute tty path. It then runs /bin/login, which resolves through the book's /bin compatibility link to /system/binaries/login.

Install init compatibility links

ln -sf ../binaries/dinit /system/systembinaries/init
ln -sf ../binaries/dinit /system/systembinaries/dinit

These links make both /sbin/init and /sbin/dinit resolve to the installed dinit binary through the book's /sbin -> /system/systembinaries compatibility link.

Check the service tree

dinit-check --services-dir /system/configuration/dinit.d boot

The check should finish without syntax errors or dependency cycles.

This setup intentionally starts only one login prompt. Additional virtual terminals can be added later by creating tty2, tty3, and similar service descriptions and adding them to boot as milestone dependencies.

Command Explanations