mirror of
https://github.com/coollabsio/coolify.git
synced 2026-10-28 17:44:36 +08:00
117 lines
4.6 KiB
Bash
Executable File
117 lines
4.6 KiB
Bash
Executable File
#!/usr/bin/env bash
|
||
# Patches Coolify 4.0 to 4.4 to the security fix release of its own line.
|
||
# Only the coolify container is recreated, the compose files and the other containers stay as they are.
|
||
# Usage: curl -fsSL https://cdn.coollabs.io/coolify/patch.sh | sudo bash
|
||
set -euo pipefail
|
||
|
||
SOURCE_DIR=/data/coolify/source
|
||
ENV_FILE="$SOURCE_DIR/.env"
|
||
TIMESTAMP="$(date +%Y-%m-%d-%H-%M-%S)"
|
||
LOG_FILE="$SOURCE_DIR/patch-$TIMESTAMP.log"
|
||
BACKUP_FILE="$ENV_FILE-$TIMESTAMP"
|
||
PATCH_VERSIONS=(4.0.1 4.1.3 4.2.1 4.3.24 4.4.7)
|
||
|
||
BOLD=$'\033[1m' GREEN=$'\033[32m' BLUE=$'\033[34m' RED=$'\033[31m' RESET=$'\033[0m'
|
||
|
||
heading() { printf '\n %s%s%s\n' "$BOLD" "$*" "$RESET"; }
|
||
info() { printf ' %sℹ%s %s\n' "$BLUE" "$RESET" "$*"; }
|
||
ok() { printf ' %s✔%s %s\n' "$GREEN" "$RESET" "$*"; }
|
||
die() {
|
||
printf ' %s✖%s %s\n' "$RED" "$RESET" "$*" >&2
|
||
exit 1
|
||
}
|
||
|
||
main() {
|
||
check_installation
|
||
read_version
|
||
select_patch_version
|
||
check_compose_files
|
||
heading "Patching Coolify $current_version to $patch_version"
|
||
pull_image
|
||
update_env_file
|
||
restart_coolify
|
||
wait_for_coolify
|
||
}
|
||
|
||
check_installation() {
|
||
heading "Checking the installation"
|
||
[ "$EUID" = 0 ] || die "run this script as root, for example with sudo"
|
||
[ -f "$ENV_FILE" ] && [ -f "$SOURCE_DIR/docker-compose.prod.yml" ] || die "Coolify is not installed in $SOURCE_DIR"
|
||
docker compose version > /dev/null 2>&1 || die "the Docker Compose plugin is not installed"
|
||
compose=(docker compose --env-file "$ENV_FILE" -f "$SOURCE_DIR/docker-compose.yml" -f "$SOURCE_DIR/docker-compose.prod.yml")
|
||
if [ -f "$SOURCE_DIR/docker-compose.custom.yml" ]; then
|
||
compose+=(-f "$SOURCE_DIR/docker-compose.custom.yml")
|
||
fi
|
||
if [ -f "$SOURCE_DIR/docker-compose.postgres-upgrade.yml" ]; then
|
||
compose+=(-f "$SOURCE_DIR/docker-compose.postgres-upgrade.yml")
|
||
fi
|
||
ok "Coolify is installed in $SOURCE_DIR"
|
||
}
|
||
|
||
read_version() {
|
||
# Copy the file out of the container, because this also works when the mitigation advice was followed and the container is stopped
|
||
current_version="$(docker cp coolify:/var/www/html/config/constants.php - 2> /dev/null | tar -xO 2> /dev/null | awk -F "'" "/'version' =>/ && !found { print \$(NF - 1); found = 1 }")" && [ -n "$current_version" ] || die "could not read the Coolify version from the coolify container"
|
||
ok "Coolify $BOLD$current_version$RESET is installed"
|
||
}
|
||
|
||
select_patch_version() {
|
||
[[ "$current_version" =~ ^4\.([0-4])\.([0-9]+)$ ]] || die "Coolify $current_version has no security fix release, upgrade to the latest version from the dashboard instead"
|
||
patch_version="${PATCH_VERSIONS[${BASH_REMATCH[1]}]}"
|
||
if [ "${BASH_REMATCH[2]}" -ge "${patch_version##*.}" ]; then
|
||
ok "Coolify $current_version already includes the security fixes"
|
||
exit 0
|
||
fi
|
||
}
|
||
|
||
check_compose_files() {
|
||
local has_realtime=false needs_realtime=true
|
||
if grep -q 'coollabsio/coolify-realtime:' "$SOURCE_DIR/docker-compose.prod.yml"; then
|
||
has_realtime=true
|
||
fi
|
||
if [[ "$patch_version" == 4.4.* ]]; then
|
||
needs_realtime=false
|
||
fi
|
||
[ "$has_realtime" = "$needs_realtime" ] || die "the compose files in $SOURCE_DIR do not belong to Coolify $current_version, update to ${PATCH_VERSIONS[4]} instead: curl -fsSL https://cdn.coollabs.io/coolify/upgrade.sh | sudo bash -s ${PATCH_VERSIONS[4]}"
|
||
ok "the compose files belong to Coolify $current_version"
|
||
}
|
||
|
||
pull_image() {
|
||
LATEST_IMAGE="$patch_version" "${compose[@]}" pull coolify < /dev/null >> "$LOG_FILE" 2>&1 || die "could not pull Coolify $patch_version, nothing was changed (log: $LOG_FILE)"
|
||
ok "pulled Coolify $patch_version"
|
||
}
|
||
|
||
update_env_file() {
|
||
local key updated
|
||
cp "$ENV_FILE" "$BACKUP_FILE"
|
||
for key in LATEST_IMAGE COOLIFY_VERSION; do
|
||
if grep -q "^$key=" "$ENV_FILE"; then
|
||
updated="$(sed "s|^$key=.*|$key=$patch_version|" "$ENV_FILE")"
|
||
printf '%s\n' "$updated" > "$ENV_FILE"
|
||
fi
|
||
done
|
||
ok "backed up .env to $BACKUP_FILE"
|
||
}
|
||
|
||
restart_coolify() {
|
||
# Detached, because the Coolify 4.4 terminal runs inside the coolify container and closes when it stops
|
||
LATEST_IMAGE="$patch_version" nohup "${compose[@]}" up -d --no-deps coolify < /dev/null >> "$LOG_FILE" 2>&1 &
|
||
wait $! || die "could not restart the coolify container (log: $LOG_FILE)"
|
||
ok "restarted the coolify container"
|
||
}
|
||
|
||
wait_for_coolify() {
|
||
local status
|
||
for _ in $(seq 60); do
|
||
status="$(docker inspect --format '{{.State.Health.Status}}' coolify 2> /dev/null || true)"
|
||
if [ "$status" = healthy ]; then
|
||
ok "Coolify $BOLD$patch_version$RESET is healthy and runs PHP $(docker exec coolify php -r 'echo PHP_VERSION;')"
|
||
return
|
||
fi
|
||
sleep 5
|
||
done
|
||
info "roll back with: cp $BACKUP_FILE $ENV_FILE && LATEST_IMAGE=$current_version ${compose[*]} up -d --no-deps coolify"
|
||
die "Coolify $patch_version is not healthy after 5 minutes, check it with: docker logs coolify"
|
||
}
|
||
|
||
main
|