COSI Void Build
|This is an archived article or section.
This page is a legacy practice, project, or tutorial, and the information may not be up to date. See the talk page for more information about the page's status.
This is a page for the Void Linux lab build made by Benjamin Lannon in Summer 2016
- 1 Install
- 2 Post Install
- 3 Packages
- 4 Quick Setup
To install, burn any of the amd64 isos onto a flashdrive or cd. Next, boot it up and run
sudo void-installer in a terminal. This will give you a ncurses installer to install Void.
Skip Keyboard, and go down to Network and set it up with the ethernet and dhcp.
Next, choose network in the source menu which will download a minimal install with almost no packages other than the neccesary ones needed to boot.
In Hostname, name the computer cosi-0# depending on what computer it is being installed on. (When cloned, update it to match the computer in /etc/hostname)
Locale & Timezone
The locale is UTF-8 and the Timezone is America/New York
Enter the default COSI root password for the password section
In bootloader, install grub onto sda (or whatever the hard disk's is mounted as)
Next is the partitioning of the hard drive. I would suggest a configuration of the following: sda1 (/boot 2G), sda2 (swap 4G), sda3 (/ the rest). Make sure sda1's boot option is on.
In filesystems, change the file systems for each partition to be ext2, swap, and ext4 respectively and mount them to the above mountpoints.
Then you should be able to install completely. Once it has installed, reboot and you should come up to a default linux TTY.
Installing Extra packages
log in as csguest. A few packages need the non-free void repo, which can be installed with
sudo xbps-install -S void-repo-nonfree. Next, install the default packages as seen below.
Void Linux uses the Runit init system instead of systemd.
Runit's services are all contained in one directory--the one that
runsvdir is running in. On Void, these directories are used like runlevels, and may be found in
/etc/runit/runsvdir. A command
runsvchdir is provided to change runlevels in a smooth way.
The current runlevel is linked to
/etc/runit/runsvdir/current. That is also linked to
/var/service, which you'll see more of in this document. Bear in mind, when installing services, that these other runlevels exist.
The items in a
runsvdir directory, like
/var/service, have a well-defined layout; each entry should be a directory whose name is the service (hidden dot-directories are ignored), and this directory should contain:
- run, an exeutable file that runs the service. This should continue running for as long as the service is active, so you need to pass parameters to services that normally daemonize to tell them not to. It's also usually a good idea to
execthese processes, to avoid the extra useless shell. This is the only required entry.
- finish, an optional executable file called with two parameters after run exits: it's exit code, and it's
waitpidstatus. This can be used to clean up temporary files and perhaps log a shutdown.
- down, an optional file which, if it exists, indicates that
runsvdirwon't try to start this process automatically. You can still start it with
- log, an optional directory, which should contain a run and optional finish which will run as above, but the stdin of this run is piped from the stdout of the service's run. Useful for logging applications which aren't
- control, an optional directory, which should contain executable, single-character files corresponding to the commands sent to supervise/control (see below).
- check, an optional executable file called when
svis asked to check that a service is up (usually as a result of check, start, up with -v or -w, etc.). If omitted, a service is considered up as soon as runsv fork/execs run (which happens pretty quickly), so overriding this is a good idea for sensible dependency resolution. A service is considered "up" when check exits with code 0 (true).
runsvdir spawns a new
runsv in the directory of each conforming service directory in its working directory. Each
runsv process supervises the behavior of these services, and creates a directory in the service directory called control, which contains:
- status, a
daemontools-compatible status of the service itself.
- log/status, the same of the log service, if it exists.
- stat, a human-compatible version of status.
- log/stat, idem for the log service, if it exists.
- pid, the process ID of the service (under
- log/pid, idem for the log.
- control, a pipe which accepts character-based commands for the service. Each of these can be overriden by reimplementing control/X, where X is the command sent:
- u brings a service up, and tries to keep it up.
- d brings a service down, terminating it if need be. For control scripts, first t is invoked (to terminate it), then d.
- o brings a service up, but does not attempt to keep it up. For control scripts, this is effectively the same as u.
- p sends SIGSTOP, pausing the service.
- c sends SIGCONT, continuing a paused service.
- h sends SIGHUP.
- a sends SIGALRM.
- i sends SIGINT (usually equivalent to ^C).
- q sends SIGQUIT.
- 1 sends SIGUSR1.
- 2 sends SIGUSR2.
- t sends SIGTERM.
- k sends SIGKILL (which can't be blocked).
- x causes
runsvto exit, after shutting down the service: first, the control t (TERM) is invoked, followed by c (CONT). Then, if a log service exists, runsv breaks the stdin pipe and waits for it to terminate. (This can't be sent to the log service's control.) For control scripts, t is invoked, then x (but not c, notably).
In Void, service directories often reside in
/etc/sv, and are symlinked into any of the runsvdirs for various runlevels. This allows an administrator to easily control which services are available and/or started on boot.
sv command is used both by administrators and other services (normally for dependencies; see below). It accepts some options, a command, and the remaining positional arguments are interpreted as service names (id est, names of service directories under the WD of
runsvdir). The commands are:
- status or s: report the service(s)' status(es).
- exit or e: exit
runsv(send x to control). If -v is given, wait at most 7 seconds for check to return true. If -w n is given, wait at most n seconds. -w implies -v.
- Anything else: send the first letter of the command to control. Handles -w and -v as above for u, d, o, t, c, and x.
Some services naturally depend on each other. In Runit, thanks to
sv's timeout arguments and semantics, waiting on a dependent service is as easy as executing
sv -w 15 u service1 service2 service3
Where 15 is the number of seconds to wait at most, and
serviceX would be replaced with actual service names. These services should have a functioning check script to be effectively waited on.
To implement something akin to systemd's needs/wants system, one can use the exit code of sv, which is nonzero if any service fails to start or times out:
# "Needs" section if ! sv -w 15 u neededservice1 neededservice2; then logger "Failed to start $(basename $PWD): needed dependencies failed." echo -n "d" > supervise/control fi # "Wants" section sv -w 15 u wantedservice1 wantedservice2 || true; # "or true" can be omitted if -e (exit early) is not set on shell
Sometimes it is desireable to have a "service" which is more of a condition; for example, see the build's networking service, which represents more of an event. The core of this is that, since there is no daemon, we must keep run from terminating, which is easily done with an infinite sleep:
The check script, on the other hand, checks for the existence of a temporary file:
, namely the /etc/dhcpcd.exit-hook, which if the interface is up, touches that file:exec test -f /run/net_up </code>
This file is created in a hook on <code>dhcpcd
if $if_up; then touch /run/net_up fi
That's it! Now, services that need a network (like
rpc.gssd) can be made to wait on the service "networking":
sv -w 15 u networking
The tools used for these "event-based checks" can also be used to delay check for a little bit after a daemon is started, especially when that daemon takes a while to begin servicing requests; for an example of this, see again the rpcgssd service.
Although it rarely needs to be touched,
runit is the UNIX init process itself--PID 1. It is a little less flexible than the other executables (notably with hard-coded paths) out of necessity: it is the first user process spawned by the kernel, and as such it is exceedingly hard to pass it arguments.
Runit's config is isolated to
/etc/runit/, wherein you can find:
- 1, an executable file for phase 1 initialization, which contains things that should be done when the machine starts to get ready to run other processes; this includes, e.g., setting the hostname, mounting all filesystems, setting kernel parameters, etc.. In Void, this runs scripts found in core-services in lexicographic order, amongst some other little housekeeping things. If 1 crashes,
- 2, an executable file for phase 2 operation, which should start the system's normal array of user processes (usually via
runsvdir). In Void, this also handles some little things like determining what runlevel the system should start in, running the ancient
/etc/rc.local, and so forth. If 2 crashes, it is restarted.
- 3, an executable file for phase 3 termination, which should gracefully end all processes and save any state that needs to be saved before powering down. Regardless of how 3 exits,
runitthen calls the
rebootsyscall, either halting the system or rebooting, depending on the presence of reboot (see below).
- reboot, an optional file which, if executable by the owner, causes
runitto issue a reboot instead of a halt at the end of 3. Its contents are ignored. Void sets this in ctrlaltdel; see below.
- stopit, an optional file which, if executable by the owner, causes
runitto begin a shutdown (enter phase 3) if it receives a SIGCONT in phase 2 (which is otherwise ignored). Its contents are ignored. Void installs this file at the end of 1, immediately before it can take effect.
- ctrlaltdel, an optional file which, if executable by the owner, is run by
runitupon receiving SIGINT (usually via the kernel's handling of Ctrl+Alt+Del) in phase 2, immediately before sending SIGCONT to itself (and thus defering to stopit above).
Although strictly a part of Void and not Runit, you can consider core-services to be a cross between BSD-style and SysV-style initscripts, where they are run in lexicographic order by init without arguments and bring the system into a usable state. Sensibly, since running in phase 1 is so dire and risky, editing these should be avoided, and when it is done, they should be made pedantically fault-tolerant. In general, services should not be started here; it's more sensible (and usually quite a bit easier) to do that in the service runlevels, as a bove.
These are all packages manually installed after the base install (output of xbps-query -m)
alsa-utils arandr atom audacity blender chromium chromium-pepperflash codeblocks cowsay dia dmenu eclipse emacs espeak feh filezilla firefox gimp git go grub htop hub inkscape libreoffice lxdm mit-krb5-client neofetch neovim nfs-utils nodejs nss-pam-ldapd octave pam-krb5 python3 racket rsyslog ruby rxvt-unicode strace tmux vim vivaldi vlc void-repo-nonfree wget wireshark xfce4 xorg xterm xtools
This section assumes you're starting with a freshly-installed Void Linux, and that you would like to bring it into alignment with the COSI lab build (including Central Authentication).
For starters, enable the following services by symlinking them from
/var/service/, which, as above, is the "current" runlevel:
You may want to experiment with adding these to other runlevels.
Clone our build files repository, and copy everything in
/etc/sv/; then, symlink these services too:
Extract the contents of
/etc; this should configure PAM, LXDM, nslcd, and dhcpcd.
After this, in
nslcd/run and add a networking wait on the top, after the shebang:
#!/bin/sh sv -w 15 u networking mkdir -p /var/run/nslcd # ...lines elided...
Note: This has been observed to be destroyed during Void updates; if authentication seems broken after an update, please check that this edit is still in place.
/etc/hostname to set the hostname of the machine, then use
kadmin to download the correct host key from Talos.
Reboot, and check that everything works; if not, refer to the troubleshooting in How to add Kerberos to a Debian Machine, but bear in mind the differences:
/etc/pam.d/is completely different, and you're better off reading the man pages for PAM and the individual modules.
pamtesterisn't in Void's repos (yet).
- Note that Void uses the
sudoers(like BSD) instead of
sudo(though the file references both).
- Configuration for the nsswitch LDAP is in
/etc/libnss-ldap.conf. The libraries are different, but their configuration files appear to be completely compatible