about summary refs log tree commit diff
path: root/bundles/s6
diff options
context:
space:
mode:
authorRobert Günzler <r@gnzler.io>2025-09-07 17:32:13 +0200
committerRobert Günzler <r@gnzler.io>2025-09-07 17:42:42 +0200
commit38be6c13f76e893cf47636257071b440dec0c5b2 (patch)
treef7ded3235a7e3362cbd1ed3d91523968fe0faf90 /bundles/s6
initial commit
Signed-off-by: Robert Günzler <r@gnzler.io>
Diffstat (limited to 'bundles/s6')
-rw-r--r--bundles/s6/files/etc/conf.d/s6-rc-common8
-rwxr-xr-xbundles/s6/files/etc/init.d/s6-rc-init56
-rwxr-xr-xbundles/s6/files/etc/init.d/s6-rc-up37
-rwxr-xr-xbundles/s6/files/etc/periodic/15min/s6-rc-metrics61
-rw-r--r--bundles/s6/files/etc/s6-rc/README18
-rw-r--r--bundles/s6/files/etc/s6-rc/services/default/type1
-rw-r--r--bundles/s6/files/etc/s6-rc/system.conf3
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-log/consumer-for1
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-log/notification-fd1
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-log/pipeline-name1
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-log/run10
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-log/type1
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-srv/producer-for1
-rwxr-xr-xbundles/s6/files/etc/s6-rc/templates/service/+service-srv/run6
-rw-r--r--bundles/s6/files/etc/s6-rc/templates/service/+service-srv/type1
-rw-r--r--bundles/s6/items.py62
-rw-r--r--bundles/s6/metadata.py9
17 files changed, 277 insertions, 0 deletions
diff --git a/bundles/s6/files/etc/conf.d/s6-rc-common b/bundles/s6/files/etc/conf.d/s6-rc-common
new file mode 100644
index 0000000..bcd0e23
--- /dev/null
+++ b/bundles/s6/files/etc/conf.d/s6-rc-common
@@ -0,0 +1,8 @@
+s6_rc_base=/etc/s6-rc/services
+
+s6_rc_generated=/run/s6-rc-generated
+
+s6_rc_merged=/run/s6-rc-merged
+
+# used when starting/stopping service tree
+s6_rc_timeout=30000
diff --git a/bundles/s6/files/etc/init.d/s6-rc-init b/bundles/s6/files/etc/init.d/s6-rc-init
new file mode 100755
index 0000000..df1cd78
--- /dev/null
+++ b/bundles/s6/files/etc/init.d/s6-rc-init
@@ -0,0 +1,56 @@
+#!/sbin/openrc-run
+
+description="Initialize s6-rc"
+
+source /etc/conf.d/s6-rc-common
+
+depend()
+{
+        need localmount
+}
+
+start()
+{
+        s6-rc-generate ${s6_rc_generated}
+
+        local lower=$s6_rc_base
+        test -e "$lower" || eerror "Missing lower: $lower"
+
+        local upper=$s6_rc_generated
+        test -e "$upper" || eerror "Missing upper: $upper"
+
+        # mandatory for overlayfs, though not used because we mount read-only
+        local workdir=${s6_rc_merged}.ovlwork
+        mkdir -p ${workdir}
+
+        # create mountpoint
+        mkdir -p ${s6_rc_merged}
+
+        mount -t overlay overlay \
+                -o lowerdir=${lower},upperdir=${upper},workdir=${workdir},ro \
+                ${s6_rc_merged}
+
+        test -e /etc/s6-rc/compiled || s6-rc-recompile ${s6_rc_merged}
+
+        test -e /run/s6-rc || s6-rc-init -bd -t 3000 "${RC_SVCDIR}"/s6-scan
+}
+
+stop()
+{
+        rm -rf ${s6_rc_generated}
+
+        umount ${s6_rc_merged}
+        rm -rf ${s6_rc_merged}.ovlwork
+}
+
+reload()
+{
+        s6-rc-generate ${s6_rc_generated}
+
+        s6-rc-recompile ${s6_rc_merged}
+
+        s6-rc -v2 -upb -t "$s6_rc_timeout" change default
+}
+
+
+extra_commands="reload"
diff --git a/bundles/s6/files/etc/init.d/s6-rc-up b/bundles/s6/files/etc/init.d/s6-rc-up
new file mode 100755
index 0000000..a2c1dee
--- /dev/null
+++ b/bundles/s6/files/etc/init.d/s6-rc-up
@@ -0,0 +1,37 @@
+#!/sbin/openrc-run
+
+description="Bring up s6-rc services."
+
+source /etc/conf.d/s6-rc-common
+
+depend()
+{
+        need s6-svscan localmount
+        use s6-rc-init
+
+        need network-online
+        use net
+
+        after podman
+}
+
+start()
+{
+        s6-rc -v2 -upb -t "$s6_rc_timeout" change default
+}
+
+stop()
+{
+        s6-rc -v2 -dpb -t "$s6_rc_timeout" change default
+}
+
+cleanup()
+{
+        rc-service s6-svscan stop || true # HACK
+        rm -rfv /etc/s6-rc/compiled
+        rm -rfv /etc/s6-rc/_*
+        rm -rfv /run/s6-rc
+        rm -rfv /run/openrc/s6-scan # HACK
+}
+
+extra_commands="cleanup"
diff --git a/bundles/s6/files/etc/periodic/15min/s6-rc-metrics b/bundles/s6/files/etc/periodic/15min/s6-rc-metrics
new file mode 100755
index 0000000..4fa7625
--- /dev/null
+++ b/bundles/s6/files/etc/periodic/15min/s6-rc-metrics
@@ -0,0 +1,61 @@
+#!/bin/sh
+set -eu
+
+textfile_directory=/run/prom
+
+s6rc_service_is_up() {
+	if s6-rc -a list | grep -q "${1:?}"; then printf '1'; else printf '0'; fi
+}
+
+printmetric() {
+	local name=${1:?}
+	local labels=${2:?}
+	local value=${3:?}
+	printf '%s{%s} %s\n' "$name" "$labels" "$value"
+}
+
+services_count() {
+	printf '# HELP s6_rc_services_count number of services\n'
+	printf '# TYPE s6_rc_services_count gauge\n'
+	for bundle in $(s6-rc-db list bundles); do
+		printmetric 's6_rc_services_count' \
+			$(printf 'bundle="%s"' $bundle) \
+			$(s6-rc list $bundle | wc -l)
+	done
+}
+
+services_up() {
+	printf '# HELP s6_rc_service_up if a service is running\n'
+	#printf '# TYPE s6_rc_service_up stateset\n'
+	for bundle in $(s6-rc-db list bundles)
+	do
+		for service in $(s6-rc-db contents "$bundle")
+		do
+			printmetric 's6_rc_service_up' \
+				$(printf 'bundle="%s",service="%s"' $bundle $service) \
+				$(s6rc_service_is_up $service)
+		done
+	done
+}
+
+write_textfile() {
+	mkdir -p "$textfile_directory" || exit 1
+
+	tmp=$(mktemp --tmpdir metrics_s6_rc.XXXXX)
+
+	(
+		services_count
+		services_up
+	) | tee "$tmp"
+
+	mv -v "$tmp" "$textfile_directory"/s6_rc.prom || exit 1
+
+	chmod +r "$textfile_directory"/s6_rc.prom
+	chown nobody:nobody "$textfile_directory"/s6_rc.prom
+}
+
+main() {
+	write_textfile
+}
+
+main >/dev/null 2>&1
diff --git a/bundles/s6/files/etc/s6-rc/README b/bundles/s6/files/etc/s6-rc/README
new file mode 100644
index 0000000..bd9014c
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/README
@@ -0,0 +1,18 @@
+
+./services
+----------
+this is the base s6-rc service tree that is merged with the services generated
+by `s6-rc-generate`.
+There MUST at least be a default target, most commonly a `bundle` that declares
+the set of services that should run on boot.
+
+./templates
+-----------
+defines a set of services templates `s6-rc-generate` uses as input,
+the string `+service` will be replaced with the target service name
+(works in file names and inside files)
+
+./generate
+----------
+defines a set of services `s6-rc-generate` should generate,
+the names MUST be in the format <template>.<service>
diff --git a/bundles/s6/files/etc/s6-rc/services/default/type b/bundles/s6/files/etc/s6-rc/services/default/type
new file mode 100644
index 0000000..757b422
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/services/default/type
@@ -0,0 +1 @@
+bundle
diff --git a/bundles/s6/files/etc/s6-rc/system.conf b/bundles/s6/files/etc/s6-rc/system.conf
new file mode 100644
index 0000000..066fe0a
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/system.conf
@@ -0,0 +1,3 @@
+# location of deployment charts for container services
+deployments_dir=/etc/deployments
+www_dir=/var/www
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-log/consumer-for b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/consumer-for
new file mode 100644
index 0000000..83c1762
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/consumer-for
@@ -0,0 +1 @@
++service-srv
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-log/notification-fd b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/notification-fd
new file mode 100644
index 0000000..00750ed
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/notification-fd
@@ -0,0 +1 @@
+3
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-log/pipeline-name b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/pipeline-name
new file mode 100644
index 0000000..0db7d83
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/pipeline-name
@@ -0,0 +1 @@
++service
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-log/run b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/run
new file mode 100644
index 0000000..d558f3c
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/run
@@ -0,0 +1,10 @@
+#!/bin/execlineb -P
+
+envfile -I /etc/s6-rc/system.conf
+importas -sCuD "/run/log" s6_log_dir s6_log_dir
+
+envfile -I /etc/s6-rc/+service.conf
+importas -sCuD "n3 s2000000 T" s6_log_directives s6_log_directives
+
+foreground { install -d ${s6_log_dir}/+service }
+exec -c s6-log -d3 -b -- ${s6_log_directives} ${s6_log_dir}/+service
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-log/type b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/type
new file mode 100644
index 0000000..5883cff
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-log/type
@@ -0,0 +1 @@
+longrun
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/producer-for b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/producer-for
new file mode 100644
index 0000000..cba6eea
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/producer-for
@@ -0,0 +1 @@
++service-log
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/run b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/run
new file mode 100755
index 0000000..87531f7
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/run
@@ -0,0 +1,6 @@
+#!/bin/execlineb -P
+
+# route all logs to stdout
+fdmove -c 2 1
+
+exec /etc/service/+service.run
diff --git a/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/type b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/type
new file mode 100644
index 0000000..5883cff
--- /dev/null
+++ b/bundles/s6/files/etc/s6-rc/templates/service/+service-srv/type
@@ -0,0 +1 @@
+longrun
diff --git a/bundles/s6/items.py b/bundles/s6/items.py
new file mode 100644
index 0000000..2fd8370
--- /dev/null
+++ b/bundles/s6/items.py
@@ -0,0 +1,62 @@
+if node.os != "alpine":
+    raise BundleError(f"{node.name}: OS {node.os} is not supported.")
+
+from os.path import join
+
+files = {
+    "/bin/svdn":                                       {"mode": "0755"},
+    "/bin/svup":                                       {"mode": "0755"},
+    "/bin/svls":                                       {"mode": "0755"},
+    "/bin/svre":                                       {"mode": "0755"},
+    "/bin/s6-rc-recompile":                            {"mode": "0755"},
+    "/bin/s6-rc-generate":                             {"mode": "0755"},
+    "/etc/init.d/s6-rc-init":                          {"mode": "0755"},
+    "/etc/init.d/s6-rc-up":                            {"mode": "0755"},
+    "/etc/periodic/15min/s6-rc-metrics":               {"mode": "0755"},
+
+    "/etc/s6-rc/templates/service/+service-srv/run":   {"mode": "0755"},
+    "/etc/s6-rc/templates/service/+service-log/run":   {"mode": "0755"},
+    "/etc/s6-rc/services/default/contents.d/services": {
+        "content_type": "text",
+        "content": "",
+        "triggers": {
+            "svc_openrc:s6-rc-up:restart",
+        },
+    },
+    "/etc/s6-rc/services/services/type": {
+        "content_type": "text",
+        "content": "bundle",
+        "triggers": {
+            "svc_openrc:s6-rc-up:restart",
+        },
+    },
+}
+
+directories = {
+    "/etc/s6-rc/services/services/contents.d": {}
+}
+
+repo.libs.gen.add_files_recursive(
+    files,
+    join(repo.path, "bundles", "s6", "files"),
+)
+
+svc_openrc = {
+    "s6-rc-init": {
+        "enabled": True,
+        "running": True,
+        "needs": {"file:/etc/init.d/s6-rc-init"},
+    },
+    "s6-rc-up": {
+        "enabled": True,
+        "running": True,
+        "needs": {"file:/etc/init.d/s6-rc-up"},
+    },
+}
+
+
+for service, _ in node.metadata.get("services", {}).items():
+    svc_s6rc[service] = {
+        "bundle": "services",
+        "generate": "service",
+    }
diff --git a/bundles/s6/metadata.py b/bundles/s6/metadata.py
new file mode 100644
index 0000000..0ddc51b
--- /dev/null
+++ b/bundles/s6/metadata.py
@@ -0,0 +1,9 @@
+defaults = {
+    "apk": {
+        "packages": {
+            "coreutils": {}, # TODO: make scripts busybox compatible
+            "s6-rc": {},
+            "s6-portable-utils": {},
+        },
+    },
+}