Crashes when run against installed nextcloud.
What happened?
Disclaimer: I have zero prior experience in php - so if you find this bug report irrelevant, lmk.
I tried to hack together the nextcloud dockerfile to make it work with frankenphp - The original code can be found at https://github.com/nextcloud/docker/tree/master/28/apache
I have basically change the build container to frakenphp and the entry point to frankenphp run --config /etc/caddy/Caddyfile
The TLDR can be - how to run nextcloud under frankenphp ?
Dockerfile
# DO NOT EDIT: created by update.sh from Dockerfile-alpine.template
FROM dunglas/frankenphp:1.1-php8.2-alpine
# FROM php:8.2-fpm-alpine3.19
# entrypoint.sh and cron.sh dependencies
RUN set -ex; \
\
apk add --no-cache \
imagemagick \
rsync \
; \
\
rm /var/spool/cron/crontabs/root; \
echo '*/5 * * * * php -f /var/www/html/cron.php' > /var/spool/cron/crontabs/www-data
# install the PHP extensions we need
# see https://docs.nextcloud.com/server/stable/admin_manual/installation/source_installation.html
RUN set -ex; \
\
apk add --no-cache --virtual .build-deps \
$PHPIZE_DEPS \
autoconf \
freetype-dev \
gmp-dev \
icu-dev \
imagemagick-dev \
libevent-dev \
libjpeg-turbo-dev \
libmcrypt-dev \
libmemcached-dev \
libpng-dev \
libwebp-dev \
libxml2-dev \
libzip-dev \
openldap-dev \
pcre-dev \
postgresql-dev \
; \
\
docker-php-ext-configure gd --with-freetype --with-jpeg --with-webp; \
docker-php-ext-configure ldap; \
docker-php-ext-install -j "$(nproc)" \
bcmath \
exif \
gd \
gmp \
intl \
ldap \
opcache \
pcntl \
pdo_mysql \
pdo_pgsql \
sysvsem \
zip \
; \
\
# pecl will claim success even if one install fails, so we need to perform each install separately
pecl install APCu-5.1.23; \
pecl install imagick-3.7.0; \
pecl install memcached-3.2.0; \
pecl install redis-6.0.2; \
\
docker-php-ext-enable \
apcu \
imagick \
memcached \
redis \
; \
rm -r /tmp/pear; \
\
runDeps="$( \
scanelf --needed --nobanner --format '%n#p' --recursive /usr/local/lib/php/extensions \
| tr ',' '\n' \
| sort -u \
| awk 'system("[ -e /usr/local/lib/" $1 " ]") == 0 { next } { print "so:" $1 }' \
)"; \
apk add --no-network --virtual .nextcloud-phpext-rundeps $runDeps; \
apk del --no-network .build-deps
# set recommended PHP.ini settings
# see https://docs.nextcloud.com/server/latest/admin_manual/installation/server_tuning.html#enable-php-opcache
ENV PHP_MEMORY_LIMIT 512M
ENV PHP_UPLOAD_LIMIT 512M
RUN { \
echo 'opcache.enable=1'; \
echo 'opcache.interned_strings_buffer=32'; \
echo 'opcache.max_accelerated_files=10000'; \
echo 'opcache.memory_consumption=128'; \
echo 'opcache.save_comments=1'; \
echo 'opcache.revalidate_freq=60'; \
echo 'opcache.jit=1255'; \
echo 'opcache.jit_buffer_size=128M'; \
} > "${PHP_INI_DIR}/conf.d/opcache-recommended.ini"; \
\
echo 'apc.enable_cli=1' >> "${PHP_INI_DIR}/conf.d/docker-php-ext-apcu.ini"; \
\
{ \
echo 'memory_limit=${PHP_MEMORY_LIMIT}'; \
echo 'upload_max_filesize=${PHP_UPLOAD_LIMIT}'; \
echo 'post_max_size=${PHP_UPLOAD_LIMIT}'; \
} > "${PHP_INI_DIR}/conf.d/nextcloud.ini"; \
\
mkdir /var/www/data; \
mkdir -p /docker-entrypoint-hooks.d/pre-installation \
/docker-entrypoint-hooks.d/post-installation \
/docker-entrypoint-hooks.d/pre-upgrade \
/docker-entrypoint-hooks.d/post-upgrade \
/docker-entrypoint-hooks.d/before-starting; \
chown -R www-data:root /var/www; \
chmod -R g=u /var/www
VOLUME /var/www/html
ENV NEXTCLOUD_VERSION 28.0.2
RUN set -ex; \
apk add --no-cache --virtual .fetch-deps \
bzip2 \
gnupg \
; \
\
curl -fsSL -o nextcloud.tar.bz2 "https://download.nextcloud.com/server/releases/nextcloud-28.0.2.tar.bz2"; \
curl -fsSL -o nextcloud.tar.bz2.asc "https://download.nextcloud.com/server/releases/nextcloud-28.0.2.tar.bz2.asc"; \
export GNUPGHOME="$(mktemp -d)"; \
# gpg key from https://nextcloud.com/nextcloud.asc
gpg --batch --keyserver keyserver.ubuntu.com --recv-keys 28806A878AE423A28372792ED75899B9A724937A; \
gpg --batch --verify nextcloud.tar.bz2.asc nextcloud.tar.bz2; \
tar -xjf nextcloud.tar.bz2 -C /usr/src/; \
gpgconf --kill all; \
rm nextcloud.tar.bz2.asc nextcloud.tar.bz2; \
rm -rf "$GNUPGHOME" /usr/src/nextcloud/updater; \
mkdir -p /usr/src/nextcloud/data; \
mkdir -p /usr/src/nextcloud/custom_apps; \
chmod +x /usr/src/nextcloud/occ; \
apk del --no-network .fetch-deps
# RUN setcap CAP_NET_BIND_SERVICE=+eip /usr/local/bin/frankenphp
# Caddy requires write access to /data/caddy and /config/caddy
# RUN chown -R www-data:www-data /data/caddy && chown -R www-data:www-data /config/caddy
COPY *.sh upgrade.exclude /
COPY config/* /usr/src/nextcloud/config/
ENTRYPOINT ["/entrypoint.sh"]
# CMD ["php-fpm"]
CMD ["frankenphp", "run", "--config", "/etc/caddy/Caddyfile", "--adapter", "caddyfile"]
I also made a small change to entrypoint into run nextcloud installations for frankenphp
entrypoint
#!/bin/sh
set -eu
# version_greater A B returns whether A > B
version_greater() {
[ "$(printf '%s\n' "$@" | sort -t '.' -n -k1,1 -k2,2 -k3,3 -k4,4 | head -n 1)" != "$1" ]
}
# return true if specified directory is empty
directory_empty() {
[ -z "$(ls -A "$1/")" ]
}
run_as() {
if [ "$(id -u)" = 0 ]; then
su -p "$user" -s /bin/sh -c "$1"
else
sh -c "$1"
fi
}
# Execute all executable files in a given directory in alphanumeric order
run_path() {
local hook_folder_path="/docker-entrypoint-hooks.d/$1"
local return_code=0
if ! [ -d "${hook_folder_path}" ]; then
echo "=> Skipping the folder \"${hook_folder_path}\", because it doesn't exist"
return 0
fi
echo "=> Searching for scripts (*.sh) to run, located in the folder: ${hook_folder_path}"
(
find "${hook_folder_path}" -maxdepth 1 -iname '*.sh' '(' -type f -o -type l ')' -print | sort | while read -r script_file_path; do
if ! [ -x "${script_file_path}" ]; then
echo "==> The script \"${script_file_path}\" was skipped, because it didn't have the executable flag"
continue
fi
echo "==> Running the script (cwd: $(pwd)): \"${script_file_path}\""
run_as "${script_file_path}" || return_code="$?"
if [ "${return_code}" -ne "0" ]; then
echo "==> Failed at executing \"${script_file_path}\". Exit code: ${return_code}"
exit 1
fi
echo "==> Finished the script: \"${script_file_path}\""
done
)
}
# usage: file_env VAR [DEFAULT]
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
file_env() {
local var="$1"
local fileVar="${var}_FILE"
local def="${2:-}"
local varValue=$(env | grep -E "^${var}=" | sed -E -e "s/^${var}=//")
local fileVarValue=$(env | grep -E "^${fileVar}=" | sed -E -e "s/^${fileVar}=//")
if [ -n "${varValue}" ] && [ -n "${fileVarValue}" ]; then
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
exit 1
fi
if [ -n "${varValue}" ]; then
export "$var"="${varValue}"
elif [ -n "${fileVarValue}" ]; then
export "$var"="$(cat "${fileVarValue}")"
elif [ -n "${def}" ]; then
export "$var"="$def"
fi
unset "$fileVar"
}
if expr "$1" : "apache" 1>/dev/null; then
if [ -n "${APACHE_DISABLE_REWRITE_IP+x}" ]; then
a2disconf remoteip
fi
fi
if expr "$1" : "apache" 1>/dev/null || [ "$1" = "php-fpm" ] || [ "$1" = "frankenphp" ] || [ "${NEXTCLOUD_UPDATE:-0}" -eq 1 ]; then
uid="$(id -u)"
gid="$(id -g)"
if [ "$uid" = '0' ]; then
case "$1" in
apache2*)
user="${APACHE_RUN_USER:-www-data}"
group="${APACHE_RUN_GROUP:-www-data}"
# strip off any '#' symbol ('#1000' is valid syntax for Apache)
user="${user#'#'}"
group="${group#'#'}"
;;
*) # php-fpm
user='www-data'
group='www-data'
;;
esac
else
user="$uid"
group="$gid"
fi
if [ -n "${REDIS_HOST+x}" ]; then
echo "Configuring Redis as session handler"
{
file_env REDIS_HOST_PASSWORD
echo 'session.save_handler = redis'
# check if redis host is an unix socket path
if [ "$(echo "$REDIS_HOST" | cut -c1-1)" = "/" ]; then
if [ -n "${REDIS_HOST_PASSWORD+x}" ]; then
echo "session.save_path = \"unix://${REDIS_HOST}?auth=${REDIS_HOST_PASSWORD}\""
else
echo "session.save_path = \"unix://${REDIS_HOST}\""
fi
# check if redis password has been set
elif [ -n "${REDIS_HOST_PASSWORD+x}" ]; then
echo "session.save_path = \"tcp://${REDIS_HOST}:${REDIS_HOST_PORT:=6379}?auth=${REDIS_HOST_PASSWORD}\""
else
echo "session.save_path = \"tcp://${REDIS_HOST}:${REDIS_HOST_PORT:=6379}\""
fi
echo "redis.session.locking_enabled = 1"
echo "redis.session.lock_retries = -1"
# redis.session.lock_wait_time is specified in microseconds.
# Wait 10ms before retrying the lock rather than the default 2ms.
echo "redis.session.lock_wait_time = 10000"
} >/usr/local/etc/php/conf.d/redis-session.ini
fi
# If another process is syncing the html folder, wait for
# it to be done, then escape initalization.
(
if ! flock -n 9; then
# If we couldn't get it immediately, show a message, then wait for real
echo "Another process is initializing Nextcloud. Waiting..."
flock 9
fi
installed_version="0.0.0.0"
if [ -f /var/www/html/version.php ]; then
# shellcheck disable=SC2016
installed_version="$(php -r 'require "/var/www/html/version.php"; echo implode(".", $OC_Version);')"
fi
# shellcheck disable=SC2016
image_version="$(php -r 'require "/usr/src/nextcloud/version.php"; echo implode(".", $OC_Version);')"
if version_greater "$installed_version" "$image_version"; then
echo "Can't start Nextcloud because the version of the data ($installed_version) is higher than the docker image version ($image_version) and downgrading is not supported. Are you sure you have pulled the newest image version?"
exit 1
fi
if version_greater "$image_version" "$installed_version"; then
echo "Initializing nextcloud $image_version ..."
if [ "$installed_version" != "0.0.0.0" ]; then
if [ "${image_version%%.*}" -gt "$((${installed_version%%.*} + 1))" ]; then
echo "Can't start Nextcloud because upgrading from $installed_version to $image_version is not supported."
echo "It is only possible to upgrade one major version at a time. For example, if you want to upgrade from version 14 to 16, you will have to upgrade from version 14 to 15, then from 15 to 16."
exit 1
fi
echo "Upgrading nextcloud from $installed_version ..."
run_as 'php /var/www/html/occ app:list' | sed -n "/Enabled:/,/Disabled:/p" >/tmp/list_before
fi
if [ "$(id -u)" = 0 ]; then
rsync_options="-rlDog --chown $user:$group"
else
rsync_options="-rlD"
fi
rsync $rsync_options --delete --exclude-from=/upgrade.exclude /usr/src/nextcloud/ /var/www/html/
for dir in config data custom_apps themes; do
if [ ! -d "/var/www/html/$dir" ] || directory_empty "/var/www/html/$dir"; then
rsync $rsync_options --include "/$dir/" --exclude '/*' /usr/src/nextcloud/ /var/www/html/
fi
done
rsync $rsync_options --include '/version.php' --exclude '/*' /usr/src/nextcloud/ /var/www/html/
# Install
if [ "$installed_version" = "0.0.0.0" ]; then
echo "New nextcloud instance"
file_env NEXTCLOUD_ADMIN_PASSWORD
file_env NEXTCLOUD_ADMIN_USER
if [ -n "${NEXTCLOUD_ADMIN_USER+x}" ] && [ -n "${NEXTCLOUD_ADMIN_PASSWORD+x}" ]; then
# shellcheck disable=SC2016
install_options='-n --admin-user "$NEXTCLOUD_ADMIN_USER" --admin-pass "$NEXTCLOUD_ADMIN_PASSWORD"'
if [ -n "${NEXTCLOUD_DATA_DIR+x}" ]; then
# shellcheck disable=SC2016
install_options=$install_options' --data-dir "$NEXTCLOUD_DATA_DIR"'
fi
file_env MYSQL_DATABASE
file_env MYSQL_PASSWORD
file_env MYSQL_USER
file_env POSTGRES_DB
file_env POSTGRES_PASSWORD
file_env POSTGRES_USER
install=false
if [ -n "${SQLITE_DATABASE+x}" ]; then
echo "Installing with SQLite database"
# shellcheck disable=SC2016
install_options=$install_options' --database-name "$SQLITE_DATABASE"'
install=true
elif [ -n "${MYSQL_DATABASE+x}" ] && [ -n "${MYSQL_USER+x}" ] && [ -n "${MYSQL_PASSWORD+x}" ] && [ -n "${MYSQL_HOST+x}" ]; then
echo "Installing with MySQL database"
# shellcheck disable=SC2016
install_options=$install_options' --database mysql --database-name "$MYSQL_DATABASE" --database-user "$MYSQL_USER" --database-pass "$MYSQL_PASSWORD" --database-host "$MYSQL_HOST"'
install=true
elif [ -n "${POSTGRES_DB+x}" ] && [ -n "${POSTGRES_USER+x}" ] && [ -n "${POSTGRES_PASSWORD+x}" ] && [ -n "${POSTGRES_HOST+x}" ]; then
echo "Installing with PostgreSQL database"
# shellcheck disable=SC2016
install_options=$install_options' --database pgsql --database-name "$POSTGRES_DB" --database-user "$POSTGRES_USER" --database-pass "$POSTGRES_PASSWORD" --database-host "$POSTGRES_HOST"'
install=true
fi
if [ "$install" = true ]; then
run_path pre-installation
echo "Starting nextcloud installation"
max_retries=10
try=0
until run_as "php /var/www/html/occ maintenance:install $install_options" || [ "$try" -gt "$max_retries" ]; do
echo "Retrying install..."
try=$((try + 1))
sleep 10s
done
if [ "$try" -gt "$max_retries" ]; then
echo "Installing of nextcloud failed!"
exit 1
fi
if [ -n "${NEXTCLOUD_TRUSTED_DOMAINS+x}" ]; then
echo "Setting trusted domains…"
NC_TRUSTED_DOMAIN_IDX=1
for DOMAIN in $NEXTCLOUD_TRUSTED_DOMAINS; do
DOMAIN=$(echo "$DOMAIN" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//')
run_as "php /var/www/html/occ config:system:set trusted_domains $NC_TRUSTED_DOMAIN_IDX --value=$DOMAIN"
NC_TRUSTED_DOMAIN_IDX=$((NC_TRUSTED_DOMAIN_IDX + 1))
done
fi
run_path post-installation
else
echo "Please run the web-based installer on first connect!"
fi
fi
# Upgrade
else
run_path pre-upgrade
run_as 'php /var/www/html/occ upgrade'
run_as 'php /var/www/html/occ app:list' | sed -n "/Enabled:/,/Disabled:/p" >/tmp/list_after
echo "The following apps have been disabled:"
diff /tmp/list_before /tmp/list_after | grep '<' | cut -d- -f2 | cut -d: -f1
rm -f /tmp/list_before /tmp/list_after
run_path post-upgrade
fi
echo "Initializing finished"
fi
# Update htaccess after init if requested
if [ -n "${NEXTCLOUD_INIT_HTACCESS+x}" ] && [ "$installed_version" != "0.0.0.0" ]; then
run_as 'php /var/www/html/occ maintenance:update:htaccess'
fi
) 9>/var/www/html/nextcloud-init-sync.lock
run_path before-starting
fi
exec "$@"
Caddy logs
app-1 | New nextcloud instance
app-1 | Installing with PostgreSQL database
app-1 | => Searching for scripts (*.sh) to run, located in the folder: /docker-entrypoint-hooks.d/pre-installation
app-1 | Starting nextcloud installation
app-1 | Nextcloud was successfully installed
app-1 | => Searching for scripts (*.sh) to run, located in the folder: /docker-entrypoint-hooks.d/post-installation
app-1 | Initializing finished
app-1 | => Searching for scripts (*.sh) to run, located in the folder: /docker-entrypoint-hooks.d/before-starting
app-1 | {"level":"info","ts":1707121293.4429927,"msg":"using provided configuration","config_file":"/etc/caddy/Caddyfile","config_adapter":""}
app-1 | {"level":"info","ts":1707121293.4698567,"logger":"admin","msg":"admin endpoint started","address":"localhost:2019","enforce_origin":false,"origins":["//localhost:2019","//[::1]:2019","//127.0.0.1:2019"]}
app-1 | {"level":"info","ts":1707121293.4729865,"logger":"http.auto_https","msg":"server is listening only on the HTTPS port but has no TLS connection policies; adding one to enable TLS","server_name":"srv0","https_port":443}
app-1 | {"level":"info","ts":1707121293.4733138,"logger":"http.auto_https","msg":"enabling automatic HTTP->HTTPS redirects","server_name":"srv0"}
app-1 | {"level":"info","ts":1707121293.4752572,"logger":"tls.cache.maintenance","msg":"started background certificate maintenance","cache":"0xc00042ca00"}
app-1 | {"level":"info","ts":1707121293.4928567,"msg":"FrankenPHP started 🐘","php_version":"8.2.15"}
app-1 | {"level":"info","ts":1707121293.5175326,"logger":"tls","msg":"cleaning storage unit","storage":"FileStorage:/data/caddy"}
app-1 | {"level":"info","ts":1707121293.5254633,"logger":"tls","msg":"finished cleaning storage units"}
app-1 | {"level":"warn","ts":1707121294.02207,"logger":"pki.ca.local","msg":"installing root certificate (you might be prompted for password)","path":"storage:pki/authorities/local/root.crt"}
app-1 | {"level":"info","ts":1707121294.0234227,"msg":"warning: \"certutil\" is not available, install \"certutil\" with \"apt install libnss3-tools\" or \"yum install nss-tools\" and try again"}
app-1 | {"level":"info","ts":1707121294.0236008,"msg":"define JAVA_HOME environment variable to use the Java trust"}
app-1 | {"level":"info","ts":1707121300.6172276,"msg":"certificate installed properly in linux trusts"}
app-1 | {"level":"info","ts":1707121300.6183708,"logger":"http","msg":"enabling HTTP/3 listener","addr":":443"}
app-1 | {"level":"info","ts":1707121300.6520422,"msg":"failed to sufficiently increase receive buffer size (was: 208 kiB, wanted: 2048 kiB, got: 416 kiB). See https://github.com/quic-go/quic-go/wiki/UDP-Buffer-Sizes for details."}
app-1 | {"level":"info","ts":1707121300.655253,"logger":"http.log","msg":"server running","name":"srv0","protocols":["h1","h2","h3"]}
app-1 | {"level":"info","ts":1707121300.6573725,"logger":"http.log","msg":"server running","name":"remaining_auto_https_redirects","protocols":["h1","h2","h3"]}
app-1 | {"level":"info","ts":1707121300.657596,"logger":"http","msg":"enabling automatic TLS certificate management","domains":["localhost"]}
app-1 | {"level":"info","ts":1707121300.6600044,"msg":"autosaved config (load with --resume flag)","file":"/config/caddy/autosave.json"}
app-1 | {"level":"info","ts":1707121300.6603096,"msg":"serving initial configuration"}
app-1 | {"level":"info","ts":1707121300.665742,"logger":"tls.obtain","msg":"acquiring lock","identifier":"localhost"}
app-1 | {"level":"info","ts":1707121300.684313,"logger":"tls.obtain","msg":"lock acquired","identifier":"localhost"}
app-1 | {"level":"info","ts":1707121300.685793,"logger":"tls.obtain","msg":"obtaining certificate","identifier":"localhost"}
app-1 | {"level":"info","ts":1707121300.7016816,"logger":"tls.obtain","msg":"certificate obtained successfully","identifier":"localhost"}
app-1 | {"level":"info","ts":1707121300.7032683,"logger":"tls.obtain","msg":"releasing lock","identifier":"localhost"}
app-1 | {"level":"warn","ts":1707121300.709363,"logger":"tls","msg":"stapling OCSP","error":"no OCSP stapling for [localhost]: no OCSP server specified in certificate","identifiers":["localhost"]}
app-1 exited with code 0
Now when I try to run the docker image with the below caddyfile
{
debug
frankenphp
order mercure after encode
order vulcain after reverse_proxy
order php_server before file_server
order php before file_server
}
localhost {
root * /var/www/html/
encode zstd br gzip
php_server
}
The container crashes when I visit https://localhost
Build Type
Docker (Alpine)
Worker Mode
No
Operating System
GNU/Linux
CPU Architecture
x86_64
Relevant log output
No response
I see an exit code 0, so something cleanly terminated the server. That would be a good starting point, try to figure out why the server is exiting.
Hey ! I suspect it may be due to user change as I see some logs mentioning cannot create directories.
To add more info, when run with the worker mode, it crashes with code 139
The app seems to work fine with php-fpm - likely because of the user and group settings in fpm config.
Worker mode logs
app-1 | {"level":"info","ts":1707285398.4587631,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4600906,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4621444,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.464938,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4678853,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4696634,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4722056,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4762714,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4780812,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4812984,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.484174,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4860249,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.487745,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4927628,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4943702,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4953227,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4966986,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4979026,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.4991028,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5024211,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5029106,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.505871,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5074112,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5090914,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.511721,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5135226,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5152075,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5169046,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5195568,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5241697,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5267816,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5330698,"msg":"restarting","worker":"/var/www/html/index.php"}
app-1 | {"level":"info","ts":1707285398.5395887,"msg":"restarting","worker":"/var/www/html/index.php"}
db-1 | 2024-02-07 05:56:38.550 UTC [440] LOG: could not receive data from client: Connection reset by peer
app-1 exited with code 139
yes, php-fpm starts as root and then switches users after opening ports. Caddy starts as whatever user starts it and that's it. This means if you want to open a port less than 1024, you'll need to give it permission to do so, as well as give it access to whatever folders it needs access to as that user.
There's a pretty good guide here: https://www.booleanworld.com/host-website-caddy-web-server-linux/ that is still relevant and covers all the details.
Have updated the docs at #565 as I wasn't able to use the existing example.
I have been able to create a container which runs as www-data. Now I see segmentation fault in the frankenphp.
app-1 | {"level":"info","ts":1707555919.3249483,"logger":"tls","msg":"finished cleaning storage units"}
app-1 | Segmentation fault
app-1 exited with code 0
Hmm, I see it uses amphp which uses fibers, which means you might be hitting #46 ...
Something I haven't tried, but might be worth trying, is to try putting this in your worker script:
// at the beginning of the request
ob_start();
// handle request
// at the very end of the request
ob_end_flush();
That should prevent any output from being sent to Go inside a fiber 🤞 and prevent the crash. I'm not sure about headers, which we would also want to prevent. It would also prevent any streaming responses from working, so it isn't ideal. At all (and might break many things).
@dunglas it just occurred to me (and possibly not even related to the main issue) that it might be worth asking in internals if there is a way to switch back to the main stack in C, then send the data to Go, then switch the stack back to the target stack and resume execution; instead of sending output directly to Go.
Something like this:
void handleOutputCallback(/*args*/) {
if(!in_fiber()) {
go_output(/*args*/);
}
original_stack = switch_fiber_stack_main();
go_output(/*args*/);
switch_fiber_stack(original_stack);
}
I'm pretty sick today, so I can't do anything complicated like digging into that.
Hello, can reproduce using FrankenPHP standalone binary on arm64 (Raspberry Pi 3)
I can successfully install Nextcloud using occ command :
OCC_CMD="./frankenphp php-cli nextcloud/occ"
$OCC_CMD maintenance:install \
--database='pgsql' --database-name='nextcloud' --database-host='localhost' \
--database-user='nextcloud' --database-pass='nextcloud' \
--admin-user='admin' --admin-pass='admin
When, at the first connection using the Web UI, I got a segmentation fault:
root@DietPi:/mnt/dietpi_userdata/iglou# ./frankenphp php-server
2024/05/01 09:53:22.085 WARN admin admin endpoint disabled
2024/05/01 09:53:22.085 WARN http.auto_https server is listening only on the HTTP port, so no automatic HTTPS will be applied to this server {"server_name": "php", "http_port": 80}
2024/05/01 09:53:22.085 INFO tls.cache.maintenance started background certificate maintenance {"cache": "0x40004de100"}
2024/05/01 09:53:22.088 INFO FrankenPHP started 🐘 {"php_version": "8.3.6"}
2024/05/01 09:53:22.090 INFO http.log server running {"name": "php", "protocols": ["h1", "h2", "h3"]}
2024/05/01 09:53:22.090 INFO Caddy serving PHP app on :80
2024/05/01 09:53:22.147 WARN tls storage cleaning happened too recently; skipping for now {"storage": "FileStorage:/root/.local/share/caddy", "instance": "598d3c03-4a41-4648-bf3f-e649b833ae03", "try_again": "2024/05/02 09:53:22.147", "try_again_in": 86399.999997343}
2024/05/01 09:53:22.148 INFO tls finished cleaning storage units
Segmentation fault
I could try to reproduce it on x86_64, if it is useful? Thanks
What would be the most useful is a stack trace.
You can gather one by following these instructions: https://frankenphp.dev/docs/contributing/#debugging-segmentation-faults-with-static-builds