Files
awoooi/ops/runner/install-awoooi-non110-runner-user-service.sh

406 lines
14 KiB
Bash
Executable File

#!/usr/bin/env bash
set -euo pipefail
# Non-secret installer for the 188 user-level AWOOOI runner service. It never
# registers a runner, never reads .runner contents, and does not start the
# service unless --enable is explicitly requested after registration exists.
RUNNER_USER="${RUNNER_USER:-$(id -un)}"
RUNNER_HOME="${RUNNER_HOME:-${HOME}}"
RUNNER_DIR="${RUNNER_DIR:-${RUNNER_HOME}/act-runner-awoooi}"
RUNNER_BINARY="${RUNNER_BINARY:-${RUNNER_DIR}/act_runner}"
RUNNER_CONFIG="${RUNNER_CONFIG:-${RUNNER_DIR}/config.yaml}"
RUNNER_REGISTRATION="${RUNNER_REGISTRATION:-${RUNNER_DIR}/.runner}"
ENABLE_SENTINEL="${ENABLE_SENTINEL:-${RUNNER_DIR}/.awoooi-non110-runner-enabled}"
SERVICE_NAME="${SERVICE_NAME:-awoooi-non110-runner.service}"
ROLLBACK_SERVICE_NAME="${ROLLBACK_SERVICE_NAME:-awoooi-non110-runner-rollback.service}"
AUTOSTART_SERVICE_NAME="${AUTOSTART_SERVICE_NAME:-awoooi-non110-runner-autostart.service}"
AUTOSTART_PATH_NAME="${AUTOSTART_PATH_NAME:-awoooi-non110-runner-autostart.path}"
KEEPALIVE_SERVICE_NAME="${KEEPALIVE_SERVICE_NAME:-awoooi-non110-runner-keepalive.service}"
KEEPALIVE_TIMER_NAME="${KEEPALIVE_TIMER_NAME:-awoooi-non110-runner-keepalive.timer}"
KEEPALIVE_INTERVAL_SECONDS="${KEEPALIVE_INTERVAL_SECONDS:-15}"
USER_SERVICE_DIR="${USER_SERVICE_DIR:-${RUNNER_HOME}/.config/systemd/user}"
RUNNER_LABELS="${RUNNER_LABELS:-awoooi-non110-host:host,awoooi-non110-ubuntu:docker://192.168.0.110:5000/awoooi/ci-runner:act-22.04}"
WRITE_CONFIG_IF_MISSING="${WRITE_CONFIG_IF_MISSING:-1}"
RESTORE_BINARY_IF_MISSING="${RESTORE_BINARY_IF_MISSING:-1}"
CPU_QUOTA="${CPU_QUOTA:-200%}"
MEMORY_HIGH="${MEMORY_HIGH:-6G}"
MEMORY_MAX="${MEMORY_MAX:-8G}"
TASKS_MAX="${TASKS_MAX:-512}"
PRESSURE_GUARD="${PRESSURE_GUARD:-${RUNNER_HOME}/.local/bin/awoooi-wait-host-web-build-pressure.sh}"
PRESSURE_GUARD_ATTEMPTS="${PRESSURE_GUARD_ATTEMPTS:-1}"
PRESSURE_GUARD_SLEEP_SECONDS="${PRESSURE_GUARD_SLEEP_SECONDS:-0}"
ACTION="check"
if [ "$#" -gt 0 ]; then
case "$1" in
--check|--apply|--enable|--rollback)
ACTION="${1#--}"
shift
;;
*)
echo "usage: $0 [--check|--apply|--enable|--rollback]" >&2
exit 2
;;
esac
fi
service_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$SERVICE_NAME"
}
rollback_service_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$ROLLBACK_SERVICE_NAME"
}
autostart_service_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_SERVICE_NAME"
}
autostart_path_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$AUTOSTART_PATH_NAME"
}
keepalive_service_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$KEEPALIVE_SERVICE_NAME"
}
keepalive_timer_path() {
printf '%s/%s\n' "$USER_SERVICE_DIR" "$KEEPALIVE_TIMER_NAME"
}
metadata_path() {
local path="$1"
if [ -e "$path" ]; then
stat -c 'PATH=%n exists=1 type=%F mode=%a size=%s' "$path" 2>/dev/null || printf 'PATH=%s exists=1 stat=unavailable\n' "$path"
return 0
fi
printf 'PATH=%s exists=0\n' "$path"
}
write_runner_service() {
cat >"$(service_path)" <<EOF
[Unit]
Description=AWOOOI non-110 Gitea runner user service, capacity 1
After=default.target
ConditionPathExists=${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}
[Service]
Type=simple
WorkingDirectory=${RUNNER_DIR}
Environment=HOME=${RUNNER_HOME}
ExecStartPre=/usr/bin/test -x ${RUNNER_BINARY}
ExecStartPre=/usr/bin/test -S /var/run/docker.sock
ExecStartPre=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStartPre=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=${RUNNER_BINARY} daemon --config ${RUNNER_CONFIG}
Restart=always
RestartSec=20
KillSignal=SIGINT
TimeoutStartSec=120
TimeoutStopSec=3700
CPUQuota=${CPU_QUOTA}
MemoryHigh=${MEMORY_HIGH}
MemoryMax=${MEMORY_MAX}
TasksMax=${TASKS_MAX}
NoNewPrivileges=true
[Install]
WantedBy=default.target
EOF
}
write_default_config() {
if [ "$WRITE_CONFIG_IF_MISSING" != "1" ] || [ -s "$RUNNER_CONFIG" ]; then
return 0
fi
umask 077
cat >"$RUNNER_CONFIG" <<EOF
log:
level: info
runner:
file: ${RUNNER_REGISTRATION}
capacity: 1
envs: {}
env_file: ""
timeout: 3h
shutdown_timeout: 1h
insecure: false
fetch_timeout: 5s
fetch_interval: 2s
fetch_interval_max: 5s
labels:
$(printf '%s' "$RUNNER_LABELS" | tr ',' '\n' | awk '{ printf " - \"%s\"\n", $0 }')
cache:
enabled: false
container:
network: ""
privileged: false
valid_volumes: []
docker_host: "unix:///var/run/docker.sock"
force_pull: false
force_rebuild: false
require_docker: true
host:
workdir_parent: ${RUNNER_DIR}/host-workdir
metrics:
enabled: false
addr: "127.0.0.1:9101"
EOF
printf 'CONFIG_WRITE_PERFORMED=1 path=%s secret_values_collected=false\n' "$RUNNER_CONFIG"
}
restore_binary_from_disabled() {
if [ "$RESTORE_BINARY_IF_MISSING" != "1" ] || [ -x "$RUNNER_BINARY" ]; then
return 0
fi
local source=""
if [ -n "${ACT_RUNNER_SOURCE:-}" ]; then
source="$ACT_RUNNER_SOURCE"
else
source="$(find "$RUNNER_HOME" -maxdepth 1 -type d -name "$(basename "$RUNNER_DIR")-disabled-*" -print 2>/dev/null \
| sort -r \
| while IFS= read -r dir; do
if [ -x "${dir}/act_runner" ]; then
printf '%s/act_runner\n' "$dir"
break
fi
done)"
fi
if [ -n "$source" ] && [ -x "$source" ]; then
install -m 0755 "$source" "$RUNNER_BINARY"
printf 'BINARY_RESTORE_PERFORMED=1 source=%s target=%s\n' "$source" "$RUNNER_BINARY"
return 0
fi
printf 'BINARY_RESTORE_PERFORMED=0 reason=no_disabled_binary_source target=%s\n' "$RUNNER_BINARY"
}
write_rollback_service() {
cat >"$(rollback_service_path)" <<EOF
[Unit]
Description=Rollback AWOOOI non-110 user Gitea runner to inactive
[Service]
Type=oneshot
ExecStart=-/usr/bin/systemctl --user stop ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${KEEPALIVE_SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${KEEPALIVE_SERVICE_NAME}
ExecStart=-/usr/bin/systemctl --user stop ${AUTOSTART_PATH_NAME}
ExecStart=-/usr/bin/systemctl --user disable ${AUTOSTART_PATH_NAME}
ExecStart=-/usr/bin/systemctl --user reset-failed ${AUTOSTART_SERVICE_NAME}
ExecStart=-/usr/bin/rm -f ${ENABLE_SENTINEL}
RemainAfterExit=no
EOF
}
write_autostart_units() {
cat >"$(autostart_service_path)" <<EOF
[Unit]
Description=Enable AWOOOI non-110 runner after registration metadata appears
ConditionPathExists=!${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}
ConditionPathExists=${RUNNER_BINARY}
[Service]
Type=oneshot
ExecStart=/usr/bin/test -x ${RUNNER_BINARY}
ExecStart=/usr/bin/test -s ${RUNNER_CONFIG}
ExecStart=/usr/bin/test -s ${RUNNER_REGISTRATION}
ExecStart=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStart=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=/usr/bin/touch ${ENABLE_SENTINEL}
ExecStart=/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user start ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable --now ${KEEPALIVE_TIMER_NAME}
ExecStart=-/usr/bin/systemctl --user disable --now ${AUTOSTART_PATH_NAME}
RemainAfterExit=no
EOF
cat >"$(autostart_path_path)" <<EOF
[Unit]
Description=Watch AWOOOI non-110 runner registration metadata
[Path]
PathExists=${RUNNER_REGISTRATION}
Unit=${AUTOSTART_SERVICE_NAME}
[Install]
WantedBy=default.target
EOF
}
write_keepalive_units() {
cat >"$(keepalive_service_path)" <<EOF
[Unit]
Description=Keep AWOOOI non-110 runner active while enable sentinel exists
ConditionPathExists=${ENABLE_SENTINEL}
ConditionPathExists=${RUNNER_CONFIG}
ConditionPathExists=${RUNNER_REGISTRATION}
ConditionPathExists=${RUNNER_BINARY}
[Service]
Type=oneshot
ExecStart=/usr/bin/test -x ${RUNNER_BINARY}
ExecStart=/usr/bin/test -s ${RUNNER_CONFIG}
ExecStart=/usr/bin/test -s ${RUNNER_REGISTRATION}
ExecStart=/usr/bin/test -x ${PRESSURE_GUARD}
ExecStart=/usr/bin/env HOST_WEB_BUILD_PRESSURE_ATTEMPTS=${PRESSURE_GUARD_ATTEMPTS} HOST_WEB_BUILD_PRESSURE_SLEEP_SECONDS=${PRESSURE_GUARD_SLEEP_SECONDS} ${PRESSURE_GUARD}
ExecStart=/usr/bin/systemctl --user daemon-reload
ExecStart=-/usr/bin/systemctl --user reset-failed ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user enable ${SERVICE_NAME}
ExecStart=/usr/bin/systemctl --user start ${SERVICE_NAME}
RemainAfterExit=no
EOF
cat >"$(keepalive_timer_path)" <<EOF
[Unit]
Description=Periodically verify AWOOOI non-110 runner user service is active
[Timer]
OnBootSec=30s
OnUnitInactiveSec=${KEEPALIVE_INTERVAL_SECONDS}s
AccuracySec=10s
Unit=${KEEPALIVE_SERVICE_NAME}
[Install]
WantedBy=timers.target
EOF
}
systemd_user_reload() {
systemctl --user daemon-reload
}
readback() {
printf 'AWOOOI_NON110_USER_INSTALLER action=%s\n' "$ACTION"
printf 'runner_user=%s\n' "$RUNNER_USER"
printf 'runner_home=%s\n' "$RUNNER_HOME"
printf 'runner_dir=%s\n' "$RUNNER_DIR"
printf 'service_name=%s\n' "$SERVICE_NAME"
printf 'rollback_service_name=%s\n' "$ROLLBACK_SERVICE_NAME"
printf 'autostart_service_name=%s\n' "$AUTOSTART_SERVICE_NAME"
printf 'autostart_path_name=%s\n' "$AUTOSTART_PATH_NAME"
printf 'keepalive_service_name=%s\n' "$KEEPALIVE_SERVICE_NAME"
printf 'keepalive_timer_name=%s\n' "$KEEPALIVE_TIMER_NAME"
printf 'pressure_guard=%s\n' "$PRESSURE_GUARD"
printf 'pressure_guard_attempts=%s\n' "$PRESSURE_GUARD_ATTEMPTS"
printf 'pressure_guard_sleep_seconds=%s\n' "$PRESSURE_GUARD_SLEEP_SECONDS"
printf 'secret_values_collected=false\n'
printf 'runner_token_read=false\n'
printf 'raw_runner_registration_read=false\n'
loginctl show-user "$RUNNER_USER" -p Linger 2>/dev/null || true
metadata_path "$RUNNER_DIR"
metadata_path "$RUNNER_BINARY"
metadata_path "$RUNNER_CONFIG"
metadata_path "$RUNNER_REGISTRATION"
metadata_path "$ENABLE_SENTINEL"
printf 'RUNNER_REGISTRATION content_read=false\n'
metadata_path "$(service_path)"
metadata_path "$(rollback_service_path)"
metadata_path "$(autostart_service_path)"
metadata_path "$(autostart_path_path)"
metadata_path "$(keepalive_service_path)"
metadata_path "$(keepalive_timer_path)"
systemctl --user show "$SERVICE_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
systemctl --user show "$ROLLBACK_SERVICE_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
systemctl --user show "$AUTOSTART_PATH_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
systemctl --user show "$KEEPALIVE_TIMER_NAME" -p LoadState -p ActiveState -p UnitFileState -p MainPID --no-pager 2>/dev/null || true
}
apply_units() {
mkdir -p "$RUNNER_DIR" "$USER_SERVICE_DIR"
restore_binary_from_disabled
write_default_config
write_runner_service
write_rollback_service
write_autostart_units
write_keepalive_units
chmod 0644 \
"$(service_path)" \
"$(rollback_service_path)" \
"$(autostart_service_path)" \
"$(autostart_path_path)" \
"$(keepalive_service_path)" \
"$(keepalive_timer_path)"
systemd_user_reload
if registration_ready; then
printf 'AUTOSTART_PATH_ENABLE_PERFORMED=0 reason=registration_ready_requires_explicit_enable\n'
else
systemctl --user enable --now "$AUTOSTART_PATH_NAME" >/dev/null
printf 'AUTOSTART_PATH_ENABLE_PERFORMED=1\n'
fi
printf 'APPLY_PERFORMED=1\n'
printf 'SERVICE_START_PERFORMED=0\n'
printf 'SERVICE_ENABLE_PERFORMED=0\n'
}
registration_ready() {
[ -x "$RUNNER_BINARY" ] && [ -s "$RUNNER_CONFIG" ] && [ -s "$RUNNER_REGISTRATION" ]
}
enable_runner() {
apply_units
if [ "${AWOOOI_NON110_ENABLE:-0}" != "1" ]; then
echo "Refusing --enable without AWOOOI_NON110_ENABLE=1" >&2
exit 1
fi
if ! registration_ready; then
echo "Refusing --enable: binary/config/.runner metadata is not complete" >&2
exit 1
fi
touch "$ENABLE_SENTINEL"
systemctl --user reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user reset-failed "$AUTOSTART_SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user disable --now "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
systemctl --user enable --now "$KEEPALIVE_TIMER_NAME"
systemctl --user enable "$SERVICE_NAME"
systemctl --user start "$SERVICE_NAME"
printf 'SERVICE_ENABLE_PERFORMED=1\n'
printf 'SERVICE_START_PERFORMED=1\n'
printf 'KEEPALIVE_TIMER_ENABLE_PERFORMED=1\n'
}
rollback_runner() {
systemctl --user stop "$KEEPALIVE_TIMER_NAME" >/dev/null 2>&1 || true
systemctl --user disable "$KEEPALIVE_TIMER_NAME" >/dev/null 2>&1 || true
systemctl --user stop "$KEEPALIVE_SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user reset-failed "$KEEPALIVE_SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user stop "$SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user disable "$SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user reset-failed "$SERVICE_NAME" >/dev/null 2>&1 || true
systemctl --user stop "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
systemctl --user disable "$AUTOSTART_PATH_NAME" >/dev/null 2>&1 || true
systemctl --user reset-failed "$AUTOSTART_SERVICE_NAME" >/dev/null 2>&1 || true
rm -f "$ENABLE_SENTINEL"
printf 'ROLLBACK_PERFORMED=1\n'
}
case "$ACTION" in
check)
;;
apply)
apply_units
;;
enable)
enable_runner
;;
rollback)
rollback_runner
;;
esac
readback