From 54eb4e3ffe4e60bee0718127e1fe8c0ccf977346 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 17 Jan 2025 17:22:52 +0100 Subject: [PATCH 01/12] feat: add log file check message in upgrade script for better troubleshooting --- scripts/upgrade.sh | 1 + 1 file changed, 1 insertion(+) diff --git a/scripts/upgrade.sh b/scripts/upgrade.sh index 1bdf0f461..369ac067d 100644 --- a/scripts/upgrade.sh +++ b/scripts/upgrade.sh @@ -33,6 +33,7 @@ fi docker network create --attachable coolify 2>/dev/null # docker network create --attachable --driver=overlay coolify-overlay 2>/dev/null +echo "If you encounter any issues, please check the log file: $LOGFILE" if [ -f /data/coolify/source/docker-compose.custom.yml ]; then echo "docker-compose.custom.yml detected." >> $LOGFILE docker run -v /data/coolify/source:/data/coolify/source -v /var/run/docker.sock:/var/run/docker.sock --rm ghcr.io/coollabsio/coolify-helper:${LATEST_HELPER_VERSION} bash -c "LATEST_IMAGE=${LATEST_IMAGE} docker compose --env-file /data/coolify/source/.env -f /data/coolify/source/docker-compose.yml -f /data/coolify/source/docker-compose.prod.yml -f /data/coolify/source/docker-compose.custom.yml up -d --remove-orphans --force-recreate --wait --wait-timeout 60" >> $LOGFILE 2>&1 From 0b4211512733bb20bfc08ba51a551a07ce204909 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 17 Jan 2025 17:30:26 +0100 Subject: [PATCH 02/12] feat: add root user details to install script --- other/nightly/install.sh | 8 ++++---- scripts/install.sh | 20 +++++++++++++++++++- 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index 766b1fc63..1889ad355 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -8,7 +8,7 @@ set -o pipefail # Cause a pipeline to return the status of the last command that CDN="https://cdn.coollabs.io/coolify" DATE=$(date +"%Y%m%d-%H%M%S") -VERSION="1.6" +VERSION="1.7" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -488,13 +488,13 @@ fi # Add default root user credentials from environment variables if [ -n "$ROOT_USERNAME" ] && [ -n "$ROOT_USER_EMAIL" ] && [ -n "$ROOT_USER_PASSWORD" ]; then - if ! grep -q "^ROOT_USERNAME=" "$ENV_FILE-$DATE"; then + if grep -q "^ROOT_USERNAME=" "$ENV_FILE-$DATE"; then sed -i "s|^ROOT_USERNAME=.*|ROOT_USERNAME=$ROOT_USERNAME|" "$ENV_FILE-$DATE" fi - if ! grep -q "^ROOT_USER_EMAIL=" "$ENV_FILE-$DATE"; then + if grep -q "^ROOT_USER_EMAIL=" "$ENV_FILE-$DATE"; then sed -i "s|^ROOT_USER_EMAIL=.*|ROOT_USER_EMAIL=$ROOT_USER_EMAIL|" "$ENV_FILE-$DATE" fi - if ! grep -q "^ROOT_USER_PASSWORD=" "$ENV_FILE-$DATE"; then + if grep -q "^ROOT_USER_PASSWORD=" "$ENV_FILE-$DATE"; then sed -i "s|^ROOT_USER_PASSWORD=.*|ROOT_USER_PASSWORD=$ROOT_USER_PASSWORD|" "$ENV_FILE-$DATE" fi fi diff --git a/scripts/install.sh b/scripts/install.sh index b5e163907..1889ad355 100755 --- a/scripts/install.sh +++ b/scripts/install.sh @@ -8,7 +8,7 @@ set -o pipefail # Cause a pipeline to return the status of the last command that CDN="https://cdn.coollabs.io/coolify" DATE=$(date +"%Y%m%d-%H%M%S") -VERSION="1.6" +VERSION="1.7" DOCKER_VERSION="27.0" # TODO: Ask for a user CURRENT_USER=$USER @@ -22,6 +22,11 @@ echo -e "Welcome to Coolify Installer!" echo -e "This script will install everything for you. Sit back and relax." echo -e "Source code: https://github.com/coollabsio/coolify/blob/main/scripts/install.sh\n" +# Predefined root user +ROOT_USERNAME=${ROOT_USERNAME:-} +ROOT_USER_EMAIL=${ROOT_USER_EMAIL:-} +ROOT_USER_PASSWORD=${ROOT_USER_PASSWORD:-} + TOTAL_SPACE=$(df -BG / | awk 'NR==2 {print $2}' | sed 's/G//') AVAILABLE_SPACE=$(df -BG / | awk 'NR==2 {print $4}' | sed 's/G//') REQUIRED_TOTAL_SPACE=30 @@ -481,6 +486,19 @@ else sed -i "s|^PUSHER_APP_SECRET=.*|PUSHER_APP_SECRET=$(openssl rand -hex 32)|" "$ENV_FILE-$DATE" fi +# Add default root user credentials from environment variables +if [ -n "$ROOT_USERNAME" ] && [ -n "$ROOT_USER_EMAIL" ] && [ -n "$ROOT_USER_PASSWORD" ]; then + if grep -q "^ROOT_USERNAME=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USERNAME=.*|ROOT_USERNAME=$ROOT_USERNAME|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_EMAIL=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_EMAIL=.*|ROOT_USER_EMAIL=$ROOT_USER_EMAIL|" "$ENV_FILE-$DATE" + fi + if grep -q "^ROOT_USER_PASSWORD=" "$ENV_FILE-$DATE"; then + sed -i "s|^ROOT_USER_PASSWORD=.*|ROOT_USER_PASSWORD=$ROOT_USER_PASSWORD|" "$ENV_FILE-$DATE" + fi +fi + # Merge .env and .env.production. New values will be added to .env echo -e "7. Propagating .env with new values - if necessary." awk -F '=' '!seen[$1]++' "$ENV_FILE-$DATE" /data/coolify/source/.env.production > $ENV_FILE From 815abb823c1e2576cde8b5ea905757760f4292e7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Fri, 17 Jan 2025 17:31:17 +0100 Subject: [PATCH 03/12] version++ --- config/constants.php | 2 +- versions.json | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/config/constants.php b/config/constants.php index 1aff0b787..fc2d92c56 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.382', + 'version' => '4.0.0-beta.383', 'self_hosted' => env('SELF_HOSTED', true), 'autoupdate' => env('AUTOUPDATE'), 'base_config_path' => env('BASE_CONFIG_PATH', '/data/coolify'), diff --git a/versions.json b/versions.json index f8214d091..a1a01432c 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.382" + "version": "4.0.0-beta.383" }, "nightly": { - "version": "4.0.0-beta.383" + "version": "4.0.0-beta.384" }, "helper": { "version": "1.0.4" From 36a987eb9d5fb43e9a43f8bd861718fa4cd567af Mon Sep 17 00:00:00 2001 From: Zakher Masri <46135573+zaaakher@users.noreply.github.com> Date: Mon, 20 Jan 2025 13:33:25 +0300 Subject: [PATCH 04/12] fix(ui): missing underline for docs link in the Swarm section (#4860) --- resources/views/livewire/server/new/by-ip.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/server/new/by-ip.blade.php b/resources/views/livewire/server/new/by-ip.blade.php index b0786341e..225a59a5a 100644 --- a/resources/views/livewire/server/new/by-ip.blade.php +++ b/resources/views/livewire/server/new/by-ip.blade.php @@ -31,7 +31,7 @@

Swarm (experimental)

-
Read the docs Read the docs here.
@if ($is_swarm_worker || $is_build_server) Date: Mon, 20 Jan 2025 10:35:59 +0000 Subject: [PATCH 05/12] fix(service): Change chatwoot service postgres image from `postgres:12` to `pgvector/pgvector:pg12` --- templates/compose/chatwoot.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/chatwoot.yaml b/templates/compose/chatwoot.yaml index aaeb73071..b7eec88cc 100644 --- a/templates/compose/chatwoot.yaml +++ b/templates/compose/chatwoot.yaml @@ -88,7 +88,7 @@ services: retries: 3 postgres: - image: postgres:12 + image: pgvector/pgvector:pg12 restart: always volumes: - postgres-data:/var/lib/postgresql/data From eaf546fe75f643dfeb213a74766d8ed89afbbf5a Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Mon, 20 Jan 2025 13:38:39 +0100 Subject: [PATCH 06/12] Update service-templates.json --- templates/service-templates.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/service-templates.json b/templates/service-templates.json index 4de2e70e6..c703f9bdc 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -358,7 +358,7 @@ "chatwoot": { "documentation": "https://www.chatwoot.com/docs/self-hosted/?utm_source=coolify.io", "slogan": "Delightful customer relationships at scale.", - "compose": "c2VydmljZXM6CiAgY2hhdHdvb3Q6CiAgICBpbWFnZTogJ2NoYXR3b290L2NoYXR3b290OmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcG9zdGdyZXMKICAgICAgLSByZWRpcwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0NIQVRXT09UXzMwMDAKICAgICAgLSBTRUNSRVRfS0VZX0JBU0U9JFNFUlZJQ0VfUEFTU1dPUkRfQ0hBVFdPT1QKICAgICAgLSAnRlJPTlRFTkRfVVJMPSR7U0VSVklDRV9GUUROX0NIQVRXT09UfScKICAgICAgLSAnREVGQVVMVF9MT0NBTEU9JHtDSEFUV09PVF9ERUZBVUxUX0xPQ0FMRX0nCiAgICAgIC0gJ0ZPUkNFX1NTTD0ke0ZPUkNFX1NTTDotZmFsc2V9JwogICAgICAtICdFTkFCTEVfQUNDT1VOVF9TSUdOVVA9JHtFTkFCTEVfQUNDT1VOVF9TSUdOVVA6LWZhbHNlfScKICAgICAgLSAnUkVESVNfVVJMPXJlZGlzOi8vZGVmYXVsdEByZWRpczo2Mzc5JwogICAgICAtIFJFRElTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1JFRElTCiAgICAgIC0gJ1JFRElTX09QRU5TU0xfVkVSSUZZX01PREU9JHtSRURJU19PUEVOU1NMX1ZFUklGWV9NT0RFOi1ub25lfScKICAgICAgLSAnUE9TVEdSRVNfREFUQUJBU0U9JHtQT1NUR1JFU19EQjotY2hhdHdvb3R9JwogICAgICAtICdQT1NUR1JFU19IT1NUPSR7UE9TVEdSRVNfSE9TVDotcG9zdGdyZXN9JwogICAgICAtIFBPU1RHUkVTX1VTRVJOQU1FPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdSQUlMU19NQVhfVEhSRUFEUz0ke1JBSUxTX01BWF9USFJFQURTOi01fScKICAgICAgLSAnTk9ERV9FTlY9JHtOT0RFX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ1JBSUxTX0VOVj0ke1JBSUxTX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ0lOU1RBTExBVElPTl9FTlY9JHtJTlNUQUxMQVRJT05fRU5WOi1kb2NrZXJ9JwogICAgICAtICdNQUlMRVJfU0VOREVSX0VNQUlMPSR7Q0hBVFdPT1RfTUFJTEVSX1NFTkRFUl9FTUFJTH0nCiAgICAgIC0gJ1NNVFBfQUREUkVTUz0ke0NIQVRXT09UX1NNVFBfQUREUkVTU30nCiAgICAgIC0gJ1NNVFBfQVVUSEVOVElDQVRJT049JHtDSEFUV09PVF9TTVRQX0FVVEhFTlRJQ0FUSU9OfScKICAgICAgLSAnU01UUF9ET01BSU49JHtDSEFUV09PVF9TTVRQX0RPTUFJTn0nCiAgICAgIC0gJ1NNVFBfRU5BQkxFX1NUQVJUVExTX0FVVE89JHtDSEFUV09PVF9TTVRQX0VOQUJMRV9TVEFSVFRMU19BVVRPfScKICAgICAgLSAnU01UUF9QT1JUPSR7Q0hBVFdPT1RfU01UUF9QT1JUfScKICAgICAgLSAnU01UUF9VU0VSTkFNRT0ke0NIQVRXT09UX1NNVFBfVVNFUk5BTUV9JwogICAgICAtICdTTVRQX1BBU1NXT1JEPSR7Q0hBVFdPT1RfU01UUF9QQVNTV09SRH0nCiAgICAgIC0gJ0FDVElWRV9TVE9SQUdFX1NFUlZJQ0U9JHtBQ1RJVkVfU1RPUkFHRV9TRVJWSUNFOi1sb2NhbH0nCiAgICBlbnRyeXBvaW50OiBkb2NrZXIvZW50cnlwb2ludHMvcmFpbHMuc2gKICAgIGNvbW1hbmQ6ICdzaCAtYyAiYnVuZGxlIGV4ZWMgcmFpbHMgZGI6Y2hhdHdvb3RfcHJlcGFyZSAmJiBidW5kbGUgZXhlYyByYWlscyBzIC1wIDMwMDAgLWIgMC4wLjAuMCInCiAgICB2b2x1bWVzOgogICAgICAtICdyYWlscy1kYXRhOi9hcHAvc3RvcmFnZScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLS1zcGlkZXInCiAgICAgICAgLSAnLXEnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMDAwJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgc2lkZWtpcToKICAgIGltYWdlOiAnY2hhdHdvb3QvY2hhdHdvb3Q6bGF0ZXN0JwogICAgZGVwZW5kc19vbjoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtIHJlZGlzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRUNSRVRfS0VZX0JBU0U9JFNFUlZJQ0VfUEFTU1dPUkRfQ0hBVFdPT1QKICAgICAgLSAnRlJPTlRFTkRfVVJMPSR7U0VSVklDRV9GUUROX0NIQVRXT09UfScKICAgICAgLSAnREVGQVVMVF9MT0NBTEU9JHtDSEFUV09PVF9ERUZBVUxUX0xPQ0FMRX0nCiAgICAgIC0gJ0ZPUkNFX1NTTD0ke0ZPUkNFX1NTTDotZmFsc2V9JwogICAgICAtICdFTkFCTEVfQUNDT1VOVF9TSUdOVVA9JHtFTkFCTEVfQUNDT1VOVF9TSUdOVVA6LWZhbHNlfScKICAgICAgLSAnUkVESVNfVVJMPXJlZGlzOi8vZGVmYXVsdEByZWRpczo2Mzc5JwogICAgICAtIFJFRElTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1JFRElTCiAgICAgIC0gJ1JFRElTX09QRU5TU0xfVkVSSUZZX01PREU9JHtSRURJU19PUEVOU1NMX1ZFUklGWV9NT0RFOi1ub25lfScKICAgICAgLSAnUE9TVEdSRVNfREFUQUJBU0U9JHtQT1NUR1JFU19EQjotY2hhdHdvb3R9JwogICAgICAtICdQT1NUR1JFU19IT1NUPSR7UE9TVEdSRVNfSE9TVDotcG9zdGdyZXN9JwogICAgICAtIFBPU1RHUkVTX1VTRVJOQU1FPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdSQUlMU19NQVhfVEhSRUFEUz0ke1JBSUxTX01BWF9USFJFQURTOi01fScKICAgICAgLSAnTk9ERV9FTlY9JHtOT0RFX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ1JBSUxTX0VOVj0ke1JBSUxTX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ0lOU1RBTExBVElPTl9FTlY9JHtJTlNUQUxMQVRJT05fRU5WOi1kb2NrZXJ9JwogICAgICAtICdNQUlMRVJfU0VOREVSX0VNQUlMPSR7Q0hBVFdPT1RfTUFJTEVSX1NFTkRFUl9FTUFJTH0nCiAgICAgIC0gJ1NNVFBfQUREUkVTUz0ke0NIQVRXT09UX1NNVFBfQUREUkVTU30nCiAgICAgIC0gJ1NNVFBfQVVUSEVOVElDQVRJT049JHtDSEFUV09PVF9TTVRQX0FVVEhFTlRJQ0FUSU9OfScKICAgICAgLSAnU01UUF9ET01BSU49JHtDSEFUV09PVF9TTVRQX0RPTUFJTn0nCiAgICAgIC0gJ1NNVFBfRU5BQkxFX1NUQVJUVExTX0FVVE89JHtDSEFUV09PVF9TTVRQX0VOQUJMRV9TVEFSVFRMU19BVVRPfScKICAgICAgLSAnU01UUF9QT1JUPSR7Q0hBVFdPT1RfU01UUF9QT1JUfScKICAgICAgLSAnU01UUF9VU0VSTkFNRT0ke0NIQVRXT09UX1NNVFBfVVNFUk5BTUV9JwogICAgICAtICdTTVRQX1BBU1NXT1JEPSR7Q0hBVFdPT1RfU01UUF9QQVNTV09SRH0nCiAgICAgIC0gJ0FDVElWRV9TVE9SQUdFX1NFUlZJQ0U9JHtBQ1RJVkVfU1RPUkFHRV9TRVJWSUNFOi1sb2NhbH0nCiAgICBjb21tYW5kOgogICAgICAtIGJ1bmRsZQogICAgICAtIGV4ZWMKICAgICAgLSBzaWRla2lxCiAgICAgIC0gJy1DJwogICAgICAtIGNvbmZpZy9zaWRla2lxLnltbAogICAgdm9sdW1lczoKICAgICAgLSAnc2lkZWtpcS1kYXRhOi9hcHAvc3RvcmFnZScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAiYnVuZGxlIGV4ZWMgcmFpbHMgcnVubmVyICdwdXRzIFNpZGVraXEucmVkaXMoJjppbmZvKScgPiAvZGV2L251bGwgMj4mMSIKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxMicKICAgIHJlc3RhcnQ6IGFsd2F5cwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotY2hhdHdvb3R9JwogICAgICAtIFBPU1RHUkVTX1VTRVI9JFNFUlZJQ0VfVVNFUl9QT1NUR1JFUwogICAgICAtIFBPU1RHUkVTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJFNFUlZJQ0VfVVNFUl9QT1NUR1JFUyAtZCBjaGF0d29vdCAtaCAxMjcuMC4wLjEnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDUKICByZWRpczoKICAgIGltYWdlOiAncmVkaXM6YWxwaW5lJwogICAgcmVzdGFydDogYWx3YXlzCiAgICBjb21tYW5kOgogICAgICAtIHNoCiAgICAgIC0gJy1jJwogICAgICAtICdyZWRpcy1zZXJ2ZXIgLS1yZXF1aXJlcGFzcyAiJFNFUlZJQ0VfUEFTU1dPUkRfUkVESVMiJwogICAgdm9sdW1lczoKICAgICAgLSAncmVkaXMtZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSByZWRpcy1jbGkKICAgICAgICAtICctYScKICAgICAgICAtICRTRVJWSUNFX1BBU1NXT1JEX1JFRElTCiAgICAgICAgLSBQSU5HCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDUK", + "compose": "c2VydmljZXM6CiAgY2hhdHdvb3Q6CiAgICBpbWFnZTogJ2NoYXR3b290L2NoYXR3b290OmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIC0gcG9zdGdyZXMKICAgICAgLSByZWRpcwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0NIQVRXT09UXzMwMDAKICAgICAgLSBTRUNSRVRfS0VZX0JBU0U9JFNFUlZJQ0VfUEFTU1dPUkRfQ0hBVFdPT1QKICAgICAgLSAnRlJPTlRFTkRfVVJMPSR7U0VSVklDRV9GUUROX0NIQVRXT09UfScKICAgICAgLSAnREVGQVVMVF9MT0NBTEU9JHtDSEFUV09PVF9ERUZBVUxUX0xPQ0FMRX0nCiAgICAgIC0gJ0ZPUkNFX1NTTD0ke0ZPUkNFX1NTTDotZmFsc2V9JwogICAgICAtICdFTkFCTEVfQUNDT1VOVF9TSUdOVVA9JHtFTkFCTEVfQUNDT1VOVF9TSUdOVVA6LWZhbHNlfScKICAgICAgLSAnUkVESVNfVVJMPXJlZGlzOi8vZGVmYXVsdEByZWRpczo2Mzc5JwogICAgICAtIFJFRElTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1JFRElTCiAgICAgIC0gJ1JFRElTX09QRU5TU0xfVkVSSUZZX01PREU9JHtSRURJU19PUEVOU1NMX1ZFUklGWV9NT0RFOi1ub25lfScKICAgICAgLSAnUE9TVEdSRVNfREFUQUJBU0U9JHtQT1NUR1JFU19EQjotY2hhdHdvb3R9JwogICAgICAtICdQT1NUR1JFU19IT1NUPSR7UE9TVEdSRVNfSE9TVDotcG9zdGdyZXN9JwogICAgICAtIFBPU1RHUkVTX1VTRVJOQU1FPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdSQUlMU19NQVhfVEhSRUFEUz0ke1JBSUxTX01BWF9USFJFQURTOi01fScKICAgICAgLSAnTk9ERV9FTlY9JHtOT0RFX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ1JBSUxTX0VOVj0ke1JBSUxTX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ0lOU1RBTExBVElPTl9FTlY9JHtJTlNUQUxMQVRJT05fRU5WOi1kb2NrZXJ9JwogICAgICAtICdNQUlMRVJfU0VOREVSX0VNQUlMPSR7Q0hBVFdPT1RfTUFJTEVSX1NFTkRFUl9FTUFJTH0nCiAgICAgIC0gJ1NNVFBfQUREUkVTUz0ke0NIQVRXT09UX1NNVFBfQUREUkVTU30nCiAgICAgIC0gJ1NNVFBfQVVUSEVOVElDQVRJT049JHtDSEFUV09PVF9TTVRQX0FVVEhFTlRJQ0FUSU9OfScKICAgICAgLSAnU01UUF9ET01BSU49JHtDSEFUV09PVF9TTVRQX0RPTUFJTn0nCiAgICAgIC0gJ1NNVFBfRU5BQkxFX1NUQVJUVExTX0FVVE89JHtDSEFUV09PVF9TTVRQX0VOQUJMRV9TVEFSVFRMU19BVVRPfScKICAgICAgLSAnU01UUF9QT1JUPSR7Q0hBVFdPT1RfU01UUF9QT1JUfScKICAgICAgLSAnU01UUF9VU0VSTkFNRT0ke0NIQVRXT09UX1NNVFBfVVNFUk5BTUV9JwogICAgICAtICdTTVRQX1BBU1NXT1JEPSR7Q0hBVFdPT1RfU01UUF9QQVNTV09SRH0nCiAgICAgIC0gJ0FDVElWRV9TVE9SQUdFX1NFUlZJQ0U9JHtBQ1RJVkVfU1RPUkFHRV9TRVJWSUNFOi1sb2NhbH0nCiAgICBlbnRyeXBvaW50OiBkb2NrZXIvZW50cnlwb2ludHMvcmFpbHMuc2gKICAgIGNvbW1hbmQ6ICdzaCAtYyAiYnVuZGxlIGV4ZWMgcmFpbHMgZGI6Y2hhdHdvb3RfcHJlcGFyZSAmJiBidW5kbGUgZXhlYyByYWlscyBzIC1wIDMwMDAgLWIgMC4wLjAuMCInCiAgICB2b2x1bWVzOgogICAgICAtICdyYWlscy1kYXRhOi9hcHAvc3RvcmFnZScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLS1zcGlkZXInCiAgICAgICAgLSAnLXEnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMDAwJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgc2lkZWtpcToKICAgIGltYWdlOiAnY2hhdHdvb3QvY2hhdHdvb3Q6bGF0ZXN0JwogICAgZGVwZW5kc19vbjoKICAgICAgLSBwb3N0Z3JlcwogICAgICAtIHJlZGlzCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRUNSRVRfS0VZX0JBU0U9JFNFUlZJQ0VfUEFTU1dPUkRfQ0hBVFdPT1QKICAgICAgLSAnRlJPTlRFTkRfVVJMPSR7U0VSVklDRV9GUUROX0NIQVRXT09UfScKICAgICAgLSAnREVGQVVMVF9MT0NBTEU9JHtDSEFUV09PVF9ERUZBVUxUX0xPQ0FMRX0nCiAgICAgIC0gJ0ZPUkNFX1NTTD0ke0ZPUkNFX1NTTDotZmFsc2V9JwogICAgICAtICdFTkFCTEVfQUNDT1VOVF9TSUdOVVA9JHtFTkFCTEVfQUNDT1VOVF9TSUdOVVA6LWZhbHNlfScKICAgICAgLSAnUkVESVNfVVJMPXJlZGlzOi8vZGVmYXVsdEByZWRpczo2Mzc5JwogICAgICAtIFJFRElTX1BBU1NXT1JEPSRTRVJWSUNFX1BBU1NXT1JEX1JFRElTCiAgICAgIC0gJ1JFRElTX09QRU5TU0xfVkVSSUZZX01PREU9JHtSRURJU19PUEVOU1NMX1ZFUklGWV9NT0RFOi1ub25lfScKICAgICAgLSAnUE9TVEdSRVNfREFUQUJBU0U9JHtQT1NUR1JFU19EQjotY2hhdHdvb3R9JwogICAgICAtICdQT1NUR1JFU19IT1NUPSR7UE9TVEdSRVNfSE9TVDotcG9zdGdyZXN9JwogICAgICAtIFBPU1RHUkVTX1VTRVJOQU1FPSRTRVJWSUNFX1VTRVJfUE9TVEdSRVMKICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0kU0VSVklDRV9QQVNTV09SRF9QT1NUR1JFUwogICAgICAtICdSQUlMU19NQVhfVEhSRUFEUz0ke1JBSUxTX01BWF9USFJFQURTOi01fScKICAgICAgLSAnTk9ERV9FTlY9JHtOT0RFX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ1JBSUxTX0VOVj0ke1JBSUxTX0VOVjotcHJvZHVjdGlvbn0nCiAgICAgIC0gJ0lOU1RBTExBVElPTl9FTlY9JHtJTlNUQUxMQVRJT05fRU5WOi1kb2NrZXJ9JwogICAgICAtICdNQUlMRVJfU0VOREVSX0VNQUlMPSR7Q0hBVFdPT1RfTUFJTEVSX1NFTkRFUl9FTUFJTH0nCiAgICAgIC0gJ1NNVFBfQUREUkVTUz0ke0NIQVRXT09UX1NNVFBfQUREUkVTU30nCiAgICAgIC0gJ1NNVFBfQVVUSEVOVElDQVRJT049JHtDSEFUV09PVF9TTVRQX0FVVEhFTlRJQ0FUSU9OfScKICAgICAgLSAnU01UUF9ET01BSU49JHtDSEFUV09PVF9TTVRQX0RPTUFJTn0nCiAgICAgIC0gJ1NNVFBfRU5BQkxFX1NUQVJUVExTX0FVVE89JHtDSEFUV09PVF9TTVRQX0VOQUJMRV9TVEFSVFRMU19BVVRPfScKICAgICAgLSAnU01UUF9QT1JUPSR7Q0hBVFdPT1RfU01UUF9QT1JUfScKICAgICAgLSAnU01UUF9VU0VSTkFNRT0ke0NIQVRXT09UX1NNVFBfVVNFUk5BTUV9JwogICAgICAtICdTTVRQX1BBU1NXT1JEPSR7Q0hBVFdPT1RfU01UUF9QQVNTV09SRH0nCiAgICAgIC0gJ0FDVElWRV9TVE9SQUdFX1NFUlZJQ0U9JHtBQ1RJVkVfU1RPUkFHRV9TRVJWSUNFOi1sb2NhbH0nCiAgICBjb21tYW5kOgogICAgICAtIGJ1bmRsZQogICAgICAtIGV4ZWMKICAgICAgLSBzaWRla2lxCiAgICAgIC0gJy1DJwogICAgICAtIGNvbmZpZy9zaWRla2lxLnltbAogICAgdm9sdW1lczoKICAgICAgLSAnc2lkZWtpcS1kYXRhOi9hcHAvc3RvcmFnZScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAiYnVuZGxlIGV4ZWMgcmFpbHMgcnVubmVyICdwdXRzIFNpZGVraXEucmVkaXMoJjppbmZvKScgPiAvZGV2L251bGwgMj4mMSIKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwZ3ZlY3Rvci9wZ3ZlY3RvcjpwZzEyJwogICAgcmVzdGFydDogYWx3YXlzCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlcy1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1jaGF0d29vdH0nCiAgICAgIC0gUE9TVEdSRVNfVVNFUj0kU0VSVklDRV9VU0VSX1BPU1RHUkVTCiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JFNFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVMKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAkU0VSVklDRV9VU0VSX1BPU1RHUkVTIC1kIGNoYXR3b290IC1oIDEyNy4wLjAuMScKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogNQogIHJlZGlzOgogICAgaW1hZ2U6ICdyZWRpczphbHBpbmUnCiAgICByZXN0YXJ0OiBhbHdheXMKICAgIGNvbW1hbmQ6CiAgICAgIC0gc2gKICAgICAgLSAnLWMnCiAgICAgIC0gJ3JlZGlzLXNlcnZlciAtLXJlcXVpcmVwYXNzICIkU0VSVklDRV9QQVNTV09SRF9SRURJUyInCiAgICB2b2x1bWVzOgogICAgICAtICdyZWRpcy1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHJlZGlzLWNsaQogICAgICAgIC0gJy1hJwogICAgICAgIC0gJFNFUlZJQ0VfUEFTU1dPUkRfUkVESVMKICAgICAgICAtIFBJTkcKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogNQo=", "tags": [ "chatwoot", "chat", From f35f45324b6bf40e19e6e368ff79e8b2cc3cae05 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 13:56:53 +0100 Subject: [PATCH 07/12] fix: server proxy set correctly through the API fix: cannto delete localhost through the API. --- app/Http/Controllers/Api/ServersController.php | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/app/Http/Controllers/Api/ServersController.php b/app/Http/Controllers/Api/ServersController.php index b1deb5321..a9a0a2e53 100644 --- a/app/Http/Controllers/Api/ServersController.php +++ b/app/Http/Controllers/Api/ServersController.php @@ -530,11 +530,11 @@ class ServersController extends Controller 'user' => $request->user, 'private_key_id' => $privateKey->id, 'team_id' => $teamId, - 'proxy' => [ - 'type' => $proxyType, - 'status' => ProxyStatus::EXITED->value, - ], ]); + $server->proxy->set('type', $proxyType); + $server->proxy->set('status', ProxyStatus::EXITED->value); + $server->save(); + $server->settings()->update([ 'is_build_server' => $request->is_build_server, ]); @@ -742,6 +742,9 @@ class ServersController extends Controller if ($server->definedResources()->count() > 0) { return response()->json(['message' => 'Server has resources, so you need to delete them before.'], 400); } + if ($server->isLocalhost()) { + return response()->json(['message' => 'Local server cannot be deleted.'], 400); + } $server->delete(); DeleteServer::dispatch($server); From 57f61d45895e57da75457cf438233f45ad01b3b8 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 13:57:12 +0100 Subject: [PATCH 08/12] fix: docker image parser --- app/Livewire/Project/New/DockerImage.php | 15 ++- app/Services/DockerImageParser.php | 74 +++++++++++++++ tests/Unit/Services/DockerImageParserTest.php | 94 +++++++++++++++++++ 3 files changed, 175 insertions(+), 8 deletions(-) create mode 100644 app/Services/DockerImageParser.php create mode 100644 tests/Unit/Services/DockerImageParserTest.php diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index 942924437..7d68ce068 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -6,6 +6,7 @@ use App\Models\Application; use App\Models\Project; use App\Models\StandaloneDocker; use App\Models\SwarmDocker; +use App\Services\DockerImageParser; use Livewire\Component; use Visus\Cuid2\Cuid2; @@ -28,12 +29,10 @@ class DockerImage extends Component $this->validate([ 'dockerImage' => 'required', ]); - $image = str($this->dockerImage)->before(':'); - if (str($this->dockerImage)->contains(':')) { - $tag = str($this->dockerImage)->after(':'); - } else { - $tag = 'latest'; - } + + $parser = new DockerImageParser; + $parser->parse($this->dockerImage); + $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); if (! $destination) { @@ -53,8 +52,8 @@ class DockerImage extends Component 'git_branch' => 'main', 'build_pack' => 'dockerimage', 'ports_exposes' => 80, - 'docker_registry_image_name' => $image, - 'docker_registry_image_tag' => $tag, + 'docker_registry_image_name' => $parser->getFullImageNameWithoutTag(), + 'docker_registry_image_tag' => $parser->getTag(), 'environment_id' => $environment->id, 'destination_id' => $destination->id, 'destination_type' => $destination_class, diff --git a/app/Services/DockerImageParser.php b/app/Services/DockerImageParser.php new file mode 100644 index 000000000..4987f953d --- /dev/null +++ b/app/Services/DockerImageParser.php @@ -0,0 +1,74 @@ + strrpos($imageString, '/'))) { + $mainPart = substr($imageString, 0, $lastColon); + $this->tag = substr($imageString, $lastColon + 1); + } else { + $mainPart = $imageString; + $this->tag = 'latest'; + } + + // Split the main part by / to handle registry and image name + $pathParts = explode('/', $mainPart); + + // If we have more than one part and the first part contains a dot or colon + // it's likely a registry URL + if (count($pathParts) > 1 && (str_contains($pathParts[0], '.') || str_contains($pathParts[0], ':'))) { + $this->registryUrl = array_shift($pathParts); + $this->imageName = implode('/', $pathParts); + } else { + $this->imageName = $mainPart; + } + + return $this; + } + + public function getFullImageNameWithoutTag(): string + { + return $this->registryUrl.'/'.$this->imageName; + } + + public function getRegistryUrl(): string + { + return $this->registryUrl; + } + + public function getImageName(): string + { + return $this->imageName; + } + + public function getTag(): string + { + return $this->tag; + } + + public function toString(): string + { + $parts = []; + if ($this->registryUrl) { + $parts[] = $this->registryUrl; + } + $parts[] = $this->imageName; + + return implode('/', $parts).':'.$this->tag; + } +} diff --git a/tests/Unit/Services/DockerImageParserTest.php b/tests/Unit/Services/DockerImageParserTest.php new file mode 100644 index 000000000..876d68ef0 --- /dev/null +++ b/tests/Unit/Services/DockerImageParserTest.php @@ -0,0 +1,94 @@ +parser = new DockerImageParser; + } + + #[Test] + public function it_parses_simple_image_name() + { + $this->parser->parse('nginx'); + + $this->assertEquals('', $this->parser->getRegistryUrl()); + $this->assertEquals('nginx', $this->parser->getImageName()); + $this->assertEquals('latest', $this->parser->getTag()); + } + + #[Test] + public function it_parses_image_with_tag() + { + $this->parser->parse('nginx:1.19'); + + $this->assertEquals('', $this->parser->getRegistryUrl()); + $this->assertEquals('nginx', $this->parser->getImageName()); + $this->assertEquals('1.19', $this->parser->getTag()); + } + + #[Test] + public function it_parses_image_with_organization() + { + $this->parser->parse('coollabs/coolify:latest'); + + $this->assertEquals('', $this->parser->getRegistryUrl()); + $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); + $this->assertEquals('latest', $this->parser->getTag()); + } + + #[Test] + public function it_parses_image_with_registry_url() + { + $this->parser->parse('ghcr.io/coollabs/coolify:v4'); + + $this->assertEquals('ghcr.io', $this->parser->getRegistryUrl()); + $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); + $this->assertEquals('v4', $this->parser->getTag()); + } + + #[Test] + public function it_parses_image_with_port_in_registry() + { + $this->parser->parse('localhost:5000/my-app:dev'); + + $this->assertEquals('localhost:5000', $this->parser->getRegistryUrl()); + $this->assertEquals('my-app', $this->parser->getImageName()); + $this->assertEquals('dev', $this->parser->getTag()); + } + + #[Test] + public function it_parses_image_without_tag() + { + $this->parser->parse('ghcr.io/coollabs/coolify'); + + $this->assertEquals('ghcr.io', $this->parser->getRegistryUrl()); + $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); + $this->assertEquals('latest', $this->parser->getTag()); + } + + #[Test] + public function it_converts_back_to_string() + { + $originalString = 'ghcr.io/coollabs/coolify:v4'; + $this->parser->parse($originalString); + + $this->assertEquals($originalString, $this->parser->toString()); + } + + #[Test] + public function it_converts_to_string_with_default_tag() + { + $this->parser->parse('nginx'); + $this->assertEquals('nginx:latest', $this->parser->toString()); + } +} From c891102db664eb3d8fc83eb081f8282f010aed0f Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 13:57:40 +0100 Subject: [PATCH 09/12] fix: add public key attribute to privatekey model --- app/Models/PrivateKey.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php index 80015d87f..0e702e460 100644 --- a/app/Models/PrivateKey.php +++ b/app/Models/PrivateKey.php @@ -40,6 +40,8 @@ class PrivateKey extends BaseModel 'private_key' => 'encrypted', ]; + protected $appends = ['public_key']; + protected static function booted() { static::saving(function ($key) { @@ -64,6 +66,11 @@ class PrivateKey extends BaseModel }); } + public function getPublicKeyAttribute() + { + return self::extractPublicKeyFromPrivate($this->private_key) ?? 'Error loading private key'; + } + public function getPublicKey() { return self::extractPublicKeyFromPrivate($this->private_key) ?? 'Error loading private key'; @@ -208,15 +215,14 @@ class PrivateKey extends BaseModel { try { $key = PublicKeyLoader::load($privateKey); - $publicKey = $key->getPublicKey(); - return $publicKey->getFingerprint('sha256'); + return $key->getPublicKey()->getFingerprint('sha256'); } catch (\Throwable $e) { return null; } } - private static function fingerprintExists($fingerprint, $excludeId = null) + public static function fingerprintExists($fingerprint, $excludeId = null) { $query = self::query() ->where('fingerprint', $fingerprint) From 3bc85b1a8c97e49456d3f49db41f1974f96090e5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 13:58:11 +0100 Subject: [PATCH 10/12] fix: validate private key through API feat: able to add base64 encoded private key, not just oneline --- .../Controllers/Api/SecurityController.php | 25 +++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/app/Http/Controllers/Api/SecurityController.php b/app/Http/Controllers/Api/SecurityController.php index a14b0da20..fdd46b100 100644 --- a/app/Http/Controllers/Api/SecurityController.php +++ b/app/Http/Controllers/Api/SecurityController.php @@ -195,6 +195,31 @@ class SecurityController extends Controller if (! $request->description) { $request->offsetSet('description', 'Created by Coolify via API'); } + + $isPrivateKeyString = str_starts_with($request->private_key, '-----BEGIN'); + if (! $isPrivateKeyString) { + try { + $base64PrivateKey = base64_decode($request->private_key); + $request->offsetSet('private_key', $base64PrivateKey); + } catch (\Exception $e) { + return response()->json([ + 'message' => 'Invalid private key.', + ], 422); + } + } + $isPrivateKeyValid = PrivateKey::validatePrivateKey($request->private_key); + if (! $isPrivateKeyValid) { + return response()->json([ + 'message' => 'Invalid private key.', + ], 422); + } + $fingerPrint = PrivateKey::generateFingerprint($request->private_key); + $isFingerPrintExists = PrivateKey::fingerprintExists($fingerPrint); + if ($isFingerPrintExists) { + return response()->json([ + 'message' => 'Private key already exists.', + ], 422); + } $key = PrivateKey::create([ 'team_id' => $teamId, 'name' => $request->name, From 8350c3e039c74d59e9af33ee5339dfc74474cd7d Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 13:58:52 +0100 Subject: [PATCH 11/12] fix: correct service update logic in Docker Compose parser --- bootstrap/helpers/shared.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/bootstrap/helpers/shared.php b/bootstrap/helpers/shared.php index 5d34c63b6..ff2933f72 100644 --- a/bootstrap/helpers/shared.php +++ b/bootstrap/helpers/shared.php @@ -2005,7 +2005,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal projectName: $resource->project()->name, resourceName: $resource->name, type: 'service', - subType: $isDatabase ? 'database' : 'application', + subType: $isDatabase ? 'database' : 'application', subId: $savedService->id, subName: $savedService->name, environment: $resource->environment->name, @@ -2872,7 +2872,7 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal data_forget($service, 'volumes.*.is_directory'); data_forget($service, 'exclude_from_hc'); data_set($service, 'environment', $serviceVariables->toArray()); - updateCompose($savedService); + updateCompose($service); return $service; }); From 3957bb31ce0d556a5d1f04c5b1b6ce2dafc40b2c Mon Sep 17 00:00:00 2001 From: Andras Bacsai Date: Mon, 20 Jan 2025 14:01:14 +0100 Subject: [PATCH 12/12] fix: update CDN URL in install script to point to nightly version --- other/nightly/install.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/other/nightly/install.sh b/other/nightly/install.sh index 1889ad355..31d0a1759 100755 --- a/other/nightly/install.sh +++ b/other/nightly/install.sh @@ -5,7 +5,7 @@ set -e # Exit immediately if a command exits with a non-zero status ## $1 could be empty, so we need to disable this check #set -u # Treat unset variables as an error and exit set -o pipefail # Cause a pipeline to return the status of the last command that exited with a non-zero status -CDN="https://cdn.coollabs.io/coolify" +CDN="https://cdn.coollabs.io/coolify-nightly" DATE=$(date +"%Y%m%d-%H%M%S") VERSION="1.7"