Files
homarr/scripts/run.sh
T

113 lines
3.3 KiB
Bash

#!/usr/bin/env bash
MIGRATION_PID=""
NEXTJS_PID=""
NGINX_PID=""
REDIS_PID=""
SHUTTING_DOWN=false
stop_process() {
if [ -n "$1" ]; then
kill -TERM "$1" 2>/dev/null
wait "$1" 2>/dev/null
fi
}
terminate() {
trap '' TERM INT
SHUTTING_DOWN=true
echo "Shutting down..."
stop_process "$MIGRATION_PID"
stop_process "$NEXTJS_PID"
stop_process "$NGINX_PID"
stop_process "$REDIS_PID"
echo "Shutdown complete."
exit 0
}
# Install before migrations: a foreground child defers the shell's signal trap.
trap terminate TERM INT
# Check before creating SQLite files or invoking a removed migration bundle.
reject_mysql() {
echo "ERROR: MySQL is no longer supported in v2. Use the MySQL-to-SQLite converter before starting Homarr."
exit 1
}
case "$DB_DIALECT:$DB_DRIVER" in
mysql:*|mariadb:*|*:mysql2|*:mysql|*:mariadb) reject_mysql ;;
esac
case "$DB_URL" in
[mM][yY][sS][qQ][lL]:*|[mM][aA][rR][iI][aA][dD][bB]:*) reject_mysql ;;
esac
# Create sub directories in volume
mkdir -p /appdata/db
mkdir -p /appdata/redis
mkdir -p /appdata/trusted-certificates
# Run migrations
if [ "$DB_MIGRATIONS_DISABLED" = "true" ]; then
echo "DB migrations are disabled, skipping"
else
echo "Running DB migrations"
DISABLE_REDIS_LOGS=true node ./db/migrations/$DB_DIALECT/migrate.cjs ./db/migrations/$DB_DIALECT &
MIGRATION_PID=$!
wait "$MIGRATION_PID"
MIGRATION_EXIT_CODE=$?
MIGRATION_PID=""
if [ "$MIGRATION_EXIT_CODE" -ne 0 ]; then
echo "ERROR: DB migrations failed, aborting startup"
exit 1
fi
fi
# Auth secret is generated every time the container starts as it is required, but not used because we don't need JWTs or Mail hashing
export AUTH_SECRET=$(openssl rand -base64 32)
# Start nginx proxy
# 1. Create the nginx configuration file from the template
# 2. Start the nginx server
# Only listen on IPv6 when the host actually has IPv6 configured (#4596).
# Otherwise nginx aborts with "socket() [::]:7575 failed (97: Address family
# not supported by protocol)". Check HOMARR_DISABLE_IPV6 first so users can
# force IPv4-only even when the host supports IPv6, then probe for IPv6
# addresses via grep (not -s: proc files always report size 0).
export NGINX_LISTEN_IPV6=''
if [ "${HOMARR_DISABLE_IPV6:-false}" != "true" ] && grep -q . /proc/net/if_inet6 2>/dev/null; then
NGINX_LISTEN_IPV6='listen [::]:7575;'
fi
envsubst '${NGINX_LISTEN_IPV6}' < /etc/nginx/templates/nginx.conf > /etc/nginx/nginx.conf
# Start services in the background and store their PIDs
nginx -g 'daemon off;' &
NGINX_PID=$!
if [ "$REDIS_IS_EXTERNAL" = "true" ]; then
echo "Using external Redis server at redis://$REDIS_HOST:$REDIS_PORT"
REDIS_PID=""
else
echo "Starting internal Redis server"
redis-server /app/redis.conf &
REDIS_PID=$!
fi
# Next.js standalone uses HOSTNAME as its bind address. Docker's generated
# hostname can be unresolvable, so bind explicitly while nginx uses loopback.
export HOSTNAME=0.0.0.0
export NODE_OPTIONS="--max-semi-space-size=4 ${NODE_OPTIONS:-}"
node apps/nextjs/server.js &
NEXTJS_PID=$!
while true; do
wait $NEXTJS_PID
EXIT_CODE=$?
if [ "$SHUTTING_DOWN" = true ]; then
break
fi
echo "Next.js exited with code $EXIT_CODE, restarting in 1s..."
sleep 1
node apps/nextjs/server.js &
NEXTJS_PID=$!
done