#!/bin/sh # SPDX-License-Identifier: CC0-1.0 # Copyright (C) 2022 Wojtek Kosior # # Available under the terms of Creative Commons Zero v1.0 Universal. ### BEGIN INIT INFO # Provides: guix-container # Required-Start: $local_fs $remote_fs $syslog # Required-Stop: $local_fs $remote_fs $syslog # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start Wojtek's Guix container with various services ### END INIT INFO set -e . /lib/lsb/init-functions if [ 0 != $(id -u) ]; then log_action_msg "Script '$0' must be run as root" exit 1 fi PIDFILE=/run/guix-container.pid EXECUTABLE=/usr/local/bin/guix-container HOST_SYSTEM_ROOT= MAX_CONTAINER_SPINUP_WAIT=60 ACTION="$1" shift OPTIND=1 while getopts p:e:r:s: OPTION_LETTER ; do case "$OPTION_LETTER" in p) PIDFILE="$OPTARG" ;; e) EXECUTABLE="$OPTARG" ;; r) HOST_SYSTEM_ROOT="$OPTARG" ;; s) MAX_CONTAINER_SPINUP_WAIT="$OPTARG" ;; esac done GUILE_PID= SUCCESS= QUIET_EXIT= is_running() { test -e "$PIDFILE" && test -n "$(ps -o pid= --pid $(cat "$PIDFILE"))" return $? } network_rip() { ip link delete veth-guix-out 2>/dev/null || true } stop() { network_rip /sbin/start-stop-daemon \ --stop --signal TERM --pidfile "$PIDFILE" --remove-pidfile --quiet \ --retry 60 2>/dev/null || true } onexit() { if [ -z "$SUCCESS" ]; then if [ "x$ACTION" = "xstart" -a -n "$GUILE_PID" ]; then stop kill $GUILE_PID >/dev/null || true fi if [ -z "$QUIET_EXIT" ]; then log_failure_msg fi else if [ -z "$QUIET_EXIT" ]; then log_success_msg fi fi } start() { LOG_DIR="$HOST_SYSTEM_ROOT"/var/log/guix-container KOSZKO_SIDELOAD_REAL="$HOST_SYSTEM_ROOT"/var/www/koszko.org/html HYDRILLA_HTTP_REAL="$HOST_SYSTEM_ROOT"/var/www/hydrilla.koszko.org/html HYDRILLAREPOS_HTTP_REAL="$HOST_SYSTEM_ROOT"/var/www/hydrillarepos.koszko.org/html LOG_REAL="$LOG_DIR"/container ETC_REAL="$HOST_SYSTEM_ROOT"/etc/guix-container VAR_HYDRILLA_REAL="$HOST_SYSTEM_ROOT"/var/lib/hydrilla VAR_GITOLITE_REAL="$HOST_SYSTEM_ROOT"/var/lib/gitolite3 KOSZKO_SIDELOAD_DIR_SHARE_OPT=--share="$KOSZKO_SIDELOAD_REAL"=/srv/http/koszko.org HYDRILLA_HTTP_DIR_SHARE_OPT=--share="$HYDRILLA_HTTP_REAL"=/srv/http/hydrilla.koszko.org HYDRILLAREPOS_HTTP_DIR_SHARE_OPT=--share="$HYDRILLAREPOS_HTTP_REAL"=/srv/http/hydrillarepos.koszko.org LOG_DIR_SHARE_OPT=--share="$LOG_REAL"=/var/log ETC_DIR_SHARE_OPT=--share="$ETC_REAL"=/etc VAR_HYDRILLA_DIR_SHARE_OPT=--share="$VAR_HYDRILLA_REAL"=/var/lib/hydrilla VAR_GITOLITE_DIR_SHARE_OPT=--share="$VAR_GITOLITE_REAL"=/var/lib/gitolite3 mkdir --mode=700 -p "$LOG_DIR" mkdir --mode=700 -p "$LOG_DIR"/container "$EXECUTABLE" "$KOSZKO_SIDELOAD_DIR_SHARE_OPT" \ "$HYDRILLA_HTTP_DIR_SHARE_OPT" \ "$HYDRILLAREPOS_HTTP_DIR_SHARE_OPT" \ "$LOG_DIR_SHARE_OPT" \ "$ETC_DIR_SHARE_OPT" \ "$VAR_HYDRILLA_DIR_SHARE_OPT" \ "$VAR_GITOLITE_DIR_SHARE_OPT" \ >> "$LOG_DIR"/stdout.log 2>> "$LOG_DIR"/stderr.log & GUILE_PID=$! WAIT_TIME=0 SHEPHERD_PID= while [ $WAIT_TIME -lt "$MAX_CONTAINER_SPINUP_WAIT" ]; do sleep 1 WAIT_TIME=$((WAIT_TIME + 1)) SHEPHERD_PID=$(ps -o pid= --ppid $GUILE_PID || true) if [ -n "$SHEPHERD_PID" ]; then mkdir -p "$(dirname "$PIDFILE")" printf '%s' $SHEPHERD_PID > "$PIDFILE" break fi done if [ -z "$SHEPHERD_PID" ]; then exit 1 fi network_rip ip link add veth-guix-out type veth peer name veth-guix-in ip link set veth-guix-in netns "$SHEPHERD_PID" ip link set veth-guix-out up ip addr add 10.207.87.1/24 dev veth-guix-out nsenter -t "$SHEPHERD_PID" --net ip link set lo up nsenter -t "$SHEPHERD_PID" --net ip link set veth-guix-in up nsenter -t "$SHEPHERD_PID" --net ip addr add 10.207.87.2/24 dev veth-guix-in } trap onexit EXIT case "$ACTION" in start) if is_running; then log_daemon_msg "Guix container" "already running" log_warning_msg QUIET_EXIT=1 else log_daemon_msg "Guix container" "starting" start fi ;; stop) log_daemon_msg "Guix container" "stopping" stop ;; restart) QUIET_EXIT=1 "$0" stop "$@" "$0" start "$@" ;; reload|force-reload) QUIET_EXIT=1 "$0" stop "$@" "$0" start "$@" ;; status) status_of_proc -p "$PIDFILE" "$EXECUTABLE" "Guix container" QUIET_EXIT=1 ;; *) log_action_msg "Usage: $0 {start|stop|status|restart|reload|force-reload}" QUIET_EXIT=1 exit 2 ;; esac SUCCESS=1 exit 0