🔧 Fix Gitea API token auth and container restart/runner races 🔧

Gitea config: `ALLOWED_HOST_LIST` was misplaced under `[webhook]` — the current
config-cheat-sheet places it under `[security]` (default `external`), where it
gates outbound webhook/OAuth2 calls. Left at its `[webhook]` default of unset
(no such key there), `[security] ALLOWED_HOST_LIST` silently fell back to
`external`, blocking internal-facing calls triggered by API actions like org
creation and surfacing as an opaque 502 through the reverse proxy. Also pinned
`DISABLE_QUERY_AUTH_TOKEN=false` explicitly, since Gitea flips its default to
`true` in 1.23 (deprecated in 1.24) and this image always builds against the
latest Gitea release — leaving it unset would silently downgrade `?token=`
API calls to anonymous on the next image rebuild.

Runtime/entrypoint: hardened `grep`/`type -t | grep` calls with `--` across
the entrypoint function library and init.d scripts to stop values starting
with `-` from being parsed as flags; guarded the entrypoint and `__no_exit`
monitor-loop PID-reuse checks with a cmdline marker (PID namespaces reset on
`docker restart` but `/run` persists, so a recorded PID can coincidentally be
reused by an unrelated process and falsely appear "still running"); added a
stale `/tmp/docker.pid` cleanup before each dockerd start attempt for the
same reason; added `NO_COLOR`-aware plain-text fallbacks for emoji status
banners; renamed the `su_cmd` helper to `__su_cmd` for naming consistency
with other private functions; added `fuse-overlayfs` as the Docker-in-Docker
storage driver.

act_runner: removed the legacy single "gitea"-named runner registration and
daemon start in `zz-act_runner.sh` — `start-runners` already owns all runner
registration/count via `RUNNERS_START`, and running both duplicated runners.
Registration now targets `127.0.0.1` instead of the detected external IPv4
address, which is transient/wrong under Docker-in-Docker networking and
caused "no route to host" registration failures. Long-running background
jobs (`cache-server`, `start-runners`) now redirect stdout/stderr to real log
files and are `disown`ed instead of inheriting the `__post_execute` pipe —
otherwise the `tee` reading that pipe never sees EOF and `__run_start_script`
hangs forever waiting on a process that never exits. `start-runners` gained a
version-stamp header and builds `RUNNER_LABELS` from an array instead of one
long string for readability; its `ERR` trap and ports list now respect
`NO_COLOR`.

- rootfs/tmp/etc/gitea/app.ini: move `ALLOWED_HOST_LIST` to `[security]`; add explicit `DISABLE_QUERY_AUTH_TOKEN=false`
- rootfs/tmp/etc/docker/daemon.json: add `storage-driver: fuse-overlayfs`
- rootfs/usr/local/bin/entrypoint.sh: version bump; `grep --` hardening; cmdline-marker PID-reuse guard; `exit 0` instead of bare `exit`
- rootfs/usr/local/bin/start-runners: add version-stamp header; `NO_COLOR`-aware ERR trap; build `RUNNER_LABELS` from an array
- rootfs/usr/local/etc/docker/functions/entrypoint.sh: version bump; `grep --` hardening across helpers; `__no_exit` monitor-loop cmdline-marker guard; `NO_COLOR`-aware service banners; rename `su_cmd` to `__su_cmd`
- rootfs/usr/local/etc/docker/init.d/05-dockerd.sh: version bump; `NO_COLOR`-aware messages; stale `/tmp/docker.pid` cleanup before start; `symlink`/`su_cmd` calls updated to `__symlink`/`__su_cmd`; `grep --` hardening; add `storage-driver` to both daemon.json heredocs
- rootfs/usr/local/etc/docker/init.d/08-gitea.sh: version bump; `NO_COLOR`-aware messages (including stale-PID-file cleanup); `grep --` hardening; `su_cmd` call updated to `__su_cmd`
- rootfs/usr/local/etc/docker/init.d/zz-act_runner.sh: version bump; remove legacy duplicate runner registration/daemon start; register against `127.0.0.1`; redirect and disown long-running background jobs to prevent pipe hangs; `NO_COLOR`-aware messages
This commit is contained in:
casjay
2026-09-03 18:18:41 -04:00
parent 4a954b0eb3
commit 7e1c90cff6
8 changed files with 253 additions and 102 deletions
+1
View File
@@ -5,6 +5,7 @@
"experimental": true,
"pidfile": "/tmp/docker.pid",
"cgroup-parent": "/docker",
"storage-driver": "fuse-overlayfs",
"default-address-pools": [
{"base": "172.17.0.0/12", "size": 24},
{"base": "192.168.0.0/16", "size": 24},
+6 -1
View File
@@ -200,6 +200,12 @@ REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
REVERSE_PROXY_AUTHENTICATION_FULL_NAME = X-WEBAUTH-FULLNAME
X_FRAME_OPTIONS = SAMEORIGIN
ALLOWED_HOST_LIST = *
; explicit: defaults to true starting Gitea 1.23 and deprecates ?token=/?access_token=
; auth entirely in 1.24 — pin false so query-token API calls keep authenticating on
; upgrade instead of silently downgrading to anonymous; migrate callers to
; "Authorization: token <token>" when convenient
DISABLE_QUERY_AUTH_TOKEN = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[time]
DEFAULT_UI_LOCATION = REPLACE_TZ
@@ -224,7 +230,6 @@ http.sslVerify = false
[webhook]
QUEUE_LENGTH = 1000
DELIVER_TIMEOUT = 30
ALLOWED_HOST_LIST = *
SKIP_TLS_VERIFY = true
PAGING_NUM = 10
PROXY_URL =
+19 -10
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261500-git
##@Version : 202609030524-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
@@ -20,6 +20,8 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202609030524-git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run trap command on exit
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' INT TERM
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' SIGPWR 2>/dev/null || true
@@ -330,7 +332,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
# if ipv6 add it to /etc/hosts
if [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
echo "# known hostname mappings" >"/etc/hosts" 2>/dev/null || true
if [ -n "$(ip a 2>/dev/null | grep 'inet6.*::' || ifconfig 2>/dev/null | grep 'inet6.*::')" ]; then
if [ -n "$(ip a 2>/dev/null | grep -- 'inet6.*::' || ifconfig 2>/dev/null | grep -- 'inet6.*::')" ]; then
__printf_space "40" "::1" "localhost" >>"/etc/hosts" 2>/dev/null || true
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
else
@@ -371,7 +373,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import hosts file into container
if [ -f "/usr/local/etc/hosts" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
grep -vF "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" || true
grep -vF -- "$HOSTNAME" "/usr/local/etc/hosts" 2>/dev/null >>"/etc/hosts" || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import resolv.conf file into container
@@ -431,9 +433,16 @@ fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# if no pid assume container restart - clean stale files on restart
if [ -f "$ENTRYPOINT_PID_FILE" ]; then
# Check if the PID in the file is still running
# Check if the PID in the file is still running. /run persists across
# `docker restart` (same container filesystem), but the PID namespace
# resets every restart, so a recorded PID can coincidentally be reused by
# an unrelated early-boot process in the new namespace. A bare `kill -0`
# would then wrongly treat this as "entrypoint already running" and skip
# __start_init_scripts entirely on a genuine restart, so also require the
# live process's own cmdline to actually be this entrypoint script.
entrypoint_pid=$(<"$ENTRYPOINT_PID_FILE") 2>/dev/null
if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null; then
if [ -n "$entrypoint_pid" ] && kill -0 "$entrypoint_pid" 2>/dev/null \
&& grep -q -- "entrypoint.sh" "/proc/$entrypoint_pid/cmdline" 2>/dev/null; then
# Process is still running, don't restart services
START_SERVICES="no"
touch "$ENTRYPOINT_PID_FILE"
@@ -550,7 +559,7 @@ cron)
shift 1
__cron "$@" &
__log_info "Cron script is running with PID: $!"
exit
exit 0
;;
# backup data and config dirs
backup)
@@ -581,7 +590,7 @@ healthcheck)
services+="$name "
done
fi
services="$(printf '%s\n' $services | sort -u | grep -v '^$')"
services="$(printf '%s\n' $services | sort -u | grep -v -- '^$')"
for proc in $services; do
if [ -n "$proc" ]; then
if ! __pgrep "$proc"; then
@@ -592,7 +601,7 @@ healthcheck)
done
for port in $healthPorts; do
if command -v netstat &>/dev/null && [ -n "$port" ]; then
if ! netstat -taupln | grep -q ":$port "; then
if ! netstat -taupln | grep -q -- ":$port "; then
echo "$port isn't open" >&2
healthStatus=$((healthStatus + 1))
fi
@@ -622,7 +631,7 @@ ports)
# show running processes
procs)
shift 1
ps="$(__ps axco command 2>/dev/null | grep -vE '^(COMMAND|grep|ps)$' | sort -u)"
ps="$(__ps axco command 2>/dev/null | grep -vE -- '^(COMMAND|grep|ps)$' | sort -u)"
[ -n "$ps" ] && printf '%s\n%s\n' "Found the following processes" "$ps" | tr '\n' ' '
exit $?
;;
@@ -659,7 +668,7 @@ start)
if [ $# -eq 0 ]; then
scripts="$(ls -A "/usr/local/etc/docker/init.d")"
[ -n "$scripts" ] && echo "$scripts" || echo "No scripts found in: /usr/local/etc/docker/init.d"
exit
exit 0
elif [ "$1" = "all" ]; then
shift $#
if [ "$START_SERVICES" = "yes" ]; then
+56 -3
View File
@@ -1,8 +1,31 @@
#!/usr/bin/env bash
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202609030524-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : LICENSE.md
# @@ReadME : start-runners --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Friday, Jun 05, 2026 18:14 EDT
# @@File : start-runners
# @@Description : Start act runners
# @@Changelog : New script
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : shell/bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202609030524-git"
set -e
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
trap 'retVal=$?; echo "❌ Fatal error occurred: Exit code $retVal at line $LINENO in command: $BASH_COMMAND"; kill -TERM 1' ERR
trap 'retVal=$?; emoji=$( [ -z "$NO_COLOR" ] && echo "❌ " || echo "" ); \
echo "${emoji}Fatal error occurred: Exit code $retVal at line $LINENO in command: $BASH_COMMAND"; \
kill -TERM 1' ERR
trap 'retVal=$?;if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then rm -Rf "$SERVICE_PID_FILE"; fi;exit $retVal' SIGINT SIGTERM SIGPWR
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Function to __log messages with timestamp
@@ -33,7 +56,37 @@ if [ -z "$SERVER_TOKEN" ]; then
exit 1
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RUNNER_LABELS="${RUNNER_LABELS:-linux:host,node14:docker://node:14,node16:docker://node:16,node18:docker://node:18,node20:docker://node:20,node22:docker://node:22,node:docker://node:latest,perl:docker://perl:latest,ruby:docker://ruby:latest,python:docker://python:latest,python3:docker://python:latest,php7:docker://casjaysdevdocker/php:7,php8:docker://casjaysdevdocker/php:8,php:docker://casjaysdevdocker/php:latest,alpine:docker://casjaysdev/alpine:latest,debian:docker://casjaysdev/debian:latest,ubuntu:docker://casjaysdev/ubuntu:latest,rhel:docker://casjaysdev/almalinux:latest,redhat:docker://casjaysdev/almalinux:latest,almalinux:docker://casjaysdev/almalinux:latest,act_runner:docker://catthehacker/ubuntu:full-latest,ubuntu-latest:docker://catthehacker/ubuntu:full-latest}"
if [ -z "$RUNNER_LABELS" ]; then
_default_runner_labels=(
"linux:host"
"node14:docker://node:14"
"node16:docker://node:16"
"node18:docker://node:18"
"node20:docker://node:20"
"node22:docker://node:22"
"node:docker://node:latest"
"perl:docker://perl:latest"
"ruby:docker://ruby:latest"
"python:docker://python:latest"
"python3:docker://python:latest"
"php7:docker://casjaysdevdocker/php:7"
"php8:docker://casjaysdevdocker/php:8"
"php:docker://casjaysdevdocker/php:latest"
"alpine:docker://casjaysdev/alpine:latest"
"debian:docker://casjaysdev/debian:latest"
"ubuntu:docker://casjaysdev/ubuntu:latest"
"rhel:docker://casjaysdev/almalinux:latest"
"redhat:docker://casjaysdev/almalinux:latest"
"almalinux:docker://casjaysdev/almalinux:latest"
"act_runner:docker://catthehacker/ubuntu:full-latest"
"ubuntu-latest:docker://catthehacker/ubuntu:full-latest"
)
RUNNER_LABELS="$(
IFS=,
echo "${_default_runner_labels[*]}"
)"
unset _default_runner_labels
fi
# Determine number of runners to start
RUNNERS_START=${RUNNERS_START:-1}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202607271325-git
##@Version : 202609030524-git
# @@Author : Jason Hempstead
# @@Contact : git-admin@casjaysdev.pro
# @@License : LICENSE.md
@@ -20,6 +20,8 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202609030524-git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
if [ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ]; then
export DEBUGGER_OPTIONS="$(<"/config/.debug")"
@@ -77,7 +79,7 @@ __rm() {
fi
return 0
}
__grep_test() { grep -sh "$1" "$2" 2>/dev/null | grep -qwF "${3:-$1}"; }
__grep_test() { grep -sh -- "$1" "$2" 2>/dev/null | grep -qwF -- "${3:-$1}"; }
__netstat() {
command -v netstat &>/dev/null || {
[ "$DEBUGGER" = "on" ] && echo "Warning: netstat command not found" >&2 || true
@@ -89,7 +91,7 @@ __cd() {
[ -d "$1" ] || mkdir -p "$1" 2>/dev/null || return 1
builtin cd "$1" || return 1
}
__is_in_file() { [ -e "$2" ] && grep -Rsq "$1" "$2" 2>/dev/null; }
__is_in_file() { [ -e "$2" ] && grep -Rsq -- "$1" "$2" 2>/dev/null; }
__curl() { curl -q -sfI --max-time 3 -k -o /dev/null "$@" 2>/dev/null || return 10; }
__find() {
local result
@@ -108,7 +110,7 @@ __file_exists_with_content() { [ -n "$1" ] && [ -f "$1" ] && [ -s "$1" ] || retu
__sed() { sed -i "s|$1|$2|g" "$3" 2>/dev/null || return 1; }
__ps() {
command -v ps &>/dev/null || return 10
ps "$@" 2>/dev/null | sed 's|:||g' | grep -Fw " ${1:-$SERVICE_NAME}$" || return 10
ps "$@" 2>/dev/null | sed 's|:||g' | grep -Fw -- " ${1:-$SERVICE_NAME}$" || return 10
}
__is_dir_empty() {
[ -n "$1" ] && [ -d "$1" ] || return 1
@@ -138,7 +140,7 @@ __pgrep() {
while [ $count -ge 0 ]; do
pgrep -x "$srvc" &>/dev/null && return 0
pgrep -f "$srvc" &>/dev/null && return 0
ps -eo comm 2>/dev/null | grep -qxF "$srvc" && return 0
ps -eo comm 2>/dev/null | grep -qxF -- "$srvc" && return 0
[ $count -gt 0 ] && sleep 1
count=$((count - 1))
done
@@ -166,7 +168,7 @@ __is_running() {
if command -v pgrep &>/dev/null; then
pgrep -f "$pat" &>/dev/null
else
ps -eo args 2>/dev/null | grep -v grep | grep -Eq "$pat"
ps -eo args 2>/dev/null | grep -v -- grep | grep -Eq -- "$pat"
fi
}
__get_pid() {
@@ -205,19 +207,34 @@ __no_exit() {
local failed_services=""
local failure_count=0
# only return early if the recorded PID is still alive; a leftover
# pid file from a prior container life (docker restart) would otherwise
# cause us to exit instead of entering the monitor loop.
# only return early if the recorded PID is still alive AND it is actually
# this same monitor loop (not just some unrelated process that happens to
# have been assigned the same number). /run persists across `docker
# restart` (same container filesystem), but the PID namespace resets on
# every restart, so a low PID recorded before the restart can coincidentally
# be reused by an unrelated early-boot process within the new namespace. A
# bare `kill -0` on that number alone would then wrongly report the old
# monitor as still running and `return 0` here without ever exec'ing the
# replacement monitor loop below — silently leaving the container with no
# supervisor loop, so it exits as soon as the caller's own script reaches
# its end. Guarding on the "__no_exit_monitor_loop" marker (embedded in the
# exec'd bash -c command below, so it shows up in that PID's own cmdline)
# confirms the live process is actually this monitor, not a coincidental
# PID-reuse false positive.
if [ -f "/run/.no_exit.pid" ]; then
local no_exit_pid
no_exit_pid=$(<"/run/.no_exit.pid") 2>/dev/null
if [ -n "$no_exit_pid" ] && kill -0 "$no_exit_pid" 2>/dev/null; then
if [ -n "$no_exit_pid" ] && kill -0 "$no_exit_pid" 2>/dev/null \
&& grep -q -- "__no_exit_monitor_loop" "/proc/$no_exit_pid/cmdline" 2>/dev/null; then
return 0
fi
rm -f /run/.no_exit.pid 2>/dev/null || true
fi
exec bash -c "
# __no_exit_monitor_loop marker: identifies this process's cmdline as the
# genuine monitor loop, so a future __no_exit call can tell it apart from
# an unrelated process that coincidentally reused this PID after a restart
trap 'echo \"Container shutdown requested\"; rm -f /run/.no_exit.pid /run/*.pid; exit 0' TERM INT
echo \$\$ > /run/.no_exit.pid
failed_services=\"\"
@@ -267,7 +284,8 @@ __banner() {
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
__service_banner() {
local icon="${1:-🔧}"
local icon="${1:-}"
[ -z "$icon" ] && icon="$( [ -z "$NO_COLOR" ] && echo "🔧" || echo "" )"
local message="${2:-Processing}"
local service="${3:-service}"
local full_message="$message $service"
@@ -682,7 +700,7 @@ __file_copy() {
__generate_random_uids() {
local set_random_uid=$((100 + RANDOM % 900))
while :; do
if grep -shq "x:.*:$set_random_uid:" "/etc/group" && ! grep -shq "x:$set_random_uid:.*:" "/etc/passwd"; then
if grep -shq -- "x:.*:$set_random_uid:" "/etc/group" && ! grep -shq -- "x:$set_random_uid:.*:" "/etc/passwd"; then
set_random_uid=$((set_random_uid + 1))
else
echo "$set_random_uid"
@@ -738,7 +756,7 @@ __fix_permissions() {
change_group="${2:-${SERVICE_GROUP:-$change_user}}"
[ -n "$RUNAS_USER" ] && [ "$RUNAS_USER" != "root" ] && change_user="$RUNAS_USER" && change_group="$change_user"
if [ -n "$change_user" ]; then
if grep -shq "^$change_user:" "/etc/passwd"; then
if grep -shq -- "^$change_user:" "/etc/passwd"; then
for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
chown -Rf "$change_user" "$permissions" 2>/dev/null
@@ -748,7 +766,7 @@ __fix_permissions() {
fi
fi
if [ -n "$change_group" ]; then
if grep -shq "^$change_group:" "/etc/group"; then
if grep -shq -- "^$change_group:" "/etc/group"; then
for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
chgrp -Rf "$change_group" "$permissions" 2>/dev/null
@@ -809,7 +827,7 @@ __set_user_group_id() {
return 0
fi
# Nothing to do if the user does not exist yet
if ! grep -shq "^$set_user:" "/etc/passwd" "/etc/group"; then
if ! grep -shq -- "^$set_user:" "/etc/passwd" "/etc/group"; then
return 0
fi
set_uid="$(__get_uid "$set_user" || echo "$set_uid")"
@@ -852,7 +870,7 @@ __create_service_user() {
return 1
fi
# Check if user and group already exist
if grep -shq "^$create_user:" "/etc/passwd" && grep -shq "^$create_group:" "/etc/group"; then
if grep -shq -- "^$create_user:" "/etc/passwd" && grep -shq -- "^$create_group:" "/etc/group"; then
return 0
fi
# Override with RUNAS_USER if specified and not root
@@ -898,7 +916,7 @@ __create_service_user() {
if ! groupadd --force --system -g "$create_gid" "$create_group" 2>&1 | tee -a "$log_file"; then
echo "Error: Failed to create group '$create_group'" >&2
exitStatus=$((exitStatus + 1))
elif ! grep -shq "^$create_group:" "/etc/group"; then
elif ! grep -shq -- "^$create_group:" "/etc/group"; then
echo "Error: Group '$create_group' not found in /etc/group after creation" >&2
exitStatus=$((exitStatus + 1))
fi
@@ -906,10 +924,12 @@ __create_service_user() {
# Create user if needed (only if group creation succeeded)
if [ $exitStatus -eq 0 ] && [ -n "$create_user" ] && ! __check_for_user "$create_user"; then
echo "Creating system user '$create_user' with UID $create_uid"
if ! useradd --system --uid "$create_uid" --gid "$create_group" --comment "Account for $create_user" --home-dir "$create_home_dir" --shell /bin/false "$create_user" 2>&1 | tee -a "$log_file"; then
if ! useradd --system --uid "$create_uid" --gid "$create_group" \
--comment "Account for $create_user" --home-dir "$create_home_dir" \
--shell /bin/false "$create_user" 2>&1 | tee -a "$log_file"; then
echo "Error: Failed to create user '$create_user'" >&2
exitStatus=$((exitStatus + 1))
elif ! grep -shq "^$create_user:" "/etc/passwd"; then
elif ! grep -shq -- "^$create_user:" "/etc/passwd"; then
echo "Error: User '$create_user' not found in /etc/passwd after creation" >&2
exitStatus=$((exitStatus + 1))
fi
@@ -933,7 +953,7 @@ __create_service_user() {
echo "$create_user ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/$create_user" 2>/dev/null || echo "Warning: Failed to create sudoers file for '$create_user'" >&2
chmod 0440 "/etc/sudoers.d/$create_user" 2>/dev/null
fi
elif [ -f "/etc/sudoers" ] && ! grep -qs "^$create_user " "/etc/sudoers"; then
elif [ -f "/etc/sudoers" ] && ! grep -qs -- "^$create_user " "/etc/sudoers"; then
echo "$create_user ALL=(ALL) NOPASSWD: ALL" >>"/etc/sudoers" 2>/dev/null || echo "Warning: Failed to add '$create_user' to sudoers" >&2
fi
SERVICE_UID="$create_uid"
@@ -1030,7 +1050,7 @@ __start_init_scripts() {
touch "$pidFile"
name="${init##*/}"
service="${name#*-}"; service="${service%.sh}"
[ "$DEBUGGER" = "on" ] && __service_banner "🔧" "Executing service script:" "${init##*/}" || true
[ "$DEBUGGER" = "on" ] && __service_banner "$( [ -z "$NO_COLOR" ] && echo "🔧" || echo "" )" "Executing service script:" "${init##*/}" || true
# Execute the init script and capture the exit code (subshell isolates exit calls)
if ( source "$init" ); then
# Check if service was disabled first
@@ -1093,7 +1113,7 @@ __start_init_scripts() {
else
initStatus="1"
critical_failures=$((critical_failures + 1))
__service_banner "" "Service $service failed to start -" "check logs"
__service_banner "$( [ -z "$NO_COLOR" ] && echo "❌" || echo "" )" "Service $service failed to start -" "check logs"
fi
echo ""
fi
@@ -1103,12 +1123,24 @@ __start_init_scripts() {
# Summary
echo ""
if [ $critical_failures -gt 0 ]; then
echo "⚠️ Warning: $critical_failures critical service(s) reported failures"
if [ -z "$NO_COLOR" ]; then
echo "⚠️ Warning: $critical_failures critical service(s) reported failures"
else
echo "Warning: $critical_failures critical service(s) reported failures"
fi
if [ "$exit_on_failure" = "true" ] && [ $critical_failures -ge 2 ]; then
echo "❌ Exiting due to multiple critical service failures (threshold: 2)"
if [ -z "$NO_COLOR" ]; then
echo "❌ Exiting due to multiple critical service failures (threshold: 2)"
else
echo "Exiting due to multiple critical service failures (threshold: 2)"
fi
return 1
else
echo "️ Continuing with $critical_failures failure(s) - container may still be functional"
if [ -z "$NO_COLOR" ]; then
echo "️ Continuing with $critical_failures failure(s) - container may still be functional"
else
echo "Continuing with $critical_failures failure(s) - container may still be functional"
fi
fi
else
echo "✅ All service initializations completed successfully"
@@ -1516,22 +1548,22 @@ __switch_to_user() {
local switch_user="${SERVICE_USER:-$RUNAS_USER}"
if [ "$switch_user" = "root" ]; then
su_exec=""
su_cmd() { eval "$@" || return 1; }
__su_cmd() { eval "$@" || return 1; }
elif command -v gosu &>/dev/null; then
su_exec="gosu $switch_user"
su_cmd() { $su_exec "$@" || return 1; }
__su_cmd() { $su_exec "$@" || return 1; }
elif command -v runuser &>/dev/null; then
su_exec="runuser -u $switch_user"
su_cmd() { $su_exec "$@" || return 1; }
__su_cmd() { $su_exec "$@" || return 1; }
elif command -v sudo &>/dev/null; then
su_exec="sudo -u $switch_user"
su_cmd() { $su_exec "$@" || return 1; }
__su_cmd() { $su_exec "$@" || return 1; }
elif command -v su &>/dev/null; then
su_exec="su -s /bin/sh - $switch_user"
su_cmd() { $su_exec -c "$@" || return 1; }
__su_cmd() { $su_exec -c "$@" || return 1; }
else
su_exec=""
su_cmd() {
__su_cmd() {
echo "Can not switch to $switch_user: attempting to run as root"
if ! eval "$@"; then
return 1
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261600-git
##@Version : 202609030524-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : LICENSE.md
@@ -20,6 +20,8 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202609030524-git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
set -e
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run trap command on exit
@@ -43,7 +45,11 @@ __trap_err_handler() {
fi
# Critical error - but only fail if service hasn't started yet
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
if [ -z "$NO_COLOR" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
else
echo "Critical error (exit $retVal): $command" >&2
fi
kill -TERM 1 2>/dev/null || exit $retVal
fi
return 0
@@ -108,7 +114,11 @@ fi
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
if [ -z "$NO_COLOR" ]; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
else
echo "Removing stale PID file for $SERVICE_NAME"
fi
rm -f "/run/init.d/$SERVICE_NAME.pid"
fi
fi
@@ -275,7 +285,7 @@ __run_precopy() {
ln -sf "$CONF_DIR" "$ETC_DIR"
fi
# allow custom functions
if builtin type -t __run_precopy_local | grep -q 'function'; then __run_precopy_local; fi
if builtin type -t __run_precopy_local | grep -q -- 'function'; then __run_precopy_local; fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom prerun functions - IE setup WWW_ROOT_DIR
@@ -285,7 +295,7 @@ __execute_prerun() {
# Define actions/commands
# allow custom functions
if builtin type -t __execute_prerun_local | grep -q 'function'; then __execute_prerun_local; fi
if builtin type -t __execute_prerun_local | grep -q -- 'function'; then __execute_prerun_local; fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Run any pre-execution checks
@@ -370,6 +380,17 @@ __run_pre_execute_checks() {
echo "Warning: cgroup v2 not available, Docker-in-Docker may have limited functionality"
fi
# Remove a stale dockerd pidfile before starting
# /tmp persists across `docker restart` (same container filesystem), but the PID
# namespace is reset on every restart, so a low PID number like the one dockerd
# wrote last time can coincidentally be reused by an unrelated process very early
# in the new namespace. dockerd's own startup check then sees /proc/<pid> exists
# and refuses to start with "process with PID <n> is still running", even though
# it is not actually the previous dockerd. This init script is the sole owner of
# the dockerd lifecycle (enforced separately via SERVICE_PID_FILE), so it is always
# safe to clear docker's own pidfile here before each start attempt.
[ -f "/tmp/docker.pid" ] && rm -f "/tmp/docker.pid"
# Clean up orphaned containers before dockerd starts
# This prevents "failed to load container" errors on restart
if [ -d "/data/docker/containers" ]; then
@@ -392,7 +413,7 @@ __run_pre_execute_checks() {
for get_reg in $DOCKER_REGISTRIES; do
set_reg+="\"$get_reg\" "
done
registry="$(printf '%s\n' "$set_reg" | tr ' ' '\n' | sort -V | grep -v '^$' | tr '\n' ',' | sed 's|,$||g;s| ||g' | grep '^')"
registry="$(printf '%s\n' "$set_reg" | tr ' ' '\n' | sort -V | grep -v -- '^$' | tr '\n' ',' | sed 's|,$||g;s| ||g' | grep -E -- '^')"
export registry
else
unset registry
@@ -425,6 +446,7 @@ EOF
"experimental": true,
"pidfile": "/tmp/docker.pid",
"cgroup-parent": "/docker",
"storage-driver": "fuse-overlayfs",
"default-address-pools": [
{"base": "172.17.0.0/12", "size": 24},
{"base": "192.168.0.0/16", "size": 24},
@@ -442,6 +464,7 @@ EOF
"experimental": true,
"pidfile": "/tmp/docker.pid",
"cgroup-parent": "/docker",
"storage-driver": "fuse-overlayfs",
"default-address-pools": [
{"base": "172.17.0.0/12", "size": 24},
{"base": "192.168.0.0/16", "size": 24},
@@ -463,7 +486,7 @@ EOF
__script_exit 1
fi
# allow custom functions
if builtin type -t __run_pre_execute_checks_local | grep -q 'function'; then __run_pre_execute_checks_local; fi
if builtin type -t __run_pre_execute_checks_local | grep -q -- 'function'; then __run_pre_execute_checks_local; fi
# exit function
return $exitStatus
}
@@ -489,12 +512,12 @@ __update_conf_files() {
# - - - - - - - - - - - - - - - - - - - - - - - - -
# define actions
symlink "$DATA_DIR" "/var/lib/docker"
__symlink "$DATA_DIR" "/var/lib/docker"
chmod 777 "$DATA_DIR" "/var/lib/docker"
# Mark config as fully initialised so __run_precopy skips re-seeding on restart
touch "$CONF_DIR/.initialized" 2>/dev/null || true
# allow custom functions
if builtin type -t __update_conf_files_local | grep -q 'function'; then __update_conf_files_local; fi
if builtin type -t __update_conf_files_local | grep -q -- 'function'; then __update_conf_files_local; fi
# exit function
return $exitCode
}
@@ -516,7 +539,7 @@ __pre_execute() {
# Lets wait a few seconds before continuing
sleep 2
# allow custom functions
if builtin type -t __pre_execute_local | grep -q 'function'; then __pre_execute_local; fi
if builtin type -t __pre_execute_local | grep -q -- 'function'; then __pre_execute_local; fi
# exit function
return $exitCode
}
@@ -549,7 +572,7 @@ __post_execute() {
# fire-and-forget: backgrounded subshell always succeeds at launch
retVal=0
# allow custom functions
if builtin type -t __post_execute_local | grep -q 'function'; then __post_execute_local; fi
if builtin type -t __post_execute_local | grep -q -- 'function'; then __post_execute_local; fi
# exit function
return $retVal
}
@@ -561,7 +584,7 @@ __pre_message() {
# execute commands
# allow custom functions
if builtin type -t __pre_message_local | grep -q 'function'; then __pre_message_local; fi
if builtin type -t __pre_message_local | grep -q -- 'function'; then __pre_message_local; fi
# exit function
return $exitCode
}
@@ -574,7 +597,7 @@ __update_ssl_conf() {
# execute commands
# allow custom functions
if builtin type -t __update_ssl_conf_local | grep -q 'function'; then __update_ssl_conf_local; fi
if builtin type -t __update_ssl_conf_local | grep -q -- 'function'; then __update_ssl_conf_local; fi
# set exitCode
return $exitCode
}
@@ -696,7 +719,7 @@ __run_start_script() {
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
fi
__log_info "$message" | tee -a -p "/data/logs/init.txt"
su_cmd touch "$SERVICE_PID_FILE"
__su_cmd touch "$SERVICE_PID_FILE"
# W14: invalidate cached START_SCRIPT if key variables changed
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
local _script_hash
+21 -12
View File
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606261600-git
##@Version : 202609030601-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : LICENSE.md
@@ -20,6 +20,7 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202609030601-git"
set -e
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run trap command on exit
@@ -43,7 +44,11 @@ __trap_err_handler() {
fi
# Critical error - but only fail if service hasn't started yet
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
if [ -z "$NO_COLOR" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
else
echo "Critical error (exit $retVal): $command" >&2
fi
kill -TERM 1 2>/dev/null || exit $retVal
fi
return 0
@@ -108,7 +113,11 @@ fi
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
if [ -z "$NO_COLOR" ]; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
else
echo "Removing stale PID file for $SERVICE_NAME"
fi
rm -f "/run/init.d/$SERVICE_NAME.pid"
fi
fi
@@ -320,7 +329,7 @@ __run_precopy() {
ln -sf "$CONF_DIR" "$ETC_DIR"
fi
# allow custom functions
if builtin type -t __run_precopy_local | grep -q 'function'; then __run_precopy_local; fi
if builtin type -t __run_precopy_local | grep -q -- 'function'; then __run_precopy_local; fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom prerun functions - IE setup WWW_ROOT_DIR
@@ -330,7 +339,7 @@ __execute_prerun() {
# Define actions/commands
# allow custom functions
if builtin type -t __execute_prerun_local | grep -q 'function'; then __execute_prerun_local; fi
if builtin type -t __execute_prerun_local | grep -q -- 'function'; then __execute_prerun_local; fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Run any pre-execution checks
@@ -356,7 +365,7 @@ __run_pre_execute_checks() {
__script_exit 1
fi
# allow custom functions
if builtin type -t __run_pre_execute_checks_local | grep -q 'function'; then __run_pre_execute_checks_local; fi
if builtin type -t __run_pre_execute_checks_local | grep -q -- 'function'; then __run_pre_execute_checks_local; fi
# exit function
return $exitStatus
}
@@ -441,7 +450,7 @@ __update_conf_files() {
touch "$CONF_DIR/.initialized" 2>/dev/null || true
# allow custom functions
if builtin type -t __update_conf_files_local | grep -q 'function'; then __update_conf_files_local; fi
if builtin type -t __update_conf_files_local | grep -q -- 'function'; then __update_conf_files_local; fi
# exit function
return $exitCode
}
@@ -463,7 +472,7 @@ __pre_execute() {
# Lets wait a few seconds before continuing
sleep 2
# allow custom functions
if builtin type -t __pre_execute_local | grep -q 'function'; then __pre_execute_local; fi
if builtin type -t __pre_execute_local | grep -q -- 'function'; then __pre_execute_local; fi
# exit function
return $exitCode
}
@@ -496,7 +505,7 @@ __post_execute() {
# fire-and-forget: backgrounded subshell always succeeds at launch
retVal=0
# allow custom functions
if builtin type -t __post_execute_local | grep -q 'function'; then __post_execute_local; fi
if builtin type -t __post_execute_local | grep -q -- 'function'; then __post_execute_local; fi
# exit function
return $retVal
}
@@ -508,7 +517,7 @@ __pre_message() {
# execute commands
# allow custom functions
if builtin type -t __pre_message_local | grep -q 'function'; then __pre_message_local; fi
if builtin type -t __pre_message_local | grep -q -- 'function'; then __pre_message_local; fi
# exit function
return $exitCode
}
@@ -521,7 +530,7 @@ __update_ssl_conf() {
# execute commands
# allow custom functions
if builtin type -t __update_ssl_conf_local | grep -q 'function'; then __update_ssl_conf_local; fi
if builtin type -t __update_ssl_conf_local | grep -q -- 'function'; then __update_ssl_conf_local; fi
# set exitCode
return $exitCode
}
@@ -643,7 +652,7 @@ __run_start_script() {
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
fi
__log_info "$message" | tee -a -p "/data/logs/init.txt"
su_cmd touch "$SERVICE_PID_FILE"
__su_cmd touch "$SERVICE_PID_FILE"
# W14: invalidate cached START_SCRIPT if key variables changed
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
local _script_hash
@@ -1,7 +1,7 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202608031200-git
##@Version : 202609030534-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : LICENSE.md
@@ -20,7 +20,7 @@
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
VERSION="202608031200-git"
VERSION="202609030534-git"
set -e
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run trap command on exit
@@ -44,7 +44,11 @@ __trap_err_handler() {
fi
# Critical error - but only fail if service hasn't started yet
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
if [ -z "$NO_COLOR" ]; then
echo "❌ Critical error (exit $retVal): $command" >&2
else
echo "Critical error (exit $retVal): $command" >&2
fi
kill -TERM 1 2>/dev/null || exit $retVal
fi
return 0
@@ -109,7 +113,11 @@ fi
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
if [ -z "$NO_COLOR" ]; then
echo "🧹 Removing stale PID file for $SERVICE_NAME"
else
echo "Removing stale PID file for $SERVICE_NAME"
fi
rm -f "/run/init.d/$SERVICE_NAME.pid"
fi
fi
@@ -132,7 +140,10 @@ __gen_auth_token() {
if [ -z "$auth_token" ] && [ -n "$gitea_bin" ] && [ -n "$conf_file" ]; then
# Only attempt token generation if gitea is fully installed (INSTALL_LOCK = true)
if grep -qiE -- 'INSTALL_LOCK\s*=\s*true' "$conf_file" 2>/dev/null; then
auth_token="$(gosu $user $gitea_bin --config "$conf_file" --work-path /data/gitea --custom-path /config/gitea/custom actions generate-runner-token 2>/dev/null | grep -oE -- '[A-Za-z0-9]{20,}' | tail -n1)"
auth_token="$( gosu $user $gitea_bin --config "$conf_file" \
--work-path /data/gitea --custom-path /config/gitea/custom \
actions generate-runner-token 2>/dev/null | \
grep -oE -- '[A-Za-z0-9]{20,}' | tail -n1 )"
fi
fi
if [ -n "$auth_token" ]; then
@@ -317,7 +328,10 @@ RUNNER_LABELS+="act_runner:docker://catthehacker/ubuntu:full-latest,"
RUNNER_LABELS+="ubuntu-latest:docker://catthehacker/ubuntu:full-latest"
unset _HOST_ARCH _ARCH_LABEL
# - - - - - - - - - - - - - - - - - - - - - - - - -
RUNNER_IP_ADDRESS="${RUNNER_IP_ADDRESS:-$IP4_ADDRESS}"
# act_runner registers against gitea in the same container/network namespace, so use
# loopback rather than the detected external IP4_ADDRESS (which can be transient/wrong
# under Docker-in-Docker networking and caused "no route to host" registration failures)
RUNNER_IP_ADDRESS="${RUNNER_IP_ADDRESS:-127.0.0.1}"
RUNNER_CONFIG_DEFAULT="${RUNNER_CONFIG_DEFAULT:-$CONF_DIR/default_config.yaml}"
RUNNER_DEFAULT_HOME="${RUNNER_DEFAULT_HOME:-$CONF_DIR/gitea}"
RUNNER_CONFIG_NAME="${RUNNER_CONFIG_NAME:-act_runner.yaml}"
@@ -416,11 +430,9 @@ __run_pre_execute_checks() {
__replace "REPLACE_RUNNER_CACHE_HOST" "$RUNNER_CACHE_HOST" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME"
__replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME"
__replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME"
if [ ! -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -n "$SYS_AUTH_TOKEN" ]; then
echo "creating gitea runner in $RUNNER_DEFAULT_HOME and registering with http://$INSTANCE_HOSTNAME"
act_runner register --config "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" --labels "$RUNNER_LABELS" --name "gitea" --instance "http://$RUNNER_IP_ADDRESS:$GITEA_PORT" --token "$SYS_AUTH_TOKEN" --no-interactive >>"$RUNNER_LOG_FILE" 2>&1 &
echo $! >"$RUN_DIR/act_runner.gitea.pid"
fi
# Legacy single "gitea"-named runner registration removed: start-runners
# (invoked from __post_execute) now owns all runner registration/count via
# RUNNERS_START, and registering a second runner here duplicated it
fi
exitStatus="${exitStatus:-0}"
chown -Rf "$SERVICE_USER":"$SERVICE_GROUP" "$CONF_DIR" "$ETC_DIR" "$DATA_DIR" 2>/dev/null
@@ -518,29 +530,25 @@ __post_execute() {
(
# show message
__banner "$postMessageST"
# commands to execute
if [ -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -f "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" ]; then
act_runner daemon --config "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" >>"$RUNNER_DAEMON_LOG" 2>/dev/stderr &
pid=$!
sleep 5
if ps ax | awk '{print $1}' | grep -v -- 'grep' | grep -q -- "$pid$"; then
echo "$(date)" >"$CONF_DIR/.runner"
echo "$pid" >"$RUN_DIR/act_runner.gitea.pid"
echo "Runner: gitea has been started with pid: $pid" | tee -a -p "$LOG_DIR/init.txt"
else
echo "Runner: gitea has failed to start" >/dev/stderr
[ -f "$RUN_DIR/act_runner.gitea.pid" ] && rm -f "$RUN_DIR/act_runner.gitea.pid"
fi
unset pid
fi
# Legacy single "gitea"-named runner daemon start removed: start-runners
# (below) now owns all runner registration/daemon startup via RUNNERS_START
#
if [ -f "$CACHE_CONFIG_FILE" ]; then
mkdir -p "$DATA_DIR/cache"
__replace "REPLACE_RUNNER_CACHE_DIR" "$DATA_DIR/cache" "$CACHE_CONFIG_FILE"
__replace "REPLACE_RUNNER_CACHE_PORT" "$RUNNER_CACHE_PORT" "$CACHE_CONFIG_FILE"
__replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$CACHE_CONFIG_FILE"
act_runner cache-server --config "$CACHE_CONFIG_FILE" 2>>/dev/stderr >>"$CACHE_LOG_FILE" &
# stdout/stderr are redirected to a real file here (not inherited from the
# __post_execute pipe) because cache-server is a long-running process that
# never exits; if it inherited the pipe's write end, the tee reading it
# would never see EOF and __run_start_script would hang forever (same
# fd-leak class as the start-runners fix below)
act_runner cache-server --config "$CACHE_CONFIG_FILE" >>"$CACHE_LOG_FILE" 2>&1 &
execPid=$!
# disown so this long-running background job is fully detached from this
# subshell's job table; otherwise bash can block waiting on it when this
# subshell (itself the left side of the __post_execute pipe) reaches its end
disown "$execPid" 2>/dev/null || true
sleep 5
if ps ax | awk '{print $1}' | grep -v -- 'grep' | grep -q -- "$execPid$"; then
echo "Cache server has been started and is listening on $RUNNER_CACHE_PORT"
@@ -549,7 +557,17 @@ __post_execute() {
fi
unset pid
fi
[ -x "/usr/local/bin/start-runners" ] && /usr/local/bin/start-runners &
# stdout/stderr are redirected to a real file here (not inherited from the
# __post_execute pipe) because start-runners execs long-running act_runner
# daemons that never exit; if they inherited the pipe's write end, the
# tee reading it would never see EOF and __run_start_script would hang forever
if [ -x "/usr/local/bin/start-runners" ]; then
/usr/local/bin/start-runners >>"$LOG_DIR/runners.log" 2>&1 &
# disown so this long-running background job is fully detached from this
# subshell's job table; otherwise bash can block waiting on it when this
# subshell (itself the left side of the __post_execute pipe) reaches its end
disown "$!" 2>/dev/null || true
fi
# show exit message
__banner "$postMessageEnd: Status $retVal"
) 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
@@ -703,7 +721,7 @@ __run_start_script() {
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
fi
__log_info "$message" | tee -a -p "/data/logs/init.txt"
su_cmd touch "$SERVICE_PID_FILE"
__su_cmd touch "$SERVICE_PID_FILE"
# W14: invalidate cached START_SCRIPT if key variables changed
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
local _script_hash
@@ -1027,7 +1045,8 @@ if [ -n "$EXEC_CMD_BIN" ]; then
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# start the post execute function in background
__post_execute 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
# EXEC_CMD_BIN is empty for this service, so __run_start_script already invoked
# __post_execute internally (its empty-cmd branch); calling it again here would
# duplicate runner registration/daemon startup
# - - - - - - - - - - - - - - - - - - - - - - - - -
__script_exit $SERVICE_EXIT_CODE