Chisle
The coding-agent plugin that bills 52% of a bare model across 20 live tasks. Terse persona + tool-output compressor + context diet.
翻訳待ち
NixithOS: NixOS without systemd, on s6-rc
翻訳待ち
Loading the full README.
Read the full README ↗NixOS without systemd: choose s6, dinit, runit, OpenRC or Finit as the init
system and service manager. Devices are managed by eudev, logs by s6-log.
The default is s6-linux-init with s6-rc.
This is not a rewritten distribution but a layer on top of ordinary nixpkgs
(currently the nixos-26.05 branch). The configuration is still a NixOS
configuration: the same configuration.nix, the same options, the same
service modules. What changes is what runs underneath them.
{ pkgs, ... }: {
networking.hostName = "box";
services.openssh.enable = true;
users.users.alice.isNormalUser = true;
# your own service is described the same way as in NixOS
systemd.services.hello = {
wantedBy = [ "multi-user.target" ];
serviceConfig.ExecStart = "${pkgs.hello}/bin/hello";
};
}
$ cat /proc/1/comm
s6-svscan
$ s6-rc -a list | head -3
basic.target
dbus
dbus-log
In NixOS every daemon, mount point and boot step is described by a systemd
unit; two thousand modules are written that way. Throwing them away would be
silly, so here systemd.services.* stays the data model: the units are
generated by the same code as in NixOS, and then the unitc compiler (it
runs only while the system is built) turns the directory of units into an
s6-rc service database.
| unit | what it becomes in s6-rc |
|---|---|
foo.service, Type=oneshot | oneshot foo |
foo.service, any other type | longrun foo + its logger foo-log |
foo.target | an empty oneshot: a synchronisation point |
foo.mount, foo.swap | oneshot running mount / swapon |
foo.socket | oneshot: the socket is bound in advance and kept in s6-fdholder; the service takes it on every start |
foo.timer | longrun with a scheduler (OnCalendar= and the rest) |
dev-….device | oneshot that waits for the device to appear |
The process of every service is started by unit-runtime: the environment,
User=, directories (RuntimeDirectory= and the like), limits,
capabilities, credentials, readiness (Type=notify, forking, dbus),
Restart=, ExecStartPre/Post, ExecStop, a cgroup per service.
s6-rc has one kind of dependency: "start after, require, restart together".
In systemd, ordering (After=) and requirement (Requires=) are different
things. If all the ordering were turned into dependencies, adding any timer
during nixith switch would restart half the system, because everything is
"after basic.target", and that one is "after timers.target".
So two databases are compiled from the same services:
compiled-boot: all the ordering is written as dependencies. The
system boots from it: s6-rc brings everything up in the right order and as
much in parallel as the order allows.compiled: only the real dependencies (Requires=, BindsTo=). The
system switches to it right after boot (s6-rc-update, without a single
restart) and lives on it.The order between units that are later started or stopped together
(systemctl start, switching the configuration, shutdown) is recovered from
a "rank": a number that grows along every After=.
More in docs/design.md.
The init system is a setting: nixithos.init = "dinit"; (the installer asks
too). dinit is PID 1 and the service manager then, and each user's manager
is dinit --user; the units, systemctl (with --user too), journalctl
and the logs stay the same. The unit compiler writes dinit's service
descriptions from the same graph, and since dinit tells requirement from
ordering itself (depends-on, waits-for, after), one set of them does
for the boot and for what comes after: no second database. A unit's
processes run under unit-supervise, which does for them what
s6-supervise does under s6. A switch to the other init system applies the
rest of the configuration at once and the init system at the next boot.
An installed system changes its init the same way: the line in
/etc/nixith/configuration.nix, sudo nixith boot and a reboot (the test
init-change takes one installation through dinit, runit, OpenRC and Finit and back
to s6).
$ cat /proc/1/comm
dinit
$ dinitctl list | head -3
[[+] ] boot
[{+} ] default
[{+} ] dbus (pid: 612)
nixithos.init = "runit"; makes runit PID 1, with runsvdir over a runsv
for every process of the system. runit knows nothing of what a service needs,
so unit-rc does (rcctl list, rcctl start …, the commands of dinitctl):
it reads the same service descriptions as dinit does, starts a service with
what it requires and waits for, runs the oneshots, and has runsv start the
processes, under unit-supervise as with dinit. Shutdown is runit's stage 3
after systemctl poweroff has stopped the units in order. The managers of
users stay s6 trees. The unit tests run on it as nix-build -A runit.boot
and so on.
$ cat /proc/1/comm
runit
$ rcctl list | head -3
[{+} ] boot
[[+] ] default
[[+] ] dbus
This is the beginning of the README. Read the rest at the original. Read the full README ↗