aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore34
-rw-r--r--LICENSE13
-rw-r--r--Makefile.am42
-rw-r--r--README.md9
-rwxr-xr-xautogen.sh3
-rw-r--r--configure.ac44
-rw-r--r--docs/defconfig.md124
-rw-r--r--docs/network.md83
-rw-r--r--etc/initd.env1
-rw-r--r--m4/ac_define_dir.m435
-rw-r--r--netcfg/ifrename13
-rw-r--r--scripts/Makemodule.am6
-rw-r--r--scripts/devfs.sh.in21
-rwxr-xr-xscripts/ifcfg.sh.in71
-rw-r--r--scripts/ifdown.sh8
-rwxr-xr-xscripts/ifrename.sh.in47
-rw-r--r--scripts/modules_load.sh.in21
-rwxr-xr-xscripts/overlay.sh21
-rwxr-xr-xscripts/setntpdate.sh49
-rw-r--r--scripts/trymount.sh7
-rw-r--r--services/Makemodule.am23
-rw-r--r--services/agetty6
-rw-r--r--services/consolefont6
-rw-r--r--services/devfs.in6
-rw-r--r--services/dhcpcd7
-rw-r--r--services/dhcpcdmaster10
-rw-r--r--services/dnsmasq6
-rw-r--r--services/gcrond5
-rw-r--r--services/hostapd.in7
-rw-r--r--services/hostname6
-rw-r--r--services/hwclock6
-rw-r--r--services/ifcfg.in7
-rw-r--r--services/ifdown.in7
-rw-r--r--services/ifrename.in7
-rw-r--r--services/klogd6
-rw-r--r--services/loopback10
-rw-r--r--services/modules.in7
-rw-r--r--services/mountusr.in5
-rw-r--r--services/network4
-rw-r--r--services/nft.in7
-rw-r--r--services/nginx6
-rw-r--r--services/ntpsetdate.gcron.in7
-rw-r--r--services/procfs.in9
-rw-r--r--services/sigkill.in6
-rw-r--r--services/sigterm.in9
-rw-r--r--services/sshd.in5
-rw-r--r--services/sshd_keygen.in14
-rw-r--r--services/swclock.in6
-rw-r--r--services/swclocksave.gcron.in3
-rw-r--r--services/swclocksave.in7
-rw-r--r--services/sync6
-rwxr-xr-xservices/sysctl7
-rw-r--r--services/sysfs.in13
-rw-r--r--services/sysinit5
-rw-r--r--services/tmpfs5
-rw-r--r--services/tmpfsrun11
-rw-r--r--services/tmpfsvar.in16
-rw-r--r--services/unbound6
-rw-r--r--services/usyslogd6
-rw-r--r--services/vfs4
60 files changed, 951 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..20c4545
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,34 @@
+Makefile
+Makefile.in
+aclocal.m4
+autom4te.cache
+config.log
+config.status
+configure
+install-sh
+missing
+reboot
+scripts/devfs.sh
+scripts/ifcfg.sh
+scripts/ifrename.sh
+scripts/modules_load.sh
+services/devfs
+services/hostapd
+services/ifcfg
+services/ifdown
+services/ifrename
+services/modules
+services/nft
+services/procfs
+services/sigkill
+services/sigterm
+services/sshd
+services/sshd_keygen
+services/swclock
+services/swclocksave
+services/swclocksave.gcron
+services/sysfs
+services/mountusr
+services/ntpsetdate.gcron
+services/tmpfsvar
+.#* \ No newline at end of file
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..77dfedb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,13 @@
+Copyright (c) 2018 David Oberhollenzer <david.oberhollenzer@tele2.at>
+
+Permission to use, copy, modify, and distribute this software for any
+purpose with or without fee is hereby granted, provided that the above
+copyright notice and this permission notice appear in all copies.
+
+THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
diff --git a/Makefile.am b/Makefile.am
new file mode 100644
index 0000000..0cc0cd6
--- /dev/null
+++ b/Makefile.am
@@ -0,0 +1,42 @@
+ACLOCAL_AMFLAGS = -I m4
+
+sysconf_DATA = etc/initd.env
+nobase_sysconf_DATA = netcfg/ifrename
+EXTRA_DIST = docs netcfg etc LICENSE README.md
+
+helperdir = @SCRIPTDIR@
+helper_PROGRAMS =
+helper_SCRIPTS =
+
+include scripts/Makemodule.am
+include services/Makemodule.am
+
+install-data-local:
+ $(MKDIR_P) $(DESTDIR)$(SVCDIR)
+ $(LN_S) $(TEMPLATEDIR)/loopback $(DESTDIR)$(SVCDIR)/loopback
+ $(LN_S) $(TEMPLATEDIR)/hostname $(DESTDIR)$(SVCDIR)/hostname
+ $(LN_S) $(TEMPLATEDIR)/sysctl $(DESTDIR)$(SVCDIR)/sysctl
+ $(LN_S) $(TEMPLATEDIR)/sysinit $(DESTDIR)$(SVCDIR)/sysinit
+ $(LN_S) $(TEMPLATEDIR)/procfs $(DESTDIR)$(SVCDIR)/procfs
+ $(LN_S) $(TEMPLATEDIR)/sysfs $(DESTDIR)$(SVCDIR)/sysfs
+ $(LN_S) $(TEMPLATEDIR)/devfs $(DESTDIR)$(SVCDIR)/devfs
+ $(LN_S) $(TEMPLATEDIR)/tmpfs $(DESTDIR)$(SVCDIR)/tmpfs
+ $(LN_S) $(TEMPLATEDIR)/vfs $(DESTDIR)$(SVCDIR)/vfs
+ $(LN_S) $(TEMPLATEDIR)/ifdown $(DESTDIR)$(SVCDIR)/ifdown@shutdown
+ $(LN_S) $(TEMPLATEDIR)/sync $(DESTDIR)$(SVCDIR)/sync@shutdown
+ $(LN_S) $(TEMPLATEDIR)/sigkill $(DESTDIR)$(SVCDIR)/sigkill@shutdown
+ $(LN_S) $(TEMPLATEDIR)/sigterm $(DESTDIR)$(SVCDIR)/sigterm@shutdown
+ $(LN_S) $(TEMPLATEDIR)/sync $(DESTDIR)$(SVCDIR)/sync@reboot
+ $(LN_S) $(TEMPLATEDIR)/sigkill $(DESTDIR)$(SVCDIR)/sigkill@reboot
+ $(LN_S) $(TEMPLATEDIR)/sigterm $(DESTDIR)$(SVCDIR)/sigterm@reboot
+ $(LN_S) $(TEMPLATEDIR)/ifdown $(DESTDIR)$(SVCDIR)/ifdown@reboot
+ $(LN_S) $(TEMPLATEDIR)/ifcfg $(DESTDIR)$(SVCDIR)/ifcfg
+ $(LN_S) $(TEMPLATEDIR)/modules $(DESTDIR)$(SVCDIR)/modules
+ $(LN_S) $(TEMPLATEDIR)/network $(DESTDIR)$(SVCDIR)/network
+ $(LN_S) $(TEMPLATEDIR)/usyslogd $(DESTDIR)$(SVCDIR)/usyslogd
+ $(LN_S) $(TEMPLATEDIR)/klogd $(DESTDIR)$(SVCDIR)/klogd
+ $(LN_S) $(TEMPLATEDIR)/mountusr $(DESTDIR)$(SVCDIR)/mountusr
+ $(LN_S) $(TEMPLATEDIR)/tmpfsrun $(DESTDIR)$(SVCDIR)/tmpfsrun
+ $(LN_S) $(TEMPLATEDIR)/tmpfsvar $(DESTDIR)$(SVCDIR)/tmpfsvar
+ $(MKDIR_P) $(DESTDIR)$(GCRONDIR)
+ $(LN_S) $(TEMPLATEDIR)/gcrond $(DESTDIR)$(SVCDIR)/gcrond
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..5387127
--- /dev/null
+++ b/README.md
@@ -0,0 +1,9 @@
+# About
+
+This directory contains the basic system configuration for the Pygos system.
+
+See [docs/defconfig.md](docs/defconfig.md) for an overview of the default init
+service configuration and further, available services.
+
+See [docs/network.md](docs/network.md) for a description on how to do static
+network configuration with the provided script and service.
diff --git a/autogen.sh b/autogen.sh
new file mode 100755
index 0000000..c08fadf
--- /dev/null
+++ b/autogen.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+
+autoreconf --force --install --symlink
diff --git a/configure.ac b/configure.ac
new file mode 100644
index 0000000..a91fbaf
--- /dev/null
+++ b/configure.ac
@@ -0,0 +1,44 @@
+AC_PREREQ([2.60])
+
+AC_INIT([init-scripts], [1], [david.oberhollenzer@tele2.at], init-scripts)
+AC_CONFIG_MACRO_DIR([m4])
+AM_INIT_AUTOMAKE([foreign subdir-objects dist-xz])
+AM_SILENT_RULES([yes])
+AC_PROG_INSTALL
+AC_PROG_MKDIR_P
+AC_PROG_LN_S
+
+AC_DEFINE_DIR(SVCDIR, sysconfdir/init.d, [Startup service directory])
+AC_DEFINE_DIR(GCRONDIR, sysconfdir/gcron.d, [Cron service directory])
+AC_DEFINE_DIR(TEMPLATEDIR, datadir/init, [Service template directory])
+AC_DEFINE_DIR(SCRIPTDIR, libexecdir/init, [Helper script directory])
+
+AC_DEFINE_DIR(SBINPATH, sbindir, [Fully evaluated sbin directory])
+AC_DEFINE_DIR(ETCPATH, sysconfdir, [Fulle evaluated etc directory])
+AC_DEFINE_DIR(STATEFILESPATH, prefix/var/lib, [Path for persistent state files])
+
+AC_CONFIG_FILES([services/sigkill])
+AC_CONFIG_FILES([services/sigterm])
+AC_CONFIG_FILES([services/sysfs])
+AC_CONFIG_FILES([services/devfs])
+AC_CONFIG_FILES([services/procfs])
+AC_CONFIG_FILES([services/ifrename])
+AC_CONFIG_FILES([services/ifcfg])
+AC_CONFIG_FILES([services/ifdown])
+AC_CONFIG_FILES([services/modules])
+AC_CONFIG_FILES([services/hostapd])
+AC_CONFIG_FILES([services/swclock])
+AC_CONFIG_FILES([services/swclocksave])
+AC_CONFIG_FILES([services/swclocksave.gcron])
+AC_CONFIG_FILES([services/nft])
+AC_CONFIG_FILES([services/sshd])
+AC_CONFIG_FILES([services/sshd_keygen])
+AC_CONFIG_FILES([services/mountusr])
+AC_CONFIG_FILES([services/ntpsetdate.gcron])
+AC_CONFIG_FILES([services/tmpfsvar])
+AC_CONFIG_FILES([scripts/devfs.sh])
+AC_CONFIG_FILES([scripts/ifrename.sh])
+AC_CONFIG_FILES([scripts/ifcfg.sh])
+AC_CONFIG_FILES([scripts/modules_load.sh])
+
+AC_OUTPUT([Makefile])
diff --git a/docs/defconfig.md b/docs/defconfig.md
new file mode 100644
index 0000000..f0a6c86
--- /dev/null
+++ b/docs/defconfig.md
@@ -0,0 +1,124 @@
+# Default Service Configuration
+
+## Pseudo Services
+
+The default configuration contains a number of "pseudo services" in the boot
+target that don't actually do anything but are merely used as anchors in
+service dependencies, i.e. they indicate that some sort of milestone in the
+boot sequence has been reached. Everything that is part of that milestone
+specifies that it should be run *before* that pseudo service and everything
+that requires that this milestone has been reached, specifies that it wants
+to run afterwards.
+
+The pseudo targets are (in the order that they are executed):
+
+ * vfs
+
+ All services that do mount point setup go before this, all service that
+ depend on the fully mounted rootfs go after this.
+
+ * sysinit
+
+ The system has reached a sane state, i.e. the hostname is set, the system
+ clock has a sane value, modules and kernel parameters are loaded, some
+ very basic, fundamental services are running.
+ Everything that is part of that setup process goes between `vfs` and
+ `sysinit`, everything that requires a sane setup goes *after* `sysinit`.
+
+ * network
+
+ Network configuration is done. All services that do network configuration
+ should position themselves between `sysinit` and `network`. Everything that
+ requires a fully configured networking setup should go *after* `network`.
+
+## Default Bootup Services
+
+This section outlines the services for the boot target that are enabled by
+default.
+
+
+The following services are enabled by default and run *before* the `vfs` target
+for filesystem setup:
+
+ * procfs - mount `procfs` to `/proc` and try to mount additional pseudo
+ filesystems in `/proc` such as `binfmt_misc`
+ * tmpfs - mount a `tmpfs` to `/tmp`
+ * sysfs - mount `sysfs` to `/sys` and try to mount additional pseudo
+ filesystems in `/sys` (e.g. `securityfs`, `configfs`, ...)
+ * devfs - mount `devtmpfs` to `/dev`, try to mount additional pseudo
+ filesystems in `/dev` (e.g. `devpts`, `mqueue`, ...) and try to create
+ some additional device nodes and symlinks.
+ * tmpfsvar - mount a `tmpfs` to `/var` and populate it with a default set
+ of files and directories. Overlay mount `/var/lib` with lower dir on
+ `/cfg/preserve/var_lib/` and upper on `/cfg/overlay/var_lib/`.
+ * tmpfsrun - mount a `tmpfs` to `/run`, symlink `/var/run` to `/run` and
+ `/var/lock` to `/run/lock`.
+ * mountusr - overlay mount setup for `/usr`. Lower dir is on
+ `/cfg/preserve/usr/` and upper on `/cfg/overlay/usr/`.
+
+
+The following services are enabled by default and configured to run *after*
+the `vfs` target and *before* the `sysinit` target:
+
+ * hostname - reload hostname `/etc/hostname`
+ * loopback - bring the loopback device up
+ * modules - iterate over the file `/etc/modules` and try to load each module
+ using modprobe.
+ * sysctl - restore kernel parameters using `sysctl --system`. See `sysctl(8)`
+ for a list of possible locations that the parameters are read from.
+ * usyslogd - Starts and supervises the `usyslogd` syslog implementation.
+ * klogd - Starts and supervises the `klogd` daemon.
+
+
+The following services are enabled by default and configured to run *after*
+the `sysinit` target and *before* the `network` target:
+
+ * ifcfg - static network configuration
+ Does the static network configuration outlined in [network.md](network.md)
+
+
+The following services are enabled by default and configured to run *after*
+the `network` target:
+
+ * gcrond
+
+
+## Default Shutdown and Reboot Services
+
+For the shutdown and reboot targets, the following services are executed:
+
+ * sigterm - send the SIGTERM signal to all processes and wait for 5 seconds
+ * sigkill - send the SIGKILL signal to all remaining processes
+ * ifdown - bring all network interfaces down
+ * sync - run the sync command
+
+
+## Additional Services not Enabled by Default
+
+ * agetty - A parameterizeable, respawn type `agetty` service. The first
+ parameter is the terminal device that the getty should run on.
+ * consolefont - If enabled, run once before sysinit. Sets the console font
+ to the first parameter.
+ * dhcpcdmaster - If one or more network interfaces should be configured using
+ dhcpcd, this service starts a central `dhcpcd` master instance.
+ * dhcpcd - A parameterizeable single shot service that signals the `dhcpcd`
+ master that it should configure a specific interface. The first parameter
+ is the interface that should be configured by `dhcpcd`.
+ * dnsmasq - A respawn type service for the `dnsmasq` DNS and DHCP server.
+ * hostapd - If the system should operate a WIFI access point, this respawn
+ type service can be enabled to manage an instace of the `hostapd` program.
+ * unbound - A respawn type service that manages an instance of the `unbound`
+ name resolver.
+ * hwclock - If the system has a hardware clock, this service can restore the
+ kernels clock from the hardware at bootup, between the `vfs` and `sysinit`
+ targets.
+ * nft - If enabled, restores net filter table rules during boot.
+ * swclock - For systems that don't have a hardware clock, this service
+ restores a somewhat usable time from a file during boot.
+ * swclocksave - For systems that don't have a hardware clock, this service
+ saves the current time to a file during shutdown or reboot.
+ * sshd_keygen - A wait type service that generates host keys for the OpenSSH
+ server and then disables itself.
+ * sshd - Starts an OpenSSH server after the network pseudo service and after
+ the sshd_keygen service.
+ * nginx - Starts the Nginx server after the network pseudo serivce.
diff --git a/docs/network.md b/docs/network.md
new file mode 100644
index 0000000..f111a8f
--- /dev/null
+++ b/docs/network.md
@@ -0,0 +1,83 @@
+# Static Network Configuration
+
+The default configuration provides multiple services that perform network
+initialization and static configuration using helper scripts that require
+programs from the `iproute2` package.
+
+Configuration files are typically stored in `/etc/netcfg/` (depending on
+configure options).
+
+Please note that the loopback device is treated specially and not included in
+any of the network configuration outlined below. The loopback device is brought
+up and configured by a dedicated service long before the network configuration
+is done.
+
+
+## Interface Renaming
+
+If the `ifrename` service is enabled (it is disabled by default), network
+interfaces are renamed based on a rule set stored in the file `ifrename`.
+The file contains comma separated shell globing patterns for the current
+interface name, MAC address and a prefix for the new interface name.
+
+For each network interface, rules are processed top to bottom. If the first two
+globing patterns apply, the interface is renamed. Interfaces with the same
+prefix are sorted by mac address and a running index is appended to the prefix.
+
+If none of the rules apply, the interface name is left unchanged.
+
+
+The intent is, to provide a way to configure persistent, deterministic names for
+at least all network interfaces that are permanently installed on a board.
+
+Extension cards or external network adapters should be given a different prefix
+to avoid changes in the order as they come and go.
+
+
+## Interface Configuration
+
+After interface renaming, for each network interface, the configuration path is
+scanned for files with the same name as the interface.
+
+Each successfully found configuration file is processed line by line, top to
+bottom. Each line may contain a keyword, followed by multiple arguments.
+
+The following keywords can be used to add IPv4 or IPv6 network addresses to
+an interface:
+
+ * address
+ * addr
+ * ip
+ * ip6
+ * ipv6
+
+Those commands are expected to be followed by an IPv4 or IPv6 address and
+network mask.
+
+
+Furthermore, the following commands can be used for configuring interface
+parameters:
+
+ * `arp {on|off}`
+ * `multicast {on|off}`
+ * `mtu <value>`
+ * `offload [rx {on|off}] [tx {on|off}] [sg {on|off}] [tso {on|off}]`
+ * `offload [gso {on|off}] [gro {on|off}] [lro {on|off}] [rxvlan {on|off}]`
+ * `offload [txvlan {on|off}] [ntuple {on|off}] [rxhash {on|off}]`
+ * `offload [ufo {on|off}]`
+
+
+## Route Configuration
+
+After interface configuration is done, routes and rules are restored from a
+file named `routes` in the same configuration path.
+
+The file may contain lines starting with `route` or `rule`. Everything that
+follows is passed on to `ip route add` or `ip rule add` respectively.
+
+
+## Net Filter Tables
+
+
+An additional service is provided that restores the nft rule set from
+`/etc/nftables.rules`.
diff --git a/etc/initd.env b/etc/initd.env
new file mode 100644
index 0000000..c31cb70
--- /dev/null
+++ b/etc/initd.env
@@ -0,0 +1 @@
+PATH=/bin \ No newline at end of file
diff --git a/m4/ac_define_dir.m4 b/m4/ac_define_dir.m4
new file mode 100644
index 0000000..3b48c8b
--- /dev/null
+++ b/m4/ac_define_dir.m4
@@ -0,0 +1,35 @@
+dnl @synopsis AC_DEFINE_DIR(VARNAME, DIR [, DESCRIPTION])
+dnl
+dnl This macro sets VARNAME to the expansion of the DIR variable,
+dnl taking care of fixing up ${prefix} and such.
+dnl
+dnl VARNAME is then offered as both an output variable and a C
+dnl preprocessor symbol.
+dnl
+dnl Example:
+dnl
+dnl AC_DEFINE_DIR([DATADIR], [datadir], [Where data are placed to.])
+dnl
+dnl @category Misc
+dnl @author Stepan Kasal <kasal@ucw.cz>
+dnl @author Andreas Schwab <schwab@suse.de>
+dnl @author Guido U. Draheim <guidod@gmx.de>
+dnl @author Alexandre Oliva
+dnl @version 2006-10-13
+dnl @license AllPermissive
+
+AC_DEFUN([AC_DEFINE_DIR], [
+ prefix_NONE=
+ exec_prefix_NONE=
+ test "x$prefix" = xNONE && prefix_NONE=yes && prefix=$ac_default_prefix
+ test "x$exec_prefix" = xNONE && exec_prefix_NONE=yes && exec_prefix=$prefix
+dnl In Autoconf 2.60, ${datadir} refers to ${datarootdir}, which in turn
+dnl refers to ${prefix}. Thus we have to use `eval' twice.
+ eval ac_define_dir="\"[$]$2\""
+ eval ac_define_dir="\"$ac_define_dir\""
+ AC_SUBST($1, "$ac_define_dir")
+ AC_DEFINE_UNQUOTED($1, "$ac_define_dir", [$3])
+ test "$prefix_NONE" && prefix=NONE
+ test "$exec_prefix_NONE" && exec_prefix=NONE
+])
+
diff --git a/netcfg/ifrename b/netcfg/ifrename
new file mode 100644
index 0000000..08909fa
--- /dev/null
+++ b/netcfg/ifrename
@@ -0,0 +1,13 @@
+#
+# Interface renaming rules
+#
+# Format: NAME,MAC,NEWNAME
+#
+# NAME and MAC are shell glob patterns. Both must match for a rule to apply.
+# The first matching rule is chosen (top to bottom).
+#
+# Interfaces with the same NEWNAME are sorted by MAC and have a running
+# index appended to their new name.
+#
+# Example: rename all ethernet interfaces to "port<X>"
+# eth*,*,port
diff --git a/scripts/Makemodule.am b/scripts/Makemodule.am
new file mode 100644
index 0000000..207b9d2
--- /dev/null
+++ b/scripts/Makemodule.am
@@ -0,0 +1,6 @@
+helper_SCRIPTS += scripts/devfs.sh scripts/trymount.sh scripts/ifrename.sh
+helper_SCRIPTS += scripts/ifcfg.sh scripts/ifdown.sh scripts/modules_load.sh
+helper_SCRIPTS += scripts/setntpdate.sh scripts/overlay.sh
+
+EXTRA_DIST += scripts/trymount.sh scripts/ifdown.sh scripts/setntpdate.sh
+EXTRA_DIST += scripts/overlay.sh
diff --git a/scripts/devfs.sh.in b/scripts/devfs.sh.in
new file mode 100644
index 0000000..af002f6
--- /dev/null
+++ b/scripts/devfs.sh.in
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+mount -t devtmpfs none /dev
+
+[ -c /dev/console ] || mknod -m 600 /dev/console c 5 1
+[ -c /dev/tty ] || mknod -m 666 /dev/tty c 5 0
+[ -c /dev/null ] || mknod -m 666 /dev/null c 1 3
+[ -c /dev/kmsg ] || mknod -m 660 /dev/kmsg c 1 11
+[ -e /dev/fd ] || ln -snf /proc/self/fd /dev/fd
+[ -e /dev/stdin ] || ln -snf /proc/self/fd/0 /dev/stdin
+[ -e /dev/stdout ] || ln -snf /proc/self/fd/1 /dev/stdout
+[ -e /dev/stderr ] || ln -snf /proc/self/fd/2 /dev/stderr
+[ -e /proc/kcore ] && ln -snf /proc/kcore /dev/core
+
+mkdir -p /dev/mqueue -m 1777
+mkdir -p /dev/pts -m 0755
+mkdir -p /dev/shm -m 1777
+
+@SCRIPTDIR@/trymount.sh "/dev/mqueue" "mqueue" "noexec,nosuid,nodev"
+@SCRIPTDIR@/trymount.sh "/dev/pts" "devpts" "noexec,nosuid,gid=5,mode=0620"
+@SCRIPTDIR@/trymount.sh "/dev/shm" "tmpfs" "noexec,nosuid,nodev,mode=1777"
diff --git a/scripts/ifcfg.sh.in b/scripts/ifcfg.sh.in
new file mode 100755
index 0000000..f8396c6
--- /dev/null
+++ b/scripts/ifcfg.sh.in
@@ -0,0 +1,71 @@
+#!/bin/sh
+CFGPATH="@ETCPATH@/netcfg"
+
+[ -d "$CFGPATH" ] || exit 0
+
+# configure interfaces
+for IFPATH in /sys/class/net/*; do
+ [ "$IFPATH" == "/sys/class/net/lo" ] && continue
+
+ IF=`basename $IFPATH`
+ CFGFILE="$CFGPATH/$IF"
+
+ [ -f "$CFGFILE" ] || continue
+
+ ip link set dev "$IF" down
+
+ while read LINE;
+ do
+ trimmed=`echo -- $LINE`
+ [ ! -z "$trimmed" ] || continue
+ set $trimmed
+
+ case "$1" in
+ address|addr|ip|ip6|ipv6)
+ shift
+ ip address add $@ dev "$IF"
+ ;;
+ arp|multicast|mtu)
+ ip link set dev "$IF" $@
+ ;;
+ offload)
+ shift
+ ethtool -K "$IF" $@
+ ;;
+ *)
+ ;;
+ esac
+ done < "$CFGFILE"
+done
+
+# configure static routs
+if [ -f "$CFGPATH/routes" ]; then
+ while read LINE;
+ do
+ trimmed=`echo -- $LINE`
+ [ ! -z "$trimmed" ] || continue
+ set $trimmed
+
+ case "$1" in
+ route)
+ shift
+ ip route add $@
+ ;;
+ rule)
+ shift
+ ip rule add $@
+ ;;
+ *)
+ ;;
+ esac
+ done < "$CFGFILE"
+fi
+
+# activate interfaces
+for IFPATH in /sys/class/net/*; do
+ [ "$IFPATH" == "/sys/class/net/lo" ] && continue
+
+ IF=`basename $IFPATH`
+
+ [ ! -f "$CFGPATH/$IF" ] || ip link set dev "$IF" up
+done
diff --git a/scripts/ifdown.sh b/scripts/ifdown.sh
new file mode 100644
index 0000000..e6f4500
--- /dev/null
+++ b/scripts/ifdown.sh
@@ -0,0 +1,8 @@
+#!/bin/sh
+for IFPATH in /sys/class/net/*; do
+ [ "$IFPATH" == "/sys/class/net/lo" ] && continue
+
+ IF=`basename $IFPATH`
+
+ ip link set dev "$IF" down
+done
diff --git a/scripts/ifrename.sh.in b/scripts/ifrename.sh.in
new file mode 100755
index 0000000..0820c94
--- /dev/null
+++ b/scripts/ifrename.sh.in
@@ -0,0 +1,47 @@
+#!/bin/sh
+NAMERULES="@ETCPATH@/netcfg/ifrename"
+TMPPATH="/tmp/ifrename"
+
+[ -f "$NAMERULES" ] || exit 0
+
+mkdir -p "$TMPPATH"
+
+for IFPATH in /sys/class/net/*; do
+ [ "$IFPATH" == "/sys/class/net/lo" ] && continue
+
+ IF=`basename $IFPATH`
+ MAC=`cat $IFPATH/address`
+
+ grep "^[^,]\+,[^,]\+,[a-zA-Z0-9]\+$" $NAMERULES | while read LINE;
+ do
+ NAMECMP=$(echo $LINE | cut -d',' -f1)
+ ADDRCMP=$(echo $LINE | cut -d',' -f2)
+ RULE=$(echo $LINE | cut -d',' -f3)
+
+ case $IF in ($NAMECMP) ;; *) continue;; esac
+ case $MAC in ($ADDRCMP) ;; *) continue;; esac
+
+ echo "$MAC,$IF" >> "$TMPPATH/$RULE"
+ break
+ done
+done
+
+for FNAME in $TMPPATH/*; do
+ [ ! -f "$FNAME" ] && break
+
+ IDX=0
+ PREFIX=$(basename $FNAME)
+
+ sort -t',' -k1 -u $FNAME | while read LINE;
+ do
+ OLDNAME=$(echo $LINE | cut -d',' -f2)
+ NEWNAME="$PREFIX$IDX"
+ IDX=`expr $IDX + 1`
+
+ ip link set "$OLDNAME" name "$NEWNAME"
+ done
+
+ rm "$FNAME"
+done
+
+rmdir "$TMPPATH"
diff --git a/scripts/modules_load.sh.in b/scripts/modules_load.sh.in
new file mode 100644
index 0000000..58bb2ab
--- /dev/null
+++ b/scripts/modules_load.sh.in
@@ -0,0 +1,21 @@
+#!/bin/sh
+MODLIST="@ETCPATH@/modules"
+
+if [ ! -f "$MODLIST" ]; then
+ exit 0
+fi
+
+while read LINE;
+do
+ trimmed=`echo -- $LINE`
+ [ ! -z "$trimmed" ] || continue
+ set $trimmed
+
+ case "$1" in
+ \#*)
+ ;;
+ *)
+ modprobe "$1"
+ ;;
+ esac
+done < "$MODLIST"
diff --git a/scripts/overlay.sh b/scripts/overlay.sh
new file mode 100755
index 0000000..090671c
--- /dev/null
+++ b/scripts/overlay.sh
@@ -0,0 +1,21 @@
+#!/bin/sh
+
+lower=/cfg/preserve/${1}
+upper=/cfg/overlay/${1}
+work=/cfg/overlay/${1}_work
+target=${2}
+
+if [ ! -d "$target" ]; then
+ exit
+fi
+
+if [ -d "$lower" ]; then
+ if [ -d "$upper" ]; then
+ mkdir -p "$work"
+ mount -t overlay overlay \
+ -olowerdir=${lower},upperdir=${upper},workdir=${work} \
+ ${target}
+ else
+ mount --bind "$lower" "$target"
+ fi
+fi
diff --git a/scripts/setntpdate.sh b/scripts/setntpdate.sh
new file mode 100755
index 0000000..bf0a753
--- /dev/null
+++ b/scripts/setntpdate.sh
@@ -0,0 +1,49 @@
+#!/bin/sh
+
+resolve() {
+ local domain="$1"
+ local server="$2"
+
+ if [ -x "$(command -v dig)" ]; then
+ if [ -z "$server" ]; then
+ dig +short "$domain"
+ else
+ dig +short "@$server" "$domain"
+ fi
+ return $?
+ fi
+
+ if [ -x "$(command -v drill)" ]; then
+ if [ -z "$server" ]; then
+ drill "$domain" | grep "^${domain}." | cut -d$'\t' -f5
+ else
+ drill "@$server" "$domain" | grep "^${domain}." |\
+ cut -d$'\t' -f5
+ fi
+ return $?
+ fi
+ exit 1
+}
+
+try_update() {
+ while read ip; do
+ if ntpdate -bu "$ip"; then
+ return 0
+ fi
+ done
+
+ return 1
+}
+
+pool="pool.ntp.org"
+dns="1.1.1.1"
+
+# try default DNS server first
+resolve "$pool" "" | try_update
+[ $? -eq 0 ] && exit 0
+
+# try fallback public dns server
+ping -q -c 1 "$dns" || exit 1
+
+resolve "$pool" "$dns" | try_update
+exit $?
diff --git a/scripts/trymount.sh b/scripts/trymount.sh
new file mode 100644
index 0000000..9be77f6
--- /dev/null
+++ b/scripts/trymount.sh
@@ -0,0 +1,7 @@
+#!/bin/sh
+
+if [ -d "$1" ]; then
+ if grep -qsE "[[:space:]]+$2$" "/proc/filesystems"; then
+ mount -n -t "$2" -o "$3" "$2" "$1"
+ fi
+fi
diff --git a/services/Makemodule.am b/services/Makemodule.am
new file mode 100644
index 0000000..e39e200
--- /dev/null
+++ b/services/Makemodule.am
@@ -0,0 +1,23 @@
+initdir = @TEMPLATEDIR@
+init_DATA = services/agetty services/hostname services/loopback
+init_DATA += services/sysctl services/hwclock services/sysinit
+init_DATA += services/sigterm services/sync services/devfs
+init_DATA += services/sysfs services/procfs services/tmpfs
+init_DATA += services/vfs services/ifrename services/ifcfg
+init_DATA += services/dhcpcd services/dhcpcdmaster services/unbound
+init_DATA += services/dnsmasq services/ifdown services/modules
+init_DATA += services/network services/hostapd services/swclock
+init_DATA += services/swclocksave services/nft services/sigkill
+init_DATA += services/sshd services/sshd_keygen services/consolefont
+init_DATA += services/nginx services/usyslogd services/klogd
+init_DATA += services/swclocksave.gcron services/gcrond
+init_DATA += services/mountusr services/ntpsetdate.gcron
+init_DATA += services/tmpfsrun services/tmpfsvar
+
+EXTRA_DIST += services/sysinit services/vfs services/agetty services/hostname
+EXTRA_DIST += services/hwclock services/loopback services/klogd
+EXTRA_DIST += services/sync services/sysctl services/tmpfs
+EXTRA_DIST += services/dhcpcd services/dhcpcdmaster services/unbound
+EXTRA_DIST += services/usyslogd services/dnsmasq services/network
+EXTRA_DIST += services/consolefont services/gcrond services/nginx
+EXTRA_DIST += services/tmpfsrun
diff --git a/services/agetty b/services/agetty
new file mode 100644
index 0000000..6c8945b
--- /dev/null
+++ b/services/agetty
@@ -0,0 +1,6 @@
+description agetty on %0
+exec agetty %0 linux
+type respawn
+target boot
+after network
+tty "/dev/%0"
diff --git a/services/consolefont b/services/consolefont
new file mode 100644
index 0000000..1584db9
--- /dev/null
+++ b/services/consolefont
@@ -0,0 +1,6 @@
+description set console font
+type once
+target boot
+before sysinit
+after vfs
+exec setfont %0
diff --git a/services/devfs.in b/services/devfs.in
new file mode 100644
index 0000000..271eae7
--- /dev/null
+++ b/services/devfs.in
@@ -0,0 +1,6 @@
+description "mount /dev"
+type wait
+target boot
+after procfs sysfs
+before vfs
+exec "@SCRIPTDIR@/devfs.sh"
diff --git a/services/dhcpcd b/services/dhcpcd
new file mode 100644
index 0000000..184a843
--- /dev/null
+++ b/services/dhcpcd
@@ -0,0 +1,7 @@
+description "DHCP client on %0"
+type once
+target boot
+after dhcpcdmaster network
+
+tty /dev/null
+exec dhcpcd -n %0
diff --git a/services/dhcpcdmaster b/services/dhcpcdmaster
new file mode 100644
index 0000000..879497a
--- /dev/null
+++ b/services/dhcpcdmaster
@@ -0,0 +1,10 @@
+description "DHCP client - master service"
+type wait
+target boot
+after network
+tty /dev/null
+
+exec {
+ mkdir -p /var/db/dhcpcd
+ dhcpcd --inactive
+}
diff --git a/services/dnsmasq b/services/dnsmasq
new file mode 100644
index 0000000..4045824
--- /dev/null
+++ b/services/dnsmasq
@@ -0,0 +1,6 @@
+description "dnsmasq DNS & DHCP server"
+type respawn limit 5
+target boot
+after network unbound
+
+exec dnsmasq -k
diff --git a/services/gcrond b/services/gcrond
new file mode 100644
index 0000000..0ee1ee5
--- /dev/null
+++ b/services/gcrond
@@ -0,0 +1,5 @@
+description start gcron daemon
+exec gcrond
+type respawn
+target boot
+after network
diff --git a/services/hostapd.in b/services/hostapd.in
new file mode 100644
index 0000000..172aa6f
--- /dev/null
+++ b/services/hostapd.in
@@ -0,0 +1,7 @@
+description "WIFI access point daemon"
+type respawn limit 10
+target boot
+after sysinit ifrename
+before network ifcfg
+
+exec hostapd "@ETCPATH@/hostapd.conf"
diff --git a/services/hostname b/services/hostname
new file mode 100644
index 0000000..d0daa23
--- /dev/null
+++ b/services/hostname
@@ -0,0 +1,6 @@
+description reload hostname
+exec hostname --file /etc/hostname
+type wait
+target boot
+before sysinit
+after hwclock vfs
diff --git a/services/hwclock b/services/hwclock
new file mode 100644
index 0000000..7eac1da
--- /dev/null
+++ b/services/hwclock
@@ -0,0 +1,6 @@
+description restore time from RTC
+exec hwclock --hctosys --utc
+type wait
+target boot
+before sysinit
+after vfs modules
diff --git a/services/ifcfg.in b/services/ifcfg.in
new file mode 100644
index 0000000..c2b4127
--- /dev/null
+++ b/services/ifcfg.in
@@ -0,0 +1,7 @@
+description "static network configuration"
+type wait
+target boot
+after sysinit ifrename
+before network
+
+exec "@SCRIPTDIR@/ifcfg.sh" \ No newline at end of file
diff --git a/services/ifdown.in b/services/ifdown.in
new file mode 100644
index 0000000..1310098
--- /dev/null
+++ b/services/ifdown.in
@@ -0,0 +1,7 @@
+description "stop all network interfaces"
+type wait
+target %0
+after sigkill sigterm
+before sync
+
+exec "@SCRIPTDIR@/ifdown.sh" \ No newline at end of file
diff --git a/services/ifrename.in b/services/ifrename.in
new file mode 100644
index 0000000..efb00de
--- /dev/null
+++ b/services/ifrename.in
@@ -0,0 +1,7 @@
+description "rename network interfaces"
+type wait
+target boot
+after sysinit
+before network
+
+exec "@SCRIPTDIR@/ifrename.sh" \ No newline at end of file
diff --git a/services/klogd b/services/klogd
new file mode 100644
index 0000000..aaca59a
--- /dev/null
+++ b/services/klogd
@@ -0,0 +1,6 @@
+description "starting uklogd"
+exec klogd
+type respawn limit 5
+target boot
+after usyslogd
+before sysinit
diff --git a/services/loopback b/services/loopback
new file mode 100644
index 0000000..53118b5
--- /dev/null
+++ b/services/loopback
@@ -0,0 +1,10 @@
+description configure network loopback device
+type wait
+target boot
+before sysinit
+after hostname vfs
+
+exec {
+ ip addr add 127.0.0.1/8 dev lo brd +
+ ip link set lo up
+}
diff --git a/services/modules.in b/services/modules.in
new file mode 100644
index 0000000..e8c1863
--- /dev/null
+++ b/services/modules.in
@@ -0,0 +1,7 @@
+description "load kernel modules"
+type wait
+target boot
+after vfs usyslogd
+before sysinit
+
+exec "@SCRIPTDIR@/modules_load.sh" \ No newline at end of file
diff --git a/services/mountusr.in b/services/mountusr.in
new file mode 100644
index 0000000..14b1e8f
--- /dev/null
+++ b/services/mountusr.in
@@ -0,0 +1,5 @@
+description "mount /usr"
+type wait
+target boot
+before vfs
+exec "@SCRIPTDIR@/overlay.sh" usr /usr
diff --git a/services/network b/services/network
new file mode 100644
index 0000000..5ba505c
--- /dev/null
+++ b/services/network
@@ -0,0 +1,4 @@
+description "static network configuration completed"
+type wait
+target boot
+after sysinit \ No newline at end of file
diff --git a/services/nft.in b/services/nft.in
new file mode 100644
index 0000000..21caab0
--- /dev/null
+++ b/services/nft.in
@@ -0,0 +1,7 @@
+description "restore netfilter rule set"
+type wait
+target boot
+after sysinit ifrename
+before network ifcfg
+
+exec nft -f "@ETCPATH@/nftables.rules"
diff --git a/services/nginx b/services/nginx
new file mode 100644
index 0000000..6a36af9
--- /dev/null
+++ b/services/nginx
@@ -0,0 +1,6 @@
+description "start nginx web server"
+type once
+target boot
+after network
+tty /dev/null
+exec nginx
diff --git a/services/ntpsetdate.gcron.in b/services/ntpsetdate.gcron.in
new file mode 100644
index 0000000..6f86bd5
--- /dev/null
+++ b/services/ntpsetdate.gcron.in
@@ -0,0 +1,7 @@
+hour */4
+minute 5
+dayofmonth *
+dayofweek *
+month *
+tty /dev/null
+exec "@SCRIPTDIR@/setntpdate.sh"
diff --git a/services/procfs.in b/services/procfs.in
new file mode 100644
index 0000000..8c0743b
--- /dev/null
+++ b/services/procfs.in
@@ -0,0 +1,9 @@
+description "mount /proc"
+type wait
+target boot
+before vfs
+
+exec {
+ mount -t proc proc /proc
+ "@SCRIPTDIR@/trymount.sh" /proc/sys/fs/binfmt_misc binfmt_misc nodev,noexec,nosuid
+}
diff --git a/services/sigkill.in b/services/sigkill.in
new file mode 100644
index 0000000..cddd49d
--- /dev/null
+++ b/services/sigkill.in
@@ -0,0 +1,6 @@
+description send SIGKILL to remaining processes
+exec "@SCRIPTDIR@/killall5" 9
+type wait
+target %0
+after sigterm
+before sync shutdown reboot
diff --git a/services/sigterm.in b/services/sigterm.in
new file mode 100644
index 0000000..7e77fba
--- /dev/null
+++ b/services/sigterm.in
@@ -0,0 +1,9 @@
+description send SIGTERM to all processes
+type wait
+target %0
+before sigkill sync reboot shutdown
+
+exec {
+ "@SCRIPTDIR@/killall5" 15
+ sleep 5
+}
diff --git a/services/sshd.in b/services/sshd.in
new file mode 100644
index 0000000..a6292bc
--- /dev/null
+++ b/services/sshd.in
@@ -0,0 +1,5 @@
+description "OpenSSH server"
+type respawn limit 5
+target boot
+after network sshd_keygen
+exec "@SBINPATH@/sshd" -D
diff --git a/services/sshd_keygen.in b/services/sshd_keygen.in
new file mode 100644
index 0000000..6425e63
--- /dev/null
+++ b/services/sshd_keygen.in
@@ -0,0 +1,14 @@
+description "OpenSSH server - generate host keys"
+type wait
+target boot
+after network
+tty /dev/null
+exec {
+ mkdir -p "@ETCPATH@/ssh/"
+
+ ssh-keygen -f "@ETCPATH@/ssh/host_rsa_key" -N "" -t rsa
+ ssh-keygen -f "@ETCPATH@/ssh/host_ecdsa_key" -N "" -t ecdsa
+ ssh-keygen -f "@ETCPATH@/ssh/host_ed25519_key" -N "" -t ed25519
+
+ service disable sshd_keygen
+}
diff --git a/services/swclock.in b/services/swclock.in
new file mode 100644
index 0000000..02c4c27
--- /dev/null
+++ b/services/swclock.in
@@ -0,0 +1,6 @@
+description restore saved time from last shutdown
+type wait
+target boot
+before sysinit
+after vfs modules
+exec xargs -a @STATEFILESPATH@/swclock date --utc
diff --git a/services/swclocksave.gcron.in b/services/swclocksave.gcron.in
new file mode 100644
index 0000000..24e162b
--- /dev/null
+++ b/services/swclocksave.gcron.in
@@ -0,0 +1,3 @@
+interval hourly
+tty truncate @STATEFILESPATH@/swclock
+exec date --utc +%%m%%d%%H%%M%%Y.%%S
diff --git a/services/swclocksave.in b/services/swclocksave.in
new file mode 100644
index 0000000..683ded7
--- /dev/null
+++ b/services/swclocksave.in
@@ -0,0 +1,7 @@
+description write current time to backup file
+type wait
+target %0
+after sigkill
+before sync
+tty truncate @STATEFILESPATH@/swclock
+exec date --utc +%%m%%d%%H%%M%%Y.%%S
diff --git a/services/sync b/services/sync
new file mode 100644
index 0000000..d7217f9
--- /dev/null
+++ b/services/sync
@@ -0,0 +1,6 @@
+description sync
+exec sync
+type wait
+target %0
+after sigkill sigterm
+before reboot shutdown
diff --git a/services/sysctl b/services/sysctl
new file mode 100755
index 0000000..6664297
--- /dev/null
+++ b/services/sysctl
@@ -0,0 +1,7 @@
+description configure kernel paramters
+tty /dev/null
+exec sysctl --system
+type wait
+target boot
+before sysinit
+after vfs loopback
diff --git a/services/sysfs.in b/services/sysfs.in
new file mode 100644
index 0000000..8eebd0a
--- /dev/null
+++ b/services/sysfs.in
@@ -0,0 +1,13 @@
+description "mount /sys"
+type wait
+target boot
+after procfs
+before vfs
+
+exec {
+ mount -t sysfs sysfs /sys
+ "@SCRIPTDIR@/trymount.sh" /sys/kernel/security securityfs nodev,noexec,nosuid
+ "@SCRIPTDIR@/trymount.sh" /sys/kernel/config configfs nodev,noexec,nosuid
+ "@SCRIPTDIR@/trymount.sh" /sys/fs/fuse/connections fusectl nodev,noexec,nosuid
+ "@SCRIPTDIR@/trymount.sh" /sys/firmware/efi/efivars efivarfs ro
+}
diff --git a/services/sysinit b/services/sysinit
new file mode 100644
index 0000000..801ac97
--- /dev/null
+++ b/services/sysinit
@@ -0,0 +1,5 @@
+description basic system initialization
+type wait
+target boot
+after vfs
+before network \ No newline at end of file
diff --git a/services/tmpfs b/services/tmpfs
new file mode 100644
index 0000000..411a42b
--- /dev/null
+++ b/services/tmpfs
@@ -0,0 +1,5 @@
+description "mount /tmp"
+type wait
+target boot
+before vfs
+exec mount -t tmpfs none /tmp
diff --git a/services/tmpfsrun b/services/tmpfsrun
new file mode 100644
index 0000000..07dbd0a
--- /dev/null
+++ b/services/tmpfsrun
@@ -0,0 +1,11 @@
+description "mount /run"
+type wait
+target boot
+before vfs
+after tmpfsvar
+exec {
+ mount -t tmpfs none /run
+ mkdir /run/lock -m 0755
+ ln -s /run /var/run
+ ln -s /run/lock /var/lock
+}
diff --git a/services/tmpfsvar.in b/services/tmpfsvar.in
new file mode 100644
index 0000000..2c3c808
--- /dev/null
+++ b/services/tmpfsvar.in
@@ -0,0 +1,16 @@
+description "mount /var"
+type wait
+target boot
+before vfs
+exec {
+ mount -t tmpfs none /var
+ mkdir /var/log -m 0755
+ mkdir /var/spool -m 0755
+ mkdir /var/lib -m 0755
+ mkdir /var/tmp -m 0755
+ mkdir /var/nginx -m 0755
+ touch /var/log/lastlog
+ touch /var/log/faillog
+ touch /var/log/sulog
+ "@SCRIPTDIR@/overlay.sh" var_lib /var/lib
+}
diff --git a/services/unbound b/services/unbound
new file mode 100644
index 0000000..e9980ab
--- /dev/null
+++ b/services/unbound
@@ -0,0 +1,6 @@
+description "Unbound resolver"
+type respawn limit 5
+target boot
+after network
+
+exec unbound -d
diff --git a/services/usyslogd b/services/usyslogd
new file mode 100644
index 0000000..6b378d9
--- /dev/null
+++ b/services/usyslogd
@@ -0,0 +1,6 @@
+description "starting usyslogd"
+exec usyslogd --chroot --rotate-replace --max-size 8192
+type respawn limit 5
+target boot
+after vfs
+before sysinit \ No newline at end of file
diff --git a/services/vfs b/services/vfs
new file mode 100644
index 0000000..b699976
--- /dev/null
+++ b/services/vfs
@@ -0,0 +1,4 @@
+description VFS setup done
+type wait
+target boot
+before sysinit \ No newline at end of file