🦈🏠🐜 Initial Commit 🐜🦈🏠

This commit is contained in:
casjay
2026-09-03 21:08:19 -04:00
commit c8f7ff8d22
37 changed files with 9238 additions and 0 deletions
+45
View File
@@ -0,0 +1,45 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 00-init.sh
# @@Description : script to run init
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/00-init.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
if [ -d "/usr/local/share/template-files/data" ]; then rm -Rf "/usr/local/share/template-files/data"/*; fi
if [ -d "/usr/local/share/template-files/config" ]; then rm -Rf "/usr/local/share/template-files/config"/*; fi
if [ -d "/usr/local/share/template-files/defaults" ]; then rm -Rf "/usr/local/share/template-files/defaults"/*; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 01-system.sh
# @@Description : script to run system
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/01-system.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 02-packages.sh
# @@Description : script to run packages
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/02-packages.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+74
View File
@@ -0,0 +1,74 @@
#!/usr/bin/env bash
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202606041215-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : WTFPL
# @@ReadME :
# @@Copyright : Copyright: (c) 2023 CasjaysDev
# @@Created : Mon Aug 28 06:48:42 PM EDT 2023
# @@File : 03-files.sh
# @@Description : script to run files
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck shell=bash
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -d "/tmp/bin" ]; then
\mkdir -p "/usr/local/bin"
for bin in "/tmp/bin"/*; do
name="${bin##*/}"
echo "Installing $name to /usr/local/bin/$name"
copy "$bin" "/usr/local/bin/$name"
\chmod -f +x "/usr/local/bin/$name"
done
fi
unset bin
if [ -d "/tmp/var" ]; then
for var in "/tmp/var"/*; do
name="${var##*/}"
echo "Installing $var to /var/$name"
if [ -d "$var" ]; then
\mkdir -p "/var/$name"
copy "$var/." "/var/$name/"
else
copy "$var" "/var/$name"
fi
done
fi
unset var
if [ -d "/tmp/etc" ]; then
for config in "/tmp/etc"/*; do
name="${config##*/}"
echo "Installing $config to /etc/$name"
if [ -d "$config" ]; then
\mkdir -p "/etc/$name"
copy "$config/." "/etc/$name/"
else
copy "$config" "/etc/$name"
fi
done
fi
unset config
if [ -d "/tmp/usr" ]; then
for usrpath in "/tmp/usr"/*; do
name="${usrpath##*/}"
echo "Installing $usrpath to /usr/$name"
if [ -d "$usrpath" ]; then
\mkdir -p "/usr/$name"
copy "$usrpath/." "/usr/$name/"
else
copy "$usrpath" "/usr/$name"
fi
done
fi
unset usrpath
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# ex: ts=2 sw=2 et filetype=sh
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 04-users.sh
# @@Description : script to run users
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/04-users.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202609030601-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 05-custom.sh
# @@Description : script to run custom
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/05-custom.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
VERSION="202609030601-git"
exitCode=0
apk add --no-cache ca-certificates 2>/dev/null || true
update-ca-certificates 2>/dev/null || true
FORGEJO_VERSION="${FORGEJO_VERSION:-latest}"
FORGEJO_BIN_FILE="/usr/local/bin/forgejo"
ACT_BIN_FILE="/usr/local/bin/act_runner"
ARCH="$(uname -m | tr '[:upper]' '[:lower]')"
case "$ARCH" in x86_64) ARCH="amd64" ;; aarch64) ARCH="arm64" ;; *) echo "$ARCH is not supported by this script" >&2 && exit 1 ;; esac
# Pinned fallback used when code.forgejo.org is unreachable from the build host
ACT_RUNNER_FALLBACK_VERSION="${ACT_RUNNER_FALLBACK_VERSION:-v13.1.0}"
# Fetch latest version tag from the forgejo-runner repo — 30s connect timeout
ACT_VERSIONS="$(curl -q --connect-timeout 30 --max-time 45 -LSsf \
'https://code.forgejo.org/api/v1/repos/forgejo/runner/releases' \
-H 'accept: application/json' 2>/dev/null | jq -r '.[].tag_name' | sort -Vr | head -n1)"
# Fall back to pinned version if API is unreachable
[ -z "$ACT_VERSIONS" ] && ACT_VERSIONS="$ACT_RUNNER_FALLBACK_VERSION" && echo "WARNING: code.forgejo.org unreachable, using act_runner $ACT_VERSIONS" >&2
# Fetch download URL from API; binary names use the version without leading 'v'
ACT_URL="$(curl -q --connect-timeout 30 --max-time 45 -LSsf \
"https://code.forgejo.org/api/v1/repos/forgejo/runner/releases/tags/$ACT_VERSIONS" \
-H 'accept: application/json' 2>/dev/null | jq -rc '.assets|.[]|.browser_download_url' | grep -E -- "linux-${ARCH}$")"
# If API parse yielded nothing, construct the direct download URL from the version
# Tag format: v13.1.0 → filename: forgejo-runner-13.1.0-linux-amd64 (strip leading 'v')
ACT_VER_PLAIN="${ACT_VERSIONS#v}"
[ -z "$ACT_URL" ] && ACT_URL="https://code.forgejo.org/forgejo/runner/releases/download/${ACT_VERSIONS}/forgejo-runner-${ACT_VER_PLAIN}-linux-${ARCH}"
if [ -z "$FORGEJO_VERSION" ] || [ "$FORGEJO_VERSION" = "latest" ] || [ "$FORGEJO_VERSION" = "current" ]; then
_latest_url="$(curl -4sfL -o /dev/null -w '%{url_effective}' https://code.forgejo.org/forgejo/forgejo/releases/latest 2>/dev/null)"
FORGEJO_VERSION="$(printf '%s\n' "$_latest_url" | grep -oE -- '[0-9]+\.[0-9]+\.[0-9]+')"
fi
if [ -z "$FORGEJO_VERSION" ]; then
echo "Failed to resolve forgejo latest version from code.forgejo.org" >&2
exit 1
fi
FORGEJO_URL="https://code.forgejo.org/forgejo/forgejo/releases/download/v${FORGEJO_VERSION}/forgejo-${FORGEJO_VERSION}-linux-${ARCH}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
echo "Downloading forgejo from $FORGEJO_URL"
if curl -4 -q -LSsf --retry 5 --retry-delay 10 --retry-all-errors "$FORGEJO_URL" -o "/tmp/forgejo.$$"; then
mv -f "/tmp/forgejo.$$" "$FORGEJO_BIN_FILE"
echo "forgejo has been installed to: $FORGEJO_BIN_FILE"
chmod +x "$FORGEJO_BIN_FILE"
if [ -d "/etc/sudoers.d" ]; then
echo "root ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/root"
echo "git ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/git"
echo "docker ALL=(ALL) NOPASSWD: ALL" >"/etc/sudoers.d/docker"
fi
else
echo "Failed to download forgejo" >&2
exitCode=$((exitCode + 1))
fi
echo "Downloading act_runner from $ACT_URL"
if [ -z "$ACT_URL" ]; then
echo "Failed to resolve act_runner download URL" >&2
exitCode=$((exitCode + 1))
elif curl -q -LSsf --retry 5 --retry-delay 10 --retry-all-errors "$ACT_URL" -o "/tmp/act_runner.$$"; then
mv -f "/tmp/act_runner.$$" "$ACT_BIN_FILE"
echo "act_runner has been installed to: $ACT_BIN_FILE"
chmod +x "$ACT_BIN_FILE"
else
echo "Failed to download act_runner" >&2
exitCode=$((exitCode + 1))
fi
[ -x "$ACT_BIN_FILE" ] && [ -x "$FORGEJO_BIN_FILE" ] && exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit "$exitCode"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+43
View File
@@ -0,0 +1,43 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 06-post.sh
# @@Description : script to run post
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/06-post.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605241158-git
# @@Author : CasjaysDev
# @@Contact : CasjaysDev <docker-admin@casjaysdev.pro>
# @@License : MIT
# @@Copyright : Copyright 2026 CasjaysDev
# @@Created : Sun May 24 11:58:45 AM EDT 2026
# @@File : 07-cleanup.sh
# @@Description : script to run cleanup
# @@Changelog : newScript
# @@TODO : Refactor code
# @@Other : N/A
# @@Resource : N/A
# @@Terminal App : yes
# @@sudo/root : yes
# @@Template : templates/dockerfiles/init_scripts/07-cleanup.sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
set -o pipefail
[ "$DEBUGGER" = "on" ] && echo "Enabling debugging" && set -x$DEBUGGER_OPTIONS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Load functions
__find_and_remove() { [ -z "$1" ] || find "${2:-/etc}" -iname "$1" -exec rm -Rf {} \; 2>/dev/null; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set env variables
exitCode=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Predefined actions
if [ -d "/tmp" ]; then rm -Rf "/tmp"/*; fi
if [ -d "$HOME/.cache" ]; then rm -Rf "$HOME/.cache"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main script
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the exit code
#exitCode=$?
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $exitCode
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
@@ -0,0 +1,9 @@
log:
level: warn
cache:
enabled: true
dir: 'REPLACE_RUNNER_CACHE_DIR'
host: '0.0.0.0'
port: REPLACE_RUNNER_CACHE_PORT
external_secret: 'REPLACE_RUNNER_CACHE_SECRET'
@@ -0,0 +1,71 @@
# Config for act_runner daemon
log:
# The level of logging, can be trace, debug, info, warn, error, fatal
level: warn
host:
# The parent directory of a job's working directory.
workdir_parent: 'REPLACE_RUNNER_TEMP'
runner:
# Where to store the registration result.
file: REPLACE_RUNNER_HOME/runners
# Execute how many tasks concurrently at the same time.
capacity: 4
# Extra environment variables to run jobs.
envs:
A_TEST_ENV_NAME_1: a_test_env_value_1
# Extra environment variables to run jobs from a file.
env_file: .env
# The timeout for a job to be finished.
timeout: 3h
# Whether skip verifying the TLS certificate of the Forgejo instance.
insecure: true
# The timeout for fetching the job from the Forgejo instance.
fetch_timeout: 5s
# The interval for fetching the job from the Forgejo instance.
fetch_interval: 2s
# The labels of a runner are used to determine which jobs the runner can run, and how to run them.
labels:
#- 'macos:docker:dockurr/macos'
#- 'windows:docker:dockurr/windows'
#- 'linux:docker:casjaysdev/almalinux'
#- 'alma:docker:casjaysdev/almalinux'
#- 'alpine:docker:casjaysdev/alpine'
#- 'debian:docker:casjaysdev/debian'
#- 'arch:docker:casjaysdev/archlinux'
#- 'node:docker://node:latest'
#- 'node14:docker://node:14'
#- 'node16:docker://node:16'
#- 'node18:docker://node:18'
#- 'node20:docker://node:20'
#- 'node20:docker://node:20'
#- 'python3:docker://python:latest'
#- 'php7:docker://php:7-fpm'
#- 'php8:docker://php:8-fpm'
#- 'php:docker://php:8.4-rc-fpm-alpine3.20'
#- 'alpine:docker://casjaysdev/alpine:latest'
#- 'almalinux:docker://casjaysdev/almalinux:latest'
#- 'debian:docker://casjaysdev/debian:latest'
#- 'ubuntu:docker://casjaysdev/ubuntu:latest'
#- 'linux:host,ubuntu-latest:docker://catthehacker/ubuntu:full-latest'
container:
# Specifies the network to which the container will connect.
network: 'bridge'
# Whether to use privileged mode or not when launching task containers (privileged mode is required for Docker-in-Docker).
privileged: true
# And other options to be used when the container is started (eg, --add-host=my.forgejo.url:host-gateway).
options:
# The parent directory of a job's working directory.
workdir_parent: 'REPLACE_RUNNER_TEMP/volumes'
# Volumes (including bind mounts) can be mounted to containers. Glob syntax is supported, see https://github.com/gobwas/glob
valid_volumes:
- '**'
# overrides the docker client host with the specified one.
docker_host: ''
cache:
enabled: true
external_server: 'http://REPLACE_RUNNER_CACHE_HOST:REPLACE_RUNNER_CACHE_PORT/'
external_secret: 'REPLACE_RUNNER_CACHE_SECRET'
+15
View File
@@ -0,0 +1,15 @@
{
"ip": "0.0.0.0",
"iptables": true,
"log-level": "error",
"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},
{"base": "10.0.0.0/8", "size": 24}
],
"insecure-registries": ["localhost"]
}
+383
View File
@@ -0,0 +1,383 @@
; https://forgejo.org/docs/latest/admin/config-cheat-sheet/#default-configuration-non-appini-configuration
APP_NAME = REPLACE_SERVER_SITE_TITLE
RUN_USER = REPLACE_SERVICE_USER
RUN_MODE = prod
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[server]
PROTOCOL = http
HTTP_ADDR = 0.0.0.0
HTTP_PORT = 80
ROOT_URL = REPLACE_SERVER_PROTO://REPLACE_SERVER_NAME
DOMAIN = REPLACE_SERVER_NAME
APP_DATA_PATH = REPLACE_DATA_DIR
OFFLINE_MODE = false
LFS_START_SERVER = true
LFS_JWT_SECRET = REPLACE_FORGEJO_LFS_JWT_SECRET
LANDING_PAGE = explore
ACME_URL =
ACME_ACCEPTTOS = true
ACME_EMAIL = ssl-admin@REPLACE_SERVER_NAME
ACME_DIRECTORY = REPLACE_DATA_DIR/certs
LETSENCRYPT_ACCEPTTOS = true
DISABLE_SSH = false
START_SSH_SERVER = true
SSH_LISTEN_HOST = 0.0.0.0
SSH_PORT = 7833
SSH_LISTEN_PORT = 22
SSH_CREATE_AUTHORIZED_KEYS_FILE = true
SSH_CREATE_AUTHORIZED_PRINCIPALS_FILE = true
SSH_AUTHORIZED_KEYS_BACKUP = true
SSH_ROOT_PATH = REPLACE_DATA_DIR/ssh
SSH_DOMAIN = REPLACE_SERVER_NAME
; reverse-proxy passthrough — TLS terminated upstream
USE_PROXY_PROTOCOL = false
REDIRECT_OTHER_PORT = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[lfs]
STORAGE_TYPE = local
PATH = REPLACE_DATA_DIR/lfs
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage.repo-archive]
STORAGE_TYPE = local
PATH = REPLACE_DATA_DIR/repositories/archive
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository]
SCRIPT_TYPE = sh
ROOT = REPLACE_DATA_DIR/repositories/root
DEFAULT_BRANCH = main
DEFAULT_PRIVATE = false
MAX_CREATION_LIMIT = -1
PREFERRED_LICENSES = MIT,Apache-2.0
DISABLE_HTTP_GIT = false
USE_COMPAT_SSH_URI = false
DEFAULT_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions
DEFAULT_FORK_REPO_UNITS = repo.code,repo.releases,repo.issues,repo.pulls,repo.wiki,repo.projects,repo.packages,repo.actions
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository.local]
LOCAL_COPY_PATH = REPLACE_DATA_DIR/repositories/local
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository.upload]
TEMP_PATH = REPLACE_DATA_DIR/repositories/uploads
FILE_MAX_SIZE = 100
MAX_FILES = 10
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository.pull-request]
DEFAULT_MERGE_STYLE = merge
WORK_IN_PROGRESS_PREFIXES = WIP:,[WIP]
CLOSE_KEYWORDS = close,closes,closed,fix,fixes,fixed,resolve,resolves,resolved
REOPEN_KEYWORDS = reopen,reopens,reopened
DEFAULT_MERGE_MESSAGE_COMMITS_LIMIT = 50
DEFAULT_MERGE_MESSAGE_SIZE = 5120
DEFAULT_MERGE_MESSAGE_ALL_AUTHORS = false
DEFAULT_MERGE_MESSAGE_MAX_APPROVERS = 10
ADD_CO_COMMITTER_TRAILERS = true
TEST_CONFLICTING_PATCHES_WITH_GIT_APPLY = false
RETARGET_CHILDREN_ON_MERGE = true
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository.release]
ALLOWED_TYPES =
DEFAULT_PAGING_NUM = 20
ADD_CO_COMMITTER_TRAILERS = true
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[repository.signing]
DEFAULT_TRUST_MODEL = collaboratorcommitter
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[packages]
ENABLED = true
CHUNKED_UPLOAD_PATH = REPLACE_DATA_DIR/tmp/package-upload
LIMIT_TOTAL_OWNER_COUNT = -1
LIMIT_TOTAL_OWNER_SIZE = -1
LIMIT_SIZE_ALPINE = -1
LIMIT_SIZE_CARGO = -1
LIMIT_SIZE_CHEF = -1
LIMIT_SIZE_COMPOSER = -1
LIMIT_SIZE_CONAN = -1
LIMIT_SIZE_CONDA = -1
LIMIT_SIZE_CONTAINER = -1
LIMIT_SIZE_CRAN = -1
LIMIT_SIZE_DEBIAN = -1
LIMIT_SIZE_GENERIC = -1
LIMIT_SIZE_GO = -1
LIMIT_SIZE_HELM = -1
LIMIT_SIZE_MAVEN = -1
LIMIT_SIZE_NPM = -1
LIMIT_SIZE_NUGET = -1
LIMIT_SIZE_PUB = -1
LIMIT_SIZE_PYPI = -1
LIMIT_SIZE_RPM = -1
LIMIT_SIZE_RUBYGEMS = -1
LIMIT_SIZE_SWIFT = -1
LIMIT_SIZE_VAGRANT = -1
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[attachment]
PATH = REPLACE_DATA_DIR/attachments
MAX_SIZE = 100
MAX_FILES = 10
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[indexer]
ISSUE_INDEXER_PATH = REPLACE_DATA_DIR/indexers/issues.bleve
REPO_INDEXER_ENABLED = true
REPO_INDEXER_PATH = REPLACE_DATA_DIR/indexers/repos.bleve
REPO_INDEXER_INCLUDE =
REPO_INDEXER_EXCLUDE = vendor,node_modules
MAX_FILE_SIZE = 1048576
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[session]
PROVIDER = file
PROVIDER_CONFIG = REPLACE_DATA_DIR/sessions
COOKIE_SECURE = false
SAME_SITE = lax
SESSION_LIFE_TIME = 86400
GC_INTERVAL_TIME = 86400
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cache]
ADAPTER = memory
INTERVAL = 60
HOST =
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[queue]
TYPE = channel
CONN_STR =
LENGTH = 100
BATCH_LENGTH = 20
WORKERS = 0
MAX_WORKERS = 10
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[database]
DB_TYPE = REPLACE_SQL_TYPE
HOST = REPLACE_SQL_HOST
USER = REPLACE_SQL_USER
PASSWD = REPLACE_SQL_PASS
NAME = REPLACE_SQL_NAME
LOG_SQL = false
SCHEMA =
SSL_MODE = disable
CHARSET = utf8
PATH = REPLACE_DATABASE_DIR/forgejo.db
MAX_IDLE_CONNS = 2
MAX_OPEN_CONNS = 100
CONN_MAX_LIFETIME = 3s
ITERATE_BUFFER_SIZE = 50
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[git]
MAX_GIT_DIFF_LINES = 1000
MAX_GIT_DIFF_LINE_CHARACTERS = 5000
MAX_GIT_DIFF_FILES = 100
GC_ARGS =
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[git.timeout]
DEFAULT = 360
MIGRATE = 600
MIRROR = 300
CLONE = 300
PULL = 300
GC = 60
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[picture]
AVATAR_UPLOAD_PATH = REPLACE_DATA_DIR/avatars/users
REPOSITORY_AVATAR_UPLOAD_PATH = REPLACE_DATA_DIR/avatars/repos
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[log]
MODE = console
LEVEL = warn
ROOT_PATH = REPLACE_LOG_DIR
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[security]
INSTALL_LOCK = true
SECRET_KEY = REPLACE_SECRET_KEY
INTERNAL_TOKEN = REPLACE_FORGEJO_INTERNAL_TOKEN
PASSWORD_HASH_ALGO = argon2
MIN_PASSWORD_LENGTH = 8
PASSWORD_COMPLEXITY = on
LOGIN_REMEMBER_DAYS = 1825
COOKIE_USERNAME = git_REPLACE_RANDOM_COOKIE_KEY
COOKIE_SECURE = false
CSRF_COOKIE_HTTP_ONLY = true
REVERSE_PROXY_LIMIT = 1
REVERSE_PROXY_TRUSTED_PROXIES = *
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
FORMAT = RFC1123
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[api]
ENABLE_SWAGGER = true
MAX_RESPONSE_ITEMS = 500
DEFAULT_PAGING_NUM = 50
DEFAULT_GIT_TREES_PER_PAGE = 1000
DEFAULT_MAX_BLOB_SIZE = 10485760
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[migration]
SKIP_TLS_VERIFY = true
ALLOWED_DOMAINS =
BLOCKED_DOMAINS =
ALLOW_LOCALNETWORKS = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[git.config]
http.sslVerify = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[webhook]
QUEUE_LENGTH = 1000
DELIVER_TIMEOUT = 30
SKIP_TLS_VERIFY = true
PAGING_NUM = 10
PROXY_URL =
PROXY_HOSTS =
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[service]
DISABLE_REGISTRATION = false
REQUIRE_SIGNIN_VIEW = false
REGISTER_EMAIL_CONFIRM = REPLACE_FORGEJO_EMAIL_CONFIRM
ENABLE_NOTIFY_MAIL = REPLACE_FORGEJO_EMAIL_CONFIRM
ALLOW_ONLY_EXTERNAL_REGISTRATION = false
ENABLE_CAPTCHA = true
DEFAULT_KEEP_EMAIL_PRIVATE = true
DEFAULT_ALLOW_CREATE_ORGANIZATION = true
DEFAULT_ENABLE_TIMETRACKING = true
NO_REPLY_ADDRESS = no-reply.REPLACE_SERVER_NAME
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[actions]
ENABLED = true
DEFAULT_ACTIONS_URL = github
ARTIFACT_RETENTION_DAYS = 90
ZOMBIE_TASK_TIMEOUT = 10m
ENDLESS_TASK_TIMEOUT = 3h
ABANDONED_JOB_TIMEOUT = 24h
SKIP_WORKFLOW_STRINGS = [skip ci],[ci skip],[no ci],[skip actions],[actions skip]
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[actions.artifacts]
ENABLED = true
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[storage.actions_log]
STORAGE_TYPE = local
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[mailer]
ENABLED = REPLACE_FORGEJO_EMAIL_CONFIRM
SMTP_ADDR = REPLACE_EMAIL_RELAY
SMTP_PORT = 25
FROM = REPLACE_SERVER_ADMIN
USER =
PASSWD =
PROTOCOL =
SEND_AS_PLAIN_TEXT = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[email.incoming]
ENABLED = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[notify.email]
ENABLED = REPLACE_FORGEJO_EMAIL_CONFIRM
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[openid]
ENABLE_OPENID_SIGNIN = true
ENABLE_OPENID_SIGNUP = true
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[oauth2]
ENABLED = true
JWT_SIGNING_ALGORITHM = RS256
JWT_SECRET = REPLACE_FORGEJO_LFS_JWT_SECRET
ACCESS_TOKEN_EXPIRATION_TIME = 3600
REFRESH_TOKEN_EXPIRATION_TIME = 730
MAX_TOKEN_LENGTH = 32767
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[oauth2_client]
REGISTER_EMAIL_CONFIRM = REPLACE_FORGEJO_EMAIL_CONFIRM
OPENID_CONNECT_SCOPES =
ENABLE_AUTO_REGISTRATION = true
USERNAME = nickname
UPDATE_AVATAR = false
ACCOUNT_LINKING = login
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[ui]
DEFAULT_THEME = forgejo-dark
SEARCH_REPO_DESCRIPTION = true
EXPLORE_PAGING_NUM = 20
ISSUE_PAGING_NUM = 20
FEED_MAX_COMMIT_NUM = 5
GRAPH_MAX_COMMIT_NUM = 100
CODE_COMMENT_LINES = 4
REACTIONS = +1,-1,laugh,hooray,confused,heart,rocket,eyes
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[ui.meta]
AUTHOR = forgejo
DESCRIPTION = REPLACE_SERVER_SITE_TITLE
KEYWORDS = go,git,self-hosted,forgejo
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[ui.notification]
MIN_TIMEOUT = 10s
MAX_TIMEOUT = 60s
TIMEOUT_STEP = 10s
EVENT_SOURCE_UPDATE_TIME = 10s
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[metrics]
ENABLED = false
TOKEN =
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cors]
ENABLED = true
SCHEME = REPLACE_SERVER_PROTO
ALLOW_DOMAIN = *
ALLOW_SUBDOMAIN = true
METHODS = GET,HEAD,POST,PUT,PATCH,DELETE,OPTIONS
MAX_AGE = 10m
ALLOW_CREDENTIALS = true
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[project]
PROJECT_BOARD_BASIC_KANBAN_TYPE = To Do, In Progress, Done
PROJECT_BOARD_BUG_TRIAGE_TYPE = Needs Triage, High Priority, Low Priority, Closed
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron]
ENABLED = true
RUN_AT_START = false
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.archive_cleanup]
ENABLED = true
RUN_AT_START = true
NO_SUCCESS_NOTICE = false
OLDER_THAN = 24h
SCHEDULE = @midnight
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.update_mirrors]
ENABLED = true
RUN_AT_START = true
NO_SUCCESS_NOTICE = true
PULL_LIMIT = 100000
PUSH_LIMIT = 100000
SCHEDULE = @every 360m
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.repo_health_check]
ENABLED = true
RUN_AT_START = false
NO_SUCCESS_NOTICE = false
TIMEOUT = 60s
SCHEDULE = @midnight
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.delete_inactive_accounts]
ENABLED = false
RUN_AT_START = false
NO_SUCCESS_NOTICE = false
OLDER_THAN = 168h
SCHEDULE = @annually
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.delete_repo_archives]
ENABLED = false
RUN_AT_START = false
NO_SUCCESS_NOTICE = false
SCHEDULE = @annually
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
[cron.update_checker]
ENABLED = false
RUN_AT_START = false
ENABLE_SUCCESS_NOTICE = true
SCHEDULE = @every 168h
HTTP_ENDPOINT = https://dl.gitea.com/gitea/version.json
+35
View File
@@ -0,0 +1,35 @@
Port 7833
Protocol 2
AddressFamily any
ListenAddress 0.0.0.0
ListenAddress ::
LogLevel INFO
HostKey REPLACE_SSH_CONF_DIR/ssh_host_ed25519_key
HostKey REPLACE_SSH_CONF_DIR/ssh_host_rsa_key
HostKey REPLACE_SSH_CONF_DIR/ssh_host_ecdsa_key
AuthorizedKeysFile REPLACE_SSH_DATA_DIR/authorized_keys
AuthorizedPrincipalsFile REPLACE_SSH_DATA_DIR/authorized_principals
TrustedUserCAKeys REPLACE_SSH_DATA_DIR/forgejo-trusted-user-ca-keys.pem
CASignatureAlgorithms ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521,sk-ecdsa-sha2-nistp256@openssh.com,ssh-ed25519,sk-ssh-ed25519@openssh.com,rsa-sha2-512,rsa-sha2-256,ssh-rsa
UseDNS no
AllowAgentForwarding no
AllowTcpForwarding no
PrintMotd no
PermitUserEnvironment yes
PermitRootLogin no
ChallengeResponseAuthentication no
PasswordAuthentication no
PermitEmptyPasswords no
AllowUsers git
Banner none
Subsystem sftp /usr/lib/ssh/sftp-server
AcceptEnv GIT_PROTOCOL
+78
View File
@@ -0,0 +1,78 @@
#!/usr/bin/env sh
# shellcheck shell=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605051306-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
# @@ReadME : copy --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Tuesday, May 05, 2026 13:06 EDT
# @@File : copy
# @@Description : copies a file and shows progress
# @@Changelog : Refactored for self-contained operation
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : shell/sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
APPNAME="$(basename -- "$0" 2>/dev/null)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# colorization
if [ -n "$NO_COLOR" ]; then
__printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
else
__printf_color() { { [ -z "$2" ] || DEFAULT_COLOR=$2; } && printf "%b" "$(tput setaf "$DEFAULT_COLOR" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; }
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
__unlink() { [ -L "$1" ] && rm -f -- "$1" >/dev/null; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
# custom functions
__copy() {
exitCode=0
if [ -d "$1" ]; then
__printf_color "Copying $1/* to $2/"
__unlink "$2"
mkdir -p "$2"
for f in "$1"/* "$1"/.[!.]* "$1"/..?*; do
[ -e "$f" ] || [ -L "$f" ] || continue
base=$(basename -- "$f")
__copy "$f" "$2/$base" || exitCode=$?
done
elif [ -f "$1" ] || [ -L "$1" ]; then
__printf_color "Copying $1 to $2"
__unlink "$2"
cp -Rf "$1" "$2"
exitCode=$?
fi
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Define variables
DEFAULT_COLOR="254"
COPY_EXIT_STATUS=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main application
if [ $# -ne 2 ]; then
__printf_color "USAGE: $APPNAME to from" "1" >&2
COPY_EXIT_STATUS=1
elif [ ! -e "$1" ]; then
__printf_color "$1 does not exist" >&2
COPY_EXIT_STATUS=2
else
__printf_color "Copying $1 to $2" "4"
__copy "$1" "$2" >/dev/null
COPY_EXIT_STATUS=$?
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# End application
# - - - - - - - - - - - - - - - - - - - - - - - - -
# lets exit with code
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $COPY_EXIT_STATUS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
+702
View File
@@ -0,0 +1,702 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202609030524-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
# @@ReadME : entrypoint.sh --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Friday, Jun 05, 2026 18:14 EDT
# @@File : entrypoint.sh
# @@Description : Entrypoint file for alpine
# @@Changelog : New script
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : other/docker-entrypoint
# - - - - - - - - - - - - - - - - - - - - - - - - -
# 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
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
[ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ] && export DEBUGGER_OPTIONS="$(<"/config/.debug")" || DEBUGGER_OPTIONS="${DEBUGGER_OPTIONS:-}"
if [ "$DEBUGGER" = "on" ] || [ -f "/config/.debug" ]; then
echo "Enabling debugging"
set -eo pipefail
[ -n "$DEBUGGER_OPTIONS" ] && set -"$DEBUGGER_OPTIONS"
export DEBUGGER="on"
else
set -eo pipefail
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
PATH="/usr/local/etc/docker/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set bash options
SCRIPT_FILE="$0"
CONTAINER_NAME="alpine"
SCRIPT_NAME="${SCRIPT_FILE##*/}"
CONTAINER_NAME="${ENV_CONTAINER_NAME:-$CONTAINER_NAME}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# remove whitespaces from beginning argument
while :; do [ "$1" = " " ] && shift 1 || break; done
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ "$1" = "$SCRIPT_FILE" ] && shift 1
[ "$1" = "$SCRIPT_NAME" ] && shift 1
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import the functions file
if [ -f "/usr/local/etc/docker/functions/entrypoint.sh" ]; then
. "/usr/local/etc/docker/functions/entrypoint.sh"
else
echo "Can not load functions from /usr/local/etc/docker/functions/entrypoint.sh"
exit 1
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
case "$1" in
# Help message
-h | --help)
shift 1
echo "Docker container for $CONTAINER_NAME"
echo "Usage: $CONTAINER_NAME [help tail cron exec start init shell procs ports healthcheck backup command]"
echo ""
exit 0
;;
-*)
shift
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Create the default env files
__create_env_file "/config/env/default.sh" "/root/env.sh" &>/dev/null
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import variables from files
for set_env in "/root/env.sh" "/usr/local/etc/docker/env"/*.sh "/config/env"/*.sh; do
[ -f "$set_env" ] && . "$set_env"
done
unset set_env
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User to use to launch service - IE: postgres
# normally root
RUNAS_USER="root"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set user and group from env
SERVICE_USER="${PUID:-$SERVICE_USER}"
SERVICE_GROUP="${PGID:-$SERVICE_GROUP}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set user and group ID
# set the user id
SERVICE_UID="${SERVICE_UID:-0}"
# set the group id
SERVICE_GID="${SERVICE_GID:-0}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User and group in which the service switches to - IE: nginx,apache,mysql,postgres
#SERVICE_USER="${SERVICE_USER:-alpine}" # execute command as another user
#SERVICE_GROUP="${SERVICE_GROUP:-alpine}" # Set the service group
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Secondary ports
# specifiy other ports
SERVER_PORTS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Primary server port- will be added to server ports
# port : 80,443
WEB_SERVER_PORT=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Healthcheck variables
# enable healthcheck [yes/no]
HEALTH_ENABLED="yes"
# comma separated list of processes for the healthcheck
SERVICES_LIST="tini"
# url endpoints: [http://localhost/health,http://localhost/test]
HEALTH_ENDPOINTS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Update path var
export PATH RUNAS_USER SERVICE_USER SERVICE_GROUP SERVICE_UID SERVICE_GID WWW_ROOT_DIR DATABASE_DIR
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom variables
# - - - - - - - - - - - - - - - - - - - - - - - - -
# show message
__run_message() {
return
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
################## END OF CONFIGURATION #####################
# Lets get containers ip address
IP4_ADDRESS="$(__get_ip4)"
IP6_ADDRESS="$(__get_ip6)"
CONTAINER_IP4_ADDRESS="${CONTAINER_IP4_ADDRESS:-$IP4_ADDRESS}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Startup variables
export INIT_DATE="${INIT_DATE:-$(date)}"
export CONTAINER_INIT="${CONTAINER_INIT:-no}"
export START_SERVICES="${START_SERVICES:-no}"
export ENTRYPOINT_MESSAGE="${ENTRYPOINT_MESSAGE:-yes}"
export ENTRYPOINT_FIRST_RUN="${ENTRYPOINT_FIRST_RUN:-yes}"
export DATA_DIR_INITIALIZED="${DATA_DIR_INITIALIZED:-no}"
export CONFIG_DIR_INITIALIZED="${CONFIG_DIR_INITIALIZED:-no}"
export CONTAINER_NAME="${ENV_CONTAINER_NAME:-$CONTAINER_NAME}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# System
export LANG="${LANG:-C.UTF-8}"
export LC_ALL="${LANG:-C.UTF-8}"
export TZ="${TZ:-${TIMEZONE:-America/New_York}}"
export HOSTNAME="$(hostname -s)"
export DOMAINNAME="$(hostname -d)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Default directories
export SSL_DIR="${SSL_DIR:-/config/ssl}"
export SSL_CA="${SSL_CA:-/config/ssl/ca.crt}"
export SSL_KEY="${SSL_KEY:-/config/ssl/localhost.pem}"
export SSL_CERT="${SSL_CERT:-/config/ssl/localhost.crt}"
export LOCAL_BIN_DIR="${LOCAL_BIN_DIR:-/usr/local/bin}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Backup settings
export BACKUP_MAX_DAYS="${BACKUP_MAX_DAYS:-}"
export BACKUP_RUN_CRON="${BACKUP_RUN_CRON:-}"
export BACKUP_DIR="${BACKUP_DIR:-/data/backups}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional
export PHP_INI_DIR="${PHP_INI_DIR:-$(__find_php_ini)}"
export PHP_BIN_DIR="${PHP_BIN_DIR:-$(__find_php_bin)}"
export HTTPD_CONFIG_FILE="${HTTPD_CONFIG_FILE:-$(__find_httpd_conf)}"
export NGINX_CONFIG_FILE="${NGINX_CONFIG_FILE:-$(__find_nginx_conf)}"
export MYSQL_CONFIG_FILE="${MYSQL_CONFIG_FILE:-$(__find_mysql_conf)}"
export PGSQL_CONFIG_FILE="${PGSQL_CONFIG_FILE:-$(__find_pgsql_conf)}"
export MONGODB_CONFIG_FILE="${MONGODB_CONFIG_FILE:-$(__find_mongodb_conf)}"
export ENTRYPOINT_PID_FILE="${ENTRYPOINT_PID_FILE:-/run/.entrypoint.pid}"
export ENTRYPOINT_INIT_FILE="${ENTRYPOINT_INIT_FILE:-/config/.entrypoint.done}"
export ENTRYPOINT_DATA_INIT_FILE="${ENTRYPOINT_DATA_INIT_FILE:-/data/.docker_has_run}"
export ENTRYPOINT_CONFIG_INIT_FILE="${ENTRYPOINT_CONFIG_INIT_FILE:-/config/.docker_has_run}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -n "$CONTAINER_WEB_SERVER_WWW_REPO" ]; then
www_temp_dir="/tmp/git/${CONTAINER_WEB_SERVER_WWW_REPO##*/}"
rm -Rf "${WWW_ROOT_DIR:?}"/* "${www_temp_dir:?}"/* 2>/dev/null || true
mkdir -p "$WWW_ROOT_DIR" "$www_temp_dir" 2>/dev/null || true
git clone -q "$CONTAINER_WEB_SERVER_WWW_REPO" "$www_temp_dir" 2>/dev/null || true
rm -Rf "$www_temp_dir/.git" "$www_temp_dir"/.git* 2>/dev/null || true
rsync -ra "$www_temp_dir/" "$WWW_ROOT_DIR" --delete 2>/dev/null || true
rm -Rf "$www_temp_dir" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# variables based on env/files
if [ -f "/config/enable/ssl" ]; then SSL_ENABLED="yes"; fi
if [ -f "/config/enable/ssh" ]; then SSH_ENABLED="yes"; fi
if [ "$WEB_SERVER_PORT" = "443" ]; then SSL_ENABLED="yes"; fi
if [ "$CONTAINER_WEB_SERVER_PROTOCOL" = "https" ]; then SSL_ENABLED="yes"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# export variables
# - - - - - - - - - - - - - - - - - - - - - - - - -
# is already Initialized
if [ -f "$ENTRYPOINT_DATA_INIT_FILE" ]; then
DATA_DIR_INITIALIZED="yes"
else
DATA_DIR_INITIALIZED="no"
fi
if [ -f "$ENTRYPOINT_CONFIG_INIT_FILE" ]; then
CONFIG_DIR_INITIALIZED="yes"
else
CONFIG_DIR_INITIALIZED="no"
fi
if [ -f "$ENTRYPOINT_PID_FILE" ] || [ -f "$ENTRYPOINT_INIT_FILE" ]; then
ENTRYPOINT_FIRST_RUN="no"
else
ENTRYPOINT_FIRST_RUN="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean ENV_PORTS variables
ENV_PORTS="${ENV_PORTS//,/ }"
ENV_PORTS="${ENV_PORTS//\/*/}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean SERVER_PORTS variables
SERVER_PORTS="${SERVER_PORTS//,/ }"
SERVER_PORTS="${SERVER_PORTS//\/*/}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# clean WEB_SERVER_PORTS variables
WEB_SERVER_PORTS="${WEB_SERVER_PORT//,/ } ${ENV_WEB_SERVER_PORTS//,/ }"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# rewrite and merge variables
ENV_PORTS="$(__format_variables "$ENV_PORTS" || false)"
WEB_SERVER_PORTS="$(__format_variables "$WEB_SERVER_PORTS" || false)"
ENV_PORTS="$(__format_variables "$SERVER_PORTS" "$WEB_SERVER_PORTS" "$ENV_PORTS" "$SERVER_PORTS" || false)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Remove the commas from env
HEALTH_ENDPOINTS="${HEALTH_ENDPOINTS//,/ }"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create required directories
mkdir -p "/run" 2>/dev/null || true
mkdir -p "/tmp" 2>/dev/null || true
mkdir -p "/root" 2>/dev/null || true
mkdir -p "/var/run" 2>/dev/null || true
mkdir -p "/var/tmp" 2>/dev/null || true
mkdir -p "/run/cron" 2>/dev/null || true
mkdir -p "/data/logs" 2>/dev/null || true
mkdir -p "/run/init.d" 2>/dev/null || true
mkdir -p "/config/enable" 2>/dev/null || true
mkdir -p "/config/secure" 2>/dev/null || true
mkdir -p "/config/env" 2>/dev/null || true
mkdir -p "/usr/local/etc/docker/exec" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create required files
touch "/data/logs/start.log" 2>/dev/null || true
touch "/data/logs/entrypoint.log" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# fix permissions
chmod -f 777 "/run" 2>/dev/null || true
chmod -f 777 "/tmp" 2>/dev/null || true
chmod -f 700 "/root" 2>/dev/null || true
chmod -f 777 "/var/run" 2>/dev/null || true
chmod -f 777 "/var/tmp" 2>/dev/null || true
chmod -f 777 "/run/cron" 2>/dev/null || true
chmod -f 777 "/data/logs" 2>/dev/null || true
chmod -f 777 "/run/init.d" 2>/dev/null || true
chmod -f 777 "/config/enable" 2>/dev/null || true
chmod -f 777 "/config/secure" 2>/dev/null || true
chmod -f 777 "/data/logs/entrypoint.log" 2>/dev/null || true
chmod -f 777 "/usr/local/etc/docker/exec" 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# lets ensure everyone can write to std*
if [ -f "/dev/stdin" ]; then
chmod -f 777 "/dev/stdin" 2>/dev/null || true
fi
if [ -f "/dev/stderr" ]; then
chmod -f 777 "/dev/stderr" 2>/dev/null || true
fi
if [ -f "/dev/stdout" ]; then
chmod -f 777 "/dev/stdout" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
cat <<EOF 2>/dev/null | tee /etc/profile.d/locales.shadow /etc/profile.d/locales.sh >/dev/null 2>&1 || true
export LANG="\${LANG:-C.UTF-8}"
export LC_ALL="\${LANG:-C.UTF-8}"
export TZ="\${TZ:-\${TIMEZONE:-America/New_York}}"
EOF
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Create the backup dir
if [ -n "$BACKUP_DIR" ]; then
if [ ! -d "$BACKUP_DIR" ]; then
mkdir -p "$BACKUP_DIR" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "$ENTRYPOINT_INIT_FILE" ]; then
ENTRYPOINT_MESSAGE="no" ENTRYPOINT_FIRST_RUN="no"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ "$ENTRYPOINT_FIRST_RUN" != "no" ]; then
if [ "$CONFIG_DIR_INITIALIZED" = "no" ] || [ "$DATA_DIR_INITIALIZED" = "no" ]; then
if [ "$ENTRYPOINT_MESSAGE" = "yes" ]; then
echo "Executing entrypoint script for alpine"
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set reusable variables
if [ -w "/etc" ] && [ ! -f "/etc/hosts" ]; then
UPDATE_FILE_HOSTS="yes"
touch "/etc/hosts"
elif [ -w "/etc/hosts" ]; then
UPDATE_FILE_HOSTS="yes"
touch "/etc/hosts"
fi
if [ -w "/etc" ] && [ ! -f "/etc/timezone" ]; then
UPDATE_FILE_TZ="yes"
touch "/etc/timezone"
elif [ -w "/etc/timezone" ]; then
UPDATE_FILE_TZ="yes"
touch "/etc/timezone"
fi
if [ -w "/etc" ] && [ ! -f "/etc/resolv.conf" ]; then
UPDATE_FILE_RESOLV="yes"
touch "/etc/resolv.conf"
elif [ -w "/etc/resolv.conf" ]; then
UPDATE_FILE_RESOLV="yes"
touch "/etc/resolv.conf"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set timezone
if [ -n "$TZ" ] && [ "$UPDATE_FILE_TZ" = "yes" ]; then
echo "$TZ" >"/etc/timezone" 2>/dev/null || true
fi
if [ -f "/usr/share/zoneinfo/$TZ" ] && [ "$UPDATE_FILE_TZ" = "yes" ]; then
ln -sf "/usr/share/zoneinfo/$TZ" "/etc/localtime" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# 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
__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
__printf_space "40" "127.0.0.1" "localhost" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# add .internal domain
if [ "$UPDATE_FILE_HOSTS" = "yes" ] && [ -n "$HOSTNAME" ]; then
if ! __grep_test " $HOSTNAME" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "$HOSTNAME" >>"/etc/hosts" 2>/dev/null || true
fi
if ! __grep_test " ${HOSTNAME%%.*}.internal" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "${HOSTNAME%%.*}.internal" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# add domainname
if [ "$UPDATE_FILE_HOSTS" = "yes" ] && [ "$DOMAINNAME" != "internal" ] && [ -n "$DOMAINNAME" ] && [ "$HOSTNAME.$DOMAINNAME" != "$DOMAINNAME" ]; then
if ! __grep_test " ${HOSTNAME%%.*}.$DOMAINNAME" "/etc/hosts"; then
__printf_space "40" "${CONTAINER_IP4_ADDRESS:-127.0.0.1}" "${HOSTNAME%%.*}.$DOMAINNAME" >>"/etc/hosts" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set containers hostname
if [ -n "$HOSTNAME" ] && [ "$UPDATE_FILE_HOSTS" = "yes" ]; then
echo "$HOSTNAME" >"/etc/hostname" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "/etc/hostname" ]; then
if command -v hostname &>/dev/null; then
hostname -F "/etc/hostname" 2>/dev/null || true
else
HOSTNAME="$(<"/etc/hostname")" 2>/dev/null || true
fi
export HOSTNAME
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# 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
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import resolv.conf file into container
if [ "$CUSTOM_DNS" != "yes" ] && [ -f "/usr/local/etc/resolv.conf" ] && [ "$UPDATE_FILE_RESOLV" = "yes" ]; then
cp -f "/usr/local/etc/resolv.conf" "/etc/resolv.conf" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -n "$HOME" ] && [ -d "/usr/local/etc/skel" ]; then
if [ -d "$HOME" ]; then
cp -Rf "/usr/local/etc/skel/." "$HOME/" 2>/dev/null || true
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Delete any .gitkeep files (bash * does not match dotfiles by default,
# so the explicit /.gitkeep path is required at each depth)
if [ -d "/data" ]; then
rm -Rf "/data/.gitkeep" "/data"/*/.gitkeep 2>/dev/null || true
fi
if [ -d "/config" ]; then
rm -Rf "/config/.gitkeep" "/config"/*/.gitkeep 2>/dev/null || true
fi
if [ -f "/usr/local/bin/.gitkeep" ]; then
rm -Rf "/usr/local/bin/.gitkeep" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Only run initialization on first run or when directories are not initialized
if [ "$ENTRYPOINT_FIRST_RUN" != "no" ] || [ "$CONFIG_DIR_INITIALIZED" = "no" ] || [ "$DATA_DIR_INITIALIZED" = "no" ]; then
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Setup bin directory - /config/bin > /usr/local/bin
__initialize_custom_bin_dir
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Initialize SSL certificates
__initialize_ssl_certs
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Mark directories as initialized (only write if not already initialized)
if [ -d "/config" ] && [ "$CONFIG_DIR_INITIALIZED" = "no" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_CONFIG_INIT_FILE" 2>/dev/null || true
CONFIG_DIR_INITIALIZED="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -d "/data" ] && [ "$DATA_DIR_INITIALIZED" = "no" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_DATA_INIT_FILE" 2>/dev/null || true
DATA_DIR_INITIALIZED="yes"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -d "/config" ] && [ ! -f "$ENTRYPOINT_INIT_FILE" ]; then
echo "Initialized on: $INIT_DATE" >"$ENTRYPOINT_INIT_FILE" 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup the smtp server
__setup_mta
# - - - - - - - - - - - - - - - - - - - - - - - - -
ENTRYPOINT_FIRST_RUN="no"
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. /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 \
&& 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"
else
# PID file exists but process is dead - this is a restart
START_SERVICES="yes"
# Clean any stale PID files on restart
rm -f /run/.start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
fi
else
START_SERVICES=yes
# Clean any stale PID files on first run
rm -f /run/.start_init_scripts.pid /run/init.d/*.pid /run/*.pid 2>/dev/null || true
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ "$ENTRYPOINT_MESSAGE" = "yes" ] && __printf_space "40" "The containers ip address is:" "$CONTAINER_IP4_ADDRESS"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Show configured listing processes
if [ "$ENTRYPOINT_MESSAGE" = "yes" ] && [ -n "$ENV_PORTS" ]; then
show_port=""
for port in $ENV_PORTS; do [ -n "$port" ] && show_port+="$(printf '%s ' "${port// /}") "; done
__printf_space "40" "The following ports are open:" "$show_port"
unset port show_port
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# execute init script
if [ -f "/tmp/init" ]; then sh "/tmp/init"; fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create user if needed
__create_service_user "$SERVICE_USER" "$SERVICE_GROUP" "${WORK_DIR:-/home/$SERVICE_USER}" "${SERVICE_UID:-}" "${SERVICE_GID:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Modify user if needed
__set_user_group_id $SERVICE_USER ${SERVICE_UID:-} ${SERVICE_GID:-}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Show message
__run_message
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Just start services
START_SERVICES="${START_SERVICES:-yes}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Determine if we should start services based on command
# Only skip service start for the 'init' command
SKIP_SERVICE_START="no"
[ "$1" = "init" ] && SKIP_SERVICE_START="yes" && CONTAINER_INIT="yes"
[ "$2" = "init" ] && SKIP_SERVICE_START="yes" && CONTAINER_INIT="yes"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Start all services if no pidfile and not skipping
# Start all services only when no command was given at all — an explicit
# command (exec, shell, tail, or an arbitrary program) must reach the case
# statement below instead of being swallowed into daemon/monitor mode, even
# on a first run where START_SERVICES is force-set to "yes"
if [ -z "$1" ]; then
if [ "$SKIP_SERVICE_START" = "no" ]; then
[ "$1" = "start" ] && shift 1
[ "$1" = "all" ] && shift 1
rm -Rf "/run"/*/*pid 2>/dev/null || true
echo "$$" >"$ENTRYPOINT_PID_FILE"
__start_init_scripts "/usr/local/etc/docker/init.d"
CONTAINER_INIT="${CONTAINER_INIT:-no}"
# Services started successfully - enter monitoring mode
__no_exit
exit $?
fi
START_SERVICES="no"
fi
export START_SERVICES CONTAINER_INIT ENTRYPOINT_PID_FILE
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Begin options
case "$1" in
init)
shift 1
__log_info "Container has been initialized"
exit 0
;;
tail)
shift 1
case "$1" in
null)
shift $#
tail -F "/dev/null"
;;
app)
shift $#
tail -F /data/logs/*/*.log
;;
-*)
tail "$@"
;;
*)
tail -F "${@:-/dev/null}"
;;
esac
;;
logs)
shift 1
case "$1" in
follow)
tail -Fq /data/logs/*/*
;;
clean)
mapfile -t log_files < <(find "/data/logs" -type f 2>/dev/null)
for log in "${log_files[@]}"; do
__log_info "Clearing log file: $log"
printf '' >"$log"
done
;;
*)
echo "Usage: logs [follow,clean]"
exit 0
;;
esac
;;
cron)
shift 1
__cron "$@" &
__log_info "Cron script is running with PID: $!"
exit 0
;;
# backup data and config dirs
backup)
shift 1
__backup $BACKUP_MAX_DAYS $1
exit $?
;;
# Docker healthcheck
healthcheck)
shift 1
case "$1" in
init | test)
exit 0
;;
*)
arguments="$*"
healthStatus=0
healthEnabled="${HEALTH_ENABLED:-}"
healthPorts="${WEB_SERVER_PORTS:-}"
healthEndPoints="${HEALTH_ENDPOINTS:-}"
SERVICES_LIST="${arguments:-$SERVICES_LIST}"
services="${SERVICES_LIST//,/ }"
healthMessage="Everything seems to be running"
[ "$healthEnabled" = "yes" ] || exit 0
if [ -d "/run/healthcheck" ] && ! __is_dir_empty "/run/healthcheck"; then
for service in /run/healthcheck/*; do
name="${service##*/}"
services+="$name "
done
fi
services="$(printf '%s\n' $services | sort -u | grep -v -- '^$')"
for proc in $services; do
if [ -n "$proc" ]; then
if ! __pgrep "$proc"; then
echo "$proc is not running" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
for port in $healthPorts; do
if command -v netstat &>/dev/null && [ -n "$port" ]; then
if ! netstat -taupln | grep -q -- ":$port "; then
echo "$port isn't open" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
for endpoint in $healthEndPoints; do
if [ -n "$endpoint" ]; then
if ! __curl "$endpoint"; then
echo "Can not connect to $endpoint" >&2
healthStatus=$((healthStatus + 1))
fi
fi
done
[ "$healthStatus" -eq 0 ] || healthMessage="Errors reported see: docker logs --follow $CONTAINER_NAME"
[ -n "$healthMessage" ] && echo "$healthMessage"
exit $healthStatus
;;
esac
;;
# show open ports
ports)
shift 1
ports="$(__netstat -taupln 2>/dev/null | awk '{ split($4, a, ":"); if (a[2] != "") print a[2] }' | sort -uV)"
[ -n "$ports" ] && printf '%s\n%s\n' "The following are servers:" "$ports" | tr '\n' ' '
exit $?
;;
# show running processes
procs)
shift 1
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 $?
;;
# Launch shell
# Launch shell — do not shift here: "sh -c 'cmd'" / "bash -c 'cmd'" needs the
# interpreter name kept as argv[0] for __exec_command's `exec "$@"` to work;
# shifting it away turned "sh -c 'cmd'" into `exec -c cmd` (command not found)
*/bin/sh | */bin/bash | bash | sh)
__exec_command "${@:-/bin/bash -l}"
exit $?
;;
# "shell" is a keyword, not a real interpreter — it must be shifted away, and
# any remaining args need "sh" prepended so __exec_command's `exec "$@"` gets
# a real interpreter instead of trying to exec "-c" as a program
shell)
shift 1
if [ $# -eq 0 ]; then
__exec_command
else
__exec_command sh "$@"
fi
exit $?
;;
# execute commands
exec)
shift 1
__exec_command "${@:-echo "No commands given"}"
exit $?
;;
# show/start init scripts
start)
shift 1
export PATH="/usr/local/etc/docker/init.d:$PATH"
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 0
elif [ "$1" = "all" ]; then
shift $#
if [ "$START_SERVICES" = "yes" ]; then
echo "$$" >"$ENTRYPOINT_PID_FILE"
__start_init_scripts "/usr/local/etc/docker/init.d"
__no_exit
elif [ -f "/usr/local/etc/docker/init.d/$1" ]; then
eval "/usr/local/etc/docker/init.d/$1" &
__no_exit
fi
fi
;;
# Execute primary command
*)
if [ $# -eq 0 ]; then
if [ ! -f "$ENTRYPOINT_PID_FILE" ]; then
echo "$$" >"$ENTRYPOINT_PID_FILE"
[ "$START_SERVICES" = "no" ] && [ "$CONTAINER_INIT" = "yes" ] || __start_init_scripts "/usr/local/etc/docker/init.d"
fi
__no_exit
else
__exec_command "$@"
fi
exit $?
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# end of entrypoint
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
+249
View File
@@ -0,0 +1,249 @@
#!/usr/bin/env sh
# shellcheck shell=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605051654-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
# @@ReadME : healthcheck --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Tuesday, May 05, 2026 16:54 EDT
# @@File : healthcheck
# @@Description : Docker container healthcheck — HTTP/TCP/process/file checks
# @@Changelog : Rewrote as a real Docker HEALTHCHECK probe
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : shell/sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
APPNAME="$(basename -- "$0" 2>/dev/null)"
VERSION="202605051654-git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Defaults (env vars override built-ins, CLI flags override env vars)
HEALTHCHECK_URL="${HEALTHCHECK_URL:-}"
HEALTHCHECK_HTTP_STATUS="${HEALTHCHECK_HTTP_STATUS:-2,3}"
HEALTHCHECK_HOST="${HEALTHCHECK_HOST:-127.0.0.1}"
HEALTHCHECK_PORT="${HEALTHCHECK_PORT:-}"
HEALTHCHECK_PROCESS="${HEALTHCHECK_PROCESS:-}"
HEALTHCHECK_FILE="${HEALTHCHECK_FILE:-}"
HEALTHCHECK_FILE_MAX_AGE="${HEALTHCHECK_FILE_MAX_AGE:-}"
HEALTHCHECK_TIMEOUT="${HEALTHCHECK_TIMEOUT:-5}"
HEALTHCHECK_VERBOSE="${HEALTHCHECK_VERBOSE:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
__cmd_exists() { command -v "$1" >/dev/null 2>&1; }
__log() { [ -n "$HEALTHCHECK_VERBOSE" ] && printf '%s\n' "$*" >&2; return 0; }
__fail() { printf 'UNHEALTHY: %s\n' "$*" >&2; exit 1; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__usage() {
cat <<EOF
$APPNAME $VERSION — Docker container healthcheck
Usage: $APPNAME [options]
At least one check must be configured (via env var or flag), or the script
exits 1. All configured checks must pass for the container to be healthy.
Options:
--url LIST HTTP(S) URL(s) to GET, comma-separated; ALL must
return an accepted status
(e.g. "http://localhost/health,http://localhost/ready")
--status PREFIXES Accepted status code prefixes, comma-separated
(default: "2,3" — any 2xx or 3xx; e.g. "200,204,301")
--host HOST Host for TCP port check (default: 127.0.0.1)
--port LIST TCP port(s) that must be accepting connections,
comma-separated; ALL must be reachable
(e.g. "80,443,3306")
--process LIST Process name(s) that must be running (matches the
executable name via pgrep). Comma-separated for
multiple — ALL must be present
(e.g. "tini,nginx,postfix,mariadb")
--file LIST File path(s) that must exist, comma-separated; ALL
must exist (and pass --file-max-age, if set)
--file-max-age SECONDS Each file's mtime must be within this many seconds
--timeout SECONDS Network check timeout (default: 5)
-v, --verbose Print check progress to stderr
-h, --help Show this help and exit 0
Environment variables (overridden by flags):
HEALTHCHECK_URL, HEALTHCHECK_HTTP_STATUS, HEALTHCHECK_HOST,
HEALTHCHECK_PORT, HEALTHCHECK_PROCESS, HEALTHCHECK_FILE,
HEALTHCHECK_FILE_MAX_AGE, HEALTHCHECK_TIMEOUT, HEALTHCHECK_VERBOSE
Exit codes:
0 all configured checks passed
1 at least one check failed, or no checks were configured
EOF
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Parse CLI flags (override env vars)
while [ $# -gt 0 ]; do
case "$1" in
--url) HEALTHCHECK_URL="$2"; shift 2 ;;
--url=*) HEALTHCHECK_URL="${1#*=}"; shift ;;
--status) HEALTHCHECK_HTTP_STATUS="$2"; shift 2 ;;
--status=*) HEALTHCHECK_HTTP_STATUS="${1#*=}"; shift ;;
--host) HEALTHCHECK_HOST="$2"; shift 2 ;;
--host=*) HEALTHCHECK_HOST="${1#*=}"; shift ;;
--port) HEALTHCHECK_PORT="$2"; shift 2 ;;
--port=*) HEALTHCHECK_PORT="${1#*=}"; shift ;;
--process) HEALTHCHECK_PROCESS="$2"; shift 2 ;;
--process=*) HEALTHCHECK_PROCESS="${1#*=}"; shift ;;
--file) HEALTHCHECK_FILE="$2"; shift 2 ;;
--file=*) HEALTHCHECK_FILE="${1#*=}"; shift ;;
--file-max-age) HEALTHCHECK_FILE_MAX_AGE="$2"; shift 2 ;;
--file-max-age=*) HEALTHCHECK_FILE_MAX_AGE="${1#*=}"; shift ;;
--timeout) HEALTHCHECK_TIMEOUT="$2"; shift 2 ;;
--timeout=*) HEALTHCHECK_TIMEOUT="${1#*=}"; shift ;;
-v|--verbose) HEALTHCHECK_VERBOSE=1; shift ;;
-h|--help) __usage; exit 0 ;;
--) shift; break ;;
-*) printf 'Unknown option: %s\n' "$1" >&2; __usage >&2; exit 1 ;;
*) printf 'Unexpected argument: %s\n' "$1" >&2; exit 1 ;;
esac
done
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Individual checks — each prints why it failed and exits 1 on failure
__trim() { printf '%s' "$1" | sed 's/^[[:space:]]*//;s/[[:space:]]*$//'; }
__check_one_http() {
url="$1"; accepted="$2"; timeout="$3"
if __cmd_exists curl; then
code="$(curl -ksSL -o /dev/null -w '%{http_code}' --max-time "$timeout" "$url" 2>/dev/null)" \
|| __fail "HTTP request to $url failed (curl error)"
elif __cmd_exists wget; then
code="$(wget -q -S --spider --timeout="$timeout" --tries=1 "$url" 2>&1 \
| awk '/^ HTTP\// {c=$2} END {print c+0}')"
[ "$code" -gt 0 ] 2>/dev/null || __fail "HTTP request to $url failed (wget error)"
else
__fail "HTTP check requires curl or wget"
fi
IFS=','
for prefix in $accepted; do
case "$code" in
"$prefix"*) unset IFS; __log "HTTP ok: $url -> $code"; return 0 ;;
esac
done
unset IFS
__fail "HTTP $url returned $code (expected prefix in: $accepted)"
}
__check_http() {
urls="$1"; accepted="$2"; timeout="$3"
__log "HTTP: urls=$urls (timeout=${timeout}s, accept=${accepted})"
IFS=','
for u in $urls; do
unset IFS
u="$(__trim "$u")"
[ -n "$u" ] || { IFS=','; continue; }
__check_one_http "$u" "$accepted" "$timeout"
IFS=','
done
unset IFS
return 0
}
__check_one_tcp() {
host="$1"; port="$2"; timeout="$3"
if __cmd_exists nc; then
nc -z -w "$timeout" "$host" "$port" >/dev/null 2>&1 && { __log "TCP ok: $host:$port"; return 0; }
fi
if __cmd_exists ncat; then
ncat -z -w "${timeout}s" "$host" "$port" >/dev/null 2>&1 && { __log "TCP ok (ncat): $host:$port"; return 0; }
fi
# Last resort: bash /dev/tcp (only if bash is available; sh-only systems skip)
if __cmd_exists bash; then
bash -c "exec 3<>/dev/tcp/$host/$port" >/dev/null 2>&1 && { __log "TCP ok (bash): $host:$port"; return 0; }
fi
return 1
}
__check_tcp() {
host="$1"; ports="$2"; timeout="$3"
__log "TCP: host=$host ports=$ports (timeout=${timeout}s)"
IFS=','
for p in $ports; do
unset IFS
p="$(__trim "$p")"
[ -n "$p" ] || { IFS=','; continue; }
__check_one_tcp "$host" "$p" "$timeout" || __fail "TCP $host:$p not reachable"
IFS=','
done
unset IFS
return 0
}
__check_one_process() {
pattern="$1"
if __cmd_exists pgrep; then
# Match against process name (not full cmdline) so our own argv doesn't self-match
pgrep -- "$pattern" >/dev/null 2>&1 && return 0
else
# Portable fallback: ps -o comm= prints just the command name
ps -e -o comm= 2>/dev/null | grep -v -e "^grep$" -e "^$APPNAME$" | grep -q -- "$pattern" && return 0
fi
return 1
}
__check_process() {
patterns="$1"
__log "Process: patterns=$patterns"
IFS=','
for p in $patterns; do
unset IFS
p="$(__trim "$p")"
[ -n "$p" ] || { IFS=','; continue; }
__check_one_process "$p" || __fail "Process not running: $p"
__log "Process ok: $p"
IFS=','
done
unset IFS
return 0
}
__check_one_file() {
path="$1"; max_age="$2"
[ -e "$path" ] || __fail "File not found: $path"
if [ -n "$max_age" ]; then
now="$(date +%s)"
mtime="$(stat -c %Y "$path" 2>/dev/null || stat -f %m "$path" 2>/dev/null \
|| perl -e 'print((stat(shift))[9])' "$path" 2>/dev/null)"
[ -n "$mtime" ] || __fail "Cannot determine mtime of $path"
age=$(( now - mtime ))
[ "$age" -le "$max_age" ] || __fail "File $path is stale (age=${age}s, max=${max_age}s)"
fi
__log "File ok: $path"
return 0
}
__check_file() {
paths="$1"; max_age="$2"
__log "File: paths=$paths max_age=${max_age:-none}"
IFS=','
for f in $paths; do
unset IFS
f="$(__trim "$f")"
[ -n "$f" ] || { IFS=','; continue; }
__check_one_file "$f" "$max_age"
IFS=','
done
unset IFS
return 0
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Run checks
ran_any=0
[ -n "$HEALTHCHECK_URL" ] && { __check_http "$HEALTHCHECK_URL" "$HEALTHCHECK_HTTP_STATUS" "$HEALTHCHECK_TIMEOUT"; ran_any=1; }
[ -n "$HEALTHCHECK_PORT" ] && { __check_tcp "$HEALTHCHECK_HOST" "$HEALTHCHECK_PORT" "$HEALTHCHECK_TIMEOUT"; ran_any=1; }
[ -n "$HEALTHCHECK_PROCESS" ] && { __check_process "$HEALTHCHECK_PROCESS"; ran_any=1; }
[ -n "$HEALTHCHECK_FILE" ] && { __check_file "$HEALTHCHECK_FILE" "$HEALTHCHECK_FILE_MAX_AGE"; ran_any=1; }
[ "$ran_any" -eq 1 ] || __fail "no checks configured (set HEALTHCHECK_URL/PORT/PROCESS/FILE or pass --url/--port/--process/--file)"
__log "All checks passed"
exit 0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
+143
View File
@@ -0,0 +1,143 @@
#!/usr/bin/env sh
# shellcheck shell=sh
# shellcheck disable=SC2016
# - - - - - - - - - - - - - - - - - - - - - - - - -
USER_UID="$(id -u)"
USER_GID="$(id -g)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -x "$(command -v apt 2>/dev/null)" ]; then
export DEBIAN_FRONTEND=noninteractive
pkmgr_cmd="apt"
pkmgr_clean_cmd="$pkmgr_cmd clean"
pkmgr_mkcache_cmd="$pkmgr_cmd update"
pkmgr_update_cmd="$pkmgr_cmd upgrade -yy"
pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS"
pkmgr_install_post="$pkmgr_cmd --fix-broken install"
elif [ -x "$(command -v apt-get 2>/dev/null)" ]; then
export DEBIAN_FRONTEND=noninteractive
pkmgr_cmd="apt-get"
pkmgr_clean_cmd="$pkmgr_cmd clean"
pkmgr_mkcache_cmd="$pkmgr_cmd update"
pkmgr_update_cmd="$pkmgr_cmd upgrade -yy"
pkmgr_install_cmd="$pkmgr_cmd install -yy $PKMGR_OPTS"
pkmgr_install_post="$pkmgr_cmd --fix-broken install"
elif [ -x "$(command -v dnf 2>/dev/null)" ]; then
pkmgr_cmd="dnf"
pkmgr_clean_cmd="$pkmgr_cmd clean all"
pkmgr_mkcache_cmd="$pkmgr_cmd makecache"
pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS"
elif [ -x "$(command -v yum 2>/dev/null)" ]; then
pkmgr_cmd="yum"
pkmgr_clean_cmd="$pkmgr_cmd clean all"
pkmgr_mkcache_cmd="$pkmgr_cmd makecache"
pkmgr_update_cmd="$pkmgr_cmd update -y --skip-broken $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y --skip-broken $PKMGR_OPTS"
elif [ -n "$(command -v pacman 2>/dev/null)" ]; then
pkmgr_cmd="pacman"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd -Scc --noconfirm"
pkmgr_update_cmd="$pkmgr_cmd -Syyu --noconfirm $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd -Syy --noconfirm $PKMGR_OPTS"
elif [ -x "$(command -v apk 2>/dev/null)" ]; then
pkmgr_cmd="apk"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd cache clean"
pkmgr_update_cmd="$pkmgr_cmd -U upgrade --no-cache $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd add --no-cache $PKMGR_OPTS"
elif [ -x "$(command -v zypper 2>/dev/null)" ]; then
pkmgr_cmd="zypper"
pkmgr_mkcache_cmd="true"
pkmgr_clean_cmd="$pkmgr_cmd clean --all"
pkmgr_update_cmd="$pkmgr_cmd update -y $PKMGR_OPTS"
pkmgr_install_cmd="$pkmgr_cmd install -y $PKMGR_OPTS"
else
pkmgr_cmd="true"
pkmgr_mkcache_cmd="$pkmgr_cmd"
pkmgr_clean_cmd="$pkmgr_cmd"
pkmgr_update_cmd="$pkmgr_cmd"
pkmgr_install_cmd="$pkmgr_cmd"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -f "/config/pkmgr/settings.conf" ]; then
. "/config/pkmgr/settings.conf"
elif [ -f "/etc/pkmgr/settings.conf" ]; then
. "/etc/pkmgr/settings.conf"
else
mkdir -p "/config/pkmgr"
cat <<EEOF >"/config/pkmgr/settings.conf"
pkmgr_cmd="$pkmgr_cmd"
pkmgr_clean_cmd="$pkmgr_clean_cmd"
pkmgr_update_cmd="$pkmgr_update_cmd"
pkmgr_install_cmd="$pkmgr_install_cmd"
pkmgr_mkcache_cmd="$pkmgr_mkcache_cmd"
EEOF
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ -n "$pkmgr_cmd" ] || { echo "Can not determine the package manager" && exit 1; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
case "$1" in
pip)
shift 1
pip_bin="$(command -v python3 2>/dev/null || command -v python2 2>/dev/null || command -v python 2>/dev/null || echo "")"
py_version="$($pip_bin --version | sed 's|[pP]ython ||g' | awk -F '.' '{print $1$2}' | grep '[0-9]' || echo "0")"
[ "$py_version" -gt "310" ] && pip_opts="--break-system-packages " || pip_opts=""
case "$1" in
install)
shift 1
pkg_list="$*"
for pkg in $pkg_list; do
$pip_bin -m pip $pip_opts "$pkg"
done
;;
*)
for pkg in "$@"; do
$pip_bin -m pip "$pkg"
done
;;
esac
exit
;;
install)
shift 1
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_install_cmd="sudo $pkmgr_install_cmd"
if [ -f "$1" ]; then
install_list="$(tr '\n' ' ' < "$1")"
else
install_list="$*"
fi
for pkg in $install_list;do
echo "installing packages command: $pkmgr_install_cmd $pkg"
$pkmgr_install_cmd $pkg
if [ -n "$pkmgr_install_post" ]; then eval $pkmgr_install_post; fi
done
exit
;;
update | upgrade)
shift $#
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_update_cmd="sudo $pkmgr_install_cmd"
echo "Updating packages command: $pkmgr_update_cmd"
$pkmgr_mkcache_cmd
$pkmgr_update_cmd
exit $?
;;
clean)
shift $#
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_clean_cmd="sudo $pkmgr_clean_cmd"
echo "Cleaning package cache: $pkmgr_clean_cmd"
$pkmgr_clean_cmd
exit $?
;;
*)
[ -n "$1" ] || exit 0
[ "$USER_UID" -eq 0 ] || [ "$USER" = "root" ] || pkmgr_cmd="sudo $pkmgr_cmd"
echo "executing packages command: $pkmgr_cmd $*"
$pkmgr_cmd "$@"
exit $?
;;
esac
# - - - - - - - - - - - - - - - - - - - - - - - - -
# end
+174
View File
@@ -0,0 +1,174 @@
#!/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=$?; 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
__log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >>"$RUNNERS_LOG_DIR/runners" 2>&1; }
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Function to cleanup child processes on exit
__cleanup() {
__log "Shutting down runners..."
kill $(jobs -p) 2>/dev/null || true
wait
__log "All runners stopped"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Set up signal handling
trap __cleanup SIGTERM SIGINT
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Validate required environment variables
if [ -n "$SERVER_ADDRESS" ]; then
if [[ "$SERVER_ADDRESS" != *"://"* ]]; then
SERVER_ADDRESS="http://$SERVER_ADDRESS"
fi
else
SERVER_ADDRESS=http://$HOSTNAME
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
if [ -z "$SERVER_TOKEN" ]; then
__log "ERROR: SERVER_TOKEN environment variable is required"
exit 1
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
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}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Validate RUNNERS_START is a positive integer
if ! [[ "$RUNNERS_START" =~ ^[0-9]+$ ]] || [ "$RUNNERS_START" -lt 1 ]; then
__log "WARNING: Invalid RUNNERS_START value '$RUNNERS_START', defaulting to 1"
RUNNERS_START=1
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
__log "Starting $RUNNERS_START act_runner instance(s)"
__log "Server Address: $SERVER_ADDRESS"
__log "Runner Name Prefix: ${RUNNER_NAME_PREFIX:-runner}"
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Shared cache config so runner-N instances use the same cache-server
# started by zz-act_runner.sh instead of an unshared per-process cache.
RUNNERS_CACHE_CONFIG=""
if [ -n "$RUNNER_CACHE_HOST" ] && [ -n "$RUNNER_CACHE_PORT" ] && [ -n "$RUNNER_CACHE_SECRET" ]; then
RUNNERS_CACHE_CONFIG="/config/act_runner/runners-cache.yaml"
cat <<EOF >"$RUNNERS_CACHE_CONFIG"
cache:
enabled: true
external_server: 'http://${RUNNER_CACHE_HOST}:${RUNNER_CACHE_PORT}/'
external_secret: '${RUNNER_CACHE_SECRET}'
EOF
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Register a single runner synchronously (no daemon start)
__register_runner() {
local runner_id=$1
local runner_name="${RUNNER_NAME_PREFIX:-runner}-${runner_id}"
local runner_dir="/config/act_runner/reg/${runner_name}"
local config_args=()
mkdir -p "$runner_dir"
[ -d "$runner_dir" ] && cd "$runner_dir" || return 1
[ -n "$RUNNERS_CACHE_CONFIG" ] && config_args=(--config "$RUNNERS_CACHE_CONFIG")
if [ ! -f "$runner_dir/.runner" ]; then
__log "Registering runner: $runner_name (ID: $runner_id)"
act_runner register "${config_args[@]}" --instance "$SERVER_ADDRESS" --token "$SERVER_TOKEN" --name "$runner_name" --labels "$RUNNER_LABELS" --no-interactive
if [ $? -ne 0 ]; then
__log "ERROR: Failed to register runner $runner_name"
return 1
fi
fi
__log "Runner $runner_name registered"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Start daemon for a single runner (called in background after all are registered)
__start_runner_daemon() {
local runner_id=$1
local runner_name="${RUNNER_NAME_PREFIX:-runner}-${runner_id}"
local runner_dir="/config/act_runner/reg/${runner_name}"
local config_args=()
[ -d "$runner_dir" ] && cd "$runner_dir" || return 1
[ -n "$RUNNERS_CACHE_CONFIG" ] && config_args=(--config "$RUNNERS_CACHE_CONFIG")
__log "Starting daemon for runner: $runner_name"
exec act_runner daemon "${config_args[@]}"
}
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Phase 1: register all runners sequentially so IDs are assigned in order
for i in $(seq 1 $RUNNERS_START); do
__register_runner "$i" || { __log "Aborting: registration failed for runner-$i"; exit 1; }
done
unset i
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Phase 2: start all daemons in parallel
for i in $(seq 1 $RUNNERS_START); do
(__start_runner_daemon "$i") &
done
unset i
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
RUNNERS_ID="$(jobs -p | tr '\n' ' ')"
if [ -n "$RUNNERS_ID" ]; then
__log "All $RUNNERS_START runners started successfully"
__log "Process IDs: $RUNNERS_ID"
printf 'All %s runners started successfully: %s\n' "$RUNNERS_START" "$RUNNERS_ID"
else
__log "The runners have failed to start"
printf '%s\n' "The runners have failed to start"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
# Wait for all background processes
wait
+77
View File
@@ -0,0 +1,77 @@
#!/usr/bin/env sh
# shellcheck shell=sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202605051306-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : WTFPL
# @@ReadME : symlink --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Tuesday, May 05, 2026 13:06 EDT
# @@File : symlink
# @@Description :
# @@Changelog : New script
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : shell/sh
# - - - - - - - - - - - - - - - - - - - - - - - - -
# shellcheck disable=SC1001,SC1003,SC2001,SC2003,SC2016,SC2031,SC2090,SC2115,SC2120,SC2155,SC2199,SC2229,SC2317,SC2329
# - - - - - - - - - - - - - - - - - - - - - - - - -
APPNAME="$(basename -- "$0" 2>/dev/null)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# colorization
if [ -n "$NO_COLOR" ]; then
__printf_color() { printf '%b' "$1\n" | tr -d '\t' | sed '/^%b$/d;s,\x1B\[ 0-9;]*[a-zA-Z],,g'; }
else
__printf_color() { { [ -z "$2" ] || DEFAULT_COLOR=$2; } && printf "%b" "$(tput setaf "$DEFAULT_COLOR" 2>/dev/null)" "$1\n" "$(tput sgr0 2>/dev/null)"; }
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
__unlink() { [ -L "$1" ] && rm -f -- "$1" >/dev/null; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
# custom functions
__ln_sf() {
exitCode=0
if [ -d "$1" ] && [ ! -L "$1" ]; then
__printf_color "symlinking contents of $1 into $2/" "4"
__unlink "$2"
mkdir -p "$2"
for f in "$1"/* "$1"/.[!.]* "$1"/..?*; do
[ -e "$f" ] || [ -L "$f" ] || continue
base=$(basename -- "$f")
__ln_sf "$f" "$2/$base" || exitCode=$?
done
else
__printf_color "symlinking $2 to $1" "4"
__unlink "$2"
ln -sf "$1" "$2"
exitCode=$?
fi
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Define variables
DEFAULT_COLOR="254"
SYMLINK_EXIT_STATUS=0
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Main application
if [ $# -ne 2 ]; then
__printf_color "USAGE: $APPNAME from to" "2" >&2
SYMLINK_EXIT_STATUS=1
elif [ ! -e "$1" ]; then
__printf_color "$1 does not exist" >&2
SYMLINK_EXIT_STATUS=2
else
__ln_sf "$1" "$2" >/dev/null
SYMLINK_EXIT_STATUS=$?
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# End application
# - - - - - - - - - - - - - - - - - - - - - - - - -
# lets exit with code
# - - - - - - - - - - - - - - - - - - - - - - - - -
exit $SYMLINK_EXIT_STATUS
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ex: ts=2 sw=2 et filetype=sh
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+983
View File
@@ -0,0 +1,983 @@
#!/usr/bin/env bash
# shellcheck shell=bash
# - - - - - - - - - - - - - - - - - - - - - - - - -
##@Version : 202609030601-git
# @@Author : Jason Hempstead
# @@Contact : jason@casjaysdev.pro
# @@License : LICENSE.md
# @@ReadME : 08-forgejo.sh --help
# @@Copyright : Copyright: (c) 2026 Jason Hempstead, Casjays Developments
# @@Created : Sunday, May 24, 2026 11:59 EDT
# @@File : 08-forgejo.sh
# @@Description :
# @@Changelog : New script
# @@TODO : Better documentation
# @@Other :
# @@Resource :
# @@Terminal App : no
# @@sudo/root : no
# @@Template : other/start-service
# - - - - - - - - - - - - - - - - - - - - - - - - -
# 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
trap '__trap_err_handler' ERR
trap 'retVal=$?;if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then rm -Rf "$SERVICE_PID_FILE"; fi;exit $retVal' SIGINT SIGTERM
trap 'retVal=$?;if [ "$SERVICE_IS_RUNNING" != "yes" ] && [ -f "$SERVICE_PID_FILE" ]; then rm -Rf "$SERVICE_PID_FILE"; fi;exit $retVal' SIGPWR 2>/dev/null || true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ERR trap handler - smart about critical vs non-critical errors
__trap_err_handler() {
local retVal=$?
local command="$BASH_COMMAND"
# Ignore SIGPIPE and user interrupts
[ $retVal -eq 130 ] || [ $retVal -eq 141 ] && return $retVal
# Non-critical: file operations, text processing, user/group operations
if [[ "$command" =~ (mkdir|touch|chmod|chown|chgrp|ln|cp|mv|rm|echo|printf|cat|tee|sed|awk|grep|find|sort|uniq|adduser|addgroup|usermod|groupmod|id|getent) ]]; then
return 0
fi
# Non-critical: conditional checks that might fail
if [[ "$command" =~ (test|\[|\[\[|kill -0|pgrep|pidof|ps) ]]; then
return 0
fi
# Critical error - but only fail if service hasn't started yet
if [ "$SERVICE_IS_RUNNING" != "yes" ]; then
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
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
SCRIPT_FILE="$0"
SERVICE_NAME="forgejo"
SCRIPT_NAME="${SCRIPT_FILE##*/}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Function to exit appropriately based on context
__script_exit() {
local exit_code="${1:-0}"
if [ "${BASH_SOURCE[0]}" != "${0}" ]; then
# Script is being sourced - use return
return "$exit_code"
else
# Script is being executed - use exit
exit "$exit_code"
fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Exit if service is disabled
if [ -n "$FORGEJO_APPNAME_ENABLED" ]; then
if [ "$FORGEJO_APPNAME_ENABLED" != "yes" ]; then
export SERVICE_DISABLED="$SERVICE_NAME"
__script_exit 0
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# setup debugging - https://www.gnu.org/software/bash/manual/html_node/The-Set-Builtin.html
[ -f "/config/.debug" ] && [ -z "$DEBUGGER_OPTIONS" ] && export DEBUGGER_OPTIONS="$(<"/config/.debug")" || DEBUGGER_OPTIONS="${DEBUGGER_OPTIONS:-}"
if [ "$DEBUGGER" = "on" ] || [ -f "/config/.debug" ]; then
echo "Enabling debugging"
set -o pipefail
[ -n "$DEBUGGER_OPTIONS" ] && set -"$DEBUGGER_OPTIONS"
export DEBUGGER="on"
else
set -o pipefail
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
export PATH="/usr/local/etc/docker/bin:/usr/local/bin:/usr/bin:/usr/sbin:/bin:/sbin"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import the functions file
if [ -f "/usr/local/etc/docker/functions/entrypoint.sh" ]; then
. "/usr/local/etc/docker/functions/entrypoint.sh"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# import variables
for set_env in "/root/env.sh" "/usr/local/etc/docker/env"/*.sh "/config/env"/*.sh; do
if [ -f "$set_env" ]; then
. "$set_env"
fi
done
# - - - - - - - - - - - - - - - - - - - - - - - - -
# exit if __start_init_scripts function hasn't been Initialized
if [ ! -f "/run/.start_init_scripts.pid" ]; then
echo "__start_init_scripts function hasn't been Initialized" >&2
SERVICE_IS_RUNNING="no"
__script_exit 1
fi
# Clean up any stale PID file for this service on startup
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
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
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom functions
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Script to execute
START_SCRIPT="/usr/local/etc/docker/exec/$SERVICE_NAME"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Reset environment before executing service
RESET_ENV="no"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set webroot
WWW_ROOT_DIR="/usr/local/share/httpd/default"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Default predefined variables
# set data directory
DATA_DIR="/data/forgejo"
# set config directory
CONF_DIR="/config/forgejo"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set the containers etc directory
ETC_DIR="/etc/forgejo"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set the var dir
VAR_DIR=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set the temp dir
TMP_DIR="/tmp/forgejo"
# set scripts pid dir
RUN_DIR="/run/forgejo"
# set log directory
LOG_DIR="/data/logs/forgejo"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the working dir
WORK_DIR="/data/forgejo"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# port which service is listening on
SERVICE_PORT="80"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User to use to launch service - IE: postgres
# forgejo must run as git user, not root
RUNAS_USER="git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# User and group in which the service switches to - IE: nginx,apache,mysql,postgres
# execute command as another user
SERVICE_USER="git"
# Set the service group
SERVICE_GROUP="git"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set password length
RANDOM_PASS_USER=""
RANDOM_PASS_ROOT=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set user and group ID
# set the user id
SERVICE_UID="0"
# set the group id
SERVICE_GID="0"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# execute command variables - keep single quotes variables will be expanded later
# command to execute
EXEC_CMD_BIN='forgejo'
# command arguments
EXEC_CMD_ARGS='web '
# command arguments
EXEC_CMD_ARGS+='--port $SERVICE_PORT --config $CONF_DIR/app.ini '
# command arguments
EXEC_CMD_ARGS+='--custom-path $CONF_DIR/custom --work-path $DATA_DIR '
# execute script before
EXEC_PRE_SCRIPT=''
# Set to no if the service is not running otherwise leave blank
SERVICE_USES_PID=''
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Is this service a web server
IS_WEB_SERVER="no"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Is this service a database server
IS_DATABASE_SERVICE="no"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Does this service use a database server
USES_DATABASE_SERVICE="no"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set defualt type - [custom,sqlite,redis,postgres,mariadb,mysql,couchdb,mongodb,supabase]
DATABASE_SERVICE_TYPE="sqlite"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Show message before execute
PRE_EXEC_MESSAGE=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set the wait time to execute __post_execute function - minutes
POST_EXECUTE_WAIT_TIME="1"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Update path var
PATH="$PATH:."
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Lets get containers ip address
IP4_ADDRESS="$(__get_ip4)"
IP6_ADDRESS="$(__get_ip6)"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Where to save passwords to
# directory to save username/password for root user
ROOT_FILE_PREFIX="/config/secure/auth/root"
# directory to save username/password for normal user
USER_FILE_PREFIX="/config/secure/auth/user"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# root/admin user info password/random]
# root user name
root_user_name="${FORGEJO_ROOT_USER_NAME:-}"
# root user password
root_user_pass="${FORGEJO_ROOT_PASS_WORD:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Normal user info [password/random]
# normal user name
user_name="${FORGEJO_USER_NAME:-}"
# normal user password
user_pass="${FORGEJO_USER_PASS_WORD:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Load variables from config
# Generated by my dockermgr script
[ -f "/config/env/forgejo.script.sh" ] && . "/config/env/forgejo.script.sh"
# Overwrite the variabes
[ -f "/config/env/forgejo.sh" ] && . "/config/env/forgejo.sh"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional predefined variables
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional variables
DATABASE_DIR="${DATABASE_DIR_SQLITE:-$DATA_DIR/db/sqlite}"
FORGEJO_SQL_NAME="${FORGEJO_SQL_NAME:-}"
FORGEJO_SQL_HOST="${FORGEJO_SQL_HOST:-localhost}"
FORGEJO_WORK_DIR="${FORGEJO_WORK_DIR:-$WORK_DIR}"
TZ="${FORGEJO_TZ:-${TZ:-America/New_York}}"
# Map container-generic protocol env vars to SERVICE_PROTOCOL
SERVICE_PROTOCOL="${FORGEJO_PROTO:-${CONTAINER_PROTOCOL:-${CONTAINER_WEB_SERVER_PROTOCOL:-${SERVICE_PROTOCOL:-http}}}}"
# Map container-generic port env vars to SERVICE_PORT
SERVICE_PORT="${WEB_PORT:-${ENV_PORTS:-${SERVICE_PORT:-80}}}"
EMAIL_RELAY="${FORGEJO_EMAIL_RELAY:-${EMAIL_RELAY:-172.17.0.1}}"
SERVER_SITE_TITLE="${FORGEJO_NAME:-${SERVER_SITE_TITLE:-SelfHosted GIT Server}}"
SERVER_ADMIN="${FORGEJO_ADMIN:-${SERVER_ADMIN:-administrator@${HOSTNAME}}}"
FORGEJO_SERVER="${ENV_FORGEJO_SERVER:-$FORGEJO_SERVER}"
FORGEJO_EMAIL_CONFIRM="${FORGEJO_EMAIL_CONFIRM:-false}"
FORGEJO_SQL_DB_HOST="${FORGEJO_SQL_DB_HOST:-localhost}"
FORGEJO_SQL_USER="${ENV_FORGEJO_SQL_USER:-$FORGEJO_SQL_USER}"
FORGEJO_SQL_PASS="${ENV_FORGEJO_SQL_PASS:-$FORGEJO_SQL_PASS}"
# Map CONTAINER_DEFAULT_DATABASE_TYPE to forgejo's DB_TYPE value
if [ -n "$CONTAINER_DEFAULT_DATABASE_TYPE" ]; then
DATABASE_SERVICE_TYPE="$CONTAINER_DEFAULT_DATABASE_TYPE"
case "$CONTAINER_DEFAULT_DATABASE_TYPE" in
sqlite|sqlite3) FORGEJO_SQL_TYPE="${FORGEJO_SQL_TYPE:-sqlite3}" ;;
postgres|postgresql) FORGEJO_SQL_TYPE="${FORGEJO_SQL_TYPE:-postgres}" ;;
mysql|mariadb) FORGEJO_SQL_TYPE="${FORGEJO_SQL_TYPE:-mysql}" ;;
mssql) FORGEJO_SQL_TYPE="${FORGEJO_SQL_TYPE:-mssql}" ;;
esac
fi
FORGEJO_SQL_TYPE="${ENV_FORGEJO_SQL_TYPE:-${FORGEJO_SQL_TYPE:-sqlite3}}"
HOSTNAME="${FORGEJO_SERVER:-${FORGEJO_HOSTNAME:-${FULL_DOMAIN_NAME:-$(hostname -f 2>/dev/null || echo "$HOSTNAME")}}}"
SERVER_NAME="${DOMAIN:-$HOSTNAME}"
SERVER_PROTO="${SERVICE_PROTOCOL:-http}"
# Feed SERVER_NAME back into FULL_DOMAIN_NAME so __initialize_replace_variables
# uses DOMAIN (if set) rather than falling back to the raw HOSTNAME.
export FULL_DOMAIN_NAME="$SERVER_NAME"
FORGEJO_SECRET_KEY="${FORGEJO_SECRET_KEY:-$(__random_password 32)}"
FORGEJO_LFS_JWT_SECRET="${FORGEJO_LFS_JWT_SECRET:-$($EXEC_CMD_BIN generate secret LFS_JWT_SECRET)}"
FORGEJO_INTERNAL_TOKEN="${FORGEJO_INTERNAL_TOKEN:-$($EXEC_CMD_BIN generate secret INTERNAL_TOKEN)}"
FORGEJO_RANDOM_COOKIE_KEY="${FORGEJO_RANDOM_COOKIE_KEY:-$(__random_password 16)}"
[ "$FORGEJO_EMAIL_CONFIRM" = "yes" ] && FORGEJO_EMAIL_CONFIRM="true"
export CUSTOM_PATH="$CONF_DIR/custom" WORK_DIR="${FORGEJO_WORK_DIR:-$DATA_DIR}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Specifiy custom directories to be created
ADD_APPLICATION_FILES=""
ADD_APPLICATION_DIRS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
APPLICATION_FILES="$LOG_DIR/$SERVICE_NAME.log"
APPLICATION_DIRS="$ETC_DIR $CONF_DIR $DATA_DIR $LOG_DIR $TMP_DIR $RUN_DIR $VAR_DIR"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Additional config dirs - will be Copied to /etc/$name
ADDITIONAL_CONFIG_DIRS=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# define variables that need to be loaded into the service - escape quotes - var=\"value\",other=\"test\"
CMD_ENV=""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Overwrite based on file/directory
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Per Application Variables or imports
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom commands to run before copying to /config
__run_precopy() {
# Define environment
local hostname=${HOSTNAME}
[ -d "/run/healthcheck" ] || mkdir -p "/run/healthcheck"
# Re-apply custom resolv.conf — Docker rewrites /etc/resolv.conf asynchronously
# during container startup, after the entrypoint's initial copy. Applying it here
# (in the init.d phase) ensures it takes effect after Docker finishes network setup.
[ -f "/usr/local/etc/resolv.conf" ] && cp -f "/usr/local/etc/resolv.conf" "/etc/resolv.conf" 2>/dev/null || true
# Seed /config/$SERVICE_NAME from the baked /etc copy on first initialisation only.
# The marker file $CONF_DIR/.initialized is written after substitution completes;
# delete it to force a re-seed (e.g. after intentional config reset).
# Then replace the /etc/$SERVICE_NAME directory with a symlink to /config/$SERVICE_NAME
# so both paths always resolve to the same processed config.
if [ -d "$ETC_DIR" ] && ! [ -L "$ETC_DIR" ]; then
if [ ! -f "$CONF_DIR/.initialized" ]; then
mkdir -p "$CONF_DIR"
cp -Rf "$ETC_DIR/." "$CONF_DIR/" 2>/dev/null || true
fi
rm -Rf "$ETC_DIR"
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
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Custom prerun functions - IE setup WWW_ROOT_DIR
__execute_prerun() {
# Define environment
local hostname=${HOSTNAME}
# Define actions/commands
# allow custom functions
if builtin type -t __execute_prerun_local | grep -q -- 'function'; then __execute_prerun_local; fi
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Run any pre-execution checks
__run_pre_execute_checks() {
# Set variables
local exitStatus=0
# message to show at start
local pre_execute_checks_MessageST="Running preexecute check for $SERVICE_NAME"
# message to show at completion
local pre_execute_checks_MessageEnd="Finished preexecute check for $SERVICE_NAME"
__banner "$pre_execute_checks_MessageST"
# Put command to execute in parentheses
{
true
}
exitStatus=$?
__banner "$pre_execute_checks_MessageEnd: Status $exitStatus"
# show exit message
if [ $exitStatus -ne 0 ]; then
echo "The pre-execution check has failed" >&2
[ -f "$SERVICE_PID_FILE" ] && rm -Rf "$SERVICE_PID_FILE"
__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
# exit function
return $exitStatus
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# use this function to update config files - IE: change port
__update_conf_files() {
# default exit code
local exitCode=0
# set hostname
local sysname="${SERVER_NAME:-${FULL_DOMAIN_NAME:-$HOSTNAME}}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# delete files
#__rm ""
# - - - - - - - - - - - - - - - - - - - - - - - - -
# custom commands
__is_dir_empty "/config/ssh" && COPY_SSHD_CONF="yes"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# replace variables
__replace "REPLACE_SSH_CONF_DIR" "/config/ssh" "/etc/ssh/sshd_config"
__replace "REPLACE_SSH_DATA_DIR" "$DATA_DIR/ssh" "/etc/ssh/sshd_config"
__replace "REPLACE_RANDOM_COOKIE_KEY" "$FORGEJO_RANDOM_COOKIE_KEY" "$CONF_DIR/app.ini"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# define actions
[ -d "/config/ssh" ] || mkdir -p "/config/ssh"
[ -d "$DATA_DIR/ssh" ] || mkdir -p "$DATA_DIR/ssh"
[ "$COPY_SSHD_CONF" = "yes" ] && copy "/etc/ssh/sshd_config" "/config/ssh/"
if [ ! -f "/config/ssh/ssh_host_ed25519_key" ]; then
echo "Generating /config/ssh/ssh_host_ed25519_key..."
ssh-keygen -t ed25519 -f /config/ssh/ssh_host_ed25519_key -N "" >/dev/null && __symlink "/config/ssh/ssh_host_ed25519_key" "$DATA_DIR/ssh/ssh_host_ed25519_key"
fi
if [ ! -f "/config/ssh/ssh_host_rsa_key" ]; then
echo "Generating /config/ssh/ssh_host_rsa_key..."
ssh-keygen -t rsa -b 3072 -f /config/ssh/ssh_host_rsa_key -N "" >/dev/null && __symlink "/config/ssh/ssh_host_rsa_key" "$DATA_DIR/ssh/ssh_host_rsa_key"
fi
if [ ! -f "/config/ssh/ssh_host_ecdsa_key" ]; then
echo "Generating /config/ssh/ssh_host_ecdsa_key..."
ssh-keygen -t ecdsa -b 256 -f /config/ssh/ssh_host_ecdsa_key -N "" >/dev/null && __symlink "/config/ssh/ssh_host_ecdsa_key" "$DATA_DIR/ssh/ssh_host_ecdsa_key"
fi
chmod 0700 "$DATA_DIR/ssh" /config/ssh
find "$DATA_DIR/ssh" /config/ssh -maxdepth 1 -type f -exec chmod 0600 {} \;
[ -d "$DATA_DIR/ssh" ] || mkdir -p "$DATA_DIR/ssh"
[ -d "$CONF_DIR/custom" ] || mkdir -p "$CONF_DIR/custom"
if [ -n "$CONF_DIR" ] && [ -f "$CONF_DIR/app.ini" ]; then
sed -i "s|REPLACE_SQL_NAME|$FORGEJO_SQL_NAME|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_SQL_USER|$FORGEJO_SQL_USER|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_SQL_PASS|$FORGEJO_SQL_PASS|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_SQL_TYPE|${FORGEJO_SQL_TYPE}|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_SQL_HOST|$FORGEJO_SQL_DB_HOST|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_DATABASE_DIR|$DATABASE_DIR|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_SECRET_KEY|$FORGEJO_SECRET_KEY|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_FORGEJO_EMAIL_CONFIRM|$FORGEJO_EMAIL_CONFIRM|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_FORGEJO_INTERNAL_TOKEN|$FORGEJO_INTERNAL_TOKEN|g" "$CONF_DIR/app.ini"
sed -i "s|REPLACE_FORGEJO_LFS_JWT_SECRET|$FORGEJO_LFS_JWT_SECRET|g" "$CONF_DIR/app.ini"
fi
# Re-stamp dynamic values and remove deprecated settings on every startup.
for _ini_file in "$CONF_DIR/app.ini"; do
[ -f "$_ini_file" ] || continue
# Sync ROOT_URL, DOMAIN, and SSH_DOMAIN — prefer DOMAIN env var over raw hostname
sed -i "s|^ROOT_URL[[:space:]]*=.*|ROOT_URL = ${SERVICE_PROTOCOL:-http}://${SERVER_NAME}|" "$_ini_file"
sed -i "s|^DOMAIN[[:space:]]*=.*|DOMAIN = ${SERVER_NAME}|" "$_ini_file"
sed -i "s|^SSH_DOMAIN[[:space:]]*=.*|SSH_DOMAIN = ${SERVER_NAME}|" "$_ini_file"
# Remove deprecated [cors].X_FRAME_OPTIONS (moved to [security] in Gitea v1.26)
awk 'BEGIN{in_s=0}/^\[/{in_s=0}/^\[cors\]/{in_s=1}in_s&&/^X_FRAME_OPTIONS/{next}{print}' \
"$_ini_file" > /tmp/_forgejo_conf.ini && mv /tmp/_forgejo_conf.ini "$_ini_file"
# Remove deprecated [picture].DISABLE_GRAVATAR (moved to admin panel in Gitea v1.18)
awk 'BEGIN{in_s=0}/^\[/{in_s=0}/^\[picture\]/{in_s=1}in_s&&/^DISABLE_GRAVATAR/{next}{print}' \
"$_ini_file" > /tmp/_forgejo_conf.ini && mv /tmp/_forgejo_conf.ini "$_ini_file"
# Remove deprecated [picture].ENABLE_FEDERATED_AVATAR (moved to admin panel in Gitea v1.18)
awk 'BEGIN{in_s=0}/^\[/{in_s=0}/^\[picture\]/{in_s=1}in_s&&/^ENABLE_FEDERATED_AVATAR/{next}{print}' \
"$_ini_file" > /tmp/_forgejo_conf.ini && mv /tmp/_forgejo_conf.ini "$_ini_file"
done
unset _ini_file
if [ -n "$DATA_DIR" ] && [ -d "$DATA_DIR" ]; then
find "$DATA_DIR" -type d -exec chmod 0777 {} \;
chown -Rf $SERVICE_USER:$SERVICE_GROUP "$DATA_DIR" 2>/dev/null
fi
[ -d "$DATABASE_DIR" ] && chown -Rf $SERVICE_USER:$SERVICE_GROUP "$DATABASE_DIR" 2>/dev/null
# 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
# exit function
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# function to run before executing
__pre_execute() {
# default exit code
local exitCode=0
# set hostname
local sysname="${SERVER_NAME:-${FULL_DOMAIN_NAME:-$HOSTNAME}}"
# execute if directories is empty
# __is_dir_empty "$CONF_DIR" && true
# - - - - - - - - - - - - - - - - - - - - - - - - -
# define actions to run after copying to /config
# - - - - - - - - - - - - - - - - - - - - - - - - -
# unset unneeded variables
unset sysname
# 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
# exit function
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# function to run after executing
__post_execute() {
# init pid var
local pid=""
# set default exit code
local retVal=0
# how long to wait before executing
local ctime=${POST_EXECUTE_WAIT_TIME:-1}
# convert minutes to seconds
local waitTime=$((ctime * 60))
# message to show at start
local postMessageST="Running post commands for $SERVICE_NAME"
# message to show at completion
local postMessageEnd="Finished post commands for $SERVICE_NAME"
# wait
sleep $waitTime
# execute commands after waiting
(
# show message
__banner "$postMessageST"
# commands to execute
sleep 5
# show exit message
__banner "$postMessageEnd: Status $retVal"
) 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
# 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
# exit function
return $retVal
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# use this function to update config files - IE: change port
__pre_message() {
local exitCode=0
[ -n "$PRE_EXEC_MESSAGE" ] && eval echo "$PRE_EXEC_MESSAGE"
# execute commands
# allow custom functions
if builtin type -t __pre_message_local | grep -q -- 'function'; then __pre_message_local; fi
# exit function
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# use this function to setup ssl support
__update_ssl_conf() {
local exitCode=0
# set hostname
local sysname="${SERVER_NAME:-${FULL_DOMAIN_NAME:-$HOSTNAME}}"
# execute commands
# allow custom functions
if builtin type -t __update_ssl_conf_local | grep -q -- 'function'; then __update_ssl_conf_local; fi
# set exitCode
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
__create_service_env() {
local exitCode=0
if [ ! -f "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh" ]; then
cat <<EOF | tee -p "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh" &>/dev/null
# - - - - - - - - - - - - - - - - - - - - - - - - -
# root/admin user info [password/random]
#ENV_ROOT_USER_NAME="${ENV_ROOT_USER_NAME:-$FORGEJO_ROOT_USER_NAME}" # root user name
#ENV_ROOT_USER_PASS="${ENV_ROOT_USER_NAME:-$FORGEJO_ROOT_PASS_WORD}" # root user password
#root_user_name="${ENV_ROOT_USER_NAME:-$root_user_name}" #
#root_user_pass="${ENV_ROOT_USER_PASS:-$root_user_pass}" #
# - - - - - - - - - - - - - - - - - - - - - - - - -
#Normal user info [password/random]
#ENV_USER_NAME="${ENV_USER_NAME:-$FORGEJO_USER_NAME}" #
#ENV_USER_PASS="${ENV_USER_PASS:-$FORGEJO_USER_PASS_WORD}" #
#user_name="${ENV_USER_NAME:-$user_name}" # normal user name
#user_pass="${ENV_USER_PASS:-$user_pass}" # normal user password
EOF
fi
if [ ! -f "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.local.sh" ]; then
cat <<'EOF' >"/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.local.sh"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Local overrides - sourced after the main env file.
# Redefine any of these functions to customise behaviour.
# - - - - - - - - - - - - - - - - - - - - - - - - -
__run_precopy_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__execute_prerun_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__run_pre_execute_checks_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__update_conf_files_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__pre_execute_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__post_execute_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__pre_message_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
__update_ssl_conf_local() { true; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
EOF
fi
__file_exists_with_content "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh" || exitCode=$((exitCode + 1))
__file_exists_with_content "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.local.sh" || exitCode=$((exitCode + 1))
return $exitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# script to start server
__run_start_script() {
local runExitCode=0
# expand variables
local workdir="$(eval echo "${WORK_DIR:-}")"
# expand variables
local cmd="$(eval echo "${EXEC_CMD_BIN:-}")"
# expand variables
local args="$(eval echo "${EXEC_CMD_ARGS:-}")"
# expand variables
local name="$(eval echo "${EXEC_CMD_NAME:-}")"
# expand variables
local pre="$(eval echo "${EXEC_PRE_SCRIPT:-}")"
# expand variables
local extra_env="$(eval echo "${CMD_ENV//,/ }")"
# expand variables
local lc_type="$(eval echo "${LANG:-${LC_ALL:-$LC_CTYPE}}")"
# expand variables
local home="$(eval echo "${workdir//\/root/\/tmp\/docker}")"
# expand variables
local path="$(eval echo "$PATH")"
# expand variables
local message="$(eval echo "")"
local sysname="${SERVER_NAME:-${FULL_DOMAIN_NAME:-$HOSTNAME}}"
if [ -f "$CONF_DIR/$SERVICE_NAME.exec_cmd.sh" ]; then
. "$CONF_DIR/$SERVICE_NAME.exec_cmd.sh"
fi
#
if [ -z "$cmd" ]; then
__post_execute 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt"
retVal=$?
__log_info "Initialization of $SCRIPT_NAME has completed"
__script_exit $retVal
else
# ensure the command exists
if [ ! -x "$cmd" ]; then
__log_error "$name is not a valid executable"
return 2
fi
# check and exit if already running (respects SERVICE_USES_PID in __proc_check)
if __proc_check "$name" || __proc_check "$cmd"; then
__log_debug "Service $name is already running"
return 0
else
# - - - - - - - - - - - - - - - - - - - - - - - - -
# show message if env exists
if [ -n "$cmd" ]; then
if [ -n "$SERVICE_USER" ]; then
__log_info "Setting up $cmd to run as $SERVICE_USER"
else
SERVICE_USER="root"
fi
if [ -n "$SERVICE_PORT" ]; then
__log_info "$name will be running on port $SERVICE_PORT"
else
SERVICE_PORT=""
fi
fi
if [ -n "$pre" ] && command -v "$pre" &>/dev/null; then
export cmd_exec="$pre $cmd $args"
message="Starting service: $name $args through $pre"
else
export cmd_exec="$cmd $args"
message="Starting service: $name $args"
fi
if [ -n "$su_exec" ]; then
__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"
# W14: invalidate cached START_SCRIPT if key variables changed
local _script_hash_src="$cmd $args $SERVICE_USER $RESET_ENV $su_exec"
local _script_hash
_script_hash=$(printf '%s' "$_script_hash_src" | md5sum 2>/dev/null | cut -c1-8 || true)
if [ -f "${START_SCRIPT}.hash" ] && [ -f "$START_SCRIPT" ]; then
if [ "$(cat "${START_SCRIPT}.hash" 2>/dev/null)" != "$_script_hash" ]; then
rm -f "$START_SCRIPT" "${START_SCRIPT}.hash"
fi
fi
if [ "$RESET_ENV" = "yes" ]; then
# RESET_ENV=yes intentionally strips all inherited vars; only explicit vars are passed
if [ ! -f "$START_SCRIPT" ]; then
# Use printf %q to safely quote each env component for embedding in the script
local _q_home _q_lc _q_path _q_sysname _q_svcuser _q_su _q_cmd _q_args _q_extra
_q_home=$(printf '%q' "$home")
_q_lc=$(printf '%q' "$lc_type")
_q_path=$(printf '%q' "$path")
_q_sysname=$(printf '%q' "$sysname")
_q_svcuser=$(printf '%q' "${SERVICE_USER:-$RUNAS_USER}")
_q_su="${su_exec:+$(printf '%q ' $su_exec)}"
_q_cmd=$(printf '%q' "$cmd")
_q_args=$(printf '%q ' $args)
_q_extra=$(printf '%q ' $extra_env)
{
printf '#!/usr/bin/env bash\n'
printf "trap 'exitCode=\$?;[ \$exitCode -ne 0 ] && [ -f \"\$SERVICE_PID_FILE\" ] && rm -Rf \"\$SERVICE_PID_FILE\";exit \$exitCode' EXIT\n"
printf 'set -Eeo pipefail\n'
printf '# Setting up %s to run as %s with env\n' "$cmd" "${SERVICE_USER:-root}"
printf 'retVal=10\n'
printf 'SERVICE_NAME=%q\n' "$SERVICE_NAME"
printf 'SERVICE_PID_FILE=%q\n' "$SERVICE_PID_FILE"
printf 'LOG_DIR=%q\n' "$LOG_DIR"
printf '%senv -i HOME=%s LC_CTYPE=%s PATH=%s HOSTNAME=%s USER=%s %s %s %s 2>>"/dev/stderr" >>"$LOG_DIR/$SERVICE_NAME.log" &\n' \
"$_q_su" "$_q_home" "$_q_lc" "$_q_path" "$_q_sysname" "$_q_svcuser" "$_q_extra" "$_q_cmd" "$_q_args"
printf 'execPid=$!\n'
printf 'sleep 1\n'
printf 'if [ -n "$execPid" ] && kill -0 "$execPid" 2>/dev/null; then\n'
printf ' echo "$execPid" >"$SERVICE_PID_FILE"\n'
printf ' retVal=0\n'
printf ' printf '"'"'%%s\n'"'"' "$SERVICE_NAME: $execPid" >"/run/healthcheck/$SERVICE_NAME"\n'
printf 'else\n'
printf ' retVal=10\n'
printf ' echo "Failed to start service %s" >&2\n' "$cmd"
printf 'fi\n'
printf 'exit $retVal\n'
} >"$START_SCRIPT"
printf '%s' "$_script_hash" >"${START_SCRIPT}.hash"
fi
else
if [ ! -f "$START_SCRIPT" ]; then
local _q_su _q_cmd _q_args _q_path _q_home
_q_su="${su_exec:+$(printf '%q ' $su_exec)}"
_q_cmd=$(printf '%q' "$cmd")
_q_args=$(printf '%q ' $args)
_q_path=$(printf '%q' "$path")
_q_home=$(printf '%q' "$home")
{
printf '#!/usr/bin/env bash\n'
printf "trap 'exitCode=\$?;[ \$exitCode -ne 0 ] && [ -f \"\$SERVICE_PID_FILE\" ] && rm -Rf \"\$SERVICE_PID_FILE\";exit \$exitCode' EXIT\n"
printf 'set -Eeo pipefail\n'
printf '# Setting up %s to run as %s\n' "$cmd" "${SERVICE_USER:-root}"
printf 'export PATH=%s\n' "$_q_path"
printf 'export HOME=%s\n' "$_q_home"
printf 'retVal=10\n'
printf 'SERVICE_NAME=%q\n' "$SERVICE_NAME"
printf 'SERVICE_PID_FILE=%q\n' "$SERVICE_PID_FILE"
printf 'LOG_DIR=%q\n' "$LOG_DIR"
printf '%s%s %s 2>>"/dev/stderr" >>"$LOG_DIR/$SERVICE_NAME.log" &\n' \
"$_q_su" "$_q_cmd" "$_q_args"
printf 'execPid=$!\n'
printf 'sleep 1\n'
printf 'if [ -n "$execPid" ] && kill -0 "$execPid" 2>/dev/null; then\n'
printf ' echo "$execPid" >"$SERVICE_PID_FILE"\n'
printf ' retVal=0\n'
printf 'else\n'
printf ' retVal=10\n'
printf ' echo "Failed to start service %s" >&2\n' "$cmd"
printf 'fi\n'
printf 'exit $retVal\n'
} >"$START_SCRIPT"
printf '%s' "$_script_hash" >"${START_SCRIPT}.hash"
fi
fi
fi
if [ ! -x "$START_SCRIPT" ]; then
chmod 755 -Rf "$START_SCRIPT"
fi
if [ "$CONTAINER_INIT" != "yes" ]; then
# W15: launch as bash, not sh, since the generated script uses bash-specific features
bash "$START_SCRIPT"
runExitCode=$?
fi
fi
return $runExitCode
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# username and password actions
__run_secure_function() {
local filesperms
if [ -n "$user_name" ] || [ -n "$user_pass" ]; then
for filesperms in "${USER_FILE_PREFIX}"/*; do
if [ -e "$filesperms" ]; then
chmod -Rf 600 "$filesperms"
chown -Rf $SERVICE_USER:$SERVICE_USER "$filesperms" 2>/dev/null
fi
done 2>/dev/null | tee -p -a "/data/logs/init.txt"
fi
if [ -n "$root_user_name" ] || [ -n "$root_user_pass" ]; then
for filesperms in "${ROOT_FILE_PREFIX}"/*; do
if [ -e "$filesperms" ]; then
chmod -Rf 600 "$filesperms"
chown -Rf $SERVICE_USER:$SERVICE_USER "$filesperms" 2>/dev/null
fi
done 2>/dev/null | tee -p -a "/data/logs/init.txt"
fi
unset filesperms
}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Allow ENV_ variable - Import env file
__file_exists_with_content "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh" && . "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh"
__file_exists_with_content "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.local.sh" && . "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.local.sh"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# default exit code
SERVICE_EXIT_CODE=0
# application specific
# set the binary name
EXEC_CMD_NAME="${EXEC_CMD_BIN##*/}"
# set the pid file location
SERVICE_PID_FILE="/run/init.d/$EXEC_CMD_NAME.pid"
# check if running
SERVICE_PID_NUMBER="$(__pgrep "$EXEC_CMD_NAME" || echo '')"
# set full path
EXEC_CMD_BIN="$(type -P "$EXEC_CMD_BIN" || echo "$EXEC_CMD_BIN")"
# set full path
EXEC_PRE_SCRIPT="$(type -P "$EXEC_PRE_SCRIPT" || echo "$EXEC_PRE_SCRIPT")"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Only run check when explicitly requested
if [ "$1" = "check" ] && __check_service "$1"; then
SERVICE_IS_RUNNING=yes
elif [ "$1" = "check" ]; then
SERVICE_IS_RUNNING="no"
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# ensure needed directories exists
[ -d "$LOG_DIR" ] || mkdir -p "$LOG_DIR"
[ -d "$RUN_DIR" ] || mkdir -p "$RUN_DIR"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create auth directories
[ -n "$USER_FILE_PREFIX" ] && { [ -d "$USER_FILE_PREFIX" ] || mkdir -p "$USER_FILE_PREFIX"; }
[ -n "$ROOT_FILE_PREFIX" ] && { [ -d "$ROOT_FILE_PREFIX" ] || mkdir -p "$ROOT_FILE_PREFIX"; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ -n "$RUNAS_USER" ] || RUNAS_USER="root"
[ -n "$SERVICE_USER" ] || SERVICE_USER="$RUNAS_USER"
[ -n "$SERVICE_GROUP" ] || SERVICE_GROUP="${SERVICE_USER:-$RUNAS_USER}"
[ "$IS_WEB_SERVER" = "yes" ] && RESET_ENV="yes" && __is_htdocs_mounted
[ "$IS_WEB_SERVER" = "yes" ] && [ -z "$SERVICE_PORT" ] && SERVICE_PORT="80"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Database env
if [ "$IS_DATABASE_SERVICE" = "yes" ] || [ "$USES_DATABASE_SERVICE" = "yes" ]; then
RESET_ENV="no"
DATABASE_CREATE="${ENV_DATABASE_CREATE:-$DATABASE_CREATE}"
DATABASE_USER_NORMAL="${ENV_DATABASE_USER:-${DATABASE_USER_NORMAL:-$user_name}}"
DATABASE_PASS_NORMAL="${ENV_DATABASE_PASSWORD:-${DATABASE_PASS_NORMAL:-$user_pass}}"
DATABASE_USER_ROOT="${ENV_DATABASE_ROOT_USER:-${DATABASE_USER_ROOT:-$root_user_name}}"
DATABASE_PASS_ROOT="${ENV_DATABASE_ROOT_PASSWORD:-${DATABASE_PASS_ROOT:-$root_user_pass}}"
if [ -n "$DATABASE_PASS_NORMAL" ] && [ ! -f "${USER_FILE_PREFIX}/db_pass_user" ]; then
echo "$DATABASE_PASS_NORMAL" >"${USER_FILE_PREFIX}/db_pass_user"
fi
if [ -n "$DATABASE_PASS_ROOT" ] && [ ! -f "${ROOT_FILE_PREFIX}/db_pass_root" ]; then
echo "$DATABASE_PASS_ROOT" >"${ROOT_FILE_PREFIX}/db_pass_root"
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# [DATABASE_DIR_[SQLITE,REDIS,POSTGRES,MARIADB,COUCHDB,MONGODB,SUPABASE]]
if [ "$DATABASE_SERVICE_TYPE" = "custom" ]; then
DATABASE_DIR="${DATABASE_DIR_CUSTOM:-/data/db/custom}"
DATABASE_BASE_DIR="${DATABASE_DIR_CUSTOM:-/data/db/custom}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_CUSTOM:-/usr/local/share/httpd/admin/databases}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_CUSTOM:-/admin/dbadmin}"
elif [ "$SERVICE_NAME" = "redis" ] || [ "$DATABASE_SERVICE_TYPE" = "redis" ]; then
DATABASE_DIR="${DATABASE_DIR_REDIS:-/data/db/redis}"
DATABASE_BASE_DIR="${DATABASE_DIR_REDIS:-/data/db/redis}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_REDIS:-/usr/local/share/httpd/admin/redis}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_REDIS:-/admin/redis}"
elif [ "$SERVICE_NAME" = "postgres" ] || [ "$DATABASE_SERVICE_TYPE" = "postgres" ]; then
DATABASE_DIR="${DATABASE_DIR_POSTGRES:-/data/db/postgres}"
DATABASE_BASE_DIR="${DATABASE_DIR_POSTGRES:-/data/db/postgres}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_POSTGRES:-/usr/local/share/httpd/admin/postgres}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_POSTGRES:-/admin/postgres}"
elif [ "$SERVICE_NAME" = "mariadb" ] || [ "$DATABASE_SERVICE_TYPE" = "mariadb" ]; then
DATABASE_DIR="${DATABASE_DIR_MARIADB:-/data/db/mariadb}"
DATABASE_BASE_DIR="${DATABASE_DIR_MARIADB:-/data/db/mariadb}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_MARIADB:-/usr/local/share/httpd/admin/mysql}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_MARIADB:-/admin/mysql}"
elif [ "$SERVICE_NAME" = "mysql" ] || [ "$DATABASE_SERVICE_TYPE" = "mysql" ]; then
DATABASE_DIR="${DATABASE_DIR_MYSQL:-/data/db/mysql}"
DATABASE_BASE_DIR="${DATABASE_DIR_MYSQL:-/data/db/mysql}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_MYSQL:-/usr/local/share/httpd/admin/mysql}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_MYSQL:-/admin/mysql}"
elif [ "$SERVICE_NAME" = "couchdb" ] || [ "$DATABASE_SERVICE_TYPE" = "couchdb" ]; then
DATABASE_DIR="${DATABASE_DIR_COUCHDB:-/data/db/couchdb}"
DATABASE_BASE_DIR="${DATABASE_DIR_COUCHDB:-/data/db/couchdb}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_COUCHDB:-/usr/local/share/httpd/admin/couchdb}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_COUCHDB:-/admin/couchdb}"
elif [ "$SERVICE_NAME" = "mongodb" ] || [ "$DATABASE_SERVICE_TYPE" = "mongodb" ]; then
DATABASE_DIR="${DATABASE_DIR_MONGODB:-/data/db/mongodb}"
DATABASE_BASE_DIR="${DATABASE_DIR_MONGODB:-/data/db/mongodb}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_MONGODB:-/usr/local/share/httpd/admin/mongodb}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_MONGODB:-/admin/mongodb}"
elif [ "$SERVICE_NAME" = "supabase" ] || [ "$DATABASE_SERVICE_TYPE" = "supabase" ]; then
DATABASE_DIR="${DATABASE_DIR_SUPABASE:-/data/db/supabase}"
DATABASE_BASE_DIR="${DATABASE_DIR_SUPABASE:-/data/db/supabase}"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_SUPABASE:-/usr/local/share/httpd/admin/supabase}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_SUPBASE:-/admin/supabase}"
elif [ "$SERVICE_NAME" = "sqlite" ] || [ "$DATABASE_SERVICE_TYPE" = "sqlite" ]; then
DATABASE_DIR="${DATABASE_DIR_SQLITE:-/data/db/sqlite}/$SERVER_NAME"
DATABASE_BASE_DIR="${DATABASE_DIR_SQLITE:-/data/db/sqlite}/$SERVER_NAME"
DATABASE_ADMIN_WWW_ROOT="${DATABASE_ADMIN_WWW_ROOT_SQLITE:-/usr/local/share/httpd/admin/sqlite}"
[ -d "$DATABASE_ADMIN_WWW_ROOT" ] && SERVER_ADMIN_URL="${SERVER_ADMIN_URL_SQLITE:-/admin/sqlite}"
[ -d "$DATABASE_DIR" ] || mkdir -p "$DATABASE_DIR"
chmod 777 "$DATABASE_DIR"
fi
# Override: pin to a predictable path — respect DATABASE_DIR_SQLITE if set, otherwise use DATA_DIR
DATABASE_DIR="${DATABASE_DIR_SQLITE:-$DATA_DIR/db/sqlite}"
[ -d "$DATABASE_DIR" ] || mkdir -p "$DATABASE_DIR"
[ -n "$DATABASE_ADMIN_WWW_ROOT" ] && { [ ! -d "$DATABASE_ADMIN_WWW_ROOT" ] || mkdir -p "${DATABASE_ADMIN_WWW_ROOT}"; }
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Allow variables via imports - Overwrite existing
[ -f "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh" ] && . "/config/env/${SERVICE_NAME:-$SCRIPT_NAME}.sh"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set password to random if variable is random
[ "$user_pass" = "random" ] && user_pass="$(__random_password ${RANDOM_PASS_USER:-16})"
# - - - - - - - - - - - - - - - - - - - - - - - - -
[ "$root_user_pass" = "random" ] && root_user_pass="$(__random_password ${RANDOM_PASS_ROOT:-16})"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Allow setting initial users and passwords via environment and save to file
[ -n "$user_name" ] && echo "$user_name" >"${USER_FILE_PREFIX}/${SERVICE_NAME}_name"
[ -n "$user_pass" ] && echo "$user_pass" >"${USER_FILE_PREFIX}/${SERVICE_NAME}_pass"
[ -n "$root_user_name" ] && echo "$root_user_name" >"${ROOT_FILE_PREFIX}/${SERVICE_NAME}_name"
[ -n "$root_user_pass" ] && echo "$root_user_pass" >"${ROOT_FILE_PREFIX}/${SERVICE_NAME}_pass"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create needed dirs
[ -d "$LOG_DIR" ] || mkdir -p "$LOG_DIR"
[ -d "$RUN_DIR" ] || mkdir -p "$RUN_DIR"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Allow per init script usernames and passwords
__file_exists_with_content "${USER_FILE_PREFIX}/${SERVICE_NAME}_name" && user_name="$(<"${USER_FILE_PREFIX}/${SERVICE_NAME}_name")"
__file_exists_with_content "${USER_FILE_PREFIX}/${SERVICE_NAME}_pass" && user_pass="$(<"${USER_FILE_PREFIX}/${SERVICE_NAME}_pass")"
__file_exists_with_content "${ROOT_FILE_PREFIX}/${SERVICE_NAME}_name" && root_user_name="$(<"${ROOT_FILE_PREFIX}/${SERVICE_NAME}_name")"
__file_exists_with_content "${ROOT_FILE_PREFIX}/${SERVICE_NAME}_pass" && root_user_pass="$(<"${ROOT_FILE_PREFIX}/${SERVICE_NAME}_pass")"
__file_exists_with_content "${USER_FILE_PREFIX}/db_pass_user" && DATABASE_PASS_NORMAL="$(<"${USER_FILE_PREFIX}/db_pass_user")"
__file_exists_with_content "${ROOT_FILE_PREFIX}/db_pass_root" && DATABASE_PASS_ROOT="$(<"${ROOT_FILE_PREFIX}/db_pass_root")"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set hostname for script
sysname="${SERVER_NAME:-${FULL_DOMAIN_NAME:-$HOSTNAME}}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
__create_service_env
# - - - - - - - - - - - - - - - - - - - - - - - - -
# pre-run function
__execute_prerun
# - - - - - - - - - - - - - - - - - - - - - - - - -
# create user if needed
__create_service_user "$SERVICE_USER" "$SERVICE_GROUP" "${WORK_DIR:-/home/$SERVICE_USER}" "${SERVICE_UID:-}" "${SERVICE_GID:-}"
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Modify user if needed
__set_user_group_id $SERVICE_USER ${SERVICE_UID:-} ${SERVICE_GID:-}
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Create base directories
__setup_directories
# - - - - - - - - - - - - - - - - - - - - - - - - -
# set switch user command
__switch_to_user
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Initialize the home/working dir
__init_working_dir
# - - - - - - - - - - - - - - - - - - - - - - - - -
# show init message
__pre_message
# - - - - - - - - - - - - - - - - - - - - - - - - -
#
__initialize_db_users
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Initialize ssl
__update_ssl_conf
__update_ssl_certs
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set permissions in ${USER_FILE_PREFIX} and ${ROOT_FILE_PREFIX}
__run_secure_function
# - - - - - - - - - - - - - - - - - - - - - - - - -
__run_precopy
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Replace variables
__initialize_replace_variables "$CONF_DIR" "$ADDITIONAL_CONFIG_DIRS" "$WWW_ROOT_DIR"
# - - - - - - - - - - - - - - - - - - - - - - - - -
#
__initialize_database
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Updating config files
__update_conf_files
# - - - - - - - - - - - - - - - - - - - - - - - - -
# run the pre execute commands
__pre_execute
# - - - - - - - - - - - - - - - - - - - - - - - - -
# Set permissions
__fix_permissions "$SERVICE_USER" "$SERVICE_GROUP"
# - - - - - - - - - - - - - - - - - - - - - - - - -
#
__run_pre_execute_checks 2>/dev/stderr | tee -a -p "/data/logs/entrypoint.log" "/data/logs/init.txt" || return 20
# - - - - - - - - - - - - - - - - - - - - - - - - -
__run_start_script 2>>/dev/stderr | tee -p -a "/data/logs/entrypoint.log"
errorCode=${PIPESTATUS[0]}
if [ -n "$EXEC_CMD_BIN" ]; then
if [ "$errorCode" -eq 0 ]; then
SERVICE_EXIT_CODE=0
SERVICE_IS_RUNNING="yes"
else
SERVICE_EXIT_CODE=$errorCode
SERVICE_IS_RUNNING="${SERVICE_IS_RUNNING:-no}"
if [ ! -s "$SERVICE_PID_FILE" ]; then
rm -Rf "$SERVICE_PID_FILE"
fi
fi
fi
# - - - - - - - - - - - - - - - - - - - - - - - - -
# start the post execute function in background
__post_execute 2>"/dev/stderr" | tee -p -a "/data/logs/init.txt" &
# - - - - - - - - - - - - - - - - - - - - - - - - -
__script_exit $SERVICE_EXIT_CODE
File diff suppressed because it is too large Load Diff
+6
View File
@@ -0,0 +1,6 @@
nameserver 1.1.1.1
nameserver 1.0.0.1
nameserver 8.8.8.8
nameserver 8.8.4.4
search .
options ndots:0