about summary refs log tree commit diff
path: root/examples
diff options
context:
space:
mode:
authorLaurent Bercot <ska-skaware@skarnet.org>2014-12-19 01:28:09 +0000
committerLaurent Bercot <ska-skaware@skarnet.org>2014-12-19 01:28:09 +0000
commitdf8c8876bc245c6124dd4691e5a95d8f397ca152 (patch)
treefcfec66704123b58c286aab83af16ab1b5248a21 /examples
parent90acd08f35f9691753fdd523c6970365b6ea4b73 (diff)
downloads6-df8c8876bc245c6124dd4691e5a95d8f397ca152.tar.gz
s6-df8c8876bc245c6124dd4691e5a95d8f397ca152.tar.xz
s6-df8c8876bc245c6124dd4691e5a95d8f397ca152.zip
Add examples/ subtree
Diffstat (limited to 'examples')
-rw-r--r--examples/ROOT/README6
l---------examples/ROOT/dev1
-rw-r--r--examples/ROOT/etc/README5
l---------examples/ROOT/etc/init1
-rw-r--r--examples/ROOT/etc/leapsecs.datbin0 -> 200 bytes
-rw-r--r--examples/ROOT/etc/s6-init/README9
-rwxr-xr-xexamples/ROOT/etc/s6-init/crash13
-rw-r--r--examples/ROOT/etc/s6-init/env/PATH1
-rw-r--r--examples/ROOT/etc/s6-init/env/README6
l---------examples/ROOT/etc/s6-init/init1
-rwxr-xr-xexamples/ROOT/etc/s6-init/init-stage158
-rwxr-xr-xexamples/ROOT/etc/s6-init/init-stage241
-rwxr-xr-xexamples/ROOT/etc/s6-init/init-stage346
-rwxr-xr-xexamples/ROOT/etc/s6-init/network-config5
-rw-r--r--examples/ROOT/img/README9
-rw-r--r--examples/ROOT/img/services-local/README5
-rw-r--r--examples/ROOT/img/services-local/klogd-linux/README3
-rw-r--r--examples/ROOT/img/services-local/klogd-linux/log/README1
-rwxr-xr-xexamples/ROOT/img/services-local/klogd-linux/log/run4
-rwxr-xr-xexamples/ROOT/img/services-local/klogd-linux/run5
-rw-r--r--examples/ROOT/img/services-local/syslogd-linux/README7
-rw-r--r--examples/ROOT/img/services-local/syslogd-linux/log/README4
-rwxr-xr-xexamples/ROOT/img/services-local/syslogd-linux/log/run5
-rwxr-xr-xexamples/ROOT/img/services-local/syslogd-linux/run8
-rw-r--r--examples/ROOT/img/services-network/README5
-rw-r--r--examples/ROOT/img/services-network/dns-cache/README2
-rw-r--r--examples/ROOT/img/services-network/dns-cache/env/CACHESIZE1
-rw-r--r--examples/ROOT/img/services-network/dns-cache/env/IP1
-rw-r--r--examples/ROOT/img/services-network/dns-cache/env/IPSEND1
-rw-r--r--examples/ROOT/img/services-network/dns-cache/env/ROOT1
-rw-r--r--examples/ROOT/img/services-network/dns-cache/log/README3
-rwxr-xr-xexamples/ROOT/img/services-network/dns-cache/log/run4
-rw-r--r--examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.10
-rw-r--r--examples/ROOT/img/services-network/dns-cache/root/servers/@13
-rwxr-xr-xexamples/ROOT/img/services-network/dns-cache/run12
-rw-r--r--examples/ROOT/img/services-network/fifodir-cleanup/README2
-rwxr-xr-xexamples/ROOT/img/services-network/fifodir-cleanup/run14
-rw-r--r--examples/ROOT/img/services-network/ntpclient/README9
-rw-r--r--examples/ROOT/img/services-network/ntpclient/log/README3
-rwxr-xr-xexamples/ROOT/img/services-network/ntpclient/log/run4
-rwxr-xr-xexamples/ROOT/img/services-network/ntpclient/run19
-rw-r--r--examples/ROOT/img/services-network/sshd/README5
-rw-r--r--examples/ROOT/img/services-network/sshd/log/README1
-rwxr-xr-xexamples/ROOT/img/services-network/sshd/log/run4
-rw-r--r--examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny0
-rw-r--r--examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow0
-rwxr-xr-xexamples/ROOT/img/services-network/sshd/run6
-rw-r--r--examples/ROOT/img/tmpfs/README7
-rw-r--r--examples/ROOT/img/tmpfs/dev/README4
-rw-r--r--examples/ROOT/img/tmpfs/dev/pts/README2
l---------examples/ROOT/img/tmpfs/dev/shm1
-rw-r--r--examples/ROOT/img/tmpfs/service/.s6-svscan/README2
l---------examples/ROOT/img/tmpfs/service/.s6-svscan/crash1
l---------examples/ROOT/img/tmpfs/service/.s6-svscan/finish1
-rw-r--r--examples/ROOT/img/tmpfs/service/README5
-rw-r--r--examples/ROOT/img/tmpfs/service/getty/README2
-rwxr-xr-xexamples/ROOT/img/tmpfs/service/getty/run2
-rw-r--r--examples/ROOT/img/tmpfs/service/s6-svscan-log/README9
-rwxr-xr-xexamples/ROOT/img/tmpfs/service/s6-svscan-log/run13
-rw-r--r--examples/ROOT/img/tmpfs/shm/README3
-rw-r--r--examples/ROOT/img/tmpfs/tmp/README4
-rw-r--r--examples/ROOT/img/tmpfs/tmp/uncaught-logs/README4
-rw-r--r--examples/ROOT/mnt/README1
-rw-r--r--examples/ROOT/mnt/procfs/README1
l---------examples/ROOT/mnt/rofs1
-rw-r--r--examples/ROOT/mnt/rwfs/README1
-rw-r--r--examples/ROOT/mnt/sysfs/README1
-rw-r--r--examples/ROOT/mnt/tmpfs/README1
-rw-r--r--examples/ROOT/mnt/tmpfs/dev/README14
l---------examples/ROOT/proc1
l---------examples/ROOT/sys1
l---------examples/ROOT/tmp1
-rwxr-xr-xexamples/s6-svscanboot8
73 files changed, 445 insertions, 0 deletions
diff --git a/examples/ROOT/README b/examples/ROOT/README
new file mode 100644
index 0000000..6e4806c
--- /dev/null
+++ b/examples/ROOT/README
@@ -0,0 +1,6 @@
+Study this filesystem tree skeleton carefully.
+After a few adjustments for your system, it can
+become the basis for a very fast, efficient and
+lightweight boot, with s6-svscan running as process 1
+for all of stage 2, i.e. practically the whole
+system lifetime.
diff --git a/examples/ROOT/dev b/examples/ROOT/dev
new file mode 120000
index 0000000..c957e39
--- /dev/null
+++ b/examples/ROOT/dev
@@ -0,0 +1 @@
+mnt/tmpfs/dev
\ No newline at end of file
diff --git a/examples/ROOT/etc/README b/examples/ROOT/etc/README
new file mode 100644
index 0000000..a605680
--- /dev/null
+++ b/examples/ROOT/etc/README
@@ -0,0 +1,5 @@
+Add this to your /etc/ directory.
+/etc/leapsecs.dat is needed for skalibs programs to work properly!
+/etc/init is what the kernel launches as process 1 if it does not
+find an init binary in other places. Make sure you remove other
+init programs to run this /etc/init as process 1 at boot time!
diff --git a/examples/ROOT/etc/init b/examples/ROOT/etc/init
new file mode 120000
index 0000000..d97434e
--- /dev/null
+++ b/examples/ROOT/etc/init
@@ -0,0 +1 @@
+s6-init/init
\ No newline at end of file
diff --git a/examples/ROOT/etc/leapsecs.dat b/examples/ROOT/etc/leapsecs.dat
new file mode 100644
index 0000000..86a9a90
--- /dev/null
+++ b/examples/ROOT/etc/leapsecs.dat
Binary files differdiff --git a/examples/ROOT/etc/s6-init/README b/examples/ROOT/etc/s6-init/README
new file mode 100644
index 0000000..7e104fd
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/README
@@ -0,0 +1,9 @@
+This is an example directory containing booting scripts
+that lead to s6-svscan running as process 1 in stage 2.
+
+Read them carefully and edit them to suit your needs.
+Some scripts are Linux-dependent; they can be easily
+adapted to other Unix systems.
+
+The skarnet.org servers actually run such a system, with
+scripts that are based on this model.
diff --git a/examples/ROOT/etc/s6-init/crash b/examples/ROOT/etc/s6-init/crash
new file mode 100755
index 0000000..501e316
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/crash
@@ -0,0 +1,13 @@
+#!/command/execlineb -P
+
+# This file is run when an unrecoverable error happens
+# to s6-svscan. Edit it to suit your needs.
+
+cd /
+redirfd -r 0 /dev/console
+redirfd -w 1 /dev/console
+fdmove -c 2 1
+
+foreground { s6-echo "s6-svscan panicked! Dropping to a root shell.\n" }
+
+/bin/sh -i
diff --git a/examples/ROOT/etc/s6-init/env/PATH b/examples/ROOT/etc/s6-init/env/PATH
new file mode 100644
index 0000000..a4c496e
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/env/PATH
@@ -0,0 +1 @@
+/command:/usr/bin:/bin:/usr/sbin:/sbin
diff --git a/examples/ROOT/etc/s6-init/env/README b/examples/ROOT/etc/s6-init/env/README
new file mode 100644
index 0000000..6c84e3b
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/env/README
@@ -0,0 +1,6 @@
+
+This directory is read by s6-envdir at boot time.
+It contains environment variables that will be present in
+all the supervision tree, and all the launched services.
+Make sure to remove this file, or else you'll have a
+README environment variable in all your daemons. :)
diff --git a/examples/ROOT/etc/s6-init/init b/examples/ROOT/etc/s6-init/init
new file mode 120000
index 0000000..4ac5fd9
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/init
@@ -0,0 +1 @@
+init-stage1
\ No newline at end of file
diff --git a/examples/ROOT/etc/s6-init/init-stage1 b/examples/ROOT/etc/s6-init/init-stage1
new file mode 100755
index 0000000..ea946e9
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/init-stage1
@@ -0,0 +1,58 @@
+#!/command/execlineb -P
+
+# This file is the first program run at boot time,
+# as process 1.
+# Edit it to suit your needs.
+
+# Make sure everything is sane and ignore input
+cd /
+umask 022
+fdclose 0
+
+# This should be printed to the console
+if { s6-echo "* init stage 1" }
+
+
+# Mount /sys and /proc
+if { s6-mount -wt sysfs sys /mnt/sysfs }
+if { s6-mount -wt proc proc /mnt/procfs }
+
+# Close remaining handles to /dev/console
+fdclose 1 fdclose 2
+
+# Now no process has any open fd to /dev/console (or to
+# anything for that matter).
+# We can safely overwrite the minimal /dev with the real one.
+
+# in case some Linux kernel has mounted a devtmpfs
+foreground { s6-umount /mnt/tmpfs/dev }
+
+# Make the tmpfs
+if { s6-mount -wt tmpfs -o mode=0755,size=67108864 tmpfs /mnt/tmpfs }
+
+# Copy the image to the tmpfs
+if { s6-hiercopy /img/tmpfs /mnt/tmpfs }
+
+# Now we have a working /dev and /tmp, and a minimal writable /service
+# with a catch-all logger and a getty. We're good for stage 2 !
+
+# Reopen stdin/stdout/stderr and make them point to the right places
+redirfd -r 0 /dev/null
+redirfd -wnb 1 /service/s6-svscan-log/fifo # (black magic: doesn't block)
+fdmove -c 2 1
+
+# Load the general environment
+s6-envdir /etc/s6-init/env
+
+# Fork the "init-stage2" script and have it ready to start as soon
+# as the catch-all logger is in place
+background
+{
+  s6-setsid
+  redirfd -w 1 /service/s6-svscan-log/fifo # (blocks until the logger reads)
+  /etc/s6-init/init-stage2
+}
+unexport LASTPID
+
+# Start stage 2.
+s6-svscan -t0 /service
diff --git a/examples/ROOT/etc/s6-init/init-stage2 b/examples/ROOT/etc/s6-init/init-stage2
new file mode 100755
index 0000000..ad6d8ce
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/init-stage2
@@ -0,0 +1,41 @@
+#!/command/execlineb -P
+
+# This file is executed (not as process 1!) as soon as s6-svscan
+# starts. It should perform all the remaining one-time initialization
+# tasks.
+
+
+if -nt
+{
+
+# This should be logged in /tmp/uncaught-logs/current,
+# NOT on /dev/console !
+  if { s6-echo "* init-stage2 starting." }
+
+# Call your one-time EARLY initialization scripts (before bringing
+# the network up) here:
+# set the hostname, mount filesystems, adjust sysctls, etc.
+# if { s6-mount -wt devpts -o noexec,nosuid,gid=0,mode=0600 devpts /dev/pts }
+# if { s6-mount -wt ext4 /dev/sda3 /mnt/rwfs }
+
+# Start the local services
+  if { s6-hiercopy /img/services-local /service }
+  if { s6-svscanctl -a /service }
+
+# Bring up the network
+  if { /etc/s6-init/network-config }
+
+# Start the late services
+  if { s6-hiercopy /img/services-network /service }
+  if { s6-svscanctl -a /service }
+
+# We're done and the machine is fully operational.
+  s6-echo "* init-stage2 completed."
+}
+
+
+# If anything in the if -nt { } block fails, control jumps here.
+# No need to do much because there's already an operational getty running.
+
+redirfd -w 1 /dev/console
+s6-echo "\n!!!!!\ninit-stage2 failed, please log in and investigate.\n!!!!!"
diff --git a/examples/ROOT/etc/s6-init/init-stage3 b/examples/ROOT/etc/s6-init/init-stage3
new file mode 100755
index 0000000..66b3062
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/init-stage3
@@ -0,0 +1,46 @@
+#!/command/execlineb -S0
+
+# This is the shutdown script, running as process 1.
+
+# Make sure we have no open handle to anywhere else
+# than /dev/console
+cd /
+fdclose 0
+redirfd -w 1 /dev/console
+fdmove -c 2 1
+
+foreground { s6-echo "Syncing disks." }
+foreground { s6-sync }
+
+
+# Even if s6-svscan properly brought all the services down
+# before exec'ing into this script, users might have launched
+# background nohup processes, so we have to kill everything.
+
+foreground { s6-echo "Sending all processes the TERM signal." }
+foreground { s6-nuke -th }
+foreground { s6-sleep 1 }
+foreground { s6-echo "Sending all processes the KILL signal." }
+foreground { s6-nuke -k }
+
+# Here, s6-nuke sends a SIGKILL to every process on the system.
+# It kills itself, but not before the SIGKILL has been broadcast.
+# The "foreground" process runs as process 1, so it survives,
+# and execs into the rest of the script when s6-nuke dies.
+
+# Reap the huge army of zombies we just created
+wait { }
+
+
+foreground { s6-echo "Syncing disks." }
+foreground { s6-sync } # yes, it helps.
+foreground { s6-echo "Unmounting disks." }
+
+# Unmount all your filesystems here, turn off swap,
+# remount / read-only if needed, etc.
+# foreground { s6-umount /mnt/rwfs }
+
+# Reboot, halt or poweroff the machine, depending on the parameter
+# that was given to the script.
+foreground { s6-echo "\nPerforming "${1}"." }
+s6-${1}
diff --git a/examples/ROOT/etc/s6-init/network-config b/examples/ROOT/etc/s6-init/network-config
new file mode 100755
index 0000000..2f9e3cd
--- /dev/null
+++ b/examples/ROOT/etc/s6-init/network-config
@@ -0,0 +1,5 @@
+#!/command/execlineb -P
+
+# if { ifconfig lo 127.0.0.1 netmask 255.0.0.0 }
+
+# Configure your network interfaces and routing here.
diff --git a/examples/ROOT/img/README b/examples/ROOT/img/README
new file mode 100644
index 0000000..8181be3
--- /dev/null
+++ b/examples/ROOT/img/README
@@ -0,0 +1,9 @@
+This directory is read-only. It contains the service
+repository (actually one list of services that do not
+need the network and one list of services that can only
+be started after the network is up), and an image of the
+tmpfs that it copied as-is at boot-time (during stage 1
+init).
+This directory is only used at boot-time, it is never
+written to (the service directories are copied as-is
+to /service during stage 2 init).
diff --git a/examples/ROOT/img/services-local/README b/examples/ROOT/img/services-local/README
new file mode 100644
index 0000000..9e4c027
--- /dev/null
+++ b/examples/ROOT/img/services-local/README
@@ -0,0 +1,5 @@
+This is the service repository for services that should be started
+early, typically before the network goes up.
+"klogd" and "syslogd" services should be present as soon as possible,
+because other services might need them. However, since they need
+a writable disk filesystem, they can't be run as early as a getty.
diff --git a/examples/ROOT/img/services-local/klogd-linux/README b/examples/ROOT/img/services-local/klogd-linux/README
new file mode 100644
index 0000000..ec95a00
--- /dev/null
+++ b/examples/ROOT/img/services-local/klogd-linux/README
@@ -0,0 +1,3 @@
+This klogd emulation is only valid under Linux.
+The service only processes logs from /proc/kmsg and
+sends them to stdout, i.e. its own logger.
diff --git a/examples/ROOT/img/services-local/klogd-linux/log/README b/examples/ROOT/img/services-local/klogd-linux/log/README
new file mode 100644
index 0000000..6b51a4a
--- /dev/null
+++ b/examples/ROOT/img/services-local/klogd-linux/log/README
@@ -0,0 +1 @@
+Processed kernel logs will be logged to the /var/log/klogd/ logdir.
diff --git a/examples/ROOT/img/services-local/klogd-linux/log/run b/examples/ROOT/img/services-local/klogd-linux/log/run
new file mode 100755
index 0000000..66f2cd5
--- /dev/null
+++ b/examples/ROOT/img/services-local/klogd-linux/log/run
@@ -0,0 +1,4 @@
+#!/command/execlineb -P
+s6-setuidgid klog
+exec -c
+s6-log -t s1000000 n20 /var/log/klogd
diff --git a/examples/ROOT/img/services-local/klogd-linux/run b/examples/ROOT/img/services-local/klogd-linux/run
new file mode 100755
index 0000000..453b55b
--- /dev/null
+++ b/examples/ROOT/img/services-local/klogd-linux/run
@@ -0,0 +1,5 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+redirfd -r 0 /proc/kmsg
+exec -c
+ucspilogd
diff --git a/examples/ROOT/img/services-local/syslogd-linux/README b/examples/ROOT/img/services-local/syslogd-linux/README
new file mode 100644
index 0000000..a3c3ba4
--- /dev/null
+++ b/examples/ROOT/img/services-local/syslogd-linux/README
@@ -0,0 +1,7 @@
+This syslogd emulation works on any Unix where syslog() is
+implemented via a connection on the /dev/log Unix-domain socket.
+It needs a Unix superserver (see s6-networking, ucspi-unix or
+ucspi-ipc) and ucspilogd.
+A ucspilogd process is spawned for every syslog() client. It
+processes logs and sends them to stderr, i.e. the service's
+logger.
diff --git a/examples/ROOT/img/services-local/syslogd-linux/log/README b/examples/ROOT/img/services-local/syslogd-linux/log/README
new file mode 100644
index 0000000..de384ce
--- /dev/null
+++ b/examples/ROOT/img/services-local/syslogd-linux/log/README
@@ -0,0 +1,4 @@
+This logger service logs everything the syslogd service receives
+into the /var/log/syslogd/ logdir.
+You may want to edit the logging script to provide filters to
+change s6-log's behaviour.
diff --git a/examples/ROOT/img/services-local/syslogd-linux/log/run b/examples/ROOT/img/services-local/syslogd-linux/log/run
new file mode 100755
index 0000000..0d99ba9
--- /dev/null
+++ b/examples/ROOT/img/services-local/syslogd-linux/log/run
@@ -0,0 +1,5 @@
+#!/command/execlineb -P
+s6-setuidgid syslog
+exec -c
+s6-log -t s1000000 n20 /var/log/syslogd
+# Change the logging script to alter s6-log's behaviour
diff --git a/examples/ROOT/img/services-local/syslogd-linux/run b/examples/ROOT/img/services-local/syslogd-linux/run
new file mode 100755
index 0000000..f58a862
--- /dev/null
+++ b/examples/ROOT/img/services-local/syslogd-linux/run
@@ -0,0 +1,8 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+exec -c
+s6-envuidgid nobody
+s6-notifywhenup -f
+s6-ipcserver -U -1 -- /dev/log
+fdmove -c 1 2
+ucspilogd IPCREMOTEEUID IPCREMOTEEGID
diff --git a/examples/ROOT/img/services-network/README b/examples/ROOT/img/services-network/README
new file mode 100644
index 0000000..9f4ab38
--- /dev/null
+++ b/examples/ROOT/img/services-network/README
@@ -0,0 +1,5 @@
+This is the service repository for all the late services,
+i.e. those that do not need to be started before the network
+is up.
+Only a few examples are provided here; you can make your own
+service directories depending on your needs.
diff --git a/examples/ROOT/img/services-network/dns-cache/README b/examples/ROOT/img/services-network/dns-cache/README
new file mode 100644
index 0000000..8fc5c28
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/README
@@ -0,0 +1,2 @@
+Service directory for a DNS caching resolver service,
+implemented via djbdns's dnscache running on 127.0.0.1
diff --git a/examples/ROOT/img/services-network/dns-cache/env/CACHESIZE b/examples/ROOT/img/services-network/dns-cache/env/CACHESIZE
new file mode 100644
index 0000000..6820bf1
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/env/CACHESIZE
@@ -0,0 +1 @@
+1048576
diff --git a/examples/ROOT/img/services-network/dns-cache/env/IP b/examples/ROOT/img/services-network/dns-cache/env/IP
new file mode 100644
index 0000000..7b9ad53
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/env/IP
@@ -0,0 +1 @@
+127.0.0.1
diff --git a/examples/ROOT/img/services-network/dns-cache/env/IPSEND b/examples/ROOT/img/services-network/dns-cache/env/IPSEND
new file mode 100644
index 0000000..d690dc0
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/env/IPSEND
@@ -0,0 +1 @@
+0.0.0.0
diff --git a/examples/ROOT/img/services-network/dns-cache/env/ROOT b/examples/ROOT/img/services-network/dns-cache/env/ROOT
new file mode 100644
index 0000000..0a89945
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/env/ROOT
@@ -0,0 +1 @@
+/service/dns-cache/root
diff --git a/examples/ROOT/img/services-network/dns-cache/log/README b/examples/ROOT/img/services-network/dns-cache/log/README
new file mode 100644
index 0000000..55676f1
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/log/README
@@ -0,0 +1,3 @@
+Logger service for the dns-cache service.
+djbdns's dnscache produces a lot of output, so
+you may want to add log filters.
diff --git a/examples/ROOT/img/services-network/dns-cache/log/run b/examples/ROOT/img/services-network/dns-cache/log/run
new file mode 100755
index 0000000..7bd42bd
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/log/run
@@ -0,0 +1,4 @@
+#!/command/execlineb -P
+s6-setuidgid dnslog
+exec -c
+s6-log -t s1000000 n20 /var/log/dns-cache
diff --git a/examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.1 b/examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.1
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/root/ip/127.0.0.1
diff --git a/examples/ROOT/img/services-network/dns-cache/root/servers/@ b/examples/ROOT/img/services-network/dns-cache/root/servers/@
new file mode 100644
index 0000000..ca40b38
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/root/servers/@
@@ -0,0 +1,13 @@
+198.41.0.4
+192.228.79.201
+192.33.4.12
+128.8.10.90
+192.203.230.10
+192.5.5.241
+192.112.36.4
+128.63.2.53
+192.36.148.17
+192.58.128.30
+193.0.14.129
+199.7.83.42
+202.12.27.33
diff --git a/examples/ROOT/img/services-network/dns-cache/run b/examples/ROOT/img/services-network/dns-cache/run
new file mode 100755
index 0000000..af92aae
--- /dev/null
+++ b/examples/ROOT/img/services-network/dns-cache/run
@@ -0,0 +1,12 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+s6-envuidgid dnscache
+s6-envdir env
+s6-softlimit -m 2000000
+pipeline -d
+{
+  redirfd -r 0 /dev/urandom
+  s6-head -c 128
+}
+unexport !
+dnscache
diff --git a/examples/ROOT/img/services-network/fifodir-cleanup/README b/examples/ROOT/img/services-network/fifodir-cleanup/README
new file mode 100644
index 0000000..2c41ea2
--- /dev/null
+++ b/examples/ROOT/img/services-network/fifodir-cleanup/README
@@ -0,0 +1,2 @@
+This service cleans up the fifodirs for all the services in
+/service once a day.
diff --git a/examples/ROOT/img/services-network/fifodir-cleanup/run b/examples/ROOT/img/services-network/fifodir-cleanup/run
new file mode 100755
index 0000000..9928d84
--- /dev/null
+++ b/examples/ROOT/img/services-network/fifodir-cleanup/run
@@ -0,0 +1,14 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+if
+{
+  forbacktickx -p -0 i { s6-ls -0 /service }
+  import i unexport i
+  foreground
+  {
+    if { s6-test -d /service/${i}/log }
+    s6-cleanfifodir /service/${i}/log/event
+  }
+  s6-cleanfifodir /service/${i}/event
+}
+s6-sleep 86400
diff --git a/examples/ROOT/img/services-network/ntpclient/README b/examples/ROOT/img/services-network/ntpclient/README
new file mode 100644
index 0000000..c4fc357
--- /dev/null
+++ b/examples/ROOT/img/services-network/ntpclient/README
@@ -0,0 +1,9 @@
+This service updates the system clock via NTP every 4 hours.
+If you're not in France, change 0.fr.pool.ntp.org to a NTP
+server pool more fitting your location.
+See www.ntp.pool.org for details.
+
+Do yourself a favor and don't rely on NTP internally.
+Just synchronize your main time server via this NTP client
+to the outside world, and use a saner and simpler protocol
+like TAICLOCK in your internal, fast-speed network.
diff --git a/examples/ROOT/img/services-network/ntpclient/log/README b/examples/ROOT/img/services-network/ntpclient/log/README
new file mode 100644
index 0000000..e4c7a37
--- /dev/null
+++ b/examples/ROOT/img/services-network/ntpclient/log/README
@@ -0,0 +1,3 @@
+Yes, the output of the ntpclient service is logged to
+the /var/log/ntpclient logdir.
+Make sure it has the correct Unix credentials and permissions!
diff --git a/examples/ROOT/img/services-network/ntpclient/log/run b/examples/ROOT/img/services-network/ntpclient/log/run
new file mode 100755
index 0000000..261b534
--- /dev/null
+++ b/examples/ROOT/img/services-network/ntpclient/log/run
@@ -0,0 +1,4 @@
+#!/command/execlineb -P
+s6-setuidgid ntplog
+exec -c
+s6-log -t /var/log/ntpclient
diff --git a/examples/ROOT/img/services-network/ntpclient/run b/examples/ROOT/img/services-network/ntpclient/run
new file mode 100755
index 0000000..7ade064
--- /dev/null
+++ b/examples/ROOT/img/services-network/ntpclient/run
@@ -0,0 +1,19 @@
+#!/command/execlineb -P
+
+fdmove -c 2 1
+if
+{
+  pipeline
+  {
+    s6-setuidgid ntp
+    backtick -n NTPSERVERIP
+    {
+      pipeline { s6-dnsip4 -t 16000 0.fr.pool.ntp.org. }
+      s6-head -n 1
+    }
+    s6-sntpclock -v $NTPSERVERIP
+  }
+  s6-clockadd
+}
+s6-setuidgid nobody
+s6-sleep 14400
diff --git a/examples/ROOT/img/services-network/sshd/README b/examples/ROOT/img/services-network/sshd/README
new file mode 100644
index 0000000..2d55a5e
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/README
@@ -0,0 +1,5 @@
+Service directory for a sshd server over IPv4,
+implemented via s6-networking and dropbear.
+The rules subdirectory implements access control; in
+this example, only 127.0.0.1 is allowed to connect
+(which isn't exactly useful for a SSH server).
diff --git a/examples/ROOT/img/services-network/sshd/log/README b/examples/ROOT/img/services-network/sshd/log/README
new file mode 100644
index 0000000..392ede8
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/log/README
@@ -0,0 +1 @@
+Logging service for sshd.
diff --git a/examples/ROOT/img/services-network/sshd/log/run b/examples/ROOT/img/services-network/sshd/log/run
new file mode 100755
index 0000000..9795581
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/log/run
@@ -0,0 +1,4 @@
+#!/command/execlineb -P
+s6-setuidgid log
+exec -c
+s6-log -t s1000000 n20 /var/log/sshd
diff --git a/examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny b/examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/rules/ip4/0.0.0.0_0/deny
diff --git a/examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow b/examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/rules/ip4/127.0.0.1_32/allow
diff --git a/examples/ROOT/img/services-network/sshd/run b/examples/ROOT/img/services-network/sshd/run
new file mode 100755
index 0000000..45bc6a8
--- /dev/null
+++ b/examples/ROOT/img/services-network/sshd/run
@@ -0,0 +1,6 @@
+#!/command/execlineb -P
+fdmove -c 2 1
+s6-notifywhenup -f
+s6-tcpserver4 -1 -- 0.0.0.0 22
+s6-tcpserver-access -vvDRl0 -t 5000 -i rules
+dropbear -iEg
diff --git a/examples/ROOT/img/tmpfs/README b/examples/ROOT/img/tmpfs/README
new file mode 100644
index 0000000..3b329e4
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/README
@@ -0,0 +1,7 @@
+/img/tmpfs is the hierarchy that will be copied to /mnt/tmpfs
+during stage 1 init, so the basics are covered for stage 2:
+ - /dev points to a real, writable device directory
+ - /tmp points to a real, writable temporary directory
+ - /service points to a real, writable scan directory that
+already contains basic services (s6-svscan's own logger and
+an early getty).
diff --git a/examples/ROOT/img/tmpfs/dev/README b/examples/ROOT/img/tmpfs/dev/README
new file mode 100644
index 0000000..8b944ff
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/dev/README
@@ -0,0 +1,4 @@
+This directory is the /dev image.
+It should contain all your static devices.
+It MUST contain at least /dev/null and /dev/console,
+else the system will crash during stage 1 init.
diff --git a/examples/ROOT/img/tmpfs/dev/pts/README b/examples/ROOT/img/tmpfs/dev/pts/README
new file mode 100644
index 0000000..e0553f0
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/dev/pts/README
@@ -0,0 +1,2 @@
+The place (after it's copied to the tmpfs) where
+the virtual devpts filesystem will be mounted.
diff --git a/examples/ROOT/img/tmpfs/dev/shm b/examples/ROOT/img/tmpfs/dev/shm
new file mode 120000
index 0000000..c71cdc8
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/dev/shm
@@ -0,0 +1 @@
+../shm
\ No newline at end of file
diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/README b/examples/ROOT/img/tmpfs/service/.s6-svscan/README
new file mode 100644
index 0000000..6500cc6
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/.s6-svscan/README
@@ -0,0 +1,2 @@
+This is the image of the control directory of the s6-svscan process.
+Notice how the symlinks point to ever-existing scripts.
diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/crash b/examples/ROOT/img/tmpfs/service/.s6-svscan/crash
new file mode 120000
index 0000000..262c196
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/.s6-svscan/crash
@@ -0,0 +1 @@
+/etc/s6-init/crash
\ No newline at end of file
diff --git a/examples/ROOT/img/tmpfs/service/.s6-svscan/finish b/examples/ROOT/img/tmpfs/service/.s6-svscan/finish
new file mode 120000
index 0000000..feb771e
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/.s6-svscan/finish
@@ -0,0 +1 @@
+/etc/s6-init/init-stage3
\ No newline at end of file
diff --git a/examples/ROOT/img/tmpfs/service/README b/examples/ROOT/img/tmpfs/service/README
new file mode 100644
index 0000000..dab0447
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/README
@@ -0,0 +1,5 @@
+This is the initial image of the scan directory.
+When init executes into s6-svscan, s6-svscan will immediately
+start the "s6-svscan-log" service, which logs s6-svscan's own
+output, and the "getty1" service, which spawns a getty on
+tty1 as early as possible, in case debugging is needed.
diff --git a/examples/ROOT/img/tmpfs/service/getty/README b/examples/ROOT/img/tmpfs/service/getty/README
new file mode 100644
index 0000000..efb079b
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/getty/README
@@ -0,0 +1,2 @@
+This service is started very early, to make sure a tty exists as soon
+as s6-svscan is run, so early debugging is possible.
diff --git a/examples/ROOT/img/tmpfs/service/getty/run b/examples/ROOT/img/tmpfs/service/getty/run
new file mode 100755
index 0000000..3240ffd
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/getty/run
@@ -0,0 +1,2 @@
+#!/command/execlineb -P
+getty -L -H DEBUG 38400 tty1
diff --git a/examples/ROOT/img/tmpfs/service/s6-svscan-log/README b/examples/ROOT/img/tmpfs/service/s6-svscan-log/README
new file mode 100644
index 0000000..282d4f0
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/s6-svscan-log/README
@@ -0,0 +1,9 @@
+This service reads from the "fifo" named pipe and logs
+what it reads to the /tmp/uncaught-logs log directory.
+The whole supervision tree has its stderr redirected to "fifo",
+as well as services that do not have their own logger.
+So, /tmp/uncaught-logs is the catch-all logger: logs that aren't
+caught anywhere else end up there.
+
+ You should create the "fifo" named pipe in this directory,
+belonging to nobody:nogroup with rights 0622.
diff --git a/examples/ROOT/img/tmpfs/service/s6-svscan-log/run b/examples/ROOT/img/tmpfs/service/s6-svscan-log/run
new file mode 100755
index 0000000..a55a822
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/service/s6-svscan-log/run
@@ -0,0 +1,13 @@
+#!/command/execlineb -P
+redirfd -w 2 /dev/console
+redirfd -rnb 0 fifo
+s6-setuidgid nobody
+exec -c
+s6-log -bpt /tmp/uncaught-logs
+
+#  The -p option is important:
+# even if s6-svscan is told to kill everything,
+# you do not want this logger to die.
+#  The -b option ensures s6-log processes lines one
+# at a time, so it doesn't eat up too much memory
+# in case of a problem spike.
diff --git a/examples/ROOT/img/tmpfs/shm/README b/examples/ROOT/img/tmpfs/shm/README
new file mode 100644
index 0000000..7ef7853
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/shm/README
@@ -0,0 +1,3 @@
+This directory exists so /dev/shm points to a place
+in the tmpfs.
+It should have "1777" rights.
diff --git a/examples/ROOT/img/tmpfs/tmp/README b/examples/ROOT/img/tmpfs/tmp/README
new file mode 100644
index 0000000..1e437a0
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/tmp/README
@@ -0,0 +1,4 @@
+This directory contains what will be /mnt/tmpfs/tmp after
+stage 1 init, so it contains everything /tmp should point
+to.
+It should have "1777" rights.
diff --git a/examples/ROOT/img/tmpfs/tmp/uncaught-logs/README b/examples/ROOT/img/tmpfs/tmp/uncaught-logs/README
new file mode 100644
index 0000000..c13d539
--- /dev/null
+++ b/examples/ROOT/img/tmpfs/tmp/uncaught-logs/README
@@ -0,0 +1,4 @@
+This directory should not belong to root, but to nobody:nogroup;
+it should also have "2700" rights.
+It is the catch-all logdir.
+/tmp/uncaught-logs/current will be the current catch-all log file.
diff --git a/examples/ROOT/mnt/README b/examples/ROOT/mnt/README
new file mode 100644
index 0000000..7f0e106
--- /dev/null
+++ b/examples/ROOT/mnt/README
@@ -0,0 +1 @@
+The directory containing all the real mount points.
diff --git a/examples/ROOT/mnt/procfs/README b/examples/ROOT/mnt/procfs/README
new file mode 100644
index 0000000..79b2fe0
--- /dev/null
+++ b/examples/ROOT/mnt/procfs/README
@@ -0,0 +1 @@
+/proc will be mounted here.
diff --git a/examples/ROOT/mnt/rofs b/examples/ROOT/mnt/rofs
new file mode 120000
index 0000000..a96aa0e
--- /dev/null
+++ b/examples/ROOT/mnt/rofs
@@ -0,0 +1 @@
+..
\ No newline at end of file
diff --git a/examples/ROOT/mnt/rwfs/README b/examples/ROOT/mnt/rwfs/README
new file mode 100644
index 0000000..c8b4ade
--- /dev/null
+++ b/examples/ROOT/mnt/rwfs/README
@@ -0,0 +1 @@
+If you have a disk read-write filesystem, you may mount it here.
diff --git a/examples/ROOT/mnt/sysfs/README b/examples/ROOT/mnt/sysfs/README
new file mode 100644
index 0000000..9c02561
--- /dev/null
+++ b/examples/ROOT/mnt/sysfs/README
@@ -0,0 +1 @@
+/sys will be mounted here.
diff --git a/examples/ROOT/mnt/tmpfs/README b/examples/ROOT/mnt/tmpfs/README
new file mode 100644
index 0000000..0900a3a
--- /dev/null
+++ b/examples/ROOT/mnt/tmpfs/README
@@ -0,0 +1 @@
+The general tmpfs will be mounted here.
diff --git a/examples/ROOT/mnt/tmpfs/dev/README b/examples/ROOT/mnt/tmpfs/dev/README
new file mode 100644
index 0000000..4489cc5
--- /dev/null
+++ b/examples/ROOT/mnt/tmpfs/dev/README
@@ -0,0 +1,14 @@
+This directory (/mnt/tmpfs/dev on the root filesystem) will
+be brutally overriden when the tmpfs is mounted. Its only
+purpose is to provide an initial /dev/console to the kernel
+when it starts process 1.
+The directory should contain a working /dev/console device!
+
+ init-stage1 will close all handles to this /dev/console,
+then mount the tmpfs and copy the tmpfs image to the tmpfs
+- the image contains a full version of /dev, which will then
+be used.
+ This trick is necessary to have a working read-write /dev
+when you have a root-only filesystem and when you cannot or
+do not want to rely on fancy Linux-specific tricks such as
+devtmpfs.
diff --git a/examples/ROOT/proc b/examples/ROOT/proc
new file mode 120000
index 0000000..e018ea9
--- /dev/null
+++ b/examples/ROOT/proc
@@ -0,0 +1 @@
+mnt/procfs
\ No newline at end of file
diff --git a/examples/ROOT/sys b/examples/ROOT/sys
new file mode 120000
index 0000000..6dc454d
--- /dev/null
+++ b/examples/ROOT/sys
@@ -0,0 +1 @@
+mnt/sysfs
\ No newline at end of file
diff --git a/examples/ROOT/tmp b/examples/ROOT/tmp
new file mode 120000
index 0000000..d3b5871
--- /dev/null
+++ b/examples/ROOT/tmp
@@ -0,0 +1 @@
+mnt/tmpfs/tmp
\ No newline at end of file
diff --git a/examples/s6-svscanboot b/examples/s6-svscanboot
new file mode 100755
index 0000000..6a25ced
--- /dev/null
+++ b/examples/s6-svscanboot
@@ -0,0 +1,8 @@
+#!/command/execlineb -P
+
+/command/exec -c
+/command/redirfd -wnb 1 /service/s6-svscan-log/fifo
+/command/fdmove -c 2 1
+/command/s6-envdir -I /service/.s6-svscan/env
+/command/exec -a s6-svscan
+/command/s6-svscan -t0 /service