mirror of
https://github.com/casjaysdevdocker/gitea
synced 2026-09-04 02:03:00 -04:00
🔧 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:
@@ -5,6 +5,7 @@
|
|||||||
"experimental": true,
|
"experimental": true,
|
||||||
"pidfile": "/tmp/docker.pid",
|
"pidfile": "/tmp/docker.pid",
|
||||||
"cgroup-parent": "/docker",
|
"cgroup-parent": "/docker",
|
||||||
|
"storage-driver": "fuse-overlayfs",
|
||||||
"default-address-pools": [
|
"default-address-pools": [
|
||||||
{"base": "172.17.0.0/12", "size": 24},
|
{"base": "172.17.0.0/12", "size": 24},
|
||||||
{"base": "192.168.0.0/16", "size": 24},
|
{"base": "192.168.0.0/16", "size": 24},
|
||||||
|
|||||||
@@ -200,6 +200,12 @@ REVERSE_PROXY_AUTHENTICATION_USER = X-WEBAUTH-USER
|
|||||||
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
|
REVERSE_PROXY_AUTHENTICATION_EMAIL = X-WEBAUTH-EMAIL
|
||||||
REVERSE_PROXY_AUTHENTICATION_FULL_NAME = X-WEBAUTH-FULLNAME
|
REVERSE_PROXY_AUTHENTICATION_FULL_NAME = X-WEBAUTH-FULLNAME
|
||||||
X_FRAME_OPTIONS = SAMEORIGIN
|
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]
|
[time]
|
||||||
DEFAULT_UI_LOCATION = REPLACE_TZ
|
DEFAULT_UI_LOCATION = REPLACE_TZ
|
||||||
@@ -224,7 +230,6 @@ http.sslVerify = false
|
|||||||
[webhook]
|
[webhook]
|
||||||
QUEUE_LENGTH = 1000
|
QUEUE_LENGTH = 1000
|
||||||
DELIVER_TIMEOUT = 30
|
DELIVER_TIMEOUT = 30
|
||||||
ALLOWED_HOST_LIST = *
|
|
||||||
SKIP_TLS_VERIFY = true
|
SKIP_TLS_VERIFY = true
|
||||||
PAGING_NUM = 10
|
PAGING_NUM = 10
|
||||||
PROXY_URL =
|
PROXY_URL =
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202606261500-git
|
##@Version : 202609030524-git
|
||||||
# @@Author : Jason Hempstead
|
# @@Author : Jason Hempstead
|
||||||
# @@Contact : jason@casjaysdev.pro
|
# @@Contact : jason@casjaysdev.pro
|
||||||
# @@License : WTFPL
|
# @@License : WTFPL
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
VERSION="202609030524-git"
|
||||||
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# run trap command on exit
|
# 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' INT TERM
|
||||||
trap 'retVal=$?;[ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE";exit $retVal' SIGPWR 2>/dev/null || true
|
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 ipv6 add it to /etc/hosts
|
||||||
if [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
|
if [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
|
||||||
echo "# known hostname mappings" >"/etc/hosts" 2>/dev/null || true
|
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" "::1" "localhost" >>"/etc/hosts" 2>/dev/null || true
|
||||||
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
|
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
|
||||||
else
|
else
|
||||||
@@ -371,7 +373,7 @@ if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# import hosts file into container
|
# import hosts file into container
|
||||||
if [ -f "/usr/local/etc/hosts" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
|
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
|
fi
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# import resolv.conf file into container
|
# import resolv.conf file into container
|
||||||
@@ -431,9 +433,16 @@ fi
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# if no pid assume container restart - clean stale files on restart
|
# if no pid assume container restart - clean stale files on restart
|
||||||
if [ -f "$ENTRYPOINT_PID_FILE" ]; then
|
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
|
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
|
# Process is still running, don't restart services
|
||||||
START_SERVICES="no"
|
START_SERVICES="no"
|
||||||
touch "$ENTRYPOINT_PID_FILE"
|
touch "$ENTRYPOINT_PID_FILE"
|
||||||
@@ -550,7 +559,7 @@ cron)
|
|||||||
shift 1
|
shift 1
|
||||||
__cron "$@" &
|
__cron "$@" &
|
||||||
__log_info "Cron script is running with PID: $!"
|
__log_info "Cron script is running with PID: $!"
|
||||||
exit
|
exit 0
|
||||||
;;
|
;;
|
||||||
# backup data and config dirs
|
# backup data and config dirs
|
||||||
backup)
|
backup)
|
||||||
@@ -581,7 +590,7 @@ healthcheck)
|
|||||||
services+="$name "
|
services+="$name "
|
||||||
done
|
done
|
||||||
fi
|
fi
|
||||||
services="$(printf '%s\n' $services | sort -u | grep -v '^$')"
|
services="$(printf '%s\n' $services | sort -u | grep -v -- '^$')"
|
||||||
for proc in $services; do
|
for proc in $services; do
|
||||||
if [ -n "$proc" ]; then
|
if [ -n "$proc" ]; then
|
||||||
if ! __pgrep "$proc"; then
|
if ! __pgrep "$proc"; then
|
||||||
@@ -592,7 +601,7 @@ healthcheck)
|
|||||||
done
|
done
|
||||||
for port in $healthPorts; do
|
for port in $healthPorts; do
|
||||||
if command -v netstat &>/dev/null && [ -n "$port" ]; then
|
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
|
echo "$port isn't open" >&2
|
||||||
healthStatus=$((healthStatus + 1))
|
healthStatus=$((healthStatus + 1))
|
||||||
fi
|
fi
|
||||||
@@ -622,7 +631,7 @@ ports)
|
|||||||
# show running processes
|
# show running processes
|
||||||
procs)
|
procs)
|
||||||
shift 1
|
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' ' '
|
[ -n "$ps" ] && printf '%s\n%s\n' "Found the following processes" "$ps" | tr '\n' ' '
|
||||||
exit $?
|
exit $?
|
||||||
;;
|
;;
|
||||||
@@ -659,7 +668,7 @@ start)
|
|||||||
if [ $# -eq 0 ]; then
|
if [ $# -eq 0 ]; then
|
||||||
scripts="$(ls -A "/usr/local/etc/docker/init.d")"
|
scripts="$(ls -A "/usr/local/etc/docker/init.d")"
|
||||||
[ -n "$scripts" ] && echo "$scripts" || echo "No scripts found in: /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
|
elif [ "$1" = "all" ]; then
|
||||||
shift $#
|
shift $#
|
||||||
if [ "$START_SERVICES" = "yes" ]; then
|
if [ "$START_SERVICES" = "yes" ]; then
|
||||||
|
|||||||
@@ -1,8 +1,31 @@
|
|||||||
#!/usr/bin/env bash
|
#!/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
|
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
|
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
|
# Function to __log messages with timestamp
|
||||||
@@ -33,7 +56,37 @@ if [ -z "$SERVER_TOKEN" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
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
|
# Determine number of runners to start
|
||||||
RUNNERS_START=${RUNNERS_START:-1}
|
RUNNERS_START=${RUNNERS_START:-1}
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202607271325-git
|
##@Version : 202609030524-git
|
||||||
# @@Author : Jason Hempstead
|
# @@Author : Jason Hempstead
|
||||||
# @@Contact : git-admin@casjaysdev.pro
|
# @@Contact : git-admin@casjaysdev.pro
|
||||||
# @@License : LICENSE.md
|
# @@License : LICENSE.md
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
# 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
|
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
|
||||||
if [ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ]; then
|
if [ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ]; then
|
||||||
export DEBUGGER_OPTIONS="$(<"/config/.debug")"
|
export DEBUGGER_OPTIONS="$(<"/config/.debug")"
|
||||||
@@ -77,7 +79,7 @@ __rm() {
|
|||||||
fi
|
fi
|
||||||
return 0
|
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() {
|
__netstat() {
|
||||||
command -v netstat &>/dev/null || {
|
command -v netstat &>/dev/null || {
|
||||||
[ "$DEBUGGER" = "on" ] && echo "Warning: netstat command not found" >&2 || true
|
[ "$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
|
[ -d "$1" ] || mkdir -p "$1" 2>/dev/null || return 1
|
||||||
builtin cd "$1" || 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; }
|
__curl() { curl -q -sfI --max-time 3 -k -o /dev/null "$@" 2>/dev/null || return 10; }
|
||||||
__find() {
|
__find() {
|
||||||
local result
|
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; }
|
__sed() { sed -i "s|$1|$2|g" "$3" 2>/dev/null || return 1; }
|
||||||
__ps() {
|
__ps() {
|
||||||
command -v ps &>/dev/null || return 10
|
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() {
|
__is_dir_empty() {
|
||||||
[ -n "$1" ] && [ -d "$1" ] || return 1
|
[ -n "$1" ] && [ -d "$1" ] || return 1
|
||||||
@@ -138,7 +140,7 @@ __pgrep() {
|
|||||||
while [ $count -ge 0 ]; do
|
while [ $count -ge 0 ]; do
|
||||||
pgrep -x "$srvc" &>/dev/null && return 0
|
pgrep -x "$srvc" &>/dev/null && return 0
|
||||||
pgrep -f "$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 -gt 0 ] && sleep 1
|
||||||
count=$((count - 1))
|
count=$((count - 1))
|
||||||
done
|
done
|
||||||
@@ -166,7 +168,7 @@ __is_running() {
|
|||||||
if command -v pgrep &>/dev/null; then
|
if command -v pgrep &>/dev/null; then
|
||||||
pgrep -f "$pat" &>/dev/null
|
pgrep -f "$pat" &>/dev/null
|
||||||
else
|
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
|
fi
|
||||||
}
|
}
|
||||||
__get_pid() {
|
__get_pid() {
|
||||||
@@ -205,19 +207,34 @@ __no_exit() {
|
|||||||
local failed_services=""
|
local failed_services=""
|
||||||
local failure_count=0
|
local failure_count=0
|
||||||
|
|
||||||
# only return early if the recorded PID is still alive; a leftover
|
# only return early if the recorded PID is still alive AND it is actually
|
||||||
# pid file from a prior container life (docker restart) would otherwise
|
# this same monitor loop (not just some unrelated process that happens to
|
||||||
# cause us to exit instead of entering the monitor loop.
|
# 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
|
if [ -f "/run/.no_exit.pid" ]; then
|
||||||
local no_exit_pid
|
local no_exit_pid
|
||||||
no_exit_pid=$(<"/run/.no_exit.pid") 2>/dev/null
|
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
|
return 0
|
||||||
fi
|
fi
|
||||||
rm -f /run/.no_exit.pid 2>/dev/null || true
|
rm -f /run/.no_exit.pid 2>/dev/null || true
|
||||||
fi
|
fi
|
||||||
|
|
||||||
exec bash -c "
|
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
|
trap 'echo \"Container shutdown requested\"; rm -f /run/.no_exit.pid /run/*.pid; exit 0' TERM INT
|
||||||
echo \$\$ > /run/.no_exit.pid
|
echo \$\$ > /run/.no_exit.pid
|
||||||
failed_services=\"\"
|
failed_services=\"\"
|
||||||
@@ -267,7 +284,8 @@ __banner() {
|
|||||||
}
|
}
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
__service_banner() {
|
__service_banner() {
|
||||||
local icon="${1:-🔧}"
|
local icon="${1:-}"
|
||||||
|
[ -z "$icon" ] && icon="$( [ -z "$NO_COLOR" ] && echo "🔧" || echo "" )"
|
||||||
local message="${2:-Processing}"
|
local message="${2:-Processing}"
|
||||||
local service="${3:-service}"
|
local service="${3:-service}"
|
||||||
local full_message="$message $service"
|
local full_message="$message $service"
|
||||||
@@ -682,7 +700,7 @@ __file_copy() {
|
|||||||
__generate_random_uids() {
|
__generate_random_uids() {
|
||||||
local set_random_uid=$((100 + RANDOM % 900))
|
local set_random_uid=$((100 + RANDOM % 900))
|
||||||
while :; do
|
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))
|
set_random_uid=$((set_random_uid + 1))
|
||||||
else
|
else
|
||||||
echo "$set_random_uid"
|
echo "$set_random_uid"
|
||||||
@@ -738,7 +756,7 @@ __fix_permissions() {
|
|||||||
change_group="${2:-${SERVICE_GROUP:-$change_user}}"
|
change_group="${2:-${SERVICE_GROUP:-$change_user}}"
|
||||||
[ -n "$RUNAS_USER" ] && [ "$RUNAS_USER" != "root" ] && change_user="$RUNAS_USER" && change_group="$change_user"
|
[ -n "$RUNAS_USER" ] && [ "$RUNAS_USER" != "root" ] && change_user="$RUNAS_USER" && change_group="$change_user"
|
||||||
if [ -n "$change_user" ]; then
|
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
|
for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do
|
||||||
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
|
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
|
||||||
chown -Rf "$change_user" "$permissions" 2>/dev/null
|
chown -Rf "$change_user" "$permissions" 2>/dev/null
|
||||||
@@ -748,7 +766,7 @@ __fix_permissions() {
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
if [ -n "$change_group" ]; then
|
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
|
for permissions in $ADD_APPLICATION_DIRS $APPLICATION_DIRS; do
|
||||||
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
|
if [ -n "$permissions" ] && [ -e "$permissions" ]; then
|
||||||
chgrp -Rf "$change_group" "$permissions" 2>/dev/null
|
chgrp -Rf "$change_group" "$permissions" 2>/dev/null
|
||||||
@@ -809,7 +827,7 @@ __set_user_group_id() {
|
|||||||
return 0
|
return 0
|
||||||
fi
|
fi
|
||||||
# Nothing to do if the user does not exist yet
|
# 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
|
return 0
|
||||||
fi
|
fi
|
||||||
set_uid="$(__get_uid "$set_user" || echo "$set_uid")"
|
set_uid="$(__get_uid "$set_user" || echo "$set_uid")"
|
||||||
@@ -852,7 +870,7 @@ __create_service_user() {
|
|||||||
return 1
|
return 1
|
||||||
fi
|
fi
|
||||||
# Check if user and group already exist
|
# 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
|
return 0
|
||||||
fi
|
fi
|
||||||
# Override with RUNAS_USER if specified and not root
|
# 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
|
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
|
echo "Error: Failed to create group '$create_group'" >&2
|
||||||
exitStatus=$((exitStatus + 1))
|
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
|
echo "Error: Group '$create_group' not found in /etc/group after creation" >&2
|
||||||
exitStatus=$((exitStatus + 1))
|
exitStatus=$((exitStatus + 1))
|
||||||
fi
|
fi
|
||||||
@@ -906,10 +924,12 @@ __create_service_user() {
|
|||||||
# Create user if needed (only if group creation succeeded)
|
# Create user if needed (only if group creation succeeded)
|
||||||
if [ $exitStatus -eq 0 ] && [ -n "$create_user" ] && ! __check_for_user "$create_user"; then
|
if [ $exitStatus -eq 0 ] && [ -n "$create_user" ] && ! __check_for_user "$create_user"; then
|
||||||
echo "Creating system user '$create_user' with UID $create_uid"
|
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
|
echo "Error: Failed to create user '$create_user'" >&2
|
||||||
exitStatus=$((exitStatus + 1))
|
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
|
echo "Error: User '$create_user' not found in /etc/passwd after creation" >&2
|
||||||
exitStatus=$((exitStatus + 1))
|
exitStatus=$((exitStatus + 1))
|
||||||
fi
|
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
|
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
|
chmod 0440 "/etc/sudoers.d/$create_user" 2>/dev/null
|
||||||
fi
|
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
|
echo "$create_user ALL=(ALL) NOPASSWD: ALL" >>"/etc/sudoers" 2>/dev/null || echo "Warning: Failed to add '$create_user' to sudoers" >&2
|
||||||
fi
|
fi
|
||||||
SERVICE_UID="$create_uid"
|
SERVICE_UID="$create_uid"
|
||||||
@@ -1030,7 +1050,7 @@ __start_init_scripts() {
|
|||||||
touch "$pidFile"
|
touch "$pidFile"
|
||||||
name="${init##*/}"
|
name="${init##*/}"
|
||||||
service="${name#*-}"; service="${service%.sh}"
|
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)
|
# Execute the init script and capture the exit code (subshell isolates exit calls)
|
||||||
if ( source "$init" ); then
|
if ( source "$init" ); then
|
||||||
# Check if service was disabled first
|
# Check if service was disabled first
|
||||||
@@ -1093,7 +1113,7 @@ __start_init_scripts() {
|
|||||||
else
|
else
|
||||||
initStatus="1"
|
initStatus="1"
|
||||||
critical_failures=$((critical_failures + 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
|
fi
|
||||||
echo ""
|
echo ""
|
||||||
fi
|
fi
|
||||||
@@ -1103,12 +1123,24 @@ __start_init_scripts() {
|
|||||||
# Summary
|
# Summary
|
||||||
echo ""
|
echo ""
|
||||||
if [ $critical_failures -gt 0 ]; then
|
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
|
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
|
return 1
|
||||||
else
|
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
|
fi
|
||||||
else
|
else
|
||||||
echo "✅ All service initializations completed successfully"
|
echo "✅ All service initializations completed successfully"
|
||||||
@@ -1516,22 +1548,22 @@ __switch_to_user() {
|
|||||||
local switch_user="${SERVICE_USER:-$RUNAS_USER}"
|
local switch_user="${SERVICE_USER:-$RUNAS_USER}"
|
||||||
if [ "$switch_user" = "root" ]; then
|
if [ "$switch_user" = "root" ]; then
|
||||||
su_exec=""
|
su_exec=""
|
||||||
su_cmd() { eval "$@" || return 1; }
|
__su_cmd() { eval "$@" || return 1; }
|
||||||
elif command -v gosu &>/dev/null; then
|
elif command -v gosu &>/dev/null; then
|
||||||
su_exec="gosu $switch_user"
|
su_exec="gosu $switch_user"
|
||||||
su_cmd() { $su_exec "$@" || return 1; }
|
__su_cmd() { $su_exec "$@" || return 1; }
|
||||||
elif command -v runuser &>/dev/null; then
|
elif command -v runuser &>/dev/null; then
|
||||||
su_exec="runuser -u $switch_user"
|
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
|
elif command -v sudo &>/dev/null; then
|
||||||
su_exec="sudo -u $switch_user"
|
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
|
elif command -v su &>/dev/null; then
|
||||||
su_exec="su -s /bin/sh - $switch_user"
|
su_exec="su -s /bin/sh - $switch_user"
|
||||||
su_cmd() { $su_exec -c "$@" || return 1; }
|
__su_cmd() { $su_exec -c "$@" || return 1; }
|
||||||
else
|
else
|
||||||
su_exec=""
|
su_exec=""
|
||||||
su_cmd() {
|
__su_cmd() {
|
||||||
echo "Can not switch to $switch_user: attempting to run as root"
|
echo "Can not switch to $switch_user: attempting to run as root"
|
||||||
if ! eval "$@"; then
|
if ! eval "$@"; then
|
||||||
return 1
|
return 1
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202606261600-git
|
##@Version : 202609030524-git
|
||||||
# @@Author : Jason Hempstead
|
# @@Author : Jason Hempstead
|
||||||
# @@Contact : jason@casjaysdev.pro
|
# @@Contact : jason@casjaysdev.pro
|
||||||
# @@License : LICENSE.md
|
# @@License : LICENSE.md
|
||||||
@@ -20,6 +20,8 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
VERSION="202609030524-git"
|
||||||
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
set -e
|
set -e
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# run trap command on exit
|
# run trap command on exit
|
||||||
@@ -43,7 +45,11 @@ __trap_err_handler() {
|
|||||||
fi
|
fi
|
||||||
# Critical error - but only fail if service hasn't started yet
|
# Critical error - but only fail if service hasn't started yet
|
||||||
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
|
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
|
kill -TERM 1 2>/dev/null || exit $retVal
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@@ -108,7 +114,11 @@ fi
|
|||||||
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
||||||
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
||||||
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
|
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"
|
rm -f "/run/init.d/$SERVICE_NAME.pid"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -275,7 +285,7 @@ __run_precopy() {
|
|||||||
ln -sf "$CONF_DIR" "$ETC_DIR"
|
ln -sf "$CONF_DIR" "$ETC_DIR"
|
||||||
fi
|
fi
|
||||||
# allow custom functions
|
# 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
|
# Custom prerun functions - IE setup WWW_ROOT_DIR
|
||||||
@@ -285,7 +295,7 @@ __execute_prerun() {
|
|||||||
# Define actions/commands
|
# Define actions/commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# 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"
|
echo "Warning: cgroup v2 not available, Docker-in-Docker may have limited functionality"
|
||||||
fi
|
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
|
# Clean up orphaned containers before dockerd starts
|
||||||
# This prevents "failed to load container" errors on restart
|
# This prevents "failed to load container" errors on restart
|
||||||
if [ -d "/data/docker/containers" ]; then
|
if [ -d "/data/docker/containers" ]; then
|
||||||
@@ -392,7 +413,7 @@ __run_pre_execute_checks() {
|
|||||||
for get_reg in $DOCKER_REGISTRIES; do
|
for get_reg in $DOCKER_REGISTRIES; do
|
||||||
set_reg+="\"$get_reg\" "
|
set_reg+="\"$get_reg\" "
|
||||||
done
|
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
|
export registry
|
||||||
else
|
else
|
||||||
unset registry
|
unset registry
|
||||||
@@ -425,6 +446,7 @@ EOF
|
|||||||
"experimental": true,
|
"experimental": true,
|
||||||
"pidfile": "/tmp/docker.pid",
|
"pidfile": "/tmp/docker.pid",
|
||||||
"cgroup-parent": "/docker",
|
"cgroup-parent": "/docker",
|
||||||
|
"storage-driver": "fuse-overlayfs",
|
||||||
"default-address-pools": [
|
"default-address-pools": [
|
||||||
{"base": "172.17.0.0/12", "size": 24},
|
{"base": "172.17.0.0/12", "size": 24},
|
||||||
{"base": "192.168.0.0/16", "size": 24},
|
{"base": "192.168.0.0/16", "size": 24},
|
||||||
@@ -442,6 +464,7 @@ EOF
|
|||||||
"experimental": true,
|
"experimental": true,
|
||||||
"pidfile": "/tmp/docker.pid",
|
"pidfile": "/tmp/docker.pid",
|
||||||
"cgroup-parent": "/docker",
|
"cgroup-parent": "/docker",
|
||||||
|
"storage-driver": "fuse-overlayfs",
|
||||||
"default-address-pools": [
|
"default-address-pools": [
|
||||||
{"base": "172.17.0.0/12", "size": 24},
|
{"base": "172.17.0.0/12", "size": 24},
|
||||||
{"base": "192.168.0.0/16", "size": 24},
|
{"base": "192.168.0.0/16", "size": 24},
|
||||||
@@ -463,7 +486,7 @@ EOF
|
|||||||
__script_exit 1
|
__script_exit 1
|
||||||
fi
|
fi
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitStatus
|
return $exitStatus
|
||||||
}
|
}
|
||||||
@@ -489,12 +512,12 @@ __update_conf_files() {
|
|||||||
|
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# define actions
|
# define actions
|
||||||
symlink "$DATA_DIR" "/var/lib/docker"
|
__symlink "$DATA_DIR" "/var/lib/docker"
|
||||||
chmod 777 "$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
|
# Mark config as fully initialised so __run_precopy skips re-seeding on restart
|
||||||
touch "$CONF_DIR/.initialized" 2>/dev/null || true
|
touch "$CONF_DIR/.initialized" 2>/dev/null || true
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -516,7 +539,7 @@ __pre_execute() {
|
|||||||
# Lets wait a few seconds before continuing
|
# Lets wait a few seconds before continuing
|
||||||
sleep 2
|
sleep 2
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -549,7 +572,7 @@ __post_execute() {
|
|||||||
# fire-and-forget: backgrounded subshell always succeeds at launch
|
# fire-and-forget: backgrounded subshell always succeeds at launch
|
||||||
retVal=0
|
retVal=0
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $retVal
|
return $retVal
|
||||||
}
|
}
|
||||||
@@ -561,7 +584,7 @@ __pre_message() {
|
|||||||
# execute commands
|
# execute commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -574,7 +597,7 @@ __update_ssl_conf() {
|
|||||||
# execute commands
|
# execute commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# set exitCode
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -696,7 +719,7 @@ __run_start_script() {
|
|||||||
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
|
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
|
||||||
fi
|
fi
|
||||||
__log_info "$message" | tee -a -p "/data/logs/init.txt"
|
__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
|
# W14: invalidate cached START_SCRIPT if key variables changed
|
||||||
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
||||||
local _script_hash
|
local _script_hash
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202606261600-git
|
##@Version : 202609030601-git
|
||||||
# @@Author : Jason Hempstead
|
# @@Author : Jason Hempstead
|
||||||
# @@Contact : jason@casjaysdev.pro
|
# @@Contact : jason@casjaysdev.pro
|
||||||
# @@License : LICENSE.md
|
# @@License : LICENSE.md
|
||||||
@@ -20,6 +20,7 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
|
VERSION="202609030601-git"
|
||||||
set -e
|
set -e
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# run trap command on exit
|
# run trap command on exit
|
||||||
@@ -43,7 +44,11 @@ __trap_err_handler() {
|
|||||||
fi
|
fi
|
||||||
# Critical error - but only fail if service hasn't started yet
|
# Critical error - but only fail if service hasn't started yet
|
||||||
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
|
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
|
kill -TERM 1 2>/dev/null || exit $retVal
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@@ -108,7 +113,11 @@ fi
|
|||||||
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
||||||
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
||||||
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
|
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"
|
rm -f "/run/init.d/$SERVICE_NAME.pid"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -320,7 +329,7 @@ __run_precopy() {
|
|||||||
ln -sf "$CONF_DIR" "$ETC_DIR"
|
ln -sf "$CONF_DIR" "$ETC_DIR"
|
||||||
fi
|
fi
|
||||||
# allow custom functions
|
# 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
|
# Custom prerun functions - IE setup WWW_ROOT_DIR
|
||||||
@@ -330,7 +339,7 @@ __execute_prerun() {
|
|||||||
# Define actions/commands
|
# Define actions/commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# Run any pre-execution checks
|
||||||
@@ -356,7 +365,7 @@ __run_pre_execute_checks() {
|
|||||||
__script_exit 1
|
__script_exit 1
|
||||||
fi
|
fi
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitStatus
|
return $exitStatus
|
||||||
}
|
}
|
||||||
@@ -441,7 +450,7 @@ __update_conf_files() {
|
|||||||
touch "$CONF_DIR/.initialized" 2>/dev/null || true
|
touch "$CONF_DIR/.initialized" 2>/dev/null || true
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -463,7 +472,7 @@ __pre_execute() {
|
|||||||
# Lets wait a few seconds before continuing
|
# Lets wait a few seconds before continuing
|
||||||
sleep 2
|
sleep 2
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -496,7 +505,7 @@ __post_execute() {
|
|||||||
# fire-and-forget: backgrounded subshell always succeeds at launch
|
# fire-and-forget: backgrounded subshell always succeeds at launch
|
||||||
retVal=0
|
retVal=0
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $retVal
|
return $retVal
|
||||||
}
|
}
|
||||||
@@ -508,7 +517,7 @@ __pre_message() {
|
|||||||
# execute commands
|
# execute commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# exit function
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -521,7 +530,7 @@ __update_ssl_conf() {
|
|||||||
# execute commands
|
# execute commands
|
||||||
|
|
||||||
# allow custom functions
|
# 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
|
# set exitCode
|
||||||
return $exitCode
|
return $exitCode
|
||||||
}
|
}
|
||||||
@@ -643,7 +652,7 @@ __run_start_script() {
|
|||||||
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
|
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
|
||||||
fi
|
fi
|
||||||
__log_info "$message" | tee -a -p "/data/logs/init.txt"
|
__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
|
# W14: invalidate cached START_SCRIPT if key variables changed
|
||||||
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
||||||
local _script_hash
|
local _script_hash
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# shellcheck shell=bash
|
# shellcheck shell=bash
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
##@Version : 202608031200-git
|
##@Version : 202609030534-git
|
||||||
# @@Author : Jason Hempstead
|
# @@Author : Jason Hempstead
|
||||||
# @@Contact : jason@casjaysdev.pro
|
# @@Contact : jason@casjaysdev.pro
|
||||||
# @@License : LICENSE.md
|
# @@License : LICENSE.md
|
||||||
@@ -20,7 +20,7 @@
|
|||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
VERSION="202608031200-git"
|
VERSION="202609030534-git"
|
||||||
set -e
|
set -e
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# run trap command on exit
|
# run trap command on exit
|
||||||
@@ -44,7 +44,11 @@ __trap_err_handler() {
|
|||||||
fi
|
fi
|
||||||
# Critical error - but only fail if service hasn't started yet
|
# Critical error - but only fail if service hasn't started yet
|
||||||
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
|
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
|
kill -TERM 1 2>/dev/null || exit $retVal
|
||||||
fi
|
fi
|
||||||
return 0
|
return 0
|
||||||
@@ -109,7 +113,11 @@ fi
|
|||||||
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
if [ -n "$SERVICE_NAME" ] && [ -f "/run/init.d/$SERVICE_NAME.pid" ]; then
|
||||||
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
old_pid=$(<"/run/init.d/$SERVICE_NAME.pid") 2>/dev/null
|
||||||
if [ -n "$old_pid" ] && ! kill -0 "$old_pid" 2>/dev/null; then
|
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"
|
rm -f "/run/init.d/$SERVICE_NAME.pid"
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
@@ -132,7 +140,10 @@ __gen_auth_token() {
|
|||||||
if [ -z "$auth_token" ] && [ -n "$gitea_bin" ] && [ -n "$conf_file" ]; then
|
if [ -z "$auth_token" ] && [ -n "$gitea_bin" ] && [ -n "$conf_file" ]; then
|
||||||
# Only attempt token generation if gitea is fully installed (INSTALL_LOCK = true)
|
# 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
|
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
|
||||||
fi
|
fi
|
||||||
if [ -n "$auth_token" ]; then
|
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"
|
RUNNER_LABELS+="ubuntu-latest:docker://catthehacker/ubuntu:full-latest"
|
||||||
unset _HOST_ARCH _ARCH_LABEL
|
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_CONFIG_DEFAULT="${RUNNER_CONFIG_DEFAULT:-$CONF_DIR/default_config.yaml}"
|
||||||
RUNNER_DEFAULT_HOME="${RUNNER_DEFAULT_HOME:-$CONF_DIR/gitea}"
|
RUNNER_DEFAULT_HOME="${RUNNER_DEFAULT_HOME:-$CONF_DIR/gitea}"
|
||||||
RUNNER_CONFIG_NAME="${RUNNER_CONFIG_NAME:-act_runner.yaml}"
|
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_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_PORT" "$RUNNER_CACHE_PORT" "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME"
|
||||||
__replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$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
|
# Legacy single "gitea"-named runner registration removed: start-runners
|
||||||
echo "creating gitea runner in $RUNNER_DEFAULT_HOME and registering with http://$INSTANCE_HOSTNAME"
|
# (invoked from __post_execute) now owns all runner registration/count via
|
||||||
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 &
|
# RUNNERS_START, and registering a second runner here duplicated it
|
||||||
echo $! >"$RUN_DIR/act_runner.gitea.pid"
|
|
||||||
fi
|
|
||||||
fi
|
fi
|
||||||
exitStatus="${exitStatus:-0}"
|
exitStatus="${exitStatus:-0}"
|
||||||
chown -Rf "$SERVICE_USER":"$SERVICE_GROUP" "$CONF_DIR" "$ETC_DIR" "$DATA_DIR" 2>/dev/null
|
chown -Rf "$SERVICE_USER":"$SERVICE_GROUP" "$CONF_DIR" "$ETC_DIR" "$DATA_DIR" 2>/dev/null
|
||||||
@@ -518,29 +530,25 @@ __post_execute() {
|
|||||||
(
|
(
|
||||||
# show message
|
# show message
|
||||||
__banner "$postMessageST"
|
__banner "$postMessageST"
|
||||||
# commands to execute
|
# Legacy single "gitea"-named runner daemon start removed: start-runners
|
||||||
if [ -f "$RUNNER_DEFAULT_HOME/runners" ] && [ -f "$RUNNER_DEFAULT_HOME/$RUNNER_CONFIG_NAME" ]; then
|
# (below) now owns all runner registration/daemon startup via RUNNERS_START
|
||||||
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
|
|
||||||
#
|
#
|
||||||
if [ -f "$CACHE_CONFIG_FILE" ]; then
|
if [ -f "$CACHE_CONFIG_FILE" ]; then
|
||||||
mkdir -p "$DATA_DIR/cache"
|
mkdir -p "$DATA_DIR/cache"
|
||||||
__replace "REPLACE_RUNNER_CACHE_DIR" "$DATA_DIR/cache" "$CACHE_CONFIG_FILE"
|
__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_PORT" "$RUNNER_CACHE_PORT" "$CACHE_CONFIG_FILE"
|
||||||
__replace "REPLACE_RUNNER_CACHE_SECRET" "$RUNNER_CACHE_SECRET" "$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=$!
|
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
|
sleep 5
|
||||||
if ps ax | awk '{print $1}' | grep -v -- 'grep' | grep -q -- "$execPid$"; then
|
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"
|
echo "Cache server has been started and is listening on $RUNNER_CACHE_PORT"
|
||||||
@@ -549,7 +557,17 @@ __post_execute() {
|
|||||||
fi
|
fi
|
||||||
unset pid
|
unset pid
|
||||||
fi
|
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
|
# show exit message
|
||||||
__banner "$postMessageEnd: Status $retVal"
|
__banner "$postMessageEnd: Status $retVal"
|
||||||
) 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
|
) 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"
|
__log_debug "Using $su_exec" | tee -a -p "/data/logs/init.txt"
|
||||||
fi
|
fi
|
||||||
__log_info "$message" | tee -a -p "/data/logs/init.txt"
|
__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
|
# W14: invalidate cached START_SCRIPT if key variables changed
|
||||||
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
|
||||||
local _script_hash
|
local _script_hash
|
||||||
@@ -1027,7 +1045,8 @@ if [ -n "$EXEC_CMD_BIN" ]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
# start the post execute function in background
|
# EXEC_CMD_BIN is empty for this service, so __run_start_script already invoked
|
||||||
__post_execute 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
|
# __post_execute internally (its empty-cmd branch); calling it again here would
|
||||||
|
# duplicate runner registration/daemon startup
|
||||||
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
# - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
__script_exit $SERVICE_EXIT_CODE
|
__script_exit $SERVICE_EXIT_CODE
|
||||||
|
|||||||
Reference in New Issue
Block a user