Merge pull request #673 from arabcoders/dev
Migrate to FrankenPHP instead of caddy+php-fpm
This commit is contained in:
56
Dockerfile
56
Dockerfile
@@ -6,36 +6,29 @@ RUN if [ ! -d /frontend/exported ]; then yarn install --production --prefer-offl
|
||||
|
||||
FROM alpine:edge
|
||||
|
||||
COPY --from=composer:2 /usr/bin/composer /opt/bin/composer
|
||||
COPY --from=composer/composer:2-bin /composer /opt/bin/composer
|
||||
|
||||
LABEL maintainer="admin@arabcoders.org"
|
||||
|
||||
ARG TZ=UTC
|
||||
ARG PHP_V=php84
|
||||
ARG PHP_PACKAGES="common ctype curl dom fileinfo fpm intl mbstring opcache pcntl pdo_sqlite phar posix session shmop simplexml snmp sockets sodium sysvmsg sysvsem sysvshm tokenizer xml openssl xmlreader xmlwriter zip pecl-igbinary pecl-xhprof pecl-redis"
|
||||
ARG TOOL_PATH=/opt/app
|
||||
ARG USER_ID=1000
|
||||
ARG PHP_FPM_PORT=9000
|
||||
|
||||
ENV IN_CONTAINER=1
|
||||
ENV PHP_INI_DIR=/etc/${PHP_V}
|
||||
ENV PATH=/opt/bin:${PATH}
|
||||
ENV HTTP_PORT="8080"
|
||||
ENV HTTPS_PORT="8443"
|
||||
ENV WS_DATA_PATH=/config
|
||||
ENV WS_TZ=UTC
|
||||
ENV FPM_PORT="${PHP_FPM_PORT}"
|
||||
ENV PACKAGES=""
|
||||
|
||||
# Setup the required environment.
|
||||
#
|
||||
RUN ln -snf /usr/share/zoneinfo/${TZ} /etc/localtime && echo ${TZ} > /etc/timezone && \
|
||||
for ext in ${PHP_PACKAGES}; do PACKAGES="${PACKAGES} ${PHP_V}-${ext}"; done && \
|
||||
ARCH=`uname -m` && if [ "${ARCH}" == "x86_64" ]; then PACKAGES="${PACKAGES} intel-media-driver"; fi && \
|
||||
apk add --no-cache bash caddy icu-data-full nano curl procps net-tools iproute2 ffmpeg \
|
||||
shadow sqlite redis tzdata gettext fcgi ca-certificates nss mailcap libcap fontconfig ttf-freefont font-noto \
|
||||
terminus-font font-dejavu libva-utils ${PHP_V} ${PACKAGES} && \
|
||||
apk add --no-cache bash icu-data-full nano curl procps net-tools iproute2 ffmpeg \
|
||||
shadow sqlite redis tzdata gettext ca-certificates nss mailcap libcap fontconfig ttf-freefont font-noto \
|
||||
terminus-font font-dejavu libva-utils ${PACKAGES} && \
|
||||
# Delete unused users change users group gid to allow unRaid users to use gid 100
|
||||
deluser redis && deluser caddy && groupmod -g 1588787 users && \
|
||||
deluser redis && groupmod -g 1588787 users && \
|
||||
# Create our own user.
|
||||
useradd -u ${USER_ID:-1000} -U -d /config -s /bin/bash user && \
|
||||
# Cache fonts.
|
||||
@@ -47,39 +40,36 @@ COPY ./ /opt/app
|
||||
# Copy frontend to public directory.
|
||||
COPY --chown=app:app --from=npm_builder /frontend/exported/ /opt/app/public/exported/
|
||||
|
||||
# Copy frankenphp (caddy+php) to the container.
|
||||
#
|
||||
COPY --chown=app:app --from=ghcr.io/arabcoders/franken_builder:latest /usr/local/bin/frankenphp /opt/bin/
|
||||
|
||||
# install composer & packages.
|
||||
#
|
||||
RUN echo '' && \
|
||||
# Link PHP if needed. \
|
||||
if [ ! -f /usr/bin/php ]; then ln -s /usr/bin/php${PHP_V:3} /usr/bin/php; fi && \
|
||||
chmod +x /opt/bin/frankenphp && \
|
||||
# create /usr/bin/php that points to /opt/bin/frankenphp php-cli "$@" \
|
||||
echo '#!/bin/sh' > /usr/bin/php && \
|
||||
echo 'exec /opt/bin/frankenphp php-cli "$@"' >> /usr/bin/php && chmod +x /usr/bin/php && \
|
||||
# Create basic directories.
|
||||
bash -c 'umask 0000 && mkdir -p /temp_data/ /opt/{app,bin,config} /config/{backup,cache,config,db,debug,logs,webhooks,profiler}' && \
|
||||
# Link console & php.
|
||||
bash -c "ln -s /usr/sbin/php-fpm${PHP_V:3} /usr/sbin/php-fpm" && \
|
||||
# Link console.
|
||||
ln -s ${TOOL_PATH}/bin/console /opt/bin/console && \
|
||||
# we are running rootless, so user,group config options has no affect.
|
||||
sed -i 's/user = nobody/; user = user/' /etc/${PHP_V}/php-fpm.d/www.conf && \
|
||||
sed -i 's/group = nobody/; group = users/' /etc/${PHP_V}/php-fpm.d/www.conf && \
|
||||
# expose php-fpm on all interfaces.
|
||||
sed -i "s/listen = 127.0.0.1:9000/listen = 0.0.0.0:${FPM_PORT}/" /etc/${PHP_V}/php-fpm.d/www.conf && \
|
||||
# Install dependencies.
|
||||
/opt/bin/composer --working-dir=/opt/app/ -no --no-progress --no-dev --no-cache --quiet -- install && \
|
||||
# Copy configuration files to the expected directories.
|
||||
cp ${TOOL_PATH}/container/files/job-runner.sh /opt/bin/job-runner && \
|
||||
cp ${TOOL_PATH}/container/files/init-container.sh /opt/bin/init-container && \
|
||||
cp ${TOOL_PATH}/container/files/php-fpm-healthcheck.sh /opt/bin/php-fpm-healthcheck && \
|
||||
cp ${TOOL_PATH}/container/files/Caddyfile /opt/config/Caddyfile && \
|
||||
cp ${TOOL_PATH}/container/files/redis.conf /opt/config/redis.conf && \
|
||||
caddy fmt --overwrite /opt/config/Caddyfile && \
|
||||
# Make sure /bin/* files are given executable flag.
|
||||
chmod +x /opt/bin/* && \
|
||||
# Update php.ini & php fpm
|
||||
WS_DATA_PATH=/temp_data/ WS_CACHE_NULL=1 /opt/bin/console system:php >"${PHP_INI_DIR}/conf.d/zz-custom-php.ini" && \
|
||||
WS_DATA_PATH=/temp_data/ WS_CACHE_NULL=1 /opt/bin/console system:php --fpm >"${PHP_INI_DIR}/php-fpm.d/zz-custom-pool.conf" && \
|
||||
# Update php.ini & php fpm \
|
||||
mkdir -p /etc/frankenphp/php.d && \
|
||||
WS_DATA_PATH=/temp_data/ WS_CACHE_NULL=1 /opt/bin/console system:php >"/etc/frankenphp/php.d/php.ini" && \
|
||||
# Remove unneeded directories and tools.
|
||||
bash -c 'rm -rf /temp_data/ /opt/bin/composer ${TOOL_PATH}/{container,var,.github,.git,.env}' && \
|
||||
bash -c 'rm -rf /temp_data/ /opt/bin/composer ${TOOL_PATH}/{tests,container,var,.github,.git,.env}' && \
|
||||
# Change Permissions.
|
||||
chown -R user:user /config /opt /var/log && chmod -R 777 /var/log /etc/${PHP_V}
|
||||
chown -R user:user /config /opt /var/log && chmod -R 777 /var/log /etc/frankenphp/php.d
|
||||
|
||||
# Set the entrypoint.
|
||||
#
|
||||
@@ -99,12 +89,12 @@ USER user
|
||||
|
||||
# Expose the ports.
|
||||
#
|
||||
EXPOSE 9000 8080 8443
|
||||
EXPOSE 8080
|
||||
|
||||
# Health check.
|
||||
#
|
||||
HEALTHCHECK CMD /opt/bin/php-fpm-healthcheck -v
|
||||
HEALTHCHECK --interval=10s --timeout=3s CMD curl -f http://localhost:8080/v1/api/system/healthcheck || exit 1
|
||||
|
||||
# Run php-fpm
|
||||
#
|
||||
CMD ["php-fpm", "-R"]
|
||||
CMD ["/opt/bin/frankenphp", "php-server", "--listen","0.0.0.0:8080", "--root", "/opt/app/public"]
|
||||
|
||||
58
FAQ.md
58
FAQ.md
@@ -226,6 +226,10 @@ digits, we’ll automatically prefix it with `user_`.
|
||||
No, webhooks are **not required** for the tool to function. You can use the built-in **scheduled tasks** or manually run
|
||||
**import/export operations** on demand through the WebUI or console.
|
||||
|
||||
> [!NOTE]
|
||||
> There are problems with jellyfin API, which are fixed by using webhooks, please check out
|
||||
> the [webhook guide](/guides/webhooks.md#media-backends-webhook-limitations) to learn more.
|
||||
|
||||
---
|
||||
|
||||
# I'm Using Media Backends Hosted Behind HTTPS and See Errors Related to HTTP/2
|
||||
@@ -299,7 +303,7 @@ If there are no errors, the database has been repaired successfully. And you can
|
||||
|
||||
---
|
||||
|
||||
# Which Providers id `GUIDs` supported for Plex Media Server?
|
||||
# Which Providers id `GUIDs` supported by for PlexClient?
|
||||
|
||||
* tvdb://(id) `New plex agent`
|
||||
* imdb://(id) `New plex agent`
|
||||
@@ -319,7 +323,7 @@ If there are no errors, the database has been repaired successfully. And you can
|
||||
|
||||
---
|
||||
|
||||
# Which Providers id supported for Jellyfin and Emby?
|
||||
# Which Providers id supported by Jellyfin/Emby Client?
|
||||
|
||||
* imdb://(id)
|
||||
* tvdb://(id)
|
||||
@@ -363,7 +367,7 @@ Should be added/managed via the `WebUI > Env` page.
|
||||
| WS_TRUST_HEADER | string | Which header contain user true IP. | `X-Forwarded-For` |
|
||||
| WS_LIBRARY_SEGMENT | integer | Paginate backend library items request. Per request get total X number. | `1000` |
|
||||
| WS_CACHE_URL | string | Cache server URL. | `redis://127.0.0.1:6379` |
|
||||
| WS_SECURE_API_ENDPOINTS | bool | Disregard the open route policy and require API key for all endpoints. | `false` |
|
||||
| WS_SECURE_API_ENDPOINTS | bool | Disable the open policy for webhook endpoint and require apikey. | `false` |
|
||||
|
||||
> [!NOTE]
|
||||
> for environment variables that has `{TASK}` tag, you **MUST** replace it with one of `IMPORT`, `EXPORT`, `BACKUP`,
|
||||
@@ -377,13 +381,10 @@ Should be added/managed via the `WebUI > Env` page.
|
||||
> These environment variables relates to the container itself, and MUST be added via container environment or by
|
||||
> the `compose.yaml` file.
|
||||
|
||||
| Key | Type | Description | Default |
|
||||
|---------------|---------|------------------------------------|----------|
|
||||
| DISABLE_HTTP | integer | Disable included `HTTP Server`. | `0` |
|
||||
| DISABLE_CRON | integer | Disable included `Task Scheduler`. | `0` |
|
||||
| DISABLE_CACHE | integer | Disable included `Cache Server`. | `0` |
|
||||
| HTTP_PORT | string | Change the `HTTP` listen port. | `"8080"` |
|
||||
| FPM_PORT | string | Change the `PHP-FPM` listen port. | `"9000"` |
|
||||
| Key | Type | Description | Default |
|
||||
|---------------|---------|------------------------------------|---------|
|
||||
| DISABLE_CRON | integer | Disable included `Task Scheduler`. | `0` |
|
||||
| DISABLE_CACHE | integer | Disable included `Cache Server`. | `0` |
|
||||
|
||||
> [!NOTE]
|
||||
> You need to restart the container after changing these environment variables. those variables are not managed by the
|
||||
@@ -391,43 +392,6 @@ Should be added/managed via the `WebUI > Env` page.
|
||||
|
||||
---
|
||||
|
||||
# How to disable the included HTTP server and use external server?
|
||||
|
||||
To disable the built-in HTTP server, set the following environment variable and restart the container:
|
||||
|
||||
```
|
||||
DISABLE_HTTP=1
|
||||
```
|
||||
|
||||
Your external web server must forward requests using the correct **FastCGI** environment variables.
|
||||
|
||||
## Example: Caddy Configuration
|
||||
|
||||
```caddyfile
|
||||
https://watchstate.example.org {
|
||||
# Replace "172.23.1.2" with the actual IP address of your WatchState container
|
||||
reverse_proxy 172.23.1.2:9000 {
|
||||
transport fastcgi {
|
||||
root /opt/app/public
|
||||
env DOCUMENT_ROOT /opt/app/public
|
||||
env SCRIPT_FILENAME /opt/app/public/index.php
|
||||
env X_REQUEST_ID "{http.request.uuid}"
|
||||
split .php
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
> [!NOTE]
|
||||
> If you change the FastCGI Process Manager port using the `FPM_PORT` environment variable, make sure to update the port
|
||||
> in the reverse proxy configuration as well.
|
||||
|
||||
> [!IMPORTANT]
|
||||
> This configuration mode is **not officially supported** by WatchState. If issues arise, please verify your web server
|
||||
> setup. Support does not cover external web server configurations.
|
||||
|
||||
---
|
||||
|
||||
# How to disable the included cache server and use an external cache server?
|
||||
|
||||
To disable the built-in cache server and connect to an external Redis instance, follow these steps:
|
||||
|
||||
@@ -50,7 +50,6 @@ return (function () {
|
||||
],
|
||||
],
|
||||
'webui' => [
|
||||
'enabled' => (bool)env('WEBUI_ENABLED', env('WS_WEBUI_ENABLED', true)),
|
||||
'path' => fixPath(env('WS_WEBUI_PATH', __DIR__ . '/../public/exported')),
|
||||
],
|
||||
'database' => [
|
||||
@@ -235,9 +234,9 @@ return (function () {
|
||||
'opcache.max_wasted_percentage' => 5,
|
||||
'expose_php' => 0,
|
||||
'date.timezone' => ag($config, 'tz', 'UTC'),
|
||||
'mbstring.http_input' => ag($config, 'charset', 'UTF-8'),
|
||||
'mbstring.http_output' => ag($config, 'charset', 'UTF-8'),
|
||||
'mbstring.internal_encoding' => ag($config, 'charset', 'UTF-8'),
|
||||
// 'mbstring.http_input' => ag($config, 'charset', 'UTF-8'),
|
||||
// 'mbstring.http_output' => ag($config, 'charset', 'UTF-8'),
|
||||
// 'mbstring.internal_encoding' => ag($config, 'charset', 'UTF-8'),
|
||||
],
|
||||
'fpm' => [
|
||||
'global' => [
|
||||
|
||||
@@ -151,7 +151,7 @@ return (function () {
|
||||
],
|
||||
[
|
||||
'key' => 'WS_SECURE_API_ENDPOINTS',
|
||||
'description' => 'Close all open routes and enforce API key authentication on all endpoints.',
|
||||
'description' => 'Disable the open policy for webhook endpoint and require apikey.',
|
||||
'type' => 'bool',
|
||||
],
|
||||
[
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
{
|
||||
persist_config off
|
||||
http_port {$HTTP_PORT}
|
||||
https_port {$HTTPS_PORT}
|
||||
}
|
||||
|
||||
(app) {
|
||||
root * /opt/app/public
|
||||
log {
|
||||
output discard
|
||||
}
|
||||
|
||||
header * ?X-Request-Id "{http.request.uuid}"
|
||||
|
||||
php_fastcgi 127.0.0.1:{$FPM_PORT} {
|
||||
trusted_proxies private_ranges
|
||||
env X_REQUEST_ID "{http.request.uuid}"
|
||||
}
|
||||
}
|
||||
|
||||
http:// {
|
||||
import app
|
||||
}
|
||||
|
||||
https:// {
|
||||
tls internal {
|
||||
on_demand
|
||||
}
|
||||
import app
|
||||
}
|
||||
@@ -54,15 +54,8 @@ else
|
||||
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")] INFO: No environment file present at [${ENV_FILE}]."
|
||||
fi
|
||||
|
||||
DISABLE_HTTP=${DISABLE_HTTP:-0}
|
||||
DISABLE_CRON=${DISABLE_CRON:-0}
|
||||
DISABLE_CACHE=${DISABLE_CACHE:-0}
|
||||
FPM_PORT=${FPM_PORT:-9000}
|
||||
|
||||
if [ 9000 != "${FPM_PORT}" ]; then
|
||||
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")] INFO: Changing PHP-FPM port to [${FPM_PORT}]."
|
||||
sed -i "s/listen = 0.0.0.0:9000/listen = 0.0.0.0:${FPM_PORT}/" /etc/*/php-fpm.d/www.conf
|
||||
fi
|
||||
|
||||
set -u
|
||||
|
||||
@@ -75,16 +68,6 @@ if [ 0 = "${DISABLE_CACHE}" ]; then
|
||||
redis-server "/opt/config/redis.conf"
|
||||
fi
|
||||
|
||||
if [ 0 = "${DISABLE_HTTP}" ]; then
|
||||
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")] Starting HTTP Server."
|
||||
_CADDY_UUID_FILE="${XDG_DATA_HOME}/caddy/instance.uuid"
|
||||
if [ ! -f "${_CADDY_UUID_FILE}" ]; then
|
||||
mkdir -p "${XDG_DATA_HOME}/caddy"
|
||||
printf '%s' "$(cat /proc/sys/kernel/random/uuid)" > "${_CADDY_UUID_FILE}"
|
||||
fi
|
||||
caddy start --config /opt/config/Caddyfile
|
||||
fi
|
||||
|
||||
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")] Caching tool routes."
|
||||
/opt/bin/console system:routes
|
||||
|
||||
@@ -114,9 +97,4 @@ fi
|
||||
|
||||
echo "[$(date +"%Y-%m-%dT%H:%M:%S%z")] Running - $(/opt/bin/console --version)"
|
||||
|
||||
# first arg is `-f` or `--some-option`
|
||||
if [ "${1#-}" != "$1" ]; then
|
||||
set -- php-fpm "${@}"
|
||||
fi
|
||||
|
||||
exec "${@}"
|
||||
|
||||
@@ -1,140 +0,0 @@
|
||||
#!/bin/sh
|
||||
# vim: set filetype=sh :
|
||||
|
||||
# Author: <Renato Mefi gh@mefi.in> https://github.com/renatomefi
|
||||
# The original code lives in https://github.com/renatomefi/php-fpm-healthcheck
|
||||
#
|
||||
# A POSIX compliant shell script to healthcheck PHP fpm status, can be used only for pinging the status page
|
||||
# or check for specific metrics
|
||||
#
|
||||
# i.e.: ./php-fpm-healthcheck --verbose --active-processes=6
|
||||
# The script will fail in case the 'active processes' is bigger than 6.
|
||||
#
|
||||
# You can combine multiple options as well, the first one to fail will fail the healthcheck
|
||||
# i.e.: ./php-fpm-healthcheck --listen-queue-len=10 --active-processes=6
|
||||
#
|
||||
# Ping mode (exit 0 if php-fpm returned data): ./php-fpm-healthcheck
|
||||
#
|
||||
# Ping mode with data (outputs php-fpm status text): ./php-fpm-healthcheck -v
|
||||
#
|
||||
# Exit status codes:
|
||||
# 2,9,111 - Couldn't connect to PHP fpm, is it running?
|
||||
# 8 - Couldn't reach PHP fpm status page, have you configured it with `pm.status_path = /status`?
|
||||
# 1 - A healthcheck condition has failed
|
||||
# 3 - Invalid option given
|
||||
# 4 - One or more required software's are missing
|
||||
#
|
||||
# Available options:
|
||||
# -v|--verbose
|
||||
#
|
||||
# Metric options, fails in case the CURRENT VALUE is bigger than the GIVEN VALUE
|
||||
# --accepted-conn=n
|
||||
# --listen-queue=n
|
||||
# --max-listen-queue=n
|
||||
# --idle-processes=n
|
||||
# --active-processes=n
|
||||
# --total-processes=n
|
||||
# --max-active-processes=n
|
||||
# --max-children-reached=n
|
||||
# --slow-requests=n
|
||||
#
|
||||
|
||||
set -eu
|
||||
|
||||
OPTIND=1 # Reset getopt in case it has been used previously in the shell
|
||||
|
||||
# Required software
|
||||
FCGI_CMD_PATH=$(command -v cgi-fcgi) || { >&2 echo "Make sure fcgi is installed (i.e. apk add --no-cache fcgi). Aborting."; exit 4; }
|
||||
command -v sed 1> /dev/null || { >&2 echo "Make sure sed is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
|
||||
command -v tail 1> /dev/null || { >&2 echo "Make sure tail is installed (i.e. apk add --no-cache busybox). Aborting."; exit 4; }
|
||||
command -v grep 1> /dev/null || { >&2 echo "Make sure grep is installed (i.e. apk add --no-cache grep). Aborting."; exit 4; }
|
||||
|
||||
# Get status from fastcgi connection
|
||||
# $1 - cgi-fcgi connect argument
|
||||
get_fpm_status() {
|
||||
if test "$VERBOSE" = 1; then printf "Trying to connect to php-fpm via: %s%s\\n" "$1" "$SCRIPT_NAME"; fi;
|
||||
|
||||
# Since I cannot use pipe fail I'll just split these in two commands
|
||||
FPM_STATUS=$(env -i REQUEST_METHOD="$REQUEST_METHOD" SCRIPT_NAME="$SCRIPT_NAME" SCRIPT_FILENAME="$SCRIPT_FILENAME" "$FCGI_CMD_PATH" -bind -connect "$1" 2> /dev/null)
|
||||
FPM_STATUS=$(echo "$FPM_STATUS" | tail -n +5)
|
||||
|
||||
if test "$VERBOSE" = 1; then printf "php-fpm status output:\\n%s\\n" "$FPM_STATUS"; fi;
|
||||
|
||||
if test "$FPM_STATUS" = "File not found."; then
|
||||
>&2 printf "php-fpm status page non reachable\\n";
|
||||
exit 8;
|
||||
fi;
|
||||
}
|
||||
|
||||
# $1 - fpm option
|
||||
# $2 - expected value threshold
|
||||
check_fpm_health_by() {
|
||||
OPTION=$(echo "$1" | sed 's/--//g; s/-/ /g;')
|
||||
VALUE_EXPECTED="$2";
|
||||
VALUE_ACTUAL=$(echo "$FPM_STATUS" | grep "^$OPTION:" | cut -d: -f2 | sed 's/ //g')
|
||||
|
||||
if test "$VERBOSE" = 1; then printf "'%s' value '%s' and expected is less than '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED"; fi;
|
||||
|
||||
if test "$VALUE_ACTUAL" -gt "$VALUE_EXPECTED"; then
|
||||
>&2 printf "'%s' value '%s' is greater than expected '%s'\\n" "$OPTION" "$VALUE_ACTUAL" "$VALUE_EXPECTED";
|
||||
exit 1;
|
||||
fi;
|
||||
}
|
||||
|
||||
PARAM_AMOUNT=0
|
||||
|
||||
# $1 - fpm option
|
||||
# $2 - expected value threshold
|
||||
check_later() {
|
||||
# The POSIX sh way to check if it's an integer, also the output is suppressed since it's pollution
|
||||
if ! test "$2" -eq "$2" 2> /dev/null; then
|
||||
>&2 printf "'%s' option value must be an integer, '%s' given\\n" "$1" "$2"; exit 3;
|
||||
fi
|
||||
|
||||
PARAM_AMOUNT=$(( PARAM_AMOUNT + 1 ))
|
||||
|
||||
eval "PARAM_TO_CHECK$PARAM_AMOUNT=$1"
|
||||
eval "VALUE_TO_CHECK$PARAM_AMOUNT=$2"
|
||||
}
|
||||
|
||||
# From the PARAM_TO_CHECK/VALUE_TO_CHECK magic variables, do all the checks
|
||||
check_fpm_health() {
|
||||
j=1
|
||||
while [ $j -le $PARAM_AMOUNT ]; do
|
||||
eval "CURRENT_PARAM=\$PARAM_TO_CHECK$j"
|
||||
eval "CURRENT_VALUE=\$VALUE_TO_CHECK$j"
|
||||
check_fpm_health_by "$CURRENT_PARAM" "$CURRENT_VALUE"
|
||||
j=$(( j + 1 ))
|
||||
done
|
||||
}
|
||||
|
||||
if ! GETOPT=$(getopt -o v --long verbose,accepted-conn:,listen-queue:,max-listen-queue:,listen-queue-len:,idle-processes:,active-processes:,total-processes:,max-active-processes:,max-children-reached:,slow-requests: -n 'php-fpm-healthcheck' -- "$@"); then
|
||||
>&2 echo "Invalid options, terminating." ; exit 3
|
||||
fi;
|
||||
|
||||
eval set -- "$GETOPT"
|
||||
|
||||
FPM_PORT=${FPM_PORT:-9000}
|
||||
# FastCGI variables
|
||||
FCGI_CONNECT_DEFAULT="localhost:${FPM_PORT}"
|
||||
FCGI_STATUS_PATH_DEFAULT="/status"
|
||||
|
||||
export REQUEST_METHOD="GET"
|
||||
export SCRIPT_NAME="${FCGI_STATUS_PATH:-$FCGI_STATUS_PATH_DEFAULT}"
|
||||
export SCRIPT_FILENAME="${FCGI_STATUS_PATH:-$FCGI_STATUS_PATH_DEFAULT}"
|
||||
FCGI_CONNECT="${FCGI_CONNECT:-$FCGI_CONNECT_DEFAULT}"
|
||||
|
||||
VERBOSE=0
|
||||
|
||||
while test "$1"; do
|
||||
case "$1" in
|
||||
-v|--verbose ) VERBOSE=1; shift ;;
|
||||
--) shift ; break ;;
|
||||
* ) check_later "$1" "$2"; shift 2 ;;
|
||||
esac
|
||||
done
|
||||
|
||||
FPM_STATUS=false
|
||||
|
||||
get_fpm_status "$FCGI_CONNECT"
|
||||
check_fpm_health
|
||||
@@ -119,7 +119,7 @@ const formatTag = tag => {
|
||||
}
|
||||
const branch = parts[0];
|
||||
const date = parts[1];
|
||||
const shortSha = parts[2].substring(0, 7);
|
||||
const shortSha = parts[2].substring(0, 8);
|
||||
return `${ucFirst(branch)}: ${moment(date, 'YYYYMMDD').format('YYYY-MM-DD')} - ${shortSha}`;
|
||||
}
|
||||
|
||||
|
||||
@@ -57,6 +57,9 @@ set_exception_handler(function (Throwable $e) {
|
||||
});
|
||||
|
||||
$factory = new Psr17Factory();
|
||||
if (!isset($_SERVER['X_REQUEST_ID'])) {
|
||||
$_SERVER['X_REQUEST_ID'] = generateUUID();
|
||||
}
|
||||
$request = new ServerRequestCreator($factory, $factory, $factory, $factory)->fromGlobals();
|
||||
$profiler = new Profiler(callback: function (array $data) {
|
||||
$filter = function (array $data): array {
|
||||
@@ -159,7 +162,7 @@ $exitCode = $profiler->process(function () use ($request) {
|
||||
try {
|
||||
// -- In case the frontend proxy does not generate request unique id.
|
||||
if (!isset($_SERVER['X_REQUEST_ID'])) {
|
||||
$_SERVER['X_REQUEST_ID'] = bin2hex(random_bytes(16));
|
||||
$_SERVER['X_REQUEST_ID'] = generateUUID();
|
||||
}
|
||||
|
||||
$app = new App\Libs\Initializer()->boot();
|
||||
|
||||
@@ -19,6 +19,6 @@ final class HealthCheck
|
||||
return api_response(Status::OK, [
|
||||
'status' => 'ok',
|
||||
'message' => 'System is healthy',
|
||||
]);
|
||||
], headers: ['X-No-AccessLog' => '1']);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ declare(strict_types=1);
|
||||
|
||||
namespace App\Libs;
|
||||
|
||||
use App\API\Backend\Webhooks;
|
||||
use App\Cli;
|
||||
use App\Libs\Enums\Http\Status;
|
||||
use App\Libs\Exceptions\Backends\RuntimeException;
|
||||
@@ -293,67 +292,14 @@ final class Initializer
|
||||
*/
|
||||
private function defaultHttpServer(iRequest $request): iResponse
|
||||
{
|
||||
$backend = [];
|
||||
|
||||
$requestPath = $request->getUri()->getPath();
|
||||
|
||||
// -- health endpoint.
|
||||
if (true === str_starts_with($requestPath, '/healthcheck')) {
|
||||
return api_response(Status::OK);
|
||||
}
|
||||
|
||||
// -- Forward requests to API server.
|
||||
if (true === str_starts_with($requestPath, Config::get('api.prefix', '????'))) {
|
||||
return $this->defaultAPIServer(clone $request);
|
||||
}
|
||||
|
||||
$apikey = ag($request->getQueryParams(), 'apikey', $request->getHeaderLine('x-apikey'));
|
||||
|
||||
if (empty($apikey)) {
|
||||
if (false === (bool)Config::get('webui.enabled', false)) {
|
||||
$response = api_response(Status::UNAUTHORIZED);
|
||||
$this->write(
|
||||
$request,
|
||||
Level::Info,
|
||||
$this->formatLog($request, $response, 'No webhook token was found.')
|
||||
);
|
||||
return $response;
|
||||
}
|
||||
|
||||
return new ServeStatic()->serve($request)->withHeader('Access-Control-Allow-Origin', '*')
|
||||
->withHeader('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
|
||||
$configFile = ConfigFile::open(Config::get('backends_file'), 'yaml', autoCreate: true);
|
||||
|
||||
// -- Find Relevant backend.
|
||||
foreach ($configFile->getAll() as $name => $info) {
|
||||
if (null === ag($info, 'webhook.token')) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (true !== hash_equals((string)ag($info, 'webhook.token'), (string)$apikey)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
$info['name'] = $name;
|
||||
$backend = $info;
|
||||
break;
|
||||
}
|
||||
|
||||
if (empty($backend)) {
|
||||
$response = api_response(Status::UNAUTHORIZED);
|
||||
$this->write($request, Level::Info, $this->formatLog($request, $response, 'Invalid token was given.'));
|
||||
return $response;
|
||||
}
|
||||
|
||||
$uri = r('/v1/api/backends/{backend}/webhook', ['backend' => ag($backend, 'name')]);
|
||||
return Container::get(Webhooks::class)(
|
||||
request: $request->withUri($request->getUri()->withPath($uri)->withQuery(''))
|
||||
->withHeader('Authorization', 'Bearer ' . Config::get('api.key'))
|
||||
->withoutHeader('X-Apikey'),
|
||||
name: $backend['name'],
|
||||
);
|
||||
return new ServeStatic()->serve($request)->withHeader('Access-Control-Allow-Origin', '*')
|
||||
->withHeader('Access-Control-Allow-Credentials', 'true');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -402,15 +402,16 @@ class DirectMapper implements ImportInterface
|
||||
return $this;
|
||||
}
|
||||
|
||||
if (true === $metadataOnly) {
|
||||
return $this;
|
||||
}
|
||||
|
||||
if ($entity->isWatched() !== $local->isWatched()) {
|
||||
$reasons = [];
|
||||
|
||||
if (true === $entity->isTainted()) {
|
||||
$reasons[] = 'event marked as tainted';
|
||||
}
|
||||
if (true === $metadataOnly) {
|
||||
$reasons[] = 'mapper is in metadata only mode';
|
||||
}
|
||||
|
||||
if (count($reasons) < 1) {
|
||||
$reasons[] = 'Abnormal state detected.';
|
||||
|
||||
@@ -211,6 +211,7 @@ if (!function_exists('APIRequest')) {
|
||||
'SERVER_NAME' => 'localhost',
|
||||
'SERVER_PORT' => 80,
|
||||
'HTTP_USER_AGENT' => Config::get('http.default.options.headers.User-Agent', 'APIRequest'),
|
||||
'X_REQUEST_ID' => generateUUID('intr'),
|
||||
...ag($opts, 'server', []),
|
||||
];
|
||||
|
||||
|
||||
@@ -703,7 +703,7 @@ if (!function_exists('makeBackend')) {
|
||||
backendUrl: new Uri(ag($backend, 'url')),
|
||||
cache: $cache,
|
||||
userContext: $userContext ?? Container::get(UserContext::class),
|
||||
logger: ag($options, iLogger::class, fn () => Container::get(iLogger::class)),
|
||||
logger: ag($options, iLogger::class, fn() => Container::get(iLogger::class)),
|
||||
backendId: ag($backend, 'uuid', null),
|
||||
backendToken: ag($backend, 'token', null),
|
||||
backendUser: ag($backend, 'user', null),
|
||||
@@ -823,12 +823,6 @@ if (!function_exists('getAppVersion')) {
|
||||
*/
|
||||
function getAppVersion(): string
|
||||
{
|
||||
static $_version;
|
||||
|
||||
if (null !== $_version) {
|
||||
return $_version;
|
||||
}
|
||||
|
||||
$version = Config::get('version', 'dev-master');
|
||||
|
||||
if ('$(version_via_ci)' === $version) {
|
||||
@@ -854,21 +848,16 @@ if (!function_exists('getAppVersion')) {
|
||||
$procDate->run();
|
||||
$commitDate = $procDate->isSuccessful() ? trim($procDate->getOutput()) : date('Ymd');
|
||||
|
||||
$_version = r('{branch}-{date}-{commit}', [
|
||||
return r('{branch}-{date}-{commit}', [
|
||||
'branch' => $branch,
|
||||
'date' => $commitDate,
|
||||
'commit' => $commit,
|
||||
]);
|
||||
|
||||
return $_version;
|
||||
} catch (Throwable) {
|
||||
$_version = 'dev-master';
|
||||
return 'dev-master';
|
||||
}
|
||||
}
|
||||
|
||||
$_version = $version;
|
||||
|
||||
return $version;
|
||||
}
|
||||
}
|
||||
@@ -921,7 +910,7 @@ if (!function_exists('array_keys_diff')) {
|
||||
*/
|
||||
function array_keys_diff(array $base, array $list, bool $has = true): array
|
||||
{
|
||||
return array_filter($base, fn ($key) => $has === in_array($key, $list), ARRAY_FILTER_USE_KEY);
|
||||
return array_filter($base, fn($key) => $has === in_array($key, $list), ARRAY_FILTER_USE_KEY);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1331,7 +1320,7 @@ if (!function_exists('parseConfigValue')) {
|
||||
function parseConfigValue(mixed $value, Closure|null $callback = null): mixed
|
||||
{
|
||||
if (is_string($value) && preg_match('#%{(.+?)}#s', $value)) {
|
||||
$val = preg_replace_callback('#%{(.+?)}#s', fn ($match) => Config::get($match[1], $match[1]), $value);
|
||||
$val = preg_replace_callback('#%{(.+?)}#s', fn($match) => Config::get($match[1], $match[1]), $value);
|
||||
return null !== $callback && null !== $val ? $callback($val) : $val;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user