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.
tty2, tty3, and similar service descriptions and adding them to boot as milestone dependencies.
Command Explanations
install -d /system/configuration/dinit.d/scripts: Creates the service directory and script subdirectory for dinit.cat > /system/configuration/dinit.d/boot: Writes the top-level boot target service.cat > .../scripts/early-filesystems: Writes the helper script that mounts or verifies early virtual filesystems.mounted(): Checks/system/processes/mountsso the script avoids remounting filesystems that are already present.cat > .../early-filesystems: Defines the scripted dinit service that runs the early filesystem helper.cat > .../rootrw: Defines the service that remounts/read-write after early filesystems exist.cat > .../loginreadyandcat > .../tty1: Define the login readiness target and first getty process.ln -sf ../binaries/dinit /system/systembinaries/init: Provides the conventional/system/systembinaries/initentry point for the boot process.dinit-check --services-dir ... boot: Validates the generated service graph before rebooting into it.