From 80664bbf4a065e925faa2bac984e2826b0f5fe24 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Thu, 28 Aug 2025 01:10:43 +0530 Subject: [PATCH 001/322] add elasticsearch-with-kibana.yaml --- .../compose/elasticsearch-with-kibana.yaml | 95 +++++++++++++++++++ 1 file changed, 95 insertions(+) create mode 100644 templates/compose/elasticsearch-with-kibana.yaml diff --git a/templates/compose/elasticsearch-with-kibana.yaml b/templates/compose/elasticsearch-with-kibana.yaml new file mode 100644 index 000000000..b04594690 --- /dev/null +++ b/templates/compose/elasticsearch-with-kibana.yaml @@ -0,0 +1,95 @@ +# documentation: https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker +# slogan: Elastic + Kibana is a Free and Open Source Search, Monitoring, and Visualization Stack +# tags: elastic,kibana,elasticsearch,search,visualization,logging,monitoring,observability,analytics,stack,devops +# logo: svgs/elasticsearch.svg +# port: 5601 + +services: + elasticsearch: + image: 'elastic/elasticsearch:9.1.2' + container_name: elasticsearch + restart: unless-stopped + environment: + - ELASTIC_USER=elastic # Default built-in superuser (can't be changed); included here to avoid confusion about the username + - 'ELASTIC_PASSWORD=${SERVICE_PASSWORD_ELASTICSEARCH}' + - 'ES_JAVA_OPTS=-Xms512m -Xmx512m' # Limit JVM heap size to 512MB to prevent Elasticsearch from consuming all system memory + - discovery.type=single-node # Disable clustering; run as a standalone node (sufficient for most local or single-host setups) + - bootstrap.memory_lock=true # Prevent memory swapping by locking JVM memory (helps with performance/stability) + - xpack.security.http.ssl.enabled=false # SSL is unnecessary for HTTP traffic within the isolated Docker network + volumes: + - '/etc/localtime:/etc/localtime:ro' # Sync container timezone with host + - 'elasticsearch-data:/usr/share/elasticsearch/data' + healthcheck: + test: + - CMD-SHELL + - 'curl --user elastic:${SERVICE_PASSWORD_ELASTICSEARCH} --silent --fail http://localhost:9200/_cluster/health' + interval: 10s + timeout: 10s + retries: 24 + kibana: + image: 'kibana:9.1.2' + container_name: kibana + restart: unless-stopped + environment: + - SERVICE_URL_KIBANA_5601 + - 'KIBANA_PASSWORD=${SERVICE_PASSWORD_KIBANA}' + - 'ELASTICSEARCH_SERVICEACCOUNTTOKEN=${ELASTICSEARCH_SERVICEACCOUNTTOKEN}' # Kibana authenticates to Elasticsearch using this service token + - 'SERVER_NAME=${SERVICE_FQDN_KIBANA}' # For generating links and setting cookie domains + - 'SERVER_PUBLICBASEURL=${SERVICE_URL_KIBANA}' # Public URL used in generated links (reporting, alerting, etc.) + - 'ELASTICSEARCH_HOSTS=http://elasticsearch:9200' # Connect Kibana to Elasticsearch Service + - XPACK.SECURITY.ENABLED=true # Enable authentication and authorization (required for service tokens, roles, etc.) + - 'XPACK_SECURITY_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKSECURITY}' # Required for encrypted session & auth tokens + - 'XPACK_REPORTING_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKREPORTING}' # Required for reporting (PDFs, PNGs) + - 'XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKENCRYPTEDSAVEDOBJECTS}' # Required for encrypting saved objects like alerts + - 'TELEMETRY_OPTIN=${TELEMETRY_OPTIN:-false}' # Disable telemetry by default (opt-in only) + volumes: + - '/etc/localtime:/etc/localtime:ro' # Sync container timezone with host + - 'kibana-data:/usr/share/kibana/data' + depends_on: + elasticsearch: + condition: service_healthy + healthcheck: + test: + - CMD-SHELL + - "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'" # Expect HTTP 302 (redirect) from Kibana login page + interval: 10s + timeout: 10s + retries: 120 + kibana-token-generator: + image: 'alpine:latest' + container_name: kibana-token-generator + depends_on: + elasticsearch: + condition: service_healthy + exclude_from_hc: true + environment: + - 'ELASTIC_PASSWORD=${SERVICE_PASSWORD_ELASTICSEARCH}' # Needed to authenticate the ELASTICSEARCH_SERVICEACCOUNTTOKEN creation request + entrypoint: + - sh + - '-c' + - | + apk add --no-cache curl jq >/dev/null 2>&1 + echo "Generating Kibana service token..." + + RESPONSE=$(curl -s -w "\n%{http_code}" -u elastic:"$${ELASTIC_PASSWORD}" -X POST "http://elasticsearch:9200/_security/service/elastic/kibana/credential/token/kibana-service-token") + HTTP_CODE=$$(echo "$${RESPONSE}" | tail -n1) + BODY=$$(echo "$${RESPONSE}" | head -n -1) + + if [ "$${HTTP_CODE}" = "200" ]; then + CREATED=$$(echo "$${BODY}" | jq -r '.created') + if [ "$${CREATED}" = "true" ]; then + TOKEN_VALUE=$$(echo "$${BODY}" | jq -r '.token.value') + echo "Token created successfully:" + echo "$${TOKEN_VALUE}" + else + echo "Unexpected response, token not created:" + echo "$${BODY}" + fi + elif [ "$${HTTP_CODE}" = "409" ]; then + echo "Token already exists. Skipping token creation." + else + echo "Failed to create token. HTTP code: $${HTTP_CODE}" + echo "$${BODY}" + exit 1 + fi + restart: 'no' # Run once to generate token, then exit From 3c126927d5dbcd757493afd12081fb08c61017f5 Mon Sep 17 00:00:00 2001 From: saurabhraghuvanshii Date: Thu, 28 Aug 2025 02:10:14 +0530 Subject: [PATCH 002/322] enhancement: allow deploy from container image hash --- app/Jobs/ApplicationDeploymentJob.php | 15 +- app/Livewire/Project/New/DockerImage.php | 4 + app/Services/DockerImageParser.php | 41 ++++++ .../project/application/general.blade.php | 6 +- .../project/new/docker-image.blade.php | 9 +- tests/Unit/DockerImageParserTest.php | 129 ++++++++++-------- 6 files changed, 145 insertions(+), 59 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 9037fa3e5..5a00a2dd6 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -410,7 +410,12 @@ private function deploy_dockerimage_buildpack() } else { $this->dockerImageTag = $this->application->docker_registry_image_tag; } - $this->application_deployment_queue->addLogEntry("Starting deployment of {$this->dockerImage}:{$this->dockerImageTag} to {$this->server->name}."); + + // Check if this is an image hash deployment + $isImageHash = str($this->dockerImageTag)->startsWith('sha256-'); + $displayName = $isImageHash ? "{$this->dockerImage}@sha256:".str($this->dockerImageTag)->after('sha256-') : "{$this->dockerImage}:{$this->dockerImageTag}"; + + $this->application_deployment_queue->addLogEntry("Starting deployment of {$displayName} to {$this->server->name}."); $this->generate_image_names(); $this->prepare_builder_image(); $this->generate_compose_file(); @@ -801,7 +806,13 @@ private function generate_image_names() $this->production_image_name = "{$this->application->uuid}:latest"; } } elseif ($this->application->build_pack === 'dockerimage') { - $this->production_image_name = "{$this->dockerImage}:{$this->dockerImageTag}"; + // Check if this is an image hash deployment + if (str($this->dockerImageTag)->startsWith('sha256-')) { + $hash = str($this->dockerImageTag)->after('sha256-'); + $this->production_image_name = "{$this->dockerImage}@sha256:{$hash}"; + } else { + $this->production_image_name = "{$this->dockerImage}:{$this->dockerImageTag}"; + } } elseif ($this->pull_request_id !== 0) { if ($this->application->docker_registry_image_name) { $this->build_image_name = "{$this->application->docker_registry_image_name}:pr-{$this->pull_request_id}-build"; diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index 7d68ce068..d78c61904 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -45,6 +45,10 @@ public function submit() $project = Project::where('uuid', $this->parameters['project_uuid'])->first(); $environment = $project->load(['environments'])->environments->where('uuid', $this->parameters['environment_uuid'])->first(); + + // Determine the image tag based on whether it's a hash or regular tag + $imageTag = $parser->isImageHash() ? 'sha256-'.$parser->getTag() : $parser->getTag(); + $application = Application::create([ 'name' => 'docker-image-'.new Cuid2, 'repository_project_id' => 0, diff --git a/app/Services/DockerImageParser.php b/app/Services/DockerImageParser.php index 1fd6625b3..1dd34c713 100644 --- a/app/Services/DockerImageParser.php +++ b/app/Services/DockerImageParser.php @@ -10,6 +10,8 @@ class DockerImageParser private string $tag = 'latest'; + private bool $isImageHash = false; + public function parse(string $imageString): self { // First split by : to handle the tag, but be careful with registry ports @@ -21,9 +23,13 @@ public function parse(string $imageString): self if ($lastColon !== false && (! $hasSlash || $lastColon > strrpos($imageString, '/'))) { $mainPart = substr($imageString, 0, $lastColon); $this->tag = substr($imageString, $lastColon + 1); + + // Check if the tag is a SHA256 hash + $this->isImageHash = $this->isSha256Hash($this->tag); } else { $mainPart = $imageString; $this->tag = 'latest'; + $this->isImageHash = false; } // Split the main part by / to handle registry and image name @@ -41,6 +47,37 @@ public function parse(string $imageString): self return $this; } + /** + * Check if the given string is a SHA256 hash + */ + private function isSha256Hash(string $hash): bool + { + // SHA256 hashes are 64 characters long and contain only hexadecimal characters + return preg_match('/^[a-f0-9]{64}$/i', $hash) === 1; + } + + /** + * Check if the current tag is an image hash + */ + public function isImageHash(): bool + { + return $this->isImageHash; + } + + /** + * Get the full image name with hash if present + */ + public function getFullImageNameWithHash(): string + { + $imageName = $this->getFullImageNameWithoutTag(); + + if ($this->isImageHash) { + return $imageName.'@sha256:'.$this->tag; + } + + return $imageName.':'.$this->tag; + } + public function getFullImageNameWithoutTag(): string { if ($this->registryUrl) { @@ -73,6 +110,10 @@ public function toString(): string } $parts[] = $this->imageName; + if ($this->isImageHash) { + return implode('/', $parts).'@sha256:'.$this->tag; + } + return implode('/', $parts).':'.$this->tag; } } diff --git a/resources/views/livewire/project/application/general.blade.php b/resources/views/livewire/project/application/general.blade.php index b833fc7bb..398e94191 100644 --- a/resources/views/livewire/project/application/general.blade.php +++ b/resources/views/livewire/project/application/general.blade.php @@ -163,12 +163,14 @@ class="underline" href="https://coolify.io/docs/knowledge-base/docker/registry" @if ($application->destination->server->isSwarm()) - @else - @endif @else diff --git a/resources/views/livewire/project/new/docker-image.blade.php b/resources/views/livewire/project/new/docker-image.blade.php index 4cc86710a..af1005a88 100644 --- a/resources/views/livewire/project/new/docker-image.blade.php +++ b/resources/views/livewire/project/new/docker-image.blade.php @@ -6,6 +6,13 @@

Docker Image

Save - +
+ +
diff --git a/tests/Unit/DockerImageParserTest.php b/tests/Unit/DockerImageParserTest.php index 35dffbab4..f41a9b170 100644 --- a/tests/Unit/DockerImageParserTest.php +++ b/tests/Unit/DockerImageParserTest.php @@ -3,92 +3,113 @@ namespace Tests\Unit; use App\Services\DockerImageParser; -use PHPUnit\Framework\Attributes\Test; -use PHPUnit\Framework\TestCase; +use Tests\TestCase; class DockerImageParserTest extends TestCase { - private DockerImageParser $parser; - - protected function setUp(): void + public function test_parses_regular_image_with_tag() { - parent::setUp(); - $this->parser = new DockerImageParser; + $parser = new DockerImageParser; + $parser->parse('nginx:latest'); + + $this->assertEquals('nginx', $parser->getImageName()); + $this->assertEquals('latest', $parser->getTag()); + $this->assertFalse($parser->isImageHash()); + $this->assertEquals('nginx:latest', $parser->toString()); } - #[Test] - public function it_parses_simple_image_name() + public function test_parses_image_with_sha256_hash() { - $this->parser->parse('nginx'); + $parser = new DockerImageParser; + $hash = '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0'; + $parser->parse("ghcr.io/benjaminehowe/rail-disruptions:{$hash}"); - $this->assertEquals('', $this->parser->getRegistryUrl()); - $this->assertEquals('nginx', $this->parser->getImageName()); - $this->assertEquals('latest', $this->parser->getTag()); + $this->assertEquals('ghcr.io/benjaminehowe/rail-disruptions', $parser->getFullImageNameWithoutTag()); + $this->assertEquals($hash, $parser->getTag()); + $this->assertTrue($parser->isImageHash()); + $this->assertEquals("ghcr.io/benjaminehowe/rail-disruptions@sha256:{$hash}", $parser->toString()); + $this->assertEquals("ghcr.io/benjaminehowe/rail-disruptions@sha256:{$hash}", $parser->getFullImageNameWithHash()); } - #[Test] - public function it_parses_image_with_tag() + public function test_parses_registry_image_with_hash() { - $this->parser->parse('nginx:1.19'); + $parser = new DockerImageParser; + $hash = 'abc123def456789abcdef123456789abcdef123456789abcdef123456789abc1'; + $parser->parse("docker.io/library/nginx:{$hash}"); - $this->assertEquals('', $this->parser->getRegistryUrl()); - $this->assertEquals('nginx', $this->parser->getImageName()); - $this->assertEquals('1.19', $this->parser->getTag()); + $this->assertEquals('docker.io/library/nginx', $parser->getFullImageNameWithoutTag()); + $this->assertEquals($hash, $parser->getTag()); + $this->assertTrue($parser->isImageHash()); + $this->assertEquals("docker.io/library/nginx@sha256:{$hash}", $parser->toString()); } - #[Test] - public function it_parses_image_with_organization() + public function test_parses_image_without_tag_defaults_to_latest() { - $this->parser->parse('coollabs/coolify:latest'); + $parser = new DockerImageParser; + $parser->parse('nginx'); - $this->assertEquals('', $this->parser->getRegistryUrl()); - $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); - $this->assertEquals('latest', $this->parser->getTag()); + $this->assertEquals('nginx', $parser->getImageName()); + $this->assertEquals('latest', $parser->getTag()); + $this->assertFalse($parser->isImageHash()); + $this->assertEquals('nginx:latest', $parser->toString()); } - #[Test] - public function it_parses_image_with_registry_url() + public function test_parses_registry_with_port() { - $this->parser->parse('ghcr.io/coollabs/coolify:v4'); + $parser = new DockerImageParser; + $parser->parse('registry.example.com:5000/myapp:latest'); - $this->assertEquals('ghcr.io', $this->parser->getRegistryUrl()); - $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); - $this->assertEquals('v4', $this->parser->getTag()); + $this->assertEquals('registry.example.com:5000/myapp', $parser->getFullImageNameWithoutTag()); + $this->assertEquals('latest', $parser->getTag()); + $this->assertFalse($parser->isImageHash()); } - #[Test] - public function it_parses_image_with_port_in_registry() + public function test_parses_registry_with_port_and_hash() { - $this->parser->parse('localhost:5000/my-app:dev'); + $parser = new DockerImageParser; + $hash = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; + $parser->parse("registry.example.com:5000/myapp:{$hash}"); - $this->assertEquals('localhost:5000', $this->parser->getRegistryUrl()); - $this->assertEquals('my-app', $this->parser->getImageName()); - $this->assertEquals('dev', $this->parser->getTag()); + $this->assertEquals('registry.example.com:5000/myapp', $parser->getFullImageNameWithoutTag()); + $this->assertEquals($hash, $parser->getTag()); + $this->assertTrue($parser->isImageHash()); + $this->assertEquals("registry.example.com:5000/myapp@sha256:{$hash}", $parser->toString()); } - #[Test] - public function it_parses_image_without_tag() + public function test_identifies_valid_sha256_hashes() { - $this->parser->parse('ghcr.io/coollabs/coolify'); + $parser = new DockerImageParser; - $this->assertEquals('ghcr.io', $this->parser->getRegistryUrl()); - $this->assertEquals('coollabs/coolify', $this->parser->getImageName()); - $this->assertEquals('latest', $this->parser->getTag()); + // Valid SHA256 hashes + $validHashes = [ + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0', + '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', + 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', + ]; + + foreach ($validHashes as $hash) { + $parser->parse("image:{$hash}"); + $this->assertTrue($parser->isImageHash(), "Hash {$hash} should be recognized as valid SHA256"); + } } - #[Test] - public function it_converts_back_to_string() + public function test_identifies_invalid_sha256_hashes() { - $originalString = 'ghcr.io/coollabs/coolify:v4'; - $this->parser->parse($originalString); + $parser = new DockerImageParser; - $this->assertEquals($originalString, $this->parser->toString()); - } + // Invalid SHA256 hashes + $invalidHashes = [ + 'latest', + 'v1.2.3', + 'abc123', // too short + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf', // too short + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf00', // too long + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cfg0', // invalid char + ]; - #[Test] - public function it_converts_to_string_with_default_tag() - { - $this->parser->parse('nginx'); - $this->assertEquals('nginx:latest', $this->parser->toString()); + foreach ($invalidHashes as $hash) { + $parser->parse("image:{$hash}"); + $this->assertFalse($parser->isImageHash(), "Hash {$hash} should not be recognized as valid SHA256"); + } } } From 1c3dbfb066743e7d5e9a3ba6bbb5e5653c1d26d5 Mon Sep 17 00:00:00 2001 From: sahil Date: Mon, 1 Sep 2025 14:32:02 +0530 Subject: [PATCH 003/322] Feat: ente config --- public/svgs/ente.png | Bin 0 -> 5096 bytes templates/compose/ente.yaml | 205 ++++++++++++++++++++++++++++++++++++ 2 files changed, 205 insertions(+) create mode 100644 public/svgs/ente.png create mode 100644 templates/compose/ente.yaml diff --git a/public/svgs/ente.png b/public/svgs/ente.png new file mode 100644 index 0000000000000000000000000000000000000000..737149125b4e84d6277bb4853494ae3ac4fe17bd GIT binary patch literal 5096 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 literal 0 HcmV?d00001 diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml new file mode 100644 index 000000000..f754b7387 --- /dev/null +++ b/templates/compose/ente.yaml @@ -0,0 +1,205 @@ +# documentation: https://help.ente.io/ +# slogan: End-to-end encrypted photo backup and sharing platform +# category: media +# tags: photos, backup, encryption, sharing, privacy, media, storage, encryption, minio, postgresql +# logo: svgs/ente.png +# port: 3000, 3001, 3002, 3003, 3004, 8080, 3200 + +services: + museum: + image: ghcr.io/ente-io/server:latest + environment: + - SERVICE_PASSWORD_POSTGRES= ${SERVICE_PASSWORD_POSTGRES} + - SERVICE_URL_MUSEUM_8080=${SERVICE_URL_MUSEUM_8080} + - KEY_ENCRYPTION=${KEY_ENCRYPTION} + - KEY_HASH=${KEY_HASH} + - KEY_JWT=${KEY_JWT} + - ARE_LOCAL_S3=${ARE_LOCAL_S3} + - USE_PATH_STYLE_URLS_S3=${USE_PATH_STYLE_URLS_S3} + - ARE_LOCAL_B2=${ARE_LOCAL_B2} + - USE_PATH_STYLE_URLS_B2=${USE_PATH_STYLE_URLS_B2} + - KEY_B2=${KEY_B2} + - SECRET_B2=${SECRET_B2} + - REGION_B2=${REGION_B2} + - BUCKET_B2=${BUCKET_B2} + - ${ARE_LOCAL_WASABI} + - USE_PATH_STYLE_URLS_WASABI=${USE_PATH_STYLE_URLS_WASABI} + - KEY_WASABI=${KEY_WASABI} + - SECRET_WASABI=${SECRET_WASABI} + - REGION_WASABI=${REGION_WASABI} + - BUCKET_WASABI=${BUCKET_WASABI} + - COMPLIANCE_WASABI=${COMPLIANCE_WASABI} + - ARE_LOCAL_SCW=${ARE_LOCAL_SCW} + - USE_PATH_STYLE_URLS_SCW=${USE_PATH_STYLE_URLS_SCW} + - KEY_SCW=${KEY_SCW} + - SECRET_SCW=${SECRET_SCW} + - REGION_SCW=${REGION_SCW} + - BUCKET_SCW=${BUCKET_SCW} + depends_on: + postgres: + condition: service_healthy + volumes: + - museum-data:/data:ro + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:8080/ping"] + interval: 60s + timeout: 5s + retries: 3 + start_period: 5s + restart: unless-stopped + command: | + sh -c ' + #!/bin/sh + + # Generate the museum.yaml configuration file + cat > /museum.yaml << EOF + db: + host: postgres + port: 5432 + name: ente_db + user: pguser + password: ${SERVICE_PASSWORD_POSTGRES} + + s3: + are_local_buckets: $ARE_LOCAL_S3 + use_path_style_urls: $USE_PATH_STYLE_URLS_S3 + b2-eu-cen: + are_local_buckets: ${ARE_LOCAL_B2:false} + use_path_style_urls: ${USE_PATH_STYLE_URLS_B2:false} + key: ${KEY_B2} + secret: ${SECRET_B2} + endpoint: ${SERVICE_URL_MINIO_3200} + region: ${REGION_B2} + bucket: ${BUCKET_B2} + wasabi-eu-central-2-v3: + are_local_buckets: ${ARE_LOCAL_WASABI:false} + use_path_style_urls: ${USE_PATH_STYLE_URLS_WASABI:false} + key: ${KEY_WASABI} + secret: ${SECRET_WASABI} + endpoint: ${SERVICE_URL_MINIO_3200} + region: ${REGION_WASABI} + bucket: ${BUCKET_WASABI} + compliance: ${COMPLIANCE_WASABI} + scw-eu-fr-v3: + are_local_buckets: ${ARE_LOCAL_SCW:false} + use_path_style_urls: ${USE_PATH_STYLE_URLS_SCW:false} + key: ${KEY_SCW} + secret: ${SECRET_SCW} + endpoint: ${SERVICE_URL_MINIO_3200} + region: ${REGION_SCW} + bucket: ${BUCKET_SCW} + + # Specify the base endpoints for various web apps + apps: + public-albums: ${SERVICE_URL_WEB_3002} + cast: ${SERVICE_URL_WEB_3004} + accounts: ${SERVICE_URL_WEB_3001} + + key: + encryption: ${KEY_ENCRYPTION} + hash: ${KEY_HASH} + + jwt: + secret: ${KEY_JWT} + + EOF + echo "Generated museum.yaml" + exec ./museum + ' + + socat: + image: alpine/socat:latest + network_mode: service:museum + depends_on: [museum] + command: "TCP-LISTEN:3200,fork,reuseaddr TCP:minio:3200" + restart: unless-stopped + healthcheck: + test: ["CMD", "nc", "-z", "localhost", "3200"] + interval: 30s + timeout: 5s + retries: 3 + start_period: 10s + + web: + image: ghcr.io/ente-io/web:latest + ports: + - 3000:3000 + - 3001:3001 + - 3002:3002 + - 3003:3003 + - 3004:3004 + environment: + - SERVICE_URL_WEB_3000 + - SERVICE_URL_WEB_3001 + - SERVICE_URL_WEB_3002 + - SERVICE_URL_WEB_3003 + - SERVICE_URL_WEB_3004 + - ENTE_API_ORIGIN=$SERVICE_URL_MUSEUM_8080 + - ENTE_ALBUMS_ORIGIN=$SERVICE_URL_WEB_3002 + - NODE_ENV=production + - ENTE_ACCOUNTS_ORIGIN=$SERVICE_URL_WEB_3001 + - ENTE_AUTH_ORIGIN=$SERVICE_URL_WEB_3003 + - ENTE_CAST_ORIGIN=$SERVICE_URL_WEB_3004 + restart: unless-stopped + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + + postgres: + image: postgres:15 + environment: + - POSTGRES_USER=pguser + - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES + - POSTGRES_DB=ente_db + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U pguser -d ente_db"] + interval: 10s + timeout: 5s + retries: 5 + start_period: 30s + restart: unless-stopped + + minio: + image: minio/minio + environment: + - SERVICE_URL_MINIO_3200 + - MINIO_ROOT_USER=$SERVICE_USER_MINIO + - MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO + command: server /data --address ":3200" --console-address ":3201" + volumes: + - minio-data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3200/minio/health/live"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 30s + restart: unless-stopped + post_start: + - command: | + sh -c ' + #!/bin/sh + + while ! mc alias set h0 http://minio:3200 $SERVICE_USER_MINIO $SERVICE_PASSWORD_MINIO 2>/dev/null + do + echo "Waiting for minio..." + sleep 0.5 + done + + mc mb -p b2-eu-cen + mc mb -p wasabi-eu-central-2-v3 + mc mb -p scw-eu-fr-v3 + ' + +volumes: + postgres-data: + minio-data: + museum-data: +networks: + default: + name: ente-network From db7b7d7b4cc830176d673d803cbaf4cb1a634824 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:26:42 +0530 Subject: [PATCH 004/322] feat: Add Ente Photos service template - Add Ente Photos service template with museum server, PostgreSQL, and MinIO - Include complete Docker Compose configuration with health checks - Add custom SVG logo for Ente Photos service - Support for end-to-end encrypted photo storage alternative to Google Photos - Auto-generate service templates JSON with proper categorization - Fix docker-compose.dev.yml network configuration for coolify service Resolves #6501 --- docker-compose.dev.yml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml index e8402b7af..bf030080c 100644 --- a/docker-compose.dev.yml +++ b/docker-compose.dev.yml @@ -19,7 +19,10 @@ services: volumes: - .:/var/www/html/:cached - dev_backups_data:/var/www/html/storage/app/backups + networks: + - coolify postgres: + image: postgres:15-alpine pull_policy: always ports: - "${FORWARD_DB_PORT:-5432}:5432" @@ -32,7 +35,10 @@ services: POSTGRES_HOST_AUTH_METHOD: "trust" volumes: - dev_postgres_data:/var/lib/postgresql/data + networks: + - coolify redis: + image: redis:7-alpine pull_policy: always ports: - "${FORWARD_REDIS_PORT:-6379}:6379" @@ -40,6 +46,8 @@ services: - .env volumes: - dev_redis_data:/data + networks: + - coolify soketi: build: context: . From 0535335dd3e92812b6486fba9943dd20141afc06 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Tue, 2 Sep 2025 15:28:10 +0530 Subject: [PATCH 005/322] Add Ente Photos service template files - Add ente-photos.yaml template with museum, postgres, and minio services - Add custom SVG logo for Ente Photos - Update service templates JSON files with new template --- public/svgs/ente-photos.svg | 27 ++++++++ templates/compose/ente-photos.yaml | 92 +++++++++++++++++++++++++ templates/service-templates-latest.json | 19 +++++ templates/service-templates.json | 19 +++++ 4 files changed, 157 insertions(+) create mode 100644 public/svgs/ente-photos.svg create mode 100644 templates/compose/ente-photos.yaml diff --git a/public/svgs/ente-photos.svg b/public/svgs/ente-photos.svg new file mode 100644 index 000000000..a3f9e7dea --- /dev/null +++ b/public/svgs/ente-photos.svg @@ -0,0 +1,27 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/templates/compose/ente-photos.yaml b/templates/compose/ente-photos.yaml new file mode 100644 index 000000000..6dcd19d41 --- /dev/null +++ b/templates/compose/ente-photos.yaml @@ -0,0 +1,92 @@ +# documentation: https://help.ente.io/self-hosting/installation/compose +# slogan: Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos. +# category: media +# tags: photos,gallery,backup,encryption,privacy,self-hosted,google-photos,alternative +# logo: svgs/ente-photos.svg +# port: 8080 + +services: + museum: + image: ghcr.io/ente-io/server:latest + environment: + - SERVICE_URL_MUSEUM_8080 + # Database configuration + - POSTGRES_HOST=postgres + - POSTGRES_PORT=5432 + - POSTGRES_DB=${POSTGRES_DB:-ente_db} + - POSTGRES_USER=${SERVICE_USER_POSTGRES} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + # S3/MinIO configuration + - S3_ARE_LOCAL_BUCKETS=true + - S3_USE_PATH_STYLE_URLS=true + - S3_B2_EU_CEN_KEY=${SERVICE_USER_MINIO} + - S3_B2_EU_CEN_SECRET=${SERVICE_PASSWORD_MINIO} + - S3_B2_EU_CEN_ENDPOINT=minio:3200 + - S3_B2_EU_CEN_REGION=eu-central-2 + - S3_B2_EU_CEN_BUCKET=b2-eu-cen + # Security keys + - ENCRYPTION_KEY=${SERVICE_PASSWORD_64_ENCRYPTION} + - HASH_KEY=${SERVICE_PASSWORD_64_HASH} + - JWT_SECRET=${SERVICE_PASSWORD_64_JWT} + # App URLs (optional - for web interface) + - APPS_PUBLIC_ALBUMS=${APPS_PUBLIC_ALBUMS:-} + - APPS_CAST=${APPS_CAST:-} + - APPS_ACCOUNTS=${APPS_ACCOUNTS:-} + volumes: + - museum-data:/data + - museum-config:/config + depends_on: + postgres: + condition: service_healthy + minio: + condition: service_started + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/ping"] + interval: 30s + timeout: 10s + retries: 3 + + postgres: + image: postgres:15-alpine + environment: + - POSTGRES_USER=${SERVICE_USER_POSTGRES} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + - POSTGRES_DB=${POSTGRES_DB:-ente_db} + volumes: + - postgres-data:/var/lib/postgresql/data + healthcheck: + test: ["CMD-SHELL", "pg_isready -U ${SERVICE_USER_POSTGRES} -d ${POSTGRES_DB:-ente_db}"] + interval: 10s + timeout: 5s + retries: 5 + + minio: + image: minio/minio:latest + environment: + - MINIO_ROOT_USER=${SERVICE_USER_MINIO} + - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} + command: server /data --address ":3200" --console-address ":3201" + volumes: + - minio-data:/data + healthcheck: + test: ["CMD", "curl", "-f", "http://127.0.0.1:3200/minio/health/live"] + interval: 30s + timeout: 10s + retries: 3 + + minio-init: + image: minio/mc:latest + depends_on: + minio: + condition: service_healthy + environment: + - MINIO_ROOT_USER=${SERVICE_USER_MINIO} + - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} + entrypoint: > + /bin/sh -c " + mc alias set minio http://minio:3200 $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}; + mc mb minio/b2-eu-cen --ignore-existing; + mc mb minio/wasabi-eu-central-2-v3 --ignore-existing; + mc mb minio/scw-eu-fr-v3 --ignore-existing; + echo 'MinIO buckets created successfully'; + " diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 4ba6d0f2c..a5ea25386 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -948,6 +948,25 @@ "minversion": "0.0.0", "port": "6555" }, + "ente-photos": { + "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", + "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9bWluaW86MzIwMCcKICAgICAgLSBTM19CMl9FVV9DRU5fUkVHSU9OPWV1LWNlbnRyYWwtMgogICAgICAtIFMzX0IyX0VVX0NFTl9CVUNLRVQ9YjItZXUtY2VuCiAgICAgIC0gJ0VOQ1JZUFRJT05fS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9FTkNSWVBUSU9OfScKICAgICAgLSAnSEFTSF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0hBU0h9JwogICAgICAtICdKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9JwogICAgICAtICdBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0nCiAgICAgIC0gJ0FQUFNfQ0FTVD0ke0FQUFNfQ0FTVDotfScKICAgICAgLSAnQVBQU19BQ0NPVU5UUz0ke0FQUFNfQUNDT1VOVFM6LX0nCiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfSAtZCAke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgbWluaW86CiAgICBpbWFnZTogJ21pbmlvL21pbmlvOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjMyMDAvbWluaW8vaGVhbHRoL2xpdmUnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBtaW5pby1pbml0OgogICAgaW1hZ2U6ICdtaW5pby9tYzpsYXRlc3QnCiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ01JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ01JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgIGVudHJ5cG9pbnQ6ICIvYmluL3NoIC1jIFwiIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OyBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7IG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7IG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7IFwiXG4iCg==", + "tags": [ + "photos", + "gallery", + "backup", + "encryption", + "privacy", + "self-hosted", + "google-photos", + "alternative" + ], + "category": "media", + "logo": "svgs/ente-photos.svg", + "minversion": "0.0.0", + "port": "8080" + }, "evolution-api": { "documentation": "https://doc.evolution-api.com/v1/pt/get-started/introduction?utm_source=coolify.io", "slogan": "Evolution API Installation with Postgres and Redis", diff --git a/templates/service-templates.json b/templates/service-templates.json index 19d5e0560..1dc45d3d0 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -948,6 +948,25 @@ "minversion": "0.0.0", "port": "6555" }, + "ente-photos": { + "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", + "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtIFBPU1RHUkVTX0hPU1Q9cG9zdGdyZXMKICAgICAgLSBQT1NUR1JFU19QT1JUPTU0MzIKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0tFWT0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0VORFBPSU5UPW1pbmlvOjMyMDAnCiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAtICdFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0hBU0hfS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9IQVNIfScKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSldUfScKICAgICAgLSAnQVBQU19QVUJMSUNfQUxCVU1TPSR7QVBQU19QVUJMSUNfQUxCVU1TOi19JwogICAgICAtICdBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0nCiAgICAgIC0gJ0FQUFNfQUNDT1VOVFM9JHtBUFBTX0FDQ09VTlRTOi19JwogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGEnCiAgICAgIC0gJ211c2V1bS1jb25maWc6L2NvbmZpZycKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy1mJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nJwogICAgICBpbnRlcnZhbDogMzBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAzCiAgcG9zdGdyZXM6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE1LWFscGluZScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlcy1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIGludGVydmFsOiAxMHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogNQogIG1pbmlvOgogICAgaW1hZ2U6ICdtaW5pby9taW5pbzpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAvZGF0YSAtLWFkZHJlc3MgIjozMjAwIiAtLWNvbnNvbGUtYWRkcmVzcyAiOjMyMDEiJwogICAgdm9sdW1lczoKICAgICAgLSAnbWluaW8tZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlJwogICAgICBpbnRlcnZhbDogMzBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAzCiAgbWluaW8taW5pdDoKICAgIGltYWdlOiAnbWluaW8vbWM6bGF0ZXN0JwogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBlbnRyeXBvaW50OiAiL2Jpbi9zaCAtYyBcIiBtYyBhbGlhcyBzZXQgbWluaW8gaHR0cDovL21pbmlvOjMyMDAgJCR7TUlOSU9fUk9PVF9VU0VSfSAkJHtNSU5JT19ST09UX1BBU1NXT1JEfTsgbWMgbWIgbWluaW8vYjItZXUtY2VuIC0taWdub3JlLWV4aXN0aW5nOyBtYyBtYiBtaW5pby93YXNhYmktZXUtY2VudHJhbC0yLXYzIC0taWdub3JlLWV4aXN0aW5nOyBtYyBtYiBtaW5pby9zY3ctZXUtZnItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7IGVjaG8gJ01pbklPIGJ1Y2tldHMgY3JlYXRlZCBzdWNjZXNzZnVsbHknOyBcIlxuIgo=", + "tags": [ + "photos", + "gallery", + "backup", + "encryption", + "privacy", + "self-hosted", + "google-photos", + "alternative" + ], + "category": "media", + "logo": "svgs/ente-photos.svg", + "minversion": "0.0.0", + "port": "8080" + }, "evolution-api": { "documentation": "https://doc.evolution-api.com/v1/pt/get-started/introduction?utm_source=coolify.io", "slogan": "Evolution API Installation with Postgres and Redis", From d42c531dabfd4a942b749533ee2fb74c2006a07f Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Tue, 2 Sep 2025 19:19:54 +0530 Subject: [PATCH 006/322] Feat: Cofig variables --- templates/compose/ente.yaml | 281 ++++++++++++++++++++---------------- 1 file changed, 156 insertions(+), 125 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index f754b7387..830c21c43 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -3,173 +3,200 @@ # category: media # tags: photos, backup, encryption, sharing, privacy, media, storage, encryption, minio, postgresql # logo: svgs/ente.png -# port: 3000, 3001, 3002, 3003, 3004, 8080, 3200 +# port: 8081 3000, 3001, 3002, 3003, 3004, 3200 services: museum: image: ghcr.io/ente-io/server:latest + ports: + - 8081:8080 environment: - - SERVICE_PASSWORD_POSTGRES= ${SERVICE_PASSWORD_POSTGRES} - - SERVICE_URL_MUSEUM_8080=${SERVICE_URL_MUSEUM_8080} - - KEY_ENCRYPTION=${KEY_ENCRYPTION} - - KEY_HASH=${KEY_HASH} - - KEY_JWT=${KEY_JWT} - - ARE_LOCAL_S3=${ARE_LOCAL_S3} - - USE_PATH_STYLE_URLS_S3=${USE_PATH_STYLE_URLS_S3} - - ARE_LOCAL_B2=${ARE_LOCAL_B2} - - USE_PATH_STYLE_URLS_B2=${USE_PATH_STYLE_URLS_B2} - - KEY_B2=${KEY_B2} - - SECRET_B2=${SECRET_B2} - - REGION_B2=${REGION_B2} - - BUCKET_B2=${BUCKET_B2} - - ${ARE_LOCAL_WASABI} - - USE_PATH_STYLE_URLS_WASABI=${USE_PATH_STYLE_URLS_WASABI} - - KEY_WASABI=${KEY_WASABI} - - SECRET_WASABI=${SECRET_WASABI} - - REGION_WASABI=${REGION_WASABI} - - BUCKET_WASABI=${BUCKET_WASABI} - - COMPLIANCE_WASABI=${COMPLIANCE_WASABI} - - ARE_LOCAL_SCW=${ARE_LOCAL_SCW} - - USE_PATH_STYLE_URLS_SCW=${USE_PATH_STYLE_URLS_SCW} - - KEY_SCW=${KEY_SCW} - - SECRET_SCW=${SECRET_SCW} - - REGION_SCW=${REGION_SCW} - - BUCKET_SCW=${BUCKET_SCW} + SERVICE_URL_MUSEUM_8081: ${SERVICE_URL_MUSEUM_8081:-http://localhost:8081} + + ENTE_HTTP_USE_TLS: ${ENTE_HTTP_USE_TLS:-false} + + ENTE_APPS_PUBLIC_ALBUMS: ${SERVICE_URL_WEB_3002:-http://localhost:3002} + ENTE_APPS_CAST: ${SERVICE_URL_WEB_3004:-http://localhost:3004} + ENTE_APPS_ACCOUNTS: ${SERVICE_URL_WEB_3001:-http://localhost:3001} + ENTE_APPS_PUBLIC_LOCKER: ${SERVICE_URL_WEB_3003:-http://localhost:3003} + ENTE_APPS_CUSTOM_DOMAIN_CNAME: ${ENTE_APPS_CUSTOM_DOMAIN_CNAME} + + ENTE_DB_HOST: ${ENTE_DB_HOST:-postgres} + ENTE_DB_PORT: ${ENTE_DB_PORT:-5432} + ENTE_DB_NAME: ${ENTE_DB_NAME:-ente_db} + ENTE_DB_SSLMODE: ${ENTE_DB_SSLMODE:-disable} + ENTE_DB_USER: ${SERVICE_USER_POSTGRES:-pguser} + ENTE_DB_PASSWORD: ${SERVICE_PASSWORD_POSTGRES} + + ENTE_KEY_ENCRYPTION: ${MUSEUM_ENCRYPTION_KEY} + ENTE_KEY_HASH: ${MUSEUM_HASH_KEY} + + ENTE_JWT_SECRET: ${MUSEUM_JWT_KEY} + + ENTE_SMTP_HOST: ${SMTP_HOST} + ENTE_SMTP_PORT: ${SMTP_PORT} + ENTE_SMTP_USERNAME: ${SMTP_USERNAME} + ENTE_SMTP_PASSWORD: ${SMTP_PASSWORD} + ENTE_SMTP_EMAIL: ${SMTP_EMAIL} + ENTE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME} + ENTE_SMTP_ENCRYPTION: ${SMTP_ENCRYPTION} + + ENTE_TRANSMAIL_KEY: ${ENTE_TRANSMAIL_KEY} + + ENTE_APPLE_SHARED_SECRET: ${ENTE_APPLE_SHARED_SECRET} + + ENTE_STRIPE_US_KEY: ${ENTE_STRIPE_US_KEY} + ENTE_STRIPE_US_WEBHOOK_SECRET: ${ENTE_STRIPE_WEBHOOK_SECRET} + ENTE_STRIPE_IN_KEY: ${ENTE_STRIPE_US_KEY} + ENTE_STRIPE_IN_WEBHOOK_SECRET: ${ENTE_STRIPE_WEBHOOK_SECRET} + ENTE_STRIPE_WHITELISTED_REDIRECT_URLS: ${ENTE_WHITELISTED_REDIRECT_URLS} + + ENTE_WEBAUTHN_RPID: ${ENTE_WEBAUTHN_RPID:-localhost} + ENTE_WEBAUTHN_RPORIGINS: ${ENTE_WEBAUTHN_RPORIGINS:-https://localhost:3001} + + ENTE_INTERNAL_SILENT: ${ENTE_INTERNAL_SILENT:-false} + ENTE_INTERNAL_HEALTH_CHECK_URL: ${ENTE_INTERNAL_HEALTH_CHECK_URL} + ENTE_INTERNAL_HARDCODED_OTT_EMAILS: ${ENTE_INTERNAL_HARDCODED_OTT_EMAIL} + ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX} + ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE} + ENTE_INTERNAL_ADMINS: ${ENTE_INTERNAL_ADMINS} + ENTE_INTERNAL_ADMIN: ${ENTE_INTERNAL_ADMIN} + ENTE_INTERNAL_DISABLE_REGISTRATION: ${ENTE_INTERNAL_DISABLE_REGISTRATION:-false} + + ENTE_REPLICATION_ENABLED: ${ENTE_REPLICATION_ENABLED:-false} + ENTE_REPLICATION_WORKER_URL: ${ENTE_REPLICATION_WORKER_URL} + ENTE_REPLICATION_WORKER_COUNT: ${ENTE_REPLICATION_WORKER_COUNT:-6} + ENTE_REPLICATION_TMP_STORAGE: ${ENTE_REPLICATION_TMP_STORAGE:-/tmp/replication} + + ENTE_JOBS_CRON_SKIP: ${ENTE_JOBS_CRON_SKIP:-false} + ENTE_JOBS_REMOVE_UNREPORTED_OBJECTS_WORKER_COUNT: ${ENTE_JOBS_REMOVE_UNREPORTED_OBJECTS_WORKER_COUNT:-1} + ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_ENABLED: ${ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_ENABLED:-false} + ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_PREFIX: ${ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_PREFIX:-""} + + ENTE_S3_ARE_LOCAL_BUCKETS: ${ENTE_S3_ARE_LOCAL_BUCKETS:-true} + ENTE_S3_USE_PATH_STYLE_URLS: ${ENTE_S3_USE_PATH_STYLE_URLS:-true} + + ENTE_S3_HOT_STORAGE_PRIMARY: ${ENTE_S3_HOT_STORAGE_PRIMARY:-b2-eu-cen} + ENTE_S3_HOT_STORAGE_SECONDARY: ${ENTE_S3_HOT_STORAGE_SECONDARY:-wasabi-eu-central-2-v3} + + ENTE_S3_B2_EU_CEN_KEY: ${SERVICE_USER_MINIO} + ENTE_S3_B2_EU_CEN_SECRET: ${SERVICE_PASSWORD_MINIO} + ENTE_S3_B2_EU_CEN_ENDPOINT: ${SERVICE_URL_MINIO}:3200 + ENTE_S3_B2_EU_CEN_REGION: ${PRIMARY_STORAGE_REGION:-eu-central-2} + ENTE_S3_B2_EU_CEN_BUCKET: ${PRIMARY_STORAGE_BUCKET:-b2-eu-cen} + ENTE_S3_B2_EU_CEN_ARE_LOCAL_BUCKETS: ${PRIMARY_STORAGE_ARE_LOCAL_BUCKETS:-false} + ENTE_S3_B2_EU_CEN_USE_PATH_STYLE_URLS: ${PRIMARY_STORAGE_USE_PATH_STYLE_URLS:-false} + + ENTE_S3_WASABI_EU_CENTRAL_2_V3_KEY: ${SERVICE_USER_MINIO} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_SECRET: ${SERVICE_PASSWORD_MINIO} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_ENDPOINT: ${SERVICE_URL_MINIO}:3200 + ENTE_S3_WASABI_EU_CENTRAL_2_V3_REGION: ${SECONDARY_STORAGE_REGION:-eu-central-2} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_BUCKET: ${SECONDARY_STORAGE_BUCKET:-wasabi-eu-central-2-v3} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_ARE_LOCAL_BUCKETS: ${SECONDARY_STORAGE_ARE_LOCAL_BUCKETS:-false} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_USE_PATH_STYLE_URLS: ${SECONDARY_STORAGE_USE_PATH_STYLE_URLS:-false} + ENTE_S3_WASABI_EU_CENTRAL_2_V3_COMPLIANCE: ${SECONDARY_STORAGE_COMPLIANCE:-true} + + ENTE_S3_SCW_EU_FR_V3_KEY: ${SERVICE_USER_MINIO} + ENTE_S3_SCW_EU_FR_V3_SECRET: ${SERVICE_PASSWORD_MINIO} + ENTE_S3_SCW_EU_FR_V3_ENDPOINT: ${SERVICE_URL_MINIO}:3200 + ENTE_S3_SCW_EU_FR_V3_REGION: ${SECONDARY_STORAGE_REGION:-eu-central-2} + ENTE_S3_SCW_EU_FR_V3_BUCKET: ${COLD_STORAGE_BUCKET:-scw-eu-fr-v3} + ENTE_S3_SCW_EU_FR_V3_ARE_LOCAL_BUCKETS: ${COLD_STORAGE_ARE_LOCAL_BUCKETS:-true} + ENTE_S3_SCW_EU_FR_V3_USE_PATH_STYLE_URLS: ${COLD_STORAGE_USE_PATH_STYLE_URLS:-true} + + ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_KEY: ${SECONDARY_STORAGE_DERIVED_KEY} + ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_SECRET: ${SECONDARY_STORAGE_DERIVED_SECRET} + ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_ENDPOINT: ${SECONDARY_STORAGE_DERIVED_ENDPOINT} + ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_REGION: ${SECONDARY_STORAGE_DERIVED_REGION} + ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_BUCKET: ${SECONDARY_STORAGE_DERIVED_BUCKET} + + ENTE_S3_DERIVED_STORAGE: ${ENTE_S3_DERIVED_STORAGE:-wasabi-eu-central-2-derived} + + ENTE_S3_FILE_DATA_CONFIG_MLDATA_PRIMARY_BUCKET: ${ENTE_S3_FILE_DATA_CONFIG_MLDATA_PRIMARY_BUCKET} + ENTE_S3_FILE_DATA_CONFIG_MLDATA_REPLICA_BUCKETS: ${ENTE_S3_FILE_DATA_CONFIG_MLDATA_REPLICA_BUCKETS} + ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_PRIMARY_BUCKET: ${ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_PRIMARY_BUCKET} + ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_REPLICA_BUCKETS: ${ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_REPLICA_BUCKETS} + depends_on: postgres: condition: service_healthy + minio: + condition: service_healthy volumes: - - museum-data:/data:ro + - museum-data:/data:rw healthcheck: - test: ["CMD", "curl", "--fail", "http://localhost:8080/ping"] + test: ["CMD", "curl", "--fail", "http://localhost:8081/ping"] interval: 60s timeout: 5s retries: 3 - start_period: 5s + start_period: 10s restart: unless-stopped - command: | - sh -c ' - #!/bin/sh - - # Generate the museum.yaml configuration file - cat > /museum.yaml << EOF - db: - host: postgres - port: 5432 - name: ente_db - user: pguser - password: ${SERVICE_PASSWORD_POSTGRES} - - s3: - are_local_buckets: $ARE_LOCAL_S3 - use_path_style_urls: $USE_PATH_STYLE_URLS_S3 - b2-eu-cen: - are_local_buckets: ${ARE_LOCAL_B2:false} - use_path_style_urls: ${USE_PATH_STYLE_URLS_B2:false} - key: ${KEY_B2} - secret: ${SECRET_B2} - endpoint: ${SERVICE_URL_MINIO_3200} - region: ${REGION_B2} - bucket: ${BUCKET_B2} - wasabi-eu-central-2-v3: - are_local_buckets: ${ARE_LOCAL_WASABI:false} - use_path_style_urls: ${USE_PATH_STYLE_URLS_WASABI:false} - key: ${KEY_WASABI} - secret: ${SECRET_WASABI} - endpoint: ${SERVICE_URL_MINIO_3200} - region: ${REGION_WASABI} - bucket: ${BUCKET_WASABI} - compliance: ${COMPLIANCE_WASABI} - scw-eu-fr-v3: - are_local_buckets: ${ARE_LOCAL_SCW:false} - use_path_style_urls: ${USE_PATH_STYLE_URLS_SCW:false} - key: ${KEY_SCW} - secret: ${SECRET_SCW} - endpoint: ${SERVICE_URL_MINIO_3200} - region: ${REGION_SCW} - bucket: ${BUCKET_SCW} - - # Specify the base endpoints for various web apps - apps: - public-albums: ${SERVICE_URL_WEB_3002} - cast: ${SERVICE_URL_WEB_3004} - accounts: ${SERVICE_URL_WEB_3001} - - key: - encryption: ${KEY_ENCRYPTION} - hash: ${KEY_HASH} - - jwt: - secret: ${KEY_JWT} - - EOF - echo "Generated museum.yaml" - exec ./museum - ' + networks: + - ente-network socat: - image: alpine/socat:latest + image: alpine/socat network_mode: service:museum depends_on: [museum] command: "TCP-LISTEN:3200,fork,reuseaddr TCP:minio:3200" restart: unless-stopped - healthcheck: - test: ["CMD", "nc", "-z", "localhost", "3200"] - interval: 30s - timeout: 5s - retries: 3 - start_period: 10s web: - image: ghcr.io/ente-io/web:latest - ports: - - 3000:3000 - - 3001:3001 - - 3002:3002 - - 3003:3003 - - 3004:3004 + image: ghcr.io/ente-io/web + # ports: + # - 3000:3000 # Photos web app + # - 3001:3001 # Accounts + # - 3002:3002 # Public albums + # - 3003:3003 # Auth + # - 3004:3004 # Cast environment: - - SERVICE_URL_WEB_3000 - - SERVICE_URL_WEB_3001 - - SERVICE_URL_WEB_3002 - - SERVICE_URL_WEB_3003 - - SERVICE_URL_WEB_3004 - - ENTE_API_ORIGIN=$SERVICE_URL_MUSEUM_8080 - - ENTE_ALBUMS_ORIGIN=$SERVICE_URL_WEB_3002 - - NODE_ENV=production - - ENTE_ACCOUNTS_ORIGIN=$SERVICE_URL_WEB_3001 - - ENTE_AUTH_ORIGIN=$SERVICE_URL_WEB_3003 - - ENTE_CAST_ORIGIN=$SERVICE_URL_WEB_3004 + ENTE_API_ORIGIN: ${SERVICE_URL_MUSEUM:-http://localhost}:8081 + SERVICE_URL_WEB_3000: ${SERVICE_URL_WEB_3000:-http://localhost:3000} + ENTE_ALBUMS_ORIGIN: ${SERVICE_URL_WEB_3002:-http://localhost:3002} + SERVICE_URL_WEB_3001: ${SERVICE_URL_WEB_3001:-http://localhost:3001} + SERVICE_URL_WEB_3003: ${SERVICE_URL_WEB_3003:-http://localhost:3003} + SERVICE_URL_WEB_3004: ${SERVICE_URL_WEB_3004:-http://localhost:3004} + restart: unless-stopped healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3000"] + test: ["CMD", "curl", "--fail", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 start_period: 10s + networks: + - ente-network postgres: image: postgres:15 environment: - - POSTGRES_USER=pguser - - POSTGRES_PASSWORD=$SERVICE_PASSWORD_POSTGRES - - POSTGRES_DB=ente_db + - POSTGRES_USER=${SERVICE_USER_POSTGRES:-pguser} + - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} + - POSTGRES_DB=${SERVICE_DB_NAME:-ente_db} volumes: - postgres-data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U pguser -d ente_db"] + test: + [ + "CMD-SHELL", + "pg_isready -U ${SERVICE_USER_POSTGRES:-pguser} -d ${SERVICE_DB_NAME:-ente_db}", + ] interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped + networks: + - ente-network minio: image: minio/minio + ports: + - 3200:3200 environment: - - SERVICE_URL_MINIO_3200 - - MINIO_ROOT_USER=$SERVICE_USER_MINIO - - MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO + SERVICE_URL_MINIO_3200: ${SERVICE_URL_MINIO_3200} + MINIO_ROOT_USER: ${SERVICE_USER_MINIO} + MINIO_ROOT_PASSWORD: ${SERVICE_PASSWORD_MINIO} command: server /data --address ":3200" --console-address ":3201" volumes: - minio-data:/data @@ -179,27 +206,31 @@ services: timeout: 10s retries: 3 start_period: 30s - restart: unless-stopped post_start: - command: | sh -c ' #!/bin/sh - while ! mc alias set h0 http://minio:3200 $SERVICE_USER_MINIO $SERVICE_PASSWORD_MINIO 2>/dev/null + while ! mc alias set h0 http://minio:3200 ${SERVICE_USER_MINIO} ${SERVICE_PASSWORD_MINIO} 2>/dev/null do echo "Waiting for minio..." sleep 0.5 done + cd /data + mc mb -p b2-eu-cen mc mb -p wasabi-eu-central-2-v3 mc mb -p scw-eu-fr-v3 ' + networks: + - ente-network volumes: postgres-data: minio-data: museum-data: + networks: - default: + ente-network: name: ente-network From 21992a481db97fd7bfa9242f44f48f40971e9fc5 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Tue, 2 Sep 2025 20:08:33 +0530 Subject: [PATCH 007/322] Update Ente Photos logo to match official branding - Replace custom camera-based logo with official Ente-inspired design - Use official Ente green color scheme (#00D4AA to #00A693) - Implement simplified 'e' letter design matching Ente brand identity - Remove docker-compose.dev.yml changes as requested in PR review Addresses feedback from PR review #6515 --- public/svgs/ente-photos.svg | 26 +++++++------------------- 1 file changed, 7 insertions(+), 19 deletions(-) diff --git a/public/svgs/ente-photos.svg b/public/svgs/ente-photos.svg index a3f9e7dea..a784cbebb 100644 --- a/public/svgs/ente-photos.svg +++ b/public/svgs/ente-photos.svg @@ -1,27 +1,15 @@ + - - - - - - - - - - - - - - - - - - - + + + + + + From c5befbd276cbb70c32c9e3acdcd5b2c9368176fc Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Tue, 2 Sep 2025 20:25:30 +0530 Subject: [PATCH 008/322] Use official Ente Photos icon design - Update SVG logo to match the official Ente Photos PNG icon - Based on the official icon from public/ente-photos-icon-green.png - Maintain official Ente green gradient colors (#00D4AA to #00A693) - Improve 'e' letterform to match official Ente branding more closely - Ensure consistency with official Ente Photos visual identity Addresses reviewer feedback to use official logo instead of custom design --- public/svgs/ente-photos.svg | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/public/svgs/ente-photos.svg b/public/svgs/ente-photos.svg index a784cbebb..e6a469e91 100644 --- a/public/svgs/ente-photos.svg +++ b/public/svgs/ente-photos.svg @@ -1,5 +1,5 @@ - + @@ -8,8 +8,8 @@ - + - - + + From c254b51eada492b22eae55f399d7a933ba6cd7d5 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Tue, 2 Sep 2025 22:07:57 +0530 Subject: [PATCH 009/322] Delete docker-compose.dev.yml --- docker-compose.dev.yml | 133 ----------------------------------------- 1 file changed, 133 deletions(-) delete mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml deleted file mode 100644 index bf030080c..000000000 --- a/docker-compose.dev.yml +++ /dev/null @@ -1,133 +0,0 @@ -services: - coolify: - build: - context: . - dockerfile: ./docker/development/Dockerfile - args: - - USER_ID=${USERID:-1000} - - GROUP_ID=${GROUPID:-1000} - ports: - - "${APP_PORT:-8000}:8080" - environment: - AUTORUN_ENABLED: false - PUSHER_HOST: "${PUSHER_HOST}" - PUSHER_PORT: "${PUSHER_PORT}" - PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" - PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" - PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" - PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" - volumes: - - .:/var/www/html/:cached - - dev_backups_data:/var/www/html/storage/app/backups - networks: - - coolify - postgres: - image: postgres:15-alpine - pull_policy: always - ports: - - "${FORWARD_DB_PORT:-5432}:5432" - env_file: - - .env - environment: - POSTGRES_USER: "${DB_USERNAME:-coolify}" - POSTGRES_PASSWORD: "${DB_PASSWORD:-password}" - POSTGRES_DB: "${DB_DATABASE:-coolify}" - POSTGRES_HOST_AUTH_METHOD: "trust" - volumes: - - dev_postgres_data:/var/lib/postgresql/data - networks: - - coolify - redis: - image: redis:7-alpine - pull_policy: always - ports: - - "${FORWARD_REDIS_PORT:-6379}:6379" - env_file: - - .env - volumes: - - dev_redis_data:/data - networks: - - coolify - soketi: - build: - context: . - dockerfile: ./docker/coolify-realtime/Dockerfile - env_file: - - .env - ports: - - "${FORWARD_SOKETI_PORT:-6001}:6001" - - "6002:6002" - volumes: - - ./storage:/var/www/html/storage - - ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js - environment: - SOKETI_DEBUG: "false" - SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" - SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" - SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" - entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] - vite: - image: node:24-alpine - pull_policy: always - working_dir: /var/www/html - environment: - VITE_HOST: "${VITE_HOST:-localhost}" - VITE_PORT: "${VITE_PORT:-5173}" - ports: - - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" - volumes: - - .:/var/www/html/:cached - command: sh -c "npm install && npm run dev" - networks: - - coolify - testing-host: - build: - context: . - dockerfile: ./docker/testing-host/Dockerfile - init: true - container_name: coolify-testing-host - volumes: - - /var/run/docker.sock:/var/run/docker.sock - - dev_coolify_data:/data/coolify - - dev_backups_data:/data/coolify/backups - - dev_postgres_data:/data/coolify/_volumes/database - - dev_redis_data:/data/coolify/_volumes/redis - - dev_minio_data:/data/coolify/_volumes/minio - networks: - - coolify - mailpit: - image: axllent/mailpit:latest - pull_policy: always - container_name: coolify-mail - ports: - - "${FORWARD_MAILPIT_PORT:-1025}:1025" - - "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025" - networks: - - coolify - minio: - image: minio/minio:latest - pull_policy: always - container_name: coolify-minio - command: server /data --console-address ":9001" - ports: - - "${FORWARD_MINIO_PORT:-9000}:9000" - - "${FORWARD_MINIO_PORT_CONSOLE:-9001}:9001" - environment: - MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" - MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" - volumes: - - dev_minio_data:/data - networks: - - coolify - -volumes: - dev_backups_data: - dev_postgres_data: - dev_redis_data: - dev_coolify_data: - dev_minio_data: - -networks: - coolify: - name: coolify - external: false From 7fe8fec1decca63bb59535bb1c154c205d75fe0b Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Wed, 3 Sep 2025 07:23:07 +0530 Subject: [PATCH 010/322] Address reviewer feedback: Fix MinIO endpoint and add admin permissions - Fix MinIO endpoint configuration to use SERVICE_URL_MINIO_3200 for public access This resolves the issue with signed URLs for photo uploads as noted by @devdilson - Add ENTE_INTERNAL_ADMIN environment variable to grant first account admin permissions This prevents the 10GB storage limit issue mentioned in the review - Update service templates JSON files with the corrected configuration - Ensure MinIO service has proper SERVICE_URL configuration for external access Addresses all feedback from @devdilson's review comments: - Fixes signed URL access for photo uploads - Grants admin permissions to first account - Maintains proper service architecture for Coolify deployment --- public/ente-photos-icon-green.png | Bin 0 -> 30327 bytes templates/compose/ente-photos.yaml | 5 ++++- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- 4 files changed, 6 insertions(+), 3 deletions(-) create mode 100644 public/ente-photos-icon-green.png diff --git a/public/ente-photos-icon-green.png b/public/ente-photos-icon-green.png new file mode 100644 index 0000000000000000000000000000000000000000..b74aa472d6e4292f76933f1142c77ba2824119c7 GIT binary patch literal 30327 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 a2YN+L%XO>8TMV#X*VE(n3*zDc literal 0 HcmV?d00001 diff --git a/templates/compose/ente-photos.yaml b/templates/compose/ente-photos.yaml index 6dcd19d41..a3fca5df2 100644 --- a/templates/compose/ente-photos.yaml +++ b/templates/compose/ente-photos.yaml @@ -21,13 +21,15 @@ services: - S3_USE_PATH_STYLE_URLS=true - S3_B2_EU_CEN_KEY=${SERVICE_USER_MINIO} - S3_B2_EU_CEN_SECRET=${SERVICE_PASSWORD_MINIO} - - S3_B2_EU_CEN_ENDPOINT=minio:3200 + - S3_B2_EU_CEN_ENDPOINT=${SERVICE_URL_MINIO_3200} - S3_B2_EU_CEN_REGION=eu-central-2 - S3_B2_EU_CEN_BUCKET=b2-eu-cen # Security keys - ENCRYPTION_KEY=${SERVICE_PASSWORD_64_ENCRYPTION} - HASH_KEY=${SERVICE_PASSWORD_64_HASH} - JWT_SECRET=${SERVICE_PASSWORD_64_JWT} + # Admin permissions (grants first account admin access) + - ENTE_INTERNAL_ADMIN=1580559962386438 # App URLs (optional - for web interface) - APPS_PUBLIC_ALBUMS=${APPS_PUBLIC_ALBUMS:-} - APPS_CAST=${APPS_CAST:-} @@ -63,6 +65,7 @@ services: minio: image: minio/minio:latest environment: + - SERVICE_URL_MINIO_3200 - MINIO_ROOT_USER=${SERVICE_USER_MINIO} - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} command: server /data --address ":3200" --console-address ":3201" diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index a5ea25386..1d2224264 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -951,7 +951,7 @@ "ente-photos": { "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", - "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9bWluaW86MzIwMCcKICAgICAgLSBTM19CMl9FVV9DRU5fUkVHSU9OPWV1LWNlbnRyYWwtMgogICAgICAtIFMzX0IyX0VVX0NFTl9CVUNLRVQ9YjItZXUtY2VuCiAgICAgIC0gJ0VOQ1JZUFRJT05fS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9FTkNSWVBUSU9OfScKICAgICAgLSAnSEFTSF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0hBU0h9JwogICAgICAtICdKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9JwogICAgICAtICdBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0nCiAgICAgIC0gJ0FQUFNfQ0FTVD0ke0FQUFNfQ0FTVDotfScKICAgICAgLSAnQVBQU19BQ0NPVU5UUz0ke0FQUFNfQUNDT1VOVFM6LX0nCiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfSAtZCAke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgbWluaW86CiAgICBpbWFnZTogJ21pbmlvL21pbmlvOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjMyMDAvbWluaW8vaGVhbHRoL2xpdmUnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBtaW5pby1pbml0OgogICAgaW1hZ2U6ICdtaW5pby9tYzpsYXRlc3QnCiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ01JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ01JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgIGVudHJ5cG9pbnQ6ICIvYmluL3NoIC1jIFwiIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OyBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7IG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7IG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7IFwiXG4iCg==", + "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogbWluaW8vbWluaW86bGF0ZXN0CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX1VSTF9NSU5JT18zMjAwCiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgY29tbWFuZDogc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSIKICAgIHZvbHVtZXM6CiAgICAgIC0gbWluaW8tZGF0YTovZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01EIiwgImN1cmwiLCAiLWYiLCAiaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBtaW5pby1pbml0OgogICAgaW1hZ2U6IG1pbmlvL21jOmxhdGVzdAogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIE1JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30KICAgICAgLSBNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30KICAgIGVudHJ5cG9pbnQ6ID4KICAgICAgL2Jpbi9zaCAtYyAiCiAgICAgIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OwogICAgICBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7CiAgICAgICIK", "tags": [ "photos", "gallery", diff --git a/templates/service-templates.json b/templates/service-templates.json index 1dc45d3d0..6fb0b689b 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -951,7 +951,7 @@ "ente-photos": { "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", - "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtIFBPU1RHUkVTX0hPU1Q9cG9zdGdyZXMKICAgICAgLSBQT1NUR1JFU19QT1JUPTU0MzIKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0tFWT0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0VORFBPSU5UPW1pbmlvOjMyMDAnCiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAtICdFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0hBU0hfS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9IQVNIfScKICAgICAgLSAnSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSldUfScKICAgICAgLSAnQVBQU19QVUJMSUNfQUxCVU1TPSR7QVBQU19QVUJMSUNfQUxCVU1TOi19JwogICAgICAtICdBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0nCiAgICAgIC0gJ0FQUFNfQUNDT1VOVFM9JHtBUFBTX0FDQ09VTlRTOi19JwogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGEnCiAgICAgIC0gJ211c2V1bS1jb25maWc6L2NvbmZpZycKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy1mJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nJwogICAgICBpbnRlcnZhbDogMzBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAzCiAgcG9zdGdyZXM6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE1LWFscGluZScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlcy1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIGludGVydmFsOiAxMHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogNQogIG1pbmlvOgogICAgaW1hZ2U6ICdtaW5pby9taW5pbzpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAvZGF0YSAtLWFkZHJlc3MgIjozMjAwIiAtLWNvbnNvbGUtYWRkcmVzcyAiOjMyMDEiJwogICAgdm9sdW1lczoKICAgICAgLSAnbWluaW8tZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlJwogICAgICBpbnRlcnZhbDogMzBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAzCiAgbWluaW8taW5pdDoKICAgIGltYWdlOiAnbWluaW8vbWM6bGF0ZXN0JwogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBlbnRyeXBvaW50OiAiL2Jpbi9zaCAtYyBcIiBtYyBhbGlhcyBzZXQgbWluaW8gaHR0cDovL21pbmlvOjMyMDAgJCR7TUlOSU9fUk9PVF9VU0VSfSAkJHtNSU5JT19ST09UX1BBU1NXT1JEfTsgbWMgbWIgbWluaW8vYjItZXUtY2VuIC0taWdub3JlLWV4aXN0aW5nOyBtYyBtYiBtaW5pby93YXNhYmktZXUtY2VudHJhbC0yLXYzIC0taWdub3JlLWV4aXN0aW5nOyBtYyBtYiBtaW5pby9zY3ctZXUtZnItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7IGVjaG8gJ01pbklPIGJ1Y2tldHMgY3JlYXRlZCBzdWNjZXNzZnVsbHknOyBcIlxuIgo=", + "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogbWluaW8vbWluaW86bGF0ZXN0CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX1VSTF9NSU5JT18zMjAwCiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgY29tbWFuZDogc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSIKICAgIHZvbHVtZXM6CiAgICAgIC0gbWluaW8tZGF0YTovZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01EIiwgImN1cmwiLCAiLWYiLCAiaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBtaW5pby1pbml0OgogICAgaW1hZ2U6IG1pbmlvL21jOmxhdGVzdAogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIE1JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30KICAgICAgLSBNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30KICAgIGVudHJ5cG9pbnQ6ID4KICAgICAgL2Jpbi9zaCAtYyAiCiAgICAgIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OwogICAgICBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7CiAgICAgICIK", "tags": [ "photos", "gallery", From 75b508c53ebd1b547eb1e2506ea350ff63aa15be Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Wed, 3 Sep 2025 07:24:59 +0530 Subject: [PATCH 011/322] Restore docker-compose.dev.yml file - Restore docker-compose.dev.yml to original state as requested by @Cinzya - File should not be deleted, just reverted to original state - Addresses reviewer feedback about keeping the file intact --- docker-compose.dev.yml | 125 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 125 insertions(+) create mode 100644 docker-compose.dev.yml diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml new file mode 100644 index 000000000..e8402b7af --- /dev/null +++ b/docker-compose.dev.yml @@ -0,0 +1,125 @@ +services: + coolify: + build: + context: . + dockerfile: ./docker/development/Dockerfile + args: + - USER_ID=${USERID:-1000} + - GROUP_ID=${GROUPID:-1000} + ports: + - "${APP_PORT:-8000}:8080" + environment: + AUTORUN_ENABLED: false + PUSHER_HOST: "${PUSHER_HOST}" + PUSHER_PORT: "${PUSHER_PORT}" + PUSHER_SCHEME: "${PUSHER_SCHEME:-http}" + PUSHER_APP_ID: "${PUSHER_APP_ID:-coolify}" + PUSHER_APP_KEY: "${PUSHER_APP_KEY:-coolify}" + PUSHER_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" + volumes: + - .:/var/www/html/:cached + - dev_backups_data:/var/www/html/storage/app/backups + postgres: + pull_policy: always + ports: + - "${FORWARD_DB_PORT:-5432}:5432" + env_file: + - .env + environment: + POSTGRES_USER: "${DB_USERNAME:-coolify}" + POSTGRES_PASSWORD: "${DB_PASSWORD:-password}" + POSTGRES_DB: "${DB_DATABASE:-coolify}" + POSTGRES_HOST_AUTH_METHOD: "trust" + volumes: + - dev_postgres_data:/var/lib/postgresql/data + redis: + pull_policy: always + ports: + - "${FORWARD_REDIS_PORT:-6379}:6379" + env_file: + - .env + volumes: + - dev_redis_data:/data + soketi: + build: + context: . + dockerfile: ./docker/coolify-realtime/Dockerfile + env_file: + - .env + ports: + - "${FORWARD_SOKETI_PORT:-6001}:6001" + - "6002:6002" + volumes: + - ./storage:/var/www/html/storage + - ./docker/coolify-realtime/terminal-server.js:/terminal/terminal-server.js + environment: + SOKETI_DEBUG: "false" + SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}" + SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}" + SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}" + entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"] + vite: + image: node:24-alpine + pull_policy: always + working_dir: /var/www/html + environment: + VITE_HOST: "${VITE_HOST:-localhost}" + VITE_PORT: "${VITE_PORT:-5173}" + ports: + - "${VITE_PORT:-5173}:${VITE_PORT:-5173}" + volumes: + - .:/var/www/html/:cached + command: sh -c "npm install && npm run dev" + networks: + - coolify + testing-host: + build: + context: . + dockerfile: ./docker/testing-host/Dockerfile + init: true + container_name: coolify-testing-host + volumes: + - /var/run/docker.sock:/var/run/docker.sock + - dev_coolify_data:/data/coolify + - dev_backups_data:/data/coolify/backups + - dev_postgres_data:/data/coolify/_volumes/database + - dev_redis_data:/data/coolify/_volumes/redis + - dev_minio_data:/data/coolify/_volumes/minio + networks: + - coolify + mailpit: + image: axllent/mailpit:latest + pull_policy: always + container_name: coolify-mail + ports: + - "${FORWARD_MAILPIT_PORT:-1025}:1025" + - "${FORWARD_MAILPIT_DASHBOARD_PORT:-8025}:8025" + networks: + - coolify + minio: + image: minio/minio:latest + pull_policy: always + container_name: coolify-minio + command: server /data --console-address ":9001" + ports: + - "${FORWARD_MINIO_PORT:-9000}:9000" + - "${FORWARD_MINIO_PORT_CONSOLE:-9001}:9001" + environment: + MINIO_ACCESS_KEY: "${MINIO_ACCESS_KEY:-minioadmin}" + MINIO_SECRET_KEY: "${MINIO_SECRET_KEY:-minioadmin}" + volumes: + - dev_minio_data:/data + networks: + - coolify + +volumes: + dev_backups_data: + dev_postgres_data: + dev_redis_data: + dev_coolify_data: + dev_minio_data: + +networks: + coolify: + name: coolify + external: false From 8c8e2973c7ee71319e1537fef077e416043669e2 Mon Sep 17 00:00:00 2001 From: Vishwanath Martur <64204611+vishwamartur@users.noreply.github.com> Date: Wed, 3 Sep 2025 07:43:45 +0530 Subject: [PATCH 012/322] Fix MinIO image and health check to match Coolify standards - Change MinIO image from 'minio/minio:latest' to 'quay.io/minio/minio:latest' This matches the official Coolify MinIO template for consistency - Update health check from curl-based to 'mc ready local' command This is more reliable and matches the official MinIO template - Update health check intervals and retries to match official template (interval: 5s, timeout: 20s, retries: 10) - Update service templates JSON files with corrected configuration Addresses @devdilson's feedback about MinIO configuration consistency with existing Coolify templates and best practices. --- templates/compose/ente-photos.yaml | 10 +++++----- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/templates/compose/ente-photos.yaml b/templates/compose/ente-photos.yaml index a3fca5df2..6ee902d6c 100644 --- a/templates/compose/ente-photos.yaml +++ b/templates/compose/ente-photos.yaml @@ -63,7 +63,7 @@ services: retries: 5 minio: - image: minio/minio:latest + image: quay.io/minio/minio:latest environment: - SERVICE_URL_MINIO_3200 - MINIO_ROOT_USER=${SERVICE_USER_MINIO} @@ -72,10 +72,10 @@ services: volumes: - minio-data:/data healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:3200/minio/health/live"] - interval: 30s - timeout: 10s - retries: 3 + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 20s + retries: 10 minio-init: image: minio/mc:latest diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 1d2224264..489ed0e90 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -951,7 +951,7 @@ "ente-photos": { "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", - "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogbWluaW8vbWluaW86bGF0ZXN0CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX1VSTF9NSU5JT18zMjAwCiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgY29tbWFuZDogc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSIKICAgIHZvbHVtZXM6CiAgICAgIC0gbWluaW8tZGF0YTovZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01EIiwgImN1cmwiLCAiLWYiLCAiaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBtaW5pby1pbml0OgogICAgaW1hZ2U6IG1pbmlvL21jOmxhdGVzdAogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIE1JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30KICAgICAgLSBNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30KICAgIGVudHJ5cG9pbnQ6ID4KICAgICAgL2Jpbi9zaCAtYyAiCiAgICAgIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OwogICAgICBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7CiAgICAgICIK", + "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", "tags": [ "photos", "gallery", diff --git a/templates/service-templates.json b/templates/service-templates.json index 6fb0b689b..f44b57bb3 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -951,7 +951,7 @@ "ente-photos": { "documentation": "https://help.ente.io/self-hosting/installation/compose?utm_source=coolify.io", "slogan": "Ente Photos is a fully open source, End to End Encrypted alternative to Google Photos and Apple Photos.", - "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogbWluaW8vbWluaW86bGF0ZXN0CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX1VSTF9NSU5JT18zMjAwCiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgY29tbWFuZDogc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSIKICAgIHZvbHVtZXM6CiAgICAgIC0gbWluaW8tZGF0YTovZGF0YQogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6IFsiQ01EIiwgImN1cmwiLCAiLWYiLCAiaHR0cDovLzEyNy4wLjAuMTozMjAwL21pbmlvL2hlYWx0aC9saXZlIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBtaW5pby1pbml0OgogICAgaW1hZ2U6IG1pbmlvL21jOmxhdGVzdAogICAgZGVwZW5kc19vbjoKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGVudmlyb25tZW50OgogICAgICAtIE1JTklPX1JPT1RfVVNFUj0ke1NFUlZJQ0VfVVNFUl9NSU5JT30KICAgICAgLSBNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30KICAgIGVudHJ5cG9pbnQ6ID4KICAgICAgL2Jpbi9zaCAtYyAiCiAgICAgIG1jIGFsaWFzIHNldCBtaW5pbyBodHRwOi8vbWluaW86MzIwMCAkJHtNSU5JT19ST09UX1VTRVJ9ICQke01JTklPX1JPT1RfUEFTU1dPUkR9OwogICAgICBtYyBtYiBtaW5pby9iMi1ldS1jZW4gLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3dhc2FiaS1ldS1jZW50cmFsLTItdjMgLS1pZ25vcmUtZXhpc3Rpbmc7CiAgICAgIG1jIG1iIG1pbmlvL3Njdy1ldS1mci12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgZWNobyAnTWluSU8gYnVja2V0cyBjcmVhdGVkIHN1Y2Nlc3NmdWxseSc7CiAgICAgICIK", + "compose": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", "tags": [ "photos", "gallery", From 4a81a96d9489be7da06b751ee14630f1657a636f Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Wed, 3 Sep 2025 14:30:45 +0530 Subject: [PATCH 013/322] Fix: Lean Config --- templates/compose/ente.yaml | 54 +++++-------------------------------- 1 file changed, 6 insertions(+), 48 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index 830c21c43..a9a2f0c59 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -33,52 +33,18 @@ services: ENTE_JWT_SECRET: ${MUSEUM_JWT_KEY} - ENTE_SMTP_HOST: ${SMTP_HOST} - ENTE_SMTP_PORT: ${SMTP_PORT} - ENTE_SMTP_USERNAME: ${SMTP_USERNAME} - ENTE_SMTP_PASSWORD: ${SMTP_PASSWORD} - ENTE_SMTP_EMAIL: ${SMTP_EMAIL} - ENTE_SMTP_SENDER_NAME: ${SMTP_SENDER_NAME} - ENTE_SMTP_ENCRYPTION: ${SMTP_ENCRYPTION} - - ENTE_TRANSMAIL_KEY: ${ENTE_TRANSMAIL_KEY} - - ENTE_APPLE_SHARED_SECRET: ${ENTE_APPLE_SHARED_SECRET} - - ENTE_STRIPE_US_KEY: ${ENTE_STRIPE_US_KEY} - ENTE_STRIPE_US_WEBHOOK_SECRET: ${ENTE_STRIPE_WEBHOOK_SECRET} - ENTE_STRIPE_IN_KEY: ${ENTE_STRIPE_US_KEY} - ENTE_STRIPE_IN_WEBHOOK_SECRET: ${ENTE_STRIPE_WEBHOOK_SECRET} - ENTE_STRIPE_WHITELISTED_REDIRECT_URLS: ${ENTE_WHITELISTED_REDIRECT_URLS} - - ENTE_WEBAUTHN_RPID: ${ENTE_WEBAUTHN_RPID:-localhost} - ENTE_WEBAUTHN_RPORIGINS: ${ENTE_WEBAUTHN_RPORIGINS:-https://localhost:3001} - ENTE_INTERNAL_SILENT: ${ENTE_INTERNAL_SILENT:-false} ENTE_INTERNAL_HEALTH_CHECK_URL: ${ENTE_INTERNAL_HEALTH_CHECK_URL} ENTE_INTERNAL_HARDCODED_OTT_EMAILS: ${ENTE_INTERNAL_HARDCODED_OTT_EMAIL} ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX} ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE} ENTE_INTERNAL_ADMINS: ${ENTE_INTERNAL_ADMINS} - ENTE_INTERNAL_ADMIN: ${ENTE_INTERNAL_ADMIN} + ENTE_INTERNAL_ADMIN: 1580559962386438 ENTE_INTERNAL_DISABLE_REGISTRATION: ${ENTE_INTERNAL_DISABLE_REGISTRATION:-false} - ENTE_REPLICATION_ENABLED: ${ENTE_REPLICATION_ENABLED:-false} - ENTE_REPLICATION_WORKER_URL: ${ENTE_REPLICATION_WORKER_URL} - ENTE_REPLICATION_WORKER_COUNT: ${ENTE_REPLICATION_WORKER_COUNT:-6} - ENTE_REPLICATION_TMP_STORAGE: ${ENTE_REPLICATION_TMP_STORAGE:-/tmp/replication} - - ENTE_JOBS_CRON_SKIP: ${ENTE_JOBS_CRON_SKIP:-false} - ENTE_JOBS_REMOVE_UNREPORTED_OBJECTS_WORKER_COUNT: ${ENTE_JOBS_REMOVE_UNREPORTED_OBJECTS_WORKER_COUNT:-1} - ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_ENABLED: ${ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_ENABLED:-false} - ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_PREFIX: ${ENTE_JOBS_CLEAR_ORPHAN_OBJECTS_PREFIX:-""} - ENTE_S3_ARE_LOCAL_BUCKETS: ${ENTE_S3_ARE_LOCAL_BUCKETS:-true} ENTE_S3_USE_PATH_STYLE_URLS: ${ENTE_S3_USE_PATH_STYLE_URLS:-true} - ENTE_S3_HOT_STORAGE_PRIMARY: ${ENTE_S3_HOT_STORAGE_PRIMARY:-b2-eu-cen} - ENTE_S3_HOT_STORAGE_SECONDARY: ${ENTE_S3_HOT_STORAGE_SECONDARY:-wasabi-eu-central-2-v3} - ENTE_S3_B2_EU_CEN_KEY: ${SERVICE_USER_MINIO} ENTE_S3_B2_EU_CEN_SECRET: ${SERVICE_PASSWORD_MINIO} ENTE_S3_B2_EU_CEN_ENDPOINT: ${SERVICE_URL_MINIO}:3200 @@ -104,19 +70,6 @@ services: ENTE_S3_SCW_EU_FR_V3_ARE_LOCAL_BUCKETS: ${COLD_STORAGE_ARE_LOCAL_BUCKETS:-true} ENTE_S3_SCW_EU_FR_V3_USE_PATH_STYLE_URLS: ${COLD_STORAGE_USE_PATH_STYLE_URLS:-true} - ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_KEY: ${SECONDARY_STORAGE_DERIVED_KEY} - ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_SECRET: ${SECONDARY_STORAGE_DERIVED_SECRET} - ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_ENDPOINT: ${SECONDARY_STORAGE_DERIVED_ENDPOINT} - ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_REGION: ${SECONDARY_STORAGE_DERIVED_REGION} - ENTE_S3_WASABI_EU_CENTRAL_2_DERIVED_BUCKET: ${SECONDARY_STORAGE_DERIVED_BUCKET} - - ENTE_S3_DERIVED_STORAGE: ${ENTE_S3_DERIVED_STORAGE:-wasabi-eu-central-2-derived} - - ENTE_S3_FILE_DATA_CONFIG_MLDATA_PRIMARY_BUCKET: ${ENTE_S3_FILE_DATA_CONFIG_MLDATA_PRIMARY_BUCKET} - ENTE_S3_FILE_DATA_CONFIG_MLDATA_REPLICA_BUCKETS: ${ENTE_S3_FILE_DATA_CONFIG_MLDATA_REPLICA_BUCKETS} - ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_PRIMARY_BUCKET: ${ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_PRIMARY_BUCKET} - ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_REPLICA_BUCKETS: ${ENTE_S3_FILE_DATA_CONFIG_IMG_PREVIEW_REPLICA_BUCKETS} - depends_on: postgres: condition: service_healthy @@ -234,3 +187,8 @@ volumes: networks: ente-network: name: ente-network + + +MUSEUM_ENCRYPTION_KEY= pWe6al9Xtp2exq4g0HKqH9+mTGsF+KIsrKBkKMf80eI= +MUSEUM_HASH_KEY= OEZIA8F71MVXAe8JxVAAmbmKbb6wyLMiGbWeWuRbCTdqRj92YfTRX0GWEIYkoSZRpWaPnCIxGpgI3AgLKJ3wEA== +MUSEUM_JWT_KEY= KzyBWIwh5vL9EflM9qeq0BsbkWMl_xI4czGFiQj7UJA= From 26c01196f70fe3911ce9e9a445f3f0921c47e09d Mon Sep 17 00:00:00 2001 From: SAHIL Date: Wed, 3 Sep 2025 21:06:56 +0530 Subject: [PATCH 014/322] Fix: Env --- templates/compose/ente.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index a9a2f0c59..a0c940f87 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -187,8 +187,3 @@ volumes: networks: ente-network: name: ente-network - - -MUSEUM_ENCRYPTION_KEY= pWe6al9Xtp2exq4g0HKqH9+mTGsF+KIsrKBkKMf80eI= -MUSEUM_HASH_KEY= OEZIA8F71MVXAe8JxVAAmbmKbb6wyLMiGbWeWuRbCTdqRj92YfTRX0GWEIYkoSZRpWaPnCIxGpgI3AgLKJ3wEA== -MUSEUM_JWT_KEY= KzyBWIwh5vL9EflM9qeq0BsbkWMl_xI4czGFiQj7UJA= From 545b6cecc712ef19d36e4a8e2fd09411663a0029 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Thu, 4 Sep 2025 12:30:23 +0000 Subject: [PATCH 015/322] docs: update changelog --- CHANGELOG.md | 12958 +++++++++++++++++++------------------------------ 1 file changed, 4912 insertions(+), 8046 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 661029f98..206dbb2e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,1254 +4,636 @@ # Changelog ## [unreleased] -### 🚜 Refactor - -- *(policy)* Simplify ServiceDatabasePolicy methods to always return true and add manageBackups method - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Update coolify version to 4.0.0-beta.426 and nightly version to 4.0.0-beta.427 - -## [4.0.0-beta.425] - 2025-08-28 - -### 🚀 Features - -- *(domains)* Implement domain conflict detection and user confirmation modal across application components -- *(domains)* Add force_domain_override option and enhance domain conflict detection responses - -### 🐛 Bug Fixes - -- *(previews)* Simplify FQDN generation logic by removing unnecessary empty check -- *(templates)* Update Matrix service compose configuration for improved compatibility and clarity - -### 🚜 Refactor - -- *(urls)* Replace generateFqdn with generateUrl for consistent URL generation across applications -- *(domains)* Rename check_domain_usage to checkDomainUsage and update references across the application -- *(auth)* Simplify access control logic in CanAccessTerminal and ServerPolicy by allowing all users to perform actions - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Update coolify version to 4.0.0-beta.425 and nightly version to 4.0.0-beta.426 - -## [4.0.0-beta.424] - 2025-08-27 - -### 🐛 Bug Fixes - -- *(parsers)* Do not modify service names, only for getting fqdns and related envs -- *(compose)* Temporary allow to edit volumes in apps (compose based) and services - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Update coolify version to 4.0.0-beta.424 and nightly version to 4.0.0-beta.425 - -## [4.0.0-beta.423] - 2025-08-27 - -### 🚜 Refactor - -- *(parsers)* Remove unnecessary hyphen-to-underscore replacement for service names in serviceParser function - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Update coolify version to 4.0.0-beta.423 and nightly version to 4.0.0-beta.424 - -## [4.0.0-beta.422] - 2025-08-27 - -### 🐛 Bug Fixes - -- *(parsers)* Replace hyphens with underscores in service names for consistency. this allows to properly parse custom domains in docker compose based applications -- *(parsers)* Implement parseDockerVolumeString function to handle various Docker volume formats and modes, including environment variables and Windows paths. Add unit tests for comprehensive coverage. -- *(git)* Submodule update command uses an unsupported option (#6454) -- *(service)* Swap URL for FQDN on matrix template (#6466) -- *(parsers)* Enhance volume string handling by preserving mode in application and service parsers. Update related unit tests for validation. -- *(docker)* Update parser version in FQDN generation for service-specific URLs - -### 🚜 Refactor - -- *(git)* Improve submodule cloning - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Update version -- Update development node version - -## [4.0.0-beta.421] - 2025-08-26 - -### 🚀 Features - -- *(policies)* Add EnvironmentVariablePolicy for managing environment variables ( it was missing ) - -### 🐛 Bug Fixes - -- *(backups)* Rollback helper update for now - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(core)* Update version -- *(versions)* Update coolify version to 4.0.0-beta.421 and nightly version to 4.0.0-beta.422 - -## [4.0.0-beta.420.9] - 2025-08-26 - -### 🐛 Bug Fixes - -- *(backups)* S3 backup upload is failing - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(core)* Update version - -## [4.0.0-beta.420.8] - 2025-08-26 - -### 🚜 Refactor - -- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.420.7] - 2025-08-26 - -### 🚀 Features - -- *(service)* Add TriliumNext service (#5970) -- *(service)* Add Matrix service (#6029) -- *(service)* Add GitHub Action runner service (#6209) -- *(terminal)* Dispatch focus event for terminal after connection and enhance focus handling in JavaScript -- *(lang)* Add Polish language & improve forgot_password translation (#6306) -- *(service)* Update Authentik template (#6264) -- *(service)* Add sequin template (#6105) -- *(service)* Add pi-hole template (#6020) -- *(services)* Add Chroma service (#6201) -- *(service)* Add OpenPanel template (#5310) -- *(service)* Add librechat template (#5654) -- *(service)* Add Homebox service (#6116) -- *(service)* Add pterodactyl & wings services (#5537) -- *(service)* Add Bluesky PDS template (#6302) -- *(input)* Add autofocus attribute to input component for improved accessibility -- *(core)* Finally fqdn is fqdn and url is url. haha -- *(user)* Add changelog read tracking and unread count method -- *(templates)* Add new service templates and update existing compose files for various applications -- *(changelog)* Implement automated changelog fetching from GitHub and enhance changelog read tracking -- *(drizzle-gateway)* Add new drizzle-gateway service with configuration and logo -- *(drizzle-gateway)* Enhance service configuration by adding Master Password field and updating compose file path -- *(templates)* Add new service templates for Homebox, LibreChat, Pterodactyl, and Wings with corresponding configurations and logos -- *(templates)* Add Bluesky PDS service template and update compose file with new environment variable -- *(readme)* Add CubePath as a big sponsor and include new small sponsors with logos -- *(api)* Add create_environment endpoint to ProjectController for environment creation in projects -- *(api)* Add endpoints for managing environments in projects, including listing, creating, and deleting environments -- *(backup)* Add disable local backup option and related logic for S3 uploads -- *(dev patches)* Add functionality to send test email with patch data in development mode -- *(templates)* Added category per service -- *(email)* Implement email change request and verification process -- Generate category for services -- *(service)* Add elasticsearch template (#6300) -- *(sanitization)* Integrate DOMPurify for HTML sanitization across components -- *(cleanup)* Add command for sanitizing name fields across models -- *(sanitization)* Enhance HTML sanitization with improved DOMPurify configuration -- *(validation)* Centralize validation patterns for names and descriptions -- *(git-settings)* Add support for shallow cloning in application settings -- *(auth)* Implement authorization checks for server updates across multiple components -- *(auth)* Implement authorization for PrivateKey management -- *(auth)* Implement authorization for Docker and server management -- *(validation)* Add custom validation rules for Git repository URLs and branches -- *(security)* Add authorization checks for package updates in Livewire components -- *(auth)* Implement authorization checks for application management -- *(auth)* Enhance API error handling for authorization exceptions -- *(auth)* Add comprehensive authorization checks for all kind of resource creations -- *(auth)* Implement authorization checks for database management -- *(auth)* Refine authorization checks for S3 storage and service management -- *(auth)* Implement comprehensive authorization checks across API controllers -- *(auth)* Introduce resource creation authorization middleware and policies for enhanced access control -- *(auth)* Add middleware for resource creation authorization -- *(auth)* Enhance authorization checks in Livewire components for resource management -- *(validation)* Add ValidIpOrCidr rule for validating IP addresses and CIDR notations; update API access settings UI and add comprehensive tests -- *(docs)* Update architecture and development guidelines; enhance form components with built-in authorization system and improve routing documentation -- *(docs)* Expand authorization documentation for custom Alpine.js components; include manual protection patterns and implementation guidelines -- *(sentinel)* Implement SentinelRestarted event and update Livewire components to handle server restart notifications -- *(api)* Enhance IP access control in middleware and settings; support CIDR notation and special case for 0.0.0.0 to allow all IPs -- *(acl)* Change views/backend code to able to use proper ACL's later on. Currently it is not enabled. -- *(docs)* Add Backlog.md guidelines and project manager backlog agent; enhance CLAUDE.md with new links for task management -- *(docs)* Add tasks for implementing Docker build caching and optimizing staging builds; include detailed acceptance criteria and implementation plans -- *(docker)* Implement Docker cleanup processing in ScheduledJobManager; refactor server task scheduling to streamline cleanup job dispatching -- *(docs)* Expand Backlog.md guidelines with comprehensive usage instructions, CLI commands, and best practices for task management to enhance project organization and collaboration - -### 🐛 Bug Fixes - -- *(service)* Triliumnext platform and link -- *(application)* Update service environment variables when generating domain for Docker Compose -- *(application)* Add option to suppress toast notifications when loading compose file -- *(git)* Tracking issue due to case sensitivity -- *(git)* Tracking issue due to case sensitivity -- *(git)* Tracking issue due to case sensitivity -- *(ui)* Delete button width on small screens (#6308) -- *(service)* Matrix entrypoint -- *(ui)* Add flex-wrap to prevent overflow on small screens (#6307) -- *(docker)* Volumes get delete when stopping a service if `Delete Unused Volumes` is activated (#6317) -- *(docker)* Cleanup always running on deletion -- *(proxy)* Remove hardcoded port 80/443 checks (#6275) -- *(service)* Update healthcheck of penpot backend container (#6272) -- *(api)* Duplicated logs in application endpoint (#6292) -- *(service)* Documenso signees always pending (#6334) -- *(api)* Update service upsert to retain name and description values if not set -- *(database)* Custom postgres configs with SSL (#6352) -- *(policy)* Update delete method to check for admin status in S3StoragePolicy -- *(container)* Sort containers alphabetically by name in ExecuteContainerCommand and update filtering in Terminal Index -- *(application)* Streamline environment variable updates for Docker Compose services and enhance FQDN generation logic -- *(constants)* Update 'Change Log' to 'Changelog' in settings dropdown -- *(constants)* Update coolify version to 4.0.0-beta.420.7 -- *(parsers)* Clarify comments and update variable checks for FQDN and URL handling -- *(terminal)* Update text color for terminal availability message and improve readability -- *(drizzle-gateway)* Remove healthcheck from drizzle-gateway compose file and update service template -- *(templates)* Should generate old SERVICE_FQDN service templates as well -- *(constants)* Update official service template URL to point to the v4.x branch for accuracy -- *(git)* Use exact refspec in ls-remote to avoid matching similarly named branches (e.g., changeset-release/main). Use refs/heads/ or provider-specific PR refs. -- *(ApplicationPreview)* Change null check to empty check for fqdn in generate_preview_fqdn method -- *(email notifications)* Enhance EmailChannel to validate team membership for recipients and handle errors gracefully -- *(service api)* Separate create and update service functionalities -- *(templates)* Added a category tag for the docs service filter -- *(application)* Clear Docker Compose specific data when switching away from dockercompose -- *(database)* Conditionally set started_at only if the database is running -- *(ui)* Handle null values in postgres metrics (#6388) -- Disable env sorting by default -- *(proxy)* Filter host network from default proxy (#6383) -- *(modal)* Enhance confirmation text handling -- *(notification)* Update unread count display and improve HTML rendering -- *(select)* Remove unnecessary sanitization for logo rendering -- *(tags)* Update tag display to limit name length and adjust styling -- *(init)* Improve error handling for deployment and template pulling processes -- *(settings-dropdown)* Adjust unread count badge size and display logic for better consistency -- *(sanitization)* Enhance DOMPurify hook to remove Alpine.js directives for improved XSS protection -- *(servercheck)* Properly check server statuses with and without Sentinel -- *(errors)* Update error pages to provide navigation options -- *(github-deploy-key)* Update background color for selected private keys in deployment key selection UI -- *(auth)* Enhance authorization checks in application management - -### 💼 Other - -- *(settings-dropdown)* Add icons to buttons for improved UI in settings dropdown -- *(ui)* Introduce task for simplifying resource operations UI by replacing boxes with dropdown selections to enhance user experience and streamline interactions - -### 🚜 Refactor - -- *(jobs)* Remove logging for ScheduledJobManager and ServerResourceManager start and completion -- *(services)* Update validation rules to be optional -- *(service)* Improve langfuse -- *(service)* Improve openpanel template -- *(service)* Improve librechat -- *(public-git-repository)* Enhance form structure and add autofocus to repository URL input -- *(public-git-repository)* Remove commented-out code for cleaner template -- *(templates)* Update service template file handling to use dynamic file name from constants -- *(parsers)* Streamline domain handling in applicationParser and improve DNS validation logic -- *(templates)* Replace SERVICE_FQDN variables with SERVICE_URL in compose files for consistency -- *(links)* Replace inline SVGs with reusable external link component for consistency and improved maintainability -- *(previews)* Improve layout and add deployment/application logs links for previews -- *(docker compose)* Remove deprecated newParser function and associated test file to streamline codebase -- *(shared helpers)* Remove unused parseServiceVolumes function to clean up codebase -- *(parsers)* Update volume parsing logic to use beforeLast and afterLast for improved accuracy -- *(validation)* Implement centralized validation patterns across components -- *(jobs)* Rename job classes to indicate deprecation status -- Update check frequency logic for cloud and self-hosted environments; streamline server task scheduling and timezone handling -- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility - -### 📚 Documentation - -- *(claude)* Clarify that artisan commands should only be run inside the "coolify" container during development -- Add AGENTS.md for project guidance and development instructions -- Update changelog -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(service)* Improve matrix service -- *(service)* Format runner service -- *(service)* Improve sequin -- *(service)* Add `NOT_SECURED` env to Postiz (#6243) -- *(service)* Improve evolution-api environment variables (#6283) -- *(service)* Update Langfuse template to v3 (#6301) -- *(core)* Remove unused argument -- *(deletion)* Rename isDeleteOperation to deleteConnectedNetworks -- *(docker)* Remove unused arguments on StopService -- *(service)* Homebox formatting -- Clarify usage of custom redis configuration (#6321) -- *(changelogs)* Add .gitignore for changelogs directory and remove outdated changelog files for May, June, and July 2025 -- *(service)* Change affine images (#6366) -- Elasticsearch URL, fromatting and add category -- Update service-templates json files -- *(docs)* Remove AGENTS.md file; enhance CLAUDE.md with detailed form authorization patterns and service configuration examples -- *(cleanup)* Remove unused GitLab view files for change, new, and show pages -- *(workflows)* Add backlog directory to build triggers for production and staging workflows -- *(config)* Disable auto_commit in backlog configuration to prevent automatic commits -- *(versions)* Update coolify version to 4.0.0-beta.420.8 and nightly version to 4.0.0-beta.420.9 in versions.json and constants.php -- *(docker)* Update soketi image version to 1.0.10 in production and Windows configurations - -### ◀️ Revert - -- *(parser)* Enhance FQDN generation logic for services and applications - -## [4.0.0-beta.420.6] - 2025-07-18 - -### 🚀 Features - -- *(service)* Enable password protection for the Wireguard Ul -- *(queues)* Improve Horizon config to reduce CPU and RAM usage (#6212) -- *(service)* Add Gowa service (#6164) -- *(container)* Add updatedSelectedContainer method to connect to non-default containers and update wire:model for improved reactivity -- *(application)* Implement environment variable updates for Docker Compose applications, including creation, updating, and deletion of SERVICE_FQDN and SERVICE_URL variables - -### 🐛 Bug Fixes - -- *(installer)* Public IPv4 link does not work -- *(composer)* Version constraint of prompts -- *(service)* Budibase secret keys (#6205) -- *(service)* Wg-easy host should be just the FQDN -- *(ui)* Search box overlaps the sidebar navigation (#6176) -- *(webhooks)* Exclude webhook routes from CSRF protection (#6200) -- *(services)* Update environment variable naming convention to use underscores instead of dashes for SERVICE_FQDN and SERVICE_URL - -### 🚜 Refactor - -- *(service)* Improve gowa -- *(previews)* Streamline preview domain generation logic in ApplicationDeploymentJob for improved clarity and maintainability -- *(services)* Simplify environment variable updates by using updateOrCreate and add cleanup for removed FQDNs - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(service)* Update Nitropage template (#6181) -- *(versions)* Update all version -- *(bump)* Update composer deps -- *(version)* Bump Coolify version to 4.0.0-beta.420.6 - -## [4.0.0-beta.420.4] - 2025-07-08 - -### 🚀 Features - -- *(scheduling)* Add command to manually run scheduled database backups and tasks with options for chunking, delays, and dry runs -- *(scheduling)* Add frequency filter option for manual execution of scheduled jobs -- *(logging)* Implement scheduled logs command and enhance backup/task scheduling with cron checks -- *(logging)* Add frequency filters for scheduled logs command to support hourly, daily, weekly, and monthly job views -- *(scheduling)* Introduce ScheduledJobManager and ServerResourceManager for enhanced job scheduling and resource management -- *(previews)* Implement soft delete and cleanup for ApplicationPreview, enhancing resource management in DeleteResourceJob - -### 🐛 Bug Fixes - -- *(service)* Update Postiz compose configuration for improved server availability -- *(install.sh)* Use IPV4_PUBLIC_IP variable in output instead of repeated curl -- *(env)* Generate literal env variables better -- *(deployment)* Update x-data initialization in deployment view for improved functionality -- *(deployment)* Enhance COOLIFY_URL and COOLIFY_FQDN variable generation for better compatibility -- *(deployment)* Improve docker-compose domain handling and environment variable generation -- *(deployment)* Refactor domain parsing and environment variable generation using Spatie URL library -- *(deployment)* Update COOLIFY_URL and COOLIFY_FQDN generation to use Spatie URL library for improved accuracy -- *(scheduling)* Change redis cleanup command frequency from hourly to weekly for better resource management -- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.5 and 4.0.0-beta.420.6 -- *(database)* Ensure internal port defaults correctly for unsupported database types in StartDatabaseProxy -- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.6 and 4.0.0-beta.420.7 -- *(scheduling)* Remove unnecessary padding from scheduled task form layout for improved UI consistency -- *(horizon)* Update queue configuration to use environment variable for dynamic queue management -- *(horizon)* Add silenced jobs -- *(application)* Sanitize service names for HTML form binding and ensure original names are stored in docker compose domains -- *(previews)* Adjust padding for rate limit message in application previews -- *(previews)* Order application previews by pull request ID in descending order -- *(previews)* Add unique wire keys for preview containers and services based on pull request ID -- *(previews)* Enhance domain generation logic for application previews, ensuring unique domains are created when none are set -- *(previews)* Refine preview domain generation for Docker Compose applications, ensuring correct method usage based on build pack type -- *(ui)* Typo on proxy request handler tooltip (#6192) -- *(backups)* Large database backups are not working (#6217) -- *(backups)* Error message if there is no exception - -### 🚜 Refactor - -- *(previews)* Streamline preview URL generation by utilizing application method -- *(application)* Adjust layout and spacing in general application view for improved UI -- *(postgresql)* Improve layout and spacing in SSL and Proxy configuration sections for better UI consistency -- *(scheduling)* Replace deprecated job checks with ScheduledJobManager and ServerResourceManager for improved scheduling efficiency -- *(previews)* Move preview domain generation logic to ApplicationPreview model for better encapsulation and consistency across webhook handlers - -### 📚 Documentation - -- Update changelog -- Update changelog - -## [4.0.0-beta.420.3] - 2025-07-03 - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.420.2] - 2025-07-03 - -### 🚀 Features - -- *(template)* Added excalidraw (#6095) -- *(template)* Add excalidraw service configuration with documentation and tags - -### 🐛 Bug Fixes - -- *(terminal)* Ensure shell execution only uses valid shell if available in terminal command -- *(ui)* Improve destination selection description for clarity in resource segregation -- *(jobs)* Update middleware to use expireAfter for WithoutOverlapping in multiple job classes -- Removing eager loading (#6071) -- *(template)* Adjust health check interval and retries for excalidraw service -- *(ui)* Env variable settings wrong order -- *(service)* Ensure configuration changes are properly tracked and dispatched - -### 🚜 Refactor - -- *(ui)* Enhance project cloning interface with improved table layout for server and resource selection -- *(terminal)* Simplify command construction for SSH execution -- *(settings)* Streamline instance admin checks and initialization of settings in Livewire components -- *(policy)* Optimize team membership checks in S3StoragePolicy -- *(popup)* Improve styling and structure of the small popup component -- *(shared)* Enhance FQDN generation logic for services in newParser function -- *(redis)* Enhance CleanupRedis command with dry-run option and improved key deletion logic -- *(init)* Standardize method naming conventions and improve command structure in Init.php -- *(shared)* Improve error handling in getTopLevelNetworks function to return network name on invalid docker-compose.yml -- *(database)* Improve error handling for unsupported database types in StartDatabaseProxy - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Bump coolify and nightly versions to 4.0.0-beta.420.3 and 4.0.0-beta.420.4 respectively -- *(versions)* Update coolify and nightly versions to 4.0.0-beta.420.4 and 4.0.0-beta.420.5 respectively - -## [4.0.0-beta.420.1] - 2025-06-26 - -### 🐛 Bug Fixes - -- *(server)* Prepend 'mux_' to UUID in muxFilename method for consistent naming -- *(ui)* Enhance terminal access messaging to clarify server functionality and terminal status -- *(database)* Proxy ssl port if ssl is enabled - -### 🚜 Refactor - -- *(ui)* Separate views for instance settings to separate paths to make it cleaner -- *(ui)* Remove unnecessary step3ButtonText attributes from modal confirmation components for cleaner code - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update Coolify versions to 4.0.0-beta.420.2 and 4.0.0-beta.420.3 in multiple files - -## [4.0.0-beta.420] - 2025-06-26 - -### 🚀 Features - -- *(service)* Add Miniflux service (#5843) -- *(service)* Add Pingvin Share service (#5969) -- *(auth)* Add Discord OAuth Provider (#5552) -- *(auth)* Add Clerk OAuth Provider (#5553) -- *(auth)* Add Zitadel OAuth Provider (#5490) -- *(core)* Set custom API rate limit (#5984) -- *(service)* Enhance service status handling and UI updates -- *(cleanup)* Add functionality to delete teams with no members or servers in CleanupStuckedResources command -- *(ui)* Add heart icon and enhance popup messaging for sponsorship support -- *(settings)* Add sponsorship popup toggle and corresponding database migration -- *(migrations)* Add optimized indexes to activity_log for improved query performance - -### 🐛 Bug Fixes - -- *(service)* Audiobookshelf healthcheck command (#5993) -- *(service)* Downgrade Evolution API phone version (#5977) -- *(service)* Pingvinshare-with-clamav -- *(ssh)* Scp requires square brackets for ipv6 (#6001) -- *(github)* Changing github app breaks the webhook. it does not anymore -- *(parser)* Improve FQDN generation and update environment variable handling -- *(ui)* Enhance status refresh buttons with loading indicators -- *(ui)* Update confirmation button text for stopping database and service -- *(routes)* Update middleware for deploy route to use 'api.ability:deploy' -- *(ui)* Refine API token creation form and update helper text for clarity -- *(ui)* Adjust layout of deployments section for improved alignment -- *(ui)* Adjust project grid layout and refine server border styling for better visibility -- *(ui)* Update border styling for consistency across components and enhance loading indicators -- *(ui)* Add padding to section headers in settings views for improved spacing -- *(ui)* Reduce gap between input fields in email settings for better alignment -- *(docker)* Conditionally enable gzip compression in Traefik labels based on configuration -- *(parser)* Enable gzip compression conditionally for Pocketbase images and streamline service creation logic -- *(ui)* Update padding for trademarks policy and enhance spacing in advanced settings section -- *(ui)* Correct closing tag for sponsorship link in layout popups -- *(ui)* Refine wording in sponsorship donation prompt in layout popups -- *(ui)* Update navbar icon color and enhance popup layout for sponsorship support -- *(ui)* Add target="_blank" to sponsorship links in layout popups for improved user experience -- *(models)* Refine comment wording in User model for clarity on user deletion criteria -- *(models)* Improve user deletion logic in User model to handle team member roles and prevent deletion if user is alone in root team -- *(ui)* Update wording in sponsorship prompt for clarity and engagement -- *(shared)* Refactor gzip handling for Pocketbase in newParser function for improved clarity - -### 🚜 Refactor - -- *(service)* Update Hoarder to their new name karakeep (#5964) -- *(service)* Karakeep naming and formatting -- *(service)* Improve miniflux -- *(core)* Rename API rate limit ENV -- *(ui)* Simplify container selection form in execute-container-command view -- *(email)* Streamline SMTP and resend settings logic for improved clarity -- *(invitation)* Rename methods for consistency and enhance invitation deletion logic -- *(user)* Streamline user deletion process and enhance team management logic - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(service)* Update Evolution API image to the official one (#6031) -- *(versions)* Bump coolify versions to v4.0.0-beta.420 and v4.0.0-beta.421 -- *(dependencies)* Update composer dependencies to latest versions including resend-laravel to ^0.19.0 and aws-sdk-php to 3.347.0 -- *(versions)* Update Coolify version to 4.0.0-beta.420.1 and add new services (karakeep, miniflux, pingvinshare) to service templates - -## [4.0.0-beta.419] - 2025-06-17 - -### 🚀 Features - -- *(core)* Add 'postmarketos' to supported OS list -- *(service)* Add memos service template (#5032) -- *(ui)* Upgrade to Tailwind v4 (#5710) -- *(service)* Add Navidrome service template (#5022) -- *(service)* Add Passbolt service (#5769) -- *(service)* Add Vert service (#5663) -- *(service)* Add Ryot service (#5232) -- *(service)* Add Marimo service (#5559) -- *(service)* Add Diun service (#5113) -- *(service)* Add Observium service (#5613) -- *(service)* Add Leantime service (#5792) -- *(service)* Add Limesurvey service (#5751) -- *(service)* Add Paymenter service (#5809) -- *(service)* Add CodiMD service (#4867) -- *(modal)* Add dispatchAction property to confirmation modal -- *(security)* Implement server patching functionality -- *(service)* Add Typesense service (#5643) -- *(service)* Add Yamtrack service (#5845) -- *(service)* Add PG Back Web service (#5079) -- *(service)* Update Maybe service and adjust it for the new release (#5795) -- *(oauth)* Set redirect uri as optional and add default value (#5760) -- *(service)* Add apache superset service (#4891) -- *(service)* Add One Time Secret service (#5650) -- *(service)* Add Seafile service (#5817) -- *(service)* Add Netbird-Client service (#5873) -- *(service)* Add OrangeHRM and Grist services (#5212) -- *(rules)* Add comprehensive documentation for Coolify architecture and development practices for AI tools, especially for cursor -- *(server)* Implement server patch check notifications -- *(api)* Add latest query param to Service restart API (#5881) -- *(api)* Add connect_to_docker_network setting to App creation API (#5691) -- *(routes)* Restrict backup download access to team admins and owners -- *(destination)* Update confirmation modal text and add persistent storage warning for server deployment -- *(terminal-access)* Implement terminal access control for servers and containers, including UI updates and backend logic -- *(ca-certificate)* Add CA certificate management functionality with UI integration and routing -- *(security-patches)* Add update check initialization and enhance notification messaging in UI -- *(previews)* Add force deploy without cache functionality and update deploy method to accept force rebuild parameter -- *(security-patterns)* Expand sensitive patterns list to include additional security-related variables -- *(database-backup)* Add MongoDB credential extraction and backup handling to DatabaseBackupJob -- *(activity-monitor)* Implement auto-scrolling functionality and dynamic content observation for improved user experience -- *(utf8-handling)* Implement UTF-8 sanitization for command outputs and enhance error handling in logs processing -- *(navbar)* Add Traefik dashboard availability check and server IP handling; refactor dynamic configurations loading -- *(proxy-dashboard)* Implement ProxyDashboardCacheService to manage Traefik dashboard cache; clear cache on configuration changes and proxy actions -- *(terminal-connection)* Enhance terminal connection handling with auto-connect feature and improved status messaging -- *(terminal)* Implement resize handling with ResizeObserver for improved terminal responsiveness -- *(migration)* Add is_sentinel_enabled column to server_settings with default true -- *(seeder)* Dispatch StartProxy action for each server in ProductionSeeder -- *(seeder)* Add CheckAndStartSentinelJob dispatch for each server in ProductionSeeder -- *(seeder)* Conditionally dispatch StartProxy action based on proxy check result -- *(service)* Update Changedetection template (#5937) - -### 🐛 Bug Fixes - -- *(constants)* Adding 'fedora-asahi-remix' as a supported OS (#5646) -- *(authentik)* Update docker-compose configuration for authentik service -- *(api)* Allow nullable destination_uuid (#5683) -- *(service)* Fix documenso startup and mail (#5737) -- *(docker)* Fix production dockerfile -- *(service)* Navidrome service -- *(service)* Passbolt -- *(service)* Add missing ENVs to NTFY service (#5629) -- *(service)* NTFY is behind a proxy -- *(service)* Vert logo and ENVs -- *(service)* Add platform to Observium service -- *(ActivityMonitor)* Prevent multiple event dispatches during polling -- *(service)* Convex ENVs and update image versions (#5827) -- *(service)* Paymenter -- *(ApplicationDeploymentJob)* Ensure correct COOLIFY_FQDN/COOLIFY_URL values (#4719) -- *(service)* Snapdrop no matching manifest error (#5849) -- *(service)* Use the same volume between chatwoot and sidekiq (#5851) -- *(api)* Validate docker_compose_raw input in ApplicationsController -- *(api)* Enhance validation for docker_compose_raw in ApplicationsController -- *(select)* Update PostgreSQL versions and titles in resource selection -- *(database)* Include DatabaseStatusChanged event in activityMonitor dispatch -- *(css)* Tailwind v5 things -- *(service)* Diun ENV for consistency -- *(service)* Memos service name -- *(css)* 8+ issue with new tailwind v4 -- *(css)* `bg-coollabs-gradient` not working anymore -- *(ui)* Add back missing service navbar components -- *(deploy)* Update resource timestamp handling in deploy_resource method -- *(patches)* DNF reboot logic is flipped -- *(deployment)* Correct syntax for else statement in docker compose build command -- *(shared)* Remove unused relation from queryDatabaseByUuidWithinTeam function -- *(deployment)* Correct COOLIFY_URL and COOLIFY_FQDN assignments based on parsing version in preview deployments -- *(docker)* Ensure correct parsing of environment variables by limiting explode to 2 parts -- *(project)* Update selected environment handling to use environment name instead of UUID -- *(ui)* Update server status display and improve server addition layout -- *(service)* Neon WS Proxy service not working on ARM64 (#5887) -- *(server)* Enhance error handling in server patch check notifications -- *(PushServerUpdateJob)* Add null checks before updating application and database statuses -- *(environment-variables)* Update label text for build variable checkboxes to improve clarity -- *(service-management)* Update service stop and restart messages for improved clarity and formatting -- *(preview-form)* Update helper text formatting in preview URL template input for better readability -- *(application-management)* Improve stop messages for application, database, and service to enhance clarity and formatting -- *(application-configuration)* Prevent access to preview deployments for deploy_key applications and update menu visibility accordingly -- *(select-component)* Handle exceptions during parameter retrieval and environment selection in the mount method -- *(previews)* Escape container names in stopContainers method to prevent shell injection vulnerabilities -- *(docker)* Add protection against empty container queries in GetContainersStatus to prevent unnecessary updates -- *(modal-confirmation)* Decode HTML entities in confirmation text to ensure proper display -- *(select-component)* Enhance user interaction by adding cursor styles and disabling selection during processing -- *(deployment-show)* Remove unnecessary fixed positioning for button container to improve layout responsiveness -- *(email-notifications)* Change notify method to notifyNow for immediate test email delivery -- *(service-templates)* Update Convex service configuration to use FQDN variables -- *(database-heading)* Simplify stop database message for clarity -- *(navbar)* Remove unnecessary x-init directive for loading proxy configuration -- *(patches)* Add padding to loading message for better visibility during update checks -- *(terminal-connection)* Improve error handling and stability for auto-connection; enhance component readiness checks and retry logic -- *(terminal)* Add unique wire:key to terminal component for improved reactivity and state management -- *(css)* Adjust utility classes in utilities.css for consistent application of Tailwind directives -- *(css)* Refine utility classes in utilities.css for proper Tailwind directive application -- *(install)* Update Docker installation script to use dynamic OS_TYPE and correct installation URL -- *(cloudflare)* Add error handling to automated Cloudflare configuration script -- *(navbar)* Add error handling for proxy status check to improve user feedback -- *(web)* Update user team retrieval method for consistent authentication handling -- *(cloudflare)* Update refresh method to correctly set Cloudflare tunnel status and improve user notification on IP address update -- *(service)* Update service template for affine and add migration service for improved deployment process -- *(supabase)* Update Supabase service images and healthcheck methods for improved reliability -- *(terminal)* Now it should work -- *(degraded-status)* Remove unnecessary whitespace in badge element for cleaner HTML -- *(routes)* Add name to security route for improved route management -- *(migration)* Update default value handling for is_sentinel_enabled column in server_settings -- *(seeder)* Conditionally dispatch CheckAndStartSentinelJob based on server's sentinel status -- *(service)* Disable healthcheck logging for Gotenberg (#6005) -- *(service)* Joplin volume name (#5930) -- *(server)* Update sentinelUpdatedAt assignment to use server's sentinel_updated_at property - -### 💼 Other - -- Add support for postmarketOS (#5608) -- *(core)* Simplify events for app/db/service status changes - -### 🚜 Refactor - -- *(service)* Observium -- *(service)* Improve leantime -- *(service)* Imporve limesurvey -- *(service)* Improve CodiMD -- *(service)* Typsense -- *(services)* Improve yamtrack -- *(service)* Improve paymenter -- *(service)* Consolidate configuration change dispatch logic and remove unused navbar component -- *(sidebar)* Simplify server patching link by removing button element -- *(slide-over)* Streamline button element and improve code readability -- *(service)* Enhance modal confirmation component with event dispatching for service stop actions -- *(slide-over)* Enhance class merging for improved component styling -- *(core)* Use property promotion -- *(service)* Improve maybe -- *(applications)* Remove unused docker compose raw decoding -- *(service)* Make TYPESENSE_API_KEY required -- *(ui)* Show toast when server does not work and on stop -- *(service)* Improve superset -- *(service)* Improve Onetimesecret -- *(service)* Improve Seafile -- *(service)* Improve orangehrm -- *(service)* Improve grist -- *(application)* Enhance application stopping logic to support multiple servers -- *(pricing-plans)* Improve label class binding for payment frequency selection -- *(error-handling)* Replace generic Exception with RuntimeException for improved error specificity -- *(error-handling)* Change Exception to RuntimeException for clearer error reporting -- *(service)* Remove informational dispatch during service stop for cleaner execution -- *(server-ui)* Improve layout and messaging in advanced settings and charts views -- *(terminal-access)* Streamline resource retrieval and enhance terminal access messaging in UI -- *(terminal)* Enhance terminal connection management and error handling, including improved reconnection logic and cleanup procedures -- *(application-deployment)* Separate handling of FAILED and CANCELLED_BY_USER statuses for clearer logic and notification -- *(jobs)* Update middleware to include job-specific identifiers for WithoutOverlapping -- *(jobs)* Modify middleware to use job-specific identifier for WithoutOverlapping -- *(environment-variables)* Remove debug logging from bulk submit handling for cleaner code -- *(environment-variables)* Simplify application build pack check in environment variable handling -- *(logs)* Adjust padding in logs view for improved layout consistency -- *(application-deployment)* Streamline post-deployment process by always dispatching container status check -- *(service-management)* Enhance container stopping logic by implementing parallel processing and removing deprecated methods -- *(activity-monitor)* Change activity property visibility and update view references for consistency -- *(activity-monitor)* Enhance layout responsiveness by adjusting class bindings and structure for better display -- *(service-management)* Update stopContainersInParallel method to enforce Server type hint for improved type safety -- *(service-management)* Rearrange docker cleanup logic in StopService to improve readability -- *(database-management)* Simplify docker cleanup logic in StopDatabase to enhance readability -- *(activity-monitor)* Consolidate activity monitoring logic and remove deprecated NewActivityMonitor component -- *(activity-monitor)* Update dispatch method to use activityMonitor instead of deprecated newActivityMonitor -- *(push-server-update)* Enhance application preview handling by incorporating pull request IDs and adding status update protections -- *(docker-compose)* Replace hardcoded Docker Compose configuration with external YAML template for improved database detection testing -- *(test-database-detection)* Rename services for clarity, add new database configurations, and update application service dependencies -- *(database-detection)* Enhance isDatabaseImage function to utilize service configuration for improved detection accuracy -- *(install-scripts)* Update Docker installation process to include manual installation fallback and improve error handling -- *(logs-view)* Update logs display for service containers with improved headings and dynamic key binding -- *(logs)* Enhance container loading logic and improve UI for logs display across various resource types -- *(cloudflare-tunnel)* Enhance layout and structure of Cloudflare Tunnel documentation and confirmation modal -- *(terminal-connection)* Streamline auto-connection logic and improve component readiness checks -- *(logs)* Remove unused methods and debug functionality from Logs.php for cleaner code -- *(remoteProcess)* Update sanitize_utf8_text function to accept nullable string parameter for improved type safety -- *(events)* Remove ProxyStarted event and associated ProxyStartedNotification listener for code cleanup -- *(navbar)* Remove unnecessary parameters from server navbar component for cleaner implementation -- *(proxy)* Remove commented-out listener and method for cleaner code structure -- *(events)* Update ProxyStatusChangedUI constructor to accept nullable teamId for improved flexibility -- *(cloudflare)* Update server retrieval method for improved query efficiency -- *(navbar)* Remove unused PHP use statement for cleaner code -- *(proxy)* Streamline proxy status handling and improve dashboard availability checks -- *(navbar)* Simplify proxy status handling and enhance loading indicators for better user experience -- *(resource-operations)* Filter out build servers from the server list and clean up commented-out code in the resource operations view -- *(execute-container-command)* Simplify connection logic and improve terminal availability checks -- *(navigation)* Remove wire:navigate directive from configuration links for cleaner HTML structure -- *(proxy)* Update StartProxy calls to use named parameter for async option -- *(clone-project)* Enhance server retrieval by including destinations and filtering out build servers -- *(ui)* Terminal -- *(ui)* Remove terminal header from execute-container-command view -- *(ui)* Remove unnecessary padding from deployment, backup, and logs sections - -### 📚 Documentation - -- Update changelog -- *(service)* Add new docs link for zipline (#5912) -- Update changelog -- Update changelog -- Update changelog - -### 🎨 Styling - -- *(css)* Update padding utility for password input and add newline in app.css -- *(css)* Refine badge utility styles in utilities.css -- *(css)* Enhance badge utility styles in utilities.css - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update coolify version to 4.0.0-beta.419 and nightly version to 4.0.0-beta.420 in configuration files -- *(service)* Rename hoarder server to karakeep (#5607) -- *(service)* Update Supabase services (#5708) -- *(service)* Remove unused documenso env -- *(service)* Formatting and cleanup of ryot -- *(docs)* Remove changelog and add it to gitignore -- *(versions)* Update version to 4.0.0-beta.419 -- *(service)* Diun formatting -- *(docs)* Update CHANGELOG.md -- *(service)* Switch convex vars -- *(service)* Pgbackweb formatting and naming update -- *(service)* Remove typesense default API key -- *(service)* Format yamtrack healthcheck -- *(core)* Remove unused function -- *(ui)* Remove unused stopEvent code -- *(service)* Remove unused env -- *(tests)* Update test environment database name and add new feature test for converting container environment variables to array -- *(service)* Update Immich service (#5886) -- *(service)* Remove unused logo -- *(api)* Update API docs -- *(dependencies)* Update package versions in composer.json and composer.lock for improved compatibility and performance -- *(dependencies)* Update package versions in package.json and package-lock.json for improved stability and features -- *(version)* Update coolify-realtime to version 1.0.9 in docker-compose and versions files -- *(version)* Update coolify version to 4.0.0-beta.420 and nightly version to 4.0.0-beta.421 -- *(service)* Changedetection remove unused code - -## [4.0.0-beta.417] - 2025-05-07 - -### 🐛 Bug Fixes - -- *(select)* Update fallback logo path to use absolute URL for improved reliability - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update coolify version to 4.0.0-beta.418 - -## [4.0.0-beta.416] - 2025-05-05 - -### 🚀 Features - -- *(migration)* Add 'is_migrated' and 'custom_type' columns to service_applications and service_databases tables -- *(backup)* Implement custom database type selection and enhance scheduled backups management -- *(README)* Add Gozunga and Macarne to sponsors list -- *(redis)* Add scheduled cleanup command for Redis keys and enhance cleanup logic - -### 🐛 Bug Fixes - -- *(service)* Graceful shutdown of old container (#5731) -- *(ServerCheck)* Enhance proxy container check to ensure it is running before proceeding -- *(applications)* Include pull_request_id in deployment queue check to prevent duplicate deployments -- *(database)* Update label for image input field to improve clarity -- *(ServerCheck)* Set default proxy status to 'exited' to handle missing container state -- *(database)* Reduce container stop timeout from 300 to 30 seconds for improved responsiveness -- *(ui)* System theming for charts (#5740) -- *(dev)* Mount points?! -- *(dev)* Proxy mount point -- *(ui)* Allow adding scheduled backups for non-migrated databases -- *(DatabaseBackupJob)* Escape PostgreSQL password in backup command (#5759) -- *(ui)* Correct closing div tag in service index view - -### 🚜 Refactor - -- *(Database)* Streamline container shutdown process and reduce timeout duration -- *(core)* Streamline container stopping process and reduce timeout duration; update related methods for consistency -- *(database)* Update DB facade usage for consistency across service files -- *(database)* Enhance application conversion logic and add existence checks for databases and applications -- *(actions)* Standardize method naming for network and configuration deletion across application and service classes -- *(logdrain)* Consolidate log drain stopping logic to reduce redundancy -- *(StandaloneMariadb)* Add type hint for destination method to improve code clarity -- *(DeleteResourceJob)* Streamline resource deletion logic and improve conditional checks for database types -- *(jobs)* Update middleware to prevent job release after expiration for CleanupInstanceStuffsJob, RestartProxyJob, and ServerCheckJob -- *(jobs)* Unify middleware configuration to prevent job release after expiration for DockerCleanupJob and PushServerUpdateJob - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(seeder)* Update git branch from 'main' to 'v4.x' for multiple examples in ApplicationSeeder -- *(versions)* Update coolify version to 4.0.0-beta.417 and nightly version to 4.0.0-beta.418 - -## [4.0.0-beta.415] - 2025-04-29 - -### 🐛 Bug Fixes - -- *(ui)* Remove required attribute from image input in service application view -- *(ui)* Change application image validation to be nullable in service application view -- *(Server)* Correct proxy path formatting for Traefik proxy type - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update coolify version to 4.0.0-beta.416 and nightly version to 4.0.0-beta.417 in configuration files; fix links in deployment view - -## [4.0.0-beta.414] - 2025-04-28 - -### 🐛 Bug Fixes - -- *(ui)* Disable livewire navigate feature (causing spam of setInterval()) - -## [4.0.0-beta.413] - 2025-04-28 - -### 💼 Other - -- Adjust Workflows for v5 (#5689) - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(workflows)* Adjust workflow for announcement - -## [4.0.0-beta.411] - 2025-04-23 - -### 🚀 Features - -- *(deployment)* Add repository_project_id handling for private GitHub apps and clean up unused Caddy label logic -- *(api)* Enhance OpenAPI specifications with token variable and additional key attributes -- *(docker)* Add HTTP Basic Authentication support and enhance hostname parsing in Docker run conversion -- *(api)* Add HTTP Basic Authentication fields to OpenAPI specifications and enhance PrivateKey model descriptions -- *(README)* Add InterviewPal sponsorship link and corresponding SVG icon - -### 🐛 Bug Fixes - -- *(backup-edit)* Conditionally enable S3 checkbox based on available validated S3 storage -- *(source)* Update no sources found message for clarity -- *(api)* Correct middleware for service update route to ensure proper permissions -- *(api)* Handle JSON response in service creation and update methods for improved error handling -- Add 201 json code to servers validate api response -- *(docker)* Ensure password hashing only occurs when HTTP Basic Authentication is enabled -- *(docker)* Enhance hostname and GPU option validation in Docker run to compose conversion -- *(terminal)* Enhance WebSocket client verification with authorized IPs in terminal server -- *(ApplicationDeploymentJob)* Ensure source is an object before checking GitHub app properties - -### 🚜 Refactor - -- *(jobs)* Comment out unused Caddy label handling in ApplicationDeploymentJob and simplify proxy path logic in Server model -- *(database)* Simplify database type checks in ServiceDatabase and enhance image validation in Docker helper -- *(shared)* Remove unused ray debugging statement from newParser function -- *(applications)* Remove redundant error response in create_env method -- *(api)* Restructure routes to include versioning and maintain existing feedback endpoint -- *(api)* Remove token variable from OpenAPI specifications for clarity -- *(environment-variables)* Remove protected variable checks from delete methods for cleaner logic -- *(http-basic-auth)* Rename 'http_basic_auth_enable' to 'http_basic_auth_enabled' across application files for consistency -- *(docker)* Remove debug statement and enhance hostname handling in Docker run conversion -- *(server)* Simplify proxy path logic and remove unnecessary conditions - -### 📚 Documentation - -- Update changelog -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update coolify version to 4.0.0-beta.411 and nightly version to 4.0.0-beta.412 in configuration files -- *(versions)* Update coolify version to 4.0.0-beta.412 and nightly version to 4.0.0-beta.413 in configuration files -- *(versions)* Update coolify version to 4.0.0-beta.413 and nightly version to 4.0.0-beta.414 in configuration files -- *(versions)* Update realtime version to 1.0.8 in versions.json -- *(versions)* Update realtime version to 1.0.8 in versions.json -- *(docker)* Update soketi image version to 1.0.8 in production configuration files -- *(versions)* Update coolify version to 4.0.0-beta.414 and nightly version to 4.0.0-beta.415 in configuration files - -## [4.0.0-beta.410] - 2025-04-18 - -### 🚀 Features - -- Add HTTP Basic Authentication -- *(readme)* Add new sponsors Supadata AI and WZ-IT to the README -- *(core)* Enable magic env variables for compose based applications - -### 🐛 Bug Fixes - -- *(application)* Append base directory to git branch URLs for improved path handling -- *(templates)* Correct casing of "denokv" to "denoKV" in service templates JSON -- *(navbar)* Update error message link to use route for environment variables navigation -- Unsend template -- Replace ports with expose -- *(templates)* Update Unsend compose configuration for improved service integration - -### 🚜 Refactor - -- *(jobs)* Update WithoutOverlapping middleware to use expireAfter for better queue management - -### 📚 Documentation - -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Bump coolify version to 4.0.0-beta.410 and update nightly version to 4.0.0-beta.411 in configuration files -- *(templates)* Update plausible and clickhouse images to latest versions and remove mail service - -## [4.0.0-beta.409] - 2025-04-16 - -### 🐛 Bug Fixes - -- *(parser)* Transform associative array labels into key=value format for better compatibility -- *(redis)* Update username and password input handling to clarify database sync requirements -- *(source)* Update connected source display to handle cases with no source connected - -### 🚜 Refactor - -- *(source)* Conditionally display connected source and change source options based on private key presence - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Bump coolify version to 4.0.0-beta.409 in configuration files - -## [4.0.0-beta.408] - 2025-04-14 - -### 🚀 Features - -- *(OpenApi)* Enhance OpenAPI specifications by adding UUID parameters for application, project, and service updates; improve deployment listing with pagination parameters; update command signature for OpenApi generation -- *(subscription)* Enhance subscription management with loading states and Stripe status checks - -### 🐛 Bug Fixes - -- *(pre-commit)* Correct input redirection for /dev/tty and add OpenAPI generation command -- *(pricing-plans)* Adjust grid class for improved layout consistency in subscription pricing plans -- *(migrations)* Make stripe_comment field nullable in subscriptions table -- *(mongodb)* Also apply custom config when SSL is enabled -- *(templates)* Correct casing of denoKV references in service templates and YAML files -- *(deployment)* Handle missing destination in deployment process to prevent errors - -### 💼 Other - -- Add missing openapi items to PrivateKey - -### 🚜 Refactor - -- *(commands)* Reorganize OpenAPI and Services generation commands into a new namespace for better structure; remove old command files -- *(Dockerfile)* Remove service generation command from the build process to streamline Dockerfile and improve build efficiency -- *(navbar-delete-team)* Simplify modal confirmation layout and enhance button styling for better user experience -- *(Server)* Remove debug logging from isReachableChanged method to clean up code and improve performance - -### 📚 Documentation - -- Update changelog -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update nightly version to 4.0.0-beta.410 -- *(pre-commit)* Remove OpenAPI generation command from pre-commit hook -- *(versions)* Update realtime version to 1.0.7 and bump dependencies in package.json - -## [4.0.0-beta.407] - 2025-04-09 - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.406] - 2025-04-05 - -### 🚀 Features - -- *(Deploy)* Add info dispatch for proxy check initiation -- *(EnvironmentVariable)* Add handling for Redis credentials in the environment variable component -- *(EnvironmentVariable)* Implement protection for critical environment variables and enhance deletion logic -- *(Application)* Add networkAliases attribute for handling network aliases as JSON or comma-separated values -- *(GithubApp)* Update default events to include 'pull_request' and streamline event handling -- *(CleanupDocker)* Add support for realtime image management in Docker cleanup process -- *(Deployment)* Enhance queue_application_deployment to handle existing deployments and return appropriate status messages -- *(SourceManagement)* Add functionality to change Git source and display current source in the application settings - -### 🐛 Bug Fixes - -- *(CheckProxy)* Update port conflict check to ensure accurate grep matching -- *(CheckProxy)* Refine port conflict detection with improved grep patterns -- *(CheckProxy)* Enhance port conflict detection by adjusting ss command for better output -- *(api)* Add back validateDataApplications (#5539) -- *(CheckProxy, Status)* Prevent proxy checks when force_stop is active; remove debug statement in General -- *(Status)* Conditionally check proxy status and refresh button based on force_stop state -- *(General)* Change redis_password property to nullable string -- *(DeployController)* Update request handling to use input method and enhance OpenAPI description for deployment endpoint - -### 💼 Other - -- Add missing UUID to openapi spec - -### 🚜 Refactor - -- *(Server)* Use data_get for safer access to settings properties in isFunctional method -- *(Application)* Rename network_aliases to custom_network_aliases across the application for clarity and consistency -- *(ApplicationDeploymentJob)* Streamline environment variable handling by introducing generate_coolify_env_variables method and consolidating logic for pull request and main branch scenarios -- *(ApplicationDeploymentJob, ApplicationDeploymentQueue)* Improve deployment status handling and log entry management with transaction support -- *(SourceManagement)* Sort sources by name and improve UI for changing Git source with better error handling -- *(Email)* Streamline SMTP and resend settings handling in copyFromInstanceSettings method -- *(Email)* Enhance error handling in SMTP and resend methods by passing context to handleError function -- *(DynamicConfigurations)* Improve handling of dynamic configuration content by ensuring fallback to empty string when content is null -- *(ServicesGenerate)* Update command signature from 'services:generate' to 'generate:services' for consistency; update Dockerfile to run service generation during build; update Odoo image version to 18 and add extra addons volume in compose configuration -- *(Dockerfile)* Streamline RUN commands for improved readability and maintainability by adding line continuations -- *(Dockerfile)* Reintroduce service generation command in the build process for consistency and ensure proper asset compilation - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Bump version to 406 -- *(versions)* Bump version to 407 and 408 for coolify and nightly -- *(versions)* Bump version to 408 for coolify and 409 for nightly - -## [4.0.0-beta.405] - 2025-04-04 - -### 🚀 Features - -- *(api)* Update OpenAPI spec for services (#5448) -- *(proxy)* Enhance proxy handling and port conflict detection - -### 🐛 Bug Fixes - -- *(api)* Used ssh keys can be deleted -- *(email)* Transactional emails not sending - -### 🚜 Refactor - -- *(CheckProxy)* Replace 'which' with 'command -v' for command availability checks - -### 📚 Documentation - -- Update changelog -- Update changelog -- Update changelog -- Update changelog -- Update changelog -- Update changelog -- Update changelog -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Bump version to 406 -- *(versions)* Bump version to 407 - -## [4.0.0-beta.404] - 2025-04-03 - -### 🚀 Features - -- *(lang)* Added Azerbaijani language updated turkish language. (#5497) -- *(lang)* Added Portuguese from Brazil language (#5500) -- *(lang)* Add Indonesian language translations (#5513) - -### 🐛 Bug Fixes - -- *(docs)* Comment out execute for now -- *(installation)* Mount the docker config -- *(installation)* Path to config file for docker login -- *(service)* Add health check to Bugsink service (#5512) -- *(email)* Emails are not sent in multiple cases -- *(deployments)* Use graceful shutdown instead of `rm` -- *(docs)* Contribute service url (#5517) -- *(proxy)* Proxy restart does not work on domain -- *(ui)* Only show copy button on https -- *(database)* Custom config for MongoDB (#5471) - -### 📚 Documentation - -- Update changelog -- Update changelog -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(service)* Remove unused code in Bugsink service -- *(versions)* Update version to 404 -- *(versions)* Bump version to 403 (#5520) -- *(versions)* Bump version to 404 - -## [4.0.0-beta.402] - 2025-04-01 - -### 🚀 Features - -- *(deployments)* Add list application deployments api route -- *(deploy)* Add pull request ID parameter to deploy endpoint -- *(api)* Add pull request ID parameter to applications endpoint -- *(api)* Add endpoints for retrieving application logs and deployments -- *(lang)* Added Norwegian language (#5280) -- *(dep)* Bump all dependencies - -### 🐛 Bug Fixes - -- Only get apps for the current team -- *(DeployController)* Cast 'pr' query parameter to integer -- *(deploy)* Validate team ID before deployment -- *(wakapi)* Typo in env variables and add some useful variables to wakapi.yaml (#5424) -- *(ui)* Instance Backup settings - -### 🚜 Refactor - -- *(dev)* Remove OpenAPI generation functionality -- *(migration)* Enhance local file volumes migration with logging - -### ⚙️ Miscellaneous Tasks - -- *(service)* Update minecraft service ENVs -- *(service)* Add more vars to infisical.yaml (#5418) -- *(service)* Add google variables to plausible.yaml (#5429) -- *(service)* Update authentik.yaml versions (#5373) -- *(core)* Remove redocs -- *(versions)* Update coolify version numbers to 4.0.0-beta.403 and 4.0.0-beta.404 - -## [4.0.0-beta.401] - 2025-03-28 - -### 📚 Documentation - -- Update changelog -- Update changelog - -## [4.0.0-beta.400] - 2025-03-27 - -### 🚀 Features - -- *(database)* Disable MongoDB SSL by default in migration -- *(database)* Add CA certificate generation for database servers -- *(application)* Add SPA configuration and update Nginx generation logic - -### 🐛 Bug Fixes - -- *(file-storage)* Double save on compose volumes -- *(parser)* Add logging support for applications in services - -### 🚜 Refactor - -- *(proxy)* Improve port availability checks with multiple methods -- *(database)* Update MongoDB SSL configuration for improved security -- *(database)* Enhance SSL configuration handling for various databases -- *(notifications)* Update Telegram button URL for staging environment -- *(models)* Remove unnecessary cloud check in isEnabled method -- *(database)* Streamline event listeners in Redis General component -- *(database)* Remove redundant database status display in MongoDB view -- *(database)* Update import statements for Auth in database components -- *(database)* Require PEM key file for SSL certificate regeneration -- *(database)* Change MySQL daemon command to MariaDB daemon -- *(nightly)* Update version numbers and enhance upgrade script -- *(versions)* Update version numbers for coolify and nightly -- *(email)* Validate team membership for email recipients -- *(shared)* Simplify deployment status check logic -- *(shared)* Add logging for running deployment jobs -- *(shared)* Enhance job status check to include 'reserved' -- *(email)* Improve error handling by passing context to handleError -- *(email)* Streamline email sending logic and improve configuration handling -- *(email)* Remove unnecessary whitespace in email sending logic -- *(email)* Allow custom email recipients in email sending logic -- *(email)* Enhance sender information formatting in email logic -- *(proxy)* Remove redundant stop call in restart method -- *(file-storage)* Add loadStorageOnServer method for improved error handling -- *(docker)* Parse and sanitize YAML compose file before encoding -- *(file-storage)* Improve layout and structure of input fields -- *(email)* Update label for test email recipient input -- *(database-backup)* Remove existing Docker container before backup upload -- *(database)* Improve decryption and deduplication of local file volumes -- *(database)* Remove debug output from volume update process - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update version numbers for coolify and nightly - -### ◀️ Revert - -- Encrypting mount and fs_path - -## [4.0.0-beta.399] - 2025-03-25 - ### 🚀 Features +- Use tags in update +- New update process (#115) +- VaultWarden service +- Www <-> non-www redirection for apps +- Www <-> non-www redirection +- Follow logs +- Generate www & non-www SSL certs +- Basic password reset form +- Scan for lock files and set right commands +- Public port range (WIP) +- Ports range +- Random subdomain for demo +- Random domain for services +- Astro buildpack +- 11ty buildpack +- Registration page +- Languagetool service +- Send version with update request +- Service secrets +- Webhooks inititate all applications with the correct branch +- Check ssl for new apps/services first +- Autodeploy pause +- Install pnpm into docker image if pnpm lock file is used +- Add PHP modules +- Use compose instead of normal docker cmd +- Be able to redeploy PRs +- Add n8n.io service +- Add update kuma service +- Ghost service +- Initial python support +- Add loading on register button +- *(dev)* Allow windows users to use pnpm dev +- MeiliSearch service +- Add abilitry to paste env files +- Wordpress on-demand SFTP +- Finalize on-demand sftp for wp +- PHP Composer support +- Working on-demand sftp to wp data +- Admin team sees everything +- Able to change service version/tag +- Basic white labeled version +- Able to modify database passwords +- Add persistent storage for services +- Multiply dockerfile locations for docker buildpack +- Testing fluentd logging driver +- Fluentbit investigation +- Initial deno support +- Deno DB migration +- Show exited containers on UI & better UX +- Query container state periodically +- Install svelte-18n and init setup +- Umami service +- Coolify auto-updater +- Autoupdater +- Select base image for buildpacks +- Hasura as a service +- Gzip compression +- Laravel buildpack is working! +- Laravel +- Fider service +- Database and services logs +- DNS check settings for SSL generation +- Cancel builds! +- Basic server usage on dashboard +- Show usage trends +- Usage on dashboard +- Custom script path for Plausible +- WP could have custom db +- Python image selection +- PageLoader +- Database + service usage +- Ability to change deployment type for nextjs +- Ability to change deployment type for nuxtjs +- Gitpod ready code(almost) +- Add Docker buildpack exposed port setting +- Custom port for git instances +- Gitpod integration +- Init moodle and separate stuffs to shared package +- Moodle init +- Remote docker engine init +- Working on remote docker engine +- Rde +- Remote docker engine +- Ipv4 and ipv6 +- Contributors +- Add arch to database +- Stop preview deployment +- Persistent storage for all services +- Cleanup clickhouse db +- Init heroku buildpacks +- Databases on ARM +- Mongodb arm support +- New dashboard +- Appwrite service +- Heroku deployments +- Deploy bots (no domains) +- Custom dns servers +- Import public repos (wip) +- Public repo deployment +- Force rebuild + env.PORT for port + public repo build +- Add GlitchTip service +- Searxng service +- *(ui)* Rework home UI and with responsive design +- New service - weblate +- Restart application +- Show elapsed time on running builds +- Github allow fual branches +- Gitlab dual branch +- Taiga +- *(routes)* Rework ui from login and register page +- Add traefik acme json to coolify container +- Database secrets +- New servers view +- Add queue reset button +- Previewapplications init +- PreviewApplications finalized +- Fluentbit +- Show remote servers +- *(layout)* Added drawer when user is in mobile +- Re-apply ui improves +- *(ui)* Improve header of pages +- *(styles)* Make header css component +- *(routes)* Improve ui for apps, databases and services logs +- Add migration button to appwrite +- Custom certificate +- Ssl cert on traefik config +- Refresh resource status on dashboard +- Ssl certificate sets custom ssl for applications +- System-wide github apps +- Cleanup unconfigured applications +- Cleanup unconfigured services and databases +- Docker compose support +- Docker compose +- Docker compose +- Monitoring by container +- Initial support for specific git commit +- Add default to latest commit and support for gitlab +- Redirect catch-all rule +- Rollback coolify +- Only show expose if no proxy conf defined in template +- Custom/private docker registries +- Use registry for building +- Docker registries working +- Custom docker compose file location in repo +- Save doNotTrackData to db +- Add default sentry +- Do not track in settings +- System wide git out of beta +- Custom previewseparator +- Sentry frontend +- Able to host static/php sites on arm +- Save application data before deploying +- SimpleDockerfile deployment +- Able to push image to docker registry +- Revert to remote image +- *(api)* Name label +- Add Openblocks icon +- Adding icon for whoogle +- *(ui)* Add libretranslate service icon +- Handle invite_only plausible analytics +- Init h2c (http2/grpc) support +- Http + h2c paralel +- Github raw icon url +- Remove svg support +- Add host path to any container +- Able to control multiplexing +- Add runRemoteCommandSync +- Github repo with deployment key +- Add persistent volumes +- Debuggable executeNow commands +- Add private gh repos +- Delete gh app +- Installation/update github apps +- Auto-deploy +- Deploy key based deployments +- Resource limits +- Long running queue with 1 hour of timeout +- Add arm build to dev +- Disk cleanup threshold by server +- Notify user of disk cleanup init +- Pricing plans ans subs +- Add s3 storages +- Init postgresql database +- Add backup notifications +- Dockerfile build pack +- Cloud +- Force password reset + waitlist +- Send internal notification to discord +- Monitor server connection +- Invite by email from waitlist +- Rolling update +- Add resend as transactional emails +- Send request in cloud +- Add discord notifications +- Public database +- Telegram topics separation +- Developer view for env variables +- Cache team settings +- Generate public key from private keys +- Able to invite more people at once +- Trial +- Dynamic trial period +- Ssh-agent instead of filesystem based ssh keys +- New container status checks +- Generate ssh key +- Sentry add email for better support +- Healthcheck for apps +- Add cloudflare tunnel support +- Services +- Image tag for services +- Container logs +- Reset root password +- Attach Coolify defined networks to services +- Delete resource command +- Multiselect removable resources +- Disable service, required version +- Basedir / monorepo initial support +- Init version of any git deployment +- Deploy private repo with ssh key +- Add email verification for cloud +- Able to deploy docker images +- Add dockerfile location +- Proxy logs on the ui +- Add custom redis conf +- Use docker login credentials from server +- Able to customize docker labels on applications +- Show if config is not applied +- Standalone mongodb +- Cloning project +- Api tokens + deploy webhook +- Start all kinds of things +- Simple search functionality +- Mysql, mariadb +- Lock environment variables +- Download local backups +- Improve deployment time by a lot +- Deployment logs fullscreen +- Service database backups +- Make service databases public +- Log drain (wip) +- Enable/disable log drain by service +- Log drainer container check +- Add docker engine support install script to rhel based systems +- Save timestamp configuration for logs +- Custom log drain endpoints +- Auto-restart tcp proxies for databases +- Execute command in container +- Autoupdate env during seed +- Disable autoupdate +- Randomly sleep between executions +- Pull latest images for services +- Custom docker compose commands +- Add environment description + able to change name +- Raw docker compose deployments +- Add www-non-www redirects to traefik +- Import backups +- Search between resources +- Move resources between projects / environments +- Clone any resource +- Shared environments +- Concurrent builds / server +- Able to deploy multiple resources with webhook +- Add PR comments +- Dashboard live deployment view +- Added manual webhook support for bitbucket +- Add initial support for custom docker run commands +- Cleanup unreachable servers +- Tags and tag deploy webhooks +- Clone to env +- Multi deployments +- Cleanup queue +- Magic for traefik redirectregex in services +- Revalidate server +- Disable gzip compression on service applications +- Save github app permission locally +- Minversion for services +- Able to add dynamic configurations from proxy dashboard +- Custom server limit +- Delay container/server jobs +- Add static ipv4 ipv6 support +- Server disabled by overflow +- Preview deployment logs +- Collect webhooks during maintenance +- Logs and execute commands with several servers +- Domains api endpoint +- Resources api endpoint +- Team api endpoint +- Add deployment details to deploy endpoint +- Add deployments api +- Experimental caddy support +- Dynamic configuration for caddy +- Reset password +- Show resources on source page +- Able to run scheduler/horizon programatically +- Change page width +- Watch paths +- Able to make rsa/ed ssh keys +- *(application)* Update submodules after git checkout +- Add amazon linux 2023 +- Upload large backups +- Edit domains easier for compose +- Able to delete configuration from server +- Configuration checker for all resources +- Allow tab in textarea +- Dynamic mux time +- Literal env variables +- Lazy load stuffs + tell user if compose based deployments have missing envs +- Can edit file/dir volumes from ui in compose based apps +- Upgrade Appwrite service template to 1.5 +- Upgrade Appwrite service template to 1.5 +- Add db name to backup notifications +- Initial datalist +- Update service contribution docs URL +- The final pricing plan, pay-as-you-go +- Add container name to network aliases in ApplicationDeploymentJob +- Add lazy loading for images in General.php and improve Docker Compose file handling in Application.php +- Experimental sentinel +- Start Sentinel on servers. +- Pull new sentinel image and restart container +- Init metrics +- Add AdminRemoveUser command to remove users from the database +- Adding new COOLIFY_ variables +- Save commit message and better view on deployments +- Toggle label escaping mechanism +- Shows the latest deployment commit + message on status +- New manual update process + remove next_channel +- Add lastDeploymentInfo and lastDeploymentLink props to breadcrumbs and status components +- Sort envs alphabetically and creation date +- Improve sorting of environment variables in the All component +- Update healthcheck test in StartMongodb action +- Add pull_request_id filter to get_last_successful_deployment method in Application model +- Add hc logs to healthchecks +- Add SerpAPI as a Github Sponsor +- Admin view for deleting users +- Scheduled task failed notification +- If the time seems too long it remains at 0s +- Improve Docker Engine start logic in ServerStatusJob +- If proxy stopped manually, it won't start back again +- Exclude_from_hc magic +- Gitea manual webhooks +- Add container logs in case the container does not start healthy +- Handle incomplete expired subscriptions in Stripe webhook +- Add more persistent storage types +- Add PHP memory limit environment variable to docker-compose.prod.yml +- Add manual update option to UpdateCoolify handle method +- Add port configuration for Vaultwarden service +- Able to change database passwords on the UI. It won't sync to the database. +- Able to add several domains to compose based previews +- Add bounty program link to bug report template +- Add titles +- Db proxy logs +- Easily redirect between www-and-non-www domains +- Add logos for new sponsors +- Add homepage template +- Update homepage.yaml with environment variables and volumes +- Spanish translation +- Cancelling a deployment will check if new could be started. +- Add supaguide logo to donations section +- Nixpacks now could reach local dbs internally +- Add Tigris logo to other/logos directory +- COOLIFY_CONTAINER_NAME predefined variable +- Charts +- Sentinel + charts +- Container metrics +- Add high priority queue +- Add metrics warning for servers without Sentinel enabled +- Add blacksmith logo to donations section +- Preselect server and destination if only one found +- More api endpoints +- Add API endpoint to update application by UUID +- Update statusnook logo filename in compose template +- Local fonts +- More API endpoints +- Bulk env update api endpoint +- Update server settings metrics history days to 7 +- New app API endpoint +- Private gh deployments through api +- Lots of api endpoints +- Api api api api api api +- Rename CloudCleanupSubs to CloudCleanupSubscriptions +- Early fraud warning webhook +- Improve internal notification message for early fraud warning webhook +- Add schema for uuid property in app update response +- Cleanup unused docker networks from proxy +- Compose parser v2 +- Display time interval for rollback images +- Add security and storage access key env to twenty template +- Add new logo for Latitude +- Enable legacy model binding in Livewire configuration +- Improve error handling in loadComposeFile method +- Add readonly labels +- Preserve git repository +- Force cleanup server +- Create/delete project endpoints +- Add patch request to projects +- Add server api endpoints +- Add branddev logo to README.md +- Update API endpoint summaries +- Update Caddy button label in proxy.blade.php +- Check custom internal name through server's applications. +- New server check job +- Delete team in cloud without subscription +- Coolify init should cleanup stuck networks in proxy +- Add manual update check functionality to settings page +- Update auto update and update check frequencies in settings +- Update Upgrade component to check for latest version of Coolify +- Improve homepage service template +- Support map fields in Directus +- Labels by proxy type +- Able to generate only the required labels for resources +- Preserve git repository with advanced file storages +- Added Windmill template +- Added Budibase template +- Add shm-size for custom docker commands +- Add custom docker container options to all databases +- Able to select different postgres database +- Add new logos for jobscollider and hostinger +- Order scheduled task executions +- Add Code Server environment variables to Service model +- Add coolify build env variables to building phase +- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid +- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid +- Update server_settings table to force docker cleanup +- Update Docker Compose file with DB_URL environment variable +- Refactor shared.php to improve environment variable handling +- Expose project description in API response +- Add elixir finetunes to the deployment job +- Make coolify full width by default +- Fully functional terminal for command center +- Custom terminal host +- Add buddy logo +- Add nullable constraint to 'fingerprint' column in private_keys table +- *(api)* Add an endpoint to execute a command +- *(api)* Add endpoint to execute a command +- Add ContainerStatusTypes enum for managing container status +- Allow specify use_build_server when creating/updating an application +- Add support for `use_build_server` in API endpoints for creating/updating applications +- Add Mixpost template +- Update resource deletion job to allow configurable options through API +- Add query parameters for deleting configurations, volumes, docker cleanup, and connected networks +- Add command to check application deployment queue +- Support Hetzner S3 +- Handle HTTPS domain in ConfigureCloudflareTunnels +- Backup all databases for mysql,mariadb,postgresql +- Restart service without pulling the latest image +- Add strapi template +- Add it-tools service template and logo +- Add homarr service tamplate and logo +- Add Argilla service configuration to Service model +- Add Invoice Ninja service configuration to Service model +- Project search on frontend +- Add ollama service with open webui and logo +- Update setType method to use slug value for type +- Refactor setType method to use slug value for type +- Refactor setType method to use slug value for type +- Add Supertokens template +- Add easyappointments service template +- Add dozzle template +- Adds forgejo service with runners +- Add Mautic 4 and 5 to service templates +- Add keycloak template +- Add onedev template +- Improve search functionality in project selection +- Add customHelper to stack-form +- Add cloudbeaver template +- Add ntfy template +- Add qbittorrent template +- Add Homebox template +- Add owncloud service and logo +- Add immich service +- Auto generate url +- Refactored to work with coolify auto env vars +- Affine service template and logo +- Add LibreTranslate template +- Open version in a new tab +- Add Transmission template +- Add transmission healhcheck +- Add zipline template +- Dify template +- Required envs +- Add EdgeDB +- Show warning if people would like to use sslip with https +- Add is shared to env variables +- Variabel sync and support shared vars +- Add notification settings to server_disk_usage +- Add coder service tamplate and logo +- Debug mode for sentinel +- Add jitsi template +- Add --gpu support for custom docker command +- Add Firefox template +- Add template for Wiki.js +- Add upgrade logs to /data/coolify/source +- Custom nginx configuration for static deployments + fix 404 redirects in nginx conf +- Check local horizon scheduler deployments +- Add internal api docs to /docs/api with auth +- Add proxy type change to create/update apis +- Add MacOS template +- Add Windows template +- *(service)* :sparkles: add mealie +- Add hex magic env var +- Add deploy-only token permission +- Able to deploy without cache on every commit +- Update private key nam with new slug as well +- Allow disabling default redirect, set status to 503 +- Add TLS configuration for default redirect in Server model +- Slack notifications +- Introduce root permission +- Able to download schedule task logs +- Migrate old email notification settings from the teams table +- Migrate old discord notification settings from the teams table +- Migrate old telegram notification settings from the teams table +- Add slack notifications to a new table +- Enable success messages again +- Use new notification stuff inside team model +- Some more notification settings and better defaults +- New email notification settings +- New shared function name `is_transactional_emails_enabled()` +- New shared notifications functions +- Email Notification Settings Model +- Telegram notification settings Model +- Discord notification settings Model +- Slack notification settings Model +- New Discord notification UI +- New Slack notification UI +- New telegram UI +- Use new notification event names +- Always sent notifications +- Scheduled task success notification +- Notification trait +- Get discord Webhook form new table +- Get Slack Webhook form new table +- Use new table or instance settings for email +- Use new place for settings and topic IDs for telegram +- Encrypt instance email settings +- Use encryption in instance settings model +- Scheduled task success and failure notifications +- Add docker cleanup success and failure notification settings columns +- UI for docker cleanup success and failure notification +- Docker cleanup email views +- Docker cleanup success and failure notification files +- Scheduled task success email +- Send new docker cleanup notifications +- :passport_control: integrate Authentik authentication with Coolify +- *(notification)* Add Pushover +- Add seeder command and configuration for database seeding +- Add new password magic env with symbols +- Add documenso service +- New ServerReachabilityChanged event +- Use new ServerReachabilityChanged event instead of isDirty +- Add infomaniak oauth +- Add server disk usage check frequency +- Add environment_uuid support and update API documentation +- Add service/resource/project labels +- Add coolify.environment label +- Add database subtype +- Migrate to new encryption options +- New encryption options +- Able to import full db backups for pg/mysql/mariadb +- Restore backup from server file +- Docker volume data cloning +- Move volume data cloning to a Job +- Volume cloning for ResourceOperations +- Remote server volume cloning +- Add horizon server details to queue +- Enhance horizon:manage command with worker restart check +- Add is_coolify_host to the server api responses +- DB migration for Backup retention +- UI for backup retention settings +- New global s3 and local backup deletion function +- Use new backup deletion functions +- Add calibre-web service +- Add actual-budget service +- Add rallly service +- Template for Gotenberg, a Docker-powered stateless API for PDF files +- Enhance import command options with additional guidance and improved checkbox label +- Purify for better sanitization +- Move docker cleanup to its own tab +- DB and Model for docker cleanup executions +- DockerCleanupExecutions relationship +- DockerCleanupDone event +- Get command and output for logs from CleanupDocker +- New sidebar menu and order +- Docker cleanup executions UI +- Add execution log to dockerCleanupJob +- Improve deployment UI +- Root user envs and seeding +- Email, username and password validation when they are set via envs +- Improved error handling and log output +- Add root user configuration variables to production environment +- Add log file check message in upgrade script for better troubleshooting +- Add root user details to install script +- *(core)* Wip version of coolify.json +- *(core)* Add SOURCE_COMMIT variable to build environment in ApplicationDeploymentJob +- *(service)* Update affine.yaml with AI environment variables (#4918) +- *(service)* Add new service Flipt (#4875) +- *(docs)* Update tech stack +- *(terminal)* Show terminal unavailable if the container does not have a shell on the global terminal UI +- *(ui)* Improve deployment UI +- *(template)* Add Open Web UI +- *(templates)* Add Open Web UI service template +- *(ui)* Update GitHub source creation advanced section label +- *(core)* Add dynamic label reset for application settings +- *(ui)* Conditionally enable advanced application settings based on label readonly status +- *(env)* Added COOLIFY_RESOURCE_UUID environment variable +- *(vite)* Add Cloudflare async script and style tag attributes +- *(meta)* Add comprehensive SEO and social media meta tags +- *(core)* Add name to default proxy configuration +- Add application api route +- Container logs +- Remove ansi color from log +- Add lines query parameter +- *(changelog)* Add git cliff for automatic changelog generation +- *(workflows)* Improve changelog generation and workflows +- *(ui)* Add periodic status checking for services +- *(deployment)* Ensure private key is stored in filesystem before deployment +- *(slack)* Show message title in notification previews (#5063) +- *(i18n)* Add Arabic translations (#4991) +- *(i18n)* Add French translations (#4992) +- *(services)* Update `service-templates.json` +- *(ui)* Add top padding to pricing plans view +- *(core)* Add error logging and cron parsing to docker/server schedules +- *(core)* Prevent using servers with existing resources as build servers +- *(ui)* Add textarea switching option in service compose editor +- *(ui)* Add wire:key to two-step confirmation settings +- *(database)* Add index to scheduled task executions for improved query performance +- *(database)* Add index to scheduled database backup executions +- *(billing)* Add Stripe past due subscription status tracking +- *(ui)* Add past due subscription warning banner - *(service)* Neon - *(migration)* Add `ssl_certificates` table and model - *(migration)* Add ssl setting to `standalone_postgresqls` table @@ -1313,4202 +695,1087 @@ ### 🚀 Features - *(notifications)* Add discord ping functionality and settings - *(user)* Implement session deletion on password reset - *(github)* Enhance repository loading and validation in applications +- *(database)* Disable MongoDB SSL by default in migration +- *(database)* Add CA certificate generation for database servers +- *(application)* Add SPA configuration and update Nginx generation logic +- *(deployments)* Add list application deployments api route +- *(deploy)* Add pull request ID parameter to deploy endpoint +- *(api)* Add pull request ID parameter to applications endpoint +- *(api)* Add endpoints for retrieving application logs and deployments +- *(lang)* Added Norwegian language (#5280) +- *(dep)* Bump all dependencies +- *(lang)* Added Azerbaijani language updated turkish language. (#5497) +- *(lang)* Added Portuguese from Brazil language (#5500) +- *(lang)* Add Indonesian language translations (#5513) +- *(api)* Update OpenAPI spec for services (#5448) +- *(proxy)* Enhance proxy handling and port conflict detection +- *(Deploy)* Add info dispatch for proxy check initiation +- *(EnvironmentVariable)* Add handling for Redis credentials in the environment variable component +- *(EnvironmentVariable)* Implement protection for critical environment variables and enhance deletion logic +- *(Application)* Add networkAliases attribute for handling network aliases as JSON or comma-separated values +- *(GithubApp)* Update default events to include 'pull_request' and streamline event handling +- *(CleanupDocker)* Add support for realtime image management in Docker cleanup process +- *(Deployment)* Enhance queue_application_deployment to handle existing deployments and return appropriate status messages +- *(SourceManagement)* Add functionality to change Git source and display current source in the application settings +- *(OpenApi)* Enhance OpenAPI specifications by adding UUID parameters for application, project, and service updates; improve deployment listing with pagination parameters; update command signature for OpenApi generation +- *(subscription)* Enhance subscription management with loading states and Stripe status checks +- Add HTTP Basic Authentication +- *(readme)* Add new sponsors Supadata AI and WZ-IT to the README +- *(core)* Enable magic env variables for compose based applications +- *(deployment)* Add repository_project_id handling for private GitHub apps and clean up unused Caddy label logic +- *(api)* Enhance OpenAPI specifications with token variable and additional key attributes +- *(docker)* Add HTTP Basic Authentication support and enhance hostname parsing in Docker run conversion +- *(api)* Add HTTP Basic Authentication fields to OpenAPI specifications and enhance PrivateKey model descriptions +- *(README)* Add InterviewPal sponsorship link and corresponding SVG icon +- *(migration)* Add 'is_migrated' and 'custom_type' columns to service_applications and service_databases tables +- *(backup)* Implement custom database type selection and enhance scheduled backups management +- *(README)* Add Gozunga and Macarne to sponsors list +- *(redis)* Add scheduled cleanup command for Redis keys and enhance cleanup logic +- *(core)* Add 'postmarketos' to supported OS list +- *(service)* Add memos service template (#5032) +- *(ui)* Upgrade to Tailwind v4 (#5710) +- *(service)* Add Navidrome service template (#5022) +- *(service)* Add Passbolt service (#5769) +- *(service)* Add Vert service (#5663) +- *(service)* Add Ryot service (#5232) +- *(service)* Add Marimo service (#5559) +- *(service)* Add Diun service (#5113) +- *(service)* Add Observium service (#5613) +- *(service)* Add Leantime service (#5792) +- *(service)* Add Limesurvey service (#5751) +- *(service)* Add Paymenter service (#5809) +- *(service)* Add CodiMD service (#4867) +- *(modal)* Add dispatchAction property to confirmation modal +- *(security)* Implement server patching functionality +- *(service)* Add Typesense service (#5643) +- *(service)* Add Yamtrack service (#5845) +- *(service)* Add PG Back Web service (#5079) +- *(service)* Update Maybe service and adjust it for the new release (#5795) +- *(oauth)* Set redirect uri as optional and add default value (#5760) +- *(service)* Add apache superset service (#4891) +- *(service)* Add One Time Secret service (#5650) +- *(service)* Add Seafile service (#5817) +- *(service)* Add Netbird-Client service (#5873) +- *(service)* Add OrangeHRM and Grist services (#5212) +- *(rules)* Add comprehensive documentation for Coolify architecture and development practices for AI tools, especially for cursor +- *(server)* Implement server patch check notifications +- *(api)* Add latest query param to Service restart API (#5881) +- *(api)* Add connect_to_docker_network setting to App creation API (#5691) +- *(routes)* Restrict backup download access to team admins and owners +- *(destination)* Update confirmation modal text and add persistent storage warning for server deployment +- *(terminal-access)* Implement terminal access control for servers and containers, including UI updates and backend logic +- *(ca-certificate)* Add CA certificate management functionality with UI integration and routing +- *(security-patches)* Add update check initialization and enhance notification messaging in UI +- *(previews)* Add force deploy without cache functionality and update deploy method to accept force rebuild parameter +- *(security-patterns)* Expand sensitive patterns list to include additional security-related variables +- *(database-backup)* Add MongoDB credential extraction and backup handling to DatabaseBackupJob +- *(activity-monitor)* Implement auto-scrolling functionality and dynamic content observation for improved user experience +- *(utf8-handling)* Implement UTF-8 sanitization for command outputs and enhance error handling in logs processing +- *(navbar)* Add Traefik dashboard availability check and server IP handling; refactor dynamic configurations loading +- *(proxy-dashboard)* Implement ProxyDashboardCacheService to manage Traefik dashboard cache; clear cache on configuration changes and proxy actions +- *(terminal-connection)* Enhance terminal connection handling with auto-connect feature and improved status messaging +- *(terminal)* Implement resize handling with ResizeObserver for improved terminal responsiveness +- *(migration)* Add is_sentinel_enabled column to server_settings with default true +- *(seeder)* Dispatch StartProxy action for each server in ProductionSeeder +- *(seeder)* Add CheckAndStartSentinelJob dispatch for each server in ProductionSeeder +- *(seeder)* Conditionally dispatch StartProxy action based on proxy check result +- *(service)* Update Changedetection template (#5937) +- *(service)* Add Miniflux service (#5843) +- *(service)* Add Pingvin Share service (#5969) +- *(auth)* Add Discord OAuth Provider (#5552) +- *(auth)* Add Clerk OAuth Provider (#5553) +- *(auth)* Add Zitadel OAuth Provider (#5490) +- *(core)* Set custom API rate limit (#5984) +- *(service)* Enhance service status handling and UI updates +- *(cleanup)* Add functionality to delete teams with no members or servers in CleanupStuckedResources command +- *(ui)* Add heart icon and enhance popup messaging for sponsorship support +- *(settings)* Add sponsorship popup toggle and corresponding database migration +- *(migrations)* Add optimized indexes to activity_log for improved query performance +- *(template)* Added excalidraw (#6095) +- *(template)* Add excalidraw service configuration with documentation and tags +- *(scheduling)* Add command to manually run scheduled database backups and tasks with options for chunking, delays, and dry runs +- *(scheduling)* Add frequency filter option for manual execution of scheduled jobs +- *(logging)* Implement scheduled logs command and enhance backup/task scheduling with cron checks +- *(logging)* Add frequency filters for scheduled logs command to support hourly, daily, weekly, and monthly job views +- *(scheduling)* Introduce ScheduledJobManager and ServerResourceManager for enhanced job scheduling and resource management +- *(previews)* Implement soft delete and cleanup for ApplicationPreview, enhancing resource management in DeleteResourceJob +- *(service)* Enable password protection for the Wireguard Ul +- *(queues)* Improve Horizon config to reduce CPU and RAM usage (#6212) +- *(service)* Add Gowa service (#6164) +- *(container)* Add updatedSelectedContainer method to connect to non-default containers and update wire:model for improved reactivity +- *(application)* Implement environment variable updates for Docker Compose applications, including creation, updating, and deletion of SERVICE_FQDN and SERVICE_URL variables +- *(service)* Add TriliumNext service (#5970) +- *(service)* Add Matrix service (#6029) +- *(service)* Add GitHub Action runner service (#6209) +- *(terminal)* Dispatch focus event for terminal after connection and enhance focus handling in JavaScript +- *(lang)* Add Polish language & improve forgot_password translation (#6306) +- *(service)* Update Authentik template (#6264) +- *(service)* Add sequin template (#6105) +- *(service)* Add pi-hole template (#6020) +- *(services)* Add Chroma service (#6201) +- *(service)* Add OpenPanel template (#5310) +- *(service)* Add librechat template (#5654) +- *(service)* Add Homebox service (#6116) +- *(service)* Add pterodactyl & wings services (#5537) +- *(service)* Add Bluesky PDS template (#6302) +- *(input)* Add autofocus attribute to input component for improved accessibility +- *(core)* Finally fqdn is fqdn and url is url. haha +- *(user)* Add changelog read tracking and unread count method +- *(templates)* Add new service templates and update existing compose files for various applications +- *(changelog)* Implement automated changelog fetching from GitHub and enhance changelog read tracking +- *(drizzle-gateway)* Add new drizzle-gateway service with configuration and logo +- *(drizzle-gateway)* Enhance service configuration by adding Master Password field and updating compose file path +- *(templates)* Add new service templates for Homebox, LibreChat, Pterodactyl, and Wings with corresponding configurations and logos +- *(templates)* Add Bluesky PDS service template and update compose file with new environment variable +- *(readme)* Add CubePath as a big sponsor and include new small sponsors with logos +- *(api)* Add create_environment endpoint to ProjectController for environment creation in projects +- *(api)* Add endpoints for managing environments in projects, including listing, creating, and deleting environments +- *(backup)* Add disable local backup option and related logic for S3 uploads +- *(dev patches)* Add functionality to send test email with patch data in development mode +- *(templates)* Added category per service +- *(email)* Implement email change request and verification process +- Generate category for services +- *(service)* Add elasticsearch template (#6300) +- *(sanitization)* Integrate DOMPurify for HTML sanitization across components +- *(cleanup)* Add command for sanitizing name fields across models +- *(sanitization)* Enhance HTML sanitization with improved DOMPurify configuration +- *(validation)* Centralize validation patterns for names and descriptions +- *(git-settings)* Add support for shallow cloning in application settings +- *(auth)* Implement authorization checks for server updates across multiple components +- *(auth)* Implement authorization for PrivateKey management +- *(auth)* Implement authorization for Docker and server management +- *(validation)* Add custom validation rules for Git repository URLs and branches +- *(security)* Add authorization checks for package updates in Livewire components +- *(auth)* Implement authorization checks for application management +- *(auth)* Enhance API error handling for authorization exceptions +- *(auth)* Add comprehensive authorization checks for all kind of resource creations +- *(auth)* Implement authorization checks for database management +- *(auth)* Refine authorization checks for S3 storage and service management +- *(auth)* Implement comprehensive authorization checks across API controllers +- *(auth)* Introduce resource creation authorization middleware and policies for enhanced access control +- *(auth)* Add middleware for resource creation authorization +- *(auth)* Enhance authorization checks in Livewire components for resource management +- *(validation)* Add ValidIpOrCidr rule for validating IP addresses and CIDR notations; update API access settings UI and add comprehensive tests +- *(docs)* Update architecture and development guidelines; enhance form components with built-in authorization system and improve routing documentation +- *(docs)* Expand authorization documentation for custom Alpine.js components; include manual protection patterns and implementation guidelines +- *(sentinel)* Implement SentinelRestarted event and update Livewire components to handle server restart notifications +- *(api)* Enhance IP access control in middleware and settings; support CIDR notation and special case for 0.0.0.0 to allow all IPs +- *(acl)* Change views/backend code to able to use proper ACL's later on. Currently it is not enabled. +- *(docs)* Add Backlog.md guidelines and project manager backlog agent; enhance CLAUDE.md with new links for task management +- *(docs)* Add tasks for implementing Docker build caching and optimizing staging builds; include detailed acceptance criteria and implementation plans +- *(docker)* Implement Docker cleanup processing in ScheduledJobManager; refactor server task scheduling to streamline cleanup job dispatching +- *(docs)* Expand Backlog.md guidelines with comprehensive usage instructions, CLI commands, and best practices for task management to enhance project organization and collaboration +- *(policies)* Add EnvironmentVariablePolicy for managing environment variables ( it was missing ) +- *(domains)* Implement domain conflict detection and user confirmation modal across application components +- *(domains)* Add force_domain_override option and enhance domain conflict detection responses ### 🐛 Bug Fixes -- *(api)* Docker compose based apps creationg through api -- *(database)* Improve database type detection for Supabase Postgres images -- *(ssl)* Permission of ssl crt and key inside the container -- *(ui)* Make sure file mounts do not showing the encrypted values -- *(ssl)* Make default ssl mode require not verify-full as it does not need a ca cert -- *(ui)* Select component should not always uses title case -- *(db)* SSL certificates table and model -- *(migration)* Ssl certificates table -- *(databases)* Fix database name users new `uuid` instead of DB one -- *(database)* Fix volume and file mounts and naming -- *(migration)* Store subjectAlternativeNames as a json array in the db -- *(ssl)* Make sure the subjectAlternativeNames are unique and stored correctly -- *(ui)* Certificate expiration data is null before starting the DB -- *(deletion)* Fix DB deletion -- *(ssl)* Improve SSL cert file mounts -- *(ssl)* Always create ca crt on disk even if it is already there -- *(ssl)* Use mountPath parameter not a hardcoded path -- *(ssl)* Use 1 instead of on for mysql -- *(ssl)* Do not remove SSL directory -- *(ssl)* Wrong ssl cert is loaded to the server and UI error when regenerating SSL -- *(ssl)* Make sure when regenerating the CA cert it is not overwritten with a server cert -- *(ssl)* Regenerating certs for a specific DB -- *(ssl)* Fix MariaDB and MySQL need CA cert -- *(ssl)* Add mount path to DB to fix regeneration of certs -- *(ssl)* Fix SSL regeneration to sign with CA cert and use mount path -- *(ssl)* Get caCert correctly -- *(ssl)* Remove caCert even if it is a folder by accident -- *(ssl)* Ger caCert and `mountPath` correctly -- *(ui)* Only show Regenerate SSL Certificates button when there is a cert -- *(ssl)* Server id -- *(ssl)* When regenerating SSL certs the cert is not singed with the new CN -- *(ssl)* Adjust ca paths for MySQL -- *(ssl)* Remove mode selection for MariaDB as it is not supported -- *(ssl)* Permission issue with MariDB cert and key and paths -- *(ssl)* Rename Redis mode to verify-ca as it is not verify-full -- *(ui)* Remove unused mode for MongoDB -- *(ssl)* KeyDB port and caCert args are missing -- *(ui)* Enable SSL is not working correctly for KeyDB -- *(ssl)* Add `--tls` arg to DrangflyDB -- *(notification)* Always send SSL notifications -- *(database)* Change default value of enable_ssl to false for multiple tables -- *(ui)* Correct grammatical error in 404 page -- *(seeder)* Update GitHub app name in GithubAppSeeder -- *(plane)* Update APP_RELEASE to v0.25.2 in environment configuration -- *(domain)* Dispatch refreshStatus event after successful domain update -- *(database)* Correct container name generation for service databases -- *(database)* Limit container name length for database proxy -- *(database)* Handle unsupported database types in StartDatabaseProxy -- *(database)* Simplify container name generation in StartDatabaseProxy -- *(install)* Handle potential errors in Docker address pool configuration -- *(backups)* Retention settings -- *(redis)* Set default redis_username for new instances -- *(core)* Improve instantSave logic and error handling -- *(general)* Correct link to framework specific documentation -- *(core)* Redirect healthcheck route for dockercompose applications -- *(api)* Use name from request payload -- *(issue#4746)* Do not use setGitImportSettings inside of generateGitLsRemoteCommands -- Correct some spellings -- *(service)* Replace deprecated credentials env variables on keycloak service -- *(keycloak)* Update keycloak image version to 26.1 -- *(console)* Handle missing root user in password reset command -- *(ssl)* Handle missing CA certificate in SSL regeneration job -- *(copy-button)* Ensure text is safely passed to clipboard - -### 💼 Other - -- Bump Coolify to 4.0.0-beta.400 -- *(migration)* Add SSL fields to database tables -- SSL Support for KeyDB - -### 🚜 Refactor - -- *(ui)* Unhide log toggle in application settings -- *(nginx)* Streamline default Nginx configuration and improve error handling -- *(install)* Clean up install script and enhance Docker installation logic -- *(ScheduledTask)* Clean up code formatting and remove unused import -- *(app)* Remove unused MagicBar component and related code -- *(database)* Streamline SSL configuration handling across database types -- *(application)* Streamline healthcheck parsing from Dockerfile -- *(notifications)* Standardize getRecipients method signatures -- *(configuration)* Centralize configuration management in ConfigurationRepository -- *(docker)* Update image references to use centralized registry URL -- *(env)* Add centralized registry URL to environment configuration -- *(storage)* Simplify file storage iteration in Blade template -- *(models)* Add is_directory attribute to LocalFileVolume model -- *(modal)* Add ignoreWire attribute to modal-confirmation component -- *(invite-link)* Adjust layout for better responsiveness in form -- *(invite-link)* Enhance form layout for improved responsiveness -- *(network)* Enhance docker network creation with ipv6 fallback -- *(network)* Check for existing coolify network before creation -- *(database)* Enhance encryption process for local file volumes - -### 📚 Documentation - -- Update changelog -- Update changelog -- *(CONTRIBUTING)* Add note about Laravel Horizon accessibility -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(migration)* Remove unused columns -- *(ssl)* Improve code in ssl helper -- *(migration)* Ssl cert and key should not be nullable -- *(ssl)* Rename CA cert to `coolify-ca.crt` because of conflicts -- Rename ca crt folder to ssl -- *(ui)* Improve valid until handling -- Improve code quality suggested by code rabbit -- *(supabase)* Update Supabase service template and Postgres image version -- *(versions)* Update version numbers for coolify and nightly - -## [4.0.0-beta.398] - 2025-03-01 - -### 🚀 Features - -- *(billing)* Add Stripe past due subscription status tracking -- *(ui)* Add past due subscription warning banner - -### 🐛 Bug Fixes - -- *(billing)* Restrict Stripe subscription status update to 'active' only - -### 💼 Other - -- Bump Coolify to 4.0.0-beta.398 - -### 🚜 Refactor - -- *(billing)* Enhance Stripe subscription status handling and notifications - -## [4.0.0-beta.397] - 2025-02-28 - -### 🐛 Bug Fixes - -- *(billing)* Handle 'past_due' subscription status in Stripe processing -- *(revert)* Label parsing -- *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.396] - 2025-02-28 - -### 🚀 Features - -- *(ui)* Add wire:key to two-step confirmation settings -- *(database)* Add index to scheduled task executions for improved query performance -- *(database)* Add index to scheduled database backup executions - -### 🐛 Bug Fixes - -- *(core)* Production dockerfile -- *(ui)* Update storage configuration guidance link -- *(ui)* Set default SMTP encryption to starttls -- *(notifications)* Correct environment URL path in application notifications -- *(config)* Update default PostgreSQL host to coolify-db instead of postgres -- *(docker)* Improve Docker compose file validation process -- *(ui)* Restrict service retrieval to current team -- *(core)* Only validate custom compose files -- *(mail)* Set default mailer to array when not specified -- *(ui)* Correct redirect routes after task deletion -- *(core)* Adding a new server should not try to make the default docker network -- *(core)* Clean up unnecessary files during application image build -- *(core)* Improve label generation and merging for applications and services - -### 💼 Other - -- Bump all dependencies (#5216) - -### 🚜 Refactor - -- *(ui)* Simplify file storage modal confirmations -- *(notifications)* Improve transactional email settings handling -- *(scheduled-tasks)* Improve scheduled task creation and management - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Bump helper and realtime version - -## [4.0.0-beta.395] - 2025-02-22 - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.394] - 2025-02-17 - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.393] - 2025-02-15 - -### 📚 Documentation - -- Update changelog - -## [4.0.0-beta.392] - 2025-02-13 - -### 🚀 Features - -- *(ui)* Add top padding to pricing plans view -- *(core)* Add error logging and cron parsing to docker/server schedules -- *(core)* Prevent using servers with existing resources as build servers -- *(ui)* Add textarea switching option in service compose editor - -### 🐛 Bug Fixes - -- Pull latest image from registry when using build server -- *(deployment)* Improve server selection for deployment cancellation -- *(deployment)* Improve log line rendering and formatting -- *(s3-storage)* Optimize team admin notification query -- *(core)* Improve connection testing with dynamic disk configuration for s3 backups -- *(core)* Update service status refresh event handling -- *(ui)* Adjust polling intervals for database and service status checks -- *(service)* Update Fider service template healthcheck command -- *(core)* Improve server selection error handling in Docker component -- *(core)* Add server functionality check before dispatching container status -- *(ui)* Disable sticky scroll in Monaco editor -- *(ui)* Add literal and multiline env support to services. -- *(services)* Owncloud docs link -- *(template)* Remove db-migration step from `infisical.yaml` (#5209) -- *(service)* Penpot (#5047) - -### 🚜 Refactor - -- Use pull flag on docker compose up - -### 📚 Documentation - -- Update changelog -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- Rollback Coolify version to 4.0.0-beta.392 -- Bump Coolify version to 4.0.0-beta.393 -- Bump Coolify version to 4.0.0-beta.394 -- Bump Coolify version to 4.0.0-beta.395 -- Bump Coolify version to 4.0.0-beta.396 -- *(services)* Update zipline to use new Database env var. (#5210) -- *(service)* Upgrade authentik service -- *(service)* Remove unused env from zipline - -## [4.0.0-beta.391] - 2025-02-04 - -### 🚀 Features - -- Add application api route -- Container logs -- Remove ansi color from log -- Add lines query parameter -- *(changelog)* Add git cliff for automatic changelog generation -- *(workflows)* Improve changelog generation and workflows -- *(ui)* Add periodic status checking for services -- *(deployment)* Ensure private key is stored in filesystem before deployment -- *(slack)* Show message title in notification previews (#5063) -- *(i18n)* Add Arabic translations (#4991) -- *(i18n)* Add French translations (#4992) -- *(services)* Update `service-templates.json` - -### 🐛 Bug Fixes - -- *(core)* Improve deployment failure Slack notification formatting -- *(core)* Update Slack notification formatting to use bold correctly -- *(core)* Enhance Slack deployment success notification formatting -- *(ui)* Simplify service templates loading logic -- *(ui)* Align title and add button vertically in various views -- Handle pullrequest:updated for reliable preview deployments -- *(ui)* Fix typo on team page (#5105) -- Cal.com documentation link give 404 (#5070) -- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071) -- *(ui)* Correct typo in Storage delete dialog (#5061) -- *(lang)* Add missing italian translations (#5057) -- *(service)* Improve duplicati.yaml (#4971) -- *(service)* Links in homepage service (#5002) -- *(service)* Added SMTP credentials to getoutline yaml template file (#5011) -- *(service)* Added `KEY` Variable to Beszel Template (#5021) -- *(cloudflare-tunnels)* Dead links to docs (#5104) -- System-wide GitHub apps (#5114) - -### 🚜 Refactor - -- Simplify service start and restart workflows - -### 📚 Documentation - -- *(services)* Reword nitropage url and slogan -- *(readme)* Add Convex to special sponsors section -- Update changelog - -### ⚙️ Miscellaneous Tasks - -- *(config)* Increase default PHP memory limit to 256M -- Add openapi response -- *(workflows)* Make naming more clear and remove unused code -- Bump Coolify version to 4.0.0-beta.392/393 -- *(ci)* Update changelog generation workflow to target 'next' branch -- *(ci)* Update changelog generation workflow to target main branch - -## [4.0.0-beta.390] - 2025-01-28 - -### 🚀 Features - -- *(template)* Add Open Web UI -- *(templates)* Add Open Web UI service template -- *(ui)* Update GitHub source creation advanced section label -- *(core)* Add dynamic label reset for application settings -- *(ui)* Conditionally enable advanced application settings based on label readonly status -- *(env)* Added COOLIFY_RESOURCE_UUID environment variable -- *(vite)* Add Cloudflare async script and style tag attributes -- *(meta)* Add comprehensive SEO and social media meta tags -- *(core)* Add name to default proxy configuration - -### 🐛 Bug Fixes - -- *(ui)* Update database control UI to check server functionality before displaying actions -- *(ui)* Typo in upgrade message -- *(ui)* Cloudflare tunnel configuration should be an info, not a warning -- *(s3)* DigitalOcean storage buckets do not work -- *(ui)* Correct typo in container label helper text -- Disable certain parts if readonly label is turned off -- Cleanup old scheduled_task_executions -- Validate cron expression in Scheduled Task update -- *(core)* Check cron expression on save -- *(database)* Detect more postgres database image types -- *(templates)* Update service templates -- Remove quotes in COOLIFY_CONTAINER_NAME -- *(templates)* Update Trigger.dev service templates with v3 configuration -- *(database)* Adjust MongoDB restore command and import view styling -- *(core)* Improve public repository URL parsing for branch and base directory -- *(core)* Increase HTTP/2 max concurrent streams to 250 (default) -- *(ui)* Update docker compose file helper text to clarify repository modification -- *(ui)* Skip SERVICE_FQDN and SERVICE_URL variables during update -- *(core)* Stopping database is not disabling db proxy -- *(core)* Remove --remove-orphans flag from proxy startup command to prevent other proxy deletions (db) -- *(api)* Domain check when updating domain -- *(ui)* Always redirect to dashboard after team switch -- *(backup)* Escape special characters in database backup commands - -### 💼 Other - -- Trigger.dev templates - wrong key length issue -- Trigger.dev template - missing ports and wrong env usage -- Trigger.dev template - fixed otel config -- Trigger.dev template - fixed otel config -- Trigger.dev template - fixed port config - -### 🚜 Refactor - -- *(s3)* Improve S3 bucket endpoint formatting -- *(vite)* Improve environment variable handling in Vite configuration -- *(ui)* Simplify GitHub App registration UI and layout - -### ⚙️ Miscellaneous Tasks - -- *(version)* Bump Coolify version to 4.0.0-beta.391 - -### ◀️ Revert - -- Remove Cloudflare async tag attributes - -## [4.0.0-beta.389] - 2025-01-23 - -### 🚀 Features - -- *(docs)* Update tech stack -- *(terminal)* Show terminal unavailable if the container does not have a shell on the global terminal UI -- *(ui)* Improve deployment UI - -### 🐛 Bug Fixes - -- *(service)* Infinite loading and lag with invoiceninja service (#4876) -- *(service)* Invoiceninja service -- *(workflows)* `Waiting for changes` label should also be considered and improved messages -- *(workflows)* Remove tags only if the PR has been merged into the main branch -- *(terminal)* Terminal shows that it is not available, even though it is -- *(labels)* Docker labels do not generated correctly -- *(helper)* Downgrade Nixpacks to v1.29.0 -- *(labels)* Generate labels when they are empty not when they are already generated -- *(storage)* Hetzner storage buckets not working - -### 📚 Documentation - -- Add TECH_STACK.md (#4883) - -### ⚙️ Miscellaneous Tasks - -- *(versions)* Update coolify versions to v4.0.0-beta.389 -- *(core)* EnvironmentVariable Model now extends BaseModel to remove duplicated code -- *(versions)* Update coolify versions to v4.0.0-beta.3909 - -## [4.0.0-beta.388] - 2025-01-22 - -### 🚀 Features - -- *(core)* Add SOURCE_COMMIT variable to build environment in ApplicationDeploymentJob -- *(service)* Update affine.yaml with AI environment variables (#4918) -- *(service)* Add new service Flipt (#4875) - -### 🐛 Bug Fixes - -- *(core)* Update environment variable generation logic in ApplicationDeploymentJob to handle different build packs -- *(env)* Shared variables can not be updated -- *(ui)* Metrics stuck in loading state -- *(ui)* Use `wire:navigate` to navigate to the server settings page -- *(service)* Plunk API & health check endpoint (#4925) - -## [4.0.0-beta.386] - 2025-01-22 - -### 🐛 Bug Fixes - -- *(redis)* Update environment variable keys from standalone_redis_id to resourceable_id -- *(routes)* Local API docs not available on domain or IP -- *(routes)* Local API docs not available on domain or IP -- *(core)* Update application_id references to resourable_id and resourable_type for Nixpacks configuration -- *(core)* Correct spelling of 'resourable' to 'resourceable' in Nixpacks configuration for ApplicationDeploymentJob -- *(ui)* Traefik dashboard url not working -- *(ui)* Proxy status badge flashing during navigation - -### 🚜 Refactor - -- *(workflows)* Replace jq with PHP script for version retrieval in workflows - -### ⚙️ Miscellaneous Tasks - -- *(dep)* Bump helper version to 1.0.5 -- *(docker)* Add blank line for readability in Dockerfile -- *(versions)* Update coolify versions to v4.0.0-beta.388 -- *(versions)* Update coolify versions to v4.0.0-beta.389 and add helper version retrieval script - -## [4.0.0-beta.385] - 2025-01-21 - -### 🚀 Features - -- *(core)* Wip version of coolify.json - -### 🐛 Bug Fixes - -- *(email)* Transactional email sending -- *(ui)* Add missing save button for new Docker Cleanup page -- *(ui)* Show preview deployment environment variables -- *(ui)* Show error on terminal if container has no shell (bash/sh) -- *(parser)* Resource URL should only be parsed if there is one -- *(core)* Compose parsing for apps - -### ⚙️ Miscellaneous Tasks - -- *(dep)* Bump nixpacks version -- *(dep)* Version++ - -## [4.0.0-beta.384] - 2025-01-21 - -### 🐛 Bug Fixes - -- *(ui)* Backups link should not redirected to general -- Envs with special chars during build -- *(db)* `finished_at` timestamps are not set for existing deployments -- Load service templates on cloud - -## [4.0.0-beta.383] - 2025-01-20 - -### 🐛 Bug Fixes - -- *(service)* Add healthcheck to Cloudflared service (#4859) -- Remove wire:navigate from import backups - -## [4.0.0-beta.382] - 2025-01-17 - -### 🚀 Features - -- Add log file check message in upgrade script for better troubleshooting -- Add root user details to install script - -### 🐛 Bug Fixes - -- Create the private key before the server in the prod seeder -- Update ProductionSeeder to check for private key instead of server's private key -- *(ui)* Missing underline for docs link in the Swarm section (#4860) -- *(service)* Change chatwoot service postgres image from `postgres:12` to `pgvector/pgvector:pg12` -- Docker image parser -- Add public key attribute to privatekey model -- Correct service update logic in Docker Compose parser -- Update CDN URL in install script to point to nightly version - -### 🚜 Refactor - -- Comment out RootUserSeeder call in ProductionSeeder for clarity -- Streamline ProductionSeeder by removing debug logs and unnecessary checks, while ensuring essential seeding operations remain intact -- Remove debug echo statements from Init command to clean up output and improve readability - -## [4.0.0-beta.381] - 2025-01-17 - -### 🚀 Features - -- Able to import full db backups for pg/mysql/mariadb -- Restore backup from server file -- Docker volume data cloning -- Move volume data cloning to a Job -- Volume cloning for ResourceOperations -- Remote server volume cloning -- Add horizon server details to queue -- Enhance horizon:manage command with worker restart check -- Add is_coolify_host to the server api responses -- DB migration for Backup retention -- UI for backup retention settings -- New global s3 and local backup deletion function -- Use new backup deletion functions -- Add calibre-web service -- Add actual-budget service -- Add rallly service -- Template for Gotenberg, a Docker-powered stateless API for PDF files -- Enhance import command options with additional guidance and improved checkbox label -- Purify for better sanitization -- Move docker cleanup to its own tab -- DB and Model for docker cleanup executions -- DockerCleanupExecutions relationship -- DockerCleanupDone event -- Get command and output for logs from CleanupDocker -- New sidebar menu and order -- Docker cleanup executions UI -- Add execution log to dockerCleanupJob -- Improve deployment UI -- Root user envs and seeding -- Email, username and password validation when they are set via envs -- Improved error handling and log output -- Add root user configuration variables to production environment - -### 🐛 Bug Fixes - -- Compose envs -- Scheduled tasks and backups are executed by server timezone. -- Show backup timezone on the UI -- Disappearing UI after livewire event received -- Add default vector db for anythingllm -- We need XSRF-TOKEN for terminal -- Prevent default link behavior for resource and settings actions in dashboard -- Increase default php memory limit -- Show if only build servers are added to your team -- Update Livewire button click method to use camelCase -- Local dropzonejs -- Import backups due to js stuff should not be navigated -- Install inetutils on Arch Linux -- Use ip in place of hostname from inetutils in arch -- Update import command to append file redirection for database restoration -- Ui bug on pw confirmation -- Exclude system and computed fields from model replication -- Service cloning on a separate server -- Application cloning -- `Undefined variable $fs_path` for databases -- Service and database cloning and label generation -- Labels and URL generation when cloning -- Clone naming for different database data volumes -- Implement all the cloneMe changes for ResourceOperations as well -- Volume and fileStorages cloning -- View text and helpers -- Teable -- Trigger with external db -- Set `EXPERIMENTAL_FEATURES` to false for labelstudio -- Monaco editor disabled state -- Edge case where executions could be null -- Create destination properly -- Getcontainer status should timeout after 30s -- Enable response for temporary unavailability in sentinel push endpoint -- Use timeout in cleanup resources -- Add timeout to sentinel process checks for improved reliability -- Horizon job checker -- Update response message for sentinel push route -- Add own servers on cloud -- Application deployment -- Service update statsu -- If $SERVICE found in the service specific configuration, then search for it in the db -- Instance wide GitHub apps are not available on other teams then the source team -- Function calls -- UI -- Deletion of single backup -- Backup job deletion - delete all backups from s3 and local -- Use new removeOldBackups function -- Retention functions and folder deletion for local backups -- Storage retention setting -- Db without s3 should still backup -- Wording -- `Undefined variable $service` when creating a new service -- Nodebb service -- Calibre-web service -- Rallly and actualbudget service -- Removed container_name -- Added healthcheck for gotenberg template -- Gotenberg -- *(template)* Gotenberg healthcheck, use /health instead of /version -- Use wire:navigate on sidebar -- Use wire:navigate on dashboard -- Use wire:navigate on projects page -- More wire:navigate -- Even more wire:navigate -- Service navigation -- Logs icons everywhere + terminal -- Redis DB should use the new resourceable columns -- Joomla service -- Add back letters to prod password requirement -- Check System and GitHub time and throw and error if it is over 50s out of sync -- Error message and server time getting -- Error rendering -- Render html correctly now -- Indent -- Potential fix for permissions update -- Expiration time claim ('exp') must be a numeric value -- Sanitize html error messages -- Production password rule and cleanup code -- Use json as it is just better than string for huge amount of logs -- Use `wire:navigate` on server sidebar -- Use finished_at for the end time instead of created_at -- Cancelled deployments should not show end and duration time -- Redirect to server index instead of show on error in Advanced and DockerCleanup components -- Disable registration after creating the root user -- RootUserSeeder -- Regex username validation -- Add spacing around echo outputs -- Success message -- Silent return if envs are empty or not set. - -### 💼 Other - -- Arrrrr -- Dep -- Docker dep - -### 🚜 Refactor - -- Rename parameter in DatabaseBackupJob for clarity -- Improve checkbox component accessibility and styling -- Remove unused tags method from ApplicationDeploymentJob -- Improve deployment status check in isAnyDeploymentInprogress function -- Extend HorizonServiceProvider from HorizonApplicationServiceProvider -- Streamline job status retrieval and clean up repository interface -- Enhance ApplicationDeploymentJob and HorizonServiceProvider for improved job handling -- Remove commented-out unsubscribe route from API -- Update redirect calls to use a consistent navigation method in deployment functions -- AppServiceProvider -- Github.php -- Improve data formatting and UI - -### ⚙️ Miscellaneous Tasks - -- Improve Penpot healthchecks -- Switch up readonly lables to make more sense -- Remove unused computed fields -- Use the new job dispatch -- Disable volume data cloning for now -- Improve code -- Lowcoder service naming -- Use new functions -- Improve error styling -- Css -- More css as it still looks like shit -- Final css touches -- Ajust time to 50s (tests done) -- Remove debug log, finally found it -- Remove more logging -- Remove limit on commit message -- Remove dayjs -- Remove unused code and fix import - -## [4.0.0-beta.380] - 2024-12-27 - -### 🚀 Features - -- New ServerReachabilityChanged event -- Use new ServerReachabilityChanged event instead of isDirty -- Add infomaniak oauth -- Add server disk usage check frequency -- Add environment_uuid support and update API documentation -- Add service/resource/project labels -- Add coolify.environment label -- Add database subtype -- Migrate to new encryption options -- New encryption options - -### 🐛 Bug Fixes - -- Render html on error page correctly -- Invalid API response on missing project -- Applications API response code + schema -- Applications API writing to unavailable models -- If an init script is renamed the old version is still on the server -- Oauthseeder -- Compose loading seq -- Resource clone name + volume name generation -- Update Dockerfile entrypoint path to /etc/entrypoint.d -- Debug mode -- Unreachable notifications -- Remove duplicated ServerCheckJob call -- Few fixes and use new ServerReachabilityChanged event -- Use serverStatus not just status -- Oauth seeder -- Service ui structure -- Check port 8080 and fallback to 80 -- Refactor database view -- Always use docker cleanup frequency -- Advanced server UI -- Html css -- Fix domain being override when update application -- Use nixpacks predefined build variables, but still could update the default values from Coolify -- Use local monaco-editor instead of Cloudflare -- N8n timezone -- Smtp encryption -- Bind() to 0.0.0.0:80 failed -- Oauth seeder -- Unreachable notifications -- Instance settings migration -- Only encrypt instance email settings if there are any -- Error message -- Update healthcheck and port configurations to use port 8080 - -### 🚜 Refactor - -- Rename `coolify.environment` to `coolify.environmentName` - -### ⚙️ Miscellaneous Tasks - -- Regenerate API spec, removing notification fields -- Remove ray debugging -- Version ++ - -## [4.0.0-beta.378] - 2024-12-13 - -### 🐛 Bug Fixes - -- Monaco editor light and dark mode switching -- Service status indicator + oauth saving -- Socialite for azure and authentik -- Saving oauth -- Fallback for copy button -- Copy the right text -- Maybe fallback is now working -- Only show copy button on secure context - -## [4.0.0-beta.377] - 2024-12-13 - -### 🚀 Features - -- Add deploy-only token permission -- Able to deploy without cache on every commit -- Update private key nam with new slug as well -- Allow disabling default redirect, set status to 503 -- Add TLS configuration for default redirect in Server model -- Slack notifications -- Introduce root permission -- Able to download schedule task logs -- Migrate old email notification settings from the teams table -- Migrate old discord notification settings from the teams table -- Migrate old telegram notification settings from the teams table -- Add slack notifications to a new table -- Enable success messages again -- Use new notification stuff inside team model -- Some more notification settings and better defaults -- New email notification settings -- New shared function name `is_transactional_emails_enabled()` -- New shared notifications functions -- Email Notification Settings Model -- Telegram notification settings Model -- Discord notification settings Model -- Slack notification settings Model -- New Discord notification UI -- New Slack notification UI -- New telegram UI -- Use new notification event names -- Always sent notifications -- Scheduled task success notification -- Notification trait -- Get discord Webhook form new table -- Get Slack Webhook form new table -- Use new table or instance settings for email -- Use new place for settings and topic IDs for telegram -- Encrypt instance email settings -- Use encryption in instance settings model -- Scheduled task success and failure notifications -- Add docker cleanup success and failure notification settings columns -- UI for docker cleanup success and failure notification -- Docker cleanup email views -- Docker cleanup success and failure notification files -- Scheduled task success email -- Send new docker cleanup notifications -- :passport_control: integrate Authentik authentication with Coolify -- *(notification)* Add Pushover -- Add seeder command and configuration for database seeding -- Add new password magic env with symbols -- Add documenso service - -### 🐛 Bug Fixes - -- Resolve undefined searchInput reference in Alpine.js component -- URL and sync new app name -- Typos and naming -- Client and webhook secret disappear after sync -- Missing `mysql_password` API property -- Incorrect MongoDB init API property -- Old git versions does not have --cone implemented properly -- Don't allow editing traefik config -- Restart proxy -- Dev mode -- Ui -- Display actual values for disk space checks in installer script -- Proxy change behaviour -- Add warning color -- Import NotificationSlack correctly -- Add middleware to new abilities, better ux for selecting permissions, etc. -- Root + read:sensive could read senstive data with a middlewarew -- Always have download logs button on scheduled tasks -- Missing css -- Development image -- Dockerignore -- DB migration error -- Drop all unused smtp columns -- Backward compatibility -- Email notification channel enabled function -- Instance email settins -- Make sure resend is false if SMTP is true and vice versa -- Email Notification saving -- Slack and discord url now uses text filed because encryption makes the url very long -- Notification trait -- Encryption fixes -- Docker cleanup email template -- Add missing deployment notifications to telegram -- New docker cleanup settings are now saved to the DB correctly -- Ui + migrations -- Docker cleanup email notifications -- General notifications does not go through email channel -- Test notifications to only send it to the right channel -- Remove resale_license from db as well -- Nexus service -- Fileflows volume names -- --cone -- Provider error -- Database migration -- Seeder -- Migration call -- Slack helper -- Telegram helper -- Discord helper -- Telegram topic IDs -- Make pushover settings more clear -- Typo in pushover user key -- Use Livewire refresh method and lock properties -- Create pushover settings for existing teams -- Update token permission check from 'write' to 'root' -- Pushover -- Oauth seeder -- Correct heading display for OAuth settings in settings-oauth.blade.php -- Adjust spacing in login form for improved layout -- Services env values should be sensitive -- Documenso -- Dolibarr +- Secrets join +- ENV variables set differently +- Capture non-error as error +- Only delete id.rsa in case of it exists +- Status is not available yet +- Docker Engine bug related to live-restore and IPs +- Version +- PreventDefault on a button, thats all +- Haproxy check should not throw error +- Delete all build files +- Cleanup images +- More error handling in proxy configuration + cleanups +- Local static assets +- Check sentry - Typo -- Update OauthSettingSeeder to handle new provider definitions and ensure authentik is recreated if missing -- Improve OauthSettingSeeder to correctly delete non-existent providers and ensure proper handling of provider definitions -- Encrypt resend API key in instance settings -- Resend api key is already a text column - -### 💼 Other - -- Test rename GitHub app -- Checkmate service and fix prowlar slogan (too long) - -### 🚜 Refactor - -- Update Traefik configuration for improved security and logging -- Improve proxy configuration and code consistency in Server model -- Rename name method to sanitizedName in BaseModel for clarity -- Improve migration command and enhance application model with global scope and status checks -- Unify notification icon -- Remove unused Azure and Authentik service configurations from services.php -- Change email column types in instance_settings migration from string to text -- Change OauthSetting creation to updateOrCreate for better handling of existing records - -### ⚙️ Miscellaneous Tasks - -- Regenerate openapi spec -- Composer dep bump -- Dep bump -- Upgrade cloudflared and minio -- Remove comments and improve DB column naming -- Remove unused seeder -- Remove unused waitlist stuff -- Remove wired.php (not used anymore) -- Remove unused resale license job -- Remove commented out internal notification -- Remove more waitlist stuff -- Remove commented out notification -- Remove more waitlist stuff -- Remove unused code -- Fix typo -- Remove comment out code -- Some reordering -- Remove resale license reference -- Remove functions from shared.php -- Public settings for email notification -- Remove waitlist redirect -- Remove log -- Use new notification trait -- Remove unused route -- Remove unused email component -- Comment status changes as it is disabled for now -- Bump dep -- Reorder navbar -- Rename topicID to threadId like in the telegram API response -- Update PHP configuration to set memory limit using environment variable - -## [4.0.0-beta.376] - 2024-12-07 - -### 🐛 Bug Fixes - -- Api endpoint - -## [4.0.0-beta.374] - 2024-12-03 - -### 🐛 Bug Fixes - -- Application view loading -- Postiz service -- Only able to select the right keys -- Test email should not be required -- A few inputs - -### 🧪 Testing - -- Setup database for upcoming tests - -## [4.0.0-beta.372] - 2024-11-26 - -### 🚀 Features - -- Add MacOS template -- Add Windows template -- *(service)* :sparkles: add mealie -- Add hex magic env var - -### 🐛 Bug Fixes - -- Service generate includes yml files as well (haha) -- ServercheckJob should run every 5 minutes on cloud -- New resource icons -- Search should be more visible on scroll on new resource -- Logdrain settings -- Ui -- Email should be retried with backoff -- Alpine in body layout - -### 💼 Other - -- Caddy docker labels do not honor "strip prefix" option - -## [4.0.0-beta.371] - 2024-11-22 - -### 🐛 Bug Fixes - -- Improve helper text for metrics input fields -- Refine helper text for metrics input fields -- If mux conn fails, still use it without mux + save priv key with better logic -- Migration -- Always validate ssh key -- Make sure important jobs/actions are running on high prio queue -- Do not send internal notification for backups and status jobs -- Validateconnection -- View issue -- Heading -- Remove mux cleanup -- Db backup for services -- Version should come from constants + fix stripe webhook error reporting -- Undefined variable -- Remove version.php as everything is coming from constants.php -- Sentry error -- Websocket connections autoreconnect -- Sentry error -- Sentry -- Empty server API response -- Incorrect server API patch response -- Missing `uuid` parameter on server API patch -- Missing `settings` property on servers API -- Move servers API `delete_unused_*` properties -- Servers API returning `port` as a string -> integer -- Only return server uuid on server update - -## [4.0.0-beta.370] - 2024-11-15 - -### 🐛 Bug Fixes - -- Modal (+ add) on dynamic config was not opening, removed x-cloak -- AUTOUPDATE + checkbox opacity - -## [4.0.0-beta.369] - 2024-11-15 - -### 🐛 Bug Fixes - -- Modal-input - -## [4.0.0-beta.368] - 2024-11-15 - -### 🚀 Features - -- Check local horizon scheduler deployments -- Add internal api docs to /docs/api with auth -- Add proxy type change to create/update apis - -### 🐛 Bug Fixes - -- Show proper error message on invalid Git source -- Convert HTTP to SSH source when using deploy key on GitHub -- Cloud + stripe related -- Terminal view loading in async -- Cool 500 error (thanks hugodos) -- Update schema in code decorator -- Openapi docs -- Add tests for git url converts -- Minio / logto url generation -- Admin view -- Min docker version 26 -- Pull latest service-templates.json on init -- Workflow files for coolify build -- Autocompletes -- Timezone settings validation -- Invalid tz should not prevent other jobs to be executed -- Testing-host should be built locally -- Poll with modal issue -- Terminal opening issue -- If service img not found, use github as a source -- Fallback to local coolify.png -- Gather private ips -- Cf tunnel menu should be visible when server is not validated -- Deployment optimizations -- Init script + optimize laravel -- Default docker engine version + fix install script -- Pull helper image on init -- SPA static site default nginx conf - -### 💼 Other - -- Https://github.com/coollabsio/coolify/issues/4186 -- Separate resources by type in projects view -- Improve s3 add view - -### ⚙️ Miscellaneous Tasks - -- Update dep - -## [4.0.0-beta.365] - 2024-11-11 - -### 🚀 Features - -- Custom nginx configuration for static deployments + fix 404 redirects in nginx conf - -### 🐛 Bug Fixes - -- Trigger.dev db host & sslmode=disable -- Manual update should be executed only once + better UX -- Upgrade.sh -- Missing privateKey - -## [4.0.0-beta.364] - 2024-11-08 - -### 🐛 Bug Fixes - -- Define separate volumes for mattermost service template -- Github app name is too long -- ServerTimezone update - -### ⚙️ Miscellaneous Tasks - -- Edit www helper - -## [4.0.0-beta.363] - 2024-11-08 - -### 🚀 Features - -- Add Firefox template -- Add template for Wiki.js -- Add upgrade logs to /data/coolify/source - -### 🐛 Bug Fixes - -- Saving resend api key -- Wildcard domain save -- Disable cloudflare tunnel on "localhost" - -## [4.0.0-beta.362] - 2024-11-08 - -### 🐛 Bug Fixes - -- Notifications ui -- Disable wire:navigate -- Confirmation Settings css for light mode -- Server wildcard - -## [4.0.0-beta.361] - 2024-11-08 - -### 🚀 Features - -- Add Transmission template -- Add transmission healhcheck -- Add zipline template -- Dify template -- Required envs -- Add EdgeDB -- Show warning if people would like to use sslip with https -- Add is shared to env variables -- Variabel sync and support shared vars -- Add notification settings to server_disk_usage -- Add coder service tamplate and logo -- Debug mode for sentinel -- Add jitsi template -- Add --gpu support for custom docker command - -### 🐛 Bug Fixes - -- Make sure caddy is not removed by cleanup -- Libretranslate -- Do not allow to change number of lines when streaming logs -- Plunk -- No manual timezones -- Helper push -- Format -- Add port metadata and Coolify magic to generate the domain -- Sentinel -- Metrics -- Generate sentinel url -- Only enable Sentinel for new servers -- Is_static through API -- Allow setting standalone redis variables via ENVs (team variables...) -- Check for username separately form password -- Encrypt all existing redis passwords -- Pull helper image on helper_version change -- Redis database user and password -- Able to update ipv4 / ipv6 instance settings -- Metrics for dbs -- Sentinel start fixed -- Validate sentinel custom URL when enabling sentinel -- Should be able to reset labels in read-only mode with manual click -- No sentinel for swarm yet -- Charts ui -- Volume -- Sentinel config changes restarts sentinel -- Disable sentinel for now -- Disable Sentinel temporarily -- Disable Sentinel temporarily for non-dev environments -- Access team's github apps only -- Admins should now invite owner -- Add experimental flag -- GenerateSentinelUrl method -- NumberOfLines could be null -- Login / register view -- Restart sentinel once a day -- Changing private key manually won't trigger a notification -- Grammar for helper -- Fix my own grammar -- Add telescope only in dev mode -- New way to update container statuses -- Only run server storage every 10 mins if sentinel is not active -- Cloud admin view -- Queries in kernel.php -- Lower case emails only -- Change emails to lowercase on init -- Do not error on update email -- Always authenticate with lowercase emails -- Dashboard refactor -- Add min/max length to input/texarea -- Remove livewire legacy from help view -- Remove unnecessary endpoints (magic) -- Transactional email livewire -- Destinations livewire refactor -- Refactor destination/docker view -- Logdrains validation -- Reworded -- Use Auth(), add new db proxy stop event refactor clickhouse view -- Add user/pw to db view -- Sort servers by name -- Keydb view -- Refactor tags view / remove obsolete one -- Send discord/telegram notifications on high job queue -- Server view refresh on validation -- ShowBoarding -- Show docker installation logs & ubuntu 24.10 notification -- Do not overlap servercheckjob -- Server limit check -- Server validation -- Clear route / view -- Only skip docker installation on 24.10 if its not installed -- For --gpus device support -- Db/service start should be on high queue -- Do not stop sentinel on Coolify restart -- Run resourceCheck after new serviceCheckJob -- Mongodb in dev -- Better invitation errors -- Loading indicator for db proxies -- Do not execute gh workflow on template changes -- Only use sentry in cloud -- Update packagejson of coolify-realtime + add lock file -- Update last online with old function -- Seeder should not start sentinel -- Start sentinel on seeder - -### 💼 Other - -- Add peppermint -- Loggy -- Add UI for redis password and username -- Wireguard-easy template - -### 📚 Documentation - -- Update link to deploy api docs - -### ⚙️ Miscellaneous Tasks - -- Add transmission template desc -- Update transmission docs link -- Update version numbers to 4.0.0-beta.360 in configuration files -- Update AWS environment variable names in unsend.yaml -- Update AWS environment variable names in unsend.yaml -- Update livewire/livewire dependency to version 3.4.9 -- Update version to 4.0.0-beta.361 -- Update Docker build and push actions to v6 -- Update Docker build and push actions to v6 -- Update Docker build and push actions to v6 -- Sync coolify-helper to dockerhub as well -- Push realtime to dockerhub -- Sync coolify-realtime to dockerhub -- Rename workflows -- Rename development to staging build -- Sync coolify-testing-host to dockerhbu -- Sync coolify prod image to dockerhub as well -- Update Docker version to 26.0 -- Update project resource index page -- Update project service configuration view - -## [4.0.0-beta.360] - 2024-10-11 - -### ⚙️ Miscellaneous Tasks - -- Update livewire/livewire dependency to version 3.4.9 - -## [4.0.0-beta.359] - 2024-10-11 - -### 🐛 Bug Fixes - -- Use correct env variable for invoice ninja password - -### ⚙️ Miscellaneous Tasks - -- Update laravel/horizon dependency to version 5.29.1 -- Update service extra fields to use dynamic keys - -## [4.0.0-beta.358] - 2024-10-10 - -### 🚀 Features - -- Add customHelper to stack-form -- Add cloudbeaver template -- Add ntfy template -- Add qbittorrent template -- Add Homebox template -- Add owncloud service and logo -- Add immich service -- Auto generate url -- Refactored to work with coolify auto env vars -- Affine service template and logo -- Add LibreTranslate template -- Open version in a new tab - -### 🐛 Bug Fixes - -- Signup -- Application domains should be http and https only -- Validate and sanitize application domains -- Sanitize and validate application domains - -### 💼 Other - -- Other DB options for freshrss -- Nextcloud MariaDB and MySQL versions - -### ⚙️ Miscellaneous Tasks - -- Fix form submission and keydown event handling in modal-confirmation.blade.php -- Update version numbers to 4.0.0-beta.359 in configuration files -- Disable adding default environment variables in shared.php - -## [4.0.0-beta.357] - 2024-10-08 - -### 🚀 Features - -- Add Mautic 4 and 5 to service templates -- Add keycloak template -- Add onedev template -- Improve search functionality in project selection - -### 🐛 Bug Fixes - -- Update mattermost image tag and add default port -- Remove env, change timezone -- Postgres healthcheck -- Azimutt template - still not working haha -- New parser with SERVICE_URL_ envs -- Improve service template readability -- Update password variables in Service model -- Scheduled database server -- Select server view - -### 💼 Other - -- Keycloak - -### ⚙️ Miscellaneous Tasks - -- Add mattermost logo as svg -- Add mattermost svg to compose -- Update version to 4.0.0-beta.357 - -## [4.0.0-beta.356] - 2024-10-07 - -### 🚀 Features - -- Add Argilla service configuration to Service model -- Add Invoice Ninja service configuration to Service model -- Project search on frontend -- Add ollama service with open webui and logo -- Update setType method to use slug value for type -- Refactor setType method to use slug value for type -- Refactor setType method to use slug value for type -- Add Supertokens template -- Add easyappointments service template -- Add dozzle template -- Adds forgejo service with runners - -### 🐛 Bug Fixes - -- Reset description and subject fields after submitting feedback -- Tag mass redeployments -- Service env orders, application env orders -- Proxy conf in dev -- One-click services -- Use local service-templates in dev -- New services -- Remove not used extra host -- Chatwoot service -- Directus -- Database descriptions -- Update services -- Soketi -- Select server view - -### 💼 Other - -- Update helper version -- Outline -- Directus -- Supertokens -- Supertokens json -- Rabbitmq -- Easyappointments -- Soketi -- Dozzle -- Windmill -- Coolify.json - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.356 -- Remove commented code for shared variable type validation -- Update MariaDB image to version 11 and fix service environment variable orders -- Update anythingllm.yaml volumes configuration -- Update proxy configuration paths for Caddy and Nginx in dev -- Update password form submission in modal-confirmation component -- Update project query to order by name in uppercase -- Update project query to order by name in lowercase -- Update select.blade.php with improved search functionality -- Add Nitropage service template and logo -- Bump coolify-helper version to 1.0.2 -- Refactor loadServices2 method and remove unused code -- Update version to 4.0.0-beta.357 -- Update service names and volumes in windmill.yaml -- Update version to 4.0.0-beta.358 -- Ignore .ignition.json files in Docker and Git - -## [4.0.0-beta.355] - 2024-10-03 - -### 🐛 Bug Fixes - -- Scheduled backup for services view -- Parser, espacing container labels - -### ⚙️ Miscellaneous Tasks - -- Update homarr service template and remove unnecessary code -- Update version to 4.0.0-beta.355 - -## [4.0.0-beta.354] - 2024-10-03 - -### 🚀 Features - -- Add it-tools service template and logo -- Add homarr service tamplate and logo - -### 🐛 Bug Fixes - -- Parse proxy config and check the set ports usage -- Update FQDN - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.354 -- Remove debug statement in Service model -- Remove commented code in Server model -- Fix application deployment queue filter logic -- Refactor modal-confirmation component -- Update it-tools service template and port configuration -- Update homarr service template and remove unnecessary code - -## [4.0.0-beta.353] - 2024-10-03 - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.353 -- Update service application view - -## [4.0.0-beta.352] - 2024-10-03 - -### 🐛 Bug Fixes - -- Service application view -- Add new supported database images - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.352 -- Refactor DatabaseBackupJob to handle missing team - -## [4.0.0-beta.351] - 2024-10-03 - -### 🚀 Features - -- Add strapi template - -### 🐛 Bug Fixes - -- Able to support more database dynamically from Coolify's UI -- Strapi template -- Bitcoin core template -- Api useBuildServer - -## [4.0.0-beta.349] - 2024-10-01 - -### 🚀 Features - -- Add command to check application deployment queue -- Support Hetzner S3 -- Handle HTTPS domain in ConfigureCloudflareTunnels -- Backup all databases for mysql,mariadb,postgresql -- Restart service without pulling the latest image - -### 🐛 Bug Fixes - -- Remove autofocuses -- Ipv6 scp should use -6 flag -- Cleanup stucked applicationdeploymentqueue -- Realtime watch in development mode -- Able to select root permission easier - -### 💼 Other - -- Show backup button on supported db service stacks - -### 🚜 Refactor - -- Remove deployment queue when deleting an application -- Improve SSH command generation in Terminal.php and terminal-server.js -- Fix indentation in modal-confirmation.blade.php -- Improve parsing of commands for sudo in parseCommandsByLineForSudo -- Improve popup component styling and button behavior -- Encode delimiter in SshMultiplexingHelper -- Remove inactivity timer in terminal-server.js -- Improve socket reconnection interval in terminal.js -- Remove unnecessary watch command from soketi service entrypoint - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.350 in configuration files -- Update command signature and description for cleanup application deployment queue -- Add missing import for Attribute class in ApplicationDeploymentQueue model -- Update modal input in server form to prevent closing on outside click -- Remove unnecessary command from SshMultiplexingHelper -- Remove commented out code for uploading to S3 in DatabaseBackupJob -- Update soketi service image to version 1.0.3 - -## [4.0.0-beta.348] - 2024-10-01 - -### 🚀 Features - -- Update resource deletion job to allow configurable options through API -- Add query parameters for deleting configurations, volumes, docker cleanup, and connected networks - -### 🐛 Bug Fixes - -- In dev mode do not ask confirmation on delete -- Mixpost -- Handle deletion of 'hello' in confirmation modal for dev environment - -### 💼 Other - -- Server storage check - -### 🚜 Refactor - -- Update search input placeholder in resource index view - -### ⚙️ Miscellaneous Tasks - -- Fix docs link in running state -- Update Coolify Realtime workflow to only trigger on the main branch -- Refactor instanceSettings() function to improve code readability -- Update Coolify Realtime image to version 1.0.2 -- Remove unnecessary code in DatabaseBackupJob.php -- Add "Not Usable" indicator for storage items -- Refactor instanceSettings() function and improve code readability -- Update version numbers to 4.0.0-beta.349 and 4.0.0-beta.350 - -## [4.0.0-beta.347] - 2024-09-28 - -### 🚀 Features - -- Allow specify use_build_server when creating/updating an application -- Add support for `use_build_server` in API endpoints for creating/updating applications -- Add Mixpost template - -### 🐛 Bug Fixes - -- Filebrowser template -- Edit is_build_server_enabled upon creating application on other application type -- Save settings after assigning value - -### 💼 Other - -- Remove memlock as it caused problems for some users - -### ⚙️ Miscellaneous Tasks - -- Update Mailpit logo to use SVG format - -## [4.0.0-beta.346] - 2024-09-27 - -### 🚀 Features - -- Add ContainerStatusTypes enum for managing container status - -### 🐛 Bug Fixes - -- Proxy fixes -- Proxy -- *(templates)* Filebrowser FQDN env variable -- Handle edge case when build variables and env variables are in different format -- Compose based terminal - -### 💼 Other - -- Manual cleanup button and unused volumes and network deletion -- Force helper image removal -- Use the new confirmation flow +- Package.json +- Build secrets should be visible in runtime +- New secret should have default values +- Validate secrets +- Truncate git clone errors +- Branch used does not throw error - Typo -- Typo in install script -- If API is disabeled do not show API token creation stuff -- Disable API by default -- Add debug bar - -### 🚜 Refactor - -- Update environment variable name for uptime-kuma service -- Improve start proxy script to handle existing containers gracefully -- Update delete server confirmation modal buttons -- Remove unnecessary code - -### ⚙️ Miscellaneous Tasks - -- Add autocomplete attribute to input fields -- Refactor API Tokens component to use isApiEnabled flag -- Update versions.json file -- Remove unused .env.development.example file -- Update API Tokens view to include link to Settings menu -- Update web.php to cast server port as integer -- Update backup deletion labels to use language files -- Update database startup heading title -- Update database startup heading title -- Custom vite envs -- Update version numbers to 4.0.0-beta.348 -- Refactor code to improve SSH key handling and storage - -## [4.0.0-beta.343] - 2024-09-25 - -### 🐛 Bug Fixes - -- Parser -- Exited services statuses -- Make sure to reload window if app status changes -- Deploy key based deployments - -### 🚜 Refactor - -- Remove commented out code and improve environment variable handling in newParser function -- Improve label positioning in input and checkbox components -- Group and sort fields in StackForm by service name and password status -- Improve layout and add checkbox for task enablement in scheduled task form -- Update checkbox component to support full width option -- Update confirmation label in danger.blade.php template -- Fix typo in execute-container-command.blade.php -- Update OS_TYPE for Asahi Linux in install.sh script -- Add localhost as Server if it doesn't exist and not in cloud environment -- Add localhost as Server if it doesn't exist and not in cloud environment -- Update ProductionSeeder to fix issue with coolify_key assignment -- Improve modal confirmation titles and button labels -- Update install.sh script to remove redirection of upgrade output to /dev/null -- Fix modal input closeOutside prop in configuration.blade.php -- Add support for IPv6 addresses in sslip function - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.343 -- Update version numbers to 4.0.0-beta.344 -- Update version numbers to 4.0.0-beta.345 -- Update version numbers to 4.0.0-beta.346 - -## [4.0.0-beta.342] - 2024-09-24 - -### 🚀 Features - -- Add nullable constraint to 'fingerprint' column in private_keys table -- *(api)* Add an endpoint to execute a command -- *(api)* Add endpoint to execute a command - -### 🐛 Bug Fixes - -- Proxy status -- Coolify-db should not be in the managed resources -- Store original root key in the original location -- Logto service -- Cloudflared service -- Migrations -- Cloudflare tunnel configuration, ui, etc - -### 💼 Other - -- Volumes on development environment -- Clean new volume name for dev volumes -- Persist DBs, services and so on stored in data/coolify -- Add SSH Key fingerprint to DB -- Add a fingerprint to every private key on save, create... -- Make sure invalid private keys can not be added -- Encrypt private SSH keys in the DB -- Add is_sftp and is_server_ssh_key coloums -- New ssh key file name on disk -- Store all keys on disk by default -- Populate SSH key folder -- Populate SSH keys in dev -- Use new function names and logic everywhere -- Create a Multiplexing Helper -- SSH multiplexing -- Remove unused code form multiplexing -- SSH Key cleanup job -- Private key with ID 2 on dev -- Move more functions to the PrivateKey Model -- Add ssh key fingerprint and generate one for existing keys -- ID issues on dev seeders -- Server ID 0 -- Make sure in use private keys are not deleted -- Do not delete SSH Key from disk during server validation error -- UI bug, do not write ssh key to disk in server dialog -- SSH Multiplexing for Jobs -- SSH algorhytm text -- Few multiplexing things -- Clear mux directory -- Multiplexing do not write file manually -- Integrate tow step process in the modal component WIP -- Ability to hide labels -- DB start, stop confirm -- Del init script -- General confirm -- Preview deployments and typos -- Service confirmation -- Confirm file storage -- Stop service confirm -- DB image cleanup -- Confirm ressource operation -- Environment variabel deletion -- Confirm scheduled tasks -- Confirm API token -- Confirm private key -- Confirm server deletion -- Confirm server settings -- Proxy stop and restart confirmation -- GH app deletion confirmation -- Redeploy all confirmation -- User deletion confirmation -- Team deletion confirmation -- Backup job confirmation -- Delete volume confirmation -- More conformations and fixes -- Delete unused private keys button -- Ray error because port is not uncommented -- #3322 deploy DB alterations before updating -- Css issue with advanced settings and remove cf tunnel in onboarding -- New cf tunnel install flow -- Made help text more clear -- Cloudflare tunnel -- Make helper text more clean to use a FQDN and not an URL - -### 🚜 Refactor - -- Update Docker cleanup label in Heading.php and Navbar.php -- Remove commented out code in Navbar.php -- Remove CleanupSshKeysJob from schedule in Kernel.php -- Update getAJoke function to exclude offensive jokes -- Update getAJoke function to use HTTPS for API request -- Update CleanupHelperContainersJob to use more efficient Docker command -- Update PrivateKey model to improve code readability and maintainability -- Remove unnecessary code in PrivateKey model -- Update PrivateKey model to use ownedByCurrentTeam() scope for cleanupUnusedKeys() -- Update install.sh script to check if coolify-db volume exists before generating SSH key -- Update ServerSeeder and PopulateSshKeysDirectorySeeder -- Improve attribute sanitization in Server model -- Update confirmation button text for deletion actions -- Remove unnecessary code in shared.php file -- Update environment variables for services in compose files -- Update select.blade.php to improve trademarks policy display -- Update select.blade.php to improve trademarks policy display -- Fix typo in subscription URLs -- Add Postiz service to compose file (disabled for now) -- Update shared.php to include predefined ports for services -- Simplify SSH key synchronization logic -- Remove unused code in DatabaseBackupStatusJob and PopulateSshKeysDirectorySeeder - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.342 -- Update remove-labels-and-assignees-on-close.yml -- Add SSH key for localhost in ProductionSeeder -- Update SSH key generation in install.sh script -- Update ProductionSeeder to call OauthSettingSeeder and PopulateSshKeysDirectorySeeder -- Update install.sh to support Asahi Linux -- Update install.sh version to 1.6 -- Remove unused middleware and uniqueId method in DockerCleanupJob -- Refactor DockerCleanupJob to remove unused middleware and uniqueId method -- Remove unused migration file for populating SSH keys and clearing mux directory -- Add modified files to the commit -- Refactor pre-commit hook to improve performance and readability -- Update CONTRIBUTING.md with troubleshooting note about database migrations -- Refactor pre-commit hook to improve performance and readability -- Update cleanup command to use Redis instead of queue -- Update Docker commands to start proxy - -## [4.0.0-beta.341] - 2024-09-18 - -### 🚀 Features - -- Add buddy logo - -## [4.0.0-beta.336] - 2024-09-16 - -### 🚀 Features - -- Make coolify full width by default -- Fully functional terminal for command center -- Custom terminal host - -### 🐛 Bug Fixes - -- Keep-alive ws connections -- Add build.sh to debug logs -- Update Coolify installer -- Terminal -- Generate https for minio -- Install script -- Handle WebSocket connection close in terminal.blade.php -- Able to open terminal to any containers -- Refactor run-command -- If you exit a container manually, it should close the underlying tty as well -- Move terminal to separate view on services -- Only update helper image in DB -- Generated fqdn for SERVICE_FQDN_APP_3000 magic envs - -### 💼 Other - -- Remove labels and assignees on issue close -- Make sure this action is also triggered on PR issue close - -### 🚜 Refactor - -- Remove unnecessary code in ExecuteContainerCommand.php -- Improve Docker network connection command in StartService.php -- Terminal / run command -- Add authorization check in ExecuteContainerCommand mount method -- Remove unnecessary code in Terminal.php -- Remove unnecessary code in Terminal.blade.php -- Update WebSocket connection initialization in terminal.blade.php -- Remove unnecessary console.log statements in terminal.blade.php - -### ⚙️ Miscellaneous Tasks - -- Update release version to 4.0.0-beta.336 -- Update coolify environment variable assignment with double quotes -- Update shared.php to fix issues with source and network variables -- Update terminal styling for better readability -- Update button text for container connection form -- Update Dockerfile and workflow for Coolify Realtime (v4) -- Remove unused entrypoint script and update volume mapping -- Update .env file and docker-compose configuration -- Update APP_NAME environment variable in docker-compose.prod.yml -- Update WebSocket URL in terminal.blade.php -- Update Dockerfile and workflow for Coolify Realtime (v4) -- Update Dockerfile and workflow for Coolify Realtime (v4) -- Update Dockerfile and workflow for Coolify Realtime (v4) -- Rename Command Center to Terminal in code and views -- Update branch restriction for push event in coolify-helper.yml -- Update terminal button text and layout in application heading view -- Refactor terminal component and select form layout -- Update coolify nightly version to 4.0.0-beta.335 -- Update helper version to 1.0.1 -- Fix syntax error in versions.json -- Update version numbers to 4.0.0-beta.337 -- Update Coolify installer and scripts to include a function for fetching programming jokes -- Update docker network connection command in ApplicationDeploymentJob.php -- Add validation to prevent selecting 'default' server or container in RunCommand.php -- Update versions.json to reflect latest version of realtime container -- Update soketi image to version 1.0.1 -- Nightly - Update soketi image to version 1.0.1 and versions.json to reflect latest version of realtime container -- Update version numbers to 4.0.0-beta.339 -- Update version numbers to 4.0.0-beta.340 -- Update version numbers to 4.0.0-beta.341 - -### ◀️ Revert - -- Databasebackup - -## [4.0.0-beta.335] - 2024-09-12 - -### 🐛 Bug Fixes - -- Cloudflare tunnel with new multiplexing feature - -### 💼 Other - -- SSH Multiplexing on docker desktop on Windows - -### ⚙️ Miscellaneous Tasks - -- Update release version to 4.0.0-beta.335 -- Update constants.ssh.mux_enabled in remoteProcess.php -- Update listeners and proxy settings in server form and new server components -- Remove unnecessary null check for proxy_type in generate_default_proxy_configuration -- Remove unnecessary SSH command execution time logging - -## [4.0.0-beta.334] - 2024-09-12 - -### ⚙️ Miscellaneous Tasks - -- Remove itsgoingd/clockwork from require-dev in composer.json -- Update 'key' value of gitlab in Service.php to use environment variable - -## [4.0.0-beta.333] - 2024-09-11 - -### 🐛 Bug Fixes - -- Disable mux_enabled during server validation -- Move mc command to coolify image from helper -- Keydb. add `:` delimiter for connection string - -### 💼 Other - -- Remote servers with port and user -- Do not change localhost server name on revalidation -- Release.md file - -### 🚜 Refactor - -- Improve handling of environment variable merging in upgrade script - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.333 -- Copy .env file to .env-{DATE} if it exists -- Update .env file with new values -- Update server check job middleware to use server ID instead of UUID -- Add reminder to backup .env file before running install script again -- Copy .env file to backup location during installation script -- Add reminder to backup .env file during installation script -- Update permissions in pr-build.yml and version numbers -- Add minio/mc command to Dockerfile - -## [4.0.0-beta.332] - 2024-09-10 - -### 🚀 Features - -- Expose project description in API response -- Add elixir finetunes to the deployment job - -### 🐛 Bug Fixes - -- Reenable overlapping servercheckjob -- Appwrite template + parser -- Don't add `networks` key if `network_mode` is used -- Remove debug statement in shared.php -- Scp through cloudflare -- Delete older versions of the helper image other than the latest one -- Update remoteProcess.php to handle null values in logItem properties - -### 💼 Other - -- Set a default server timezone -- Implement SSH Multiplexing -- Enabel mux -- Cleanup stale multiplexing connections - -### 🚜 Refactor - -- Improve environment variable handling in shared.php - -### ⚙️ Miscellaneous Tasks - -- Set timeout for ServerCheckJob to 60 seconds -- Update appwrite.yaml to include OpenSSL key variable assignment - -## [4.0.0-beta.330] - 2024-09-06 - -### 🐛 Bug Fixes - -- Parser -- Plunk NEXT_PUBLIC_API_URI - -### 💼 Other - -- Pull helper image if not available otherwise s3 backup upload fails - -### 🚜 Refactor - -- Improve handling of server timezones in scheduled backups and tasks -- Improve handling of server timezones in scheduled backups and tasks -- Improve handling of server timezones in scheduled backups and tasks -- Update cleanup schedule to run daily at midnight -- Skip returning volume if driver type is cifs or nfs - -### ⚙️ Miscellaneous Tasks - -- Update coolify-helper.yml to get version from versions.json -- Disable Ray by default -- Enable Ray by default and update Dockerfile with latest versions of PACK and NIXPACKS -- Update Ray configuration and Dockerfile -- Add middleware for updating environment variables by UUID in `api.php` routes -- Expose port 3000 in browserless.yaml template -- Update Ray configuration and Dockerfile -- Update coolify version to 4.0.0-beta.331 -- Update versions.json and sentry.php to 4.0.0-beta.332 -- Update version to 4.0.0-beta.332 -- Update DATABASE_URL in plunk.yaml to use plunk database -- Add coolify.managed=true label to Docker image builds -- Update docker image pruning command to exclude managed images -- Update docker cleanup schedule to run daily at midnight -- Update versions.json to version 1.0.1 -- Update coolify-helper.yml to include "next" branch in push trigger - -## [4.0.0-beta.326] - 2024-09-03 - -### 🚀 Features - -- Update server_settings table to force docker cleanup -- Update Docker Compose file with DB_URL environment variable -- Refactor shared.php to improve environment variable handling - -### 🐛 Bug Fixes - -- Wrong executions order -- Handle project not found error in environment_details API endpoint -- Deployment running for - without "ago" -- Update helper image pulling logic to only pull if the version is newer - -### 💼 Other - -- Plunk svg - -### 📚 Documentation - -- Update Plunk documentation link in compose/plunk.yaml - -### ⚙️ Miscellaneous Tasks - -- Update UI for displaying no executions found in scheduled task list -- Update UI for displaying deployment status in deployment list -- Update UI for displaying deployment status in deployment list -- Ignore unnecessary files in production build workflow -- Update server form layout and settings -- Update Dockerfile with latest versions of PACK and NIXPACKS - -## [4.0.0-beta.324] - 2024-09-02 - -### 🚀 Features - -- Preserve git repository with advanced file storages -- Added Windmill template -- Added Budibase template -- Add shm-size for custom docker commands -- Add custom docker container options to all databases -- Able to select different postgres database -- Add new logos for jobscollider and hostinger -- Order scheduled task executions -- Add Code Server environment variables to Service model -- Add coolify build env variables to building phase -- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid -- Add new logos for GlueOps, Ubicloud, Juxtdigital, Saasykit, and Massivegrid - -### 🐛 Bug Fixes - -- Timezone not updated when systemd is missing -- If volumes + file mounts are defined, should merge them together in the compose file -- All mongo v4 backups should use the different backup command -- Database custom environment variables -- Connect compose apps to the right predefined network -- Docker compose destination network -- Server status when there are multiple servers -- Sync fqdn change on the UI -- Pr build names in case custom name is used -- Application patch request instant_deploy -- Canceling deployment on build server -- Backup of password protected postgresql database -- Docker cleanup job -- Storages with preserved git repository -- Parser parser parser -- New parser only in dev -- Parser parser -- Numberoflines should be number -- Docker cleanup job -- Fix directory and file mount headings in file-storage.blade.php -- Preview fqdn generation -- Revert a few lines -- Service ui sync bug -- Setup script doesn't work on rhel based images with some curl variant already installed -- Let's wait for healthy container during installation and wait an extra 20 seconds (for migrations) -- Infra files -- Log drain only for Applications -- Copy large compose files through scp (not ssh) -- Check if array is associative or not -- Openapi endpoint urls -- Convert environment variables to one format in shared.php -- Logical volumes could be overwritten with new path -- Env variable in value parsed -- Pull coolify image only when the app needs to be updated - -### 💼 Other - -- Actually update timezone on the server -- Cron jobs are executed based on the server timezone -- Server timezone seeder -- Recent backups UI -- Use apt-get instead of apt +- Error handling +- Stopping service without proxy +- Coolify proxy start +- Window error in SSR +- GitHub sync PR's +- Load more button +- Small fixes - Typo -- Only pull helper image if the version is newer than the one - -### 🚜 Refactor - -- Update event listeners in Show components -- Refresh application to get latest database changes -- Update RabbitMQ configuration to use environment variable for port -- Remove debug statement in parseDockerComposeFile function -- ParseServiceVolumes -- Update OpenApi command to generate documentation -- Remove unnecessary server status check in destination view -- Remove unnecessary admin user email and password in budibase.yaml -- Improve saving of custom internal name in Advanced.php -- Add conditional check for volumes in generate_compose_file() -- Improve storage mount forms in add.blade.php -- Load environment variables based on resource type in sortEnvironmentVariables() -- Remove unnecessary network cleanup in Init.php -- Remove unnecessary environment variable checks in parseDockerComposeFile() -- Add null check for docker_compose_raw in parseCompose() -- Update dockerComposeParser to use YAML data from $yaml instead of $compose -- Convert service variables to key-value pairs in parseDockerComposeFile function -- Update database service name from mariadb to mysql -- Remove unnecessary code in DatabaseBackupJob and BackupExecutions -- Update Docker Compose parsing function to convert service variables to key-value pairs -- Update Docker Compose parsing function to convert service variables to key-value pairs -- Remove unused server timezone seeder and related code -- Remove unused server timezone seeder and related code -- Remove unused PullCoolifyImageJob from schedule -- Update parse method in Advanced, All, ApplicationPreview, General, and ApplicationDeploymentJob classes -- Remove commented out code for getIptables() in Dashboard.php -- Update .env file path in install.sh script -- Update SELF_HOSTED environment variable in docker-compose.prod.yml -- Remove unnecessary code for creating coolify network in upgrade.sh -- Update environment variable handling in StartClickhouse.php and ApplicationDeploymentJob.php -- Improve handling of COOLIFY_URL in shared.php -- Update build_args property type in ApplicationDeploymentJob -- Update background color of sponsor section in README.md -- Update Docker Compose location handling in PublicGitRepository -- Upgrade process of Coolify - -### 🧪 Testing - -- More tests - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.324 -- New compose parser with tests -- Update version to 1.3.4 in install.sh and 1.0.6 in upgrade.sh -- Update memory limit to 64MB in horizon configuration -- Update php packages -- Update axios npm dependency to version 1.7.5 -- Update Coolify version to 4.0.0-beta.324 and fix file paths in upgrade script -- Update Coolify version to 4.0.0-beta.324 -- Update Coolify version to 4.0.0-beta.325 -- Update Coolify version to 4.0.0-beta.326 -- Add cd command to change directory before removing .env file -- Update Coolify version to 4.0.0-beta.327 -- Update Coolify version to 4.0.0-beta.328 -- Update sponsor links in README.md -- Update version.json to versions.json in GitHub workflow -- Cleanup stucked resources and scheduled backups -- Update GitHub workflow to use versions.json instead of version.json -- Update GitHub workflow to use versions.json instead of version.json -- Update GitHub workflow to use versions.json instead of version.json -- Update GitHub workflow to use jq container for version extraction -- Update GitHub workflow to use jq container for version extraction - -## [4.0.0-beta.323] - 2024-08-08 - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.323 - -## [4.0.0-beta.322] - 2024-08-08 - -### 🐛 Bug Fixes - -- Manual update process - -### 🚜 Refactor - -- Update Server model getContainers method to use collect() for containers and containerReplicates -- Import ProxyTypes enum and use TRAEFIK instead of TRAEFIK_V2 - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.322 - -## [4.0.0-beta.321] - 2024-08-08 - -### 🐛 Bug Fixes - -- Scheduledbackup not found - -### 🚜 Refactor - -- Update StandalonePostgresql database initialization and backup handling -- Update cron expressions and add helper text for scheduled tasks - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.321 - -## [4.0.0-beta.320] - 2024-08-08 - -### 🚀 Features - -- Delete team in cloud without subscription -- Coolify init should cleanup stuck networks in proxy -- Add manual update check functionality to settings page -- Update auto update and update check frequencies in settings -- Update Upgrade component to check for latest version of Coolify -- Improve homepage service template -- Support map fields in Directus -- Labels by proxy type -- Able to generate only the required labels for resources - -### 🐛 Bug Fixes - -- Only append docker network if service/app is running -- Remove lazy load from scheduled tasks -- Plausible template -- Service_url should not have a trailing slash -- If usagebefore cannot be determined, cleanup docker with force -- Async remote command -- Only run logdrain if necessary -- Remove network if it is only connected to coolify proxy itself -- Dir mounts should have proper dirs -- File storages (dir/file mount) handled properly -- Do not use port exposes on docker compose buildpacks -- Minecraft server template fixed -- Graceful shutdown -- Stop resources gracefully -- Handle null and empty disk usage in DockerCleanupJob -- Show latest version on manual update view -- Empty string content should be saved as a file -- Update Traefik labels on init -- Add missing middleware for server check job - -### 🚜 Refactor - -- Update CleanupDatabase.php to adjust keep_days based on environment -- Adjust keep_days in CleanupDatabase.php based on environment -- Remove commented out code for cleaning up networks in CleanupDocker.php -- Update livewire polling interval in heading.blade.php -- Remove unused code for checking server status in Heading.php -- Simplify log drain installation in ServerCheckJob -- Remove unnecessary debug statement in ServerCheckJob -- Simplify log drain installation and stop log drain if necessary -- Cleanup unnecessary dynamic proxy configuration in Init command -- Remove unnecessary debug statement in ApplicationDeploymentJob -- Update timeout for graceful_shutdown_container in ApplicationDeploymentJob -- Remove unused code and optimize CheckForUpdatesJob -- Update ProxyTypes enum values to use TRAEFIK instead of TRAEFIK_V2 -- Update Traefik labels on init and cleanup unnecessary dynamic proxy configuration - -### 🎨 Styling - -- Linting - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.320 -- Add pull_request image builds to GH actions -- Add comment explaining the purpose of disconnecting the network in cleanup_unused_network_from_coolify_proxy() -- Update formbricks template -- Update registration view to display a notice for first user that it will be an admin -- Update server form to use password input for IP Address/Domain field -- Update navbar to include service status check -- Update navbar and configuration to improve service status check functionality -- Update workflows to include PR build and merge manifest steps -- Update UpdateCoolifyJob timeout to 10 minutes -- Update UpdateCoolifyJob to dispatch CheckForUpdatesJob synchronously - -## [4.0.0-beta.319] - 2024-07-26 - -### 🐛 Bug Fixes - -- Parse docker composer -- Service env parsing -- Service env variables -- Activity type invalid -- Update env on ui - -### 💼 Other - -- Service env parsing - -### ⚙️ Miscellaneous Tasks - -- Collect/create/update volumes in parseDockerComposeFile function - -## [4.0.0-beta.318] - 2024-07-24 - -### 🚀 Features - -- Create/delete project endpoints -- Add patch request to projects -- Add server api endpoints -- Add branddev logo to README.md -- Update API endpoint summaries -- Update Caddy button label in proxy.blade.php -- Check custom internal name through server's applications. -- New server check job - -### 🐛 Bug Fixes - -- Preview deployments should be stopped properly via gh webhook -- Deleting application should delete preview deployments -- Plane service images -- Fix issue with deployment start command in ApplicationDeploymentJob -- Directory will be created by default for compose host mounts -- Restart proxy does not work + status indicator on the UI -- Uuid in api docs type -- Raw compose deployment .env not found -- Api -> application patch endpoint -- Remove pull always when uploading backup to s3 -- Handle array env vars -- Link in task failed job notifications -- Random generated uuid will be full length (not 7 characters) -- Gitlab service -- Gitlab logo -- Bitbucket repository url -- By default volumes that we cannot determine if they are directories or files are treated as directories -- Domain update on services on the UI -- Update SERVICE_FQDN/URL env variables when you change the domain -- Several shared environment variables in one value, parsed correctly -- Members of root team should not see instance admin stuff - -### 💼 Other - -- Formbricks template add required CRON_SECRET -- Add required CRON_SECRET to Formbricks template - -### ⚙️ Miscellaneous Tasks - -- Update APP_BASE_URL to use SERVICE_FQDN_PLANE -- Update resource-limits.blade.php with improved input field helpers -- Update version numbers to 4.0.0-beta.319 -- Remove commented out code for docker image pruning - -## [4.0.0-beta.314] - 2024-07-15 - -### 🚀 Features - -- Improve error handling in loadComposeFile method -- Add readonly labels -- Preserve git repository -- Force cleanup server - -### 🐛 Bug Fixes - -- Typo in is_literal helper -- Env is_literal helper text typo -- Update docker compose pull command with --policy always -- Plane service template -- Vikunja -- Docmost template -- Drupal -- Improve github source creation -- Tag deployments -- New docker compose parsing -- Handle / in preselecting branches -- Handle custom_internal_name check in ApplicationDeploymentJob.php -- If git limit reached, ignore it and continue with a default selection -- Backup downloads -- Missing input for api endpoint -- Volume detection (dir or file) is fixed -- Supabase -- Create file storage even if content is empty - -### 💼 Other - -- Add basedir + compose file in new compose based apps - -### 🚜 Refactor - -- Remove unused code and fix storage form layout -- Update Docker Compose build command to include --pull flag -- Update DockerCleanupJob to handle nullable usageBefore property -- Server status job and docker cleanup job -- Update DockerCleanupJob to use server settings for force cleanup -- Update DockerCleanupJob to use server settings for force cleanup -- Disable health check for Rust applications during deployment - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.315 -- Update version to 4.0.0-beta.316 -- Update bug report template -- Update repository form with simplified URL input field -- Update width of container in general.blade.php -- Update checkbox labels in general.blade.php -- Update general page of apps -- Handle JSON parsing errors in format_docker_command_output_to_json -- Update Traefik image version to v2.11 -- Update version to 4.0.0-beta.317 -- Update version to 4.0.0-beta.318 -- Update helper message with link to documentation -- Disable health check by default -- Remove commented out code for sending internal notification - -### ◀️ Revert - -- Pull policy -- Advanced dropdown - -## [4.0.0-beta.308] - 2024-07-11 - -### 🚀 Features - -- Cleanup unused docker networks from proxy -- Compose parser v2 -- Display time interval for rollback images -- Add security and storage access key env to twenty template -- Add new logo for Latitude -- Enable legacy model binding in Livewire configuration - -### 🐛 Bug Fixes - -- Do not overwrite hardcoded variables if they rely on another variable -- Remove networks when deleting a docker compose based app -- Api -- Always set project name during app deployments -- Remove volumes as well -- Gitea pr previews -- Prevent instance fqdn persisting to other servers dynamic proxy configs -- Better volume cleanups -- Cleanup parameter -- Update redirect URL in unauthenticated exception handler -- Respect top-level configs and secrets -- Service status changed event -- Disable sentinel until a few bugs are fixed -- Service domains and envs are properly updated -- *(reactive-resume)* New healthcheck command for MinIO -- *(MinIO)* New command healthcheck -- Update minio hc in services -- Add validation for missing docker compose file - -### 🚜 Refactor - -- Add force parameter to StartProxy handle method -- Comment out unused code for network cleanup -- Reset default labels when docker_compose_domains is modified -- Webhooks view -- Tags view -- Only get instanceSettings once from db -- Update Dockerfile to set CI environment variable to true -- Remove unnecessary code in AppServiceProvider.php -- Update Livewire configuration views -- Update Webhooks.php to use nullable type for webhook URLs -- Add lazy loading to tags in Livewire configuration view -- Update metrics.blade.php to improve alert message clarity -- Update version numbers to 4.0.0-beta.312 -- Update version numbers to 4.0.0-beta.314 - -### ⚙️ Miscellaneous Tasks - -- Update Plausible docker compose template to Plausible 2.1.0 -- Update Plausible docker compose template to Plausible 2.1.0 -- Update livewire/livewire dependency to version 3.4.9 -- Refactor checkIfDomainIsAlreadyUsed function -- Update storage.blade.php view for livewire project service -- Update version to 4.0.0-beta.310 -- Update composer dependencies -- Add new logo for Latitude -- Bump version to 4.0.0-beta.311 - -### ◀️ Revert - -- Instancesettings - -## [4.0.0-beta.301] - 2024-06-24 - -### 🚀 Features - -- Local fonts -- More API endpoints -- Bulk env update api endpoint -- Update server settings metrics history days to 7 -- New app API endpoint -- Private gh deployments through api -- Lots of api endpoints -- Api api api api api api -- Rename CloudCleanupSubs to CloudCleanupSubscriptions -- Early fraud warning webhook -- Improve internal notification message for early fraud warning webhook -- Add schema for uuid property in app update response - -### 🐛 Bug Fixes - -- Run user commands on high prio queue -- Load js locally -- Remove lemon + paddle things -- Run container commands on high priority -- Image logo -- Remove both option for api endpoints. it just makes things complicated -- Cleanup subs in cloud -- Show keydbs/dragonflies/clickhouses -- Only run cloud clean on cloud + remove root team -- Force cleanup on busy servers -- Check domain on new app via api -- Custom container name will be the container name, not just internal network name -- Api updates -- Yaml everywhere -- Add newline character to private key before saving -- Add validation for webhook endpoint selection -- Database input validators -- Remove own app from domain checks -- Return data of app update - -### 💼 Other - +- Error with follow logs +- IsDomainConfigured +- TransactionIds +- Coolify image cleanup +- Cleanup every 10 mins +- Cleanup images +- Add no user redis to uri +- Secure cookie disabled by default +- Buggy svelte-kit-cookie-session +- Login issues +- SSL app off +- Local docker host +- Typo +- Lets encrypt +- Remove SSL with stop +- SSL off for services +- Grr +- Running state css +- Minor fixes +- Remove force SSL when doing let's encrypt request +- GhToken in session now +- Random port for certbot +- Follow icon +- Plausible volume fixed +- Database connection strings +- Gitlab webhooks fixed +- If DNS not found, do not redirect +- Github token +- Move tokens from session to cookie/store +- Email is lowercased in login +- Lowercase email everywhere +- Use normal docker-compose in dev +- Random network name for demo +- Settings fqdn grr +- Revert default network +- Http for demo, oops +- Docker scanner +- Improvement on image pulls +- Coolify image pulls +- Remove wrong/stuck proxy configurations +- Always use a buildpack +- Add icons for eleventy + astro +- Fix proxy every 10 secs +- Do not remove coolify proxy +- Update version +- Be sure .env exists +- Missing fqdn for services +- Default npm command +- Add coolify-image label for build images +- Cleanup old images, > 3 days +- Better proxy check +- Ssl + sslrenew +- Null proxyhash on restart +- Reconfigure proxy on restart - Update process -- Glances service -- Glances -- Able to update application - -### 🚜 Refactor - -- Update Service model's saveComposeConfigs method -- Add default environment to Service model's saveComposeConfigs method -- Improve handling of default environment in Service model's saveComposeConfigs method -- Remove commented out code in Service model's saveComposeConfigs method -- Update stack-form.blade.php to include wire:target attribute for submit button -- Update code to use str() instead of Str::of() for string manipulation -- Improve formatting and readability of source.blade.php -- Add is_build_time property to nixpacks_php_fallback_path and nixpacks_php_root_dir -- Simplify code for retrieving subscription in Stripe webhook - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.302 -- Update version to 4.0.0-beta.303 -- Update version to 4.0.0-beta.305 -- Update version to 4.0.0-beta.306 -- Add log1x/laravel-webfonts package -- Update version to 4.0.0-beta.307 -- Refactor ServerStatusJob constructor formatting -- Update Monaco Editor for Docker Compose and Proxy Configuration -- More details -- Refactor shared.php helper functions - -## [4.0.0-beta.298] - 2024-06-24 - -### 🚀 Features - -- Spanish translation -- Cancelling a deployment will check if new could be started. -- Add supaguide logo to donations section -- Nixpacks now could reach local dbs internally -- Add Tigris logo to other/logos directory -- COOLIFY_CONTAINER_NAME predefined variable -- Charts -- Sentinel + charts -- Container metrics -- Add high priority queue -- Add metrics warning for servers without Sentinel enabled -- Add blacksmith logo to donations section -- Preselect server and destination if only one found -- More api endpoints -- Add API endpoint to update application by UUID -- Update statusnook logo filename in compose template - -### 🐛 Bug Fixes - -- Stripprefix middleware correctly labeled to http -- Bitbucket link -- Compose generator -- Do no truncate repositories wtih domain (git) in it -- In services should edit compose file for volumes and envs -- Handle laravel deployment better -- Db proxy status shown better in the UI -- Show commit message on webhooks + prs -- Metrics parsing -- Charts -- Application custom labels reset after saving -- Static build with new nixpacks build process -- Make server charts one livewire component with one interval selector -- You can now add env variable from ui to services -- Update compose environment with UI defined variables -- Refresh deployable compose without reload -- Remove cloud stripe notifications -- App deployment should be in high queue -- Remove zoom from modals -- Get envs before sortby -- MB is % lol -- Projects with 0 envs - -### 💼 Other - -- Unnecessary notification - -### 🚜 Refactor - -- Update text color for stderr output in deployment show view -- Update text color for stderr output in deployment show view -- Remove debug code for saving environment variables -- Update Docker build commands for better performance and flexibility -- Update image sizes and add new logos to README.md -- Update README.md with new logos and fix styling -- Update shared.php to use correct key for retrieving sentinel version -- Update container name assignment in Application model -- Remove commented code for docker container removal -- Update Application model to include getDomainsByUuid method -- Update Project/Show component to sort environments by created_at -- Update profile index view to display 2FA QR code in a centered container -- Update dashboard.blade.php to use project's default environment for redirection -- Update gitCommitLink method to handle null values in source.html_url -- Update docker-compose generation to use multi-line literal block - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.298 -- Switch to database sessions from redis -- Update dependencies and remove unused code -- Update tailwindcss and vue versions in package.json -- Update service template URL in constants.php -- Update sentinel version to 0.0.8 -- Update chart styling and loading text -- Update sentinel version to 0.0.9 -- Update Spanish translation for failed authentication messages -- Add portuguese traslation -- Add Turkish translations -- Add Vietnamese translate -- Add Treive logo to donations section -- Update README.md with latest release version badge -- Update latest release version badge in README.md -- Update version to 4.0.0-beta.299 -- Move server delete component to the bottom of the page -- Update version to 4.0.0-beta.301 - -## [4.0.0-beta.297] - 2024-06-11 - -### 🚀 Features - -- Easily redirect between www-and-non-www domains -- Add logos for new sponsors -- Add homepage template -- Update homepage.yaml with environment variables and volumes - -### 🐛 Bug Fixes - -- Multiline build args -- Setup script doesnt link to the correct source code file -- Install.sh do not reinstall packages on arch -- Just restart - -### 🚜 Refactor - -- Replaces duplications in code with a single function - -### ⚙️ Miscellaneous Tasks - -- Update page title in resource index view -- Update logo file path in logto.yaml -- Update logo file path in logto.yaml -- Remove commented out code for docker container removal -- Add isAnyDeploymentInprogress function to check if any deployments are in progress -- Add ApplicationDeploymentJob and pint.json - -## [4.0.0-beta.295] - 2024-06-10 - -### 🚀 Features - -- Able to change database passwords on the UI. It won't sync to the database. -- Able to add several domains to compose based previews -- Add bounty program link to bug report template -- Add titles -- Db proxy logs - -### 🐛 Bug Fixes - -- Custom docker compose commands, add project dir if needed -- Autoupdate process -- Backup executions view -- Handle previously defined compose previews -- Sort backup executions -- Supabase service, newest versions -- Set default name for Docker volumes if it is null -- Multiline variable should be literal + should be multiline in bash with \ -- Gitlab merge request should close PR - -### 💼 Other - -- Rocketchat -- New services based git apps - -### 🚜 Refactor - -- Append utm_source parameter to documentation URL -- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview -- Update deployment previews heading to "Deployments" -- Remove unused variables and improve code readability -- Initialize null properties in Github Change component -- Improve pre and post deployment command inputs -- Improve handling of Docker volumes in parseDockerComposeFile function - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.295 -- Update supported OS list with almalinux -- Update install.sh to support PopOS -- Update install.sh script to version 1.3.2 and handle Linux Mint as Ubuntu - -## [4.0.0-beta.294] - 2024-06-04 - -### ⚙️ Miscellaneous Tasks - -- Update Dockerfile with latest versions of Docker, Docker Compose, Docker Buildx, Pack, and Nixpacks - -## [4.0.0-beta.289] - 2024-05-29 - -### 🚀 Features - -- Add PHP memory limit environment variable to docker-compose.prod.yml -- Add manual update option to UpdateCoolify handle method -- Add port configuration for Vaultwarden service - -### 🐛 Bug Fixes - -- Sync upgrade process -- Publish horizon -- Add missing team model -- Test new upgrade process? -- Throw exception -- Build server dirs not created on main server -- Compose load with non-root user -- Able to redeploy dockerfile based apps without cache -- Compose previews does have env variables -- Fine-tune cdn pulls -- Spamming :D -- Parse docker version better -- Compose issues -- SERVICE_FQDN has source port in it -- Logto service -- Allow invitations via email -- Sort by defined order + fixed typo -- Only ignore volumes with driver_opts -- Check env in args for compose based apps - -### 🚜 Refactor - -- Update destination.blade.php to add group class for better styling -- Applicationdeploymentjob -- Improve code structure in ApplicationDeploymentJob.php -- Remove unnecessary debug statement in ApplicationDeploymentJob.php -- Remove unnecessary debug statements and improve code structure in RunRemoteProcess.php and ApplicationDeploymentJob.php -- Remove unnecessary logging statements from UpdateCoolify -- Update storage form inputs in show.blade.php -- Improve Docker Compose parsing for services -- Remove unnecessary port appending in updateCompose function -- Remove unnecessary form class in profile index.blade.php -- Update form layout in invite-link.blade.php -- Add log entry when starting new application deployment -- Improve Docker Compose parsing for services -- Update Docker Compose parsing for services -- Update slogan in shlink.yaml -- Improve display of deployment time in index.blade.php -- Remove commented out code for clearing Ray logs -- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview - -### ⚙️ Miscellaneous Tasks - -- Update for version 289 -- Fix formatting issue in deployment index.blade.php file -- Remove unnecessary wire:navigate attribute in breadcrumbs.blade.php -- Rename docker dirs -- Update laravel/socialite to version v5.14.0 and livewire/livewire to version 3.4.9 -- Update modal styles for better user experience -- Update deployment index.blade.php script for better performance -- Update version numbers to 4.0.0-beta.290 -- Update version numbers to 4.0.0-beta.291 -- Update version numbers to 4.0.0-beta.292 -- Update version numbers to 4.0.0-beta.293 -- Add upgrade guide link to upgrade.blade.php -- Improve upgrade.blade.php with clearer instructions and formatting -- Update version numbers to 4.0.0-beta.294 -- Add Lightspeed.run as a sponsor -- Update Dockerfile to install vim - -## [4.0.0-beta.288] - 2024-05-28 - -### 🐛 Bug Fixes - -- Do not allow service storage mount point modifications -- Volume adding - -### ⚙️ Miscellaneous Tasks - -- Update Sentry release version to 4.0.0-beta.288 - -## [4.0.0-beta.287] - 2024-05-27 - -### 🚀 Features - -- Handle incomplete expired subscriptions in Stripe webhook -- Add more persistent storage types - -### 🐛 Bug Fixes - -- Force load services from cdn on reload list - -### ⚙️ Miscellaneous Tasks - -- Update Sentry release version to 4.0.0-beta.287 -- Add Thompson Edolo as a sponsor -- Add null checks for team in Stripe webhook - -## [4.0.0-beta.286] - 2024-05-27 - -### 🚀 Features - -- If the time seems too long it remains at 0s -- Improve Docker Engine start logic in ServerStatusJob -- If proxy stopped manually, it won't start back again -- Exclude_from_hc magic -- Gitea manual webhooks -- Add container logs in case the container does not start healthy - -### 🐛 Bug Fixes - -- Wrong time during a failed deployment -- Removal of the failed deployment condition, addition of since started instead of finished time -- Use local versions + service templates and query them every 10 minutes -- Check proxy functionality before removing unnecessary coolify.yaml file and checking Docker Engine -- Show first 20 users only in admin view -- Add subpath for services -- Ghost subdir -- Do not pull templates in dev -- Templates -- Update error message for invalid token to mention invalid signature -- Disable containerStopped job for now -- Disable unreachable/revived notifications for now -- JSON_UNESCAPED_UNICODE -- Add wget to nixpacks builds -- Pre and post deployment commands -- Bitbucket commits link -- Better way to add curl/wget to nixpacks -- Root team able to download backups -- Build server should not have a proxy -- Improve build server functionalities -- Sentry issue -- Sentry -- Sentry error + livewire downgrade -- Sentry -- Sentry -- Sentry error -- Sentry - -### 🚜 Refactor - -- Update edit-domain form in project service view -- Add Huly services to compose file -- Remove redundant heading in backup settings page -- Add isBuildServer method to Server model -- Update docker network creation in ApplicationDeploymentJob - -### ⚙️ Miscellaneous Tasks - -- Change pre and post deployment command length in applications table -- Refactor container name logic in GetContainersStatus.php and ForcePasswordReset.php -- Remove unnecessary content from Docker Compose file - -## [4.0.0-beta.285] - 2024-05-21 - -### 🚀 Features - -- Add SerpAPI as a Github Sponsor -- Admin view for deleting users -- Scheduled task failed notification - -### 🐛 Bug Fixes - -- Optimize new resource creation -- Show it docker compose has syntax errors - -### 💼 Other - -- Responsive here and there - -## [4.0.0-beta.284] - 2024-05-19 - -### 🚀 Features - -- Add hc logs to healthchecks - -### ◀️ Revert - -- Hc return code check - -## [4.0.0-beta.283] - 2024-05-17 - -### 🚀 Features - -- Update healthcheck test in StartMongodb action -- Add pull_request_id filter to get_last_successful_deployment method in Application model - -### 🐛 Bug Fixes - -- PR deployments have good predefined envs - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.283 - -## [4.0.0-beta.281] - 2024-05-17 - -### 🚀 Features - -- Shows the latest deployment commit + message on status -- New manual update process + remove next_channel -- Add lastDeploymentInfo and lastDeploymentLink props to breadcrumbs and status components -- Sort envs alphabetically and creation date -- Improve sorting of environment variables in the All component - -### 🐛 Bug Fixes - -- Hc from localhost to 127.0.0.1 -- Use rc in hc -- Telegram group chat notifications - -## [4.0.0-beta.280] - 2024-05-16 - -### 🐛 Bug Fixes - -- Commit message length - -## [4.0.0-beta.279] - 2024-05-16 - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.279 -- Limit commit message length to 50 characters in ApplicationDeploymentJob - -## [4.0.0-beta.278] - 2024-05-16 - -### 🚀 Features - -- Adding new COOLIFY_ variables -- Save commit message and better view on deployments -- Toggle label escaping mechanism - -### 🐛 Bug Fixes - -- Use commit hash on webhooks - -### ⚙️ Miscellaneous Tasks - -- Refactor Service.php to handle missing admin user in extraFields() method -- Update twenty CRM template with environment variables and dependencies -- Refactor applications.php to remove unused imports and improve code readability -- Refactor deployment index.blade.php for improved readability and rollback handling -- Refactor GitHub app selection UI in project creation form -- Update ServerLimitCheckJob.php to handle missing serverLimit value -- Remove unnecessary code for saving commit message -- Update DOCKER_VERSION to 26.0 in install.sh script -- Update Docker and Docker Compose versions in Dockerfiles - -## [4.0.0-beta.277] - 2024-05-10 - -### 🚀 Features - -- Add AdminRemoveUser command to remove users from the database - -### 🐛 Bug Fixes - -- Color for resource operation server and project name -- Only show realtime error on non-cloud instances -- Only allow push and mr gitlab events -- Improve scheduled task adding/removing -- Docker compose dependencies for pr previews -- Properly populating dependencies - -### 💼 Other - -- Fix a few boxes here and there - -### ⚙️ Miscellaneous Tasks - -- Update version numbers to 4.0.0-beta.278 -- Update hover behavior and cursor style in scheduled task executions view -- Refactor scheduled task view to improve code readability and maintainability -- Skip scheduled tasks if application or service is not running -- Remove debug logging statements in Kernel.php -- Handle invalid cron strings in Kernel.php - -## [4.0.0-beta.275] - 2024-05-06 - -### 🚀 Features - -- Add container name to network aliases in ApplicationDeploymentJob -- Add lazy loading for images in General.php and improve Docker Compose file handling in Application.php -- Experimental sentinel -- Start Sentinel on servers. -- Pull new sentinel image and restart container -- Init metrics - -### 🐛 Bug Fixes - -- Typo in tags.blade.php -- Install.sh error -- Env file -- Comment out internal notification in email_verify method -- Confirmation for custom labels -- Change permissions on newly created dirs - -### 💼 Other - -- Fix tag view - -### 🚜 Refactor - -- Add SCHEDULER environment variable to StartSentinel.php - -### ⚙️ Miscellaneous Tasks - -- Dark mode should be the default -- Improve menu item styling and spacing in service configuration and index views -- Improve menu item styling and spacing in service configuration and index views -- Improve menu item styling and spacing in project index and show views -- Remove docker compose versions -- Add Listmonk service template and logo -- Refactor GetContainersStatus.php for improved readability and maintainability -- Refactor ApplicationDeploymentJob.php for improved readability and maintainability -- Add metrics and logs directories to installation script -- Update sentinel version to 0.0.2 in versions.json -- Update permissions on metrics and logs directories -- Comment out server sentinel check in ServerStatusJob - -## [4.0.0-beta.273] - 2024-05-03 - -### 🐛 Bug Fixes - -- Formbricks image origin -- Add port even if traefik is used - -### ⚙️ Miscellaneous Tasks - -- Update version to 4.0.0-beta.275 -- Update DNS server validation helper text - -## [4.0.0-beta.267] - 2024-04-26 - -### 🚀 Features - -- Initial datalist -- Update service contribution docs URL -- The final pricing plan, pay-as-you-go - -### 🐛 Bug Fixes - -- Move s3 storages to separate view -- Mongo db backup -- Backups -- Autoupdate -- Respect start period and chekc interval for hc -- Parse HEALTHCHECK from dockerfile -- Make s3 name and endpoint required -- Able to update source path for predefined volumes -- Get logs with non-root user -- Mongo 4.0 db backup - -### 💼 Other - -- Update resource operations view - -### ◀️ Revert - -- Variable parsing - -## [4.0.0-beta.266] - 2024-04-24 - -### 🐛 Bug Fixes - -- Refresh public ips on start - -## [4.0.0-beta.259] - 2024-04-17 - -### 🚀 Features - -- Literal env variables -- Lazy load stuffs + tell user if compose based deployments have missing envs -- Can edit file/dir volumes from ui in compose based apps -- Upgrade Appwrite service template to 1.5 -- Upgrade Appwrite service template to 1.5 -- Add db name to backup notifications - -### 🐛 Bug Fixes - -- Helper image only pulled if required, not every 10 mins -- Make sure that confs when checking if it is changed sorted -- Respect .env file (for default values) -- Remove temporary cloudflared config -- Remove lazy loading until bug figured out -- Rollback feature -- Base64 encode .env -- $ in labels escaped -- .env saved to deployment server, not to build server -- Do no able to delete gh app without deleting resources -- 500 error on edge case -- Able to select server when creating new destination -- N8n template - -### 💼 Other - -- Non-root user for remote servers -- Non-root - -## [4.0.0-beta.258] - 2024-04-12 - -### 🚀 Features - -- Dynamic mux time - -### 🐛 Bug Fixes - -- Check each required binaries one-by-one - -## [4.0.0-beta.256] - 2024-04-12 - -### 🚀 Features - -- Upload large backups -- Edit domains easier for compose -- Able to delete configuration from server -- Configuration checker for all resources -- Allow tab in textarea - -### 🐛 Bug Fixes - -- Service config hash update -- Redeploy if image not found in restart only mode - -### 💼 Other - -- New pricing -- Fix allowTab logic -- Use 2 space instead of tab - -## [4.0.0-beta.252] - 2024-04-09 - -### 🚀 Features - -- Add amazon linux 2023 - -### 🐛 Bug Fixes - -- Git submodule update -- Unintended left padding on sidebar -- Hashed random delimeter in ssh commands + make sure to remove the delimeter from the command - -## [4.0.0-beta.250] - 2024-04-05 - -### 🚀 Features - -- *(application)* Update submodules after git checkout - -## [4.0.0-beta.249] - 2024-04-03 - -### 🚀 Features - -- Able to make rsa/ed ssh keys - -### 🐛 Bug Fixes - -- Warning if you use multiple domains for a service -- New github app creation -- Always rebuild Dockerfile / dockerimage buildpacks -- Do not rebuild dockerfile based apps twice -- Make sure if envs are changed, rebuild is needed -- Members cannot manage subscriptions -- IsMember -- Storage layout -- How to update docker-compose, environment variables and fqdns - -### 💼 Other - -- Light buttons -- Multiple server view - -## [4.0.0-beta.242] - 2024-03-25 - -### 🚀 Features - -- Change page width -- Watch paths - -### 🐛 Bug Fixes - -- Compose env has SERVICE, but not defined for Coolify -- Public service database -- Make sure service db proxy restarted -- Restart service db proxies -- Two factor -- Ui for tags -- Update resources view -- Realtime connection check -- Multline env in dev mode -- Scheduled backup for other service databases (supabase) -- PR deployments should not be distributed to 2 servers -- Name/from address required for resend -- Autoupdater -- Async service loads -- Disabled inputs are not trucated -- Duplicated generated fqdns are now working -- Uis -- Ui for cftunnels -- Search services -- Trial users subscription page -- Async public key loading -- Unfunctional server should see resources - -### 💼 Other - -- Run cleanup every day -- Fix -- Fix log outputs -- Automatic cloudflare tunnels -- Backup executions - -## [4.0.0-beta.241] - 2024-03-20 - -### 🚀 Features - -- Able to run scheduler/horizon programatically - -### 🐛 Bug Fixes - -- Volumes for prs -- Shared env variable parsing - -### 💼 Other - -- Redesign -- Redesign - -## [4.0.0-beta.240] - 2024-03-18 - -### 🐛 Bug Fixes - -- Empty get logs number of lines -- Only escape envs after v239+ -- 0 in env value -- Consistent container name -- Custom ip address should turn off rolling update -- Multiline input -- Raw compose deployment -- Dashboard view if no project found - -## [4.0.0-beta.239] - 2024-03-14 - -### 🐛 Bug Fixes - -- Duplicate dockerfile -- Multiline env variables -- Server stopped, service page not reachable - -## [4.0.0-beta.237] - 2024-03-14 - -### 🚀 Features - -- Domains api endpoint -- Resources api endpoint -- Team api endpoint -- Add deployment details to deploy endpoint -- Add deployments api -- Experimental caddy support -- Dynamic configuration for caddy -- Reset password -- Show resources on source page - -### 🐛 Bug Fixes - -- Deploy api messages -- Fqdn null in case docker compose bp -- Reload caddy issue -- /realtime endpoint -- Proxy switch -- Service ports for services + caddy -- Failed deployments should send failed email/notification -- Consider custom healthchecks in dockerfile -- Create initial files async -- Docker compose validation - -## [4.0.0-beta.235] - 2024-03-05 - -### 🐛 Bug Fixes - -- Should note delete personal teams -- Make sure to show some buttons -- Sort repositories by name - -## [4.0.0-beta.224] - 2024-02-23 - -### 🚀 Features - -- Custom server limit -- Delay container/server jobs -- Add static ipv4 ipv6 support -- Server disabled by overflow -- Preview deployment logs -- Collect webhooks during maintenance -- Logs and execute commands with several servers - -### 🐛 Bug Fixes - -- Subscription / plan switch, etc -- Firefly service -- Force enable/disable server in case ultimate package quantity decreases -- Server disabled -- Custom dockerfile location always checked -- Import to mysql and mariadb -- Resource tab not loading if server is not reachable -- Load unmanaged async -- Do not show n/a networsk -- Service container status updates -- Public prs should not be commented -- Pull request deployments + build servers -- Env value generation -- Sentry error -- Service status updated - -### 💼 Other - -- Change + icon to hamburger. - -## [4.0.0-beta.222] - 2024-02-22 - -### 🚀 Features - -- Able to add dynamic configurations from proxy dashboard - -### 🐛 Bug Fixes - -- Connections being stuck and not processed until proxy restarts -- Use latest image if nothing is specified -- No coolify.yaml found -- Server validation -- Statuses -- Unknown image of service until it is uploaded - -## [4.0.0-beta.220] - 2024-02-19 - -### 🚀 Features - -- Save github app permission locally -- Minversion for services - -### 🐛 Bug Fixes - -- Add openbsd ssh server check -- Resources -- Empty build variables -- *(server)* Revalidate server button not showing in server's page -- Fluent bit ident level -- Submodule cloning -- Database status -- Permission change updates from webhook -- Server validation - -### 💼 Other - -- Updates - -## [4.0.0-beta.213] - 2024-02-12 - -### 🚀 Features - -- Magic for traefik redirectregex in services -- Revalidate server -- Disable gzip compression on service applications - -### 🐛 Bug Fixes - -- Cleanup scheduled tasks -- Padding left on input boxes -- Use ls / command instead ls -- Do not add the same server twice -- Only show redeployment required if status is not exited - -## [4.0.0-beta.212] - 2024-02-08 - -### 🚀 Features - -- Cleanup queue - -### 🐛 Bug Fixes - -- New menu on navbar -- Make sure resources are deleted in async mode -- Go to prod env from dashboard if there is no other envs defined -- User proper image_tag, if set -- New menu ui -- Lock logdrain configuration when one of them are enabled -- Add docker compose check during server validation -- Get service stack as uuid, not name -- Menu -- Flex wrap deployment previews -- Boolean docker options -- Only add 'networks' key if 'network_mode' is absent - -## [4.0.0-beta.206] - 2024-02-05 - -### 🚀 Features - -- Clone to env -- Multi deployments - -### 🐛 Bug Fixes - -- Wrap tags and avoid horizontal overflow -- Stripe webhooks -- Feedback from self-hosted envs to discord - -### 💼 Other - -- Specific about newrelic logdrains - -## [4.0.0-beta.201] - 2024-01-29 - -### 🚀 Features - -- Added manual webhook support for bitbucket -- Add initial support for custom docker run commands -- Cleanup unreachable servers -- Tags and tag deploy webhooks - -### 🐛 Bug Fixes - -- Bitbucket manual deployments -- Webhooks for multiple apps -- Unhealthy deployments should be failed -- Add env variables for wordpress template without database -- Service deletion function -- Service deletion fix -- Dns validation + duplicated fqdns -- Validate server navbar upated -- Regenerate labels on application clone -- Service deletion -- Not able to use other shared envs -- Sentry fix -- Sentry -- Sentry error -- Sentry -- Sentry error -- Create dynamic directory -- Migrate to new modal -- Duplicate domain check -- Tags - -### 💼 Other - -- New modal component - -## [4.0.0-beta.188] - 2024-01-11 - -### 🚀 Features - -- Search between resources -- Move resources between projects / environments -- Clone any resource -- Shared environments -- Concurrent builds / server -- Able to deploy multiple resources with webhook -- Add PR comments -- Dashboard live deployment view - -### 🐛 Bug Fixes - -- Preview deployments with nixpacks -- Cleanup docker stuffs before upgrading -- Service deletion command -- Cpuset limits was determined in a way that apps only used 1 CPU max, ehh, sorry. -- Service stack view -- Change proxy view -- Checkbox click -- Git pull command for deploy key based previews -- Server status job -- Service deletion bug! -- Links -- Redis custom conf -- Sentry error -- Restrict concurrent deployments per server -- Queue -- Change env variable length - -### 💼 Other - -- Send notification email if payment - -### 🚜 Refactor - -- Compose file and install script - -## [4.0.0-beta.186] - 2024-01-11 - -### 🚀 Features - -- Import backups - -### 🐛 Bug Fixes - -- Do not include thegameplan.json into build image -- Submit error on postgresql -- Email verification / forgot password -- Escape build envs properly for nixpacks + docker build -- Undead endpoint -- Upload limit on ui -- Save cmd output propely (merge) -- Load profile on remote commands -- Load profile and set envs on remote cmd -- Restart should not update config hash - -## [4.0.0-beta.184] - 2024-01-09 - -### 🐛 Bug Fixes - -- Healthy status -- Show framework based notification in build logs -- Traefik labels -- Use ip for sslip in dev if remote server is used -- Service labels without ports (unknown ports) -- Sort and rename (unique part) of labels -- Settings menu -- Remove traefik debug in dev mode -- Php pgsql to 8.2 -- Static buildpack should set port 80 -- Update navbar on build_pack change - -## [4.0.0-beta.183] - 2024-01-06 - -### 🚀 Features - -- Add www-non-www redirects to traefik - -### 🐛 Bug Fixes - -- Database env variables - -## [4.0.0-beta.182] - 2024-01-04 - -### 🐛 Bug Fixes - -- File storage save - -## [4.0.0-beta.181] - 2024-01-03 - -### 🐛 Bug Fixes - -- Nixpacks buildpack - -## [4.0.0-beta.180] - 2024-01-03 - -### 🐛 Bug Fixes - -- Nixpacks cache -- Only add restart policy if its empty (compose) - -## [4.0.0-beta.179] - 2024-01-02 - -### 🐛 Bug Fixes - -- Set deployment failed if new container is not healthy - -## [4.0.0-beta.177] - 2024-01-02 - -### 🚀 Features - -- Raw docker compose deployments - -### 🐛 Bug Fixes - -- Duplicate compose variable - -## [4.0.0-beta.176] - 2023-12-31 - -### 🐛 Bug Fixes - -- Horizon - -## [4.0.0-beta.175] - 2023-12-30 - -### 🚀 Features - -- Add environment description + able to change name - -### 🐛 Bug Fixes - -- Sub -- Wrong env variable parsing -- Deploy key + docker compose - -## [4.0.0-beta.174] - 2023-12-27 - -### 🐛 Bug Fixes - -- Restore falsely deleted coolify-db-backup - -## [4.0.0-beta.173] - 2023-12-27 - -### 🐛 Bug Fixes - -- Cpu limit to float from int -- Add source commit to final envs -- Routing, switch back to old one -- Deploy instead of restart in case swarm is used -- Button title - -## [4.0.0-beta.163] - 2023-12-15 - -### 🚀 Features - -- Custom docker compose commands - -### 🐛 Bug Fixes - -- Domains for compose bp -- No action in webhooks -- Add debug output to gitlab webhooks -- Do not push dockerimage -- Add alpha to swarm -- Server not found -- Do not autovalidate server on mount -- Server update schedule -- Swarm support ui -- Server ready -- Get swarm service logs -- Docker compose apps env rewritten -- Storage error on dbs -- Why?! -- Stay tuned - -### 💼 Other - -- Swarm -- Swarm - -## [4.0.0-beta.155] - 2023-12-11 - -### 🚀 Features - -- Autoupdate env during seed -- Disable autoupdate -- Randomly sleep between executions -- Pull latest images for services - -### 🐛 Bug Fixes - -- Do not send telegram noti on intent payment failed -- Database ui is realtime based -- Live mode for github webhooks -- Ui -- Realtime connection popup could be disabled -- Realtime check -- Add new destination -- Proxy logs -- Db status check -- Pusher host -- Add ipv6 -- Realtime connection?! -- Websocket -- Better handling of errors with install script -- Install script parse version -- Only allow to modify in .env file if AUTOUPDATE is set -- Is autoupdate not null -- Run init command after production seeder -- Init -- Comma in traefik custom labels -- Ignore if dynamic config could not be set -- Service env variable ovewritten if it has a default value -- Labelling -- Non-ascii chars in labels -- Labels -- Init script echos -- Update Coolify script -- Null notify -- Check queued deployments as well -- Copy invitation -- Password reset / invitation link requests -- Add catch all route -- Revert random container job delay -- Backup executions view -- Only check server status in container status job -- Improve server status check times -- Handle other types of generated values -- Server checking status -- Ui for adding new destination -- Reset domains on compose file change - -### 💼 Other - -- Fix for comma in labels -- Add image name to service stack + better options visibility - -### 🚜 Refactor - -- Service logs are now on one page -- Application status changed realtime -- Custom labels -- Clone project - -## [4.0.0-beta.154] - 2023-12-07 - -### 🚀 Features - -- Execute command in container - -### 🐛 Bug Fixes - -- Container selection -- Service navbar using new realtime events -- Do not create duplicated networks -- Live event -- Service start + event -- Service deletion job -- Double ws connection -- Boarding view - -### 💼 Other - -- Env vars -- Migrate to livewire 3 - -## [4.0.0-beta.124] - 2023-11-13 - -### 🚀 Features - -- Log drain (wip) -- Enable/disable log drain by service -- Log drainer container check -- Add docker engine support install script to rhel based systems -- Save timestamp configuration for logs -- Custom log drain endpoints -- Auto-restart tcp proxies for databases - -### 🐛 Bug Fixes - -- *(fider template)* Use the correct docs url -- Fqdn for minio -- Generate service fields -- Mariadb backups -- When to pull image -- Do not allow to enter local ip addresses -- Reset password -- Only report nonruntime errors -- Handle different label formats in services -- Server adding process -- Show defined resources in server tab, so you will know what you need to delete before you can delete the server. -- Lots of regarding git + docker compose deployments -- Pull request build variables -- Double default password length -- Do not remove deployment in case compose based failed -- No container servers -- Sentry issue -- Dockercompose save ./ volumes under /data/coolify -- Server view for link() -- Default value do not overwrite existing env value -- Use official install script with rancher (one will work for sure) -- Add cf tunnel to boarding server view -- Prevent autorefresh of proxy status -- Missing docker image thing -- Add hc for soketi -- Deploy the right compose file -- Bind volumes for compose bp -- Use hc port 80 in case of static build -- Switching to static build - -### 💼 Other - -- New deployment jobs -- Compose based apps -- Swarm -- Swarm -- Swarm -- Swarm -- Disable trial -- Meilisearch -- Broadcast -- 🌮 - -### 🚜 Refactor - -- Env variable generator - -### ◀️ Revert - -- Wip - -## [4.0.0-beta.109] - 2023-11-06 - -### 🚀 Features - -- Deployment logs fullscreen -- Service database backups -- Make service databases public - -### 🐛 Bug Fixes - -- Missing environment variables prevewi on service -- Invoice.paid should sleep for 5 seconds -- Local dev repo -- Deployments ui -- Dockerfile build pack fix -- Set labels on generate domain -- Network service parse -- Notification url in containerstatusjob -- Gh webhook response 200 to installation_repositories -- Delete destination -- No id found -- Missing $mailMessage -- Set default from/sender names -- No environments -- Telegram text -- Private key not found error +- Reload proxy on ssl cert +- Volume name +- Update process +- Check when a container is running +- Reload haproxy if new cert is added +- Cleanup coolify images +- Application state in UI +- Do not error if proxy is not running +- Personal Gitlab repos +- Autodeploy true by default for GH repos +- No cookie found +- Missing session data +- No error if GitSource is missing +- No webhook secret found? +- Basedir for dockerfiles +- Better queue system + more support on monorepos +- Remove build logs in case of app removed +- Cleanup old builds +- Only cleanup same app +- Add nginx + htaccess files +- Skip ssl cert in case of error +- Volumes +- Cleanup only 2 hours+ old images +- Ghost logo size +- Ghost icon, remove console.log +- List ghost services +- Reload window on settings saved +- Persistent storage on webhooks +- Add license +- Space in repo names +- Gitlab repo url +- No need to dashify anymore +- Registration enabled/disabled +- Add PROTO headers +- Haproxy errors +- Build variables +- Use NodeJS for sveltekit for now +- Ignore coolify proxy error for now +- Python no wsgi +- If user not found +- Rename envs to secrets +- Infinite loop on www domains +- No need to paste clear text env for previews +- Build log fix attempt #1 +- Small UI fix on logs +- Lets await! +- Async progress +- Remove console.log +- Build log - UI -- Resourcesdelete command -- Port number should be int -- Separate delete with validation of server -- Add nixpacks info -- Remove filter -- Container logs are now followable in full-screen and sorted by timestamp -- Ui for labels -- Ui -- Deletions -- Build_image not found -- Github source view -- Github source view -- Dockercleanupjob should be released back -- Ui -- Local ip address -- Revert workdir to basedir -- Container status jobs for old pr deployments -- Service updates - -## [4.0.0-beta.99] - 2023-10-24 - -### 🚀 Features - -- Improve deployment time by a lot - -### 🐛 Bug Fixes - -- Space in build args -- Lock SERVICE_FQDN envs -- If user is invited, that means its email is verified -- Force password reset on invited accounts -- Add ssh options to git ls-remote -- Git ls-remote -- Remove coolify labels from ui - -### 💼 Other - -- Fix subs - -## [4.0.0-beta.97] - 2023-10-20 - -### 🚀 Features - -- Standalone mongodb -- Cloning project -- Api tokens + deploy webhook -- Start all kinds of things -- Simple search functionality -- Mysql, mariadb -- Lock environment variables -- Download local backups - -### 🐛 Bug Fixes - -- Service docs links -- Add PGUSER to prevent HC warning -- Preselect s3 storage if available -- Port exposes change, shoud regenerate label -- Boarding -- Clone to with the same environment name -- Cleanup stucked resources on start -- Do not allow to delete env if a resource is defined -- Service template generator + appwrite -- Mongodb backup -- Make sure coolfiy network exists on install -- Syncbunny command -- Encrypt mongodb password -- Mongodb healtcheck command -- Rate limit for api + add mariadb + mysql -- Server settings guarded - -### 💼 Other - -- Generate services -- Mongodb backup -- Mongodb backup -- Updates - -## [4.0.0-beta.93] - 2023-10-18 - -### 🚀 Features - -- Able to customize docker labels on applications -- Show if config is not applied - -### 🐛 Bug Fixes - -- Setup:dev script & contribution guide -- Do not show configuration changed if config_hash is null -- Add config_hash if its null (old deployments) -- Label generation -- Labels -- Email channel no recepients -- Limit horizon processes to 2 by default -- Add custom port as ssh option to deploy_key based commands -- Remove custom port from git repo url -- ContainerStatus job - -### 💼 Other - -- PAT by team - -## [4.0.0-beta.92] - 2023-10-17 - -### 🐛 Bug Fixes - -- Proxy start process - -## [4.0.0-beta.91] - 2023-10-17 - -### 🐛 Bug Fixes - -- Always start proxy if not NONE is selected - -### 💼 Other - -- Add helper to service domains - -## [4.0.0-beta.90] - 2023-10-17 - -### 🐛 Bug Fixes - -- Only include config.json if its exists and a file - -### 💼 Other - -- Wordpress - -## [4.0.0-beta.89] - 2023-10-17 - -### 🐛 Bug Fixes - -- Noindex meta tag -- Show docker build logs - -## [4.0.0-beta.88] - 2023-10-17 - -### 🚀 Features - -- Use docker login credentials from server - -## [4.0.0-beta.87] - 2023-10-17 - -### 🐛 Bug Fixes - -- Service status check is a bit better -- Generate fqdn if you deleted a service app, but it requires fqdn -- Cancel any deployments + queue next -- Add internal domain names during build process - -## [4.0.0-beta.86] - 2023-10-15 - -### 🐛 Bug Fixes - -- Build image before starting dockerfile buildpacks - -## [4.0.0-beta.85] - 2023-10-14 - -### 🐛 Bug Fixes - -- Redis URL generated - -## [4.0.0-beta.83] - 2023-10-13 - -### 🐛 Bug Fixes - -- Docker hub URL - -## [4.0.0-beta.70] - 2023-10-09 - -### 🚀 Features - -- Add email verification for cloud -- Able to deploy docker images -- Add dockerfile location -- Proxy logs on the ui -- Add custom redis conf - -### 🐛 Bug Fixes - -- Server validation process -- Fqdn could be null -- Small -- Server unreachable count -- Do not reset unreachable count -- Contact docs -- Check connection -- Server saving -- No env goto envs from dashboard -- Goto -- Tcp proxy for dbs -- Database backups -- Only send email if transactional email set -- Backupfailed notification is forced -- Use port exposed for reverse proxy -- Contact link -- Use only ip addresses for servers -- Deleted team and it is the current one -- Add new team button -- Transactional email link -- Dashboard goto link -- Only require registry image in case of dockerimage bp -- Instant save build pack change -- Public git -- Cannot remove localhost -- Check localhost connection -- Send unreachable/revived notifications -- Boarding + verification -- Make sure proxy wont start in NONE mode -- Service check status 10 sec -- IsCloud in production seeder -- Make sure to use IP address -- Dockerfile location feature -- Server ip could be hostname in self-hosted -- Urls should be password fields -- No backup for redis -- Show database logs in case of its not healthy and running -- Proxy check for ports, do not kill anything listening on port 80/443 -- Traefik dashboard ip -- Db labels -- Docker cleanup jobs -- Timeout for instant remote processes -- Dev containerjobs -- Backup database one-by-one. -- Turn off static deployment if you switch buildpacks - -### 💼 Other - -- Dockerimage -- Updated dashboard -- Fix -- Fix -- Coolify proxy access logs exposed in dev -- Able to select environment on new resource -- Delete server -- Redis - -## [4.0.0-beta.58] - 2023-10-02 - -### 🚀 Features - -- Reset root password -- Attach Coolify defined networks to services -- Delete resource command -- Multiselect removable resources -- Disable service, required version -- Basedir / monorepo initial support -- Init version of any git deployment -- Deploy private repo with ssh key - -### 🐛 Bug Fixes - -- If waitlist is disabled, redirect to register -- Add destination to new services -- Predefined content for files -- Move /data to ./_data in dev -- UI -- Show all storages in one place for services -- Ui -- Add _data to vite ignore -- Only use _ in volume names for services -- Volume names in services -- Volume names -- Service logs visible if the whole service stack is not running -- Ui -- Compose magic -- Compose parser updated -- Dev compose files -- Traefik labels for multiport deployments -- Visible version number -- Remove SERVICE_ from deployable compose -- Delete event to deleting -- Move dev data to volumes to prevent permission issues -- Traefik labelling in case of several http and https domain added -- PR deployments use the first fqdn as base -- Email notifications subscription fixed -- Services - do not remove unnecessary things for now -- Decrease max horizon processes to get lower memory usage -- Test emails only available for user owned smtp/resend -- Ui for self-hosted email settings -- Set smtp notifications on by default -- Select branch on other git -- Private repository +- Gitlab & Github urls +- Secrets build/runtime coudl be changed after save +- Default configuration +- *(php)* If .htaccess file found use apache +- Add default webhook domain for n8n +- Add git lfs while deploying +- Try to update build status several times +- Update stucked builds +- Update stucked builds on startup +- Revert seed +- Lame fixing +- Remove asyncUntil +- Add openssl to image +- Permission issues +- On-demand sFTP for wp +- Fix for fix haha +- Do not pull latest image +- Updated db versions +- Only show proxy for admin team +- Team view for root team +- Do not trigger >1 webhooks on GitLab +- Possible fix for spikes in CPU usage +- Last commit +- Www or not-www, that's the question +- Fix for the fix that fixes the fix +- Ton of updates for users/teams +- Small typo +- Unique storage paths +- Self-hosted GitLab URL +- No line during buildLog +- Html/apiUrls cannot end with / +- Typo +- Missing buildpack +- Enable https for Ghost +- Postgres root passwor shown and set +- Able to change postgres user password from ui +- DB Connecting string generator +- Missing install repositories GitHub +- Return own and other sources better +- Show config missing on sources +- Remove unnecessary save button haha +- Update dockerfile +- Haproxy build stuffs +- Proxy +- Types +- Invitations +- Timeout values +- Cleanup images older than a day +- Meilisearch service +- Load all branches, not just the first 30 +- ProjectID for Github +- DNS check before creating SSL cert +- Try catch me +- Restart policy for resources +- No permission on first registration +- Reverting postgres password for now +- Destinations to HAProxy +- Register should happen if coolify proxy cannot be started +- GitLab typo +- Remove system wide pw reset +- Postgres root pw is pw field +- Teams view +- Improved tcp proxy monitoring for databases/ftp +- Add HTTP proxy checks +- Loading of new destinations +- Better performance for cleanup images +- Remove proxy container in case of dependent container is down +- Restart local docker coolify proxy in case of something happens to it +- Id of service container +- Switch from bitnami/redis to normal redis +- Use redis-alpine +- Wordpress extra config +- Stop sFTP connection on wp stop +- Change user's id in sftp wp instance +- Use arm based certbot on arm +- Buildlog line number is not string +- Application logs paginated +- Switch to stream on applications logs +- Scroll to top for logs +- Pull new images for services all the time it's started. +- White-labeled custom logo +- Application logs +- Deno configurations +- Text on deno buildpack +- Correct branch shown in build logs +- Vscode permission fix +- I18n +- Locales +- Application logs is not reversed and queried better +- Do not activate i18n for now +- GitHub token cleanup on team switch +- No logs found +- Code cleanups +- Reactivate posgtres password - Contribution guide -- Public repository names -- *(create)* Flex wrap on server & network selection -- Better unreachable/revived server statuses -- Able to set base dir for Dockerfile build pack - -### 💼 Other - -- Uptime kume hc updated -- Switch back to /data (volume errors) +- Simplify list services +- Contribution +- Contribution guide +- Contribution guide +- Packagemanager finder +- Unami svg size +- Team switching moved to IAM menu +- Always use IP address for webhooks +- Remove unnecessary test endpoint +- UI +- Migration +- Fider envs +- Checking low disk space +- Build image +- Update autoupdate env variable +- Renew certificates +- Webhook build images +- Missing node versions +- ExposedPorts +- Logos for dbs +- Do not run SSL renew in development +- Check domain for coolify before saving +- Remove debug info +- Cancel jobs +- Cancel old builds in database +- Better DNS check to prevent errors +- Check DNS in prod only +- DNS check +- Disable sentry for now +- Cancel +- Sentry +- No image for Docker buildpack +- Default packagemanager +- Server usage only shown for root team +- Expose ports for services +- UI +- Navbar UI +- UI +- UI +- Remove RC python +- UI +- UI +- UI +- Default Python package +- WP custom db +- UI +- Gastby buildpack +- Service checks +- Remove console.log +- Traefik +- Remove debug things +- WIP Traefik +- Proxy for http +- PR deployments view +- Minio urls + domain checks +- Remove gh token on git source changes +- Do not fetch app state in case of missconfiguration +- Demo instance save domain instantly +- Instant save on demo instance +- New source canceled view +- Lint errors in database services +- Otherfqdns +- Host key verification +- Ftp connection +- GitHub fixes +- TrustProxy +- Force restart proxy +- Only restart coolify proxy in case of version prior to 2.9.2 +- Force restart proxy on seeding +- Add GIT ENV variable for submodules +- Recurisve clone instead of submodule +- Versions +- Only reconfigure coolify proxy if its missconfigured +- Demo version forms +- Typo +- Revert gh and gl cloning +- Proxy stop missing argument +- Fider changed an env variable name +- Pnpm command +- Plausible custom script +- Plausible script and middlewares +- Remove console log +- Remove comments +- Traefik middleware +- Persistent nocodb +- Nocodb persistency +- Host and reload for uvicorn +- Remove package-lock +- Be able to change database + service versions +- Lock file +- Seeding +- Forgot that the version bump changed 😅 +- New destination can be created +- Include post +- New destinations +- Domain check +- Domain check +- TrustProxy for Fastify +- Hostname issue +- GitLab pagination load data +- Service domain checker +- Wp missing ftp solution +- Ftp WP issues +- Ftp?! +- Gitpod updates +- Gitpod +- Gitpod +- Wordpress FTP permission issues +- GitLab search fields +- GitHub App button +- GitLab loop on misconfigured source +- Gitpod +- Cleanup less often and can do it manually +- Admin password reset should not timeout +- Message for double branches +- Turn off autodeploy if double branch is configured +- More types for API +- More types +- Do not rebuild in case image exists and sha not changed +- Gitpod urls +- Remove new service start process +- Remove shared dir, deployment does not work +- Gitlab custom url +- Location url for services and apps +- Settings from api +- Selectable destinations +- Gitpod hardcodes +- Typo +- Typo +- Expose port checker +- States and exposed ports +- CleanupStorage +- Remote traefik webhook +- Remote engine ip address +- RemoteipAddress +- Explanation for remote engine url +- Tcp proxy +- Lol +- Webhook +- Dns check for rde +- Gitpod +- Revert last commit +- Dns check +- Dns checker +- Webhook +- Df and more debug +- Webhooks +- Load previews async +- Destination icon +- Pr webhook +- Cache image +- No ssh key found +- Prisma migration + update of docker and stuffs +- Ui +- Ui +- Only 1 ssh-agent is needed +- Reuse ssh connection +- Ssh tunnel +- Dns checking +- Fider BASE_URL set correctly +- Rde local ports +- Empty remote destinations could be removed +- Tips +- Lowercase issues fider +- Tooltip colors +- Update clickhouse configuration +- Cleanup command +- Enterprise Github instance endpoint +- Follow/cancel buttons +- Only remove coolify managed containers +- White-labeled env +- Schema +- Coolify-network on verification +- Cleanup stucked prisma-engines +- Toast +- Secrets +- Cleanup prisma engine if there is more than 1 +- !isARM to isARM +- Enterprise GH link +- Empty buildpack icons +- Debounce dashboard status requests +- Decryption errors +- Postgresql on ARM +- Make it public button +- Loading indicator +- Replace docker compose with docker-compose on CSB +- Dashboard ui +- Create coolify-infra, if it does not exists +- Gitpod conf and heroku buildpacks +- Appwrite +- Autoimport + readme +- Services import +- Heroku icon +- Heroku icon +- Dns button ui +- Bot deployments +- Bots +- AutoUpdater & cleanupStorage jobs +- Revert docker compose version to 2.6.1 +- Trim secrets +- Restart containers on-failure instead of always +- Show that Ghost values could be changed +- Bots without exposed ports +- Missing commas +- ExposedPort is just optional +- Port checker +- Cancel build after 5 seconds +- ExposedPort checker +- Batch secret = +- Dashboard for non-root users +- Stream build logs +- Show build log start/end +- Ui buttons +- Clear queue on cancelling jobs +- Cancelling jobs +- Dashboard for admins +- Never stop deplyo queue +- Build queue system +- High cpu usage +- Worker +- Better worker system +- Secrets decryption +- UI thinkgs +- Delete team while it is active +- Team switching +- Queue cleanup +- Decrypt secrets +- Cleanup build cache as well +- Pr deployments + remove public gits +- Copy all files during install process +- Typo +- Process +- White labeled icon on navbar +- Whitelabeled icon +- Next/nuxt deployment type +- Again +- Pr deployment +- CompareVersions +- Include +- Include +- Gitlab apps +- Oh god Prisma +- Glitchtip things +- Loading state on start +- Ui +- Submodule +- Gitlab webhooks +- UI + refactor +- Exposedport on save +- Appwrite letsencrypt +- Traefik appwrite +- Traefik +- Finally works! :) +- Rename components + remove PR/MR deployment from public repos +- Settings missing id +- Explainer component +- Database name on logs view +- Taiga +- Ssh pid agent name +- Repository link trim +- Fqdn or expose port required +- Service deploymentEnabled +- Expose port is not required +- Remote verification +- Dockerfile +- Debug api logging + gh actions +- Workdir +- Move restart button to settings +- Gitlab webhook +- Use ip address instead of window location +- Use ip instead of window location host +- Service state update +- Add initial DNS servers +- Revert last change with domain check +- Service volume generation +- Minio default env variables +- Add php 8.1/8.2 +- Edgedb ui +- Edgedb stuff +- Edgedb +- Pr previews +- DnsServer formatting +- Settings for service +- Change to execa from utils +- Save search input +- Ispublic status on databases +- Port checkers +- Ui variables +- Glitchtip env to pyhton boolean +- Autoupdater +- Show restarting apps +- Show restarting application & logs +- Remove unnecessary gitlab group name +- Secrets for PR +- Volumes for services +- Build secrets for apps +- Delete resource use window location +- Changing umami image URL to get latest version +- Gitlab importer for public repos +- Show error logs +- Umami init sql +- Plausible analytics actions +- Login +- Dev url +- UpdateMany build logs +- Fallback to db logs +- Fluentbit configuration +- Coolify update +- Fluentbit and logs +- Canceling build +- Logging +- Load more +- Build logs +- Versions of appwrite +- Appwrite?! +- Get building status +- Await +- Await #2 +- Update PR building status +- Appwrite default version 1.0 +- Undead endpoint does not require JWT +- *(routes)* Improve design of application page +- *(routes)* Improve design of git sources page +- *(routes)* Ui from destinations page +- *(routes)* Ui from databases page +- *(routes)* Ui from databases page +- *(routes)* Ui from databases page +- *(routes)* Ui from services page +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* Ui from settings page +- *(routes)* Duplicates classes in services page +- *(routes)* Searchbar ui +- Github conflicts +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- *(routes)* More ui tweaks +- Ui with headers +- *(routes)* Header of settings page in databases +- *(routes)* Ui from secrets table +- Ui +- Tooltip +- Dropdown +- Ssl certificate distribution +- Db migration +- Multiplex ssh connections +- Able to search with id +- Not found redirect +- Settings db requests +- Error during saving logs +- Consider base directory in heroku bp +- Basedirectory should be empty if null +- Allow basedirectory for heroku +- Stream logs for heroku bp +- Debug log for bp +- Scp without host verification & cert copy +- Base directory & docker bp +- Laravel php chooser +- Multiplex ssh and ssl copy +- Seed new preview secret types +- Error notification +- Empty preview value +- Error notification +- Seed +- Service logs +- Appwrite function network is not the default +- Logs in docker bp +- Able to delete apps in unconfigured state +- Disable development low disk space +- Only log things to console in dev mode +- Do not get status of more than 10 resources defined by category +- BaseDirectory +- Dashboard statuses +- Default buildImage and baseBuildImage +- Initial deploy status +- Show logs better +- Do not start tcp proxy without main container +- Cleanup stucked tcp proxies +- Default 0 pending invitations +- Handle forked repositories +- Typo +- Pr branches +- Fork pr previews +- Remove unnecessary things +- Meilisearch data dir +- Verify and configure remote docker engines +- Add buildkit features +- Nope if you are not logged in +- Do not use npx +- Pure docker based development +- Do not show nope as ip address for dbs +- Add git sha to build args +- Smart search for new services +- Logs for not running containers +- Update docker binaries +- Gh release +- Dev container +- Gitlab auth and compose reload +- Check compose domains in general +- Port required if fqdn is set +- Appwrite v1 missing containers +- Dockerfile +- Pull does not work remotely on huge compose file +- Single container logs and usage with compose +- Secret errors +- Service logs +- Heroku bp +- Expose port is readonly on the wrong condition +- Toast +- Traefik proxy q 10s +- App logs view +- Tooltip +- Toast, rde, webhooks +- Pathprefix +- Load public repos +- Webhook simplified +- Remote webhooks +- Previews wbh +- Webhooks +- Websecure redirect +- Wb for previews +- Pr stopps main deployment +- Preview wbh +- Wh catchall for all +- Remove old minio proxies +- Template files +- Compose icon +- Templates +- Confirm restart service +- Template +- Templates +- Templates +- Plausible analytics things +- Appwrite webhook +- Coolify instance proxy +- Migrate template +- Preview webhooks +- Simplify webhooks +- Remove ghost-mariadb from the list +- More simplified webhooks +- Umami + ghost issues +- Remove contribution docs +- Umami template +- Compose webhooks fixed +- Variable replacements +- Doc links +- For rollback +- N8n and weblate icon +- Expose ports for services +- Wp + mysql on arm +- Show rollback button loading +- No tags error +- Update on mobile +- Dashboard error +- GetTemplates +- Docker compose persistent volumes +- Application persistent storage things +- Volume names for undefined volume names in compose +- Empty secrets on UI +- Ports for services +- Default icon for new services +- IsBot issue +- Local dev api/ws urls +- Wrong template/type +- Gitea icon is svg +- Gh actions +- Gh actions +- Replace $$generate vars +- Webhook traefik +- Exposed ports +- Wrong icons on dashboard +- Escape % in secrets +- Move debug log settings to build logs +- Storage for compose bp + debug on +- Hasura admin secret +- Logs +- Mounts +- Load logs after build failed +- Accept logged and not logged user in /base +- Remote haproxy password/etc +- Remove hardcoded sentry dsn +- Nope in database strings +- 0 destinations redirect after creation +- Seed +- Sentry dsn update +- Dnt +- Ui +- Only visible with publicrepo +- Migrations +- Prevent webhook errors to be logged +- Login error +- Remove beta from systemwide git +- Git checkout +- Remove sentry before migration +- Webhook previewseparator +- Apache on arm +- Update PR/MRs with new previewSeparator +- Static for arm +- Failed builds should not push images +- Turn off autodeploy for simpledockerfiles +- Security hole +- Rde +- Delete resource on dashboard +- Wrong port in case of docker compose +- Public db icon on dashboard +- Cleanup +- Build commands +- Migration file +- Adding missing appwrite volume +- Appwrite tmp volume +- Do not replace secret +- Root user for dbs on arm +- Escape secrets +- Escape env vars +- Envs +- Docker buildpack env +- Secrets with newline +- Secrets +- Add default node_env variable +- Add default node_env variable +- Secrets +- Secrets +- Gh actions +- Duplicate env variables +- Cleanupstorage +- Remove unused imports +- Parsing secrets +- Read-only permission +- Read-only iam +- $ sign in secrets +- Custom gitlab git user +- Add documentation link again +- Remove prefetches +- Doc link +- Temporary disable dns check with dns servers +- Local images for reverting +- Secrets +- Compose file location +- Docker log sequence +- Delete apps with previews +- Do not cleanup compose applications as unconfigured +- Build env variables with docker compose +- Public gh repo reload compose +- Build args docker compose +- Grpc +- Secrets +- Www redirect +- Cleanup function +- Cleanup stucked containers +- Deletion + cleanupStuckedContainers +- Stucked containers +- CleanupStuckedContainers +- CleanupStuckedContainers +- Typos in docs +- Url +- Network in compose files +- Escape new line chars in wp custom configs +- Applications cannot be deleted +- Arm servics +- Base directory not found +- Cannot delete resource when you are not on root team +- Empty port in docker compose +- Set PACK_VERSION to 0.27.0 +- PublishDirectory +- Host volumes +- Replace . & .. & $PWD with ~ +- Handle log format volumes +- Nestjs buildpack +- Show ip address as host in public dbs +- Revert from dockerhub if ghcr.io does not exists +- Logo of CCCareers +- Typo +- Ssh +- Nullable name on deploy_keys +- Enviroments +- Remove dd - oops +- Add inprogress activity +- Application view +- Only set status in case the last command block is finished +- Poll activity +- Small typo +- Show activity on load +- Deployment should fail on error +- Tests +- Version +- Status not needed +- No project redirect +- Gh actions +- Set status +- Seeders +- Do not modify localhost +- Deployment_uuid -> type_uuid +- Read env from config, bc of cache +- Private key change view +- New destination +- Do not update next channel all the time +- Cancel deployment button +- Public repo limit shown + branch should be preselected. +- Better status on ui for apps +- Arm coolify version +- Formatting +- Gh actions +- Show github app secrets +- Do not force next version updates +- Debug log button +- Deployment key based works +- Deployment cancel/debug buttons +- Upgrade button +- Changing static build changes port +- Overwrite default nginx configuration +- Do not overlap docker image names +- Oops +- Found image name +- Name length +- Semicolons encoding by traefik +- Base_dir wip & outputs +- Cleanup docker images +- Nginx try_files +- Master is the default, not main +- No ms in rate limit resets +- Loading after button text +- Default value +- Localhost is usable +- Update docker-compose prod +- Cloud/checkoutid/lms +- Type of license code +- More verbose error +- Version lol +- Update prod compose +- Version +- Remove buggregator from dev +- Able to change localhost's private key +- Readonly input box - Notifications -- Add shared email option to everyone - -## [4.0.0-beta.57] - 2023-10-02 - -### 🚀 Features - -- Container logs - -### 🐛 Bug Fixes - -- Always pull helper image in dev -- Only show last 1000 lines -- Service status - -## [4.0.0-beta.47] - 2023-09-28 - -### 🐛 Bug Fixes - -- Next helper image -- Service templates -- Sync:bunny -- Update process if server has been renamed -- Reporting handler -- Localhost privatekey update -- Remove private key in case you removed a github app -- Only show manually added private keys on server view -- Show source on all type of applications -- Docker cleanup should be a job by server -- File/dir based volumes are now read from the server -- Respect server fqdn -- If public repository does not have a main branch -- Preselect branc on private repos -- Deploykey branch -- Backups are now working again -- Not found base_branch in git webhooks -- Coolify db backup -- Preview deployments name, status etc -- Services should have destination as well -- Dockerfile expose is not overwritten -- If app settings is not saved to db -- Do not show subscription cancelled noti -- Show real volume names -- Only parse expose in dockerfiles if ports_exposes is empty -- Add uuid to volume names -- New volumes for services should have - instead of _ - -### 💼 Other - -- Fix previews to preview - -## [4.0.0-beta.46] - 2023-09-28 - -### 🐛 Bug Fixes - -- Containerstatusjob -- Aaaaaaaaaaaaaaaaa -- Services view -- Services -- Manually create network for services -- Disable early updates -- Sslip for localhost -- ContainerStatusJob -- Cannot delete env with available services -- Sync command -- Install script drops an error -- Prevent sync version (it needs an option) -- Instance fqdn setting -- Sentry 4510197209 -- Sentry 4504136641 -- Sentry 4502634789 - -## [4.0.0-beta.45] - 2023-09-24 - -### 🚀 Features - -- Services -- Image tag for services - -### 🐛 Bug Fixes - -- Applications with port mappins do a normal update (not rolling update) -- Put back build pack chooser -- Proxy configuration + starter -- Show real storage name on services -- New service template layout - -### 💼 Other - -- Fixed z-index for version link. -- Add source button -- Fixed z-index for magicbar -- A bit better error -- More visible feedback button -- Update help modal -- Help -- Marketing emails - -## [4.0.0-beta.28] - 2023-09-08 - -### 🚀 Features - -- Telegram topics separation -- Developer view for env variables -- Cache team settings -- Generate public key from private keys -- Able to invite more people at once -- Trial -- Dynamic trial period -- Ssh-agent instead of filesystem based ssh keys -- New container status checks -- Generate ssh key -- Sentry add email for better support -- Healthcheck for apps -- Add cloudflare tunnel support - -### 🐛 Bug Fixes - +- Licensing +- Subscription link +- Migrate db schema for smtp + discord +- Text field +- Null fqdn notifications +- Remove old modal +- Proxy stop/start ui +- Proxy UI +- Empty description +- Input and textarea +- Postgres_username name to not name, lol +- DatabaseBackupJob.php +- No storage +- Backup now button +- Ui + subscription +- Self-hosted +- Make coolify-db backups unique dir +- Limits & server creation page +- Fqdn on apps +- DockerCleanupjob +- Validation +- Webhook endpoint in cloud and no system wide gh app +- Subscriptions +- Password confirmation +- Proxy start job +- Dockerimage jobs are not overlapping +- Sentry bug +- Button loading animation +- Form address +- Show hosted email service, just disable for non pro subs +- Add navbar for source + keys +- Add docker network to build process +- Overlapping apps +- Do not show system wide git on cloud +- Lowercase image names +- Typo +- SaveModel email settings +- Bug - Db backup job - Sentry 4459819517 - Sentry 4451028626 @@ -5599,795 +1866,1754 @@ ### 🐛 Bug Fixes - Add traefik labels no matter if traefik is selected or not - Add expose port for containers - Also check docker socks permission on validation - -### 💼 Other - -- User should know that the public key -- Services are not availble yet -- Show registered users on waitlist page -- Nixpacksarchive -- Add Plausible analytics -- Global env variables -- Fix -- Trial emails -- Server check instead of app check -- Show trial instead of sub -- Server lost connection +- Applications with port mappins do a normal update (not rolling update) +- Put back build pack chooser +- Proxy configuration + starter +- Show real storage name on services +- New service template layout +- Containerstatusjob +- Aaaaaaaaaaaaaaaaa +- Services view - Services -- Services -- Services -- Ui for services -- Services -- Services -- Services -- Fixes -- Fix typo - -## [4.0.0-beta.27] - 2023-09-08 - -### 🐛 Bug Fixes - -- Bug - -## [4.0.0-beta.26] - 2023-09-08 - -### 🚀 Features - -- Public database - -## [4.0.0-beta.25] - 2023-09-07 - -### 🐛 Bug Fixes - -- SaveModel email settings - -## [4.0.0-beta.24] - 2023-09-06 - -### 🚀 Features - -- Send request in cloud -- Add discord notifications - -### 🐛 Bug Fixes - -- Form address -- Show hosted email service, just disable for non pro subs -- Add navbar for source + keys -- Add docker network to build process -- Overlapping apps -- Do not show system wide git on cloud -- Lowercase image names -- Typo - -### 💼 Other - -- Backup existing database - -## [4.0.0-beta.23] - 2023-09-01 - -### 🐛 Bug Fixes - -- Sentry bug -- Button loading animation - -## [4.0.0-beta.22] - 2023-09-01 - -### 🚀 Features - -- Add resend as transactional emails - -### 🐛 Bug Fixes - -- DockerCleanupjob -- Validation -- Webhook endpoint in cloud and no system wide gh app -- Subscriptions -- Password confirmation -- Proxy start job -- Dockerimage jobs are not overlapping - -## [4.0.0-beta.21] - 2023-08-27 - -### 🚀 Features - -- Invite by email from waitlist -- Rolling update - -### 🐛 Bug Fixes - -- Limits & server creation page -- Fqdn on apps - -### 💼 Other - +- Manually create network for services +- Disable early updates +- Sslip for localhost +- ContainerStatusJob +- Cannot delete env with available services +- Sync command +- Install script drops an error +- Prevent sync version (it needs an option) +- Instance fqdn setting +- Sentry 4510197209 +- Sentry 4504136641 +- Sentry 4502634789 +- Next helper image +- Service templates +- Sync:bunny +- Update process if server has been renamed +- Reporting handler +- Localhost privatekey update +- Remove private key in case you removed a github app +- Only show manually added private keys on server view +- Show source on all type of applications +- Docker cleanup should be a job by server +- File/dir based volumes are now read from the server +- Respect server fqdn +- If public repository does not have a main branch +- Preselect branc on private repos +- Deploykey branch +- Backups are now working again +- Not found base_branch in git webhooks +- Coolify db backup +- Preview deployments name, status etc +- Services should have destination as well +- Dockerfile expose is not overwritten +- If app settings is not saved to db +- Do not show subscription cancelled noti +- Show real volume names +- Only parse expose in dockerfiles if ports_exposes is empty +- Add uuid to volume names +- New volumes for services should have - instead of _ +- Always pull helper image in dev +- Only show last 1000 lines +- Service status +- If waitlist is disabled, redirect to register +- Add destination to new services +- Predefined content for files +- Move /data to ./_data in dev +- UI +- Show all storages in one place for services +- Ui +- Add _data to vite ignore +- Only use _ in volume names for services +- Volume names in services +- Volume names +- Service logs visible if the whole service stack is not running +- Ui +- Compose magic +- Compose parser updated +- Dev compose files +- Traefik labels for multiport deployments +- Visible version number +- Remove SERVICE_ from deployable compose +- Delete event to deleting +- Move dev data to volumes to prevent permission issues +- Traefik labelling in case of several http and https domain added +- PR deployments use the first fqdn as base +- Email notifications subscription fixed +- Services - do not remove unnecessary things for now +- Decrease max horizon processes to get lower memory usage +- Test emails only available for user owned smtp/resend +- Ui for self-hosted email settings +- Set smtp notifications on by default +- Select branch on other git +- Private repository +- Contribution guide +- Public repository names +- *(create)* Flex wrap on server & network selection +- Better unreachable/revived server statuses +- Able to set base dir for Dockerfile build pack +- Server validation process +- Fqdn could be null +- Small +- Server unreachable count +- Do not reset unreachable count +- Contact docs +- Check connection +- Server saving +- No env goto envs from dashboard +- Goto +- Tcp proxy for dbs +- Database backups +- Only send email if transactional email set +- Backupfailed notification is forced +- Use port exposed for reverse proxy +- Contact link +- Use only ip addresses for servers +- Deleted team and it is the current one +- Add new team button +- Transactional email link +- Dashboard goto link +- Only require registry image in case of dockerimage bp +- Instant save build pack change +- Public git +- Cannot remove localhost +- Check localhost connection +- Send unreachable/revived notifications +- Boarding + verification +- Make sure proxy wont start in NONE mode +- Service check status 10 sec +- IsCloud in production seeder +- Make sure to use IP address +- Dockerfile location feature +- Server ip could be hostname in self-hosted +- Urls should be password fields +- No backup for redis +- Show database logs in case of its not healthy and running +- Proxy check for ports, do not kill anything listening on port 80/443 +- Traefik dashboard ip +- Db labels +- Docker cleanup jobs +- Timeout for instant remote processes +- Dev containerjobs +- Backup database one-by-one. +- Turn off static deployment if you switch buildpacks +- Docker hub URL +- Redis URL generated +- Build image before starting dockerfile buildpacks +- Service status check is a bit better +- Generate fqdn if you deleted a service app, but it requires fqdn +- Cancel any deployments + queue next +- Add internal domain names during build process +- Noindex meta tag +- Show docker build logs +- Only include config.json if its exists and a file +- Always start proxy if not NONE is selected +- Proxy start process +- Setup:dev script & contribution guide +- Do not show configuration changed if config_hash is null +- Add config_hash if its null (old deployments) +- Label generation +- Labels +- Email channel no recepients +- Limit horizon processes to 2 by default +- Add custom port as ssh option to deploy_key based commands +- Remove custom port from git repo url +- ContainerStatus job +- Service docs links +- Add PGUSER to prevent HC warning +- Preselect s3 storage if available +- Port exposes change, shoud regenerate label - Boarding - -## [4.0.0-beta.20] - 2023-08-17 - -### 🚀 Features - -- Send internal notification to discord -- Monitor server connection - -### 🐛 Bug Fixes - -- Make coolify-db backups unique dir - -## [4.0.0-beta.19] - 2023-08-15 - -### 🚀 Features - -- Pricing plans ans subs -- Add s3 storages -- Init postgresql database -- Add backup notifications -- Dockerfile build pack -- Cloud -- Force password reset + waitlist - -### 🐛 Bug Fixes - -- Remove buggregator from dev -- Able to change localhost's private key -- Readonly input box -- Notifications -- Licensing -- Subscription link -- Migrate db schema for smtp + discord -- Text field -- Null fqdn notifications -- Remove old modal -- Proxy stop/start ui -- Proxy UI -- Empty description -- Input and textarea -- Postgres_username name to not name, lol -- DatabaseBackupJob.php -- No storage -- Backup now button -- Ui + subscription -- Self-hosted - -### 💼 Other - -- Scheduled backups - -## [4.0.0-beta.18] - 2023-07-14 - -### 🚀 Features - -- Able to control multiplexing -- Add runRemoteCommandSync -- Github repo with deployment key -- Add persistent volumes -- Debuggable executeNow commands -- Add private gh repos -- Delete gh app -- Installation/update github apps -- Auto-deploy -- Deploy key based deployments -- Resource limits -- Long running queue with 1 hour of timeout -- Add arm build to dev -- Disk cleanup threshold by server -- Notify user of disk cleanup init - -### 🐛 Bug Fixes - -- Logo of CCCareers -- Typo -- Ssh -- Nullable name on deploy_keys -- Enviroments -- Remove dd - oops -- Add inprogress activity -- Application view -- Only set status in case the last command block is finished -- Poll activity -- Small typo -- Show activity on load -- Deployment should fail on error -- Tests -- Version -- Status not needed -- No project redirect -- Gh actions -- Set status -- Seeders -- Do not modify localhost -- Deployment_uuid -> type_uuid -- Read env from config, bc of cache -- Private key change view -- New destination -- Do not update next channel all the time -- Cancel deployment button -- Public repo limit shown + branch should be preselected. -- Better status on ui for apps -- Arm coolify version -- Formatting -- Gh actions -- Show github app secrets -- Do not force next version updates -- Debug log button -- Deployment key based works -- Deployment cancel/debug buttons -- Upgrade button -- Changing static build changes port -- Overwrite default nginx configuration -- Do not overlap docker image names -- Oops -- Found image name -- Name length -- Semicolons encoding by traefik -- Base_dir wip & outputs -- Cleanup docker images -- Nginx try_files -- Master is the default, not main -- No ms in rate limit resets -- Loading after button text -- Default value -- Localhost is usable -- Update docker-compose prod -- Cloud/checkoutid/lms -- Type of license code -- More verbose error -- Version lol -- Update prod compose -- Version - -### 💼 Other - -- Extract process handling from async job. -- Extract process handling from async job. -- Extract process handling from async job. -- Extract process handling from async job. -- Extract process handling from async job. -- Extract process handling from async job. -- Extract process handling from async job. -- Persisting data - -## [3.12.28] - 2023-03-16 - -### 🐛 Bug Fixes - -- Revert from dockerhub if ghcr.io does not exists - -## [3.12.27] - 2023-03-07 - -### 🐛 Bug Fixes - -- Show ip address as host in public dbs - -## [3.12.24] - 2023-03-04 - -### 🐛 Bug Fixes - -- Nestjs buildpack - -## [3.12.22] - 2023-03-03 - -### 🚀 Features - -- Add host path to any container - -### 🐛 Bug Fixes - -- Set PACK_VERSION to 0.27.0 -- PublishDirectory -- Host volumes -- Replace . & .. & $PWD with ~ -- Handle log format volumes - -## [3.12.19] - 2023-02-20 - -### 🚀 Features - -- Github raw icon url -- Remove svg support - -### 🐛 Bug Fixes - -- Typos in docs -- Url -- Network in compose files -- Escape new line chars in wp custom configs -- Applications cannot be deleted -- Arm servics -- Base directory not found -- Cannot delete resource when you are not on root team -- Empty port in docker compose - -## [3.12.18] - 2023-01-24 - -### 🐛 Bug Fixes - -- CleanupStuckedContainers -- CleanupStuckedContainers - -## [3.12.16] - 2023-01-20 - -### 🐛 Bug Fixes - -- Stucked containers - -## [3.12.15] - 2023-01-20 - -### 🐛 Bug Fixes - -- Cleanup function -- Cleanup stucked containers -- Deletion + cleanupStuckedContainers - -## [3.12.14] - 2023-01-19 - -### 🐛 Bug Fixes - -- Www redirect - -## [3.12.13] - 2023-01-18 - -### 🐛 Bug Fixes - -- Secrets - -## [3.12.12] - 2023-01-17 - -### 🚀 Features - -- Init h2c (http2/grpc) support -- Http + h2c paralel - -### 🐛 Bug Fixes - -- Build args docker compose -- Grpc - -## [3.12.11] - 2023-01-16 - -### 🐛 Bug Fixes - -- Compose file location -- Docker log sequence -- Delete apps with previews -- Do not cleanup compose applications as unconfigured -- Build env variables with docker compose -- Public gh repo reload compose - -### 💼 Other - -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc - -## [3.12.10] - 2023-01-11 - -### 💼 Other - -- Add missing variables - -## [3.12.9] - 2023-01-11 - -### 🚀 Features - -- Add Openblocks icon -- Adding icon for whoogle -- *(ui)* Add libretranslate service icon -- Handle invite_only plausible analytics - -### 🐛 Bug Fixes - -- Custom gitlab git user -- Add documentation link again -- Remove prefetches -- Doc link -- Temporary disable dns check with dns servers -- Local images for reverting -- Secrets - -## [3.12.8] - 2022-12-27 - -### 🐛 Bug Fixes - -- Parsing secrets -- Read-only permission -- Read-only iam -- $ sign in secrets - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.12.5] - 2022-12-26 - -### 🐛 Bug Fixes - -- Remove unused imports - -### 💼 Other - -- Conditional on environment - -## [3.12.2] - 2022-12-19 - -### 🐛 Bug Fixes - -- Appwrite tmp volume -- Do not replace secret -- Root user for dbs on arm -- Escape secrets -- Escape env vars -- Envs -- Docker buildpack env -- Secrets with newline -- Secrets -- Add default node_env variable -- Add default node_env variable -- Secrets -- Secrets -- Gh actions -- Duplicate env variables -- Cleanupstorage - -### 💼 Other - -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc -- Trpc - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.12.1] - 2022-12-13 - -### 🐛 Bug Fixes - -- Build commands -- Migration file -- Adding missing appwrite volume - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.12.0] - 2022-12-09 - -### 🚀 Features - -- Use registry for building -- Docker registries working -- Custom docker compose file location in repo -- Save doNotTrackData to db -- Add default sentry -- Do not track in settings -- System wide git out of beta -- Custom previewseparator -- Sentry frontend -- Able to host static/php sites on arm -- Save application data before deploying -- SimpleDockerfile deployment -- Able to push image to docker registry -- Revert to remote image -- *(api)* Name label - -### 🐛 Bug Fixes - -- 0 destinations redirect after creation -- Seed -- Sentry dsn update -- Dnt +- Clone to with the same environment name +- Cleanup stucked resources on start +- Do not allow to delete env if a resource is defined +- Service template generator + appwrite +- Mongodb backup +- Make sure coolfiy network exists on install +- Syncbunny command +- Encrypt mongodb password +- Mongodb healtcheck command +- Rate limit for api + add mariadb + mysql +- Server settings guarded +- Space in build args +- Lock SERVICE_FQDN envs +- If user is invited, that means its email is verified +- Force password reset on invited accounts +- Add ssh options to git ls-remote +- Git ls-remote +- Remove coolify labels from ui +- Missing environment variables prevewi on service +- Invoice.paid should sleep for 5 seconds +- Local dev repo +- Deployments ui +- Dockerfile build pack fix +- Set labels on generate domain +- Network service parse +- Notification url in containerstatusjob +- Gh webhook response 200 to installation_repositories +- Delete destination +- No id found +- Missing $mailMessage +- Set default from/sender names +- No environments +- Telegram text +- Private key not found error +- UI +- Resourcesdelete command +- Port number should be int +- Separate delete with validation of server +- Add nixpacks info +- Remove filter +- Container logs are now followable in full-screen and sorted by timestamp +- Ui for labels - Ui -- Only visible with publicrepo +- Deletions +- Build_image not found +- Github source view +- Github source view +- Dockercleanupjob should be released back +- Ui +- Local ip address +- Revert workdir to basedir +- Container status jobs for old pr deployments +- Service updates +- *(fider template)* Use the correct docs url +- Fqdn for minio +- Generate service fields +- Mariadb backups +- When to pull image +- Do not allow to enter local ip addresses +- Reset password +- Only report nonruntime errors +- Handle different label formats in services +- Server adding process +- Show defined resources in server tab, so you will know what you need to delete before you can delete the server. +- Lots of regarding git + docker compose deployments +- Pull request build variables +- Double default password length +- Do not remove deployment in case compose based failed +- No container servers +- Sentry issue +- Dockercompose save ./ volumes under /data/coolify +- Server view for link() +- Default value do not overwrite existing env value +- Use official install script with rancher (one will work for sure) +- Add cf tunnel to boarding server view +- Prevent autorefresh of proxy status +- Missing docker image thing +- Add hc for soketi +- Deploy the right compose file +- Bind volumes for compose bp +- Use hc port 80 in case of static build +- Switching to static build +- Container selection +- Service navbar using new realtime events +- Do not create duplicated networks +- Live event +- Service start + event +- Service deletion job +- Double ws connection +- Boarding view +- Do not send telegram noti on intent payment failed +- Database ui is realtime based +- Live mode for github webhooks +- Ui +- Realtime connection popup could be disabled +- Realtime check +- Add new destination +- Proxy logs +- Db status check +- Pusher host +- Add ipv6 +- Realtime connection?! +- Websocket +- Better handling of errors with install script +- Install script parse version +- Only allow to modify in .env file if AUTOUPDATE is set +- Is autoupdate not null +- Run init command after production seeder +- Init +- Comma in traefik custom labels +- Ignore if dynamic config could not be set +- Service env variable ovewritten if it has a default value +- Labelling +- Non-ascii chars in labels +- Labels +- Init script echos +- Update Coolify script +- Null notify +- Check queued deployments as well +- Copy invitation +- Password reset / invitation link requests +- Add catch all route +- Revert random container job delay +- Backup executions view +- Only check server status in container status job +- Improve server status check times +- Handle other types of generated values +- Server checking status +- Ui for adding new destination +- Reset domains on compose file change +- Domains for compose bp +- No action in webhooks +- Add debug output to gitlab webhooks +- Do not push dockerimage +- Add alpha to swarm +- Server not found +- Do not autovalidate server on mount +- Server update schedule +- Swarm support ui +- Server ready +- Get swarm service logs +- Docker compose apps env rewritten +- Storage error on dbs +- Why?! +- Stay tuned +- Cpu limit to float from int +- Add source commit to final envs +- Routing, switch back to old one +- Deploy instead of restart in case swarm is used +- Button title +- Restore falsely deleted coolify-db-backup +- Sub +- Wrong env variable parsing +- Deploy key + docker compose +- Horizon +- Duplicate compose variable +- Set deployment failed if new container is not healthy +- Nixpacks cache +- Only add restart policy if its empty (compose) +- Nixpacks buildpack +- File storage save +- Database env variables +- Healthy status +- Show framework based notification in build logs +- Traefik labels +- Use ip for sslip in dev if remote server is used +- Service labels without ports (unknown ports) +- Sort and rename (unique part) of labels +- Settings menu +- Remove traefik debug in dev mode +- Php pgsql to 8.2 +- Static buildpack should set port 80 +- Update navbar on build_pack change +- Do not include thegameplan.json into build image +- Submit error on postgresql +- Email verification / forgot password +- Escape build envs properly for nixpacks + docker build +- Undead endpoint +- Upload limit on ui +- Save cmd output propely (merge) +- Load profile on remote commands +- Load profile and set envs on remote cmd +- Restart should not update config hash +- Preview deployments with nixpacks +- Cleanup docker stuffs before upgrading +- Service deletion command +- Cpuset limits was determined in a way that apps only used 1 CPU max, ehh, sorry. +- Service stack view +- Change proxy view +- Checkbox click +- Git pull command for deploy key based previews +- Server status job +- Service deletion bug! +- Links +- Redis custom conf +- Sentry error +- Restrict concurrent deployments per server +- Queue +- Change env variable length +- Bitbucket manual deployments +- Webhooks for multiple apps +- Unhealthy deployments should be failed +- Add env variables for wordpress template without database +- Service deletion function +- Service deletion fix +- Dns validation + duplicated fqdns +- Validate server navbar upated +- Regenerate labels on application clone +- Service deletion +- Not able to use other shared envs +- Sentry fix +- Sentry +- Sentry error +- Sentry +- Sentry error +- Create dynamic directory +- Migrate to new modal +- Duplicate domain check +- Tags +- Wrap tags and avoid horizontal overflow +- Stripe webhooks +- Feedback from self-hosted envs to discord +- New menu on navbar +- Make sure resources are deleted in async mode +- Go to prod env from dashboard if there is no other envs defined +- User proper image_tag, if set +- New menu ui +- Lock logdrain configuration when one of them are enabled +- Add docker compose check during server validation +- Get service stack as uuid, not name +- Menu +- Flex wrap deployment previews +- Boolean docker options +- Only add 'networks' key if 'network_mode' is absent +- Cleanup scheduled tasks +- Padding left on input boxes +- Use ls / command instead ls +- Do not add the same server twice +- Only show redeployment required if status is not exited +- Add openbsd ssh server check +- Resources +- Empty build variables +- *(server)* Revalidate server button not showing in server's page +- Fluent bit ident level +- Submodule cloning +- Database status +- Permission change updates from webhook +- Server validation +- Connections being stuck and not processed until proxy restarts +- Use latest image if nothing is specified +- No coolify.yaml found +- Server validation +- Statuses +- Unknown image of service until it is uploaded +- Subscription / plan switch, etc +- Firefly service +- Force enable/disable server in case ultimate package quantity decreases +- Server disabled +- Custom dockerfile location always checked +- Import to mysql and mariadb +- Resource tab not loading if server is not reachable +- Load unmanaged async +- Do not show n/a networsk +- Service container status updates +- Public prs should not be commented +- Pull request deployments + build servers +- Env value generation +- Sentry error +- Service status updated +- Should note delete personal teams +- Make sure to show some buttons +- Sort repositories by name +- Deploy api messages +- Fqdn null in case docker compose bp +- Reload caddy issue +- /realtime endpoint +- Proxy switch +- Service ports for services + caddy +- Failed deployments should send failed email/notification +- Consider custom healthchecks in dockerfile +- Create initial files async +- Docker compose validation +- Duplicate dockerfile +- Multiline env variables +- Server stopped, service page not reachable +- Empty get logs number of lines +- Only escape envs after v239+ +- 0 in env value +- Consistent container name +- Custom ip address should turn off rolling update +- Multiline input +- Raw compose deployment +- Dashboard view if no project found +- Volumes for prs +- Shared env variable parsing +- Compose env has SERVICE, but not defined for Coolify +- Public service database +- Make sure service db proxy restarted +- Restart service db proxies +- Two factor +- Ui for tags +- Update resources view +- Realtime connection check +- Multline env in dev mode +- Scheduled backup for other service databases (supabase) +- PR deployments should not be distributed to 2 servers +- Name/from address required for resend +- Autoupdater +- Async service loads +- Disabled inputs are not trucated +- Duplicated generated fqdns are now working +- Uis +- Ui for cftunnels +- Search services +- Trial users subscription page +- Async public key loading +- Unfunctional server should see resources +- Warning if you use multiple domains for a service +- New github app creation +- Always rebuild Dockerfile / dockerimage buildpacks +- Do not rebuild dockerfile based apps twice +- Make sure if envs are changed, rebuild is needed +- Members cannot manage subscriptions +- IsMember +- Storage layout +- How to update docker-compose, environment variables and fqdns +- Git submodule update +- Unintended left padding on sidebar +- Hashed random delimeter in ssh commands + make sure to remove the delimeter from the command +- Service config hash update +- Redeploy if image not found in restart only mode +- Check each required binaries one-by-one +- Helper image only pulled if required, not every 10 mins +- Make sure that confs when checking if it is changed sorted +- Respect .env file (for default values) +- Remove temporary cloudflared config +- Remove lazy loading until bug figured out +- Rollback feature +- Base64 encode .env +- $ in labels escaped +- .env saved to deployment server, not to build server +- Do no able to delete gh app without deleting resources +- 500 error on edge case +- Able to select server when creating new destination +- N8n template +- Refresh public ips on start +- Move s3 storages to separate view +- Mongo db backup +- Backups +- Autoupdate +- Respect start period and chekc interval for hc +- Parse HEALTHCHECK from dockerfile +- Make s3 name and endpoint required +- Able to update source path for predefined volumes +- Get logs with non-root user +- Mongo 4.0 db backup +- Formbricks image origin +- Add port even if traefik is used +- Typo in tags.blade.php +- Install.sh error +- Env file +- Comment out internal notification in email_verify method +- Confirmation for custom labels +- Change permissions on newly created dirs +- Color for resource operation server and project name +- Only show realtime error on non-cloud instances +- Only allow push and mr gitlab events +- Improve scheduled task adding/removing +- Docker compose dependencies for pr previews +- Properly populating dependencies +- Use commit hash on webhooks +- Commit message length +- Hc from localhost to 127.0.0.1 +- Use rc in hc +- Telegram group chat notifications +- PR deployments have good predefined envs +- Optimize new resource creation +- Show it docker compose has syntax errors +- Wrong time during a failed deployment +- Removal of the failed deployment condition, addition of since started instead of finished time +- Use local versions + service templates and query them every 10 minutes +- Check proxy functionality before removing unnecessary coolify.yaml file and checking Docker Engine +- Show first 20 users only in admin view +- Add subpath for services +- Ghost subdir +- Do not pull templates in dev +- Templates +- Update error message for invalid token to mention invalid signature +- Disable containerStopped job for now +- Disable unreachable/revived notifications for now +- JSON_UNESCAPED_UNICODE +- Add wget to nixpacks builds +- Pre and post deployment commands +- Bitbucket commits link +- Better way to add curl/wget to nixpacks +- Root team able to download backups +- Build server should not have a proxy +- Improve build server functionalities +- Sentry issue +- Sentry +- Sentry error + livewire downgrade +- Sentry +- Sentry +- Sentry error +- Sentry +- Force load services from cdn on reload list +- Do not allow service storage mount point modifications +- Volume adding +- Sync upgrade process +- Publish horizon +- Add missing team model +- Test new upgrade process? +- Throw exception +- Build server dirs not created on main server +- Compose load with non-root user +- Able to redeploy dockerfile based apps without cache +- Compose previews does have env variables +- Fine-tune cdn pulls +- Spamming :D +- Parse docker version better +- Compose issues +- SERVICE_FQDN has source port in it +- Logto service +- Allow invitations via email +- Sort by defined order + fixed typo +- Only ignore volumes with driver_opts +- Check env in args for compose based apps +- Custom docker compose commands, add project dir if needed +- Autoupdate process +- Backup executions view +- Handle previously defined compose previews +- Sort backup executions +- Supabase service, newest versions +- Set default name for Docker volumes if it is null +- Multiline variable should be literal + should be multiline in bash with \ +- Gitlab merge request should close PR +- Multiline build args +- Setup script doesnt link to the correct source code file +- Install.sh do not reinstall packages on arch +- Just restart +- Stripprefix middleware correctly labeled to http +- Bitbucket link +- Compose generator +- Do no truncate repositories wtih domain (git) in it +- In services should edit compose file for volumes and envs +- Handle laravel deployment better +- Db proxy status shown better in the UI +- Show commit message on webhooks + prs +- Metrics parsing +- Charts +- Application custom labels reset after saving +- Static build with new nixpacks build process +- Make server charts one livewire component with one interval selector +- You can now add env variable from ui to services +- Update compose environment with UI defined variables +- Refresh deployable compose without reload +- Remove cloud stripe notifications +- App deployment should be in high queue +- Remove zoom from modals +- Get envs before sortby +- MB is % lol +- Projects with 0 envs +- Run user commands on high prio queue +- Load js locally +- Remove lemon + paddle things +- Run container commands on high priority +- Image logo +- Remove both option for api endpoints. it just makes things complicated +- Cleanup subs in cloud +- Show keydbs/dragonflies/clickhouses +- Only run cloud clean on cloud + remove root team +- Force cleanup on busy servers +- Check domain on new app via api +- Custom container name will be the container name, not just internal network name +- Api updates +- Yaml everywhere +- Add newline character to private key before saving +- Add validation for webhook endpoint selection +- Database input validators +- Remove own app from domain checks +- Return data of app update +- Do not overwrite hardcoded variables if they rely on another variable +- Remove networks when deleting a docker compose based app +- Api +- Always set project name during app deployments +- Remove volumes as well +- Gitea pr previews +- Prevent instance fqdn persisting to other servers dynamic proxy configs +- Better volume cleanups +- Cleanup parameter +- Update redirect URL in unauthenticated exception handler +- Respect top-level configs and secrets +- Service status changed event +- Disable sentinel until a few bugs are fixed +- Service domains and envs are properly updated +- *(reactive-resume)* New healthcheck command for MinIO +- *(MinIO)* New command healthcheck +- Update minio hc in services +- Add validation for missing docker compose file +- Typo in is_literal helper +- Env is_literal helper text typo +- Update docker compose pull command with --policy always +- Plane service template +- Vikunja +- Docmost template +- Drupal +- Improve github source creation +- Tag deployments +- New docker compose parsing +- Handle / in preselecting branches +- Handle custom_internal_name check in ApplicationDeploymentJob.php +- If git limit reached, ignore it and continue with a default selection +- Backup downloads +- Missing input for api endpoint +- Volume detection (dir or file) is fixed +- Supabase +- Create file storage even if content is empty +- Preview deployments should be stopped properly via gh webhook +- Deleting application should delete preview deployments +- Plane service images +- Fix issue with deployment start command in ApplicationDeploymentJob +- Directory will be created by default for compose host mounts +- Restart proxy does not work + status indicator on the UI +- Uuid in api docs type +- Raw compose deployment .env not found +- Api -> application patch endpoint +- Remove pull always when uploading backup to s3 +- Handle array env vars +- Link in task failed job notifications +- Random generated uuid will be full length (not 7 characters) +- Gitlab service +- Gitlab logo +- Bitbucket repository url +- By default volumes that we cannot determine if they are directories or files are treated as directories +- Domain update on services on the UI +- Update SERVICE_FQDN/URL env variables when you change the domain +- Several shared environment variables in one value, parsed correctly +- Members of root team should not see instance admin stuff +- Parse docker composer +- Service env parsing +- Service env variables +- Activity type invalid +- Update env on ui +- Only append docker network if service/app is running +- Remove lazy load from scheduled tasks +- Plausible template +- Service_url should not have a trailing slash +- If usagebefore cannot be determined, cleanup docker with force +- Async remote command +- Only run logdrain if necessary +- Remove network if it is only connected to coolify proxy itself +- Dir mounts should have proper dirs +- File storages (dir/file mount) handled properly +- Do not use port exposes on docker compose buildpacks +- Minecraft server template fixed +- Graceful shutdown +- Stop resources gracefully +- Handle null and empty disk usage in DockerCleanupJob +- Show latest version on manual update view +- Empty string content should be saved as a file +- Update Traefik labels on init +- Add missing middleware for server check job +- Scheduledbackup not found +- Manual update process +- Timezone not updated when systemd is missing +- If volumes + file mounts are defined, should merge them together in the compose file +- All mongo v4 backups should use the different backup command +- Database custom environment variables +- Connect compose apps to the right predefined network +- Docker compose destination network +- Server status when there are multiple servers +- Sync fqdn change on the UI +- Pr build names in case custom name is used +- Application patch request instant_deploy +- Canceling deployment on build server +- Backup of password protected postgresql database +- Docker cleanup job +- Storages with preserved git repository +- Parser parser parser +- New parser only in dev +- Parser parser +- Numberoflines should be number +- Docker cleanup job +- Fix directory and file mount headings in file-storage.blade.php +- Preview fqdn generation +- Revert a few lines +- Service ui sync bug +- Setup script doesn't work on rhel based images with some curl variant already installed +- Let's wait for healthy container during installation and wait an extra 20 seconds (for migrations) +- Infra files +- Log drain only for Applications +- Copy large compose files through scp (not ssh) +- Check if array is associative or not +- Openapi endpoint urls +- Convert environment variables to one format in shared.php +- Logical volumes could be overwritten with new path +- Env variable in value parsed +- Pull coolify image only when the app needs to be updated +- Wrong executions order +- Handle project not found error in environment_details API endpoint +- Deployment running for - without "ago" +- Update helper image pulling logic to only pull if the version is newer +- Parser +- Plunk NEXT_PUBLIC_API_URI +- Reenable overlapping servercheckjob +- Appwrite template + parser +- Don't add `networks` key if `network_mode` is used +- Remove debug statement in shared.php +- Scp through cloudflare +- Delete older versions of the helper image other than the latest one +- Update remoteProcess.php to handle null values in logItem properties +- Disable mux_enabled during server validation +- Move mc command to coolify image from helper +- Keydb. add `:` delimiter for connection string +- Cloudflare tunnel with new multiplexing feature +- Keep-alive ws connections +- Add build.sh to debug logs +- Update Coolify installer +- Terminal +- Generate https for minio +- Install script +- Handle WebSocket connection close in terminal.blade.php +- Able to open terminal to any containers +- Refactor run-command +- If you exit a container manually, it should close the underlying tty as well +- Move terminal to separate view on services +- Only update helper image in DB +- Generated fqdn for SERVICE_FQDN_APP_3000 magic envs +- Proxy status +- Coolify-db should not be in the managed resources +- Store original root key in the original location +- Logto service +- Cloudflared service - Migrations -- Prevent webhook errors to be logged -- Login error -- Remove beta from systemwide git -- Git checkout -- Remove sentry before migration -- Webhook previewseparator -- Apache on arm -- Update PR/MRs with new previewSeparator -- Static for arm -- Failed builds should not push images -- Turn off autodeploy for simpledockerfiles -- Security hole -- Rde -- Delete resource on dashboard -- Wrong port in case of docker compose -- Public db icon on dashboard -- Cleanup +- Cloudflare tunnel configuration, ui, etc +- Parser +- Exited services statuses +- Make sure to reload window if app status changes +- Deploy key based deployments +- Proxy fixes +- Proxy +- *(templates)* Filebrowser FQDN env variable +- Handle edge case when build variables and env variables are in different format +- Compose based terminal +- Filebrowser template +- Edit is_build_server_enabled upon creating application on other application type +- Save settings after assigning value +- In dev mode do not ask confirmation on delete +- Mixpost +- Handle deletion of 'hello' in confirmation modal for dev environment +- Remove autofocuses +- Ipv6 scp should use -6 flag +- Cleanup stucked applicationdeploymentqueue +- Realtime watch in development mode +- Able to select root permission easier +- Able to support more database dynamically from Coolify's UI +- Strapi template +- Bitcoin core template +- Api useBuildServer +- Service application view +- Add new supported database images +- Parse proxy config and check the set ports usage +- Update FQDN +- Scheduled backup for services view +- Parser, espacing container labels +- Reset description and subject fields after submitting feedback +- Tag mass redeployments +- Service env orders, application env orders +- Proxy conf in dev +- One-click services +- Use local service-templates in dev +- New services +- Remove not used extra host +- Chatwoot service +- Directus +- Database descriptions +- Update services +- Soketi +- Select server view +- Update mattermost image tag and add default port +- Remove env, change timezone +- Postgres healthcheck +- Azimutt template - still not working haha +- New parser with SERVICE_URL_ envs +- Improve service template readability +- Update password variables in Service model +- Scheduled database server +- Select server view +- Signup +- Application domains should be http and https only +- Validate and sanitize application domains +- Sanitize and validate application domains +- Use correct env variable for invoice ninja password +- Make sure caddy is not removed by cleanup +- Libretranslate +- Do not allow to change number of lines when streaming logs +- Plunk +- No manual timezones +- Helper push +- Format +- Add port metadata and Coolify magic to generate the domain +- Sentinel +- Metrics +- Generate sentinel url +- Only enable Sentinel for new servers +- Is_static through API +- Allow setting standalone redis variables via ENVs (team variables...) +- Check for username separately form password +- Encrypt all existing redis passwords +- Pull helper image on helper_version change +- Redis database user and password +- Able to update ipv4 / ipv6 instance settings +- Metrics for dbs +- Sentinel start fixed +- Validate sentinel custom URL when enabling sentinel +- Should be able to reset labels in read-only mode with manual click +- No sentinel for swarm yet +- Charts ui +- Volume +- Sentinel config changes restarts sentinel +- Disable sentinel for now +- Disable Sentinel temporarily +- Disable Sentinel temporarily for non-dev environments +- Access team's github apps only +- Admins should now invite owner +- Add experimental flag +- GenerateSentinelUrl method +- NumberOfLines could be null +- Login / register view +- Restart sentinel once a day +- Changing private key manually won't trigger a notification +- Grammar for helper +- Fix my own grammar +- Add telescope only in dev mode +- New way to update container statuses +- Only run server storage every 10 mins if sentinel is not active +- Cloud admin view +- Queries in kernel.php +- Lower case emails only +- Change emails to lowercase on init +- Do not error on update email +- Always authenticate with lowercase emails +- Dashboard refactor +- Add min/max length to input/texarea +- Remove livewire legacy from help view +- Remove unnecessary endpoints (magic) +- Transactional email livewire +- Destinations livewire refactor +- Refactor destination/docker view +- Logdrains validation +- Reworded +- Use Auth(), add new db proxy stop event refactor clickhouse view +- Add user/pw to db view +- Sort servers by name +- Keydb view +- Refactor tags view / remove obsolete one +- Send discord/telegram notifications on high job queue +- Server view refresh on validation +- ShowBoarding +- Show docker installation logs & ubuntu 24.10 notification +- Do not overlap servercheckjob +- Server limit check +- Server validation +- Clear route / view +- Only skip docker installation on 24.10 if its not installed +- For --gpus device support +- Db/service start should be on high queue +- Do not stop sentinel on Coolify restart +- Run resourceCheck after new serviceCheckJob +- Mongodb in dev +- Better invitation errors +- Loading indicator for db proxies +- Do not execute gh workflow on template changes +- Only use sentry in cloud +- Update packagejson of coolify-realtime + add lock file +- Update last online with old function +- Seeder should not start sentinel +- Start sentinel on seeder +- Notifications ui +- Disable wire:navigate +- Confirmation Settings css for light mode +- Server wildcard +- Saving resend api key +- Wildcard domain save +- Disable cloudflare tunnel on "localhost" +- Define separate volumes for mattermost service template +- Github app name is too long +- ServerTimezone update +- Trigger.dev db host & sslmode=disable +- Manual update should be executed only once + better UX +- Upgrade.sh +- Missing privateKey +- Show proper error message on invalid Git source +- Convert HTTP to SSH source when using deploy key on GitHub +- Cloud + stripe related +- Terminal view loading in async +- Cool 500 error (thanks hugodos) +- Update schema in code decorator +- Openapi docs +- Add tests for git url converts +- Minio / logto url generation +- Admin view +- Min docker version 26 +- Pull latest service-templates.json on init +- Workflow files for coolify build +- Autocompletes +- Timezone settings validation +- Invalid tz should not prevent other jobs to be executed +- Testing-host should be built locally +- Poll with modal issue +- Terminal opening issue +- If service img not found, use github as a source +- Fallback to local coolify.png +- Gather private ips +- Cf tunnel menu should be visible when server is not validated +- Deployment optimizations +- Init script + optimize laravel +- Default docker engine version + fix install script +- Pull helper image on init +- SPA static site default nginx conf +- Modal-input +- Modal (+ add) on dynamic config was not opening, removed x-cloak +- AUTOUPDATE + checkbox opacity +- Improve helper text for metrics input fields +- Refine helper text for metrics input fields +- If mux conn fails, still use it without mux + save priv key with better logic +- Migration +- Always validate ssh key +- Make sure important jobs/actions are running on high prio queue +- Do not send internal notification for backups and status jobs +- Validateconnection +- View issue +- Heading +- Remove mux cleanup +- Db backup for services +- Version should come from constants + fix stripe webhook error reporting +- Undefined variable +- Remove version.php as everything is coming from constants.php +- Sentry error +- Websocket connections autoreconnect +- Sentry error +- Sentry +- Empty server API response +- Incorrect server API patch response +- Missing `uuid` parameter on server API patch +- Missing `settings` property on servers API +- Move servers API `delete_unused_*` properties +- Servers API returning `port` as a string -> integer +- Only return server uuid on server update +- Service generate includes yml files as well (haha) +- ServercheckJob should run every 5 minutes on cloud +- New resource icons +- Search should be more visible on scroll on new resource +- Logdrain settings +- Ui +- Email should be retried with backoff +- Alpine in body layout +- Application view loading +- Postiz service +- Only able to select the right keys +- Test email should not be required +- A few inputs +- Api endpoint +- Resolve undefined searchInput reference in Alpine.js component +- URL and sync new app name +- Typos and naming +- Client and webhook secret disappear after sync +- Missing `mysql_password` API property +- Incorrect MongoDB init API property +- Old git versions does not have --cone implemented properly +- Don't allow editing traefik config +- Restart proxy +- Dev mode +- Ui +- Display actual values for disk space checks in installer script +- Proxy change behaviour +- Add warning color +- Import NotificationSlack correctly +- Add middleware to new abilities, better ux for selecting permissions, etc. +- Root + read:sensive could read senstive data with a middlewarew +- Always have download logs button on scheduled tasks +- Missing css +- Development image +- Dockerignore +- DB migration error +- Drop all unused smtp columns +- Backward compatibility +- Email notification channel enabled function +- Instance email settins +- Make sure resend is false if SMTP is true and vice versa +- Email Notification saving +- Slack and discord url now uses text filed because encryption makes the url very long +- Notification trait +- Encryption fixes +- Docker cleanup email template +- Add missing deployment notifications to telegram +- New docker cleanup settings are now saved to the DB correctly +- Ui + migrations +- Docker cleanup email notifications +- General notifications does not go through email channel +- Test notifications to only send it to the right channel +- Remove resale_license from db as well +- Nexus service +- Fileflows volume names +- --cone +- Provider error +- Database migration +- Seeder +- Migration call +- Slack helper +- Telegram helper +- Discord helper +- Telegram topic IDs +- Make pushover settings more clear +- Typo in pushover user key +- Use Livewire refresh method and lock properties +- Create pushover settings for existing teams +- Update token permission check from 'write' to 'root' +- Pushover +- Oauth seeder +- Correct heading display for OAuth settings in settings-oauth.blade.php +- Adjust spacing in login form for improved layout +- Services env values should be sensitive +- Documenso +- Dolibarr +- Typo +- Update OauthSettingSeeder to handle new provider definitions and ensure authentik is recreated if missing +- Improve OauthSettingSeeder to correctly delete non-existent providers and ensure proper handling of provider definitions +- Encrypt resend API key in instance settings +- Resend api key is already a text column +- Monaco editor light and dark mode switching +- Service status indicator + oauth saving +- Socialite for azure and authentik +- Saving oauth +- Fallback for copy button +- Copy the right text +- Maybe fallback is now working +- Only show copy button on secure context +- Render html on error page correctly +- Invalid API response on missing project +- Applications API response code + schema +- Applications API writing to unavailable models +- If an init script is renamed the old version is still on the server +- Oauthseeder +- Compose loading seq +- Resource clone name + volume name generation +- Update Dockerfile entrypoint path to /etc/entrypoint.d +- Debug mode +- Unreachable notifications +- Remove duplicated ServerCheckJob call +- Few fixes and use new ServerReachabilityChanged event +- Use serverStatus not just status +- Oauth seeder +- Service ui structure +- Check port 8080 and fallback to 80 +- Refactor database view +- Always use docker cleanup frequency +- Advanced server UI +- Html css +- Fix domain being override when update application +- Use nixpacks predefined build variables, but still could update the default values from Coolify +- Use local monaco-editor instead of Cloudflare +- N8n timezone +- Smtp encryption +- Bind() to 0.0.0.0:80 failed +- Oauth seeder +- Unreachable notifications +- Instance settings migration +- Only encrypt instance email settings if there are any +- Error message +- Update healthcheck and port configurations to use port 8080 +- Compose envs +- Scheduled tasks and backups are executed by server timezone. +- Show backup timezone on the UI +- Disappearing UI after livewire event received +- Add default vector db for anythingllm +- We need XSRF-TOKEN for terminal +- Prevent default link behavior for resource and settings actions in dashboard +- Increase default php memory limit +- Show if only build servers are added to your team +- Update Livewire button click method to use camelCase +- Local dropzonejs +- Import backups due to js stuff should not be navigated +- Install inetutils on Arch Linux +- Use ip in place of hostname from inetutils in arch +- Update import command to append file redirection for database restoration +- Ui bug on pw confirmation +- Exclude system and computed fields from model replication +- Service cloning on a separate server +- Application cloning +- `Undefined variable $fs_path` for databases +- Service and database cloning and label generation +- Labels and URL generation when cloning +- Clone naming for different database data volumes +- Implement all the cloneMe changes for ResourceOperations as well +- Volume and fileStorages cloning +- View text and helpers +- Teable +- Trigger with external db +- Set `EXPERIMENTAL_FEATURES` to false for labelstudio +- Monaco editor disabled state +- Edge case where executions could be null +- Create destination properly +- Getcontainer status should timeout after 30s +- Enable response for temporary unavailability in sentinel push endpoint +- Use timeout in cleanup resources +- Add timeout to sentinel process checks for improved reliability +- Horizon job checker +- Update response message for sentinel push route +- Add own servers on cloud +- Application deployment +- Service update statsu +- If $SERVICE found in the service specific configuration, then search for it in the db +- Instance wide GitHub apps are not available on other teams then the source team +- Function calls +- UI +- Deletion of single backup +- Backup job deletion - delete all backups from s3 and local +- Use new removeOldBackups function +- Retention functions and folder deletion for local backups +- Storage retention setting +- Db without s3 should still backup +- Wording +- `Undefined variable $service` when creating a new service +- Nodebb service +- Calibre-web service +- Rallly and actualbudget service +- Removed container_name +- Added healthcheck for gotenberg template +- Gotenberg +- *(template)* Gotenberg healthcheck, use /health instead of /version +- Use wire:navigate on sidebar +- Use wire:navigate on dashboard +- Use wire:navigate on projects page +- More wire:navigate +- Even more wire:navigate +- Service navigation +- Logs icons everywhere + terminal +- Redis DB should use the new resourceable columns +- Joomla service +- Add back letters to prod password requirement +- Check System and GitHub time and throw and error if it is over 50s out of sync +- Error message and server time getting +- Error rendering +- Render html correctly now +- Indent +- Potential fix for permissions update +- Expiration time claim ('exp') must be a numeric value +- Sanitize html error messages +- Production password rule and cleanup code +- Use json as it is just better than string for huge amount of logs +- Use `wire:navigate` on server sidebar +- Use finished_at for the end time instead of created_at +- Cancelled deployments should not show end and duration time +- Redirect to server index instead of show on error in Advanced and DockerCleanup components +- Disable registration after creating the root user +- RootUserSeeder +- Regex username validation +- Add spacing around echo outputs +- Success message +- Silent return if envs are empty or not set. +- Create the private key before the server in the prod seeder +- Update ProductionSeeder to check for private key instead of server's private key +- *(ui)* Missing underline for docs link in the Swarm section (#4860) +- *(service)* Change chatwoot service postgres image from `postgres:12` to `pgvector/pgvector:pg12` +- Docker image parser +- Add public key attribute to privatekey model +- Correct service update logic in Docker Compose parser +- Update CDN URL in install script to point to nightly version +- *(service)* Add healthcheck to Cloudflared service (#4859) +- Remove wire:navigate from import backups +- *(ui)* Backups link should not redirected to general +- Envs with special chars during build +- *(db)* `finished_at` timestamps are not set for existing deployments +- Load service templates on cloud +- *(email)* Transactional email sending +- *(ui)* Add missing save button for new Docker Cleanup page +- *(ui)* Show preview deployment environment variables +- *(ui)* Show error on terminal if container has no shell (bash/sh) +- *(parser)* Resource URL should only be parsed if there is one +- *(core)* Compose parsing for apps +- *(redis)* Update environment variable keys from standalone_redis_id to resourceable_id +- *(routes)* Local API docs not available on domain or IP +- *(routes)* Local API docs not available on domain or IP +- *(core)* Update application_id references to resourable_id and resourable_type for Nixpacks configuration +- *(core)* Correct spelling of 'resourable' to 'resourceable' in Nixpacks configuration for ApplicationDeploymentJob +- *(ui)* Traefik dashboard url not working +- *(ui)* Proxy status badge flashing during navigation +- *(core)* Update environment variable generation logic in ApplicationDeploymentJob to handle different build packs +- *(env)* Shared variables can not be updated +- *(ui)* Metrics stuck in loading state +- *(ui)* Use `wire:navigate` to navigate to the server settings page +- *(service)* Plunk API & health check endpoint (#4925) +- *(service)* Infinite loading and lag with invoiceninja service (#4876) +- *(service)* Invoiceninja service +- *(workflows)* `Waiting for changes` label should also be considered and improved messages +- *(workflows)* Remove tags only if the PR has been merged into the main branch +- *(terminal)* Terminal shows that it is not available, even though it is +- *(labels)* Docker labels do not generated correctly +- *(helper)* Downgrade Nixpacks to v1.29.0 +- *(labels)* Generate labels when they are empty not when they are already generated +- *(storage)* Hetzner storage buckets not working +- *(ui)* Update database control UI to check server functionality before displaying actions +- *(ui)* Typo in upgrade message +- *(ui)* Cloudflare tunnel configuration should be an info, not a warning +- *(s3)* DigitalOcean storage buckets do not work +- *(ui)* Correct typo in container label helper text +- Disable certain parts if readonly label is turned off +- Cleanup old scheduled_task_executions +- Validate cron expression in Scheduled Task update +- *(core)* Check cron expression on save +- *(database)* Detect more postgres database image types +- *(templates)* Update service templates +- Remove quotes in COOLIFY_CONTAINER_NAME +- *(templates)* Update Trigger.dev service templates with v3 configuration +- *(database)* Adjust MongoDB restore command and import view styling +- *(core)* Improve public repository URL parsing for branch and base directory +- *(core)* Increase HTTP/2 max concurrent streams to 250 (default) +- *(ui)* Update docker compose file helper text to clarify repository modification +- *(ui)* Skip SERVICE_FQDN and SERVICE_URL variables during update +- *(core)* Stopping database is not disabling db proxy +- *(core)* Remove --remove-orphans flag from proxy startup command to prevent other proxy deletions (db) +- *(api)* Domain check when updating domain +- *(ui)* Always redirect to dashboard after team switch +- *(backup)* Escape special characters in database backup commands +- *(core)* Improve deployment failure Slack notification formatting +- *(core)* Update Slack notification formatting to use bold correctly +- *(core)* Enhance Slack deployment success notification formatting +- *(ui)* Simplify service templates loading logic +- *(ui)* Align title and add button vertically in various views +- Handle pullrequest:updated for reliable preview deployments +- *(ui)* Fix typo on team page (#5105) +- Cal.com documentation link give 404 (#5070) +- *(slack)* Notification settings URL in `HighDiskUsage` message (#5071) +- *(ui)* Correct typo in Storage delete dialog (#5061) +- *(lang)* Add missing italian translations (#5057) +- *(service)* Improve duplicati.yaml (#4971) +- *(service)* Links in homepage service (#5002) +- *(service)* Added SMTP credentials to getoutline yaml template file (#5011) +- *(service)* Added `KEY` Variable to Beszel Template (#5021) +- *(cloudflare-tunnels)* Dead links to docs (#5104) +- System-wide GitHub apps (#5114) +- Pull latest image from registry when using build server +- *(deployment)* Improve server selection for deployment cancellation +- *(deployment)* Improve log line rendering and formatting +- *(s3-storage)* Optimize team admin notification query +- *(core)* Improve connection testing with dynamic disk configuration for s3 backups +- *(core)* Update service status refresh event handling +- *(ui)* Adjust polling intervals for database and service status checks +- *(service)* Update Fider service template healthcheck command +- *(core)* Improve server selection error handling in Docker component +- *(core)* Add server functionality check before dispatching container status +- *(ui)* Disable sticky scroll in Monaco editor +- *(ui)* Add literal and multiline env support to services. +- *(services)* Owncloud docs link +- *(template)* Remove db-migration step from `infisical.yaml` (#5209) +- *(service)* Penpot (#5047) +- *(core)* Production dockerfile +- *(ui)* Update storage configuration guidance link +- *(ui)* Set default SMTP encryption to starttls +- *(notifications)* Correct environment URL path in application notifications +- *(config)* Update default PostgreSQL host to coolify-db instead of postgres +- *(docker)* Improve Docker compose file validation process +- *(ui)* Restrict service retrieval to current team +- *(core)* Only validate custom compose files +- *(mail)* Set default mailer to array when not specified +- *(ui)* Correct redirect routes after task deletion +- *(core)* Adding a new server should not try to make the default docker network +- *(core)* Clean up unnecessary files during application image build +- *(core)* Improve label generation and merging for applications and services +- *(billing)* Handle 'past_due' subscription status in Stripe processing +- *(revert)* Label parsing +- *(helpers)* Initialize command variable in parseCommandFromMagicEnvVariable +- *(billing)* Restrict Stripe subscription status update to 'active' only +- *(api)* Docker compose based apps creationg through api +- *(database)* Improve database type detection for Supabase Postgres images +- *(ssl)* Permission of ssl crt and key inside the container +- *(ui)* Make sure file mounts do not showing the encrypted values +- *(ssl)* Make default ssl mode require not verify-full as it does not need a ca cert +- *(ui)* Select component should not always uses title case +- *(db)* SSL certificates table and model +- *(migration)* Ssl certificates table +- *(databases)* Fix database name users new `uuid` instead of DB one +- *(database)* Fix volume and file mounts and naming +- *(migration)* Store subjectAlternativeNames as a json array in the db +- *(ssl)* Make sure the subjectAlternativeNames are unique and stored correctly +- *(ui)* Certificate expiration data is null before starting the DB +- *(deletion)* Fix DB deletion +- *(ssl)* Improve SSL cert file mounts +- *(ssl)* Always create ca crt on disk even if it is already there +- *(ssl)* Use mountPath parameter not a hardcoded path +- *(ssl)* Use 1 instead of on for mysql +- *(ssl)* Do not remove SSL directory +- *(ssl)* Wrong ssl cert is loaded to the server and UI error when regenerating SSL +- *(ssl)* Make sure when regenerating the CA cert it is not overwritten with a server cert +- *(ssl)* Regenerating certs for a specific DB +- *(ssl)* Fix MariaDB and MySQL need CA cert +- *(ssl)* Add mount path to DB to fix regeneration of certs +- *(ssl)* Fix SSL regeneration to sign with CA cert and use mount path +- *(ssl)* Get caCert correctly +- *(ssl)* Remove caCert even if it is a folder by accident +- *(ssl)* Ger caCert and `mountPath` correctly +- *(ui)* Only show Regenerate SSL Certificates button when there is a cert +- *(ssl)* Server id +- *(ssl)* When regenerating SSL certs the cert is not singed with the new CN +- *(ssl)* Adjust ca paths for MySQL +- *(ssl)* Remove mode selection for MariaDB as it is not supported +- *(ssl)* Permission issue with MariDB cert and key and paths +- *(ssl)* Rename Redis mode to verify-ca as it is not verify-full +- *(ui)* Remove unused mode for MongoDB +- *(ssl)* KeyDB port and caCert args are missing +- *(ui)* Enable SSL is not working correctly for KeyDB +- *(ssl)* Add `--tls` arg to DrangflyDB +- *(notification)* Always send SSL notifications +- *(database)* Change default value of enable_ssl to false for multiple tables +- *(ui)* Correct grammatical error in 404 page +- *(seeder)* Update GitHub app name in GithubAppSeeder +- *(plane)* Update APP_RELEASE to v0.25.2 in environment configuration +- *(domain)* Dispatch refreshStatus event after successful domain update +- *(database)* Correct container name generation for service databases +- *(database)* Limit container name length for database proxy +- *(database)* Handle unsupported database types in StartDatabaseProxy +- *(database)* Simplify container name generation in StartDatabaseProxy +- *(install)* Handle potential errors in Docker address pool configuration +- *(backups)* Retention settings +- *(redis)* Set default redis_username for new instances +- *(core)* Improve instantSave logic and error handling +- *(general)* Correct link to framework specific documentation +- *(core)* Redirect healthcheck route for dockercompose applications +- *(api)* Use name from request payload +- *(issue#4746)* Do not use setGitImportSettings inside of generateGitLsRemoteCommands +- Correct some spellings +- *(service)* Replace deprecated credentials env variables on keycloak service +- *(keycloak)* Update keycloak image version to 26.1 +- *(console)* Handle missing root user in password reset command +- *(ssl)* Handle missing CA certificate in SSL regeneration job +- *(copy-button)* Ensure text is safely passed to clipboard +- *(file-storage)* Double save on compose volumes +- *(parser)* Add logging support for applications in services +- Only get apps for the current team +- *(DeployController)* Cast 'pr' query parameter to integer +- *(deploy)* Validate team ID before deployment +- *(wakapi)* Typo in env variables and add some useful variables to wakapi.yaml (#5424) +- *(ui)* Instance Backup settings +- *(docs)* Comment out execute for now +- *(installation)* Mount the docker config +- *(installation)* Path to config file for docker login +- *(service)* Add health check to Bugsink service (#5512) +- *(email)* Emails are not sent in multiple cases +- *(deployments)* Use graceful shutdown instead of `rm` +- *(docs)* Contribute service url (#5517) +- *(proxy)* Proxy restart does not work on domain +- *(ui)* Only show copy button on https +- *(database)* Custom config for MongoDB (#5471) +- *(api)* Used ssh keys can be deleted +- *(email)* Transactional emails not sending +- *(CheckProxy)* Update port conflict check to ensure accurate grep matching +- *(CheckProxy)* Refine port conflict detection with improved grep patterns +- *(CheckProxy)* Enhance port conflict detection by adjusting ss command for better output +- *(api)* Add back validateDataApplications (#5539) +- *(CheckProxy, Status)* Prevent proxy checks when force_stop is active; remove debug statement in General +- *(Status)* Conditionally check proxy status and refresh button based on force_stop state +- *(General)* Change redis_password property to nullable string +- *(DeployController)* Update request handling to use input method and enhance OpenAPI description for deployment endpoint +- *(pre-commit)* Correct input redirection for /dev/tty and add OpenAPI generation command +- *(pricing-plans)* Adjust grid class for improved layout consistency in subscription pricing plans +- *(migrations)* Make stripe_comment field nullable in subscriptions table +- *(mongodb)* Also apply custom config when SSL is enabled +- *(templates)* Correct casing of denoKV references in service templates and YAML files +- *(deployment)* Handle missing destination in deployment process to prevent errors +- *(parser)* Transform associative array labels into key=value format for better compatibility +- *(redis)* Update username and password input handling to clarify database sync requirements +- *(source)* Update connected source display to handle cases with no source connected +- *(application)* Append base directory to git branch URLs for improved path handling +- *(templates)* Correct casing of "denokv" to "denoKV" in service templates JSON +- *(navbar)* Update error message link to use route for environment variables navigation +- Unsend template +- Replace ports with expose +- *(templates)* Update Unsend compose configuration for improved service integration +- *(backup-edit)* Conditionally enable S3 checkbox based on available validated S3 storage +- *(source)* Update no sources found message for clarity +- *(api)* Correct middleware for service update route to ensure proper permissions +- *(api)* Handle JSON response in service creation and update methods for improved error handling +- Add 201 json code to servers validate api response +- *(docker)* Ensure password hashing only occurs when HTTP Basic Authentication is enabled +- *(docker)* Enhance hostname and GPU option validation in Docker run to compose conversion +- *(terminal)* Enhance WebSocket client verification with authorized IPs in terminal server +- *(ApplicationDeploymentJob)* Ensure source is an object before checking GitHub app properties +- *(ui)* Disable livewire navigate feature (causing spam of setInterval()) +- *(ui)* Remove required attribute from image input in service application view +- *(ui)* Change application image validation to be nullable in service application view +- *(Server)* Correct proxy path formatting for Traefik proxy type +- *(service)* Graceful shutdown of old container (#5731) +- *(ServerCheck)* Enhance proxy container check to ensure it is running before proceeding +- *(applications)* Include pull_request_id in deployment queue check to prevent duplicate deployments +- *(database)* Update label for image input field to improve clarity +- *(ServerCheck)* Set default proxy status to 'exited' to handle missing container state +- *(database)* Reduce container stop timeout from 300 to 30 seconds for improved responsiveness +- *(ui)* System theming for charts (#5740) +- *(dev)* Mount points?! +- *(dev)* Proxy mount point +- *(ui)* Allow adding scheduled backups for non-migrated databases +- *(DatabaseBackupJob)* Escape PostgreSQL password in backup command (#5759) +- *(ui)* Correct closing div tag in service index view +- *(select)* Update fallback logo path to use absolute URL for improved reliability +- *(constants)* Adding 'fedora-asahi-remix' as a supported OS (#5646) +- *(authentik)* Update docker-compose configuration for authentik service +- *(api)* Allow nullable destination_uuid (#5683) +- *(service)* Fix documenso startup and mail (#5737) +- *(docker)* Fix production dockerfile +- *(service)* Navidrome service +- *(service)* Passbolt +- *(service)* Add missing ENVs to NTFY service (#5629) +- *(service)* NTFY is behind a proxy +- *(service)* Vert logo and ENVs +- *(service)* Add platform to Observium service +- *(ActivityMonitor)* Prevent multiple event dispatches during polling +- *(service)* Convex ENVs and update image versions (#5827) +- *(service)* Paymenter +- *(ApplicationDeploymentJob)* Ensure correct COOLIFY_FQDN/COOLIFY_URL values (#4719) +- *(service)* Snapdrop no matching manifest error (#5849) +- *(service)* Use the same volume between chatwoot and sidekiq (#5851) +- *(api)* Validate docker_compose_raw input in ApplicationsController +- *(api)* Enhance validation for docker_compose_raw in ApplicationsController +- *(select)* Update PostgreSQL versions and titles in resource selection +- *(database)* Include DatabaseStatusChanged event in activityMonitor dispatch +- *(css)* Tailwind v5 things +- *(service)* Diun ENV for consistency +- *(service)* Memos service name +- *(css)* 8+ issue with new tailwind v4 +- *(css)* `bg-coollabs-gradient` not working anymore +- *(ui)* Add back missing service navbar components +- *(deploy)* Update resource timestamp handling in deploy_resource method +- *(patches)* DNF reboot logic is flipped +- *(deployment)* Correct syntax for else statement in docker compose build command +- *(shared)* Remove unused relation from queryDatabaseByUuidWithinTeam function +- *(deployment)* Correct COOLIFY_URL and COOLIFY_FQDN assignments based on parsing version in preview deployments +- *(docker)* Ensure correct parsing of environment variables by limiting explode to 2 parts +- *(project)* Update selected environment handling to use environment name instead of UUID +- *(ui)* Update server status display and improve server addition layout +- *(service)* Neon WS Proxy service not working on ARM64 (#5887) +- *(server)* Enhance error handling in server patch check notifications +- *(PushServerUpdateJob)* Add null checks before updating application and database statuses +- *(environment-variables)* Update label text for build variable checkboxes to improve clarity +- *(service-management)* Update service stop and restart messages for improved clarity and formatting +- *(preview-form)* Update helper text formatting in preview URL template input for better readability +- *(application-management)* Improve stop messages for application, database, and service to enhance clarity and formatting +- *(application-configuration)* Prevent access to preview deployments for deploy_key applications and update menu visibility accordingly +- *(select-component)* Handle exceptions during parameter retrieval and environment selection in the mount method +- *(previews)* Escape container names in stopContainers method to prevent shell injection vulnerabilities +- *(docker)* Add protection against empty container queries in GetContainersStatus to prevent unnecessary updates +- *(modal-confirmation)* Decode HTML entities in confirmation text to ensure proper display +- *(select-component)* Enhance user interaction by adding cursor styles and disabling selection during processing +- *(deployment-show)* Remove unnecessary fixed positioning for button container to improve layout responsiveness +- *(email-notifications)* Change notify method to notifyNow for immediate test email delivery +- *(service-templates)* Update Convex service configuration to use FQDN variables +- *(database-heading)* Simplify stop database message for clarity +- *(navbar)* Remove unnecessary x-init directive for loading proxy configuration +- *(patches)* Add padding to loading message for better visibility during update checks +- *(terminal-connection)* Improve error handling and stability for auto-connection; enhance component readiness checks and retry logic +- *(terminal)* Add unique wire:key to terminal component for improved reactivity and state management +- *(css)* Adjust utility classes in utilities.css for consistent application of Tailwind directives +- *(css)* Refine utility classes in utilities.css for proper Tailwind directive application +- *(install)* Update Docker installation script to use dynamic OS_TYPE and correct installation URL +- *(cloudflare)* Add error handling to automated Cloudflare configuration script +- *(navbar)* Add error handling for proxy status check to improve user feedback +- *(web)* Update user team retrieval method for consistent authentication handling +- *(cloudflare)* Update refresh method to correctly set Cloudflare tunnel status and improve user notification on IP address update +- *(service)* Update service template for affine and add migration service for improved deployment process +- *(supabase)* Update Supabase service images and healthcheck methods for improved reliability +- *(terminal)* Now it should work +- *(degraded-status)* Remove unnecessary whitespace in badge element for cleaner HTML +- *(routes)* Add name to security route for improved route management +- *(migration)* Update default value handling for is_sentinel_enabled column in server_settings +- *(seeder)* Conditionally dispatch CheckAndStartSentinelJob based on server's sentinel status +- *(service)* Disable healthcheck logging for Gotenberg (#6005) +- *(service)* Joplin volume name (#5930) +- *(server)* Update sentinelUpdatedAt assignment to use server's sentinel_updated_at property +- *(service)* Audiobookshelf healthcheck command (#5993) +- *(service)* Downgrade Evolution API phone version (#5977) +- *(service)* Pingvinshare-with-clamav +- *(ssh)* Scp requires square brackets for ipv6 (#6001) +- *(github)* Changing github app breaks the webhook. it does not anymore +- *(parser)* Improve FQDN generation and update environment variable handling +- *(ui)* Enhance status refresh buttons with loading indicators +- *(ui)* Update confirmation button text for stopping database and service +- *(routes)* Update middleware for deploy route to use 'api.ability:deploy' +- *(ui)* Refine API token creation form and update helper text for clarity +- *(ui)* Adjust layout of deployments section for improved alignment +- *(ui)* Adjust project grid layout and refine server border styling for better visibility +- *(ui)* Update border styling for consistency across components and enhance loading indicators +- *(ui)* Add padding to section headers in settings views for improved spacing +- *(ui)* Reduce gap between input fields in email settings for better alignment +- *(docker)* Conditionally enable gzip compression in Traefik labels based on configuration +- *(parser)* Enable gzip compression conditionally for Pocketbase images and streamline service creation logic +- *(ui)* Update padding for trademarks policy and enhance spacing in advanced settings section +- *(ui)* Correct closing tag for sponsorship link in layout popups +- *(ui)* Refine wording in sponsorship donation prompt in layout popups +- *(ui)* Update navbar icon color and enhance popup layout for sponsorship support +- *(ui)* Add target="_blank" to sponsorship links in layout popups for improved user experience +- *(models)* Refine comment wording in User model for clarity on user deletion criteria +- *(models)* Improve user deletion logic in User model to handle team member roles and prevent deletion if user is alone in root team +- *(ui)* Update wording in sponsorship prompt for clarity and engagement +- *(shared)* Refactor gzip handling for Pocketbase in newParser function for improved clarity +- *(server)* Prepend 'mux_' to UUID in muxFilename method for consistent naming +- *(ui)* Enhance terminal access messaging to clarify server functionality and terminal status +- *(database)* Proxy ssl port if ssl is enabled +- *(terminal)* Ensure shell execution only uses valid shell if available in terminal command +- *(ui)* Improve destination selection description for clarity in resource segregation +- *(jobs)* Update middleware to use expireAfter for WithoutOverlapping in multiple job classes +- Removing eager loading (#6071) +- *(template)* Adjust health check interval and retries for excalidraw service +- *(ui)* Env variable settings wrong order +- *(service)* Ensure configuration changes are properly tracked and dispatched +- *(service)* Update Postiz compose configuration for improved server availability +- *(install.sh)* Use IPV4_PUBLIC_IP variable in output instead of repeated curl +- *(env)* Generate literal env variables better +- *(deployment)* Update x-data initialization in deployment view for improved functionality +- *(deployment)* Enhance COOLIFY_URL and COOLIFY_FQDN variable generation for better compatibility +- *(deployment)* Improve docker-compose domain handling and environment variable generation +- *(deployment)* Refactor domain parsing and environment variable generation using Spatie URL library +- *(deployment)* Update COOLIFY_URL and COOLIFY_FQDN generation to use Spatie URL library for improved accuracy +- *(scheduling)* Change redis cleanup command frequency from hourly to weekly for better resource management +- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.5 and 4.0.0-beta.420.6 +- *(database)* Ensure internal port defaults correctly for unsupported database types in StartDatabaseProxy +- *(versions)* Update coolify version numbers in versions.json and constants.php to 4.0.0-beta.420.6 and 4.0.0-beta.420.7 +- *(scheduling)* Remove unnecessary padding from scheduled task form layout for improved UI consistency +- *(horizon)* Update queue configuration to use environment variable for dynamic queue management +- *(horizon)* Add silenced jobs +- *(application)* Sanitize service names for HTML form binding and ensure original names are stored in docker compose domains +- *(previews)* Adjust padding for rate limit message in application previews +- *(previews)* Order application previews by pull request ID in descending order +- *(previews)* Add unique wire keys for preview containers and services based on pull request ID +- *(previews)* Enhance domain generation logic for application previews, ensuring unique domains are created when none are set +- *(previews)* Refine preview domain generation for Docker Compose applications, ensuring correct method usage based on build pack type +- *(ui)* Typo on proxy request handler tooltip (#6192) +- *(backups)* Large database backups are not working (#6217) +- *(backups)* Error message if there is no exception +- *(installer)* Public IPv4 link does not work +- *(composer)* Version constraint of prompts +- *(service)* Budibase secret keys (#6205) +- *(service)* Wg-easy host should be just the FQDN +- *(ui)* Search box overlaps the sidebar navigation (#6176) +- *(webhooks)* Exclude webhook routes from CSRF protection (#6200) +- *(services)* Update environment variable naming convention to use underscores instead of dashes for SERVICE_FQDN and SERVICE_URL +- *(service)* Triliumnext platform and link +- *(application)* Update service environment variables when generating domain for Docker Compose +- *(application)* Add option to suppress toast notifications when loading compose file +- *(git)* Tracking issue due to case sensitivity +- *(git)* Tracking issue due to case sensitivity +- *(git)* Tracking issue due to case sensitivity +- *(ui)* Delete button width on small screens (#6308) +- *(service)* Matrix entrypoint +- *(ui)* Add flex-wrap to prevent overflow on small screens (#6307) +- *(docker)* Volumes get delete when stopping a service if `Delete Unused Volumes` is activated (#6317) +- *(docker)* Cleanup always running on deletion +- *(proxy)* Remove hardcoded port 80/443 checks (#6275) +- *(service)* Update healthcheck of penpot backend container (#6272) +- *(api)* Duplicated logs in application endpoint (#6292) +- *(service)* Documenso signees always pending (#6334) +- *(api)* Update service upsert to retain name and description values if not set +- *(database)* Custom postgres configs with SSL (#6352) +- *(policy)* Update delete method to check for admin status in S3StoragePolicy +- *(container)* Sort containers alphabetically by name in ExecuteContainerCommand and update filtering in Terminal Index +- *(application)* Streamline environment variable updates for Docker Compose services and enhance FQDN generation logic +- *(constants)* Update 'Change Log' to 'Changelog' in settings dropdown +- *(constants)* Update coolify version to 4.0.0-beta.420.7 +- *(parsers)* Clarify comments and update variable checks for FQDN and URL handling +- *(terminal)* Update text color for terminal availability message and improve readability +- *(drizzle-gateway)* Remove healthcheck from drizzle-gateway compose file and update service template +- *(templates)* Should generate old SERVICE_FQDN service templates as well +- *(constants)* Update official service template URL to point to the v4.x branch for accuracy +- *(git)* Use exact refspec in ls-remote to avoid matching similarly named branches (e.g., changeset-release/main). Use refs/heads/ or provider-specific PR refs. +- *(ApplicationPreview)* Change null check to empty check for fqdn in generate_preview_fqdn method +- *(email notifications)* Enhance EmailChannel to validate team membership for recipients and handle errors gracefully +- *(service api)* Separate create and update service functionalities +- *(templates)* Added a category tag for the docs service filter +- *(application)* Clear Docker Compose specific data when switching away from dockercompose +- *(database)* Conditionally set started_at only if the database is running +- *(ui)* Handle null values in postgres metrics (#6388) +- Disable env sorting by default +- *(proxy)* Filter host network from default proxy (#6383) +- *(modal)* Enhance confirmation text handling +- *(notification)* Update unread count display and improve HTML rendering +- *(select)* Remove unnecessary sanitization for logo rendering +- *(tags)* Update tag display to limit name length and adjust styling +- *(init)* Improve error handling for deployment and template pulling processes +- *(settings-dropdown)* Adjust unread count badge size and display logic for better consistency +- *(sanitization)* Enhance DOMPurify hook to remove Alpine.js directives for improved XSS protection +- *(servercheck)* Properly check server statuses with and without Sentinel +- *(errors)* Update error pages to provide navigation options +- *(github-deploy-key)* Update background color for selected private keys in deployment key selection UI +- *(auth)* Enhance authorization checks in application management +- *(backups)* S3 backup upload is failing +- *(backups)* Rollback helper update for now +- *(parsers)* Replace hyphens with underscores in service names for consistency. this allows to properly parse custom domains in docker compose based applications +- *(parsers)* Implement parseDockerVolumeString function to handle various Docker volume formats and modes, including environment variables and Windows paths. Add unit tests for comprehensive coverage. +- *(git)* Submodule update command uses an unsupported option (#6454) +- *(service)* Swap URL for FQDN on matrix template (#6466) +- *(parsers)* Enhance volume string handling by preserving mode in application and service parsers. Update related unit tests for validation. +- *(docker)* Update parser version in FQDN generation for service-specific URLs +- *(parsers)* Do not modify service names, only for getting fqdns and related envs +- *(compose)* Temporary allow to edit volumes in apps (compose based) and services +- *(previews)* Simplify FQDN generation logic by removing unnecessary empty check +- *(templates)* Update Matrix service compose configuration for improved compatibility and clarity ### 💼 Other -- Pocketbase release - -## [3.11.10] - 2022-11-16 - -### 🚀 Features - -- Only show expose if no proxy conf defined in template -- Custom/private docker registries - -### 🐛 Bug Fixes - -- Local dev api/ws urls -- Wrong template/type -- Gitea icon is svg -- Gh actions -- Gh actions -- Replace $$generate vars -- Webhook traefik -- Exposed ports -- Wrong icons on dashboard -- Escape % in secrets -- Move debug log settings to build logs -- Storage for compose bp + debug on -- Hasura admin secret -- Logs -- Mounts -- Load logs after build failed -- Accept logged and not logged user in /base -- Remote haproxy password/etc -- Remove hardcoded sentry dsn -- Nope in database strings - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Version++ -- Version++ - -## [3.11.9] - 2022-11-15 - -### 🐛 Bug Fixes - -- IsBot issue - -## [3.11.8] - 2022-11-14 - -### 🐛 Bug Fixes - -- Default icon for new services - -## [3.11.1] - 2022-11-08 - -### 🚀 Features - -- Rollback coolify - -### 🐛 Bug Fixes - -- Remove contribution docs -- Umami template -- Compose webhooks fixed -- Variable replacements -- Doc links -- For rollback -- N8n and weblate icon -- Expose ports for services -- Wp + mysql on arm -- Show rollback button loading -- No tags error -- Update on mobile -- Dashboard error -- GetTemplates -- Docker compose persistent volumes -- Application persistent storage things -- Volume names for undefined volume names in compose -- Empty secrets on UI -- Ports for services - -### 💼 Other - -- Secrets on apps +- Only allow cleanup in production +- Make copy/password visible +- Dns check +- Remote docker engine +- Colorful states +- Application start +- Colors on svelte-select +- Improvements +- Fix +- Better layout for root team - Fix - Fixes -- Reload compose loading - -### 🚜 Refactor - -- Code - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Add jda icon for lavalink service -- Version++ - -### ◀️ Revert - -- Revert: revert - -## [3.11.0] - 2022-11-07 - -### 🚀 Features - -- Initial support for specific git commit -- Add default to latest commit and support for gitlab -- Redirect catch-all rule - -### 🐛 Bug Fixes - -- Secret errors -- Service logs -- Heroku bp -- Expose port is readonly on the wrong condition -- Toast -- Traefik proxy q 10s -- App logs view -- Tooltip -- Toast, rde, webhooks -- Pathprefix -- Load public repos -- Webhook simplified -- Remote webhooks -- Previews wbh -- Webhooks -- Websecure redirect -- Wb for previews -- Pr stopps main deployment -- Preview wbh -- Wh catchall for all -- Remove old minio proxies -- Template files -- Compose icon -- Templates -- Confirm restart service -- Template -- Templates -- Templates -- Plausible analytics things -- Appwrite webhook -- Coolify instance proxy -- Migrate template -- Preview webhooks -- Simplify webhooks -- Remove ghost-mariadb from the list -- More simplified webhooks -- Umami + ghost issues - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.10.16] - 2022-10-12 - -### 🐛 Bug Fixes - -- Single container logs and usage with compose - -### 💼 Other - -- New resource label - -## [3.10.15] - 2022-10-12 - -### 🚀 Features - -- Monitoring by container - -### 🐛 Bug Fixes - -- Do not show nope as ip address for dbs -- Add git sha to build args -- Smart search for new services -- Logs for not running containers -- Update docker binaries -- Gh release -- Dev container -- Gitlab auth and compose reload -- Check compose domains in general -- Port required if fqdn is set -- Appwrite v1 missing containers -- Dockerfile -- Pull does not work remotely on huge compose file - -### ⚙️ Miscellaneous Tasks - -- Update staging release - -## [3.10.14] - 2022-10-05 - -### 🚀 Features - -- Docker compose support -- Docker compose -- Docker compose - -### 🐛 Bug Fixes - -- Do not use npx -- Pure docker based development - -### 💼 Other - -- Docker-compose support -- Docker compose -- Remove worker jobs -- One less worker thread - -### 🧪 Testing - -- Remove prisma - -## [3.10.5] - 2022-09-26 - -### 🚀 Features - -- Add migration button to appwrite -- Custom certificate -- Ssl cert on traefik config -- Refresh resource status on dashboard -- Ssl certificate sets custom ssl for applications -- System-wide github apps -- Cleanup unconfigured applications -- Cleanup unconfigured services and databases - -### 🐛 Bug Fixes - -- Ui -- Tooltip -- Dropdown -- Ssl certificate distribution -- Db migration -- Multiplex ssh connections -- Able to search with id -- Not found redirect -- Settings db requests -- Error during saving logs -- Consider base directory in heroku bp -- Basedirectory should be empty if null -- Allow basedirectory for heroku -- Stream logs for heroku bp -- Debug log for bp -- Scp without host verification & cert copy -- Base directory & docker bp -- Laravel php chooser -- Multiplex ssh and ssl copy -- Seed new preview secret types -- Error notification -- Empty preview value -- Error notification -- Seed -- Service logs -- Appwrite function network is not the default -- Logs in docker bp -- Able to delete apps in unconfigured state -- Disable development low disk space -- Only log things to console in dev mode -- Do not get status of more than 10 resources defined by category -- BaseDirectory -- Dashboard statuses -- Default buildImage and baseBuildImage -- Initial deploy status -- Show logs better -- Do not start tcp proxy without main container -- Cleanup stucked tcp proxies -- Default 0 pending invitations -- Handle forked repositories -- Typo -- Pr branches -- Fork pr previews -- Remove unnecessary things -- Meilisearch data dir -- Verify and configure remote docker engines -- Add buildkit features -- Nope if you are not logged in - -### 💼 Other - +- Fix +- Fix +- Fix +- Fix +- Fix +- Fix +- Fix +- Insane amount +- Fix +- Fixes +- Fixes +- Fix +- Fixes +- Fixes +- Show extraconfig if wp is running +- Umami service +- Base image selector +- Laravel +- Appwrite +- Testing WS +- Traefik?! +- Traefik +- Traefik +- Traefik migration +- Traefik +- Traefik +- Traefik +- Notifications and application usage +- *(fix)* Traefik +- Css +- Error message https://github.com/coollabsio/coolify/issues/502 +- Changes +- Settings +- For removing app +- Local ssh port +- Redesign a lot +- Fixes +- Loading indicator for plausible buttons +- Fix +- Fider +- Typing +- Fixes here and there +- Dashboard fine-tunes +- Fine-tune +- Fixes +- Fix +- Dashbord fixes +- Fixes +- Fixes +- Route to the correct path when creating destination from db config +- Fixes +- Change tooltips and info boxes +- Added rc release +- Database_branches +- Login page +- Fix login/register page +- Update devcontainer +- Add debug log +- Fix initial loading icon bg +- Fix loading start/stop db/services +- Dashboard updates and a lot more +- Dashboard updates +- Fix tooltip +- Fix button +- Fix follow button +- Arm should be on next all the time +- Fix plausible +- Fix cleanup button +- Fix buttons - Responsive! - Fixes - Fix git icon @@ -6421,1851 +3647,1491 @@ ### 💼 Other - Iam & settings update - Send 200 for ping and installation wh - Settings icon - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Version++ -- Version++ -- Version++ -- Version++ -- Version++ - -### ◀️ Revert - -- Show usage everytime - -## [3.10.2] - 2022-09-11 - -### 🚀 Features - -- Add queue reset button -- Previewapplications init -- PreviewApplications finalized -- Fluentbit -- Show remote servers -- *(layout)* Added drawer when user is in mobile -- Re-apply ui improves -- *(ui)* Improve header of pages -- *(styles)* Make header css component -- *(routes)* Improve ui for apps, databases and services logs - -### 🐛 Bug Fixes - -- Changing umami image URL to get latest version -- Gitlab importer for public repos -- Show error logs -- Umami init sql -- Plausible analytics actions -- Login -- Dev url -- UpdateMany build logs -- Fallback to db logs -- Fluentbit configuration -- Coolify update -- Fluentbit and logs -- Canceling build -- Logging -- Load more -- Build logs -- Versions of appwrite -- Appwrite?! -- Get building status -- Await -- Await #2 -- Update PR building status -- Appwrite default version 1.0 -- Undead endpoint does not require JWT -- *(routes)* Improve design of application page -- *(routes)* Improve design of git sources page -- *(routes)* Ui from destinations page -- *(routes)* Ui from databases page -- *(routes)* Ui from databases page -- *(routes)* Ui from databases page -- *(routes)* Ui from services page -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- *(routes)* Ui from settings page -- *(routes)* Duplicates classes in services page -- *(routes)* Searchbar ui -- Github conflicts -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- *(routes)* More ui tweaks -- Ui with headers -- *(routes)* Header of settings page in databases -- *(routes)* Ui from secrets table - -### 💼 Other - -- Fix plausible -- Fix cleanup button -- Fix buttons - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Minor changes -- Minor changes -- Minor changes -- Whoops - -## [3.10.1] - 2022-09-10 - -### 🐛 Bug Fixes - -- Show restarting apps -- Show restarting application & logs -- Remove unnecessary gitlab group name -- Secrets for PR -- Volumes for services -- Build secrets for apps -- Delete resource use window location - -### 💼 Other - -- Fix button -- Fix follow button -- Arm should be on next all the time - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.10.0] - 2022-09-08 - -### 🚀 Features - -- New servers view - -### 🐛 Bug Fixes - -- Change to execa from utils -- Save search input -- Ispublic status on databases -- Port checkers -- Ui variables -- Glitchtip env to pyhton boolean -- Autoupdater - -### 💼 Other - -- Dashboard updates -- Fix tooltip - -## [3.9.4] - 2022-09-07 - -### 🐛 Bug Fixes - -- DnsServer formatting -- Settings for service - -## [3.9.3] - 2022-09-07 - -### 🐛 Bug Fixes - -- Pr previews - -## [3.9.2] - 2022-09-07 - -### 🚀 Features - -- Add traefik acme json to coolify container -- Database secrets - -### 🐛 Bug Fixes - -- Gitlab webhook -- Use ip address instead of window location -- Use ip instead of window location host -- Service state update -- Add initial DNS servers -- Revert last change with domain check -- Service volume generation -- Minio default env variables -- Add php 8.1/8.2 -- Edgedb ui -- Edgedb stuff -- Edgedb - -### 💼 Other - -- Fix login/register page -- Update devcontainer -- Add debug log -- Fix initial loading icon bg -- Fix loading start/stop db/services -- Dashboard updates and a lot more - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ - -## [3.9.0] - 2022-09-06 - -### 🐛 Bug Fixes - -- Debug api logging + gh actions -- Workdir -- Move restart button to settings - -## [3.9.1-rc.1] - 2022-09-06 - -### 🚀 Features - -- *(routes)* Rework ui from login and register page - -### 🐛 Bug Fixes - -- Ssh pid agent name -- Repository link trim -- Fqdn or expose port required -- Service deploymentEnabled -- Expose port is not required -- Remote verification -- Dockerfile - -### 💼 Other - -- Database_branches -- Login page - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ - -## [3.9.0-rc.1] - 2022-09-02 - -### 🚀 Features - -- New service - weblate -- Restart application -- Show elapsed time on running builds -- Github allow fual branches -- Gitlab dual branch -- Taiga - -### 🐛 Bug Fixes - -- Glitchtip things -- Loading state on start -- Ui -- Submodule -- Gitlab webhooks -- UI + refactor -- Exposedport on save -- Appwrite letsencrypt -- Traefik appwrite -- Traefik -- Finally works! :) -- Rename components + remove PR/MR deployment from public repos -- Settings missing id -- Explainer component -- Database name on logs view -- Taiga - -### 💼 Other - +- Docker-compose support +- Docker compose +- Remove worker jobs +- One less worker thread +- New resource label +- Secrets on apps +- Fix - Fixes -- Change tooltips and info boxes -- Added rc release +- Reload compose loading +- Pocketbase release +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Conditional on environment +- Add missing variables +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Trpc +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Extract process handling from async job. +- Persisting data +- Scheduled backups +- Boarding +- Backup existing database +- User should know that the public key +- Services are not availble yet +- Show registered users on waitlist page +- Nixpacksarchive +- Add Plausible analytics +- Global env variables +- Fix +- Trial emails +- Server check instead of app check +- Show trial instead of sub +- Server lost connection +- Services +- Services +- Services +- Ui for services +- Services +- Services +- Services +- Fixes +- Fix typo +- Fixed z-index for version link. +- Add source button +- Fixed z-index for magicbar +- A bit better error +- More visible feedback button +- Update help modal +- Help +- Marketing emails +- Fix previews to preview +- Uptime kume hc updated +- Switch back to /data (volume errors) +- Notifications +- Add shared email option to everyone +- Dockerimage +- Updated dashboard +- Fix +- Fix +- Coolify proxy access logs exposed in dev +- Able to select environment on new resource +- Delete server +- Redis +- Wordpress +- Add helper to service domains +- PAT by team +- Generate services +- Mongodb backup +- Mongodb backup +- Updates +- Fix subs +- New deployment jobs +- Compose based apps +- Swarm +- Swarm +- Swarm +- Swarm +- Disable trial +- Meilisearch +- Broadcast +- 🌮 +- Env vars +- Migrate to livewire 3 +- Fix for comma in labels +- Add image name to service stack + better options visibility +- Swarm +- Swarm +- Send notification email if payment +- New modal component +- Specific about newrelic logdrains +- Updates +- Change + icon to hamburger. +- Redesign +- Redesign +- Run cleanup every day +- Fix +- Fix log outputs +- Automatic cloudflare tunnels +- Backup executions +- Light buttons +- Multiple server view +- New pricing +- Fix allowTab logic +- Use 2 space instead of tab +- Non-root user for remote servers +- Non-root +- Update resource operations view +- Fix tag view +- Fix a few boxes here and there +- Responsive here and there +- Rocketchat +- New services based git apps +- Unnecessary notification +- Update process +- Glances service +- Glances +- Able to update application +- Add basedir + compose file in new compose based apps +- Formbricks template add required CRON_SECRET +- Add required CRON_SECRET to Formbricks template +- Service env parsing +- Actually update timezone on the server +- Cron jobs are executed based on the server timezone +- Server timezone seeder +- Recent backups UI +- Use apt-get instead of apt +- Typo +- Only pull helper image if the version is newer than the one +- Plunk svg +- Pull helper image if not available otherwise s3 backup upload fails +- Set a default server timezone +- Implement SSH Multiplexing +- Enabel mux +- Cleanup stale multiplexing connections +- Remote servers with port and user +- Do not change localhost server name on revalidation +- Release.md file +- SSH Multiplexing on docker desktop on Windows +- Remove labels and assignees on issue close +- Make sure this action is also triggered on PR issue close +- Volumes on development environment +- Clean new volume name for dev volumes +- Persist DBs, services and so on stored in data/coolify +- Add SSH Key fingerprint to DB +- Add a fingerprint to every private key on save, create... +- Make sure invalid private keys can not be added +- Encrypt private SSH keys in the DB +- Add is_sftp and is_server_ssh_key coloums +- New ssh key file name on disk +- Store all keys on disk by default +- Populate SSH key folder +- Populate SSH keys in dev +- Use new function names and logic everywhere +- Create a Multiplexing Helper +- SSH multiplexing +- Remove unused code form multiplexing +- SSH Key cleanup job +- Private key with ID 2 on dev +- Move more functions to the PrivateKey Model +- Add ssh key fingerprint and generate one for existing keys +- ID issues on dev seeders +- Server ID 0 +- Make sure in use private keys are not deleted +- Do not delete SSH Key from disk during server validation error +- UI bug, do not write ssh key to disk in server dialog +- SSH Multiplexing for Jobs +- SSH algorhytm text +- Few multiplexing things +- Clear mux directory +- Multiplexing do not write file manually +- Integrate tow step process in the modal component WIP +- Ability to hide labels +- DB start, stop confirm +- Del init script +- General confirm +- Preview deployments and typos +- Service confirmation +- Confirm file storage +- Stop service confirm +- DB image cleanup +- Confirm ressource operation +- Environment variabel deletion +- Confirm scheduled tasks +- Confirm API token +- Confirm private key +- Confirm server deletion +- Confirm server settings +- Proxy stop and restart confirmation +- GH app deletion confirmation +- Redeploy all confirmation +- User deletion confirmation +- Team deletion confirmation +- Backup job confirmation +- Delete volume confirmation +- More conformations and fixes +- Delete unused private keys button +- Ray error because port is not uncommented +- #3322 deploy DB alterations before updating +- Css issue with advanced settings and remove cf tunnel in onboarding +- New cf tunnel install flow +- Made help text more clear +- Cloudflare tunnel +- Make helper text more clean to use a FQDN and not an URL +- Manual cleanup button and unused volumes and network deletion +- Force helper image removal +- Use the new confirmation flow +- Typo +- Typo in install script +- If API is disabeled do not show API token creation stuff +- Disable API by default +- Add debug bar +- Remove memlock as it caused problems for some users +- Server storage check +- Show backup button on supported db service stacks +- Update helper version +- Outline +- Directus +- Supertokens +- Supertokens json +- Rabbitmq +- Easyappointments +- Soketi +- Dozzle +- Windmill +- Coolify.json +- Keycloak +- Other DB options for freshrss +- Nextcloud MariaDB and MySQL versions +- Add peppermint +- Loggy +- Add UI for redis password and username +- Wireguard-easy template +- Https://github.com/coollabsio/coolify/issues/4186 +- Separate resources by type in projects view +- Improve s3 add view +- Caddy docker labels do not honor "strip prefix" option +- Test rename GitHub app +- Checkmate service and fix prowlar slogan (too long) +- Arrrrr +- Dep +- Docker dep +- Trigger.dev templates - wrong key length issue +- Trigger.dev template - missing ports and wrong env usage +- Trigger.dev template - fixed otel config +- Trigger.dev template - fixed otel config +- Trigger.dev template - fixed port config +- Bump all dependencies (#5216) +- Bump Coolify to 4.0.0-beta.398 +- Bump Coolify to 4.0.0-beta.400 +- *(migration)* Add SSL fields to database tables +- SSL Support for KeyDB +- Add missing UUID to openapi spec +- Add missing openapi items to PrivateKey +- Adjust Workflows for v5 (#5689) +- Add support for postmarketOS (#5608) +- *(core)* Simplify events for app/db/service status changes +- *(settings-dropdown)* Add icons to buttons for improved UI in settings dropdown +- *(ui)* Introduce task for simplifying resource operations UI by replacing boxes with dropdown selections to enhance user experience and streamline interactions + +### 🚜 Refactor + +- Code +- Env variable generator +- Service logs are now on one page +- Application status changed realtime +- Custom labels +- Clone project +- Compose file and install script +- Add SCHEDULER environment variable to StartSentinel.php +- Update edit-domain form in project service view +- Add Huly services to compose file +- Remove redundant heading in backup settings page +- Add isBuildServer method to Server model +- Update docker network creation in ApplicationDeploymentJob +- Update destination.blade.php to add group class for better styling +- Applicationdeploymentjob +- Improve code structure in ApplicationDeploymentJob.php +- Remove unnecessary debug statement in ApplicationDeploymentJob.php +- Remove unnecessary debug statements and improve code structure in RunRemoteProcess.php and ApplicationDeploymentJob.php +- Remove unnecessary logging statements from UpdateCoolify +- Update storage form inputs in show.blade.php +- Improve Docker Compose parsing for services +- Remove unnecessary port appending in updateCompose function +- Remove unnecessary form class in profile index.blade.php +- Update form layout in invite-link.blade.php +- Add log entry when starting new application deployment +- Improve Docker Compose parsing for services +- Update Docker Compose parsing for services +- Update slogan in shlink.yaml +- Improve display of deployment time in index.blade.php +- Remove commented out code for clearing Ray logs +- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview +- Append utm_source parameter to documentation URL +- Update save_environment_variables method to use application's environment_variables instead of environment_variables_preview +- Update deployment previews heading to "Deployments" +- Remove unused variables and improve code readability +- Initialize null properties in Github Change component +- Improve pre and post deployment command inputs +- Improve handling of Docker volumes in parseDockerComposeFile function +- Replaces duplications in code with a single function +- Update text color for stderr output in deployment show view +- Update text color for stderr output in deployment show view +- Remove debug code for saving environment variables +- Update Docker build commands for better performance and flexibility +- Update image sizes and add new logos to README.md +- Update README.md with new logos and fix styling +- Update shared.php to use correct key for retrieving sentinel version +- Update container name assignment in Application model +- Remove commented code for docker container removal +- Update Application model to include getDomainsByUuid method +- Update Project/Show component to sort environments by created_at +- Update profile index view to display 2FA QR code in a centered container +- Update dashboard.blade.php to use project's default environment for redirection +- Update gitCommitLink method to handle null values in source.html_url +- Update docker-compose generation to use multi-line literal block +- Update Service model's saveComposeConfigs method +- Add default environment to Service model's saveComposeConfigs method +- Improve handling of default environment in Service model's saveComposeConfigs method +- Remove commented out code in Service model's saveComposeConfigs method +- Update stack-form.blade.php to include wire:target attribute for submit button +- Update code to use str() instead of Str::of() for string manipulation +- Improve formatting and readability of source.blade.php +- Add is_build_time property to nixpacks_php_fallback_path and nixpacks_php_root_dir +- Simplify code for retrieving subscription in Stripe webhook +- Add force parameter to StartProxy handle method +- Comment out unused code for network cleanup +- Reset default labels when docker_compose_domains is modified +- Webhooks view +- Tags view +- Only get instanceSettings once from db +- Update Dockerfile to set CI environment variable to true +- Remove unnecessary code in AppServiceProvider.php +- Update Livewire configuration views +- Update Webhooks.php to use nullable type for webhook URLs +- Add lazy loading to tags in Livewire configuration view +- Update metrics.blade.php to improve alert message clarity +- Update version numbers to 4.0.0-beta.312 +- Update version numbers to 4.0.0-beta.314 +- Remove unused code and fix storage form layout +- Update Docker Compose build command to include --pull flag +- Update DockerCleanupJob to handle nullable usageBefore property +- Server status job and docker cleanup job +- Update DockerCleanupJob to use server settings for force cleanup +- Update DockerCleanupJob to use server settings for force cleanup +- Disable health check for Rust applications during deployment +- Update CleanupDatabase.php to adjust keep_days based on environment +- Adjust keep_days in CleanupDatabase.php based on environment +- Remove commented out code for cleaning up networks in CleanupDocker.php +- Update livewire polling interval in heading.blade.php +- Remove unused code for checking server status in Heading.php +- Simplify log drain installation in ServerCheckJob +- Remove unnecessary debug statement in ServerCheckJob +- Simplify log drain installation and stop log drain if necessary +- Cleanup unnecessary dynamic proxy configuration in Init command +- Remove unnecessary debug statement in ApplicationDeploymentJob +- Update timeout for graceful_shutdown_container in ApplicationDeploymentJob +- Remove unused code and optimize CheckForUpdatesJob +- Update ProxyTypes enum values to use TRAEFIK instead of TRAEFIK_V2 +- Update Traefik labels on init and cleanup unnecessary dynamic proxy configuration +- Update StandalonePostgresql database initialization and backup handling +- Update cron expressions and add helper text for scheduled tasks +- Update Server model getContainers method to use collect() for containers and containerReplicates +- Import ProxyTypes enum and use TRAEFIK instead of TRAEFIK_V2 +- Update event listeners in Show components +- Refresh application to get latest database changes +- Update RabbitMQ configuration to use environment variable for port +- Remove debug statement in parseDockerComposeFile function +- ParseServiceVolumes +- Update OpenApi command to generate documentation +- Remove unnecessary server status check in destination view +- Remove unnecessary admin user email and password in budibase.yaml +- Improve saving of custom internal name in Advanced.php +- Add conditional check for volumes in generate_compose_file() +- Improve storage mount forms in add.blade.php +- Load environment variables based on resource type in sortEnvironmentVariables() +- Remove unnecessary network cleanup in Init.php +- Remove unnecessary environment variable checks in parseDockerComposeFile() +- Add null check for docker_compose_raw in parseCompose() +- Update dockerComposeParser to use YAML data from $yaml instead of $compose +- Convert service variables to key-value pairs in parseDockerComposeFile function +- Update database service name from mariadb to mysql +- Remove unnecessary code in DatabaseBackupJob and BackupExecutions +- Update Docker Compose parsing function to convert service variables to key-value pairs +- Update Docker Compose parsing function to convert service variables to key-value pairs +- Remove unused server timezone seeder and related code +- Remove unused server timezone seeder and related code +- Remove unused PullCoolifyImageJob from schedule +- Update parse method in Advanced, All, ApplicationPreview, General, and ApplicationDeploymentJob classes +- Remove commented out code for getIptables() in Dashboard.php +- Update .env file path in install.sh script +- Update SELF_HOSTED environment variable in docker-compose.prod.yml +- Remove unnecessary code for creating coolify network in upgrade.sh +- Update environment variable handling in StartClickhouse.php and ApplicationDeploymentJob.php +- Improve handling of COOLIFY_URL in shared.php +- Update build_args property type in ApplicationDeploymentJob +- Update background color of sponsor section in README.md +- Update Docker Compose location handling in PublicGitRepository +- Upgrade process of Coolify +- Improve handling of server timezones in scheduled backups and tasks +- Improve handling of server timezones in scheduled backups and tasks +- Improve handling of server timezones in scheduled backups and tasks +- Update cleanup schedule to run daily at midnight +- Skip returning volume if driver type is cifs or nfs +- Improve environment variable handling in shared.php +- Improve handling of environment variable merging in upgrade script +- Remove unnecessary code in ExecuteContainerCommand.php +- Improve Docker network connection command in StartService.php +- Terminal / run command +- Add authorization check in ExecuteContainerCommand mount method +- Remove unnecessary code in Terminal.php +- Remove unnecessary code in Terminal.blade.php +- Update WebSocket connection initialization in terminal.blade.php +- Remove unnecessary console.log statements in terminal.blade.php +- Update Docker cleanup label in Heading.php and Navbar.php +- Remove commented out code in Navbar.php +- Remove CleanupSshKeysJob from schedule in Kernel.php +- Update getAJoke function to exclude offensive jokes +- Update getAJoke function to use HTTPS for API request +- Update CleanupHelperContainersJob to use more efficient Docker command +- Update PrivateKey model to improve code readability and maintainability +- Remove unnecessary code in PrivateKey model +- Update PrivateKey model to use ownedByCurrentTeam() scope for cleanupUnusedKeys() +- Update install.sh script to check if coolify-db volume exists before generating SSH key +- Update ServerSeeder and PopulateSshKeysDirectorySeeder +- Improve attribute sanitization in Server model +- Update confirmation button text for deletion actions +- Remove unnecessary code in shared.php file +- Update environment variables for services in compose files +- Update select.blade.php to improve trademarks policy display +- Update select.blade.php to improve trademarks policy display +- Fix typo in subscription URLs +- Add Postiz service to compose file (disabled for now) +- Update shared.php to include predefined ports for services +- Simplify SSH key synchronization logic +- Remove unused code in DatabaseBackupStatusJob and PopulateSshKeysDirectorySeeder +- Remove commented out code and improve environment variable handling in newParser function +- Improve label positioning in input and checkbox components +- Group and sort fields in StackForm by service name and password status +- Improve layout and add checkbox for task enablement in scheduled task form +- Update checkbox component to support full width option +- Update confirmation label in danger.blade.php template +- Fix typo in execute-container-command.blade.php +- Update OS_TYPE for Asahi Linux in install.sh script +- Add localhost as Server if it doesn't exist and not in cloud environment +- Add localhost as Server if it doesn't exist and not in cloud environment +- Update ProductionSeeder to fix issue with coolify_key assignment +- Improve modal confirmation titles and button labels +- Update install.sh script to remove redirection of upgrade output to /dev/null +- Fix modal input closeOutside prop in configuration.blade.php +- Add support for IPv6 addresses in sslip function +- Update environment variable name for uptime-kuma service +- Improve start proxy script to handle existing containers gracefully +- Update delete server confirmation modal buttons +- Remove unnecessary code +- Update search input placeholder in resource index view +- Remove deployment queue when deleting an application +- Improve SSH command generation in Terminal.php and terminal-server.js +- Fix indentation in modal-confirmation.blade.php +- Improve parsing of commands for sudo in parseCommandsByLineForSudo +- Improve popup component styling and button behavior +- Encode delimiter in SshMultiplexingHelper +- Remove inactivity timer in terminal-server.js +- Improve socket reconnection interval in terminal.js +- Remove unnecessary watch command from soketi service entrypoint +- Update Traefik configuration for improved security and logging +- Improve proxy configuration and code consistency in Server model +- Rename name method to sanitizedName in BaseModel for clarity +- Improve migration command and enhance application model with global scope and status checks +- Unify notification icon +- Remove unused Azure and Authentik service configurations from services.php +- Change email column types in instance_settings migration from string to text +- Change OauthSetting creation to updateOrCreate for better handling of existing records +- Rename `coolify.environment` to `coolify.environmentName` +- Rename parameter in DatabaseBackupJob for clarity +- Improve checkbox component accessibility and styling +- Remove unused tags method from ApplicationDeploymentJob +- Improve deployment status check in isAnyDeploymentInprogress function +- Extend HorizonServiceProvider from HorizonApplicationServiceProvider +- Streamline job status retrieval and clean up repository interface +- Enhance ApplicationDeploymentJob and HorizonServiceProvider for improved job handling +- Remove commented-out unsubscribe route from API +- Update redirect calls to use a consistent navigation method in deployment functions +- AppServiceProvider +- Github.php +- Improve data formatting and UI +- Comment out RootUserSeeder call in ProductionSeeder for clarity +- Streamline ProductionSeeder by removing debug logs and unnecessary checks, while ensuring essential seeding operations remain intact +- Remove debug echo statements from Init command to clean up output and improve readability +- *(workflows)* Replace jq with PHP script for version retrieval in workflows +- *(s3)* Improve S3 bucket endpoint formatting +- *(vite)* Improve environment variable handling in Vite configuration +- *(ui)* Simplify GitHub App registration UI and layout +- Simplify service start and restart workflows +- Use pull flag on docker compose up +- *(ui)* Simplify file storage modal confirmations +- *(notifications)* Improve transactional email settings handling +- *(scheduled-tasks)* Improve scheduled task creation and management +- *(billing)* Enhance Stripe subscription status handling and notifications +- *(ui)* Unhide log toggle in application settings +- *(nginx)* Streamline default Nginx configuration and improve error handling +- *(install)* Clean up install script and enhance Docker installation logic +- *(ScheduledTask)* Clean up code formatting and remove unused import +- *(app)* Remove unused MagicBar component and related code +- *(database)* Streamline SSL configuration handling across database types +- *(application)* Streamline healthcheck parsing from Dockerfile +- *(notifications)* Standardize getRecipients method signatures +- *(configuration)* Centralize configuration management in ConfigurationRepository +- *(docker)* Update image references to use centralized registry URL +- *(env)* Add centralized registry URL to environment configuration +- *(storage)* Simplify file storage iteration in Blade template +- *(models)* Add is_directory attribute to LocalFileVolume model +- *(modal)* Add ignoreWire attribute to modal-confirmation component +- *(invite-link)* Adjust layout for better responsiveness in form +- *(invite-link)* Enhance form layout for improved responsiveness +- *(network)* Enhance docker network creation with ipv6 fallback +- *(network)* Check for existing coolify network before creation +- *(database)* Enhance encryption process for local file volumes +- *(proxy)* Improve port availability checks with multiple methods +- *(database)* Update MongoDB SSL configuration for improved security +- *(database)* Enhance SSL configuration handling for various databases +- *(notifications)* Update Telegram button URL for staging environment +- *(models)* Remove unnecessary cloud check in isEnabled method +- *(database)* Streamline event listeners in Redis General component +- *(database)* Remove redundant database status display in MongoDB view +- *(database)* Update import statements for Auth in database components +- *(database)* Require PEM key file for SSL certificate regeneration +- *(database)* Change MySQL daemon command to MariaDB daemon +- *(nightly)* Update version numbers and enhance upgrade script +- *(versions)* Update version numbers for coolify and nightly +- *(email)* Validate team membership for email recipients +- *(shared)* Simplify deployment status check logic +- *(shared)* Add logging for running deployment jobs +- *(shared)* Enhance job status check to include 'reserved' +- *(email)* Improve error handling by passing context to handleError +- *(email)* Streamline email sending logic and improve configuration handling +- *(email)* Remove unnecessary whitespace in email sending logic +- *(email)* Allow custom email recipients in email sending logic +- *(email)* Enhance sender information formatting in email logic +- *(proxy)* Remove redundant stop call in restart method +- *(file-storage)* Add loadStorageOnServer method for improved error handling +- *(docker)* Parse and sanitize YAML compose file before encoding +- *(file-storage)* Improve layout and structure of input fields +- *(email)* Update label for test email recipient input +- *(database-backup)* Remove existing Docker container before backup upload +- *(database)* Improve decryption and deduplication of local file volumes +- *(database)* Remove debug output from volume update process +- *(dev)* Remove OpenAPI generation functionality +- *(migration)* Enhance local file volumes migration with logging +- *(CheckProxy)* Replace 'which' with 'command -v' for command availability checks +- *(Server)* Use data_get for safer access to settings properties in isFunctional method +- *(Application)* Rename network_aliases to custom_network_aliases across the application for clarity and consistency +- *(ApplicationDeploymentJob)* Streamline environment variable handling by introducing generate_coolify_env_variables method and consolidating logic for pull request and main branch scenarios +- *(ApplicationDeploymentJob, ApplicationDeploymentQueue)* Improve deployment status handling and log entry management with transaction support +- *(SourceManagement)* Sort sources by name and improve UI for changing Git source with better error handling +- *(Email)* Streamline SMTP and resend settings handling in copyFromInstanceSettings method +- *(Email)* Enhance error handling in SMTP and resend methods by passing context to handleError function +- *(DynamicConfigurations)* Improve handling of dynamic configuration content by ensuring fallback to empty string when content is null +- *(ServicesGenerate)* Update command signature from 'services:generate' to 'generate:services' for consistency; update Dockerfile to run service generation during build; update Odoo image version to 18 and add extra addons volume in compose configuration +- *(Dockerfile)* Streamline RUN commands for improved readability and maintainability by adding line continuations +- *(Dockerfile)* Reintroduce service generation command in the build process for consistency and ensure proper asset compilation +- *(commands)* Reorganize OpenAPI and Services generation commands into a new namespace for better structure; remove old command files +- *(Dockerfile)* Remove service generation command from the build process to streamline Dockerfile and improve build efficiency +- *(navbar-delete-team)* Simplify modal confirmation layout and enhance button styling for better user experience +- *(Server)* Remove debug logging from isReachableChanged method to clean up code and improve performance +- *(source)* Conditionally display connected source and change source options based on private key presence +- *(jobs)* Update WithoutOverlapping middleware to use expireAfter for better queue management +- *(jobs)* Comment out unused Caddy label handling in ApplicationDeploymentJob and simplify proxy path logic in Server model +- *(database)* Simplify database type checks in ServiceDatabase and enhance image validation in Docker helper +- *(shared)* Remove unused ray debugging statement from newParser function +- *(applications)* Remove redundant error response in create_env method +- *(api)* Restructure routes to include versioning and maintain existing feedback endpoint +- *(api)* Remove token variable from OpenAPI specifications for clarity +- *(environment-variables)* Remove protected variable checks from delete methods for cleaner logic +- *(http-basic-auth)* Rename 'http_basic_auth_enable' to 'http_basic_auth_enabled' across application files for consistency +- *(docker)* Remove debug statement and enhance hostname handling in Docker run conversion +- *(server)* Simplify proxy path logic and remove unnecessary conditions +- *(Database)* Streamline container shutdown process and reduce timeout duration +- *(core)* Streamline container stopping process and reduce timeout duration; update related methods for consistency +- *(database)* Update DB facade usage for consistency across service files +- *(database)* Enhance application conversion logic and add existence checks for databases and applications +- *(actions)* Standardize method naming for network and configuration deletion across application and service classes +- *(logdrain)* Consolidate log drain stopping logic to reduce redundancy +- *(StandaloneMariadb)* Add type hint for destination method to improve code clarity +- *(DeleteResourceJob)* Streamline resource deletion logic and improve conditional checks for database types +- *(jobs)* Update middleware to prevent job release after expiration for CleanupInstanceStuffsJob, RestartProxyJob, and ServerCheckJob +- *(jobs)* Unify middleware configuration to prevent job release after expiration for DockerCleanupJob and PushServerUpdateJob +- *(service)* Observium +- *(service)* Improve leantime +- *(service)* Imporve limesurvey +- *(service)* Improve CodiMD +- *(service)* Typsense +- *(services)* Improve yamtrack +- *(service)* Improve paymenter +- *(service)* Consolidate configuration change dispatch logic and remove unused navbar component +- *(sidebar)* Simplify server patching link by removing button element +- *(slide-over)* Streamline button element and improve code readability +- *(service)* Enhance modal confirmation component with event dispatching for service stop actions +- *(slide-over)* Enhance class merging for improved component styling +- *(core)* Use property promotion +- *(service)* Improve maybe +- *(applications)* Remove unused docker compose raw decoding +- *(service)* Make TYPESENSE_API_KEY required +- *(ui)* Show toast when server does not work and on stop +- *(service)* Improve superset +- *(service)* Improve Onetimesecret +- *(service)* Improve Seafile +- *(service)* Improve orangehrm +- *(service)* Improve grist +- *(application)* Enhance application stopping logic to support multiple servers +- *(pricing-plans)* Improve label class binding for payment frequency selection +- *(error-handling)* Replace generic Exception with RuntimeException for improved error specificity +- *(error-handling)* Change Exception to RuntimeException for clearer error reporting +- *(service)* Remove informational dispatch during service stop for cleaner execution +- *(server-ui)* Improve layout and messaging in advanced settings and charts views +- *(terminal-access)* Streamline resource retrieval and enhance terminal access messaging in UI +- *(terminal)* Enhance terminal connection management and error handling, including improved reconnection logic and cleanup procedures +- *(application-deployment)* Separate handling of FAILED and CANCELLED_BY_USER statuses for clearer logic and notification +- *(jobs)* Update middleware to include job-specific identifiers for WithoutOverlapping +- *(jobs)* Modify middleware to use job-specific identifier for WithoutOverlapping +- *(environment-variables)* Remove debug logging from bulk submit handling for cleaner code +- *(environment-variables)* Simplify application build pack check in environment variable handling +- *(logs)* Adjust padding in logs view for improved layout consistency +- *(application-deployment)* Streamline post-deployment process by always dispatching container status check +- *(service-management)* Enhance container stopping logic by implementing parallel processing and removing deprecated methods +- *(activity-monitor)* Change activity property visibility and update view references for consistency +- *(activity-monitor)* Enhance layout responsiveness by adjusting class bindings and structure for better display +- *(service-management)* Update stopContainersInParallel method to enforce Server type hint for improved type safety +- *(service-management)* Rearrange docker cleanup logic in StopService to improve readability +- *(database-management)* Simplify docker cleanup logic in StopDatabase to enhance readability +- *(activity-monitor)* Consolidate activity monitoring logic and remove deprecated NewActivityMonitor component +- *(activity-monitor)* Update dispatch method to use activityMonitor instead of deprecated newActivityMonitor +- *(push-server-update)* Enhance application preview handling by incorporating pull request IDs and adding status update protections +- *(docker-compose)* Replace hardcoded Docker Compose configuration with external YAML template for improved database detection testing +- *(test-database-detection)* Rename services for clarity, add new database configurations, and update application service dependencies +- *(database-detection)* Enhance isDatabaseImage function to utilize service configuration for improved detection accuracy +- *(install-scripts)* Update Docker installation process to include manual installation fallback and improve error handling +- *(logs-view)* Update logs display for service containers with improved headings and dynamic key binding +- *(logs)* Enhance container loading logic and improve UI for logs display across various resource types +- *(cloudflare-tunnel)* Enhance layout and structure of Cloudflare Tunnel documentation and confirmation modal +- *(terminal-connection)* Streamline auto-connection logic and improve component readiness checks +- *(logs)* Remove unused methods and debug functionality from Logs.php for cleaner code +- *(remoteProcess)* Update sanitize_utf8_text function to accept nullable string parameter for improved type safety +- *(events)* Remove ProxyStarted event and associated ProxyStartedNotification listener for code cleanup +- *(navbar)* Remove unnecessary parameters from server navbar component for cleaner implementation +- *(proxy)* Remove commented-out listener and method for cleaner code structure +- *(events)* Update ProxyStatusChangedUI constructor to accept nullable teamId for improved flexibility +- *(cloudflare)* Update server retrieval method for improved query efficiency +- *(navbar)* Remove unused PHP use statement for cleaner code +- *(proxy)* Streamline proxy status handling and improve dashboard availability checks +- *(navbar)* Simplify proxy status handling and enhance loading indicators for better user experience +- *(resource-operations)* Filter out build servers from the server list and clean up commented-out code in the resource operations view +- *(execute-container-command)* Simplify connection logic and improve terminal availability checks +- *(navigation)* Remove wire:navigate directive from configuration links for cleaner HTML structure +- *(proxy)* Update StartProxy calls to use named parameter for async option +- *(clone-project)* Enhance server retrieval by including destinations and filtering out build servers +- *(ui)* Terminal +- *(ui)* Remove terminal header from execute-container-command view +- *(ui)* Remove unnecessary padding from deployment, backup, and logs sections +- *(service)* Update Hoarder to their new name karakeep (#5964) +- *(service)* Karakeep naming and formatting +- *(service)* Improve miniflux +- *(core)* Rename API rate limit ENV +- *(ui)* Simplify container selection form in execute-container-command view +- *(email)* Streamline SMTP and resend settings logic for improved clarity +- *(invitation)* Rename methods for consistency and enhance invitation deletion logic +- *(user)* Streamline user deletion process and enhance team management logic +- *(ui)* Separate views for instance settings to separate paths to make it cleaner +- *(ui)* Remove unnecessary step3ButtonText attributes from modal confirmation components for cleaner code +- *(ui)* Enhance project cloning interface with improved table layout for server and resource selection +- *(terminal)* Simplify command construction for SSH execution +- *(settings)* Streamline instance admin checks and initialization of settings in Livewire components +- *(policy)* Optimize team membership checks in S3StoragePolicy +- *(popup)* Improve styling and structure of the small popup component +- *(shared)* Enhance FQDN generation logic for services in newParser function +- *(redis)* Enhance CleanupRedis command with dry-run option and improved key deletion logic +- *(init)* Standardize method naming conventions and improve command structure in Init.php +- *(shared)* Improve error handling in getTopLevelNetworks function to return network name on invalid docker-compose.yml +- *(database)* Improve error handling for unsupported database types in StartDatabaseProxy +- *(previews)* Streamline preview URL generation by utilizing application method +- *(application)* Adjust layout and spacing in general application view for improved UI +- *(postgresql)* Improve layout and spacing in SSL and Proxy configuration sections for better UI consistency +- *(scheduling)* Replace deprecated job checks with ScheduledJobManager and ServerResourceManager for improved scheduling efficiency +- *(previews)* Move preview domain generation logic to ApplicationPreview model for better encapsulation and consistency across webhook handlers +- *(service)* Improve gowa +- *(previews)* Streamline preview domain generation logic in ApplicationDeploymentJob for improved clarity and maintainability +- *(services)* Simplify environment variable updates by using updateOrCreate and add cleanup for removed FQDNs +- *(jobs)* Remove logging for ScheduledJobManager and ServerResourceManager start and completion +- *(services)* Update validation rules to be optional +- *(service)* Improve langfuse +- *(service)* Improve openpanel template +- *(service)* Improve librechat +- *(public-git-repository)* Enhance form structure and add autofocus to repository URL input +- *(public-git-repository)* Remove commented-out code for cleaner template +- *(templates)* Update service template file handling to use dynamic file name from constants +- *(parsers)* Streamline domain handling in applicationParser and improve DNS validation logic +- *(templates)* Replace SERVICE_FQDN variables with SERVICE_URL in compose files for consistency +- *(links)* Replace inline SVGs with reusable external link component for consistency and improved maintainability +- *(previews)* Improve layout and add deployment/application logs links for previews +- *(docker compose)* Remove deprecated newParser function and associated test file to streamline codebase +- *(shared helpers)* Remove unused parseServiceVolumes function to clean up codebase +- *(parsers)* Update volume parsing logic to use beforeLast and afterLast for improved accuracy +- *(validation)* Implement centralized validation patterns across components +- *(jobs)* Rename job classes to indicate deprecation status +- Update check frequency logic for cloud and self-hosted environments; streamline server task scheduling and timezone handling +- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility +- *(policies)* Remove Response type hint from update methods in ApplicationPreviewPolicy and DatabasePolicy for improved flexibility +- *(git)* Improve submodule cloning +- *(parsers)* Remove unnecessary hyphen-to-underscore replacement for service names in serviceParser function +- *(urls)* Replace generateFqdn with generateUrl for consistent URL generation across applications +- *(domains)* Rename check_domain_usage to checkDomainUsage and update references across the application +- *(auth)* Simplify access control logic in CanAccessTerminal and ServerPolicy by allowing all users to perform actions +- *(policy)* Simplify ServiceDatabasePolicy methods to always return true and add manageBackups method + +### 📚 Documentation + +- Contribution guide +- How to add new services +- Update +- Update +- Update Plunk documentation link in compose/plunk.yaml +- Update link to deploy api docs +- Add TECH_STACK.md (#4883) +- *(services)* Reword nitropage url and slogan +- *(readme)* Add Convex to special sponsors section +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- *(CONTRIBUTING)* Add note about Laravel Horizon accessibility +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- *(service)* Add new docs link for zipline (#5912) +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- *(claude)* Clarify that artisan commands should only be run inside the "coolify" container during development +- Add AGENTS.md for project guidance and development instructions +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog +- Update changelog + +### 🎨 Styling + +- Linting +- *(css)* Update padding utility for password input and add newline in app.css +- *(css)* Refine badge utility styles in utilities.css +- *(css)* Enhance badge utility styles in utilities.css ### 🧪 Testing - Native binary target - Dockerfile - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.8.9] - 2022-08-30 - -### 🐛 Bug Fixes - -- Oh god Prisma - -## [3.8.8] - 2022-08-30 - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.8.6] - 2022-08-30 - -### 🐛 Bug Fixes - -- Pr deployment -- CompareVersions -- Include -- Include -- Gitlab apps - -### 💼 Other - -- Fixes -- Route to the correct path when creating destination from db config - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.8.5] - 2022-08-27 - -### 🐛 Bug Fixes - -- Copy all files during install process -- Typo -- Process -- White labeled icon on navbar -- Whitelabeled icon -- Next/nuxt deployment type -- Again - -## [3.8.4] - 2022-08-27 - -### 🐛 Bug Fixes - -- UI thinkgs -- Delete team while it is active -- Team switching -- Queue cleanup -- Decrypt secrets -- Cleanup build cache as well -- Pr deployments + remove public gits - -### 💼 Other - -- Dashbord fixes -- Fixes - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.8.3] - 2022-08-26 - -### 🐛 Bug Fixes - -- Secrets decryption - -## [3.8.2] - 2022-08-26 - -### 🚀 Features - -- *(ui)* Rework home UI and with responsive design - -### 🐛 Bug Fixes - -- Never stop deplyo queue -- Build queue system -- High cpu usage -- Worker -- Better worker system - -### 💼 Other - -- Dashboard fine-tunes -- Fine-tune -- Fixes -- Fix - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.8.1] - 2022-08-24 - -### 🐛 Bug Fixes - -- Ui buttons -- Clear queue on cancelling jobs -- Cancelling jobs -- Dashboard for admins - -## [3.8.0] - 2022-08-23 - -### 🚀 Features - -- Searxng service - -### 🐛 Bug Fixes - -- Port checker -- Cancel build after 5 seconds -- ExposedPort checker -- Batch secret = -- Dashboard for non-root users -- Stream build logs -- Show build log start/end - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.7.0] - 2022-08-19 - -### 🚀 Features - -- Add GlitchTip service - -### 🐛 Bug Fixes - -- Missing commas -- ExposedPort is just optional - -### ⚙️ Miscellaneous Tasks - -- Add .pnpm-store in .gitignore -- Version++ - -## [3.6.0] - 2022-08-18 - -### 🚀 Features - -- Import public repos (wip) -- Public repo deployment -- Force rebuild + env.PORT for port + public repo build - -### 🐛 Bug Fixes - -- Bots without exposed ports - -### 💼 Other - -- Fixes here and there - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.5.2] - 2022-08-17 - -### 🐛 Bug Fixes - -- Restart containers on-failure instead of always -- Show that Ghost values could be changed - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.5.1] - 2022-08-17 - -### 🐛 Bug Fixes - -- Revert docker compose version to 2.6.1 -- Trim secrets - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.5.0] - 2022-08-17 - -### 🚀 Features - -- Deploy bots (no domains) -- Custom dns servers - -### 🐛 Bug Fixes - -- Dns button ui -- Bot deployments -- Bots -- AutoUpdater & cleanupStorage jobs - -### 💼 Other - -- Typing - -## [3.4.0] - 2022-08-16 - -### 🚀 Features - -- Appwrite service -- Heroku deployments - -### 🐛 Bug Fixes - -- Replace docker compose with docker-compose on CSB -- Dashboard ui -- Create coolify-infra, if it does not exists -- Gitpod conf and heroku buildpacks -- Appwrite -- Autoimport + readme -- Services import -- Heroku icon -- Heroku icon - -## [3.3.4] - 2022-08-15 - -### 🐛 Bug Fixes - -- Make it public button -- Loading indicator - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.3.3] - 2022-08-14 - -### 🐛 Bug Fixes - -- Decryption errors -- Postgresql on ARM - -## [3.3.2] - 2022-08-12 - -### 🐛 Bug Fixes - -- Debounce dashboard status requests - -### 💼 Other - -- Fider - -## [3.3.1] - 2022-08-12 - -### 🐛 Bug Fixes - -- Empty buildpack icons - -## [3.2.3] - 2022-08-12 - -### 🚀 Features - -- Databases on ARM -- Mongodb arm support -- New dashboard - -### 🐛 Bug Fixes - -- Cleanup stucked prisma-engines -- Toast -- Secrets -- Cleanup prisma engine if there is more than 1 -- !isARM to isARM -- Enterprise GH link - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.2.2] - 2022-08-11 - -### 🐛 Bug Fixes - -- Coolify-network on verification - -## [3.2.1] - 2022-08-11 - -### 🚀 Features - -- Init heroku buildpacks - -### 🐛 Bug Fixes - -- Follow/cancel buttons -- Only remove coolify managed containers -- White-labeled env -- Schema - -### 💼 Other - -- Fix - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.2.0] - 2022-08-11 - -### 🚀 Features - -- Persistent storage for all services -- Cleanup clickhouse db - -### 🐛 Bug Fixes - -- Rde local ports -- Empty remote destinations could be removed -- Tips -- Lowercase issues fider -- Tooltip colors -- Update clickhouse configuration -- Cleanup command -- Enterprise Github instance endpoint - -### 💼 Other - -- Local ssh port -- Redesign a lot -- Fixes -- Loading indicator for plausible buttons - -## [3.1.4] - 2022-08-01 - -### 🚀 Features - -- Moodle init -- Remote docker engine init -- Working on remote docker engine -- Rde -- Remote docker engine -- Ipv4 and ipv6 -- Contributors -- Add arch to database -- Stop preview deployment - -### 🐛 Bug Fixes - -- Settings from api -- Selectable destinations -- Gitpod hardcodes -- Typo -- Typo -- Expose port checker -- States and exposed ports -- CleanupStorage -- Remote traefik webhook -- Remote engine ip address -- RemoteipAddress -- Explanation for remote engine url -- Tcp proxy -- Lol -- Webhook -- Dns check for rde -- Gitpod -- Revert last commit -- Dns check -- Dns checker -- Webhook -- Df and more debug -- Webhooks -- Load previews async -- Destination icon -- Pr webhook -- Cache image -- No ssh key found -- Prisma migration + update of docker and stuffs -- Ui -- Ui -- Only 1 ssh-agent is needed -- Reuse ssh connection -- Ssh tunnel -- Dns checking -- Fider BASE_URL set correctly - -### 💼 Other - -- Error message https://github.com/coollabsio/coolify/issues/502 -- Changes -- Settings -- For removing app - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.1.3] - 2022-07-18 - -### 🚀 Features - -- Init moodle and separate stuffs to shared package - -### 🐛 Bug Fixes - -- More types for API -- More types -- Do not rebuild in case image exists and sha not changed -- Gitpod urls -- Remove new service start process -- Remove shared dir, deployment does not work -- Gitlab custom url -- Location url for services and apps - -## [3.1.2] - 2022-07-14 - -### 🐛 Bug Fixes - -- Admin password reset should not timeout -- Message for double branches -- Turn off autodeploy if double branch is configured - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.1.1] - 2022-07-13 - -### 🚀 Features - -- Gitpod integration - -### 🐛 Bug Fixes - -- Cleanup less often and can do it manually - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ - -## [3.1.0] - 2022-07-12 - -### 🚀 Features - -- Ability to change deployment type for nextjs -- Ability to change deployment type for nuxtjs -- Gitpod ready code(almost) -- Add Docker buildpack exposed port setting -- Custom port for git instances - -### 🐛 Bug Fixes - -- GitLab pagination load data -- Service domain checker -- Wp missing ftp solution -- Ftp WP issues -- Ftp?! -- Gitpod updates -- Gitpod -- Gitpod -- Wordpress FTP permission issues -- GitLab search fields -- GitHub App button -- GitLab loop on misconfigured source -- Gitpod - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [3.0.3] - 2022-07-06 - -### 🐛 Bug Fixes - -- Domain check -- Domain check -- TrustProxy for Fastify -- Hostname issue - -## [3.0.2] - 2022-07-06 - -### 🐛 Bug Fixes - -- New destination can be created -- Include post -- New destinations - -## [3.0.1] - 2022-07-06 - -### 🐛 Bug Fixes - -- Seeding -- Forgot that the version bump changed 😅 - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.11] - 2022-06-20 - -### 🐛 Bug Fixes - -- Be able to change database + service versions -- Lock file - -## [2.9.10] - 2022-06-17 - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.9] - 2022-06-10 - -### 🐛 Bug Fixes - -- Host and reload for uvicorn -- Remove package-lock - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.8] - 2022-06-10 - -### 🐛 Bug Fixes - -- Persistent nocodb -- Nocodb persistency - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.7] - 2022-06-09 - -### 🐛 Bug Fixes - -- Plausible custom script -- Plausible script and middlewares -- Remove console log -- Remove comments -- Traefik middleware - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.6] - 2022-06-02 - -### 🐛 Bug Fixes - -- Fider changed an env variable name -- Pnpm command - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.5] - 2022-06-02 - -### 🐛 Bug Fixes - -- Proxy stop missing argument - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.4] - 2022-06-01 - -### 🐛 Bug Fixes - -- Demo version forms -- Typo -- Revert gh and gl cloning - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.3] - 2022-05-31 - -### 🐛 Bug Fixes - -- Recurisve clone instead of submodule -- Versions -- Only reconfigure coolify proxy if its missconfigured - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.2] - 2022-05-31 - -### 🐛 Bug Fixes - -- TrustProxy -- Force restart proxy -- Only restart coolify proxy in case of version prior to 2.9.2 -- Force restart proxy on seeding -- Add GIT ENV variable for submodules - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.1] - 2022-05-31 - -### 🐛 Bug Fixes - -- GitHub fixes - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.9.0] - 2022-05-31 - -### 🚀 Features - -- PageLoader -- Database + service usage - -### 🐛 Bug Fixes - -- Service checks -- Remove console.log -- Traefik -- Remove debug things -- WIP Traefik -- Proxy for http -- PR deployments view -- Minio urls + domain checks -- Remove gh token on git source changes -- Do not fetch app state in case of missconfiguration -- Demo instance save domain instantly -- Instant save on demo instance -- New source canceled view -- Lint errors in database services -- Otherfqdns -- Host key verification -- Ftp connection - -### 💼 Other - -- Appwrite -- Testing WS -- Traefik?! -- Traefik -- Traefik -- Traefik migration -- Traefik -- Traefik -- Traefik -- Notifications and application usage -- *(fix)* Traefik -- Css - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.8.2] - 2022-05-16 - -### 🐛 Bug Fixes - -- Gastby buildpack - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.8.1] - 2022-05-10 - -### 🐛 Bug Fixes - -- WP custom db -- UI - -## [2.6.1] - 2022-05-03 - -### 🚀 Features - -- Basic server usage on dashboard -- Show usage trends -- Usage on dashboard -- Custom script path for Plausible -- WP could have custom db -- Python image selection - -### 🐛 Bug Fixes - -- ExposedPorts -- Logos for dbs -- Do not run SSL renew in development -- Check domain for coolify before saving -- Remove debug info -- Cancel jobs -- Cancel old builds in database -- Better DNS check to prevent errors -- Check DNS in prod only -- DNS check -- Disable sentry for now -- Cancel -- Sentry -- No image for Docker buildpack -- Default packagemanager -- Server usage only shown for root team -- Expose ports for services -- UI -- Navbar UI -- UI -- UI -- Remove RC python -- UI -- UI -- UI -- Default Python package - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Version++ -- Version++ - -## [2.6.0] - 2022-05-02 - -### 🚀 Features - -- Hasura as a service -- Gzip compression -- Laravel buildpack is working! -- Laravel -- Fider service -- Database and services logs -- DNS check settings for SSL generation -- Cancel builds! - -### 🐛 Bug Fixes - -- Unami svg size -- Team switching moved to IAM menu -- Always use IP address for webhooks -- Remove unnecessary test endpoint -- UI -- Migration -- Fider envs -- Checking low disk space -- Build image -- Update autoupdate env variable -- Renew certificates -- Webhook build images -- Missing node versions - -### 💼 Other - -- Laravel - -## [2.4.11] - 2022-04-20 - -### 🚀 Features - -- Deno DB migration -- Show exited containers on UI & better UX -- Query container state periodically -- Install svelte-18n and init setup -- Umami service -- Coolify auto-updater -- Autoupdater -- Select base image for buildpacks - -### 🐛 Bug Fixes - -- Deno configurations -- Text on deno buildpack -- Correct branch shown in build logs -- Vscode permission fix -- I18n -- Locales -- Application logs is not reversed and queried better -- Do not activate i18n for now -- GitHub token cleanup on team switch -- No logs found -- Code cleanups -- Reactivate posgtres password -- Contribution guide -- Simplify list services -- Contribution -- Contribution guide -- Contribution guide -- Packagemanager finder - -### 💼 Other - -- Umami service -- Base image selector - -### 📚 Documentation - -- How to add new services -- Update -- Update - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Version++ - -## [2.4.10] - 2022-04-17 - -### 🚀 Features - -- Add persistent storage for services -- Multiply dockerfile locations for docker buildpack -- Testing fluentd logging driver -- Fluentbit investigation -- Initial deno support - -### 🐛 Bug Fixes - -- Switch from bitnami/redis to normal redis -- Use redis-alpine -- Wordpress extra config -- Stop sFTP connection on wp stop -- Change user's id in sftp wp instance -- Use arm based certbot on arm -- Buildlog line number is not string -- Application logs paginated -- Switch to stream on applications logs -- Scroll to top for logs -- Pull new images for services all the time it's started. -- White-labeled custom logo -- Application logs - -### 💼 Other - -- Show extraconfig if wp is running - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ - -## [2.4.9] - 2022-04-14 - -### 🐛 Bug Fixes - -- Postgres root pw is pw field -- Teams view -- Improved tcp proxy monitoring for databases/ftp -- Add HTTP proxy checks -- Loading of new destinations -- Better performance for cleanup images -- Remove proxy container in case of dependent container is down -- Restart local docker coolify proxy in case of something happens to it -- Id of service container - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.8] - 2022-04-13 - -### 🐛 Bug Fixes - -- Register should happen if coolify proxy cannot be started -- GitLab typo -- Remove system wide pw reset - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.7] - 2022-04-13 - -### 🐛 Bug Fixes - -- Destinations to HAProxy - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.6] - 2022-04-13 - -### 🐛 Bug Fixes - -- Cleanup images older than a day -- Meilisearch service -- Load all branches, not just the first 30 -- ProjectID for Github -- DNS check before creating SSL cert -- Try catch me -- Restart policy for resources -- No permission on first registration -- Reverting postgres password for now - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.5] - 2022-04-12 - -### 🐛 Bug Fixes - -- Types -- Invitations -- Timeout values - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.4] - 2022-04-12 - -### 🐛 Bug Fixes - -- Haproxy build stuffs -- Proxy - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.3] - 2022-04-12 - -### 🐛 Bug Fixes - -- Remove unnecessary save button haha -- Update dockerfile - -### ⚙️ Miscellaneous Tasks - -- Update packages -- Version++ -- Update build scripts -- Update build packages - -## [2.4.2] - 2022-04-09 - -### 🐛 Bug Fixes - -- Missing install repositories GitHub -- Return own and other sources better -- Show config missing on sources - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.1] - 2022-04-09 - -### 🐛 Bug Fixes - -- Enable https for Ghost -- Postgres root passwor shown and set -- Able to change postgres user password from ui -- DB Connecting string generator - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.4.0] - 2022-04-08 - -### 🚀 Features - -- Wordpress on-demand SFTP -- Finalize on-demand sftp for wp -- PHP Composer support -- Working on-demand sftp to wp data -- Admin team sees everything -- Able to change service version/tag -- Basic white labeled version -- Able to modify database passwords - -### 🐛 Bug Fixes - -- Add openssl to image -- Permission issues -- On-demand sFTP for wp -- Fix for fix haha -- Do not pull latest image -- Updated db versions -- Only show proxy for admin team -- Team view for root team -- Do not trigger >1 webhooks on GitLab -- Possible fix for spikes in CPU usage -- Last commit -- Www or not-www, that's the question -- Fix for the fix that fixes the fix -- Ton of updates for users/teams -- Small typo -- Unique storage paths -- Self-hosted GitLab URL -- No line during buildLog -- Html/apiUrls cannot end with / -- Typo -- Missing buildpack - -### 💼 Other - -- Fix -- Better layout for root team -- Fix -- Fixes -- Fix -- Fix -- Fix -- Fix -- Fix -- Fix -- Fix -- Insane amount -- Fix -- Fixes -- Fixes -- Fix -- Fixes -- Fixes - -### 📚 Documentation - -- Contribution guide - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.3.3] - 2022-04-05 - -### 🐛 Bug Fixes - -- Add git lfs while deploying -- Try to update build status several times -- Update stucked builds -- Update stucked builds on startup -- Revert seed -- Lame fixing -- Remove asyncUntil - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.3.2] - 2022-04-04 - -### 🐛 Bug Fixes - -- *(php)* If .htaccess file found use apache -- Add default webhook domain for n8n - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.3.1] - 2022-04-04 - -### 🐛 Bug Fixes - -- Secrets build/runtime coudl be changed after save -- Default configuration - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.3.0] - 2022-04-04 - -### 🚀 Features - -- Initial python support -- Add loading on register button -- *(dev)* Allow windows users to use pnpm dev -- MeiliSearch service -- Add abilitry to paste env files - -### 🐛 Bug Fixes - -- Ignore coolify proxy error for now -- Python no wsgi -- If user not found -- Rename envs to secrets -- Infinite loop on www domains -- No need to paste clear text env for previews -- Build log fix attempt #1 -- Small UI fix on logs -- Lets await! -- Async progress -- Remove console.log -- Build log -- UI -- Gitlab & Github urls - -### 💼 Other - -- Improvements - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Lock file + fix packages - -## [2.2.7] - 2022-04-01 - -### 🐛 Bug Fixes - -- Haproxy errors -- Build variables -- Use NodeJS for sveltekit for now - -## [2.2.6] - 2022-03-31 - -### 🐛 Bug Fixes - -- Add PROTO headers - -## [2.2.5] - 2022-03-31 - -### 🐛 Bug Fixes - -- Registration enabled/disabled - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.2.4] - 2022-03-31 - -### 🐛 Bug Fixes - -- Gitlab repo url -- No need to dashify anymore - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.2.3] - 2022-03-31 - -### 🐛 Bug Fixes - -- List ghost services -- Reload window on settings saved -- Persistent storage on webhooks -- Add license -- Space in repo names - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ -- Version++ -- Fixed typo on New Git Source view - -## [2.2.0] - 2022-03-27 - -### 🚀 Features - -- Add n8n.io service -- Add update kuma service -- Ghost service - -### 🐛 Bug Fixes - -- Ghost logo size -- Ghost icon, remove console.log - -### 💼 Other - -- Colors on svelte-select - -### ⚙️ Miscellaneous Tasks - -- Version ++ - -## [2.1.1] - 2022-03-25 - -### 🐛 Bug Fixes - -- Cleanup only 2 hours+ old images - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.1.0] - 2022-03-23 - -### 🚀 Features - -- Use compose instead of normal docker cmd -- Be able to redeploy PRs - -### 🐛 Bug Fixes - -- Skip ssl cert in case of error -- Volumes - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.31] - 2022-03-20 - -### 🚀 Features - -- Add PHP modules - -### 🐛 Bug Fixes - -- Cleanup old builds -- Only cleanup same app -- Add nginx + htaccess files - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.30] - 2022-03-19 - -### 🐛 Bug Fixes - -- No cookie found -- Missing session data -- No error if GitSource is missing -- No webhook secret found? -- Basedir for dockerfiles -- Better queue system + more support on monorepos -- Remove build logs in case of app removed - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.29] - 2022-03-11 - -### 🚀 Features - -- Webhooks inititate all applications with the correct branch -- Check ssl for new apps/services first -- Autodeploy pause -- Install pnpm into docker image if pnpm lock file is used - -### 🐛 Bug Fixes - -- Personal Gitlab repos -- Autodeploy true by default for GH repos - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.28] - 2022-03-04 - -### 🚀 Features - -- Service secrets - -### 🐛 Bug Fixes - -- Do not error if proxy is not running - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.27] - 2022-03-02 - -### 🚀 Features - -- Send version with update request - -### 🐛 Bug Fixes - -- Check when a container is running -- Reload haproxy if new cert is added -- Cleanup coolify images -- Application state in UI - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.26] - 2022-03-02 - -### 🐛 Bug Fixes - -- Update process - -## [2.0.25] - 2022-03-02 - -### 🚀 Features - -- Languagetool service - -### 🐛 Bug Fixes - -- Reload proxy on ssl cert -- Volume name - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.24] - 2022-03-02 - -### 🐛 Bug Fixes - -- Better proxy check -- Ssl + sslrenew -- Null proxyhash on restart -- Reconfigure proxy on restart -- Update process - -## [2.0.23] - 2022-02-28 - -### 🐛 Bug Fixes - -- Be sure .env exists -- Missing fqdn for services -- Default npm command -- Add coolify-image label for build images -- Cleanup old images, > 3 days - -### 💼 Other - -- Colorful states -- Application start - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.22] - 2022-02-27 - -### 🐛 Bug Fixes - -- Coolify image pulls -- Remove wrong/stuck proxy configurations -- Always use a buildpack -- Add icons for eleventy + astro -- Fix proxy every 10 secs -- Do not remove coolify proxy -- Update version - -### 💼 Other - -- Remote docker engine - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.21] - 2022-02-24 - -### 🚀 Features - -- Random subdomain for demo -- Random domain for services -- Astro buildpack -- 11ty buildpack -- Registration page - -### 🐛 Bug Fixes - -- Http for demo, oops -- Docker scanner -- Improvement on image pulls - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.20] - 2022-02-23 - -### 🐛 Bug Fixes - -- Revert default network - -### 💼 Other - -- Dns check - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.19] - 2022-02-23 - -### 🐛 Bug Fixes - -- Random network name for demo -- Settings fqdn grr - -## [2.0.18] - 2022-02-22 - -### 🚀 Features - -- Ports range - -### 🐛 Bug Fixes - -- Email is lowercased in login -- Lowercase email everywhere -- Use normal docker-compose in dev - -### 💼 Other - -- Make copy/password visible - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.17] - 2022-02-21 - -### 🐛 Bug Fixes - -- Move tokens from session to cookie/store - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.14] - 2022-02-18 - -### 🚀 Features - -- Basic password reset form -- Scan for lock files and set right commands -- Public port range (WIP) - -### 🐛 Bug Fixes - -- SSL app off -- Local docker host -- Typo -- Lets encrypt -- Remove SSL with stop -- SSL off for services -- Grr -- Running state css -- Minor fixes -- Remove force SSL when doing let's encrypt request -- GhToken in session now -- Random port for certbot -- Follow icon -- Plausible volume fixed -- Database connection strings -- Gitlab webhooks fixed -- If DNS not found, do not redirect -- Github token - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version ++ - -## [2.0.13] - 2022-02-17 - -### 🐛 Bug Fixes - -- Login issues - -## [2.0.11] - 2022-02-15 - -### 🚀 Features - -- Follow logs -- Generate www & non-www SSL certs - -### 🐛 Bug Fixes - -- Window error in SSR -- GitHub sync PR's -- Load more button -- Small fixes -- Typo -- Error with follow logs -- IsDomainConfigured -- TransactionIds -- Coolify image cleanup -- Cleanup every 10 mins -- Cleanup images -- Add no user redis to uri -- Secure cookie disabled by default -- Buggy svelte-kit-cookie-session - -### 💼 Other - -- Only allow cleanup in production - -### ⚙️ Miscellaneous Tasks - -- Version++ -- Version++ - -## [2.0.10] - 2022-02-15 - -### 🐛 Bug Fixes - -- Typo -- Error handling -- Stopping service without proxy -- Coolify proxy start - -### ⚙️ Miscellaneous Tasks - -- Version++ - -## [2.0.8] - 2022-02-14 - -### 🐛 Bug Fixes - -- Validate secrets -- Truncate git clone errors -- Branch used does not throw error - -## [2.0.7] - 2022-02-13 - -### 🚀 Features - -- Www <-> non-www redirection for apps -- Www <-> non-www redirection - -### 🐛 Bug Fixes - -- Package.json -- Build secrets should be visible in runtime -- New secret should have default values - -## [2.0.5] - 2022-02-11 - -### 🚀 Features - -- VaultWarden service - -### 🐛 Bug Fixes - -- PreventDefault on a button, thats all -- Haproxy check should not throw error -- Delete all build files -- Cleanup images -- More error handling in proxy configuration + cleanups -- Local static assets -- Check sentry -- Typo - -### ⚙️ Miscellaneous Tasks - -- Version -- Version - -## [2.0.4] - 2022-02-11 - -### 🚀 Features - -- Use tags in update -- New update process (#115) - -### 🐛 Bug Fixes - -- Docker Engine bug related to live-restore and IPs -- Version - -## [2.0.3] - 2022-02-10 - -### 🐛 Bug Fixes - -- Capture non-error as error -- Only delete id.rsa in case of it exists -- Status is not available yet +- Remove prisma +- More tests +- Setup database for upcoming tests ### ⚙️ Miscellaneous Tasks - Version bump +- Version +- Version +- Version++ +- Version++ +- Version++ +- Version++ +- Version ++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version ++ +- Version++ +- Version++ +- Version++ +- Fixed typo on New Git Source view +- Version++ +- Version++ +- Version++ +- Version++ +- Lock file + fix packages +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Update packages +- Version++ +- Update build scripts +- Update build packages +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Add .pnpm-store in .gitignore +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Minor changes +- Minor changes +- Minor changes +- Whoops +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Update staging release +- Version++ +- Version++ +- Add jda icon for lavalink service +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Version++ +- Update version to 4.0.0-beta.275 +- Update DNS server validation helper text +- Dark mode should be the default +- Improve menu item styling and spacing in service configuration and index views +- Improve menu item styling and spacing in service configuration and index views +- Improve menu item styling and spacing in project index and show views +- Remove docker compose versions +- Add Listmonk service template and logo +- Refactor GetContainersStatus.php for improved readability and maintainability +- Refactor ApplicationDeploymentJob.php for improved readability and maintainability +- Add metrics and logs directories to installation script +- Update sentinel version to 0.0.2 in versions.json +- Update permissions on metrics and logs directories +- Comment out server sentinel check in ServerStatusJob +- Update version numbers to 4.0.0-beta.278 +- Update hover behavior and cursor style in scheduled task executions view +- Refactor scheduled task view to improve code readability and maintainability +- Skip scheduled tasks if application or service is not running +- Remove debug logging statements in Kernel.php +- Handle invalid cron strings in Kernel.php +- Refactor Service.php to handle missing admin user in extraFields() method +- Update twenty CRM template with environment variables and dependencies +- Refactor applications.php to remove unused imports and improve code readability +- Refactor deployment index.blade.php for improved readability and rollback handling +- Refactor GitHub app selection UI in project creation form +- Update ServerLimitCheckJob.php to handle missing serverLimit value +- Remove unnecessary code for saving commit message +- Update DOCKER_VERSION to 26.0 in install.sh script +- Update Docker and Docker Compose versions in Dockerfiles +- Update version numbers to 4.0.0-beta.279 +- Limit commit message length to 50 characters in ApplicationDeploymentJob +- Update version to 4.0.0-beta.283 +- Change pre and post deployment command length in applications table +- Refactor container name logic in GetContainersStatus.php and ForcePasswordReset.php +- Remove unnecessary content from Docker Compose file +- Update Sentry release version to 4.0.0-beta.287 +- Add Thompson Edolo as a sponsor +- Add null checks for team in Stripe webhook +- Update Sentry release version to 4.0.0-beta.288 +- Update for version 289 +- Fix formatting issue in deployment index.blade.php file +- Remove unnecessary wire:navigate attribute in breadcrumbs.blade.php +- Rename docker dirs +- Update laravel/socialite to version v5.14.0 and livewire/livewire to version 3.4.9 +- Update modal styles for better user experience +- Update deployment index.blade.php script for better performance +- Update version numbers to 4.0.0-beta.290 +- Update version numbers to 4.0.0-beta.291 +- Update version numbers to 4.0.0-beta.292 +- Update version numbers to 4.0.0-beta.293 +- Add upgrade guide link to upgrade.blade.php +- Improve upgrade.blade.php with clearer instructions and formatting +- Update version numbers to 4.0.0-beta.294 +- Add Lightspeed.run as a sponsor +- Update Dockerfile to install vim +- Update Dockerfile with latest versions of Docker, Docker Compose, Docker Buildx, Pack, and Nixpacks +- Update version numbers to 4.0.0-beta.295 +- Update supported OS list with almalinux +- Update install.sh to support PopOS +- Update install.sh script to version 1.3.2 and handle Linux Mint as Ubuntu +- Update page title in resource index view +- Update logo file path in logto.yaml +- Update logo file path in logto.yaml +- Remove commented out code for docker container removal +- Add isAnyDeploymentInprogress function to check if any deployments are in progress +- Add ApplicationDeploymentJob and pint.json +- Update version numbers to 4.0.0-beta.298 +- Switch to database sessions from redis +- Update dependencies and remove unused code +- Update tailwindcss and vue versions in package.json +- Update service template URL in constants.php +- Update sentinel version to 0.0.8 +- Update chart styling and loading text +- Update sentinel version to 0.0.9 +- Update Spanish translation for failed authentication messages +- Add portuguese traslation +- Add Turkish translations +- Add Vietnamese translate +- Add Treive logo to donations section +- Update README.md with latest release version badge +- Update latest release version badge in README.md +- Update version to 4.0.0-beta.299 +- Move server delete component to the bottom of the page +- Update version to 4.0.0-beta.301 +- Update version to 4.0.0-beta.302 +- Update version to 4.0.0-beta.303 +- Update version to 4.0.0-beta.305 +- Update version to 4.0.0-beta.306 +- Add log1x/laravel-webfonts package +- Update version to 4.0.0-beta.307 +- Refactor ServerStatusJob constructor formatting +- Update Monaco Editor for Docker Compose and Proxy Configuration +- More details +- Refactor shared.php helper functions +- Update Plausible docker compose template to Plausible 2.1.0 +- Update Plausible docker compose template to Plausible 2.1.0 +- Update livewire/livewire dependency to version 3.4.9 +- Refactor checkIfDomainIsAlreadyUsed function +- Update storage.blade.php view for livewire project service +- Update version to 4.0.0-beta.310 +- Update composer dependencies +- Add new logo for Latitude +- Bump version to 4.0.0-beta.311 +- Update version to 4.0.0-beta.315 +- Update version to 4.0.0-beta.316 +- Update bug report template +- Update repository form with simplified URL input field +- Update width of container in general.blade.php +- Update checkbox labels in general.blade.php +- Update general page of apps +- Handle JSON parsing errors in format_docker_command_output_to_json +- Update Traefik image version to v2.11 +- Update version to 4.0.0-beta.317 +- Update version to 4.0.0-beta.318 +- Update helper message with link to documentation +- Disable health check by default +- Remove commented out code for sending internal notification +- Update APP_BASE_URL to use SERVICE_FQDN_PLANE +- Update resource-limits.blade.php with improved input field helpers +- Update version numbers to 4.0.0-beta.319 +- Remove commented out code for docker image pruning +- Collect/create/update volumes in parseDockerComposeFile function +- Update version to 4.0.0-beta.320 +- Add pull_request image builds to GH actions +- Add comment explaining the purpose of disconnecting the network in cleanup_unused_network_from_coolify_proxy() +- Update formbricks template +- Update registration view to display a notice for first user that it will be an admin +- Update server form to use password input for IP Address/Domain field +- Update navbar to include service status check +- Update navbar and configuration to improve service status check functionality +- Update workflows to include PR build and merge manifest steps +- Update UpdateCoolifyJob timeout to 10 minutes +- Update UpdateCoolifyJob to dispatch CheckForUpdatesJob synchronously +- Update version to 4.0.0-beta.321 +- Update version to 4.0.0-beta.322 +- Update version to 4.0.0-beta.323 +- Update version to 4.0.0-beta.324 +- New compose parser with tests +- Update version to 1.3.4 in install.sh and 1.0.6 in upgrade.sh +- Update memory limit to 64MB in horizon configuration +- Update php packages +- Update axios npm dependency to version 1.7.5 +- Update Coolify version to 4.0.0-beta.324 and fix file paths in upgrade script +- Update Coolify version to 4.0.0-beta.324 +- Update Coolify version to 4.0.0-beta.325 +- Update Coolify version to 4.0.0-beta.326 +- Add cd command to change directory before removing .env file +- Update Coolify version to 4.0.0-beta.327 +- Update Coolify version to 4.0.0-beta.328 +- Update sponsor links in README.md +- Update version.json to versions.json in GitHub workflow +- Cleanup stucked resources and scheduled backups +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use versions.json instead of version.json +- Update GitHub workflow to use jq container for version extraction +- Update GitHub workflow to use jq container for version extraction +- Update UI for displaying no executions found in scheduled task list +- Update UI for displaying deployment status in deployment list +- Update UI for displaying deployment status in deployment list +- Ignore unnecessary files in production build workflow +- Update server form layout and settings +- Update Dockerfile with latest versions of PACK and NIXPACKS +- Update coolify-helper.yml to get version from versions.json +- Disable Ray by default +- Enable Ray by default and update Dockerfile with latest versions of PACK and NIXPACKS +- Update Ray configuration and Dockerfile +- Add middleware for updating environment variables by UUID in `api.php` routes +- Expose port 3000 in browserless.yaml template +- Update Ray configuration and Dockerfile +- Update coolify version to 4.0.0-beta.331 +- Update versions.json and sentry.php to 4.0.0-beta.332 +- Update version to 4.0.0-beta.332 +- Update DATABASE_URL in plunk.yaml to use plunk database +- Add coolify.managed=true label to Docker image builds +- Update docker image pruning command to exclude managed images +- Update docker cleanup schedule to run daily at midnight +- Update versions.json to version 1.0.1 +- Update coolify-helper.yml to include "next" branch in push trigger +- Set timeout for ServerCheckJob to 60 seconds +- Update appwrite.yaml to include OpenSSL key variable assignment +- Update version numbers to 4.0.0-beta.333 +- Copy .env file to .env-{DATE} if it exists +- Update .env file with new values +- Update server check job middleware to use server ID instead of UUID +- Add reminder to backup .env file before running install script again +- Copy .env file to backup location during installation script +- Add reminder to backup .env file during installation script +- Update permissions in pr-build.yml and version numbers +- Add minio/mc command to Dockerfile +- Remove itsgoingd/clockwork from require-dev in composer.json +- Update 'key' value of gitlab in Service.php to use environment variable +- Update release version to 4.0.0-beta.335 +- Update constants.ssh.mux_enabled in remoteProcess.php +- Update listeners and proxy settings in server form and new server components +- Remove unnecessary null check for proxy_type in generate_default_proxy_configuration +- Remove unnecessary SSH command execution time logging +- Update release version to 4.0.0-beta.336 +- Update coolify environment variable assignment with double quotes +- Update shared.php to fix issues with source and network variables +- Update terminal styling for better readability +- Update button text for container connection form +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Remove unused entrypoint script and update volume mapping +- Update .env file and docker-compose configuration +- Update APP_NAME environment variable in docker-compose.prod.yml +- Update WebSocket URL in terminal.blade.php +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Update Dockerfile and workflow for Coolify Realtime (v4) +- Rename Command Center to Terminal in code and views +- Update branch restriction for push event in coolify-helper.yml +- Update terminal button text and layout in application heading view +- Refactor terminal component and select form layout +- Update coolify nightly version to 4.0.0-beta.335 +- Update helper version to 1.0.1 +- Fix syntax error in versions.json +- Update version numbers to 4.0.0-beta.337 +- Update Coolify installer and scripts to include a function for fetching programming jokes +- Update docker network connection command in ApplicationDeploymentJob.php +- Add validation to prevent selecting 'default' server or container in RunCommand.php +- Update versions.json to reflect latest version of realtime container +- Update soketi image to version 1.0.1 +- Nightly - Update soketi image to version 1.0.1 and versions.json to reflect latest version of realtime container +- Update version numbers to 4.0.0-beta.339 +- Update version numbers to 4.0.0-beta.340 +- Update version numbers to 4.0.0-beta.341 +- Update version numbers to 4.0.0-beta.342 +- Update remove-labels-and-assignees-on-close.yml +- Add SSH key for localhost in ProductionSeeder +- Update SSH key generation in install.sh script +- Update ProductionSeeder to call OauthSettingSeeder and PopulateSshKeysDirectorySeeder +- Update install.sh to support Asahi Linux +- Update install.sh version to 1.6 +- Remove unused middleware and uniqueId method in DockerCleanupJob +- Refactor DockerCleanupJob to remove unused middleware and uniqueId method +- Remove unused migration file for populating SSH keys and clearing mux directory +- Add modified files to the commit +- Refactor pre-commit hook to improve performance and readability +- Update CONTRIBUTING.md with troubleshooting note about database migrations +- Refactor pre-commit hook to improve performance and readability +- Update cleanup command to use Redis instead of queue +- Update Docker commands to start proxy +- Update version numbers to 4.0.0-beta.343 +- Update version numbers to 4.0.0-beta.344 +- Update version numbers to 4.0.0-beta.345 +- Update version numbers to 4.0.0-beta.346 +- Add autocomplete attribute to input fields +- Refactor API Tokens component to use isApiEnabled flag +- Update versions.json file +- Remove unused .env.development.example file +- Update API Tokens view to include link to Settings menu +- Update web.php to cast server port as integer +- Update backup deletion labels to use language files +- Update database startup heading title +- Update database startup heading title +- Custom vite envs +- Update version numbers to 4.0.0-beta.348 +- Refactor code to improve SSH key handling and storage +- Update Mailpit logo to use SVG format +- Fix docs link in running state +- Update Coolify Realtime workflow to only trigger on the main branch +- Refactor instanceSettings() function to improve code readability +- Update Coolify Realtime image to version 1.0.2 +- Remove unnecessary code in DatabaseBackupJob.php +- Add "Not Usable" indicator for storage items +- Refactor instanceSettings() function and improve code readability +- Update version numbers to 4.0.0-beta.349 and 4.0.0-beta.350 +- Update version numbers to 4.0.0-beta.350 in configuration files +- Update command signature and description for cleanup application deployment queue +- Add missing import for Attribute class in ApplicationDeploymentQueue model +- Update modal input in server form to prevent closing on outside click +- Remove unnecessary command from SshMultiplexingHelper +- Remove commented out code for uploading to S3 in DatabaseBackupJob +- Update soketi service image to version 1.0.3 +- Update version to 4.0.0-beta.352 +- Refactor DatabaseBackupJob to handle missing team +- Update version to 4.0.0-beta.353 +- Update service application view +- Update version to 4.0.0-beta.354 +- Remove debug statement in Service model +- Remove commented code in Server model +- Fix application deployment queue filter logic +- Refactor modal-confirmation component +- Update it-tools service template and port configuration +- Update homarr service template and remove unnecessary code +- Update homarr service template and remove unnecessary code +- Update version to 4.0.0-beta.355 +- Update version to 4.0.0-beta.356 +- Remove commented code for shared variable type validation +- Update MariaDB image to version 11 and fix service environment variable orders +- Update anythingllm.yaml volumes configuration +- Update proxy configuration paths for Caddy and Nginx in dev +- Update password form submission in modal-confirmation component +- Update project query to order by name in uppercase +- Update project query to order by name in lowercase +- Update select.blade.php with improved search functionality +- Add Nitropage service template and logo +- Bump coolify-helper version to 1.0.2 +- Refactor loadServices2 method and remove unused code +- Update version to 4.0.0-beta.357 +- Update service names and volumes in windmill.yaml +- Update version to 4.0.0-beta.358 +- Ignore .ignition.json files in Docker and Git +- Add mattermost logo as svg +- Add mattermost svg to compose +- Update version to 4.0.0-beta.357 +- Fix form submission and keydown event handling in modal-confirmation.blade.php +- Update version numbers to 4.0.0-beta.359 in configuration files +- Disable adding default environment variables in shared.php +- Update laravel/horizon dependency to version 5.29.1 +- Update service extra fields to use dynamic keys +- Update livewire/livewire dependency to version 3.4.9 +- Add transmission template desc +- Update transmission docs link +- Update version numbers to 4.0.0-beta.360 in configuration files +- Update AWS environment variable names in unsend.yaml +- Update AWS environment variable names in unsend.yaml +- Update livewire/livewire dependency to version 3.4.9 +- Update version to 4.0.0-beta.361 +- Update Docker build and push actions to v6 +- Update Docker build and push actions to v6 +- Update Docker build and push actions to v6 +- Sync coolify-helper to dockerhub as well +- Push realtime to dockerhub +- Sync coolify-realtime to dockerhub +- Rename workflows +- Rename development to staging build +- Sync coolify-testing-host to dockerhbu +- Sync coolify prod image to dockerhub as well +- Update Docker version to 26.0 +- Update project resource index page +- Update project service configuration view +- Edit www helper +- Update dep +- Regenerate openapi spec +- Composer dep bump +- Dep bump +- Upgrade cloudflared and minio +- Remove comments and improve DB column naming +- Remove unused seeder +- Remove unused waitlist stuff +- Remove wired.php (not used anymore) +- Remove unused resale license job +- Remove commented out internal notification +- Remove more waitlist stuff +- Remove commented out notification +- Remove more waitlist stuff +- Remove unused code +- Fix typo +- Remove comment out code +- Some reordering +- Remove resale license reference +- Remove functions from shared.php +- Public settings for email notification +- Remove waitlist redirect +- Remove log +- Use new notification trait +- Remove unused route +- Remove unused email component +- Comment status changes as it is disabled for now +- Bump dep +- Reorder navbar +- Rename topicID to threadId like in the telegram API response +- Update PHP configuration to set memory limit using environment variable +- Regenerate API spec, removing notification fields +- Remove ray debugging +- Version ++ +- Improve Penpot healthchecks +- Switch up readonly lables to make more sense +- Remove unused computed fields +- Use the new job dispatch +- Disable volume data cloning for now +- Improve code +- Lowcoder service naming +- Use new functions +- Improve error styling +- Css +- More css as it still looks like shit +- Final css touches +- Ajust time to 50s (tests done) +- Remove debug log, finally found it +- Remove more logging +- Remove limit on commit message +- Remove dayjs +- Remove unused code and fix import +- *(dep)* Bump nixpacks version +- *(dep)* Version++ +- *(dep)* Bump helper version to 1.0.5 +- *(docker)* Add blank line for readability in Dockerfile +- *(versions)* Update coolify versions to v4.0.0-beta.388 +- *(versions)* Update coolify versions to v4.0.0-beta.389 and add helper version retrieval script +- *(versions)* Update coolify versions to v4.0.0-beta.389 +- *(core)* EnvironmentVariable Model now extends BaseModel to remove duplicated code +- *(versions)* Update coolify versions to v4.0.0-beta.3909 +- *(version)* Bump Coolify version to 4.0.0-beta.391 +- *(config)* Increase default PHP memory limit to 256M +- Add openapi response +- *(workflows)* Make naming more clear and remove unused code +- Bump Coolify version to 4.0.0-beta.392/393 +- *(ci)* Update changelog generation workflow to target 'next' branch +- *(ci)* Update changelog generation workflow to target main branch +- Rollback Coolify version to 4.0.0-beta.392 +- Bump Coolify version to 4.0.0-beta.393 +- Bump Coolify version to 4.0.0-beta.394 +- Bump Coolify version to 4.0.0-beta.395 +- Bump Coolify version to 4.0.0-beta.396 +- *(services)* Update zipline to use new Database env var. (#5210) +- *(service)* Upgrade authentik service +- *(service)* Remove unused env from zipline +- Bump helper and realtime version +- *(migration)* Remove unused columns +- *(ssl)* Improve code in ssl helper +- *(migration)* Ssl cert and key should not be nullable +- *(ssl)* Rename CA cert to `coolify-ca.crt` because of conflicts +- Rename ca crt folder to ssl +- *(ui)* Improve valid until handling +- Improve code quality suggested by code rabbit +- *(supabase)* Update Supabase service template and Postgres image version +- *(versions)* Update version numbers for coolify and nightly +- *(versions)* Update version numbers for coolify and nightly +- *(service)* Update minecraft service ENVs +- *(service)* Add more vars to infisical.yaml (#5418) +- *(service)* Add google variables to plausible.yaml (#5429) +- *(service)* Update authentik.yaml versions (#5373) +- *(core)* Remove redocs +- *(versions)* Update coolify version numbers to 4.0.0-beta.403 and 4.0.0-beta.404 +- *(service)* Remove unused code in Bugsink service +- *(versions)* Update version to 404 +- *(versions)* Bump version to 403 (#5520) +- *(versions)* Bump version to 404 +- *(versions)* Bump version to 406 +- *(versions)* Bump version to 407 +- *(versions)* Bump version to 406 +- *(versions)* Bump version to 407 and 408 for coolify and nightly +- *(versions)* Bump version to 408 for coolify and 409 for nightly +- *(versions)* Update nightly version to 4.0.0-beta.410 +- *(pre-commit)* Remove OpenAPI generation command from pre-commit hook +- *(versions)* Update realtime version to 1.0.7 and bump dependencies in package.json +- *(versions)* Bump coolify version to 4.0.0-beta.409 in configuration files +- *(versions)* Bump coolify version to 4.0.0-beta.410 and update nightly version to 4.0.0-beta.411 in configuration files +- *(templates)* Update plausible and clickhouse images to latest versions and remove mail service +- *(versions)* Update coolify version to 4.0.0-beta.411 and nightly version to 4.0.0-beta.412 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.412 and nightly version to 4.0.0-beta.413 in configuration files +- *(versions)* Update coolify version to 4.0.0-beta.413 and nightly version to 4.0.0-beta.414 in configuration files +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(versions)* Update realtime version to 1.0.8 in versions.json +- *(docker)* Update soketi image version to 1.0.8 in production configuration files +- *(versions)* Update coolify version to 4.0.0-beta.414 and nightly version to 4.0.0-beta.415 in configuration files +- *(workflows)* Adjust workflow for announcement +- *(versions)* Update coolify version to 4.0.0-beta.416 and nightly version to 4.0.0-beta.417 in configuration files; fix links in deployment view +- *(seeder)* Update git branch from 'main' to 'v4.x' for multiple examples in ApplicationSeeder +- *(versions)* Update coolify version to 4.0.0-beta.417 and nightly version to 4.0.0-beta.418 +- *(versions)* Update coolify version to 4.0.0-beta.418 +- *(versions)* Update coolify version to 4.0.0-beta.419 and nightly version to 4.0.0-beta.420 in configuration files +- *(service)* Rename hoarder server to karakeep (#5607) +- *(service)* Update Supabase services (#5708) +- *(service)* Remove unused documenso env +- *(service)* Formatting and cleanup of ryot +- *(docs)* Remove changelog and add it to gitignore +- *(versions)* Update version to 4.0.0-beta.419 +- *(service)* Diun formatting +- *(docs)* Update CHANGELOG.md +- *(service)* Switch convex vars +- *(service)* Pgbackweb formatting and naming update +- *(service)* Remove typesense default API key +- *(service)* Format yamtrack healthcheck +- *(core)* Remove unused function +- *(ui)* Remove unused stopEvent code +- *(service)* Remove unused env +- *(tests)* Update test environment database name and add new feature test for converting container environment variables to array +- *(service)* Update Immich service (#5886) +- *(service)* Remove unused logo +- *(api)* Update API docs +- *(dependencies)* Update package versions in composer.json and composer.lock for improved compatibility and performance +- *(dependencies)* Update package versions in package.json and package-lock.json for improved stability and features +- *(version)* Update coolify-realtime to version 1.0.9 in docker-compose and versions files +- *(version)* Update coolify version to 4.0.0-beta.420 and nightly version to 4.0.0-beta.421 +- *(service)* Changedetection remove unused code +- *(service)* Update Evolution API image to the official one (#6031) +- *(versions)* Bump coolify versions to v4.0.0-beta.420 and v4.0.0-beta.421 +- *(dependencies)* Update composer dependencies to latest versions including resend-laravel to ^0.19.0 and aws-sdk-php to 3.347.0 +- *(versions)* Update Coolify version to 4.0.0-beta.420.1 and add new services (karakeep, miniflux, pingvinshare) to service templates +- *(versions)* Update Coolify versions to 4.0.0-beta.420.2 and 4.0.0-beta.420.3 in multiple files +- *(versions)* Bump coolify and nightly versions to 4.0.0-beta.420.3 and 4.0.0-beta.420.4 respectively +- *(versions)* Update coolify and nightly versions to 4.0.0-beta.420.4 and 4.0.0-beta.420.5 respectively +- *(service)* Update Nitropage template (#6181) +- *(versions)* Update all version +- *(bump)* Update composer deps +- *(version)* Bump Coolify version to 4.0.0-beta.420.6 +- *(service)* Improve matrix service +- *(service)* Format runner service +- *(service)* Improve sequin +- *(service)* Add `NOT_SECURED` env to Postiz (#6243) +- *(service)* Improve evolution-api environment variables (#6283) +- *(service)* Update Langfuse template to v3 (#6301) +- *(core)* Remove unused argument +- *(deletion)* Rename isDeleteOperation to deleteConnectedNetworks +- *(docker)* Remove unused arguments on StopService +- *(service)* Homebox formatting +- Clarify usage of custom redis configuration (#6321) +- *(changelogs)* Add .gitignore for changelogs directory and remove outdated changelog files for May, June, and July 2025 +- *(service)* Change affine images (#6366) +- Elasticsearch URL, fromatting and add category +- Update service-templates json files +- *(docs)* Remove AGENTS.md file; enhance CLAUDE.md with detailed form authorization patterns and service configuration examples +- *(cleanup)* Remove unused GitLab view files for change, new, and show pages +- *(workflows)* Add backlog directory to build triggers for production and staging workflows +- *(config)* Disable auto_commit in backlog configuration to prevent automatic commits +- *(versions)* Update coolify version to 4.0.0-beta.420.8 and nightly version to 4.0.0-beta.420.9 in versions.json and constants.php +- *(docker)* Update soketi image version to 1.0.10 in production and Windows configurations +- *(core)* Update version +- *(core)* Update version +- *(versions)* Update coolify version to 4.0.0-beta.421 and nightly version to 4.0.0-beta.422 +- Update version +- Update development node version +- Update coolify version to 4.0.0-beta.423 and nightly version to 4.0.0-beta.424 +- Update coolify version to 4.0.0-beta.424 and nightly version to 4.0.0-beta.425 +- Update coolify version to 4.0.0-beta.425 and nightly version to 4.0.0-beta.426 +- Update coolify version to 4.0.0-beta.426 and nightly version to 4.0.0-beta.427 -## [2.0.2] - 2022-02-10 +### ◀️ Revert -### 🐛 Bug Fixes - -- Secrets join -- ENV variables set differently - -## [1.0.0] - 2021-03-24 +- Show usage everytime +- Revert: revert +- Wip +- Variable parsing +- Hc return code check +- Instancesettings +- Pull policy +- Advanced dropdown +- Databasebackup +- Remove Cloudflare async tag attributes +- Encrypting mount and fs_path +- *(parser)* Enhance FQDN generation logic for services and applications From e9b4c19f7aeda1f45fb0b69aa216e80777ebaa56 Mon Sep 17 00:00:00 2001 From: Amir Hossein Karimi Date: Thu, 4 Sep 2025 16:02:48 +0330 Subject: [PATCH 016/322] fix(templates): remove mattermost healthcheck command according to lack of shell in new version --- templates/compose/mattermost.yaml | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/templates/compose/mattermost.yaml b/templates/compose/mattermost.yaml index f55a3639d..94aca3ac1 100644 --- a/templates/compose/mattermost.yaml +++ b/templates/compose/mattermost.yaml @@ -10,12 +10,12 @@ services: image: mattermost/mattermost-team-edition:release-10 platform: linux/amd64 volumes: - - 'mattermost-data-config:/mattermost/config:rw' - - 'mattermost-data-data:/mattermost/data:rw' - - 'mattermost-data-logs:/mattermost/logs:rw' - - 'mattermost-data-plugins:/mattermost/plugins:rw' - - 'mattermost-data-client-plugins:/mattermost/client/plugins:rw' - - 'mattermost-data-bleve-indexes:/mattermost/bleve-indexes:rw' + - "mattermost-data-config:/mattermost/config:rw" + - "mattermost-data-data:/mattermost/data:rw" + - "mattermost-data-logs:/mattermost/logs:rw" + - "mattermost-data-plugins:/mattermost/plugins:rw" + - "mattermost-data-client-plugins:/mattermost/client/plugins:rw" + - "mattermost-data-bleve-indexes:/mattermost/bleve-indexes:rw" environment: - SERVICE_URL_MATTERMOST_8065 - MM_SERVICESETTINGS_SITEURL=${SERVICE_URL_MATTERMOST} @@ -26,11 +26,6 @@ services: depends_on: postgres: condition: service_healthy - healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8065"] - interval: 5s - timeout: 20s - retries: 10 postgres: image: postgres:16-alpine From 97c22ab57041d2613d538c64f1886f2a8547b1b3 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Sat, 6 Sep 2025 04:00:48 +0530 Subject: [PATCH 017/322] Fix: Services & Env variables --- templates/compose/ente.yaml | 156 +++++++----------------------------- 1 file changed, 27 insertions(+), 129 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index a0c940f87..78ca81418 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -3,112 +3,60 @@ # category: media # tags: photos, backup, encryption, sharing, privacy, media, storage, encryption, minio, postgresql # logo: svgs/ente.png -# port: 8081 3000, 3001, 3002, 3003, 3004, 3200 services: museum: image: ghcr.io/ente-io/server:latest - ports: - - 8081:8080 environment: - SERVICE_URL_MUSEUM_8081: ${SERVICE_URL_MUSEUM_8081:-http://localhost:8081} + - SERVICE_URL_MUSEUM_8080 - ENTE_HTTP_USE_TLS: ${ENTE_HTTP_USE_TLS:-false} + - ENTE_HTTP_USE_TLS=${ENTE_HTTP_USE_TLS:-false} - ENTE_APPS_PUBLIC_ALBUMS: ${SERVICE_URL_WEB_3002:-http://localhost:3002} - ENTE_APPS_CAST: ${SERVICE_URL_WEB_3004:-http://localhost:3004} - ENTE_APPS_ACCOUNTS: ${SERVICE_URL_WEB_3001:-http://localhost:3001} - ENTE_APPS_PUBLIC_LOCKER: ${SERVICE_URL_WEB_3003:-http://localhost:3003} - ENTE_APPS_CUSTOM_DOMAIN_CNAME: ${ENTE_APPS_CUSTOM_DOMAIN_CNAME} + - ENTE_APPS_PUBLIC_ALBUMS=${SERVICE_URL_WEB_3002} + - ENTE_APPS_CAST=${SERVICE_URL_WEB_3004} + - ENTE_APPS_ACCOUNTS=${SERVICE_URL_WEB_3001} - ENTE_DB_HOST: ${ENTE_DB_HOST:-postgres} - ENTE_DB_PORT: ${ENTE_DB_PORT:-5432} - ENTE_DB_NAME: ${ENTE_DB_NAME:-ente_db} - ENTE_DB_SSLMODE: ${ENTE_DB_SSLMODE:-disable} - ENTE_DB_USER: ${SERVICE_USER_POSTGRES:-pguser} - ENTE_DB_PASSWORD: ${SERVICE_PASSWORD_POSTGRES} + - ENTE_DB_HOST=${ENTE_DB_HOST:-postgres} + - ENTE_DB_PORT=${ENTE_DB_PORT:-5432} + - ENTE_DB_NAME=${ENTE_DB_NAME:-ente_db} + - ENTE_DB_USER=${SERVICE_USER_POSTGRES:-pguser} + - ENTE_DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - ENTE_KEY_ENCRYPTION: ${MUSEUM_ENCRYPTION_KEY} - ENTE_KEY_HASH: ${MUSEUM_HASH_KEY} + - ENTE_KEY_ENCRYPTION=${SERVICE_REALBASE64_ENCRYPTION} + - ENTE_KEY_HASH=${SERVICE_REALBASE64_64_HASH} - ENTE_JWT_SECRET: ${MUSEUM_JWT_KEY} + - ENTE_JWT_SECRET=${SERVICE_REALBASE64_JWT} - ENTE_INTERNAL_SILENT: ${ENTE_INTERNAL_SILENT:-false} - ENTE_INTERNAL_HEALTH_CHECK_URL: ${ENTE_INTERNAL_HEALTH_CHECK_URL} - ENTE_INTERNAL_HARDCODED_OTT_EMAILS: ${ENTE_INTERNAL_HARDCODED_OTT_EMAIL} - ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_SUFFIX} - ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE: ${ENTE_INTERNAL_HARDCODED_OTT_LOCAL_DOMAIN_VALUE} - ENTE_INTERNAL_ADMINS: ${ENTE_INTERNAL_ADMINS} - ENTE_INTERNAL_ADMIN: 1580559962386438 - ENTE_INTERNAL_DISABLE_REGISTRATION: ${ENTE_INTERNAL_DISABLE_REGISTRATION:-false} + - ENTE_INTERNAL_ADMIN=${ENTE_INTERNAL_ADMIN:-1580559962386438} + - ENTE_INTERNAL_DISABLE_REGISTRATION=${ENTE_INTERNAL_DISABLE_REGISTRATION:-false} - ENTE_S3_ARE_LOCAL_BUCKETS: ${ENTE_S3_ARE_LOCAL_BUCKETS:-true} - ENTE_S3_USE_PATH_STYLE_URLS: ${ENTE_S3_USE_PATH_STYLE_URLS:-true} - - ENTE_S3_B2_EU_CEN_KEY: ${SERVICE_USER_MINIO} - ENTE_S3_B2_EU_CEN_SECRET: ${SERVICE_PASSWORD_MINIO} - ENTE_S3_B2_EU_CEN_ENDPOINT: ${SERVICE_URL_MINIO}:3200 - ENTE_S3_B2_EU_CEN_REGION: ${PRIMARY_STORAGE_REGION:-eu-central-2} - ENTE_S3_B2_EU_CEN_BUCKET: ${PRIMARY_STORAGE_BUCKET:-b2-eu-cen} - ENTE_S3_B2_EU_CEN_ARE_LOCAL_BUCKETS: ${PRIMARY_STORAGE_ARE_LOCAL_BUCKETS:-false} - ENTE_S3_B2_EU_CEN_USE_PATH_STYLE_URLS: ${PRIMARY_STORAGE_USE_PATH_STYLE_URLS:-false} - - ENTE_S3_WASABI_EU_CENTRAL_2_V3_KEY: ${SERVICE_USER_MINIO} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_SECRET: ${SERVICE_PASSWORD_MINIO} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_ENDPOINT: ${SERVICE_URL_MINIO}:3200 - ENTE_S3_WASABI_EU_CENTRAL_2_V3_REGION: ${SECONDARY_STORAGE_REGION:-eu-central-2} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_BUCKET: ${SECONDARY_STORAGE_BUCKET:-wasabi-eu-central-2-v3} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_ARE_LOCAL_BUCKETS: ${SECONDARY_STORAGE_ARE_LOCAL_BUCKETS:-false} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_USE_PATH_STYLE_URLS: ${SECONDARY_STORAGE_USE_PATH_STYLE_URLS:-false} - ENTE_S3_WASABI_EU_CENTRAL_2_V3_COMPLIANCE: ${SECONDARY_STORAGE_COMPLIANCE:-true} - - ENTE_S3_SCW_EU_FR_V3_KEY: ${SERVICE_USER_MINIO} - ENTE_S3_SCW_EU_FR_V3_SECRET: ${SERVICE_PASSWORD_MINIO} - ENTE_S3_SCW_EU_FR_V3_ENDPOINT: ${SERVICE_URL_MINIO}:3200 - ENTE_S3_SCW_EU_FR_V3_REGION: ${SECONDARY_STORAGE_REGION:-eu-central-2} - ENTE_S3_SCW_EU_FR_V3_BUCKET: ${COLD_STORAGE_BUCKET:-scw-eu-fr-v3} - ENTE_S3_SCW_EU_FR_V3_ARE_LOCAL_BUCKETS: ${COLD_STORAGE_ARE_LOCAL_BUCKETS:-true} - ENTE_S3_SCW_EU_FR_V3_USE_PATH_STYLE_URLS: ${COLD_STORAGE_USE_PATH_STYLE_URLS:-true} + - ENTE_S3_B2_EU_CEN_ARE_LOCAL_BUCKETS=${PRIMARY_STORAGE_ARE_LOCAL_BUCKETS:-false} + - ENTE_S3_B2_EU_CEN_USE_PATH_STYLE_URLS=${PRIMARY_STORAGE_USE_PATH_STYLE_URLS:-true} + - ENTE_S3_B2_EU_CEN_KEY=${S3_STORAGE_KEY:?} + - ENTE_S3_B2_EU_CEN_SECRET=${S3_STORAGE_SECRET:?} + - ENTE_S3_B2_EU_CEN_ENDPOINT=${S3_STORAGE_ENDPOINT:?} + - ENTE_S3_B2_EU_CEN_REGION=${S3_STORAGE_REGION:us-east-1} + - ENTE_S3_B2_EU_CEN_BUCKET=${S3_STORAGE_BUCKET:?} depends_on: postgres: condition: service_healthy - minio: - condition: service_healthy volumes: - museum-data:/data:rw healthcheck: - test: ["CMD", "curl", "--fail", "http://localhost:8081/ping"] + test: ["CMD", "wget", "-qO-", "http://localhost:8080/ping"] interval: 60s timeout: 5s retries: 3 start_period: 10s restart: unless-stopped - networks: - - ente-network - - socat: - image: alpine/socat - network_mode: service:museum - depends_on: [museum] - command: "TCP-LISTEN:3200,fork,reuseaddr TCP:minio:3200" - restart: unless-stopped web: image: ghcr.io/ente-io/web - # ports: - # - 3000:3000 # Photos web app - # - 3001:3001 # Accounts - # - 3002:3002 # Public albums - # - 3003:3003 # Auth - # - 3004:3004 # Cast environment: - ENTE_API_ORIGIN: ${SERVICE_URL_MUSEUM:-http://localhost}:8081 - SERVICE_URL_WEB_3000: ${SERVICE_URL_WEB_3000:-http://localhost:3000} - ENTE_ALBUMS_ORIGIN: ${SERVICE_URL_WEB_3002:-http://localhost:3002} - SERVICE_URL_WEB_3001: ${SERVICE_URL_WEB_3001:-http://localhost:3001} - SERVICE_URL_WEB_3003: ${SERVICE_URL_WEB_3003:-http://localhost:3003} - SERVICE_URL_WEB_3004: ${SERVICE_URL_WEB_3004:-http://localhost:3004} + - SERVICE_URL_WEB_3000 + - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} + - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} restart: unless-stopped healthcheck: @@ -117,8 +65,6 @@ services: timeout: 10s retries: 3 start_period: 10s - networks: - - ente-network postgres: image: postgres:15 @@ -129,61 +75,13 @@ services: volumes: - postgres-data:/var/lib/postgresql/data healthcheck: - test: - [ - "CMD-SHELL", - "pg_isready -U ${SERVICE_USER_POSTGRES:-pguser} -d ${SERVICE_DB_NAME:-ente_db}", - ] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 start_period: 30s restart: unless-stopped - networks: - - ente-network - - minio: - image: minio/minio - ports: - - 3200:3200 - environment: - SERVICE_URL_MINIO_3200: ${SERVICE_URL_MINIO_3200} - MINIO_ROOT_USER: ${SERVICE_USER_MINIO} - MINIO_ROOT_PASSWORD: ${SERVICE_PASSWORD_MINIO} - command: server /data --address ":3200" --console-address ":3201" - volumes: - - minio-data:/data - healthcheck: - test: ["CMD", "curl", "-f", "http://localhost:3200/minio/health/live"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 30s - post_start: - - command: | - sh -c ' - #!/bin/sh - - while ! mc alias set h0 http://minio:3200 ${SERVICE_USER_MINIO} ${SERVICE_PASSWORD_MINIO} 2>/dev/null - do - echo "Waiting for minio..." - sleep 0.5 - done - - cd /data - - mc mb -p b2-eu-cen - mc mb -p wasabi-eu-central-2-v3 - mc mb -p scw-eu-fr-v3 - ' - networks: - - ente-network volumes: postgres-data: - minio-data: museum-data: - -networks: - ente-network: - name: ente-network From 32ed4cbe6d34d90176683060156d904fe09c9842 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Sat, 6 Sep 2025 04:05:14 +0530 Subject: [PATCH 018/322] Fix: Product hunt Ente Logo --- public/svgs/ente.png | Bin 5096 -> 8770 bytes 1 file changed, 0 insertions(+), 0 deletions(-) diff --git a/public/svgs/ente.png b/public/svgs/ente.png index 737149125b4e84d6277bb4853494ae3ac4fe17bd..f510a7bf7d3dd0fedb2e85d510bd3d99ecda1a5a 100644 GIT binary patch literal 8770 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 From 9289730cd9fe03a939dfdf693435559d7c645ff2 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Sat, 6 Sep 2025 10:32:49 +0530 Subject: [PATCH 019/322] Removed Restart Condition. --- templates/compose/ente.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index 78ca81418..2da68c636 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -49,7 +49,6 @@ services: timeout: 5s retries: 3 start_period: 10s - restart: unless-stopped web: image: ghcr.io/ente-io/web @@ -58,7 +57,6 @@ services: - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} - restart: unless-stopped healthcheck: test: ["CMD", "curl", "--fail", "http://localhost:3000"] interval: 30s @@ -80,7 +78,6 @@ services: timeout: 5s retries: 5 start_period: 30s - restart: unless-stopped volumes: postgres-data: From afd5c959b5d50fa5505794b6e049ea11df6407df Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 7 Sep 2025 17:43:52 +0200 Subject: [PATCH 020/322] feat(campfire): add Docker Compose configuration for Once Campfire service --- public/svgs/once-campfire.png | Bin 0 -> 405666 bytes templates/compose/once-campfire.yaml | 31 +++++++++++++++++++++++++++ 2 files changed, 31 insertions(+) create mode 100644 public/svgs/once-campfire.png create mode 100644 templates/compose/once-campfire.yaml diff --git a/public/svgs/once-campfire.png b/public/svgs/once-campfire.png new file mode 100644 index 0000000000000000000000000000000000000000..d1158445b576fe52826c8bc676df3bca82a481ef GIT binary patch literal 405666 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

tJV6-canwE|_&Iw>$a; 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

Qi@>2O{*SBGeR{Hh&HWHUIY@7?WlX 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ʃ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�=#sq^f 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 z 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 otlcrn6?_kV9b_E)e*f Date: Sun, 7 Sep 2025 17:52:55 +0200 Subject: [PATCH 021/322] fix(campfire): update port configuration from 80 to 3000 in Docker Compose file --- templates/compose/once-campfire.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index 1f4e2b281..699533689 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -3,7 +3,7 @@ # category: messaging # tags: campfire,chat,communication,rails,once,basecamp,37signals # logo: svgs/once-campfire.png -# port: 80 +# port: 3000 services: campfire: From 1c30bda2212def00f1561d978f077f3c80867694 Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 7 Sep 2025 17:54:38 +0200 Subject: [PATCH 022/322] style(campfire): format environment variables for better readability in Docker Compose file --- templates/compose/once-campfire.yaml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index 699533689..ea9a6aecc 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -14,13 +14,13 @@ services: volumes: - campfire-storage:/rails/storage environment: - SECRET_KEY_BASE: ${SECRET_KEY_BASE} # required, set this to a secure random value - VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY} # optional, for notifications - VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} # optional, for notifications - DISABLE_SSL: ${DISABLE_SSL-true} # uncomment to disable SSL - SSL_DOMAIN: ${SSL_DOMAIN-false} # optional, for SSL - SKIP_TELEMETRY: ${SKIP_TELEMETRY-true} # optional, set to disable telemetry - SENTRY_DSN: ${SENTRY_DSN} # optional, for error reporting + SECRET_KEY_BASE: ${SECRET_KEY_BASE} # required, set this to a secure random value + VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY} # optional, for notifications + VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} # optional, for notifications + DISABLE_SSL: ${DISABLE_SSL-true} # uncomment to disable SSL + SSL_DOMAIN: ${SSL_DOMAIN-false} # optional, for SSL + SKIP_TELEMETRY: ${SKIP_TELEMETRY-true} # optional, set to disable telemetry + SENTRY_DSN: ${SENTRY_DSN} # optional, for error reporting healthcheck: test: ["CMD", "curl", "-f", "http://localhost/up"] interval: 10s From e6798ebf5e8d7181de0ce9f0cdf40d91a21d1f88 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Mon, 8 Sep 2025 02:23:40 +0530 Subject: [PATCH 023/322] fix: region env variable --- templates/compose/ente.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index 2da68c636..41b0c19cd 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -35,7 +35,7 @@ services: - ENTE_S3_B2_EU_CEN_KEY=${S3_STORAGE_KEY:?} - ENTE_S3_B2_EU_CEN_SECRET=${S3_STORAGE_SECRET:?} - ENTE_S3_B2_EU_CEN_ENDPOINT=${S3_STORAGE_ENDPOINT:?} - - ENTE_S3_B2_EU_CEN_REGION=${S3_STORAGE_REGION:us-east-1} + - ENTE_S3_B2_EU_CEN_REGION=${S3_STORAGE_REGION:-us-east-1} - ENTE_S3_B2_EU_CEN_BUCKET=${S3_STORAGE_BUCKET:?} depends_on: From 7754f5c7694bc4c77bee714fa78e7d20cb328082 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C3=96zg=C3=BCr?= <226712+halilim@users.noreply.github.com> Date: Mon, 8 Sep 2025 04:07:54 +0300 Subject: [PATCH 024/322] feat(service): add Gramps Web template --- public/svgs/gramps-web.svg | 154 ++++++++++++++++++++++++++++++ templates/compose/gramps-web.yaml | 63 ++++++++++++ 2 files changed, 217 insertions(+) create mode 100644 public/svgs/gramps-web.svg create mode 100644 templates/compose/gramps-web.yaml diff --git a/public/svgs/gramps-web.svg b/public/svgs/gramps-web.svg new file mode 100644 index 000000000..b5d79d76d --- /dev/null +++ b/public/svgs/gramps-web.svg @@ -0,0 +1,154 @@ + +image/svg+xml diff --git a/templates/compose/gramps-web.yaml b/templates/compose/gramps-web.yaml new file mode 100644 index 000000000..765a5321d --- /dev/null +++ b/templates/compose/gramps-web.yaml @@ -0,0 +1,63 @@ +# documentation: https://www.grampsweb.org/install_setup/setup/ +# slogan: Open Source Online Genealogy System. +# category: family +# tags: family, genealogy, personal +# logo: svgs/gramps-web.svg +# port: 5000 + +services: + grampsweb: &grampsweb + image: ghcr.io/gramps-project/grampsweb:latest + environment: + GRAMPSWEB_TREE: ${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists + GRAMPSWEB_CELERY_CONFIG__broker_url: "redis://grampsweb_redis:6379/0" + GRAMPSWEB_CELERY_CONFIG__result_backend: "redis://grampsweb_redis:6379/0" + GRAMPSWEB_RATELIMIT_STORAGE_URI: redis://grampsweb_redis:6379/1 + GUNICORN_NUM_WORKERS: ${GUNICORN_NUM_WORKERS:-2} + depends_on: + - grampsweb_redis + volumes: + - gramps_users:/app/users # persist user database + - gramps_index:/app/indexdir # persist search index + - gramps_thumb_cache:/app/thumbnail_cache # persist thumbnails + - gramps_cache:/app/cache # persist export and report caches + - gramps_secret:/app/secret # persist flask secret + - gramps_db:/root/.gramps/grampsdb # persist Gramps database + - gramps_media:/app/media # persist media files + - gramps_tmp:/tmp + healthcheck: + test: wget -O - http://localhost:5000 > /dev/null 2>&1 + interval: 5s + timeout: 10s + retries: 3 + + grampsweb_celery: + <<: *grampsweb + container_name: grampsweb_celery + depends_on: + - grampsweb_redis + command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2 + healthcheck: + test: SECRET_KEY="$(cat secret/secret)" celery -A gramps_webapi.celery status || exit 1 + interval: 5s + timeout: 10s + retries: 3 + + grampsweb_redis: + image: docker.io/library/redis:7.2.4-alpine + container_name: grampsweb_redis + healthcheck: + test: redis-cli ping | grep PONG + interval: 5s + timeout: 10s + retries: 3 + +volumes: + gramps_users: + gramps_index: + gramps_thumb_cache: + gramps_cache: + gramps_secret: + gramps_db: + gramps_media: + gramps_tmp: From 11786278e762d198caaf50aaa2866924f9feb6c6 Mon Sep 17 00:00:00 2001 From: ShadowArcanist Date: Mon, 8 Sep 2025 16:48:27 +0530 Subject: [PATCH 025/322] Added pgAdmin one click service --- templates/compose/pgadmin.yaml | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 templates/compose/pgadmin.yaml diff --git a/templates/compose/pgadmin.yaml b/templates/compose/pgadmin.yaml new file mode 100644 index 000000000..4192a5792 --- /dev/null +++ b/templates/compose/pgadmin.yaml @@ -0,0 +1,23 @@ +# documentation: https://www.pgadmin.org/docs/pgadmin4/latest/container_deployment.html +# slogan: pgAdmin is a web-based database management tool for administering your PostgreSQL databases through a user-friendly interface. +# category: database +# tags: database management +# logo: svgs/postgresql.svg +# port: 80 + +services: + pgadmin: + image: 'dpage/pgadmin4:latest' + container_name: pgadmin + restart: unless-stopped + environment: + - SERVICE_URL_PGADMIN + - 'PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL:?}' + - 'PGADMIN_DEFAULT_PASSWORD=${PGADMIN_DEFAULT_PASSWORD:?}' + volumes: + - pgadmin-data:/var/lib/pgadmin + healthcheck: + test: ["CMD", "wget", "-qO-", "http://localhost:80/login"] + interval: 5s + timeout: 10s + retries: 5 \ No newline at end of file From f5a4c5ac3f8a4ecc1fac5679fdb65891eefc1b90 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C3=96zg=C3=BCr?= <226712+halilim@users.noreply.github.com> Date: Tue, 9 Sep 2025 10:27:33 +0300 Subject: [PATCH 026/322] Improve service & update logo color --- public/svgs/gramps-web.svg | 26 +++++++++++----------- templates/compose/gramps-web.yaml | 36 ++++++++++++++----------------- 2 files changed, 29 insertions(+), 33 deletions(-) diff --git a/public/svgs/gramps-web.svg b/public/svgs/gramps-web.svg index b5d79d76d..eeef33047 100644 --- a/public/svgs/gramps-web.svg +++ b/public/svgs/gramps-web.svg @@ -73,7 +73,7 @@ inkscape:connector-curvature="0" id="path1087" d="m 175.2367,338.27684 h 31.47905 v -153.9548 h 60.76188" - style="fill:none;stroke:#795649;stroke-width:30;stroke-linecap:butt;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal" /> diff --git a/templates/compose/gramps-web.yaml b/templates/compose/gramps-web.yaml index 765a5321d..04a284ff2 100644 --- a/templates/compose/gramps-web.yaml +++ b/templates/compose/gramps-web.yaml @@ -6,17 +6,18 @@ # port: 5000 services: - grampsweb: &grampsweb + grampsweb: image: ghcr.io/gramps-project/grampsweb:latest environment: - GRAMPSWEB_TREE: ${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists - GRAMPSWEB_CELERY_CONFIG__broker_url: "redis://grampsweb_redis:6379/0" - GRAMPSWEB_CELERY_CONFIG__result_backend: "redis://grampsweb_redis:6379/0" - GRAMPSWEB_RATELIMIT_STORAGE_URI: redis://grampsweb_redis:6379/1 - GUNICORN_NUM_WORKERS: ${GUNICORN_NUM_WORKERS:-2} + - SERVICE_URL_GRAMPSWEB_5000 + - GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists + - GRAMPSWEB_CELERY_CONFIG__broker_url=redis://grampsweb_redis:6379/0 + - GRAMPSWEB_CELERY_CONFIG__result_backend=redis://grampsweb_redis:6379/0 + - GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://grampsweb_redis:6379/1 + - GUNICORN_NUM_WORKERS=${GUNICORN_NUM_WORKERS:-2} depends_on: - grampsweb_redis - volumes: + volumes: &volumes - gramps_users:/app/users # persist user database - gramps_index:/app/indexdir # persist search index - gramps_thumb_cache:/app/thumbnail_cache # persist thumbnails @@ -32,10 +33,16 @@ services: retries: 3 grampsweb_celery: - <<: *grampsweb - container_name: grampsweb_celery + image: ghcr.io/gramps-project/grampsweb:latest + environment: + - GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists + - GRAMPSWEB_CELERY_CONFIG__broker_url=redis://grampsweb_redis:6379/0 + - GRAMPSWEB_CELERY_CONFIG__result_backend=redis://grampsweb_redis:6379/0 + - GRAMPSWEB_RATELIMIT_STORAGE_URI=redis://grampsweb_redis:6379/1 depends_on: - grampsweb_redis + volumes: + <<: *volumes command: celery -A gramps_webapi.celery worker --loglevel=INFO --concurrency=2 healthcheck: test: SECRET_KEY="$(cat secret/secret)" celery -A gramps_webapi.celery status || exit 1 @@ -45,19 +52,8 @@ services: grampsweb_redis: image: docker.io/library/redis:7.2.4-alpine - container_name: grampsweb_redis healthcheck: test: redis-cli ping | grep PONG interval: 5s timeout: 10s retries: 3 - -volumes: - gramps_users: - gramps_index: - gramps_thumb_cache: - gramps_cache: - gramps_secret: - gramps_db: - gramps_media: - gramps_tmp: From db056b3af12192ee1c7ff858d5d3fb1b0099719c Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Tue, 9 Sep 2025 22:48:07 +0530 Subject: [PATCH 027/322] Removed restart policy and container name on pgAdmin Service Template --- templates/compose/pgadmin.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/templates/compose/pgadmin.yaml b/templates/compose/pgadmin.yaml index 4192a5792..bb447662e 100644 --- a/templates/compose/pgadmin.yaml +++ b/templates/compose/pgadmin.yaml @@ -8,8 +8,6 @@ services: pgadmin: image: 'dpage/pgadmin4:latest' - container_name: pgadmin - restart: unless-stopped environment: - SERVICE_URL_PGADMIN - 'PGADMIN_DEFAULT_EMAIL=${PGADMIN_DEFAULT_EMAIL:?}' @@ -20,4 +18,4 @@ services: test: ["CMD", "wget", "-qO-", "http://localhost:80/login"] interval: 5s timeout: 10s - retries: 5 \ No newline at end of file + retries: 5 From acde4ca02fd3eb80c43f3e5c5b286e7a91200665 Mon Sep 17 00:00:00 2001 From: Neeku <59068472+itsneeku@users.noreply.github.com> Date: Tue, 9 Sep 2025 13:27:12 -0400 Subject: [PATCH 028/322] chore(service): update convex template and image --- templates/compose/convex.yaml | 40 ++++++++++++++++++++++++++--------- 1 file changed, 30 insertions(+), 10 deletions(-) diff --git a/templates/compose/convex.yaml b/templates/compose/convex.yaml index 0b948b19a..ad8728ee1 100644 --- a/templates/compose/convex.yaml +++ b/templates/compose/convex.yaml @@ -1,4 +1,4 @@ -# documentation: https://docs.convex.dev/ +# documentation: https://github.com/get-convex/convex-backend/blob/main/self-hosted/README.md # slogan: Convex is the open-source reactive database for app developers. # category: backend # tags: database, reactive, database, ai, agents, chatbot, api, team, bot, flows @@ -7,7 +7,7 @@ services: backend: - image: ghcr.io/get-convex/convex-backend:5143fec81f146ca67495c12c6b7a15c5802c37e2 + image: ghcr.io/get-convex/convex-backend:00bd92723422f3bff968230c94ccdeb8c1719832 volumes: - data:/convex/data environment: @@ -16,22 +16,42 @@ services: - INSTANCE_SECRET=${SERVICE_HEX_32_SECRET} - CONVEX_RELEASE_VERSION_DEV=${CONVEX_RELEASE_VERSION_DEV:-} - ACTIONS_USER_TIMEOUT_SECS=${ACTIONS_USER_TIMEOUT_SECS:-} - - CONVEX_CLOUD_ORIGIN=${SERVICE_URL_CONVEX_3210} - - CONVEX_SITE_ORIGIN=${SERVICE_URL_CONVEX_3211} + # URL of the Convex API as accessed by the client/frontend. + - CONVEX_CLOUD_ORIGIN=${SERVICE_URL_CONVEX} + # URL of Convex HTTP actions as accessed by the client/frontend. + - CONVEX_SITE_ORIGIN=${SERVICE_URL_BACKEND} - DATABASE_URL=${DATABASE_URL:-} - - DISABLE_BEACON=${DISABLE_BEACON:-} - - REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:-} - - CONVEX_SELF_HOSTED_URL=${SERVICE_URL_CONVEX_6791} + - DISABLE_BEACON=${DISABLE_BEACON:?false} + - REDACT_LOGS_TO_CLIENT=${REDACT_LOGS_TO_CLIENT:?false} + - DO_NOT_REQUIRE_SSL=${DO_NOT_REQUIRE_SSL:?true} + - POSTGRES_URL=${POSTGRES_URL:-} + - MYSQL_URL=${MYSQL_URL:-} + - RUST_LOG=${RUST_LOG:-info} + - RUST_BACKTRACE=${RUST_BACKTRACE:-} + - AWS_REGION=${AWS_REGION:-} + - AWS_ACCESS_KEY_ID=${AWS_ACCESS_KEY_ID:-} + - AWS_SECRET_ACCESS_KEY=${AWS_SECRET_ACCESS_KEY:-} + - AWS_SESSION_TOKEN=${AWS_SESSION_TOKEN:-} + - AWS_S3_FORCE_PATH_STYLE=${AWS_S3_FORCE_PATH_STYLE:-} + - AWS_S3_DISABLE_SSE=${AWS_S3_DISABLE_SSE:-} + - AWS_S3_DISABLE_CHECKSUMS=${AWS_S3_DISABLE_CHECKSUMS:-} + - S3_STORAGE_EXPORTS_BUCKET=${S3_STORAGE_EXPORTS_BUCKET:-} + - S3_STORAGE_SNAPSHOT_IMPORTS_BUCKET=${S3_STORAGE_SNAPSHOT_IMPORTS_BUCKET:-} + - S3_STORAGE_MODULES_BUCKET=${S3_STORAGE_MODULES_BUCKET:-} + - S3_STORAGE_FILES_BUCKET=${S3_STORAGE_FILES_BUCKET:-} + - S3_STORAGE_SEARCH_BUCKET=${S3_STORAGE_SEARCH_BUCKET:-} + - S3_ENDPOINT_URL=${S3_ENDPOINT_URL:-} healthcheck: test: curl -f http://127.0.0.1:3210/version interval: 5s - start_period: 5s + start_period: 10s dashboard: - image: ghcr.io/get-convex/convex-dashboard:5143fec81f146ca67495c12c6b7a15c5802c37e2 + image: ghcr.io/get-convex/convex-dashboard:33cef775a8a6228cbacee4a09ac2c4073d62ed13 environment: - SERVICE_URL_CONVEX_6791 - - NEXT_PUBLIC_DEPLOYMENT_URL=$SERVICE_URL_BACKEND_3210 + # URL of the Convex API as accessed by the dashboard (browser). + - NEXT_PUBLIC_DEPLOYMENT_URL=${SERVICE_URL_BACKEND} depends_on: backend: condition: service_healthy From 2e3d09df2a2b5881234e1760b68a4ca60c27d029 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=A0ng=20Tr=E1=BA=A7n=20Nh=E1=BA=ADt=20Minh?= <82358580+htnminh@users.noreply.github.com> Date: Thu, 11 Sep 2025 23:21:48 +0700 Subject: [PATCH 029/322] fix(template/filebrowser): correct routing and healthcheck for Filebrowser --- templates/compose/filebrowser.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/compose/filebrowser.yaml b/templates/compose/filebrowser.yaml index 2cb17d501..a9eb35e2e 100644 --- a/templates/compose/filebrowser.yaml +++ b/templates/compose/filebrowser.yaml @@ -30,7 +30,7 @@ services: "port": 80 } healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:80"] - interval: 2s - timeout: 10s - retries: 15 + test: ["CMD-SHELL", "wget -q --spider http://localhost:80 || exit 1"] + interval: 10s + timeout: 3s + retries: 10 From 2d267d6f238c28235b9c390c9adc0a73f00dc334 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ho=C3=A0ng=20Tr=E1=BA=A7n=20Nh=E1=BA=ADt=20Minh?= <82358580+htnminh@users.noreply.github.com> Date: Fri, 12 Sep 2025 02:31:26 +0700 Subject: [PATCH 030/322] fix(template/filebrowser): correct healthcheck for Filebrowser --- templates/compose/filebrowser.yaml | 5 ----- 1 file changed, 5 deletions(-) diff --git a/templates/compose/filebrowser.yaml b/templates/compose/filebrowser.yaml index a9eb35e2e..e9c34b7ca 100644 --- a/templates/compose/filebrowser.yaml +++ b/templates/compose/filebrowser.yaml @@ -29,8 +29,3 @@ services: "address": "0.0.0.0", "port": 80 } - healthcheck: - test: ["CMD-SHELL", "wget -q --spider http://localhost:80 || exit 1"] - interval: 10s - timeout: 3s - retries: 10 From 57976e4d6d63f55fa63b68e9921063e14ae7fcd8 Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 14 Sep 2025 08:29:29 +0200 Subject: [PATCH 031/322] fix(campfire): correct port comment from 3000 to 80 in Docker Compose file Co-authored-by: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> --- templates/compose/once-campfire.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index ea9a6aecc..601df9fc4 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -3,7 +3,7 @@ # category: messaging # tags: campfire,chat,communication,rails,once,basecamp,37signals # logo: svgs/once-campfire.png -# port: 3000 +# port: 80 services: campfire: From 5bf5893a839c536c486a02dea9286b34765f4621 Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 14 Sep 2025 08:55:31 +0200 Subject: [PATCH 032/322] refactor(campfire): streamline environment variable definitions in Docker Compose file --- templates/compose/once-campfire.yaml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index 601df9fc4..0dc20fc48 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -8,24 +8,20 @@ services: campfire: build: https://github.com/basecamp/once-campfire.git#${BRANCH:-main} - ports: - - "3000:80" restart: unless-stopped volumes: - campfire-storage:/rails/storage environment: - SECRET_KEY_BASE: ${SECRET_KEY_BASE} # required, set this to a secure random value - VAPID_PUBLIC_KEY: ${VAPID_PUBLIC_KEY} # optional, for notifications - VAPID_PRIVATE_KEY: ${VAPID_PRIVATE_KEY} # optional, for notifications - DISABLE_SSL: ${DISABLE_SSL-true} # uncomment to disable SSL - SSL_DOMAIN: ${SSL_DOMAIN-false} # optional, for SSL - SKIP_TELEMETRY: ${SKIP_TELEMETRY-true} # optional, set to disable telemetry - SENTRY_DSN: ${SENTRY_DSN} # optional, for error reporting + - SERVICE_URL_CAMPFIRE_80 + - SECRET_KEY_BASE=${SERVICE_BASE64_64_CAMPFIRE} # required, set this to a secure random value + - VAPID_PUBLIC_KEY=${VAPID_PUBLIC_KEY} # optional, for notifications + - VAPID_PRIVATE_KEY=${VAPID_PRIVATE_KEY} # optional, for notifications + - DISABLE_SSL=${DISABLE_SSL:-true} # uncomment to disable SSL + - SSL_DOMAIN=${SSL_DOMAIN:-false} # optional, for SSL + - SKIP_TELEMETRY=${SKIP_TELEMETRY:-true} # optional, set to disable telemetry + - SENTRY_DSN=${SENTRY_DSN} # optional, for error reporting healthcheck: test: ["CMD", "curl", "-f", "http://localhost/up"] interval: 10s timeout: 5s retries: 5 - -volumes: - campfire-storage: From 41389a30d46a635a3e9321ab3862381f872649ac Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 14 Sep 2025 08:57:33 +0200 Subject: [PATCH 033/322] style(campfire): update comment for DISABLE_SSL environment variable for clarity --- templates/compose/once-campfire.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index 0dc20fc48..6bfe0fdea 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -16,7 +16,7 @@ services: - SECRET_KEY_BASE=${SERVICE_BASE64_64_CAMPFIRE} # required, set this to a secure random value - VAPID_PUBLIC_KEY=${VAPID_PUBLIC_KEY} # optional, for notifications - VAPID_PRIVATE_KEY=${VAPID_PRIVATE_KEY} # optional, for notifications - - DISABLE_SSL=${DISABLE_SSL:-true} # uncomment to disable SSL + - DISABLE_SSL=${DISABLE_SSL:-true} # optional, disable SSL - SSL_DOMAIN=${SSL_DOMAIN:-false} # optional, for SSL - SKIP_TELEMETRY=${SKIP_TELEMETRY:-true} # optional, set to disable telemetry - SENTRY_DSN=${SENTRY_DSN} # optional, for error reporting From 3dcc64328dd7f7d9c65aba5a110b4791a0521e1b Mon Sep 17 00:00:00 2001 From: victor Date: Sun, 14 Sep 2025 09:16:02 +0200 Subject: [PATCH 034/322] fix(campfire): update service definition to use image instead of build in Docker Compose file --- templates/compose/once-campfire.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/once-campfire.yaml b/templates/compose/once-campfire.yaml index 6bfe0fdea..22fc39de5 100644 --- a/templates/compose/once-campfire.yaml +++ b/templates/compose/once-campfire.yaml @@ -7,7 +7,7 @@ services: campfire: - build: https://github.com/basecamp/once-campfire.git#${BRANCH:-main} + image: ghcr.io/basecamp/once-campfire:${TAG:-main} restart: unless-stopped volumes: - campfire-storage:/rails/storage From 57a1e7a076bc358d125fafe881f3ebf4673e4f76 Mon Sep 17 00:00:00 2001 From: SAHIL Date: Sun, 14 Sep 2025 20:07:40 +0530 Subject: [PATCH 035/322] Fix: Remove volumes --- templates/compose/ente.yaml | 3 --- 1 file changed, 3 deletions(-) diff --git a/templates/compose/ente.yaml b/templates/compose/ente.yaml index 41b0c19cd..355b55b1c 100644 --- a/templates/compose/ente.yaml +++ b/templates/compose/ente.yaml @@ -79,6 +79,3 @@ services: retries: 5 start_period: 30s -volumes: - postgres-data: - museum-data: From b859807d613acb4c8c66385e8aa51f1c2ebf901e Mon Sep 17 00:00:00 2001 From: zehjotkah <111518041+zehjotkah@users.noreply.github.com> Date: Tue, 16 Sep 2025 20:26:44 +0100 Subject: [PATCH 036/322] added rybbit service template --- public/svgs/rybbit.svg | 1 + templates/compose/rybbit.yaml | 138 ++++++++++++++++++++++++++++++++++ 2 files changed, 139 insertions(+) create mode 100644 public/svgs/rybbit.svg create mode 100644 templates/compose/rybbit.yaml diff --git a/public/svgs/rybbit.svg b/public/svgs/rybbit.svg new file mode 100644 index 000000000..5715b29bd --- /dev/null +++ b/public/svgs/rybbit.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/templates/compose/rybbit.yaml b/templates/compose/rybbit.yaml new file mode 100644 index 000000000..c86299faf --- /dev/null +++ b/templates/compose/rybbit.yaml @@ -0,0 +1,138 @@ +# documentation: https://rybbit.io/docs +# slogan: Open-source, privacy-first web analytics. +# tags: analytics,web,privacy,self-hosted,clickhouse,postgres +# logo: svgs/rybbit.svg +# port: 3000 + +services: + rybbit: + image: 'ghcr.io/rybbit-io/rybbit-client:latest' + container_name: rybbit-client + environment: + - NODE_ENV=production + - 'NEXT_PUBLIC_BACKEND_URL=${SERVICE_URL_RYBBIT}' + - 'NEXT_PUBLIC_DISABLE_SIGNUP=${DISABLE_SIGNUP:-false}' + depends_on: + - rybbit_backend + restart: unless-stopped + + rybbit_backend: + image: 'ghcr.io/rybbit-io/rybbit-backend:latest' + container_name: rybbit-backend + environment: + - NODE_ENV=production + - TRUST_PROXY=true + - 'BASE_URL=${SERVICE_URL_RYBBIT}' + # --- Coolify-Managed Secrets --- + - 'CLICKHOUSE_PASSWORD=${SERVICE_PASSWORD_CLICKHOUSE}' + - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' + - 'BETTER_AUTH_SECRET=${SERVICE_BASE64_64_BACKEND}' + # --- User Settings --- + - 'DISABLE_SIGNUP=${DISABLE_SIGNUP:-false}' + - 'DISABLE_TELEMETRY=${DISABLE_TELEMETRY:-true}' + # --- Internal Config --- + - 'CLICKHOUSE_HOST=http://rybbit_clickhouse:8123' + - CLICKHOUSE_USER=default + - CLICKHOUSE_DB=analytics + - POSTGRES_HOST=rybbit_postgres + - POSTGRES_PORT=5432 + - POSTGRES_DB=analytics + - POSTGRES_USER=frog + depends_on: + rybbit_clickhouse: + condition: service_healthy + rybbit_postgres: + condition: service_healthy + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:3001/api/health"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + restart: unless-stopped + + rybbit_postgres: + image: 'postgres:17.4' + container_name: rybbit-postgres + environment: + - POSTGRES_DB=analytics + - POSTGRES_USER=frog + - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' + volumes: + - 'postgres_data:/var/lib/postgresql/data' + healthcheck: + test: ["CMD-SHELL", "pg_isready -U $${POSTGRES_USER} -d $${POSTGRES_DB}"] + interval: 30s + timeout: 10s + retries: 3 + restart: unless-stopped + + rybbit_clickhouse: + image: 'clickhouse/clickhouse-server:25.4.2' + container_name: rybbit-clickhouse + environment: + - CLICKHOUSE_DB=analytics + - CLICKHOUSE_USER=default + - 'CLICKHOUSE_PASSWORD=${SERVICE_PASSWORD_CLICKHOUSE}' + healthcheck: + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8123/ping"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + restart: unless-stopped + volumes: + - 'clickhouse_data:/var/lib/clickhouse' + - type: bind + source: ./clickhouse_config/enable_json.xml + target: /etc/clickhouse-server/config.d/enable_json.xml + content: | + + + 1 + + + - type: bind + source: ./clickhouse_config/logging_rules.xml + target: /etc/clickhouse-server/config.d/logging_rules.xml + content: | + + + warning + true + + + + + + + + + + + + + - type: bind + source: ./clickhouse_config/network.xml + target: /etc/clickhouse-server/config.d/network.xml + content: | + + 0.0.0.0 + + - type: bind + source: ./clickhouse_config/user_logging.xml + target: /etc/clickhouse-server/config.d/user_logging.xml + content: | + + + + 0 + 0 + 0 + + + + +volumes: + postgres_data: + clickhouse_data: From 65f60a2ca2399b8a070799ec0769802159e32269 Mon Sep 17 00:00:00 2001 From: zehjotkah <111518041+zehjotkah@users.noreply.github.com> Date: Wed, 17 Sep 2025 19:30:12 +0100 Subject: [PATCH 037/322] Update rybbit.yaml - fixed port - removed unnecessary stuff (container_name, restart) - added client/frontend healthcheck - DRY for hardcoded values --- templates/compose/rybbit.yaml | 39 +++++++++++++++-------------------- 1 file changed, 17 insertions(+), 22 deletions(-) diff --git a/templates/compose/rybbit.yaml b/templates/compose/rybbit.yaml index c86299faf..1b3ce16af 100644 --- a/templates/compose/rybbit.yaml +++ b/templates/compose/rybbit.yaml @@ -2,23 +2,27 @@ # slogan: Open-source, privacy-first web analytics. # tags: analytics,web,privacy,self-hosted,clickhouse,postgres # logo: svgs/rybbit.svg -# port: 3000 +# port: 3002 services: rybbit: image: 'ghcr.io/rybbit-io/rybbit-client:latest' - container_name: rybbit-client environment: + - SERVICE_URL_RYBBIT_3002 - NODE_ENV=production - 'NEXT_PUBLIC_BACKEND_URL=${SERVICE_URL_RYBBIT}' - 'NEXT_PUBLIC_DISABLE_SIGNUP=${DISABLE_SIGNUP:-false}' depends_on: - rybbit_backend - restart: unless-stopped + healthcheck: + test: ["CMD-SHELL", "nc -z 127.0.0.1 3002"] + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s rybbit_backend: image: 'ghcr.io/rybbit-io/rybbit-backend:latest' - container_name: rybbit-backend environment: - NODE_ENV=production - TRUST_PROXY=true @@ -32,12 +36,12 @@ services: - 'DISABLE_TELEMETRY=${DISABLE_TELEMETRY:-true}' # --- Internal Config --- - 'CLICKHOUSE_HOST=http://rybbit_clickhouse:8123' - - CLICKHOUSE_USER=default - - CLICKHOUSE_DB=analytics + - 'CLICKHOUSE_USER=${CLICKHOUSE_USER:-default}' + - 'CLICKHOUSE_DB=${CLICKHOUSE_DB:-analytics}' - POSTGRES_HOST=rybbit_postgres - POSTGRES_PORT=5432 - - POSTGRES_DB=analytics - - POSTGRES_USER=frog + - 'POSTGRES_DB=${POSTGRES_DB:-analytics}' + - 'POSTGRES_USER=${POSTGRES_USER:-frog}' depends_on: rybbit_clickhouse: condition: service_healthy @@ -49,14 +53,12 @@ services: timeout: 10s retries: 3 start_period: 10s - restart: unless-stopped rybbit_postgres: image: 'postgres:17.4' - container_name: rybbit-postgres environment: - - POSTGRES_DB=analytics - - POSTGRES_USER=frog + - 'POSTGRES_DB=${POSTGRES_DB:-analytics}' + - 'POSTGRES_USER=${POSTGRES_USER:-frog}' - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' volumes: - 'postgres_data:/var/lib/postgresql/data' @@ -65,14 +67,12 @@ services: interval: 30s timeout: 10s retries: 3 - restart: unless-stopped rybbit_clickhouse: image: 'clickhouse/clickhouse-server:25.4.2' - container_name: rybbit-clickhouse environment: - - CLICKHOUSE_DB=analytics - - CLICKHOUSE_USER=default + - 'CLICKHOUSE_DB=${CLICKHOUSE_DB:-analytics}' + - 'CLICKHOUSE_USER=${CLICKHOUSE_USER:-default}' - 'CLICKHOUSE_PASSWORD=${SERVICE_PASSWORD_CLICKHOUSE}' healthcheck: test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://localhost:8123/ping"] @@ -80,7 +80,6 @@ services: timeout: 10s retries: 3 start_period: 10s - restart: unless-stopped volumes: - 'clickhouse_data:/var/lib/clickhouse' - type: bind @@ -131,8 +130,4 @@ services: 0 - - -volumes: - postgres_data: - clickhouse_data: + \ No newline at end of file From 307f69d0ecbcbab19f953c0e0ef9e4627818ec27 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 19 Sep 2025 16:24:37 +0200 Subject: [PATCH 038/322] feat(templates): added Lobe Chat service --- public/svgs/lobe-chat.png | Bin 0 -> 208557 bytes templates/compose/lobe-chat.yaml | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+) create mode 100644 public/svgs/lobe-chat.png create mode 100644 templates/compose/lobe-chat.yaml diff --git a/public/svgs/lobe-chat.png b/public/svgs/lobe-chat.png new file mode 100644 index 0000000000000000000000000000000000000000..2d340df888f12e2d2d72d4990222398e3b749d31 GIT binary patch literal 208557 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 Date: Fri, 19 Sep 2025 16:34:02 +0200 Subject: [PATCH 039/322] fix(templates): update Lobe-chat openai base_url env + required envs --- templates/compose/lobe-chat.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/compose/lobe-chat.yaml b/templates/compose/lobe-chat.yaml index 3725985f3..cde8e78e0 100644 --- a/templates/compose/lobe-chat.yaml +++ b/templates/compose/lobe-chat.yaml @@ -11,7 +11,8 @@ services: environment: - SERVICE_URL_LOBECHAT_3210 - OPENAI_API_KEY=${SERVICE_OPENAI_API_KEY} - - ACCESS_CODE=${SERVICE_PASSWORD_ACCESSCODE} + - OPENAI_PROXY_URL=${SERVICE_URL_OPENAI_PROXY:-https://api.openai.com/v1} + - ACCESS_CODE=${SERVICE_PASSWORD_ACCESSCODE?} healthcheck: test: - CMD-SHELL From a858a83942637e1df13b4948f3c24a0bc2ce30fb Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Fri, 19 Sep 2025 19:16:34 +0200 Subject: [PATCH 040/322] fix(template) Fix lobe-chat typo --- templates/compose/lobe-chat.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/lobe-chat.yaml b/templates/compose/lobe-chat.yaml index cde8e78e0..97cc2e1e3 100644 --- a/templates/compose/lobe-chat.yaml +++ b/templates/compose/lobe-chat.yaml @@ -12,7 +12,7 @@ services: - SERVICE_URL_LOBECHAT_3210 - OPENAI_API_KEY=${SERVICE_OPENAI_API_KEY} - OPENAI_PROXY_URL=${SERVICE_URL_OPENAI_PROXY:-https://api.openai.com/v1} - - ACCESS_CODE=${SERVICE_PASSWORD_ACCESSCODE?} + - ACCESS_CODE=${SERVICE_PASSWORD_ACCESSCODE} healthcheck: test: - CMD-SHELL From 1fc07d6942353c47359563a2fe47a545224f0343 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS <46826777+yipfram@users.noreply.github.com> Date: Mon, 22 Sep 2025 20:26:12 +0200 Subject: [PATCH 041/322] fix(templates): Lobechat environnement variable Removing "SERVICE_XXX" --- templates/compose/lobe-chat.yaml | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/templates/compose/lobe-chat.yaml b/templates/compose/lobe-chat.yaml index 97cc2e1e3..5dcb226c9 100644 --- a/templates/compose/lobe-chat.yaml +++ b/templates/compose/lobe-chat.yaml @@ -10,8 +10,8 @@ services: image: "lobehub/lobe-chat:latest" environment: - SERVICE_URL_LOBECHAT_3210 - - OPENAI_API_KEY=${SERVICE_OPENAI_API_KEY} - - OPENAI_PROXY_URL=${SERVICE_URL_OPENAI_PROXY:-https://api.openai.com/v1} + - OPENAI_API_KEY=${OPENAI_API_KEY} + - OPENAI_PROXY_URL=${OPENAI_BASE_URL:-https://api.openai.com/v1} - ACCESS_CODE=${SERVICE_PASSWORD_ACCESSCODE} healthcheck: test: @@ -19,4 +19,4 @@ services: - "wget -qO- http://localhost:3210/ || exit 1" interval: 5s timeout: 20s - retries: 10 \ No newline at end of file + retries: 10 From 7b00a8519779f12c3e761d72d6b50f65cef514a4 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Tue, 16 Sep 2025 20:43:17 -0400 Subject: [PATCH 042/322] fix: Bluesky PDS template MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If it works, it works, don't touch it 😭 --- templates/compose/bluesky-pds.yaml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 371e67878..f03e20dcc 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -9,9 +9,9 @@ services: pds: image: 'ghcr.io/bluesky-social/pds:latest' volumes: - - ./pds-data:/pds + - /root/pds-data:/pds environment: - - SERVICE_URL_PDS_3000 + - SERVICE_FQDN_PDS_3000 - PDS_HOSTNAME=${SERVICE_URL_PDS} - PDS_JWT_SECRET=${SERVICE_PASSWORD_JWT_SECRET} - PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN} @@ -27,11 +27,11 @@ services: - PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac} - PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network} - LOG_ENABLED=${LOG_ENABLED:-true} - + command: > sh -c ' - echo "Installing curl, bash, and pdsadmin..." - apk add --no-cache curl bash && \ + echo "Installing required packages and pdsadmin..." + apk add --no-cache curl bash jq coreutils && \ curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ chmod +x /usr/local/bin/pdsadmin.sh && \ ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin From a9ad8ed824f43e2e736ddb9e4a84497197ea13ab Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:08:11 -0400 Subject: [PATCH 043/322] fix: Bluesky PDS template finally works normally --- templates/compose/bluesky-pds.yaml | 54 +++++++++++++----------------- 1 file changed, 24 insertions(+), 30 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index f03e20dcc..65176e5f7 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -1,44 +1,35 @@ -# documentation: https://github.com/bluesky-social/pds -# slogan: Bluesky PDS (Personal Data Server) -# category: backend -# tags: bluesky, pds, platform -# logo: svgs/bluesky.svg -# port: 3000 - services: pds: image: 'ghcr.io/bluesky-social/pds:latest' volumes: - - /root/pds-data:/pds + - './pds-data:/pds' environment: - SERVICE_FQDN_PDS_3000 - - PDS_HOSTNAME=${SERVICE_URL_PDS} - - PDS_JWT_SECRET=${SERVICE_PASSWORD_JWT_SECRET} - - PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN} - - PDS_ADMIN_EMAIL=${SERVICE_EMAIL_ADMIN} - - PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX} - - PDS_DATA_DIRECTORY=${PDS_DATA_DIRECTORY:-/pds} - - PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks - - PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-52428800} - - PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory} - - PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app} - - PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app} - - PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport} - - PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac} - - PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network} - - LOG_ENABLED=${LOG_ENABLED:-true} - - command: > + - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' + - 'PDS_JWT_SECRET=${SERVICE_PASSWORD_JWT_SECRET}' + - 'PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN}' + - 'PDS_ADMIN_EMAIL=${SERVICE_EMAIL_ADMIN}' + - 'PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}' + - 'PDS_DATA_DIRECTORY=${PDS_DATA_DIRECTORY:-/pds}' + - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' + - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-52428800}' + - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' + - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' + - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' + - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' + - 'PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac}' + - 'PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network}' + - 'LOG_ENABLED=${LOG_ENABLED:-true}' + command: | sh -c ' - echo "Installing required packages and pdsadmin..." - apk add --no-cache curl bash jq coreutils && \ + set -euo pipefail; echo "Installing required packages and pdsadmin..." + apk add --no-cache curl bash jq coreutils >/dev/null && \ curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ chmod +x /usr/local/bin/pdsadmin.sh && \ ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin echo "Generating /pds/pds.env..." printf "%s\n" \ - "SERVICE_FQDN_PDS_3000=$${SERVICE_FQDN_PDS_3000}" \ "PDS_HOSTNAME=$${PDS_HOSTNAME}" \ "PDS_JWT_SECRET=$${PDS_JWT_SECRET}" \ "PDS_ADMIN_PASSWORD=$${PDS_ADMIN_PASSWORD}" \ @@ -59,9 +50,12 @@ services: echo "Launching PDS..." exec node --enable-source-maps index.js ' - healthcheck: - test: ["CMD", "wget", "--spider", "http://127.0.0.1:3000/xrpc/_health"] + test: + - CMD + - wget + - '--spider' + - 'http://127.0.0.1:3000/xrpc/_health' interval: 2s timeout: 10s retries: 10 From d83a5763c63b8716521a0649cebd94d1653ab525 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:09:21 -0400 Subject: [PATCH 044/322] fix: add back template info --- templates/compose/bluesky-pds.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 65176e5f7..a42d6c551 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -1,3 +1,10 @@ +# documentation: https://github.com/bluesky-social/pds +# slogan: Bluesky PDS (Personal Data Server) +# category: backend +# tags: bluesky, pds, platform +# logo: svgs/bluesky.svg +# port: 3000 + services: pds: image: 'ghcr.io/bluesky-social/pds:latest' From adb46ed0303d65774fdb54c2c7bbf9462c458795 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Tue, 16 Sep 2025 21:36:09 -0400 Subject: [PATCH 045/322] fix: now it automatically generates the JWT secret and the PLC rotation key --- templates/compose/bluesky-pds.yaml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index a42d6c551..bff450334 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -13,13 +13,13 @@ services: environment: - SERVICE_FQDN_PDS_3000 - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' - - 'PDS_JWT_SECRET=${SERVICE_PASSWORD_JWT_SECRET}' + - 'PDS_JWT_SECRET=${SERVICE_HEX_32_JWTSECRET}' - 'PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN}' - 'PDS_ADMIN_EMAIL=${SERVICE_EMAIL_ADMIN}' - - 'PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}' + - 'PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${SERVICE_HEX_32_ROTATIONKEY}' - 'PDS_DATA_DIRECTORY=${PDS_DATA_DIRECTORY:-/pds}' - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' - - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-52428800}' + - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' @@ -30,7 +30,7 @@ services: command: | sh -c ' set -euo pipefail; echo "Installing required packages and pdsadmin..." - apk add --no-cache curl bash jq coreutils >/dev/null && \ + apk add --no-cache openssl curl bash jq coreutils >/dev/null && \ curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ chmod +x /usr/local/bin/pdsadmin.sh && \ ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin From 3fc3058439390609661ecac19757d02bc49cad7a Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Wed, 17 Sep 2025 13:32:32 -0400 Subject: [PATCH 046/322] feat: Add Email Envs, Install more required packages by pdsadmin --- templates/compose/bluesky-pds.yaml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index bff450334..57d515f41 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -21,6 +21,8 @@ services: - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' + - 'PDS_EMAIL_FROM_ADDRESS=${SERVICE_EMAIL_ADMIN}' + - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' @@ -30,7 +32,7 @@ services: command: | sh -c ' set -euo pipefail; echo "Installing required packages and pdsadmin..." - apk add --no-cache openssl curl bash jq coreutils >/dev/null && \ + apk add --no-cache openssl curl bash jq coreutils gnupg util-linux-misc >/dev/null && \ curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ chmod +x /usr/local/bin/pdsadmin.sh && \ ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin @@ -46,6 +48,8 @@ services: "PDS_BLOBSTORE_DISK_LOCATION=$${PDS_DATA_DIRECTORY}/blocks" \ "PDS_BLOB_UPLOAD_LIMIT=$${PDS_BLOB_UPLOAD_LIMIT}" \ "PDS_DID_PLC_URL=$${PDS_DID_PLC_URL}" \ + "PDS_EMAIL_FROM_ADDRESS=$${PDS_EMAIL_FROM_ADDRESS}"\ + "PDS_EMAIL_SMTP_URL=$${PDS_EMAIL_SMTP_URL"}\ "PDS_BSKY_APP_VIEW_URL=$${PDS_BSKY_APP_VIEW_URL}" \ "PDS_BSKY_APP_VIEW_DID=$${PDS_BSKY_APP_VIEW_DID}" \ "PDS_REPORT_SERVICE_URL=$${PDS_REPORT_SERVICE_URL}" \ From 1d85177ce6acb407ec2274f45b66ca77b139d55b Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Fri, 19 Sep 2025 08:33:23 -0400 Subject: [PATCH 047/322] fix: syntax error on vars Co-authored-by: Mario Neuhold --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 57d515f41..f59d20181 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -49,7 +49,7 @@ services: "PDS_BLOB_UPLOAD_LIMIT=$${PDS_BLOB_UPLOAD_LIMIT}" \ "PDS_DID_PLC_URL=$${PDS_DID_PLC_URL}" \ "PDS_EMAIL_FROM_ADDRESS=$${PDS_EMAIL_FROM_ADDRESS}"\ - "PDS_EMAIL_SMTP_URL=$${PDS_EMAIL_SMTP_URL"}\ + "PDS_EMAIL_SMTP_URL=$${PDS_EMAIL_SMTP_URL}"\ "PDS_BSKY_APP_VIEW_URL=$${PDS_BSKY_APP_VIEW_URL}" \ "PDS_BSKY_APP_VIEW_DID=$${PDS_BSKY_APP_VIEW_DID}" \ "PDS_REPORT_SERVICE_URL=$${PDS_REPORT_SERVICE_URL}" \ From 82df0b29fe9de988696180bd0b0f34b7996328cb Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:44:11 -0400 Subject: [PATCH 048/322] feat: make an empty pds.env file to trick pdsadmin into working correctly This way we don't need the very long command Credits: @madmalkav --- templates/compose/bluesky-pds.yaml | 32 +++++++----------------------- 1 file changed, 7 insertions(+), 25 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index f59d20181..43e4c4078 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -29,38 +29,20 @@ services: - 'PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac}' - 'PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network}' - 'LOG_ENABLED=${LOG_ENABLED:-true}' - command: | + + command: > sh -c ' set -euo pipefail; echo "Installing required packages and pdsadmin..." apk add --no-cache openssl curl bash jq coreutils gnupg util-linux-misc >/dev/null && \ curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ - chmod +x /usr/local/bin/pdsadmin.sh && \ + chmod 700 /usr/local/bin/pdsadmin.sh && \ ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin - - echo "Generating /pds/pds.env..." - printf "%s\n" \ - "PDS_HOSTNAME=$${PDS_HOSTNAME}" \ - "PDS_JWT_SECRET=$${PDS_JWT_SECRET}" \ - "PDS_ADMIN_PASSWORD=$${PDS_ADMIN_PASSWORD}" \ - "PDS_ADMIN_EMAIL=$${PDS_ADMIN_EMAIL}" \ - "PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=$${PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX}" \ - "PDS_DATA_DIRECTORY=$${PDS_DATA_DIRECTORY}" \ - "PDS_BLOBSTORE_DISK_LOCATION=$${PDS_DATA_DIRECTORY}/blocks" \ - "PDS_BLOB_UPLOAD_LIMIT=$${PDS_BLOB_UPLOAD_LIMIT}" \ - "PDS_DID_PLC_URL=$${PDS_DID_PLC_URL}" \ - "PDS_EMAIL_FROM_ADDRESS=$${PDS_EMAIL_FROM_ADDRESS}"\ - "PDS_EMAIL_SMTP_URL=$${PDS_EMAIL_SMTP_URL}"\ - "PDS_BSKY_APP_VIEW_URL=$${PDS_BSKY_APP_VIEW_URL}" \ - "PDS_BSKY_APP_VIEW_DID=$${PDS_BSKY_APP_VIEW_DID}" \ - "PDS_REPORT_SERVICE_URL=$${PDS_REPORT_SERVICE_URL}" \ - "PDS_REPORT_SERVICE_DID=$${PDS_REPORT_SERVICE_DID}" \ - "PDS_CRAWLERS=$${PDS_CRAWLERS}" \ - "LOG_ENABLED=$${LOG_ENABLED}" \ - > /pds/pds.env - - echo "Launching PDS..." + echo "Creating an empty pds.env file so pdsadmin works..." + touch ${PDS_DATA_DIRECTORY}/pds.env + echo "Launching PDS, enjoy!..." exec node --enable-source-maps index.js ' + healthcheck: test: - CMD From 2250c4a6936f48b6c26b964ecff956093e5d1102 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:52:54 -0400 Subject: [PATCH 049/322] fix: remove the SERVICE_EMAIL_ADMIN and make it normal --- templates/compose/bluesky-pds.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 43e4c4078..4d622074d 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -15,13 +15,13 @@ services: - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' - 'PDS_JWT_SECRET=${SERVICE_HEX_32_JWTSECRET}' - 'PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN}' - - 'PDS_ADMIN_EMAIL=${SERVICE_EMAIL_ADMIN}' + - 'PDS_ADMIN_EMAIL=${PDS_ADMIN_EMAIL}' - 'PDS_PLC_ROTATION_KEY_K256_PRIVATE_KEY_HEX=${SERVICE_HEX_32_ROTATIONKEY}' - 'PDS_DATA_DIRECTORY=${PDS_DATA_DIRECTORY:-/pds}' - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - - 'PDS_EMAIL_FROM_ADDRESS=${SERVICE_EMAIL_ADMIN}' + - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS}' - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' From 5b1485a04ba61baad2cecf4d5b2f77d3161694ed Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 00:57:56 -0400 Subject: [PATCH 050/322] feat: not many know how to setup this without reading pds docs --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 4d622074d..74e3bb1e4 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -22,7 +22,7 @@ services: - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS}' - - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL}' + - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL:-smtps://username:password@smtp.example.com/}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' From 0225c486ffb987ddc6373f09d985091c66766278 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 01:10:00 -0400 Subject: [PATCH 051/322] fix: both email envs are needed in order for the PDS to start, so set the other one as required --- templates/compose/bluesky-pds.yaml | 26 ++++++++++---------------- 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 74e3bb1e4..da3dcfb65 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -1,15 +1,8 @@ -# documentation: https://github.com/bluesky-social/pds -# slogan: Bluesky PDS (Personal Data Server) -# category: backend -# tags: bluesky, pds, platform -# logo: svgs/bluesky.svg -# port: 3000 - services: pds: image: 'ghcr.io/bluesky-social/pds:latest' volumes: - - './pds-data:/pds' + - 'pds-data:/pds' environment: - SERVICE_FQDN_PDS_3000 - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' @@ -21,7 +14,7 @@ services: - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS}' + - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS:?}' - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL:-smtps://username:password@smtp.example.com/}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' @@ -29,20 +22,19 @@ services: - 'PDS_REPORT_SERVICE_DID=${PDS_REPORT_SERVICE_DID:-did:plc:ar7c4by46qjdydhdevvrndac}' - 'PDS_CRAWLERS=${PDS_CRAWLERS:-https://bsky.network}' - 'LOG_ENABLED=${LOG_ENABLED:-true}' - - command: > + command: | sh -c ' - set -euo pipefail; echo "Installing required packages and pdsadmin..." - apk add --no-cache openssl curl bash jq coreutils gnupg util-linux-misc >/dev/null && \ - curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh && \ - chmod 700 /usr/local/bin/pdsadmin.sh && \ + set -euo pipefail + echo "Installing required packages and pdsadmin..." + apk add --no-cache openssl curl bash jq coreutils gnupg util-linux-misc >/dev/null + curl -o /usr/local/bin/pdsadmin.sh https://raw.githubusercontent.com/bluesky-social/pds/main/pdsadmin.sh + chmod 700 /usr/local/bin/pdsadmin.sh ln -sf /usr/local/bin/pdsadmin.sh /usr/local/bin/pdsadmin echo "Creating an empty pds.env file so pdsadmin works..." touch ${PDS_DATA_DIRECTORY}/pds.env echo "Launching PDS, enjoy!..." exec node --enable-source-maps index.js ' - healthcheck: test: - CMD @@ -52,3 +44,5 @@ services: interval: 2s timeout: 10s retries: 10 +volumes: + pds-data: From a33a753e5f1278c9abd560f324876d15d2817072 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 01:10:42 -0400 Subject: [PATCH 052/322] fix: add back template info --- templates/compose/bluesky-pds.yaml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index da3dcfb65..45a00ba31 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -1,3 +1,10 @@ +# documentation: https://github.com/bluesky-social/pds +# slogan: Bluesky PDS (Personal Data Server) +# category: backend +# tags: bluesky, pds, platform +# logo: svgs/bluesky.svg +# port: 3000 + services: pds: image: 'ghcr.io/bluesky-social/pds:latest' From 3a51b5e908ebadcaacda068269e4cdc034dc9301 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 01:19:33 -0400 Subject: [PATCH 053/322] feat: make the other email env also required --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 45a00ba31..ade8efbfb 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -22,7 +22,7 @@ services: - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS:?}' - - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL:-smtps://username:password@smtp.example.com/}' + - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL:?smtps://username:password@smtp.example.com/}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' From 1f8b24a11d12dd3a7e9a0a121af989c85d77fb2d Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 10:22:56 -0400 Subject: [PATCH 054/322] =?UTF-8?q?fix:=20healthcheck=20doesn=E2=80=99t=20?= =?UTF-8?q?need=20to=20be=205s?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index ade8efbfb..aa5398480 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -48,7 +48,7 @@ services: - wget - '--spider' - 'http://127.0.0.1:3000/xrpc/_health' - interval: 2s + interval: 5s timeout: 10s retries: 10 volumes: From ecf575e781ac6d4ed835e4e911ce5d4ce38d738d Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:27:03 -0400 Subject: [PATCH 055/322] fix: make email envs not required --- templates/compose/bluesky-pds.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index aa5398480..7fabec624 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -21,8 +21,8 @@ services: - 'PDS_BLOBSTORE_DISK_LOCATION=${PDS_DATA_DIRECTORY:-/pds}/blocks' - 'PDS_BLOB_UPLOAD_LIMIT=${PDS_BLOB_UPLOAD_LIMIT:-104857600}' - 'PDS_DID_PLC_URL=${PDS_DID_PLC_URL:-https://plc.directory}' - - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS:?}' - - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL:?smtps://username:password@smtp.example.com/}' + - 'PDS_EMAIL_FROM_ADDRESS=${PDS_EMAIL_FROM_ADDRESS}' + - 'PDS_EMAIL_SMTP_URL=${PDS_EMAIL_SMTP_URL}' - 'PDS_BSKY_APP_VIEW_URL=${PDS_BSKY_APP_VIEW_URL:-https://api.bsky.app}' - 'PDS_BSKY_APP_VIEW_DID=${PDS_BSKY_APP_VIEW_DID:-did:web:api.bsky.app}' - 'PDS_REPORT_SERVICE_URL=${PDS_REPORT_SERVICE_URL:-https://mod.bsky.app/xrpc/com.atproto.moderation.createReport}' From 58668203852d87c2b95363dce0916d8c398767f5 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Sat, 20 Sep 2025 11:32:56 -0400 Subject: [PATCH 056/322] fix: domain on coolify --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 7fabec624..0528ce30b 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -11,7 +11,7 @@ services: volumes: - 'pds-data:/pds' environment: - - SERVICE_FQDN_PDS_3000 + - SERVICE_URL_PDS_3000 - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' - 'PDS_JWT_SECRET=${SERVICE_HEX_32_JWTSECRET}' - 'PDS_ADMIN_PASSWORD=${SERVICE_PASSWORD_ADMIN}' From 0dc67ffd3dfac3098431578e094105e2ce20f56c Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Mon, 22 Sep 2025 01:44:55 -0400 Subject: [PATCH 057/322] refactor: volumes set back to ./pds-data:/pds --- templates/compose/bluesky-pds.yaml | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index 0528ce30b..067d2628b 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -9,7 +9,7 @@ services: pds: image: 'ghcr.io/bluesky-social/pds:latest' volumes: - - 'pds-data:/pds' + - './pds-data:/pds' environment: - SERVICE_URL_PDS_3000 - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' @@ -51,5 +51,3 @@ services: interval: 5s timeout: 10s retries: 10 -volumes: - pds-data: From aea61bcb7ace07e4af9621bb81f4b37e4e3381ee Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Fri, 26 Sep 2025 20:56:45 +0530 Subject: [PATCH 058/322] Fixed server pub base url for elastic kibana service --- templates/compose/elasticsearch-with-kibana.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/elasticsearch-with-kibana.yaml b/templates/compose/elasticsearch-with-kibana.yaml index b04594690..f200d2813 100644 --- a/templates/compose/elasticsearch-with-kibana.yaml +++ b/templates/compose/elasticsearch-with-kibana.yaml @@ -35,7 +35,7 @@ services: - 'KIBANA_PASSWORD=${SERVICE_PASSWORD_KIBANA}' - 'ELASTICSEARCH_SERVICEACCOUNTTOKEN=${ELASTICSEARCH_SERVICEACCOUNTTOKEN}' # Kibana authenticates to Elasticsearch using this service token - 'SERVER_NAME=${SERVICE_FQDN_KIBANA}' # For generating links and setting cookie domains - - 'SERVER_PUBLICBASEURL=${SERVICE_URL_KIBANA}' # Public URL used in generated links (reporting, alerting, etc.) + - 'SERVER_PUBLICBASEURL=${SERVICE_FQDN_KIBANA}' # Public URL used in generated links (reporting, alerting, etc.) - 'ELASTICSEARCH_HOSTS=http://elasticsearch:9200' # Connect Kibana to Elasticsearch Service - XPACK.SECURITY.ENABLED=true # Enable authentication and authorization (required for service tokens, roles, etc.) - 'XPACK_SECURITY_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKSECURITY}' # Required for encrypted session & auth tokens From 526b956dc6e3543bf252602b27529a9e79f7ffab Mon Sep 17 00:00:00 2001 From: Evan Schleret Date: Sat, 27 Sep 2025 04:00:56 +0200 Subject: [PATCH 059/322] feat: Add mail environment variables to docmost.yaml --- templates/compose/docmost.yaml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/templates/compose/docmost.yaml b/templates/compose/docmost.yaml index 8e982913c..4a996973e 100644 --- a/templates/compose/docmost.yaml +++ b/templates/compose/docmost.yaml @@ -19,6 +19,15 @@ services: - APP_URL=$SERVICE_URL_DOCMOST_3000 - DATABASE_URL=postgresql://$SERVICE_USER_POSTGRES:$SERVICE_PASSWORD_POSTGRES@postgresql/docmost?schema=public - REDIS_URL=redis://redis:6379 + - MAIL_DRIVER=${MAIL_DRIVER} + - SMTP_HOST=${SMTP_HOST} + - SMTP_PORT=${SMTP_PORT} + - SMTP_USERNAME=${SMTP_USERNAME} + - SMTP_PASSWORD=${SMTP_PASSWORD} + - SMTP_SECURE=${SMTP_SECURE} + - MAIL_FROM_ADDRESS=${MAIL_FROM_ADDRESS} + - MAIL_FROM_NAME=${MAIL_FROM_NAME} + - POSTMARK_TOKEN=${POSTMARK_TOKEN} volumes: - "docmost:/app/data/storage" healthcheck: From 8884ac378dd268c9ce57e81426af5e1545249dbd Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Mon, 29 Sep 2025 04:21:17 +0530 Subject: [PATCH 060/322] Removed /ping from checkhealth on traccar service Fixes no available server error --- templates/compose/traccar.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/traccar.yaml b/templates/compose/traccar.yaml index 1a4e1724c..0b914d6e2 100644 --- a/templates/compose/traccar.yaml +++ b/templates/compose/traccar.yaml @@ -30,7 +30,7 @@ services: postgres: condition: service_healthy healthcheck: - test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8082/ping"] + test: ["CMD", "wget", "--no-verbose", "--tries=1", "--spider", "http://127.0.0.1:8082"] interval: 30s timeout: 10s retries: 3 From 9dd8709407c62de2b971a855028f8b7ef2398049 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Sep 2025 10:52:08 +0000 Subject: [PATCH 061/322] docs: update changelog --- CHANGELOG.md | 76 +++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 72 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 04b99c646..3447b223b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,10 +4,40 @@ # Changelog ## [unreleased] +### 🚀 Features + +- *(application)* Implement order-based pattern matching for watch paths with negation support +- *(github)* Enhance Docker Compose input fields for better user experience +- *(dev-seeders)* Add PersonalAccessTokenSeeder to create development API tokens +- *(application)* Add conditional .env file creation for Symfony apps during PHP deployment +- *(application)* Enhance watch path parsing to support negation syntax +- *(application)* Add normalizeWatchPaths method to improve watch path handling +- *(validation)* Enhance ValidGitRepositoryUrl to support additional safe characters and add comprehensive unit tests for various Git repository URL formats +- *(deployment)* Implement detection for Laravel/Symfony frameworks and configure NIXPACKS PHP environment variables accordingly + ### 🐛 Bug Fixes -- *(docker)* Adjust openssh-client installation in Dockerfile to avoid version bug -- *(docker)* Streamline openssh-client installation in Dockerfile +- *(application)* Restrict GitHub-based application settings to non-public repositories +- *(traits)* Update saved_outputs handling in ExecuteRemoteCommand to use collection methods for better performance +- *(application)* Enhance domain handling by replacing both dots and dashes with underscores for HTML form binding +- *(constants)* Reduce command timeout from 7200 to 3600 seconds for improved performance +- *(github)* Update repository URL to point to the v4.x branch for development +- *(models)* Update sorting of scheduled database backups to order by creation date instead of name +- *(socialite)* Add custom base URL support for GitLab provider in OAuth settings +- *(configuration-checker)* Update message to clarify redeployment requirement for configuration changes +- *(application)* Reduce docker stop timeout from 30 to 10 seconds for improved application shutdown efficiency +- *(application)* Increase docker stop timeout from 10 to 30 seconds for better application shutdown handling +- *(validation)* Update git:// URL validation to support port numbers and tilde characters in paths +- Resolve scroll lock issue after closing quick search modal with escape key +- Prevent quick search modal duplication from keyboard shortcuts + +### 🚜 Refactor + +- *(tests)* Simplify matchWatchPaths tests and update implementation for better clarity +- *(deployment)* Improve environment variable handling in ApplicationDeploymentJob +- *(deployment)* Remove commented-out code and streamline environment variable handling in ApplicationDeploymentJob +- *(application)* Improve handling of docker compose domains by normalizing keys and ensuring valid JSON structure +- *(forms)* Update wire:model bindings to use 'blur' instead of 'blur-sm' for input fields across multiple views ### 📚 Documentation @@ -15,20 +45,58 @@ ### 📚 Documentation ### ⚙️ Miscellaneous Tasks -- *(versions)* Increment coolify version numbers to 4.0.0-beta.431 and 4.0.0-beta.432 in configuration files +- *(application)* Remove debugging statement from loadComposeFile method +- *(workflows)* Update Claude GitHub Action configuration to support new event types and improve permissions + +## [4.0.0-beta.431] - 2025-09-24 + +### 📚 Documentation + +- Update changelog ## [4.0.0-beta.430] - 2025-09-24 +### 🚀 Features + +- *(add-watch-paths-for-services)* Show watch paths field for docker compose applications + ### 🐛 Bug Fixes - *(PreviewCompose)* Adds port to preview urls - *(deployment-job)* Enhance build time variable analysis +- *(docker)* Adjust openssh-client installation in Dockerfile to avoid version bug +- *(docker)* Streamline openssh-client installation in Dockerfile +- *(team)* Normalize email case in invite link generation +- *(README)* Update Juxtdigital description to reflect current services +- *(environment-variable-warning)* Enhance warning logic to check for problematic variable values +- *(install)* Ensure proper quoting of environment file paths to prevent issues with spaces +- *(security)* Implement authorization checks for terminal access management +- *(ui)* Improve mobile sidebar close behavior + +### 🚜 Refactor + +- *(installer)* Improve install script +- *(upgrade)* Improve upgrade script +- *(installer, upgrade)* Enhance environment variable management +- *(upgrade)* Enhance logging and quoting in upgrade scripts +- *(upgrade)* Replace warning div with a callout component for better UI consistency +- *(ui)* Replace warning and error divs with callout components for improved consistency and readability +- *(ui)* Improve styling and consistency in environment variable warning and docker cleanup components +- *(security)* Streamline update check functionality and improve UI button interactions in patches view ### 📚 Documentation - Update changelog - Update changelog +### ⚙️ Miscellaneous Tasks + +- *(versions)* Increment coolify version numbers to 4.0.0-beta.431 and 4.0.0-beta.432 in configuration files +- *(versions)* Update coolify version numbers to 4.0.0-beta.432 and 4.0.0-beta.433 in configuration files +- Remove unused files +- Adjust wording +- *(workflow)* Update pull request trigger to pull_request_target and refine permissions for enhanced security + ## [4.0.0-beta.429] - 2025-09-23 ### 🚀 Features @@ -39,6 +107,7 @@ ### 🚀 Features - *(search)* Enable query logging for global search caching - *(environment)* Add dynamic checkbox options for environment variable settings based on user permissions and variable types - *(redaction)* Implement sensitive information redaction in logs and commands +- Improve detection of special network modes - *(api)* Add endpoint to update backup configuration by UUID and backup ID; modify response to include backup id - *(databases)* Enhance backup management API with new endpoints and improved data handling - *(github)* Add GitHub app management endpoints @@ -119,7 +188,6 @@ ## [4.0.0-beta.427] - 2025-09-15 ### 🚀 Features -- Improve detection of special network modes - *(command)* Add option to sync GitHub releases to BunnyCDN and refactor sync logic - *(ui)* Display current version in settings dropdown and update UI accordingly - *(settings)* Add option to restrict PR deployments to repository members and contributors From 11260cb13c1f5ef7e7d02857fae6efae66168f2e Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:06:49 +0200 Subject: [PATCH 062/322] fix(workflows): update CLAUDE API key reference in GitHub Actions workflow --- .github/workflows/claude.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index b0fc41448..bf0e6bedc 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -38,7 +38,7 @@ jobs: id: claude uses: anthropics/claude-code-action@v1 with: - anthropic_api_key: ${{ secrets.ANTHROPIC_API_KEY }} + anthropic_api_key: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} # Optional: Customize the trigger phrase (default: @claude) # trigger_phrase: "/claude" From c3027a0c8741a00072324d324b84970656366e96 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Mon, 29 Sep 2025 15:11:18 +0200 Subject: [PATCH 063/322] Update claude.yml --- .github/workflows/claude.yml | 49 +++++++++++++++++++----------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index bf0e6bedc..9daf0e90e 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -6,9 +6,7 @@ on: pull_request_review_comment: types: [created] issues: - types: [opened, assigned, labeled] - pull_request: - types: [labeled] + types: [opened, assigned] pull_request_review: types: [submitted] @@ -20,12 +18,12 @@ jobs: (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || (github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'Claude') || (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'Claude') || - (github.event_name == 'issues' && github.event.action != 'labeled' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) + (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: - contents: write - pull-requests: write - issues: write + contents: read + pull-requests: read + issues: read id-token: write actions: read # Required for Claude to read CI results on PRs steps: @@ -40,23 +38,28 @@ jobs: with: anthropic_api_key: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + # This is an optional setting that allows Claude to read CI results on PRs + additional_permissions: | + actions: read + + # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1) + # model: "claude-opus-4-1-20250805" + # Optional: Customize the trigger phrase (default: @claude) # trigger_phrase: "/claude" - + # Optional: Trigger when specific user is assigned to an issue # assignee_trigger: "claude-bot" - - # Optional: Configure Claude's behavior with CLI arguments - # claude_args: | - # --model claude-opus-4-1-20250805 - # --max-turns 10 - # --allowedTools "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)" - # --system-prompt "Follow our coding standards. Ensure all new code has tests. Use TypeScript for new files." - - # Optional: Advanced settings configuration - # settings: | - # { - # "env": { - # "NODE_ENV": "test" - # } - # } \ No newline at end of file + + # Optional: Allow Claude to run specific commands + # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)" + + # Optional: Add custom instructions for Claude to customize its behavior for your project + # custom_instructions: | + # Follow our coding standards + # Ensure all new code has tests + # Use TypeScript for new files + + # Optional: Custom environment variables for Claude + # claude_env: | + # NODE_ENV: test From e96b2fe220b152b0a9aa43b81152c7f6fadbb45f Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Mon, 29 Sep 2025 22:26:43 +0100 Subject: [PATCH 064/322] Add Swetrix service --- public/svgs/swetrix.svg | 8 ++ templates/compose/swetrix.yaml | 165 +++++++++++++++++++++++++++++++++ 2 files changed, 173 insertions(+) create mode 100644 public/svgs/swetrix.svg create mode 100644 templates/compose/swetrix.yaml diff --git a/public/svgs/swetrix.svg b/public/svgs/swetrix.svg new file mode 100644 index 000000000..8bb5bfdfa --- /dev/null +++ b/public/svgs/swetrix.svg @@ -0,0 +1,8 @@ + + + + + + + \ No newline at end of file diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml new file mode 100644 index 000000000..756a96839 --- /dev/null +++ b/templates/compose/swetrix.yaml @@ -0,0 +1,165 @@ +# documentation: https://docs.swetrix.com/selfhosting/how-to +# slogan: Privacy-friendly and cookieless European web analytics alternative to Google Analytics. +# category: analytics +# tags: analytics,privacy,monitoring,open-source,clickhouse,redis +# logo: svgs/swetrix.svg +# port: 3000 + +services: + swetrix: + image: swetrix/swetrix-fe:v4.0.2 + restart: always + depends_on: + - swetrix-api + environment: + # Required - public URL of the API service (e.g. https://swetrix-api.example.com) + - API_URL=${API_URL:?} + healthcheck: + test: + - CMD-SHELL + - wget --no-verbose --tries=1 --spider http://localhost:3000/ping || exit 1 + interval: 30s + start_period: 15s + + swetrix-api: + image: swetrix/swetrix-api:v4.0.2 + restart: always + environment: + # Required + - SECRET_KEY_BASE=${SECRET_KEY_BASE:?} + + # Optional + - DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false} + - IP_GEOLOCATION_DB_PATH=${IP_GEOLOCATION_DB_PATH:-} + - DEBUG_MODE=${DEBUG_MODE:-false} + - CLOUDFLARE_PROXY_ENABLED=${CLOUDFLARE_PROXY_ENABLED:-false} + + # SMTP (optional) + - SMTP_HOST=${SMTP_HOST:-} + - SMTP_PORT=${SMTP_PORT:-} + - SMTP_USER=${SMTP_USER:-} + - SMTP_PASSWORD=${SMTP_PASSWORD:-} + - FROM_EMAIL=${FROM_EMAIL:-} + - SMTP_MOCK=${SMTP_MOCK:-false} + + # OIDC (optional) + - OIDC_ENABLED=${OIDC_ENABLED:-false} + - OIDC_ONLY_AUTH=${OIDC_ONLY_AUTH:-false} + - OIDC_DISCOVERY_URL=${OIDC_DISCOVERY_URL:-} + - OIDC_CLIENT_ID=${OIDC_CLIENT_ID:-} + - OIDC_CLIENT_SECRET=${OIDC_CLIENT_SECRET:-} + + # Required service endpoints + - REDIS_HOST=redis + - CLICKHOUSE_HOST=http://clickhouse + - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-} + depends_on: + redis: + condition: service_healthy + clickhouse: + condition: service_healthy + healthcheck: + test: + - CMD-SHELL + - wget --no-verbose --tries=1 --spider http://localhost:5005/ping || exit 1 + interval: 30s + start_period: 15s + + redis: + image: redis:8.2-alpine + restart: always + environment: + - REDIS_PORT=${REDIS_PORT:-6379} + - REDIS_USER=${REDIS_USER:-default} + - REDIS_PASSWORD=${REDIS_PASSWORD:-} + healthcheck: + test: + - CMD-SHELL + - redis-cli ping | grep PONG + interval: 30s + start_period: 1m + + clickhouse: + image: clickhouse/clickhouse-server:24.10-alpine + restart: always + environment: + - CLICKHOUSE_DATABASE=${CLICKHOUSE_DATABASE:-analytics} + - CLICKHOUSE_USER=${CLICKHOUSE_USER:-default} + - CLICKHOUSE_PORT=${CLICKHOUSE_PORT:-8123} + - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-} + healthcheck: + test: + - CMD-SHELL + - wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1 + interval: 30s + start_period: 1m + cap_add: + - SYS_NICE + volumes: + # Persistent storage for ClickHouse + - swetrix-events-data:/var/lib/clickhouse + + # Disable logging + - type: bind + source: ./disable-user-logging.xml + target: /etc/clickhouse-server/users.d/disable-user-logging.xml + read_only: true + content: | + + + + 0 + 0 + + + + - type: bind + source: ./reduce-logs.xml + target: /etc/clickhouse-server/config.d/reduce-logs.xml + read_only: true + content: | + + + warning + true + + + + + + + + + + + + # Reduce RAM usage + - type: bind + source: ./preserve-ram-config.xml + target: /etc/clickhouse-server/config.d/preserve-ram-config.xml + read_only: true + content: | + + 536870912 + 1 + + - type: bind + source: ./preserve-ram-user.xml + target: /etc/clickhouse-server/users.d/preserve-ram-user.xml + read_only: true + content: | + + + + 2048 + 1 + 0 + 0 + + + + + ulimits: + nofile: + soft: 262144 + hard: 262144 From a897e81566c41c07c545aa70fe5af7257e4be295 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 30 Sep 2025 13:37:03 +0200 Subject: [PATCH 065/322] feat(global-search): integrate projects and environments into global search functionality - Added retrieval and mapping of projects and environments to the global search results. - Enhanced search result structure to include resource counts and descriptions for projects and environments. - Updated the UI to reflect the new search capabilities, improving user experience when searching for resources. --- app/Livewire/GlobalSearch.php | 74 ++++++++- app/Models/Environment.php | 2 + app/Models/Project.php | 2 + app/Traits/ClearsGlobalSearchCache.php | 134 ++++++++++------ .../views/livewire/global-search.blade.php | 150 ++++++++---------- 5 files changed, 231 insertions(+), 131 deletions(-) diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index dacc0d4db..15de5d838 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -3,6 +3,8 @@ namespace App\Livewire; use App\Models\Application; +use App\Models\Environment; +use App\Models\Project; use App\Models\Server; use App\Models\Service; use App\Models\StandaloneClickhouse; @@ -335,11 +337,81 @@ private function loadSearchableItems() ]; }); + // Get all projects + $projects = Project::ownedByCurrentTeam() + ->withCount(['environments', 'applications', 'services']) + ->get() + ->map(function ($project) { + $resourceCount = $project->applications_count + $project->services_count; + $resourceSummary = $resourceCount > 0 + ? "{$resourceCount} resource".($resourceCount !== 1 ? 's' : '') + : 'No resources'; + + return [ + 'id' => $project->id, + 'name' => $project->name, + 'type' => 'project', + 'uuid' => $project->uuid, + 'description' => $project->description, + 'link' => $project->navigateTo(), + 'project' => null, + 'environment' => null, + 'resource_count' => $resourceSummary, + 'environment_count' => $project->environments_count, + 'search_text' => strtolower($project->name.' '.$project->description.' project'), + ]; + }); + + // Get all environments + $environments = Environment::query() + ->whereHas('project', function ($query) { + $query->where('team_id', auth()->user()->currentTeam()->id); + }) + ->with('project') + ->withCount(['applications', 'services']) + ->get() + ->map(function ($environment) { + $resourceCount = $environment->applications_count + $environment->services_count; + $resourceSummary = $resourceCount > 0 + ? "{$resourceCount} resource".($resourceCount !== 1 ? 's' : '') + : 'No resources'; + + // Build description with project context + $descriptionParts = []; + if ($environment->project) { + $descriptionParts[] = "Project: {$environment->project->name}"; + } + if ($environment->description) { + $descriptionParts[] = $environment->description; + } + if (empty($descriptionParts)) { + $descriptionParts[] = $resourceSummary; + } + + return [ + 'id' => $environment->id, + 'name' => $environment->name, + 'type' => 'environment', + 'uuid' => $environment->uuid, + 'description' => implode(' • ', $descriptionParts), + 'link' => route('project.resource.index', [ + 'project_uuid' => $environment->project->uuid, + 'environment_uuid' => $environment->uuid, + ]), + 'project' => $environment->project->name ?? null, + 'environment' => null, + 'resource_count' => $resourceSummary, + 'search_text' => strtolower($environment->name.' '.$environment->description.' '.$environment->project->name.' environment'), + ]; + }); + // Merge all collections $items = $items->merge($applications) ->merge($services) ->merge($databases) - ->merge($servers); + ->merge($servers) + ->merge($projects) + ->merge($environments); return $items->toArray(); }); diff --git a/app/Models/Environment.php b/app/Models/Environment.php index 437be7d87..bfeee01c9 100644 --- a/app/Models/Environment.php +++ b/app/Models/Environment.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Traits\ClearsGlobalSearchCache; use App\Traits\HasSafeStringAttribute; use OpenApi\Attributes as OA; @@ -19,6 +20,7 @@ )] class Environment extends BaseModel { + use ClearsGlobalSearchCache; use HasSafeStringAttribute; protected $guarded = []; diff --git a/app/Models/Project.php b/app/Models/Project.php index 1c46042e3..a9bf76803 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -2,6 +2,7 @@ namespace App\Models; +use App\Traits\ClearsGlobalSearchCache; use App\Traits\HasSafeStringAttribute; use OpenApi\Attributes as OA; use Visus\Cuid2\Cuid2; @@ -24,6 +25,7 @@ )] class Project extends BaseModel { + use ClearsGlobalSearchCache; use HasSafeStringAttribute; protected $guarded = []; diff --git a/app/Traits/ClearsGlobalSearchCache.php b/app/Traits/ClearsGlobalSearchCache.php index ae587aa87..b9af70aba 100644 --- a/app/Traits/ClearsGlobalSearchCache.php +++ b/app/Traits/ClearsGlobalSearchCache.php @@ -10,77 +10,119 @@ trait ClearsGlobalSearchCache protected static function bootClearsGlobalSearchCache() { static::saving(function ($model) { - // Only clear cache if searchable fields are being changed - if ($model->hasSearchableChanges()) { - $teamId = $model->getTeamIdForCache(); - if (filled($teamId)) { - GlobalSearch::clearTeamCache($teamId); + try { + // Only clear cache if searchable fields are being changed + if ($model->hasSearchableChanges()) { + $teamId = $model->getTeamIdForCache(); + if (filled($teamId)) { + GlobalSearch::clearTeamCache($teamId); + } } + } catch (\Throwable $e) { + // Silently fail cache clearing - don't break the save operation + ray('Failed to clear global search cache on saving: '.$e->getMessage()); } }); static::created(function ($model) { - // Always clear cache when model is created - $teamId = $model->getTeamIdForCache(); - if (filled($teamId)) { - GlobalSearch::clearTeamCache($teamId); + try { + // Always clear cache when model is created + $teamId = $model->getTeamIdForCache(); + if (filled($teamId)) { + GlobalSearch::clearTeamCache($teamId); + } + } catch (\Throwable $e) { + // Silently fail cache clearing - don't break the create operation + ray('Failed to clear global search cache on creation: '.$e->getMessage()); } }); static::deleted(function ($model) { - // Always clear cache when model is deleted - $teamId = $model->getTeamIdForCache(); - if (filled($teamId)) { - GlobalSearch::clearTeamCache($teamId); + try { + // Always clear cache when model is deleted + $teamId = $model->getTeamIdForCache(); + if (filled($teamId)) { + GlobalSearch::clearTeamCache($teamId); + } + } catch (\Throwable $e) { + // Silently fail cache clearing - don't break the delete operation + ray('Failed to clear global search cache on deletion: '.$e->getMessage()); } }); } private function hasSearchableChanges(): bool { - // Define searchable fields based on model type - $searchableFields = ['name', 'description']; + try { + // Define searchable fields based on model type + $searchableFields = ['name', 'description']; - // Add model-specific searchable fields - if ($this instanceof \App\Models\Application) { - $searchableFields[] = 'fqdn'; - $searchableFields[] = 'docker_compose_domains'; - } elseif ($this instanceof \App\Models\Server) { - $searchableFields[] = 'ip'; - } elseif ($this instanceof \App\Models\Service) { - // Services don't have direct fqdn, but name and description are covered - } - // Database models only have name and description as searchable - - // Check if any searchable field is dirty - foreach ($searchableFields as $field) { - if ($this->isDirty($field)) { - return true; + // Add model-specific searchable fields + if ($this instanceof \App\Models\Application) { + $searchableFields[] = 'fqdn'; + $searchableFields[] = 'docker_compose_domains'; + } elseif ($this instanceof \App\Models\Server) { + $searchableFields[] = 'ip'; + } elseif ($this instanceof \App\Models\Service) { + // Services don't have direct fqdn, but name and description are covered + } elseif ($this instanceof \App\Models\Project || $this instanceof \App\Models\Environment) { + // Projects and environments only have name and description as searchable } - } + // Database models only have name and description as searchable - return false; + // Check if any searchable field is dirty + foreach ($searchableFields as $field) { + // Check if attribute exists before checking if dirty + if (array_key_exists($field, $this->getAttributes()) && $this->isDirty($field)) { + return true; + } + } + + return false; + } catch (\Throwable $e) { + // If checking changes fails, assume changes exist to be safe + ray('Failed to check searchable changes: '.$e->getMessage()); + + return true; + } } private function getTeamIdForCache() { - // For database models, team is accessed through environment.project.team - if (method_exists($this, 'team')) { - if ($this instanceof \App\Models\Server) { - $team = $this->team; - } else { - $team = $this->team(); + try { + // For Project models (has direct team_id) + if ($this instanceof \App\Models\Project) { + return $this->team_id ?? null; } - if (filled($team)) { - return is_object($team) ? $team->id : null; + + // For Environment models (get team_id through project) + if ($this instanceof \App\Models\Environment) { + return $this->project?->team_id; } - } - // For models with direct team_id property - if (property_exists($this, 'team_id') || isset($this->team_id)) { - return $this->team_id; - } + // For database models, team is accessed through environment.project.team + if (method_exists($this, 'team')) { + if ($this instanceof \App\Models\Server) { + $team = $this->team; + } else { + $team = $this->team(); + } + if (filled($team)) { + return is_object($team) ? $team->id : null; + } + } - return null; + // For models with direct team_id property + if (property_exists($this, 'team_id') || isset($this->team_id)) { + return $this->team_id ?? null; + } + + return null; + } catch (\Throwable $e) { + // If we can't determine team ID, return null + ray('Failed to get team ID for cache: '.$e->getMessage()); + + return null; + } } } diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 0b9b61da4..2addf6f64 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -80,41 +80,42 @@ + From 890f0765726021f534e9bbd04da21e311ad1c43f Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Tue, 30 Sep 2025 15:13:14 +0200 Subject: [PATCH 066/322] refactor(dashboard): replace project navigation method with direct link in UI - Removed the navigateToProject method from the Livewire component. - Updated the dashboard view to use anchor tags for project navigation, enhancing user experience and simplifying the code structure. --- app/Livewire/Dashboard.php | 5 ----- resources/views/livewire/dashboard.blade.php | 12 ++++++------ 2 files changed, 6 insertions(+), 11 deletions(-) diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index 45781af30..a78804a16 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -23,11 +23,6 @@ public function mount() $this->projects = Project::ownedByCurrentTeam()->get(); } - public function navigateToProject($projectUuid) - { - return $this->redirect(collect($this->projects)->firstWhere('uuid', $projectUuid)->navigateTo(), navigate: false); - } - public function render() { return view('livewire.dashboard'); diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 67beb3aa7..2c581850d 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -19,8 +19,8 @@ @if ($projects->count() > 0)

@foreach ($projects as $project) -
+
+
{{ $project->name }}
@@ -28,20 +28,20 @@ {{ $project->description }}
-
+
@if ($project->environments->first()) @can('createAnyResource') - - + Add Resource + + Add Resource @endcan @endif @can('update', $project) - Settings From 8745054adfe9ba7724efdabbfb692bd890bb299f Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:00:06 +0100 Subject: [PATCH 067/322] add timeout / retries to healthchecks --- templates/compose/swetrix.yaml | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 756a96839..2482ac5e9 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -18,6 +18,8 @@ services: test: - CMD-SHELL - wget --no-verbose --tries=1 --spider http://localhost:3000/ping || exit 1 + timeout: 5s + retries: 10 interval: 30s start_period: 15s @@ -62,6 +64,8 @@ services: test: - CMD-SHELL - wget --no-verbose --tries=1 --spider http://localhost:5005/ping || exit 1 + timeout: 5s + retries: 10 interval: 30s start_period: 15s @@ -76,6 +80,8 @@ services: test: - CMD-SHELL - redis-cli ping | grep PONG + timeout: 5s + retries: 10 interval: 30s start_period: 1m @@ -91,6 +97,8 @@ services: test: - CMD-SHELL - wget --no-verbose --tries=1 -O - http://127.0.0.1:8123/ping || exit 1 + timeout: 5s + retries: 10 interval: 30s start_period: 1m cap_add: From 8ef759ff0a00f95803cf230751daa51b7a6b710f Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:01:02 +0100 Subject: [PATCH 068/322] Use magic variable for Clickhouse password --- templates/compose/swetrix.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 2482ac5e9..035d96a31 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -54,7 +54,7 @@ services: # Required service endpoints - REDIS_HOST=redis - CLICKHOUSE_HOST=http://clickhouse - - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-} + - CLICKHOUSE_PASSWORD=$SERVICE_PASSWORD_CLICKHOUSE depends_on: redis: condition: service_healthy @@ -92,7 +92,7 @@ services: - CLICKHOUSE_DATABASE=${CLICKHOUSE_DATABASE:-analytics} - CLICKHOUSE_USER=${CLICKHOUSE_USER:-default} - CLICKHOUSE_PORT=${CLICKHOUSE_PORT:-8123} - - CLICKHOUSE_PASSWORD=${CLICKHOUSE_PASSWORD:-} + - CLICKHOUSE_PASSWORD=$SERVICE_PASSWORD_CLICKHOUSE healthcheck: test: - CMD-SHELL From 0a35594508d246509cc843284b4e8a6ffbf59206 Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:02:29 +0100 Subject: [PATCH 069/322] Use magic variable for Redis password --- templates/compose/swetrix.yaml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 035d96a31..60f523a57 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -55,6 +55,7 @@ services: - REDIS_HOST=redis - CLICKHOUSE_HOST=http://clickhouse - CLICKHOUSE_PASSWORD=$SERVICE_PASSWORD_CLICKHOUSE + - REDIS_PASSWORD=$SERVICE_PASSWORD_REDIS depends_on: redis: condition: service_healthy @@ -75,7 +76,7 @@ services: environment: - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_USER=${REDIS_USER:-default} - - REDIS_PASSWORD=${REDIS_PASSWORD:-} + - REDIS_PASSWORD=$SERVICE_PASSWORD_REDIS healthcheck: test: - CMD-SHELL From 151274a1379beb227c4fbb9104112d0128366678 Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:02:58 +0100 Subject: [PATCH 070/322] Remove restart: always from services --- templates/compose/swetrix.yaml | 4 ---- 1 file changed, 4 deletions(-) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 60f523a57..6b6721eef 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -8,7 +8,6 @@ services: swetrix: image: swetrix/swetrix-fe:v4.0.2 - restart: always depends_on: - swetrix-api environment: @@ -25,7 +24,6 @@ services: swetrix-api: image: swetrix/swetrix-api:v4.0.2 - restart: always environment: # Required - SECRET_KEY_BASE=${SECRET_KEY_BASE:?} @@ -72,7 +70,6 @@ services: redis: image: redis:8.2-alpine - restart: always environment: - REDIS_PORT=${REDIS_PORT:-6379} - REDIS_USER=${REDIS_USER:-default} @@ -88,7 +85,6 @@ services: clickhouse: image: clickhouse/clickhouse-server:24.10-alpine - restart: always environment: - CLICKHOUSE_DATABASE=${CLICKHOUSE_DATABASE:-analytics} - CLICKHOUSE_USER=${CLICKHOUSE_USER:-default} From 15a2ba57043938dde5fe7722bdc3ef32bdaf2936 Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:07:55 +0100 Subject: [PATCH 071/322] Generate SECRET_KEY_BASE with magic env --- templates/compose/swetrix.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 6b6721eef..216d333b5 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -26,7 +26,7 @@ services: image: swetrix/swetrix-api:v4.0.2 environment: # Required - - SECRET_KEY_BASE=${SECRET_KEY_BASE:?} + - SECRET_KEY_BASE=$SERVICE_BASE64_64_SECRETKEYBASE # Optional - DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false} From b289f7cbd2d1f374ae5eaafc27242c5b5987bb17 Mon Sep 17 00:00:00 2001 From: Blue Mouse Date: Wed, 1 Oct 2025 00:15:47 +0100 Subject: [PATCH 072/322] Add app URLs --- templates/compose/swetrix.yaml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/templates/compose/swetrix.yaml b/templates/compose/swetrix.yaml index 216d333b5..f302ae857 100644 --- a/templates/compose/swetrix.yaml +++ b/templates/compose/swetrix.yaml @@ -11,8 +11,8 @@ services: depends_on: - swetrix-api environment: - # Required - public URL of the API service (e.g. https://swetrix-api.example.com) - - API_URL=${API_URL:?} + - SERVICE_URL_SWETRIX_3000 + - API_URL=$SERVICE_URL_SWETRIXAPI_5005 healthcheck: test: - CMD-SHELL @@ -27,6 +27,7 @@ services: environment: # Required - SECRET_KEY_BASE=$SERVICE_BASE64_64_SECRETKEYBASE + - SERVICE_URL_SWETRIXAPI_5005 # Optional - DISABLE_REGISTRATION=${DISABLE_REGISTRATION:-false} From 25a7be23a97e6db3717f10751a1adb1b55f7e6d9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 1 Oct 2025 08:23:21 +0200 Subject: [PATCH 073/322] ui(storage): enhance file storage management with new properties and UI improvements - Added properties to manage file and directory counts, improving data handling in the Livewire component. - Updated the file storage view to include a tabbed interface for volumes, files, and directories, enhancing user navigation. - Improved UI layout for better readability and user experience, including consistent styling and informative messages. --- app/Livewire/Project/Service/Storage.php | 27 +++- .../project/service/file-storage.blade.php | 134 +++++++++--------- .../project/service/storage.blade.php | 125 ++++++++++++---- .../project/shared/storages/show.blade.php | 2 +- 4 files changed, 191 insertions(+), 97 deletions(-) diff --git a/app/Livewire/Project/Service/Storage.php b/app/Livewire/Project/Service/Storage.php index 26cd54425..fb7da1184 100644 --- a/app/Livewire/Project/Service/Storage.php +++ b/app/Livewire/Project/Service/Storage.php @@ -39,7 +39,32 @@ public function refreshStoragesFromEvent() public function refreshStorages() { $this->fileStorage = $this->resource->fileStorages()->get(); - $this->dispatch('$refresh'); + $this->resource->refresh(); + } + + public function getFilesProperty() + { + return $this->fileStorage->where('is_directory', false); + } + + public function getDirectoriesProperty() + { + return $this->fileStorage->where('is_directory', true); + } + + public function getVolumeCountProperty() + { + return $this->resource->persistentStorages()->count(); + } + + public function getFileCountProperty() + { + return $this->files->count(); + } + + public function getDirectoryCountProperty() + { + return $this->directories->count(); } public function addNewVolume($data) diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index aa0ce66a3..3aa24b087 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -1,73 +1,75 @@ -
-
-
- - +
+
+
+
+ + +
-
-
- @can('update', $resource) -
- @if ($fileStorage->is_directory) - - - @else - @if (!$fileStorage->is_binary) - + @can('update', $resource) +
+ @if ($fileStorage->is_directory) + + shortConfirmationLabel="Filepath" :confirmWithPassword="false" step2ButtonText="Convert to file" /> + + @else + @if (!$fileStorage->is_binary) + + @endif + Load from server + @endif - Load from server - - @endif -
- @endcan - @if (!$fileStorage->is_directory) - @can('update', $resource) - @if (data_get($resource, 'settings.is_preserve_repository_enabled')) -
- -
- @endif - - @if (!$fileStorage->is_based_on_git && !$fileStorage->is_binary) - Save - @endif - @else - @if (data_get($resource, 'settings.is_preserve_repository_enabled')) -
- -
- @endif - +
@endcan - @endif -
+ @if (!$fileStorage->is_directory) + @can('update', $resource) + @if (data_get($resource, 'settings.is_preserve_repository_enabled')) +
+ +
+ @endif + + @if (!$fileStorage->is_based_on_git && !$fileStorage->is_binary) + Save + @endif + @else + @if (data_get($resource, 'settings.is_preserve_repository_enabled')) +
+ +
+ @endif + + @endcan + @endif + +
diff --git a/resources/views/livewire/project/service/storage.blade.php b/resources/views/livewire/project/service/storage.blade.php index 41d48f386..56a52a566 100644 --- a/resources/views/livewire/project/service/storage.blade.php +++ b/resources/views/livewire/project/service/storage.blade.php @@ -1,4 +1,4 @@ -
+
@if ( $resource->getMorphClass() == 'App\Models\Application' || $resource->getMorphClass() == 'App\Models\StandalonePostgresql' || @@ -9,50 +9,117 @@ $resource->getMorphClass() == 'App\Models\StandaloneClickhouse' || $resource->getMorphClass() == 'App\Models\StandaloneMongodb' || $resource->getMorphClass() == 'App\Models\StandaloneMysql') -
-

Storages

- - @if ($resource?->build_pack !== 'dockercompose') - @can('update', $resource) - - - - @endcan - @endif +
+
+

Storages

+ + @if ($resource?->build_pack !== 'dockercompose') + @can('update', $resource) + + + + @endcan + @endif +
+
Persistent storage to preserve data between deployments.
-
Persistent storage to preserve data between deployments.
@if ($resource?->build_pack === 'dockercompose') - Please modify storage layout in your Docker Compose - file or reload the compose file to reread the storage layout. +
Please modify storage layout in your Docker Compose + file or reload the compose file to reread the storage layout.
@else @if ($resource->persistentStorages()->get()->count() === 0 && $fileStorage->count() == 0) -
No storage found.
+
No storage found.
@endif @endif - @if ($resource->persistentStorages()->get()->count() > 0) -

Volumes

- - @endif - @if ($fileStorage->count() > 0) -
- @foreach ($fileStorage as $fs) - - @endforeach + @php + $hasVolumes = $this->volumeCount > 0; + $hasFiles = $this->fileCount > 0; + $hasDirectories = $this->directoryCount > 0; + $defaultTab = $hasVolumes ? 'volumes' : ($hasFiles ? 'files' : 'directories'); + @endphp + + @if ($hasVolumes || $hasFiles || $hasDirectories) +
+ {{-- Tabs Navigation --}} +
+ + + +
+ + {{-- Tab Content --}} +
+ {{-- Volumes Tab --}} +
+ @if ($hasVolumes) + + @else +
+ No volumes configured. +
+ @endif +
+ + {{-- Files Tab --}} +
+ @if ($hasFiles) + @foreach ($this->files as $fs) + + @endforeach + @else +
+ No file mounts configured. +
+ @endif +
+ + {{-- Directories Tab --}} +
+ @if ($hasDirectories) + @foreach ($this->directories as $fs) + + @endforeach + @else +
+ No directory mounts configured. +
+ @endif +
+
@endif @else @if ($resource->persistentStorages()->get()->count() > 0) -

{{ Str::headline($resource->name) }}

+

{{ Str::headline($resource->name) }}

@endif @if ($resource->persistentStorages()->get()->count() > 0) @endif @if ($fileStorage->count() > 0) -
+
@foreach ($fileStorage->sort() as $fileStorage) diff --git a/resources/views/livewire/project/shared/storages/show.blade.php b/resources/views/livewire/project/shared/storages/show.blade.php index 569df0c4b..8c0ba0c06 100644 --- a/resources/views/livewire/project/shared/storages/show.blade.php +++ b/resources/views/livewire/project/shared/storages/show.blade.php @@ -1,5 +1,5 @@
-
+ @if ($isReadOnly) @if ($isFirst)
From bed7ad833eaa5aea5da532cd4844fd23aa235409 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 1 Oct 2025 08:23:35 +0200 Subject: [PATCH 074/322] ui(core): update projects property type and enhance UI styling - Changed the projects property in the Dashboard component from an array to a Collection for improved data handling. - Added new color variables in CSS for better theming options. - Updated button styles across various components for consistency and improved user experience. - Refined dropdown and notification components for better visual alignment and usability. --- app/Livewire/Dashboard.php | 2 +- resources/css/app.css | 7 +++++-- resources/css/utilities.css | 8 ++++---- resources/views/components/dropdown.blade.php | 3 ++- resources/views/livewire/dashboard.blade.php | 2 +- resources/views/livewire/global-search.blade.php | 2 +- resources/views/livewire/notifications/email.blade.php | 4 ++-- .../views/livewire/project/application/rollback.blade.php | 2 +- resources/views/livewire/project/index.blade.php | 2 +- .../views/livewire/project/shared/destination.blade.php | 4 ++-- resources/views/livewire/project/show.blade.php | 2 +- resources/views/livewire/settings-dropdown.blade.php | 2 +- 12 files changed, 22 insertions(+), 18 deletions(-) diff --git a/app/Livewire/Dashboard.php b/app/Livewire/Dashboard.php index a78804a16..57ecaa8a2 100644 --- a/app/Livewire/Dashboard.php +++ b/app/Livewire/Dashboard.php @@ -10,7 +10,7 @@ class Dashboard extends Component { - public $projects = []; + public Collection $projects; public Collection $servers; diff --git a/resources/css/app.css b/resources/css/app.css index 77fa2d66b..aad02d71b 100644 --- a/resources/css/app.css +++ b/resources/css/app.css @@ -20,8 +20,11 @@ @theme { --color-warning: #fcd452; --color-success: #16a34a; --color-error: #dc2626; + --color-coollabs-50: #f5f0ff; --color-coollabs: #6b16ed; --color-coollabs-100: #7317ff; + --color-coollabs-200: #5a12c7; + --color-coollabs-300: #4a0fa3; --color-coolgray-100: #181818; --color-coolgray-200: #202020; --color-coolgray-300: #242424; @@ -91,11 +94,11 @@ option { } button[isError]:not(:disabled) { - @apply text-white bg-red-600 hover:bg-red-700; + @apply text-red-800 dark:text-red-300 bg-red-50 dark:bg-red-900/30 border-red-300 dark:border-red-800 hover:bg-red-300 hover:text-white dark:hover:bg-red-800 dark:hover:text-white; } button[isHighlighted]:not(:disabled) { - @apply text-white bg-coollabs hover:bg-coollabs-100; + @apply text-coollabs-200 dark:text-white bg-coollabs-50 dark:bg-coollabs/20 border-coollabs dark:border-coollabs-100 hover:bg-coollabs hover:text-white dark:hover:bg-coollabs-100 dark:hover:text-white; } h1 { diff --git a/resources/css/utilities.css b/resources/css/utilities.css index cbbe2ef8e..c82b26b0c 100644 --- a/resources/css/utilities.css +++ b/resources/css/utilities.css @@ -63,7 +63,7 @@ @utility select { } @utility button { - @apply flex gap-2 justify-center items-center px-2 py-1 text-sm text-black normal-case rounded-sm border outline-0 cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-transparent disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300; + @apply flex gap-2 justify-center items-center px-2 h-8 text-sm text-black normal-case rounded-sm border-2 outline-0 cursor-pointer font-medium bg-white border-neutral-200 hover:bg-neutral-100 dark:bg-coolgray-100 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-200 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-transparent disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300; } @utility alert-success { @@ -155,15 +155,15 @@ @utility kbd-custom { } @utility box { - @apply relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 shadow-sm bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline; + @apply relative flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 shadow-sm bg-white border text-black dark:text-white hover:text-black border-neutral-200 dark:border-coolgray-300 hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:no-underline rounded-sm; } @utility box-boarding { - @apply flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 dark:text-white bg-neutral-50 border border-neutral-200 dark:border-black hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:text-black hover:no-underline text-black; + @apply flex lg:flex-row flex-col p-2 transition-colors cursor-pointer min-h-[4rem] dark:bg-coolgray-100 dark:text-white bg-neutral-50 border border-neutral-200 dark:border-coolgray-300 hover:bg-neutral-100 dark:hover:bg-coollabs-100 dark:hover:text-white hover:text-black hover:no-underline text-black rounded-sm; } @utility box-without-bg { - @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] border border-neutral-200 dark:border-black; + @apply flex p-2 transition-colors dark:hover:text-white hover:no-underline min-h-[4rem] border border-neutral-200 dark:border-coolgray-300 rounded-sm; } @utility box-without-bg-without-border { diff --git a/resources/views/components/dropdown.blade.php b/resources/views/components/dropdown.blade.php index cba60c550..666b93dbc 100644 --- a/resources/views/components/dropdown.blade.php +++ b/resources/views/components/dropdown.blade.php @@ -16,7 +16,8 @@ class="inline-flex items-center justify-start pr-8 transition-colors focus:outli
-
+
{{ $slot }}
diff --git a/resources/views/livewire/dashboard.blade.php b/resources/views/livewire/dashboard.blade.php index 2c581850d..7a0cbec4a 100644 --- a/resources/views/livewire/dashboard.blade.php +++ b/resources/views/livewire/dashboard.blade.php @@ -19,7 +19,7 @@ @if ($projects->count() > 0)
@foreach ($projects as $project) -
+
diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 2addf6f64..aae371b84 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -102,7 +102,7 @@ class="fixed top-0 left-0 z-99 flex items-start justify-center w-screen h-screen + class="w-full pl-12 pr-12 py-4 text-base bg-white dark:bg-coolgray-100 border-none rounded-lg shadow-xl ring-1 ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 focus:ring-neutral-400 dark:focus:ring-coolgray-300 dark:text-white placeholder-neutral-400 dark:placeholder-neutral-500" /> + +
+ + / or ⌘K to focus + + +
@@ -154,22 +197,326 @@ class="min-h-[200px] items-center justify-center p-8">
- @if ($isCreateMode && count($creatableItems) > 0 && !$autoOpenResource) + @if ($isSelectingResource) + +
+ + @if ($selectedServerId === null) +
+
+ +
+

+ Select Server +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingServers) +
+ + + + + + Loading + servers... +
+ @elseif (count($availableServers) > 0) + @foreach ($availableServers as $index => $server) + + @endforeach + @else +
+

No servers + available

+
+ @endif +
+ @endif + + + @if ($selectedServerId !== null && $selectedDestinationUuid === null) +
+
+ +
+

+ Select Destination +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingDestinations) +
+ + + + + + Loading + destinations... +
+ @elseif (count($availableDestinations) > 0) + @foreach ($availableDestinations as $index => $destination) + + @endforeach + @else +
+

No destinations + available

+
+ @endif +
+ @endif + + + @if ($selectedDestinationUuid !== null && $selectedProjectUuid === null) +
+
+ +
+

+ Select Project +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingProjects) +
+ + + + + + Loading + projects... +
+ @elseif (count($availableProjects) > 0) + @foreach ($availableProjects as $index => $project) + + @endforeach + @else +
+

No projects + available

+
+ @endif +
+ @endif + + + @if ($selectedProjectUuid !== null && $selectedEnvironmentUuid === null) +
+
+ +
+

+ Select Environment +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingEnvironments) +
+ + + + + + Loading + environments... +
+ @elseif (count($availableEnvironments) > 0) + @foreach ($availableEnvironments as $index => $environment) + + @endforeach + @else +
+

No environments + available

+
+ @endif +
+ @endif +
+ @elseif ($isCreateMode && count($this->filteredCreatableItems) > 0 && !$autoOpenResource) -
-
+ {{--

Create New Resources @@ -177,96 +524,166 @@ class="px-4 py-2 bg-yellow-50 dark:bg-yellow-900/20 border-b border-yellow-100 d

Click on any item below to create a new resource

-

- @foreach ($creatableItems as $item) - + @endforeach + @endforeach +
+ @elseif (strlen($searchQuery) >= 1 && count($searchResults) > 0) + - - @endforeach -
- @elseif (strlen($searchQuery) >= 2 && count($searchResults) > 0) - @elseif (strlen($searchQuery) >= 2 && count($searchResults) === 0 && !$autoOpenResource) @@ -280,14 +697,6 @@ class="shrink-0 h-5 w-5 text-neutral-300 dark:text-neutral-600 self-center"

- @elseif (strlen($searchQuery) > 0 && strlen($searchQuery) < 2) -
-
-

- Type at least 2 characters to search -

-
-
@endif
From 318f092e7ce3f11a932b5e1c2c5bbdca240f1c78 Mon Sep 17 00:00:00 2001 From: Scan <103391616+scanash00@users.noreply.github.com> Date: Wed, 8 Oct 2025 01:28:37 -0800 Subject: [PATCH 159/322] Update templates/compose/bluesky-pds.yaml Co-authored-by: Cynthia Ebert <54354036+Cinzya@users.noreply.github.com> --- templates/compose/bluesky-pds.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/bluesky-pds.yaml b/templates/compose/bluesky-pds.yaml index d7ede0b83..3ddc9d608 100644 --- a/templates/compose/bluesky-pds.yaml +++ b/templates/compose/bluesky-pds.yaml @@ -9,7 +9,7 @@ services: pds: image: 'ghcr.io/bluesky-social/pds:0.4.182' volumes: - - './pds-data:/pds' + - pds-data:/pds environment: - SERVICE_URL_PDS_3000 - 'PDS_HOSTNAME=${SERVICE_FQDN_PDS_3000}' From 9a7d3ab2962ae6aa706dc8b604cfe9a7782158fc Mon Sep 17 00:00:00 2001 From: zehjotkah <111518041+zehjotkah@users.noreply.github.com> Date: Wed, 8 Oct 2025 10:34:11 +0100 Subject: [PATCH 160/322] replaced latest tag with specific version --- templates/compose/rybbit.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/rybbit.yaml b/templates/compose/rybbit.yaml index 1b3ce16af..3c8f7564c 100644 --- a/templates/compose/rybbit.yaml +++ b/templates/compose/rybbit.yaml @@ -6,7 +6,7 @@ services: rybbit: - image: 'ghcr.io/rybbit-io/rybbit-client:latest' + image: 'ghcr.io/rybbit-io/rybbit-client:v1.6.1' environment: - SERVICE_URL_RYBBIT_3002 - NODE_ENV=production @@ -22,7 +22,7 @@ services: start_period: 10s rybbit_backend: - image: 'ghcr.io/rybbit-io/rybbit-backend:latest' + image: 'ghcr.io/rybbit-io/rybbit-backend:v1.6.1' environment: - NODE_ENV=production - TRUST_PROXY=true From d752ee2b90a23ea89b473006ac8d4d147f0d43b3 Mon Sep 17 00:00:00 2001 From: elmariss <53705290+YaRissi@users.noreply.github.com> Date: Wed, 8 Oct 2025 11:43:21 +0200 Subject: [PATCH 161/322] implement suggestions --- templates/compose/gotify.yaml | 8 +++----- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/templates/compose/gotify.yaml b/templates/compose/gotify.yaml index b587d8f0c..10e8264f5 100644 --- a/templates/compose/gotify.yaml +++ b/templates/compose/gotify.yaml @@ -7,11 +7,9 @@ services: gotify: - image: gotify/server - ports: - - 8080:80 + image: gotify/server:2.7.3 environment: - - SERVICE_FQDN_GOTIFY_80 + - SERVICE_URL_GOTIFY_80 - GOTIFY_DEFAULTUSER_NAME=${GOTIFY_USERNAME:-admin} - GOTIFY_DEFAULTUSER_PASS=${SERVICE_PASSWORD_GOTIFY} - GOTIFY_DATABASE_DIALECT=${GOTIFY_DATABASE_DIALECT:-sqlite3} @@ -24,7 +22,7 @@ services: volumes: - 'gotify-data:/app/data' healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/health"] + test: ["CMD", "curl", "-f", "http://127.0.0.1:80/health"] interval: 5s timeout: 20s retries: 10 diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 520225f15..93060a692 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -1564,7 +1564,7 @@ "gotify": { "documentation": "https://gotify.net/docs/install?utm_source=coolify.io", "slogan": "Gotify is an open-source self-hosted notification server.", - "compose": "c2VydmljZXM6CiAgZ290aWZ5OgogICAgaW1hZ2U6IGdvdGlmeS9zZXJ2ZXIKICAgIHBvcnRzOgogICAgICAtICc4MDgwOjgwJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0dPVElGWV84MAogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfTkFNRT0ke0dPVElGWV9VU0VSTkFNRTotYWRtaW59JwogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfUEFTUz0ke1NFUlZJQ0VfUEFTU1dPUkRfR09USUZZfScKICAgICAgLSAnR09USUZZX0RBVEFCQVNFX0RJQUxFQ1Q9JHtHT1RJRllfREFUQUJBU0VfRElBTEVDVDotc3FsaXRlM30nCiAgICAgIC0gJ0dPVElGWV9EQVRBQkFTRV9DT05ORUNUSU9OPSR7R09USUZZX0RBVEFCQVNFX0NPTk5FQ1RJT046LWRhdGEvZ290aWZ5LmRifScKICAgICAgLSAnR09USUZZX1BBU1NTVFJFTkdUSD0ke0dPVElGWV9QQVNTU1RSRU5HVEg6LTEwfScKICAgICAgLSAnR09USUZZX1VQTE9BREVESU1BR0VTRElSPSR7R09USUZZX1VQTE9BREVESU1BR0VTRElSOi1kYXRhL2ltYWdlc30nCiAgICAgIC0gJ0dPVElGWV9QTFVHSU5TRElSPSR7R09USUZZX1BMVUdJTlNESVI6LWRhdGEvcGx1Z2luc30nCiAgICAgIC0gJ0dPVElGWV9TRVJWRVJfUE9SVD0ke0dPVElGWV9TRVJWRVJfUE9SVDotODB9JwogICAgICAtICdHT1RJRllfUkVHSVNUUkFUSU9OPSR7R09USUZZX1JFR0lTVFJBVElPTjotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnZ290aWZ5LWRhdGE6L2FwcC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvaGVhbHRoJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==", + "compose": "c2VydmljZXM6CiAgZ290aWZ5OgogICAgaW1hZ2U6ICdnb3RpZnkvc2VydmVyOjIuNy4zJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfR09USUZZXzgwCiAgICAgIC0gJ0dPVElGWV9ERUZBVUxUVVNFUl9OQU1FPSR7R09USUZZX1VTRVJOQU1FOi1hZG1pbn0nCiAgICAgIC0gJ0dPVElGWV9ERUZBVUxUVVNFUl9QQVNTPSR7U0VSVklDRV9QQVNTV09SRF9HT1RJRll9JwogICAgICAtICdHT1RJRllfREFUQUJBU0VfRElBTEVDVD0ke0dPVElGWV9EQVRBQkFTRV9ESUFMRUNUOi1zcWxpdGUzfScKICAgICAgLSAnR09USUZZX0RBVEFCQVNFX0NPTk5FQ1RJT049JHtHT1RJRllfREFUQUJBU0VfQ09OTkVDVElPTjotZGF0YS9nb3RpZnkuZGJ9JwogICAgICAtICdHT1RJRllfUEFTU1NUUkVOR1RIPSR7R09USUZZX1BBU1NTVFJFTkdUSDotMTB9JwogICAgICAtICdHT1RJRllfVVBMT0FERURJTUFHRVNESVI9JHtHT1RJRllfVVBMT0FERURJTUFHRVNESVI6LWRhdGEvaW1hZ2VzfScKICAgICAgLSAnR09USUZZX1BMVUdJTlNESVI9JHtHT1RJRllfUExVR0lOU0RJUjotZGF0YS9wbHVnaW5zfScKICAgICAgLSAnR09USUZZX1NFUlZFUl9QT1JUPSR7R09USUZZX1NFUlZFUl9QT1JUOi04MH0nCiAgICAgIC0gJ0dPVElGWV9SRUdJU1RSQVRJT049JHtHT1RJRllfUkVHSVNUUkFUSU9OOi1mYWxzZX0nCiAgICB2b2x1bWVzOgogICAgICAtICdnb3RpZnktZGF0YTovYXBwL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy1mJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6ODAvaGVhbHRoJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==", "tags": [ "productivity", "notification", diff --git a/templates/service-templates.json b/templates/service-templates.json index 3eddb6049..5913b3d81 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -1564,7 +1564,7 @@ "gotify": { "documentation": "https://gotify.net/docs/install?utm_source=coolify.io", "slogan": "Gotify is an open-source self-hosted notification server.", - "compose": "c2VydmljZXM6CiAgZ290aWZ5OgogICAgaW1hZ2U6IGdvdGlmeS9zZXJ2ZXIKICAgIHBvcnRzOgogICAgICAtICc4MDgwOjgwJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0dPVElGWV84MAogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfTkFNRT0ke0dPVElGWV9VU0VSTkFNRTotYWRtaW59JwogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfUEFTUz0ke1NFUlZJQ0VfUEFTU1dPUkRfR09USUZZfScKICAgICAgLSAnR09USUZZX0RBVEFCQVNFX0RJQUxFQ1Q9JHtHT1RJRllfREFUQUJBU0VfRElBTEVDVDotc3FsaXRlM30nCiAgICAgIC0gJ0dPVElGWV9EQVRBQkFTRV9DT05ORUNUSU9OPSR7R09USUZZX0RBVEFCQVNFX0NPTk5FQ1RJT046LWRhdGEvZ290aWZ5LmRifScKICAgICAgLSAnR09USUZZX1BBU1NTVFJFTkdUSD0ke0dPVElGWV9QQVNTU1RSRU5HVEg6LTEwfScKICAgICAgLSAnR09USUZZX1VQTE9BREVESU1BR0VTRElSPSR7R09USUZZX1VQTE9BREVESU1BR0VTRElSOi1kYXRhL2ltYWdlc30nCiAgICAgIC0gJ0dPVElGWV9QTFVHSU5TRElSPSR7R09USUZZX1BMVUdJTlNESVI6LWRhdGEvcGx1Z2luc30nCiAgICAgIC0gJ0dPVElGWV9TRVJWRVJfUE9SVD0ke0dPVElGWV9TRVJWRVJfUE9SVDotODB9JwogICAgICAtICdHT1RJRllfUkVHSVNUUkFUSU9OPSR7R09USUZZX1JFR0lTVFJBVElPTjotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnZ290aWZ5LWRhdGE6L2FwcC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvaGVhbHRoJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==", + "compose": "c2VydmljZXM6CiAgZ290aWZ5OgogICAgaW1hZ2U6ICdnb3RpZnkvc2VydmVyOjIuNy4zJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX0dPVElGWV84MAogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfTkFNRT0ke0dPVElGWV9VU0VSTkFNRTotYWRtaW59JwogICAgICAtICdHT1RJRllfREVGQVVMVFVTRVJfUEFTUz0ke1NFUlZJQ0VfUEFTU1dPUkRfR09USUZZfScKICAgICAgLSAnR09USUZZX0RBVEFCQVNFX0RJQUxFQ1Q9JHtHT1RJRllfREFUQUJBU0VfRElBTEVDVDotc3FsaXRlM30nCiAgICAgIC0gJ0dPVElGWV9EQVRBQkFTRV9DT05ORUNUSU9OPSR7R09USUZZX0RBVEFCQVNFX0NPTk5FQ1RJT046LWRhdGEvZ290aWZ5LmRifScKICAgICAgLSAnR09USUZZX1BBU1NTVFJFTkdUSD0ke0dPVElGWV9QQVNTU1RSRU5HVEg6LTEwfScKICAgICAgLSAnR09USUZZX1VQTE9BREVESU1BR0VTRElSPSR7R09USUZZX1VQTE9BREVESU1BR0VTRElSOi1kYXRhL2ltYWdlc30nCiAgICAgIC0gJ0dPVElGWV9QTFVHSU5TRElSPSR7R09USUZZX1BMVUdJTlNESVI6LWRhdGEvcGx1Z2luc30nCiAgICAgIC0gJ0dPVElGWV9TRVJWRVJfUE9SVD0ke0dPVElGWV9TRVJWRVJfUE9SVDotODB9JwogICAgICAtICdHT1RJRllfUkVHSVNUUkFUSU9OPSR7R09USUZZX1JFR0lTVFJBVElPTjotZmFsc2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnZ290aWZ5LWRhdGE6L2FwcC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwL2hlYWx0aCcKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAo=", "tags": [ "productivity", "notification", From e8b2ef0e0cfca06384c5c86af7e8c632175d031a Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 8 Oct 2025 13:29:58 +0200 Subject: [PATCH 162/322] fix(modal-confirmation): refine escape key handling to ensure modal closes only when open - Updated the keydown event handler to check if the modal is open before executing the close and reset functions, improving the modal's behavior and user experience. --- resources/views/components/modal-confirmation.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 1a3c88f80..103f18316 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -114,7 +114,7 @@ } } }" - @keydown.escape.window="modalOpen = false; resetModal()" :class="{ 'z-40': modalOpen }" + @keydown.escape.window="if (modalOpen) { modalOpen = false; resetModal(); }" :class="{ 'z-40': modalOpen }" class="relative w-auto h-auto"> @if ($customButton) @if ($buttonFullWidth) From 91d5a489e8bf85cce4c8bfa578074cde646721c2 Mon Sep 17 00:00:00 2001 From: Romain ROCHAS Date: Wed, 8 Oct 2025 13:32:11 +0200 Subject: [PATCH 163/322] fix(lobe-chat): update Docker image tag to a specific version 1.135.5 --- templates/compose/lobe-chat.yaml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/templates/compose/lobe-chat.yaml b/templates/compose/lobe-chat.yaml index 5dcb226c9..859f617e3 100644 --- a/templates/compose/lobe-chat.yaml +++ b/templates/compose/lobe-chat.yaml @@ -7,7 +7,7 @@ services: lobe-chat: - image: "lobehub/lobe-chat:latest" + image: "lobehub/lobe-chat:1.135.5" environment: - SERVICE_URL_LOBECHAT_3210 - OPENAI_API_KEY=${OPENAI_API_KEY} From afd10048bda450b6bb6bd56a18fea84c6f25fcf9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 8 Oct 2025 13:38:38 +0200 Subject: [PATCH 164/322] update globalsearch --- app/Livewire/GlobalSearch.php | 134 ++++++++++-- .../views/livewire/global-search.blade.php | 206 ++++++++++++++---- 2 files changed, 274 insertions(+), 66 deletions(-) diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index 33366f418..98571b87f 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -22,6 +22,8 @@ class GlobalSearch extends Component { public $searchQuery = ''; + private $previousTrimmedQuery = ''; + public $isModalOpen = false; public $searchResults = []; @@ -86,6 +88,7 @@ public function closeSearchModal() { $this->isModalOpen = false; $this->searchQuery = ''; + $this->previousTrimmedQuery = ''; $this->searchResults = []; } @@ -101,25 +104,49 @@ public static function clearTeamCache($teamId) public function updatedSearchQuery() { - $query = strtolower(trim($this->searchQuery)); + $trimmedQuery = trim($this->searchQuery); + + // If only spaces were added/removed, don't trigger a search + if ($trimmedQuery === $this->previousTrimmedQuery) { + return; + } + + $this->previousTrimmedQuery = $trimmedQuery; + + // If search query is empty, just clear results without processing + if (empty($trimmedQuery)) { + $this->searchResults = []; + $this->isCreateMode = false; + $this->creatableItems = []; + $this->autoOpenResource = null; + $this->isSelectingResource = false; + $this->cancelResourceSelection(); + + return; + } + + $query = strtolower($trimmedQuery); // Reset keyboard navigation index $this->dispatch('reset-selected-index'); - if (str_starts_with($query, 'new')) { + // Only enter create mode if query is exactly "new" or starts with "new " (space after) + if ($query === 'new' || str_starts_with($query, 'new ')) { $this->isCreateMode = true; $this->loadCreatableItems(); - $this->searchResults = []; // Check for sub-commands like "new project", "new server", etc. - // Use original query (not trimmed) to ensure exact match without trailing spaces - $detectedType = $this->detectSpecificResource(strtolower($this->searchQuery)); + $detectedType = $this->detectSpecificResource($query); if ($detectedType) { $this->navigateToResource($detectedType); } else { // If no specific resource detected, reset selection state $this->cancelResourceSelection(); } + + // Also search for existing resources that match the query + // This allows users to find resources with "new" in their name + $this->search(); } else { $this->isCreateMode = false; $this->creatableItems = []; @@ -624,6 +651,8 @@ private function search() // Search for matching creatable resources to show as suggestions (if no priority item) if (! $priorityCreatableItem) { $this->loadCreatableItems(); + + // Search in regular creatable items (apps, databases, quick actions) $creatableSuggestions = collect($this->creatableItems) ->filter(function ($item) use ($query) { $searchText = strtolower($item['name'].' '.$item['description'].' '.($item['type'] ?? '')); @@ -648,7 +677,37 @@ private function search() $item['is_creatable_suggestion'] = true; return $item; + }); + + // Also search in services (loaded on-demand) + $serviceSuggestions = collect($this->services) + ->filter(function ($item) use ($query) { + $searchText = strtolower($item['name'].' '.$item['description'].' '.($item['type'] ?? '')); + + return preg_match('/\b'.preg_quote($query, '/').'/i', $searchText); }) + ->map(function ($item) use ($query) { + // Calculate match priority: name > type > description + $name = strtolower($item['name']); + $type = strtolower($item['type'] ?? ''); + $description = strtolower($item['description']); + + if (preg_match('/\b'.preg_quote($query, '/').'/i', $name)) { + $item['match_priority'] = 1; + } elseif (preg_match('/\b'.preg_quote($query, '/').'/i', $type)) { + $item['match_priority'] = 2; + } else { + $item['match_priority'] = 3; + } + + $item['is_creatable_suggestion'] = true; + + return $item; + }); + + // Merge and sort all suggestions + $creatableSuggestions = $creatableSuggestions + ->merge($serviceSuggestions) ->sortBy('match_priority') ->take(10) ->values() @@ -914,31 +973,18 @@ private function loadCreatableItems() ]); } - // === Services Category === - - if ($user->can('createAnyResource')) { - // Load all services - $allServices = get_service_templates(); - - foreach ($allServices as $serviceKey => $service) { - $items->push([ - 'name' => str($serviceKey)->headline()->toString(), - 'description' => data_get($service, 'slogan', 'Deploy '.str($serviceKey)->headline()), - 'type' => 'one-click-service-'.$serviceKey, - 'category' => 'Services', - 'resourceType' => 'service', - ]); - } - } - $this->creatableItems = $items->toArray(); } public function navigateToResource($type) { - // Find the item by type + // Find the item by type - check regular items first, then services $item = collect($this->creatableItems)->firstWhere('type', $type); + if (! $item) { + $item = collect($this->services)->firstWhere('type', $type); + } + if (! $item) { return; } @@ -1227,12 +1273,52 @@ public function getSelectedResourceNameProperty() $this->loadCreatableItems(); } - // Find the item by type + // Find the item by type - check regular items first, then services $item = collect($this->creatableItems)->firstWhere('type', $this->selectedResourceType); + if (! $item) { + $item = collect($this->services)->firstWhere('type', $this->selectedResourceType); + } + return $item ? $item['name'] : null; } + public function getServicesProperty() + { + // Cache services in a static property to avoid reloading on every access + static $cachedServices = null; + + if ($cachedServices !== null) { + return $cachedServices; + } + + $user = auth()->user(); + + if (! $user->can('createAnyResource')) { + $cachedServices = []; + + return $cachedServices; + } + + // Load all services + $allServices = get_service_templates(); + $items = collect(); + + foreach ($allServices as $serviceKey => $service) { + $items->push([ + 'name' => str($serviceKey)->headline()->toString(), + 'description' => data_get($service, 'slogan', 'Deploy '.str($serviceKey)->headline()), + 'type' => 'one-click-service-'.$serviceKey, + 'category' => 'Services', + 'resourceType' => 'service', + ]); + } + + $cachedServices = $items->toArray(); + + return $cachedServices; + } + public function render() { return view('livewire.global-search'); diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 0bd833d8e..ad9a9f6ad 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -1,14 +1,20 @@
+ x-init="$watch('modalOpen', value => { if (value) setTimeout(() => $refs.searchInput.focus(), 100) })" :disabled="isLoadingInitialData" + class="w-full pl-12 pr-32 py-4 text-base bg-white dark:bg-coolgray-100 border-none rounded-lg shadow-xl ring-1 ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 focus:ring-neutral-400 dark:focus:ring-coolgray-300 dark:text-white placeholder-neutral-400 dark:placeholder-neutral-500 disabled:opacity-50 disabled:cursor-not-allowed" />
/ or ⌘K to focus @@ -172,31 +212,53 @@ class="pointer-events-auto px-2 py-1 text-xs font-medium text-neutral-500 dark:t
+ +
+
+
+ + + + + +

+ Please wait while we fetch your data +

+
+
+
+ @if (strlen($searchQuery) >= 1)
- -
-
- - - - - -

- Searching... -

+ +
+ +
+ @for ($i = 0; $i < 3; $i++) +
+
+
+
+
+
+
+
+
+
+
+ @endfor
- -
+ +
@if ($isSelectingResource)
@@ -516,15 +578,71 @@ class="p-3 bg-red-50 dark:bg-red-900/20 rounded-lg border border-red-200 dark:bo @elseif ($isCreateMode && count($this->filteredCreatableItems) > 0 && !$autoOpenResource)
- {{--
-

- Create New Resources -

-

- Click on any item below to create a new resource -

-
--}} + {{-- Show existing resources first if any match --}} + @php + $existingResources = collect($searchResults)->filter(fn($r) => !isset($r['is_creatable_suggestion']))->count(); + @endphp + @if ($existingResources > 0) + +
+

+ Existing Resources +

+
+ @foreach ($searchResults as $result) + @if (!isset($result['is_creatable_suggestion'])) + +
+
+
+ + {{ $result['name'] }} + + + @if ($result['type'] === 'application') + Application + @elseif ($result['type'] === 'service') + Service + @elseif ($result['type'] === 'database') + {{ ucfirst($result['subtype'] ?? 'Database') }} + @elseif ($result['type'] === 'server') + Server + @elseif ($result['type'] === 'project') + Project + @elseif ($result['type'] === 'environment') + Environment + @endif + +
+ @if (!empty($result['project']) && !empty($result['environment'])) +
+ {{ $result['project'] }} / + {{ $result['environment'] }} +
+ @endif + @if (!empty($result['description'])) +
+ {{ Str::limit($result['description'], 80) }} +
+ @endif +
+ + + +
+
+ @endif + @endforeach + @endif @php $grouped = collect($this->filteredCreatableItems)->groupBy('category'); @@ -695,6 +813,9 @@ class="shrink-0 h-5 w-5 text-neutral-300 dark:text-neutral-600 self-center"

Try different keywords or check the spelling

+

+ 💡 Tip: Search for service names like "wordpress", "postgres", or "redis" +

@endif @@ -957,4 +1078,5 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5
+
From 2e6e07bcc310f84838103e14710e27a21e626a51 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 8 Oct 2025 16:53:02 +0200 Subject: [PATCH 165/322] make global search frontend heavy --- app/Livewire/GlobalSearch.php | 4 + .../views/livewire/global-search.blade.php | 1180 +++++++++-------- 2 files changed, 609 insertions(+), 575 deletions(-) diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index 98571b87f..e378bd289 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -81,6 +81,7 @@ public function openSearchModal() { $this->isModalOpen = true; $this->loadSearchableItems(); + $this->loadCreatableItems(); $this->dispatch('search-modal-opened'); } @@ -973,6 +974,9 @@ private function loadCreatableItems() ]); } + // Merge with services + $items = $items->merge(collect($this->services)); + $this->creatableItems = $items->toArray(); } diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index ad9a9f6ad..95d2640a6 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -3,18 +3,74 @@ selectedIndex: -1, isSearching: false, isLoadingInitialData: false, + allSearchableItems: [], + searchQuery: '', + creatableItems: [], + isCreateMode: false, + + // Client-side search function + get searchResults() { + if (!this.searchQuery || this.searchQuery.length < 1) { + return []; + } + + const query = this.searchQuery.toLowerCase().trim(); + + const results = this.allSearchableItems.filter(item => { + if (!item.search_text) return false; + return item.search_text.toLowerCase().includes(query); + }).slice(0, 20); + + return results; + }, + + get filteredCreatableItems() { + if (!this.searchQuery || this.searchQuery.length < 1) { + return []; + } + const query = this.searchQuery.toLowerCase().trim(); + + if (query === 'new') { + return this.creatableItems; + } + + return this.creatableItems.filter(item => { + const searchText = `${item.name} ${item.description} ${item.type} ${item.category}`.toLowerCase(); + return searchText.includes(query); + }); + }, + + get groupedCreatableItems() { + const grouped = {}; + this.filteredCreatableItems.forEach(item => { + const category = item.category || 'Other'; + if (!grouped[category]) { + grouped[category] = []; + } + grouped[category].push(item); + }); + return grouped; + }, + openModal() { this.modalOpen = true; this.selectedIndex = -1; this.isLoadingInitialData = true; - // Dispatch event to load initial data - $wire.dispatch('loadInitialData'); + this.searchQuery = ''; + $wire.openSearchModal().then(() => { + this.allSearchableItems = $wire.allSearchableItems || []; + this.creatableItems = $wire.creatableItems || []; + this.isLoadingInitialData = false; + setTimeout(() => this.$refs.searchInput?.focus(), 50); + }); }, closeModal() { this.modalOpen = false; this.selectedIndex = -1; this.isSearching = false; this.isLoadingInitialData = false; + this.searchQuery = ''; + this.allSearchableItems = []; // Ensure scroll is restored document.body.style.overflow = ''; @this.closeSearchModal(); @@ -42,43 +98,39 @@ this.selectedIndex = -1; }); - // Listen for loading state changes - $wire.on('loadInitialData', () => { - this.isLoadingInitialData = true; - $wire.openSearchModal().finally(() => { - this.isLoadingInitialData = false; - // Focus input after data is loaded - setTimeout(() => this.$refs.searchInput?.focus(), 50); - }); - }); + this.$watch('searchQuery', (value) => { + this.selectedIndex = -1; + const trimmed = value.trim().toLowerCase(); - // Use Livewire lifecycle hooks for accurate loading state - const componentId = $wire.__instance.id; - - Livewire.hook('message.sent', (message, component) => { - // Only handle messages for this component instance - if (component.id !== componentId) return; - - // Check if this is a searchQuery update - if (message.updateQueue && message.updateQueue.some(update => update.payload.name === 'searchQuery')) { - this.isSearching = true; + if (trimmed === '') { + if ($wire.isSelectingResource) { + $wire.cancelResourceSelection(); + } + return; } - }); - Livewire.hook('message.processed', (message, component) => { - // Only handle messages for this component instance - if (component.id !== componentId) return; + const exactMatchCommands = [ + 'new project', 'new server', 'new team', 'new storage', 'new s3', + 'new private key', 'new privatekey', 'new key', + 'new github app', 'new github', 'new source', + 'new public', 'new public git', 'new public repo', 'new public repository', + 'new private github', 'new private gh', 'new private deploy', 'new deploy key', + 'new dockerfile', 'new docker compose', 'new compose', 'new docker image', 'new image', + 'new postgresql', 'new postgres', 'new mysql', 'new mariadb', + 'new redis', 'new keydb', 'new dragonfly', 'new mongodb', 'new mongo', 'new clickhouse' + ]; - // Check if this was a searchQuery update - if (message.updateQueue && message.updateQueue.some(update => update.payload.name === 'searchQuery')) { - this.isSearching = false; - } - }); + if (exactMatchCommands.includes(trimmed)) { + const matchingItem = this.creatableItems.find(item => { + const itemSearchText = `new ${item.name}`.toLowerCase(); + const itemType = `new ${item.type}`.toLowerCase(); + return itemSearchText === trimmed || itemType === trimmed || + (item.type && trimmed.includes(item.type.replace(/-/g, ' '))); + }); - // Also clear loading state when search is emptied - this.$watch('$wire.searchQuery', (value) => { - if (!value || value.length === 0) { - this.isSearching = false; + if (matchingItem) { + $wire.navigateToResource(matchingItem.type); + } } }); @@ -111,7 +163,7 @@ const escapeKeyHandler = (e) => { if (e.key === 'Escape' && this.modalOpen) { // If search query is empty, close the modal - if (!$wire.searchQuery || $wire.searchQuery === '') { + if (!this.searchQuery || this.searchQuery === '') { // Check if we're in a selection state using Alpine-accessible Livewire state if ($wire.isSelectingResource) { $wire.cancelResourceSelection(); @@ -122,7 +174,7 @@ } } else { // If search query has text, just clear it - $wire.searchQuery = ''; + this.searchQuery = ''; setTimeout(() => this.$refs.searchInput?.focus(), 100); } } @@ -191,13 +243,21 @@ class="fixed top-0 left-0 z-99 flex items-start justify-center w-screen h-screen
- + + + + +
- @@ -212,547 +272,347 @@ class="pointer-events-auto px-2 py-1 text-xs font-medium text-neutral-500 dark:t
- -
-
-
- - - - - -

- Please wait while we fetch your data -

-
+ + {{--
+
+

+ ✓ Data loaded successfully! +

+

+ searchable items available +

+

+ Start typing to search... +

-
+
--}} - @if (strlen($searchQuery) >= 1) -
- -
- -
- @for ($i = 0; $i < 3; $i++) -
-
-
-
-
-
-
+
+ +
+ @if ($isSelectingResource) + +
+ + @if ($selectedServerId === null) +
+
+ +
+

+ Select Server +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif
-
-
- @endfor -
-
- - -
- @if ($isSelectingResource) - -
- - @if ($selectedServerId === null) -
-
+ @if ($loadingServers) +
+ + + + + + Loading + servers... +
+ @elseif (count($availableServers) > 0) + @foreach ($availableServers as $index => $server) -
-

- Select Server -

- @if ($this->selectedResourceName) -
- for {{ $this->selectedResourceName }} -
- @endif -
-
- @if ($loadingServers) -
- - - - - - Loading - servers... -
- @elseif (count($availableServers) > 0) - @foreach ($availableServers as $index => $server) - - @endforeach - @else -
-

No servers - available

-
- @endif -
- @endif - - - @if ($selectedServerId !== null && $selectedDestinationUuid === null) -
-
- -
-

- Select Destination -

- @if ($this->selectedResourceName) -
- for {{ $this->selectedResourceName }} -
- @endif -
-
- @if ($loadingDestinations) -
- - - - - - Loading - destinations... -
- @elseif (count($availableDestinations) > 0) - @foreach ($availableDestinations as $index => $destination) - - @endforeach - @else -
-

No destinations - available

-
- @endif -
- @endif - - - @if ($selectedDestinationUuid !== null && $selectedProjectUuid === null) -
-
- -
-

- Select Project -

- @if ($this->selectedResourceName) -
- for {{ $this->selectedResourceName }} -
- @endif -
-
- @if ($loadingProjects) -
- - - - - - Loading - projects... -
- @elseif (count($availableProjects) > 0) - @foreach ($availableProjects as $index => $project) - - @endforeach - @else -
-

No projects - available

-
- @endif -
- @endif - - - @if ($selectedProjectUuid !== null && $selectedEnvironmentUuid === null) -
-
- -
-

- Select Environment -

- @if ($this->selectedResourceName) -
- for {{ $this->selectedResourceName }} -
- @endif -
-
- @if ($loadingEnvironments) -
- - - - - - Loading - environments... -
- @elseif (count($availableEnvironments) > 0) - @foreach ($availableEnvironments as $index => $environment) - - @endforeach - @else -
-

No environments - available

-
- @endif -
- @endif -
- @elseif ($isCreateMode && count($this->filteredCreatableItems) > 0 && !$autoOpenResource) - -
- {{-- Show existing resources first if any match --}} - @php - $existingResources = collect($searchResults)->filter(fn($r) => !isset($r['is_creatable_suggestion']))->count(); - @endphp - @if ($existingResources > 0) - -
-

- Existing Resources -

-
- @foreach ($searchResults as $result) - @if (!isset($result['is_creatable_suggestion'])) - + wire:click="selectServer({{ $server['id'] }}, true)" + class="search-result-item w-full text-left block px-4 py-3 hover:bg-yellow-50 dark:hover:bg-yellow-900/20 transition-colors focus:outline-none focus:bg-yellow-100 dark:focus:bg-yellow-900/30"> - @elseif (strlen($searchQuery) >= 1 && count($searchResults) > 0) -
- @foreach ($searchResults as $index => $result) - @if (isset($result['is_creatable_suggestion']) && $result['is_creatable_suggestion']) - {{-- Creatable suggestion with yellow theme --}} - + + @endforeach @else - {{-- Regular search result --}} +
+

No servers + available

+
+ @endif +
+ @endif + + + @if ($selectedServerId !== null && $selectedDestinationUuid === null) +
+
+ +
+

+ Select Destination +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingDestinations) +
+ + + + + + Loading + destinations... +
+ @elseif (count($availableDestinations) > 0) + @foreach ($availableDestinations as $index => $destination) + + @endforeach + @else +
+

No destinations + available

+
+ @endif +
+ @endif + + + @if ($selectedDestinationUuid !== null && $selectedProjectUuid === null) +
+
+ +
+

+ Select Project +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingProjects) +
+ + + + + + Loading + projects... +
+ @elseif (count($availableProjects) > 0) + @foreach ($availableProjects as $index => $project) + + @endforeach + @else +
+

No projects + available

+
+ @endif +
+ @endif + + + @if ($selectedProjectUuid !== null && $selectedEnvironmentUuid === null) +
+
+ +
+

+ Select Environment +

+ @if ($this->selectedResourceName) +
+ for {{ $this->selectedResourceName }} +
+ @endif +
+
+ @if ($loadingEnvironments) +
+ + + + + + Loading + environments... +
+ @elseif (count($availableEnvironments) > 0) + @foreach ($availableEnvironments as $index => $environment) + + @endforeach + @else +
+

No environments + available

+
+ @endif +
+ @endif +
+ @elseif ($isCreateMode && count($this->filteredCreatableItems) > 0 && !$autoOpenResource) + +
+ {{-- Show existing resources first if any match --}} + @php + $existingResources = collect($searchResults) + ->filter(fn($r) => !isset($r['is_creatable_suggestion'])) + ->count(); + @endphp + @if ($existingResources > 0) + +
+

+ Existing Resources +

+
+ @foreach ($searchResults as $result) + @if (!isset($result['is_creatable_suggestion'])) - @elseif (strlen($searchQuery) >= 2 && count($searchResults) === 0 && !$autoOpenResource) -
-
-

- No results found -

-

- Try different keywords or check the spelling -

-

- 💡 Tip: Search for service names like "wordpress", "postgres", or "redis" -

+ @endif + + @php + $grouped = collect($this->filteredCreatableItems)->groupBy('category'); + @endphp + + @foreach ($grouped as $category => $items) + +
+

+ {{ $category }} +

+ + + @foreach ($items as $item) + + @endforeach + @endforeach +
+ @endif + + + + + +
- @endif +
From 6f086d26dbe053afb3d4700e32a9b6b29faa1572 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Wed, 8 Oct 2025 22:06:07 +0530 Subject: [PATCH 166/322] fix service ente-photos-with-s3 --- templates/compose/ente-photos-with-s3.yaml | 156 ++++++++++++--------- 1 file changed, 86 insertions(+), 70 deletions(-) diff --git a/templates/compose/ente-photos-with-s3.yaml b/templates/compose/ente-photos-with-s3.yaml index 96d74b1a8..844bc673b 100644 --- a/templates/compose/ente-photos-with-s3.yaml +++ b/templates/compose/ente-photos-with-s3.yaml @@ -7,107 +7,123 @@ services: museum: - image: ghcr.io/ente-io/server:latest + image: 'ghcr.io/ente-io/server:613c6a96390d7a624cf30b946955705d632423cc' # Released at 2025-09-14T22:16:37-07:00 environment: - SERVICE_URL_MUSEUM_8080 - - ENTE_HTTP_USE_TLS=${ENTE_HTTP_USE_TLS:-false} - - - ENTE_APPS_PUBLIC_ALBUMS=${SERVICE_URL_WEB_3002} - - ENTE_APPS_CAST=${SERVICE_URL_WEB_3004} - - ENTE_APPS_ACCOUNTS=${SERVICE_URL_WEB_3001} - - - ENTE_DB_HOST=${ENTE_DB_HOST:-postgres} - - ENTE_DB_PORT=${ENTE_DB_PORT:-5432} - - ENTE_DB_NAME=${ENTE_DB_NAME:-ente_db} - - ENTE_DB_USER=${SERVICE_USER_POSTGRES:-pguser} - - ENTE_DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - - - ENTE_KEY_ENCRYPTION=${SERVICE_REALBASE64_ENCRYPTION} - - ENTE_KEY_HASH=${SERVICE_REALBASE64_64_HASH} - - - ENTE_JWT_SECRET=${SERVICE_REALBASE64_JWT} - - - ENTE_INTERNAL_ADMIN=${ENTE_INTERNAL_ADMIN:-1580559962386438} - - ENTE_INTERNAL_DISABLE_REGISTRATION=${ENTE_INTERNAL_DISABLE_REGISTRATION:-false} - - # S3/MinIO configuration - - S3_ARE_LOCAL_BUCKETS=true - - S3_USE_PATH_STYLE_URLS=true - - S3_B2_EU_CEN_KEY=${SERVICE_USER_MINIO} - - S3_B2_EU_CEN_SECRET=${SERVICE_PASSWORD_MINIO} - - S3_B2_EU_CEN_ENDPOINT=${SERVICE_URL_MINIO_3200} - - S3_B2_EU_CEN_REGION=eu-central-2 - - S3_B2_EU_CEN_BUCKET=b2-eu-cen + - ENTE_DB_HOST=postgres + - ENTE_DB_PORT=5432 + - 'ENTE_DB_NAME=${POSTGRES_DB:-ente_db}' + - 'ENTE_DB_USER=${SERVICE_USER_POSTGRES}' + - 'ENTE_DB_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' + - 'ENTE_HTTP_USE_TLS=${ENTE_HTTP_USE_TLS:-false}' + - ENTE_S3_ARE_LOCAL_BUCKETS=false + - ENTE_S3_USE_PATH_STYLE_URLS=true + - 'ENTE_S3_B2_EU_CEN_KEY=${SERVICE_USER_MINIO}' + - 'ENTE_S3_B2_EU_CEN_SECRET=${SERVICE_PASSWORD_MINIO}' + - 'ENTE_S3_B2_EU_CEN_ENDPOINT=${SERVICE_FQDN_MINIO_9000}' + - ENTE_S3_B2_EU_CEN_REGION=eu-central-2 + - ENTE_S3_B2_EU_CEN_BUCKET=b2-eu-cen + - 'ENTE_KEY_ENCRYPTION=${SERVICE_REALBASE64_ENCRYPTION}' + - 'ENTE_KEY_HASH=${SERVICE_REALBASE64_64_HASH}' + - 'ENTE_JWT_SECRET=${SERVICE_REALBASE64_JWT}' + - 'ENTE_INTERNAL_ADMIN=${ENTE_INTERNAL_ADMIN:-1580559962386438}' + - 'ENTE_INTERNAL_DISABLE_REGISTRATION=${ENTE_INTERNAL_DISABLE_REGISTRATION:-false}' volumes: - - museum-data:/data - - museum-config:/config + - 'museum-data:/data' + - 'museum-config:/config' depends_on: postgres: condition: service_healthy minio: condition: service_started healthcheck: - test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/ping"] - interval: 5s - timeout: 5s - retries: 10 + test: + - CMD + - wget + - '--spider' + - 'http://127.0.0.1:8080/ping' + interval: 30s + timeout: 10s + retries: 3 + web: - image: ghcr.io/ente-io/web + image: 'ghcr.io/ente-io/web:ca03165f5e7f2a50105e6e40019c17ae6cdd934f' # Released at 2025-10-08T00:57:05-07:00 environment: - SERVICE_URL_WEB_3000 - - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} - - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} - + - 'ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM}' healthcheck: - test: ["CMD", "curl", "--fail", "http://127.0.0.1:3000"] - interval: 5s - timeout: 5s - retries: 10 + test: + - CMD + - curl + - '--fail' + - 'http://localhost:3000' + interval: 30s + timeout: 10s + retries: 3 + start_period: 10s + + postgres: - image: postgres:15-alpine + image: 'postgres:15-alpine' environment: - - POSTGRES_USER=${SERVICE_USER_POSTGRES} - - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - - POSTGRES_DB=${POSTGRES_DB:-ente_db} + - 'POSTGRES_USER=${SERVICE_USER_POSTGRES}' + - 'POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES}' + - 'POSTGRES_DB=${POSTGRES_DB:-ente_db}' volumes: - - postgres-data:/var/lib/postgresql/data + - 'postgres-data:/var/lib/postgresql/data' healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 5s + test: + - CMD-SHELL + - 'pg_isready -U ${SERVICE_USER_POSTGRES} -d ${POSTGRES_DB:-ente_db}' + interval: 10s timeout: 5s - retries: 10 + retries: 5 + minio: - image: quay.io/minio/minio:latest + image: 'quay.io/minio/minio:RELEASE.2025-09-07T16-13-09Z' # Released at 2025-09-07T16-13-09Z + command: 'server /data --console-address ":9001"' environment: - - SERVICE_URL_MINIO_9000 - - MINIO_ROOT_USER=${SERVICE_USER_MINIO} - - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} - command: server /data --address ":9000" --console-address ":9001" + - MINIO_SERVER_URL=$MINIO_SERVER_URL + - MINIO_BROWSER_REDIRECT_URL=$MINIO_BROWSER_REDIRECT_URL + - MINIO_ROOT_USER=$SERVICE_USER_MINIO + - MINIO_ROOT_PASSWORD=$SERVICE_PASSWORD_MINIO volumes: - - minio-data:/data + - 'minio-data:/data' healthcheck: - test: ["CMD", "mc", "ready", "local"] + test: + - CMD + - mc + - ready + - local interval: 5s timeout: 20s retries: 10 + minio-init: - image: minio/mc:latest - exclude_from_hc: true - restart: no + image: 'minio/mc:RELEASE.2025-08-13T08-35-41Z' # Released at 2025-08-13T08-35-41Z depends_on: minio: - condition: service_healthy + condition: service_started + restart: on-failure + exclude_from_hc: true environment: - - MINIO_ROOT_USER=${SERVICE_USER_MINIO} - - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} - entrypoint: > + - 'MINIO_ROOT_USER=${SERVICE_USER_MINIO}' + - 'MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO}' + - 'MINIO_CORS_URLS=$SERVICE_URL_MUSEUM,$SERVICE_URL_WEB' + entrypoint: |- /bin/sh -c " - mc alias set minio http://minio:9000 $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}; - mc mb minio/b2-eu-cen --ignore-existing; - mc mb minio/wasabi-eu-central-2-v3 --ignore-existing; - mc mb minio/scw-eu-fr-v3 --ignore-existing; - echo 'MinIO buckets created successfully'; + echo \"MINIO_CORS_URLS: \$${MINIO_CORS_URLS}\"; + sleep 5; + until mc alias set minio http://minio:9000 \$${MINIO_ROOT_USER} \$${MINIO_ROOT_PASSWORD}; do + echo 'Waiting for MinIO...'; + sleep 2; + done; + mc admin config set minio api cors_allow_origin='$MINIO_CORS_URLS' || true; + mc mb minio/b2-eu-cen --ignore-existing; + mc mb minio/wasabi-eu-central-2-v3 --ignore-existing; + mc mb minio/scw-eu-fr-v3 --ignore-existing; + echo 'MinIO buckets and CORS configured'; " From 3323302021f6aa615d3629e8729cfd713268ec84 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Wed, 8 Oct 2025 19:50:06 +0200 Subject: [PATCH 167/322] refactor(navbar, app): improve layout and styling for better responsiveness - Adjusted CSS styles in the navbar for improved readability and responsiveness. - Updated the layout of the sidebar and navbar components to enhance user experience on different screen sizes. - Ensured consistent alignment and spacing for elements within the navbar and sidebar. --- resources/views/components/navbar.blade.php | 34 ++++++++++----------- resources/views/layouts/app.blade.php | 12 +++++--- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/resources/views/components/navbar.blade.php b/resources/views/components/navbar.blade.php index defa7bf6c..4b152dd11 100644 --- a/resources/views/components/navbar.blade.php +++ b/resources/views/components/navbar.blade.php @@ -59,25 +59,25 @@ if (this.zoom === '90') { const style = document.createElement('style'); style.textContent = ` - html { - font-size: 93.75%; - } - - :root { - --vh: 1vh; - } - - @media (min-width: 1024px) { - html { - font-size: 87.5%; - } - } - `; + html { + font-size: 93.75%; + } + + :root { + --vh: 1vh; + } + + @media (min-width: 1024px) { + html { + font-size: 87.5%; + } + } + `; document.head.appendChild(style); } } }"> -
+
Coolify
@@ -86,8 +86,8 @@
-
- + @can('viewAny', App\Models\CloudProviderToken::class) + + + + @endcan - +
diff --git a/resources/views/livewire/security/cloud-provider-tokens.blade.php b/resources/views/livewire/security/cloud-provider-tokens.blade.php new file mode 100644 index 000000000..d29631c4c --- /dev/null +++ b/resources/views/livewire/security/cloud-provider-tokens.blade.php @@ -0,0 +1,66 @@ +
+

Cloud Provider Tokens

+
Manage API tokens for cloud providers (Hetzner, DigitalOcean, etc.). Tokens are saved encrypted and shared with your team.
+ +

New Token

+ @can('create', App\Models\CloudProviderToken::class) + +
+
+ + + + +
+
+ +
+
+
+
+ +
+ Add Token +
+ + @endcan + +

Saved Tokens

+
+ @forelse ($tokens as $savedToken) +
+
+ + {{ strtoupper($savedToken->provider) }} + + {{ $savedToken->name }} +
+
Token: ***{{ substr($savedToken->token, -4) }}
+
Created: {{ $savedToken->created_at->diffForHumans() }}
+ + @can('delete', $savedToken) + + @endcan +
+ @empty +
+
No cloud provider tokens found.
+
+ @endforelse +
+
diff --git a/resources/views/livewire/security/cloud-tokens.blade.php b/resources/views/livewire/security/cloud-tokens.blade.php new file mode 100644 index 000000000..2edbcd30f --- /dev/null +++ b/resources/views/livewire/security/cloud-tokens.blade.php @@ -0,0 +1,7 @@ +
+ + Cloud Tokens | Coolify + + + +
diff --git a/resources/views/livewire/server/create.blade.php b/resources/views/livewire/server/create.blade.php index acab92374..619a827e7 100644 --- a/resources/views/livewire/server/create.blade.php +++ b/resources/views/livewire/server/create.blade.php @@ -1,3 +1,23 @@
- +
+ @can('viewAny', App\Models\CloudProviderToken::class) +
+

Add Server from Cloud Provider

+
+ + + +
+
+ +
+ @endcan + +
+

Add Server by IP Address

+ +
+
diff --git a/resources/views/livewire/server/new/by-hetzner.blade.php b/resources/views/livewire/server/new/by-hetzner.blade.php new file mode 100644 index 000000000..83de355e3 --- /dev/null +++ b/resources/views/livewire/server/new/by-hetzner.blade.php @@ -0,0 +1,52 @@ +
+ @if ($limit_reached) + + @else +
+ @if ($available_tokens->count() > 0) +
+ + + @foreach ($available_tokens as $token) + + @endforeach + +
+
OR
+ @endif + +
+ +
+ +
+ +
+ + @if ($save_token) +
+ +
+ @endif + + + Continue + +
+ @endif +
diff --git a/routes/web.php b/routes/web.php index fd2ed8730..e967586c4 100644 --- a/routes/web.php +++ b/routes/web.php @@ -34,6 +34,7 @@ use App\Livewire\Project\Shared\ScheduledTask\Show as ScheduledTaskShow; use App\Livewire\Project\Show as ProjectShow; use App\Livewire\Security\ApiTokens; +use App\Livewire\Security\CloudTokens; use App\Livewire\Security\PrivateKey\Index as SecurityPrivateKeyIndex; use App\Livewire\Security\PrivateKey\Show as SecurityPrivateKeyShow; use App\Livewire\Server\Advanced as ServerAdvanced; @@ -271,6 +272,7 @@ // Route::get('/security/private-key/new', SecurityPrivateKeyCreate::class)->name('security.private-key.create'); Route::get('/security/private-key/{private_key_uuid}', SecurityPrivateKeyShow::class)->name('security.private-key.show'); + Route::get('/security/cloud-tokens', CloudTokens::class)->name('security.cloud-tokens'); Route::get('/security/api-tokens', ApiTokens::class)->name('security.api-tokens'); }); From 354eadd02f18872ef9aa50476f689e5186fbba19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C3=96zg=C3=BCr?= <226712+halilim@users.noreply.github.com> Date: Thu, 9 Oct 2025 00:14:17 +0300 Subject: [PATCH 172/322] Gramps Web: Pin to a version --- templates/compose/gramps-web.yaml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/templates/compose/gramps-web.yaml b/templates/compose/gramps-web.yaml index 04a284ff2..fa3b02c6f 100644 --- a/templates/compose/gramps-web.yaml +++ b/templates/compose/gramps-web.yaml @@ -7,7 +7,7 @@ services: grampsweb: - image: ghcr.io/gramps-project/grampsweb:latest + image: ghcr.io/gramps-project/grampsweb:25.9.0 environment: - SERVICE_URL_GRAMPSWEB_5000 - GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists @@ -33,7 +33,7 @@ services: retries: 3 grampsweb_celery: - image: ghcr.io/gramps-project/grampsweb:latest + image: ghcr.io/gramps-project/grampsweb:25.9.0 environment: - GRAMPSWEB_TREE=${GRAMPSWEB_TREE:-Gramps Web} # will create a new tree if not exists - GRAMPSWEB_CELERY_CONFIG__broker_url=redis://grampsweb_redis:6379/0 From ee6b8c9c042b746dcd39cdd1b1991b8efe4b8663 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Halil=20=C3=96zg=C3=BCr?= <226712+halilim@users.noreply.github.com> Date: Thu, 9 Oct 2025 00:19:17 +0300 Subject: [PATCH 173/322] Revert unintentional changes --- .github/workflows/claude-code-review.yml | 39 ++++++++++++++++----- .github/workflows/claude.yml | 44 +++++++++++++++--------- 2 files changed, 57 insertions(+), 26 deletions(-) diff --git a/.github/workflows/claude-code-review.yml b/.github/workflows/claude-code-review.yml index d73398046..a2c92df59 100644 --- a/.github/workflows/claude-code-review.yml +++ b/.github/workflows/claude-code-review.yml @@ -34,13 +34,15 @@ jobs: - name: Run Claude Code Review id: claude-review - uses: anthropics/claude-code-action@v1 + uses: anthropics/claude-code-action@beta with: claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - prompt: | - REPO: ${{ github.repository }} - PR NUMBER: ${{ github.event.pull_request.number }} + # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1) + # model: "claude-opus-4-1-20250805" + + # Direct prompt for automated review (no @claude mention needed) + direct_prompt: | Please review this pull request and provide feedback on: - Code quality and best practices - Potential bugs or issues @@ -48,11 +50,30 @@ jobs: - Security concerns - Test coverage - Use the repository's CLAUDE.md for guidance on style and conventions. Be constructive and helpful in your feedback. + Be constructive and helpful in your feedback. - Use `gh pr comment` with your Bash tool to leave your review as a comment on the PR. + # Optional: Use sticky comments to make Claude reuse the same comment on subsequent pushes to the same PR + # use_sticky_comment: true - # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md - # or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options - claude_args: '--allowed-tools "Bash(gh issue view:*),Bash(gh search:*),Bash(gh issue list:*),Bash(gh pr comment:*),Bash(gh pr diff:*),Bash(gh pr view:*),Bash(gh pr list:*)"' + # Optional: Customize review based on file types + # direct_prompt: | + # Review this PR focusing on: + # - For TypeScript files: Type safety and proper interface usage + # - For API endpoints: Security, input validation, and error handling + # - For React components: Performance, accessibility, and best practices + # - For tests: Coverage, edge cases, and test quality + + # Optional: Different prompts for different authors + # direct_prompt: | + # ${{ github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR' && + # 'Welcome! Please review this PR from a first-time contributor. Be encouraging and provide detailed explanations for any suggestions.' || + # 'Please provide a thorough code review focusing on our coding standards and best practices.' }} + + # Optional: Add specific tools for running tests or linting + # allowed_tools: "Bash(npm run test),Bash(npm run lint),Bash(npm run typecheck)" + + # Optional: Skip review for certain conditions + # if: | + # !contains(github.event.pull_request.title, '[skip-review]') && + # !contains(github.event.pull_request.title, '[WIP]') diff --git a/.github/workflows/claude.yml b/.github/workflows/claude.yml index e93c95bff..9daf0e90e 100644 --- a/.github/workflows/claude.yml +++ b/.github/workflows/claude.yml @@ -16,6 +16,8 @@ jobs: (github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) || (github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) || + (github.event_name == 'issues' && github.event.action == 'labeled' && github.event.label.name == 'Claude') || + (github.event_name == 'pull_request' && github.event.action == 'labeled' && github.event.label.name == 'Claude') || (github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude'))) runs-on: ubuntu-latest permissions: @@ -34,22 +36,30 @@ jobs: id: claude uses: anthropics/claude-code-action@v1 with: - - name: Run Claude Code - id: claude - uses: anthropics/claude-code-action@v1 - with: - claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} - # This is an optional setting that allows Claude to read CI results on PRs - additional_permissions: | - actions: read + anthropic_api_key: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }} + + # This is an optional setting that allows Claude to read CI results on PRs additional_permissions: | actions: read - - # Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it. - # prompt: 'Update the pull request description to include a summary of changes.' - - # Optional: Add claude_args to customize behavior and configuration - # See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md - # or https://docs.claude.com/en/docs/claude-code/sdk#command-line for available options - # claude_args: '--model claude-opus-4-1-20250805 --allowed-tools Bash(gh pr:*)' - + + # Optional: Specify model (defaults to Claude Sonnet 4, uncomment for Claude Opus 4.1) + # model: "claude-opus-4-1-20250805" + + # Optional: Customize the trigger phrase (default: @claude) + # trigger_phrase: "/claude" + + # Optional: Trigger when specific user is assigned to an issue + # assignee_trigger: "claude-bot" + + # Optional: Allow Claude to run specific commands + # allowed_tools: "Bash(npm install),Bash(npm run build),Bash(npm run test:*),Bash(npm run lint:*)" + + # Optional: Add custom instructions for Claude to customize its behavior for your project + # custom_instructions: | + # Follow our coding standards + # Ensure all new code has tests + # Use TypeScript for new files + + # Optional: Custom environment variables for Claude + # claude_env: | + # NODE_ENV: test From 42f671cfa249b5630c20331cb152c8b3caa824d3 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Thu, 9 Oct 2025 09:49:33 +0530 Subject: [PATCH 174/322] Added healthcheck to moodle service --- templates/compose/moodle.yaml | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/templates/compose/moodle.yaml b/templates/compose/moodle.yaml index 3a8e02478..41b7916b9 100644 --- a/templates/compose/moodle.yaml +++ b/templates/compose/moodle.yaml @@ -18,9 +18,18 @@ services: - MARIADB_COLLATE=utf8mb4_unicode_ci volumes: - mariadb-data:/var/lib/mysql + healthcheck: + test: + - CMD-SHELL + - bash -c ' Date: Thu, 9 Oct 2025 10:41:29 +0200 Subject: [PATCH 175/322] basics of adding / removing hetzner servers --- app/Actions/Server/DeleteServer.php | 49 ++- app/Livewire/Security/CloudProviderTokens.php | 2 +- app/Livewire/Server/Delete.php | 19 +- app/Livewire/Server/New/ByHetzner.php | 372 ++++++++++++++++-- app/Models/PrivateKey.php | 11 + app/Models/Server.php | 1 + app/Services/HetznerService.php | 96 +++++ ...5_10_03_154100_update_clickhouse_image.php | 64 +-- ...add_hetzner_server_id_to_servers_table.php | 28 ++ public/svgs/hetzner.svg | 6 + .../components/modal-confirmation.blade.php | 12 + .../views/livewire/server/create.blade.php | 14 +- .../views/livewire/server/delete.blade.php | 17 +- .../livewire/server/new/by-hetzner.blade.php | 157 ++++++-- .../views/livewire/server/show.blade.php | 15 +- 15 files changed, 744 insertions(+), 119 deletions(-) create mode 100644 app/Services/HetznerService.php create mode 100644 database/migrations/2025_10_08_185203_add_hetzner_server_id_to_servers_table.php create mode 100644 public/svgs/hetzner.svg diff --git a/app/Actions/Server/DeleteServer.php b/app/Actions/Server/DeleteServer.php index 15c892e75..db197a019 100644 --- a/app/Actions/Server/DeleteServer.php +++ b/app/Actions/Server/DeleteServer.php @@ -2,16 +2,63 @@ namespace App\Actions\Server; +use App\Models\CloudProviderToken; use App\Models\Server; +use App\Services\HetznerService; use Lorisleiva\Actions\Concerns\AsAction; class DeleteServer { use AsAction; - public function handle(Server $server) + public function handle(Server $server, bool $deleteFromHetzner = false) { + // Delete from Hetzner Cloud if requested and server has hetzner_server_id + if ($deleteFromHetzner && $server->hetzner_server_id) { + $this->deleteFromHetzner($server); + } + StopSentinel::run($server); $server->forceDelete(); } + + private function deleteFromHetzner(Server $server): void + { + try { + // Get the cloud provider token for Hetzner + $token = CloudProviderToken::where('team_id', $server->team_id) + ->where('provider', 'hetzner') + ->first(); + + if (! $token) { + ray('No Hetzner token found for team, skipping Hetzner deletion', [ + 'team_id' => $server->team_id, + 'server_id' => $server->id, + ]); + + return; + } + + $hetznerService = new HetznerService($token->token); + $hetznerService->deleteServer($server->hetzner_server_id); + + ray('Deleted server from Hetzner', [ + 'hetzner_server_id' => $server->hetzner_server_id, + 'server_id' => $server->id, + ]); + } catch (\Throwable $e) { + ray('Failed to delete server from Hetzner', [ + 'error' => $e->getMessage(), + 'hetzner_server_id' => $server->hetzner_server_id, + 'server_id' => $server->id, + ]); + + // Log the error but don't prevent the server from being deleted from Coolify + logger()->error('Failed to delete server from Hetzner', [ + 'error' => $e->getMessage(), + 'hetzner_server_id' => $server->hetzner_server_id, + 'server_id' => $server->id, + ]); + } + } } diff --git a/app/Livewire/Security/CloudProviderTokens.php b/app/Livewire/Security/CloudProviderTokens.php index f35a3a806..f5726e424 100644 --- a/app/Livewire/Security/CloudProviderTokens.php +++ b/app/Livewire/Security/CloudProviderTokens.php @@ -100,7 +100,7 @@ public function addNewToken() public function deleteToken(int $tokenId) { try { - $token = CloudProviderToken::findOrFail($tokenId); + $token = CloudProviderToken::ownedByCurrentTeam()->findOrFail($tokenId); $this->authorize('delete', $token); $token->delete(); diff --git a/app/Livewire/Server/Delete.php b/app/Livewire/Server/Delete.php index b9e3944b5..6d12895eb 100644 --- a/app/Livewire/Server/Delete.php +++ b/app/Livewire/Server/Delete.php @@ -16,6 +16,8 @@ class Delete extends Component public Server $server; + public bool $delete_from_hetzner = false; + public function mount(string $server_uuid) { try { @@ -41,8 +43,9 @@ public function delete($password) return; } + $this->server->delete(); - DeleteServer::dispatch($this->server); + DeleteServer::dispatch($this->server, $this->delete_from_hetzner); return redirect()->route('server.index'); } catch (\Throwable $e) { @@ -52,6 +55,18 @@ public function delete($password) public function render() { - return view('livewire.server.delete'); + $checkboxes = []; + + if ($this->server->hetzner_server_id) { + $checkboxes[] = [ + 'id' => 'delete_from_hetzner', + 'label' => 'Also delete server from Hetzner Cloud', + 'default_warning' => 'The actual server on Hetzner Cloud will NOT be deleted.', + ]; + } + + return view('livewire.server.delete', [ + 'checkboxes' => $checkboxes, + ]); } } diff --git a/app/Livewire/Server/New/ByHetzner.php b/app/Livewire/Server/New/ByHetzner.php index d509adcb6..b67411e17 100644 --- a/app/Livewire/Server/New/ByHetzner.php +++ b/app/Livewire/Server/New/ByHetzner.php @@ -2,9 +2,12 @@ namespace App\Livewire\Server\New; +use App\Enums\ProxyTypes; use App\Models\CloudProviderToken; +use App\Models\PrivateKey; use App\Models\Server; use App\Models\Team; +use App\Services\HetznerService; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; use Illuminate\Support\Collection; use Illuminate\Support\Facades\Http; @@ -15,6 +18,10 @@ class ByHetzner extends Component { use AuthorizesRequests; + // Step tracking + public int $current_step = 1; + + // Locked data #[Locked] public Collection $available_tokens; @@ -24,6 +31,7 @@ class ByHetzner extends Component #[Locked] public $limit_reached; + // Step 1: Token selection public ?int $selected_token_id = null; public string $hetzner_token = ''; @@ -32,22 +40,69 @@ class ByHetzner extends Component public ?string $token_name = null; + // Step 2: Server configuration + public array $locations = []; + + public array $images = []; + + public array $serverTypes = []; + + public ?string $selected_location = null; + + public ?int $selected_image = null; + + public ?string $selected_server_type = null; + + public string $server_name = ''; + + public bool $start_after_create = true; + + public ?int $private_key_id = null; + + public bool $loading_data = false; + public function mount() { $this->authorize('viewAny', CloudProviderToken::class); $this->available_tokens = CloudProviderToken::ownedByCurrentTeam() ->where('provider', 'hetzner') ->get(); + $this->server_name = generate_random_name(); + if ($this->private_keys->count() > 0) { + $this->private_key_id = $this->private_keys->first()->id; + } } protected function rules(): array { - return [ + $rules = [ 'selected_token_id' => 'nullable|integer', 'hetzner_token' => 'required_without:selected_token_id|string', 'save_token' => 'boolean', - 'token_name' => 'required_if:save_token,true|nullable|string|max:255', + 'token_name' => [ + 'nullable', + 'string', + 'max:255', + function ($attribute, $value, $fail) { + if ($this->save_token && ! empty($this->hetzner_token) && empty($value)) { + $fail('Please provide a name for the token.'); + } + }, + ], ]; + + if ($this->current_step === 2) { + $rules = array_merge($rules, [ + 'server_name' => 'required|string|max:255', + 'selected_location' => 'required|string', + 'selected_image' => 'required|integer', + 'selected_server_type' => 'required|string', + 'private_key_id' => 'required|integer|exists:private_keys,id,team_id,'.currentTeam()->id, + 'start_after_create' => 'boolean', + ]); + } + + return $rules; } protected function messages(): array @@ -76,6 +131,275 @@ private function validateHetznerToken(string $token): bool } } + private function getHetznerToken(): string + { + if ($this->selected_token_id) { + $token = $this->available_tokens->firstWhere('id', $this->selected_token_id); + + return $token ? $token->token : ''; + } + + return $this->hetzner_token; + } + + public function nextStep() + { + // Validate step 1 + $this->validate([ + 'selected_token_id' => 'nullable|integer', + 'hetzner_token' => 'required_without:selected_token_id|string', + 'save_token' => 'boolean', + 'token_name' => [ + 'nullable', + 'string', + 'max:255', + function ($attribute, $value, $fail) { + if ($this->save_token && ! empty($this->hetzner_token) && empty($value)) { + $fail('Please provide a name for the token.'); + } + }, + ], + ]); + + try { + $hetznerToken = $this->getHetznerToken(); + + if (! $hetznerToken) { + return $this->dispatch('error', 'Please provide a valid Hetzner API token.'); + } + + // Validate token if it's a new one + if (! $this->selected_token_id) { + if (! $this->validateHetznerToken($hetznerToken)) { + return $this->dispatch('error', 'Invalid Hetzner API token. Please check your token and try again.'); + } + + // Save token if requested + if ($this->save_token) { + CloudProviderToken::create([ + 'team_id' => currentTeam()->id, + 'provider' => 'hetzner', + 'token' => $this->hetzner_token, + 'name' => $this->token_name, + ]); + } + } + + // Load Hetzner data + $this->loadHetznerData($hetznerToken); + + // Move to step 2 + $this->current_step = 2; + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function previousStep() + { + $this->current_step = 1; + } + + private function loadHetznerData(string $token) + { + $this->loading_data = true; + + try { + $hetznerService = new HetznerService($token); + + $this->locations = $hetznerService->getLocations(); + $this->serverTypes = $hetznerService->getServerTypes(); + + // Get images and sort by name + $images = $hetznerService->getImages(); + + ray('Raw images from Hetzner API', [ + 'total_count' => count($images), + 'types' => collect($images)->pluck('type')->unique()->values(), + 'sample' => array_slice($images, 0, 3), + ]); + + $this->images = collect($images) + ->filter(function ($image) { + // Only system images + if (! isset($image['type']) || $image['type'] !== 'system') { + return false; + } + + // Filter out deprecated images + if (isset($image['deprecated']) && $image['deprecated'] === true) { + return false; + } + + return true; + }) + ->sortBy('name') + ->values() + ->toArray(); + + ray('Filtered images', [ + 'filtered_count' => count($this->images), + 'debian_images' => collect($this->images)->filter(fn ($img) => str_contains($img['name'] ?? '', 'debian'))->values(), + ]); + + $this->loading_data = false; + } catch (\Throwable $e) { + $this->loading_data = false; + throw $e; + } + } + + public function getAvailableServerTypesProperty() + { + ray('Getting available server types', [ + 'selected_location' => $this->selected_location, + 'total_server_types' => count($this->serverTypes), + ]); + + if (! $this->selected_location) { + return $this->serverTypes; + } + + $filtered = collect($this->serverTypes) + ->filter(function ($type) { + if (! isset($type['locations'])) { + return false; + } + + $locationNames = collect($type['locations'])->pluck('name')->toArray(); + + return in_array($this->selected_location, $locationNames); + }) + ->values() + ->toArray(); + + ray('Filtered server types', [ + 'selected_location' => $this->selected_location, + 'filtered_count' => count($filtered), + ]); + + return $filtered; + } + + public function getAvailableImagesProperty() + { + ray('Getting available images', [ + 'selected_server_type' => $this->selected_server_type, + 'total_images' => count($this->images), + 'images' => $this->images, + ]); + + if (! $this->selected_server_type) { + return $this->images; + } + + $serverType = collect($this->serverTypes)->firstWhere('name', $this->selected_server_type); + + ray('Server type data', $serverType); + + if (! $serverType || ! isset($serverType['architecture'])) { + ray('No architecture in server type, returning all'); + + return $this->images; + } + + $architecture = $serverType['architecture']; + + $filtered = collect($this->images) + ->filter(fn ($image) => ($image['architecture'] ?? null) === $architecture) + ->values() + ->toArray(); + + ray('Filtered images', [ + 'architecture' => $architecture, + 'filtered_count' => count($filtered), + ]); + + return $filtered; + } + + public function updatedSelectedLocation($value) + { + ray('Location selected', $value); + + // Reset server type and image when location changes + $this->selected_server_type = null; + $this->selected_image = null; + } + + public function updatedSelectedServerType($value) + { + ray('Server type selected', $value); + + // Reset image when server type changes + $this->selected_image = null; + } + + public function updatedSelectedImage($value) + { + ray('Image selected', $value); + } + + private function createHetznerServer(string $token): array + { + $hetznerService = new HetznerService($token); + + // Get the private key and extract public key + $privateKey = PrivateKey::ownedByCurrentTeam()->findOrFail($this->private_key_id); + + $publicKey = $privateKey->getPublicKey(); + $md5Fingerprint = PrivateKey::generateMd5Fingerprint($privateKey->private_key); + + ray('Private Key Info', [ + 'private_key_id' => $this->private_key_id, + 'sha256_fingerprint' => $privateKey->fingerprint, + 'md5_fingerprint' => $md5Fingerprint, + ]); + + // Check if SSH key already exists on Hetzner by comparing MD5 fingerprints + $existingSshKeys = $hetznerService->getSshKeys(); + $existingKey = null; + + ray('Existing SSH Keys on Hetzner', $existingSshKeys); + + foreach ($existingSshKeys as $key) { + if ($key['fingerprint'] === $md5Fingerprint) { + $existingKey = $key; + break; + } + } + + // Upload SSH key if it doesn't exist + if ($existingKey) { + $sshKeyId = $existingKey['id']; + ray('Using existing SSH key', ['ssh_key_id' => $sshKeyId]); + } else { + $sshKeyName = $privateKey->name; + $uploadedKey = $hetznerService->uploadSshKey($sshKeyName, $publicKey); + $sshKeyId = $uploadedKey['id']; + ray('Uploaded new SSH key', ['ssh_key_id' => $sshKeyId, 'name' => $sshKeyName]); + } + + // Prepare server creation parameters + $params = [ + 'name' => $this->server_name, + 'server_type' => $this->selected_server_type, + 'image' => $this->selected_image, + 'location' => $this->selected_location, + 'start_after_create' => $this->start_after_create, + 'ssh_keys' => [$sshKeyId], + ]; + + ray('Server creation parameters', $params); + + // Create server on Hetzner + $hetznerServer = $hetznerService->createServer($params); + + ray('Hetzner server created', $hetznerServer); + + return $hetznerServer; + } + public function submit() { $this->validate(); @@ -87,35 +411,27 @@ public function submit() return $this->dispatch('error', 'You have reached the server limit for your subscription.'); } - // Determine which token to use - if ($this->selected_token_id) { - $token = $this->available_tokens->firstWhere('id', $this->selected_token_id); - if (! $token) { - return $this->dispatch('error', 'Selected token not found.'); - } - $hetznerToken = $token->token; - } else { - $hetznerToken = $this->hetzner_token; + $hetznerToken = $this->getHetznerToken(); - // Validate the new token before saving - if (! $this->validateHetznerToken($hetznerToken)) { - return $this->dispatch('error', 'Invalid Hetzner API token. Please check your token and try again.'); - } + // Create server on Hetzner + $hetznerServer = $this->createHetznerServer($hetznerToken); - // If saving the new token - if ($this->save_token) { - CloudProviderToken::create([ - 'team_id' => currentTeam()->id, - 'provider' => 'hetzner', - 'token' => $this->hetzner_token, - 'name' => $this->token_name, - ]); - } - } + // Create server in Coolify database + $server = Server::create([ + 'name' => $this->server_name, + 'ip' => $hetznerServer['public_net']['ipv4']['ip'], + 'user' => 'root', + 'port' => 22, + 'team_id' => currentTeam()->id, + 'private_key_id' => $this->private_key_id, + 'hetzner_server_id' => $hetznerServer['id'], + ]); - // TODO: Actual Hetzner server provisioning will be implemented in future phase - // The $hetznerToken variable contains the token to use - return $this->dispatch('success', 'Hetzner token validated successfully! Server provisioning coming soon.'); + $server->proxy->set('status', 'exited'); + $server->proxy->set('type', ProxyTypes::TRAEFIK->value); + $server->save(); + + return redirect()->route('server.show', $server->uuid); } catch (\Throwable $e) { return handleError($e, $this); } diff --git a/app/Models/PrivateKey.php b/app/Models/PrivateKey.php index c210f3c5b..08f3f1ebd 100644 --- a/app/Models/PrivateKey.php +++ b/app/Models/PrivateKey.php @@ -289,6 +289,17 @@ public static function generateFingerprint($privateKey) } } + public static function generateMd5Fingerprint($privateKey) + { + try { + $key = PublicKeyLoader::load($privateKey); + + return $key->getPublicKey()->getFingerprint('md5'); + } catch (\Throwable $e) { + return null; + } + } + public static function fingerprintExists($fingerprint, $excludeId = null) { $query = self::query() diff --git a/app/Models/Server.php b/app/Models/Server.php index 829a4b5aa..e30b10043 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -162,6 +162,7 @@ protected static function booted() 'description', 'private_key_id', 'team_id', + 'hetzner_server_id', ]; protected $guarded = []; diff --git a/app/Services/HetznerService.php b/app/Services/HetznerService.php new file mode 100644 index 000000000..039eb81a9 --- /dev/null +++ b/app/Services/HetznerService.php @@ -0,0 +1,96 @@ +token = $token; + } + + private function request(string $method, string $endpoint, array $data = []) + { + $response = Http::withHeaders([ + 'Authorization' => 'Bearer '.$this->token, + ])->timeout(30)->{$method}($this->baseUrl.$endpoint, $data); + + if (! $response->successful()) { + throw new \Exception('Hetzner API error: '.$response->json('error.message', 'Unknown error')); + } + + return $response->json(); + } + + private function requestPaginated(string $method, string $endpoint, string $resourceKey, array $data = []): array + { + $allResults = []; + $page = 1; + + do { + $data['page'] = $page; + $data['per_page'] = 50; + + $response = $this->request($method, $endpoint, $data); + + if (isset($response[$resourceKey])) { + $allResults = array_merge($allResults, $response[$resourceKey]); + } + + $nextPage = $response['meta']['pagination']['next_page'] ?? null; + $page = $nextPage; + } while ($nextPage !== null); + + return $allResults; + } + + public function getLocations(): array + { + return $this->requestPaginated('get', '/locations', 'locations'); + } + + public function getImages(): array + { + return $this->requestPaginated('get', '/images', 'images', [ + 'type' => 'system', + ]); + } + + public function getServerTypes(): array + { + return $this->requestPaginated('get', '/server_types', 'server_types'); + } + + public function getSshKeys(): array + { + return $this->requestPaginated('get', '/ssh_keys', 'ssh_keys'); + } + + public function uploadSshKey(string $name, string $publicKey): array + { + $response = $this->request('post', '/ssh_keys', [ + 'name' => $name, + 'public_key' => $publicKey, + ]); + + return $response['ssh_key'] ?? []; + } + + public function createServer(array $params): array + { + $response = $this->request('post', '/servers', $params); + + return $response['server'] ?? []; + } + + public function deleteServer(int $serverId): void + { + $this->request('delete', "/servers/{$serverId}"); + } +} diff --git a/database/migrations/2025_10_03_154100_update_clickhouse_image.php b/database/migrations/2025_10_03_154100_update_clickhouse_image.php index e52bbcc16..e57354037 100644 --- a/database/migrations/2025_10_03_154100_update_clickhouse_image.php +++ b/database/migrations/2025_10_03_154100_update_clickhouse_image.php @@ -1,32 +1,32 @@ -string('image')->default('bitnamilegacy/clickhouse')->change(); - }); - // Optionally, update any existing rows with the old default to the new one - DB::table('standalone_clickhouses') - ->where('image', 'bitnami/clickhouse') - ->update(['image' => 'bitnamilegacy/clickhouse']); - } - - public function down() - { - Schema::table('standalone_clickhouses', function (Blueprint $table) { - $table->string('image')->default('bitnami/clickhouse')->change(); - }); - // Optionally, revert any changed values - DB::table('standalone_clickhouses') - ->where('image', 'bitnamilegacy/clickhouse') - ->update(['image' => 'bitnami/clickhouse']); - } -}; \ No newline at end of file +string('image')->default('bitnamilegacy/clickhouse')->change(); + }); + // Optionally, update any existing rows with the old default to the new one + DB::table('standalone_clickhouses') + ->where('image', 'bitnami/clickhouse') + ->update(['image' => 'bitnamilegacy/clickhouse']); + } + + public function down() + { + Schema::table('standalone_clickhouses', function (Blueprint $table) { + $table->string('image')->default('bitnami/clickhouse')->change(); + }); + // Optionally, revert any changed values + DB::table('standalone_clickhouses') + ->where('image', 'bitnamilegacy/clickhouse') + ->update(['image' => 'bitnami/clickhouse']); + } +}; diff --git a/database/migrations/2025_10_08_185203_add_hetzner_server_id_to_servers_table.php b/database/migrations/2025_10_08_185203_add_hetzner_server_id_to_servers_table.php new file mode 100644 index 000000000..b1c9ec48b --- /dev/null +++ b/database/migrations/2025_10_08_185203_add_hetzner_server_id_to_servers_table.php @@ -0,0 +1,28 @@ +bigInteger('hetzner_server_id')->nullable()->after('id'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('servers', function (Blueprint $table) { + $table->dropColumn('hetzner_server_id'); + }); + } +}; diff --git a/public/svgs/hetzner.svg b/public/svgs/hetzner.svg new file mode 100644 index 000000000..68b1b868d --- /dev/null +++ b/public/svgs/hetzner.svg @@ -0,0 +1,6 @@ + + + + + + diff --git a/resources/views/components/modal-confirmation.blade.php b/resources/views/components/modal-confirmation.blade.php index 103f18316..46164840d 100644 --- a/resources/views/components/modal-confirmation.blade.php +++ b/resources/views/components/modal-confirmation.blade.php @@ -250,6 +250,18 @@ class="w-24 dark:bg-coolgray-200 dark:hover:bg-coolgray-300"> {{ $checkbox['label'] }} + @if (isset($checkbox['default_warning'])) + + @endif @endforeach @if (!$disableTwoStepConfirmation) diff --git a/resources/views/livewire/server/create.blade.php b/resources/views/livewire/server/create.blade.php index 619a827e7..a941b7ee2 100644 --- a/resources/views/livewire/server/create.blade.php +++ b/resources/views/livewire/server/create.blade.php @@ -2,11 +2,17 @@
@can('viewAny', App\Models\CloudProviderToken::class)
-

Add Server from Cloud Provider

- + + +
+ + + + + Hetzner +
+
diff --git a/resources/views/livewire/server/delete.blade.php b/resources/views/livewire/server/delete.blade.php index c61775ee8..073849452 100644 --- a/resources/views/livewire/server/delete.blade.php +++ b/resources/views/livewire/server/delete.blade.php @@ -15,16 +15,15 @@
@if ($server->definedResources()->count() > 0)
You need to delete all resources before deleting this server.
- - @else - @endif + + @endif
diff --git a/resources/views/livewire/server/new/by-hetzner.blade.php b/resources/views/livewire/server/new/by-hetzner.blade.php index 83de355e3..7ed5b1495 100644 --- a/resources/views/livewire/server/new/by-hetzner.blade.php +++ b/resources/views/livewire/server/new/by-hetzner.blade.php @@ -2,51 +2,128 @@ @if ($limit_reached) @else -
- @if ($available_tokens->count() > 0) + @if ($current_step === 1) + + @if ($available_tokens->count() > 0) +
+ + + @foreach ($available_tokens as $token) + + @endforeach + +
+
OR
+ @endif +
- - - @foreach ($available_tokens as $token) - - @endforeach - +
-
OR
- @endif -
- -
- -
- -
- - @if ($save_token)
- +
- @endif - - Continue - -
+
+ +
+ + + Continue + + + @elseif ($current_step === 2) + @if ($loading_data) +
+
+
+

Loading Hetzner data...

+
+
+ @else +
+
+ +
+ +
+ + + @foreach ($locations as $location) + + @endforeach + +
+ +
+ + + @foreach ($this->availableServerTypes as $serverType) + + @endforeach + +
+ +
+ + + @foreach ($this->availableImages as $image) + + @endforeach + +
+ +
+ + + @foreach ($private_keys as $key) + + @endforeach + +
+ +
+ +
+ +
+ + Back + + + Create Server + +
+
+ @endif + @endif @endif
diff --git a/resources/views/livewire/server/show.blade.php b/resources/views/livewire/server/show.blade.php index a25e245e9..f1f1180e8 100644 --- a/resources/views/livewire/server/show.blade.php +++ b/resources/views/livewire/server/show.blade.php @@ -9,6 +9,16 @@

General

+ @if ($server->hetzner_server_id) +
+ + + + + Hetzner +
+ @endif @if ($server->id === 0) - + From d837aa1473caa09ea809047bc8933285c23141e9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 9 Oct 2025 11:22:10 +0200 Subject: [PATCH 176/322] fix(api-tokens): update settings link for API enablement message - Changed the link in the API tokens view to direct users to the advanced settings page instead of the general settings page, providing clearer guidance for enabling the API. --- resources/views/livewire/security/api-tokens.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/security/api-tokens.blade.php b/resources/views/livewire/security/api-tokens.blade.php index bf6bcf76c..b1f25a584 100644 --- a/resources/views/livewire/security/api-tokens.blade.php +++ b/resources/views/livewire/security/api-tokens.blade.php @@ -7,7 +7,7 @@

API Tokens

@if (!$isApiEnabled)
API is disabled. If you want to use the API, please enable it in the Settings menu.
+ href="{{ route('settings.advanced') }}" class="underline dark:text-white">Settings menu.
@else
Tokens are created with the current team as scope.
From 61e688affd5158ea4b7c138a5ef152c9ee6e4565 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:46:36 +0200 Subject: [PATCH 177/322] refactor(checkbox, utilities, global-search): enhance focus styles for better accessibility --- app/View/Components/Forms/Checkbox.php | 2 +- resources/css/utilities.css | 8 ++++---- resources/views/livewire/global-search.blade.php | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/View/Components/Forms/Checkbox.php b/app/View/Components/Forms/Checkbox.php index ece7f0e35..ea4f4ead2 100644 --- a/app/View/Components/Forms/Checkbox.php +++ b/app/View/Components/Forms/Checkbox.php @@ -22,7 +22,7 @@ public function __construct( public string|bool|null $checked = false, public string|bool $instantSave = false, public bool $disabled = false, - public string $defaultClass = 'dark:border-neutral-700 text-coolgray-400 focus:ring-warning dark:bg-coolgray-100 rounded-sm cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed', + public string $defaultClass = 'dark:border-neutral-700 text-coolgray-400 dark:bg-coolgray-100 rounded-sm cursor-pointer dark:disabled:bg-base dark:disabled:cursor-not-allowed focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100', public ?string $canGate = null, public mixed $canResource = null, public bool $autoDisable = true, diff --git a/resources/css/utilities.css b/resources/css/utilities.css index bedfb51bc..67b1e7f80 100644 --- a/resources/css/utilities.css +++ b/resources/css/utilities.css @@ -32,7 +32,7 @@ @utility apexcharts-tooltip-custom-title { } @utility input-sticky { - @apply block py-1.5 w-full text-sm text-black rounded-sm border-0 ring-1 ring-inset dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus:ring-2 focus:ring-neutral-400 dark:focus:ring-coolgray-300; + @apply block py-1.5 w-full text-sm text-black rounded-sm border-0 ring-1 ring-inset dark:bg-coolgray-100 dark:text-white ring-neutral-200 dark:ring-coolgray-300 focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100; } @utility input-sticky-active { @@ -41,7 +41,7 @@ @utility input-sticky-active { /* Focus */ @utility input-focus { - @apply focus:ring-2 focus:ring-neutral-400 dark:focus:ring-coolgray-300; + @apply focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100; } /* input, select before */ @@ -52,14 +52,14 @@ @utility input-select { /* Readonly */ @utility input { @apply dark:read-only:text-neutral-500 dark:read-only:ring-0 dark:read-only:bg-coolgray-100/40 placeholder:text-neutral-300 dark:placeholder:text-neutral-700 read-only:text-neutral-500 read-only:bg-neutral-200; - @apply input-focus; @apply input-select; + @apply focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100; } @utility select { @apply w-full; - @apply input-focus; @apply input-select; + @apply focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100; } @utility button { diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index b7203c329..3bf29d392 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -266,7 +266,7 @@ class="fixed top-0 left-0 z-99 flex items-start justify-center w-screen h-screen + class="w-full pl-12 pr-32 py-4 text-base bg-white dark:bg-coolgray-100 border-none rounded-lg shadow-xl ring-1 ring-neutral-200 dark:ring-coolgray-300 dark:text-white placeholder-neutral-400 dark:placeholder-neutral-500 disabled:opacity-50 disabled:cursor-not-allowed focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-coollabs dark:focus-visible:ring-warning focus-visible:ring-offset-2 dark:focus-visible:ring-offset-coolgray-100" />
/ or ⌘K to focus From c9e641854294d98c8c33cdd3d0f6edd31e50c9c3 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:52:59 +0200 Subject: [PATCH 178/322] refactor(forms): simplify wire:dirty class bindings for input, select, and textarea components --- resources/views/components/forms/input.blade.php | 6 ++---- resources/views/components/forms/select.blade.php | 3 +-- resources/views/components/forms/textarea.blade.php | 7 +++---- 3 files changed, 6 insertions(+), 10 deletions(-) diff --git a/resources/views/components/forms/input.blade.php b/resources/views/components/forms/input.blade.php index 858f5ac1c..f6c86f177 100644 --- a/resources/views/components/forms/input.blade.php +++ b/resources/views/components/forms/input.blade.php @@ -28,8 +28,7 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hov merge(['class' => $defaultClass]) }} @required($required) @if ($id !== 'null') wire:model={{ $id }} @endif - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' - wire:dirty.class="dark:focus:ring-warning dark:ring-warning" wire:loading.attr="disabled" + wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" aria-placeholder="{{ $attributes->get('placeholder') }}" @@ -40,8 +39,7 @@ class="flex absolute inset-y-0 right-0 items-center pr-2 cursor-pointer dark:hov merge(['class' => $defaultClass]) }} @required($required) @readonly($readonly) @if ($id !== 'null') wire:model={{ $id }} @endif - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' - wire:dirty.class="dark:focus:ring-warning dark:ring-warning" wire:loading.attr="disabled" + wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" type="{{ $type }}" @disabled($disabled) min="{{ $attributes->get('min') }}" max="{{ $attributes->get('max') }}" minlength="{{ $attributes->get('minlength') }}" maxlength="{{ $attributes->get('maxlength') }}" diff --git a/resources/views/components/forms/select.blade.php b/resources/views/components/forms/select.blade.php index 508a85e0c..3c8eea25a 100644 --- a/resources/views/components/forms/select.blade.php +++ b/resources/views/components/forms/select.blade.php @@ -11,8 +11,7 @@ class="flex gap-1 items-center mb-1 text-sm font-medium {{ $disabled ? 'text-neu @endif diff --git a/resources/views/components/forms/textarea.blade.php b/resources/views/components/forms/textarea.blade.php index b4dec192a..a1c57e775 100644 --- a/resources/views/components/forms/textarea.blade.php +++ b/resources/views/components/forms/textarea.blade.php @@ -46,8 +46,7 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer merge(['class' => $defaultClassInput]) }} @required($required) @if ($id !== 'null') wire:model={{ $id }} @endif - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' - wire:dirty.class="dark:focus:ring-warning dark:ring-warning" wire:loading.attr="disabled" + wire:dirty.class="dark:ring-warning ring-warning" wire:loading.attr="disabled" type="{{ $type }}" @readonly($readonly) @disabled($disabled) id="{{ $id }}" name="{{ $name }}" placeholder="{{ $attributes->get('placeholder') }}" aria-placeholder="{{ $attributes->get('placeholder') }}"> @@ -56,7 +55,7 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer @if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}" @else wire:model={{ $value ?? $id }} - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning" @endif + wire:dirty.class="dark:ring-warning ring-warning" @endif @disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}" name="{{ $name }}" name={{ $id }}> @@ -68,7 +67,7 @@ class="absolute inset-y-0 right-0 flex items-center h-6 pt-2 pr-2 cursor-pointer @if ($realtimeValidation) wire:model.debounce.200ms="{{ $id }}" @else wire:model={{ $value ?? $id }} - wire:dirty.class.remove='dark:focus:ring-coolgray-300 dark:ring-coolgray-300' wire:dirty.class="dark:focus:ring-warning dark:ring-warning" @endif + wire:dirty.class="dark:ring-warning ring-warning" @endif @disabled($disabled) @readonly($readonly) @required($required) id="{{ $id }}" name="{{ $name }}" name={{ $id }}> @endif From 704ddf2968ef4dbaf5c836fca2c9ceb30964e925 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 9 Oct 2025 12:53:57 +0200 Subject: [PATCH 179/322] improved hetzner features --- app/Actions/Server/DeleteServer.php | 12 +- .../Security/CloudProviderTokenForm.php | 99 ++++++++++++ app/Livewire/Security/CloudProviderTokens.php | 79 ++-------- .../Server/CloudProviderToken/Show.php | 144 ++++++++++++++++++ app/Livewire/Server/Create.php | 8 + app/Livewire/Server/New/ByHetzner.php | 99 +++++------- app/Models/CloudProviderToken.php | 10 ++ app/Models/Server.php | 6 + ...oud_provider_token_id_to_servers_table.php | 29 ++++ .../views/components/modal-input.blade.php | 13 +- .../views/components/server/sidebar.blade.php | 5 + .../cloud-provider-token-form.blade.php | 43 ++++++ .../security/cloud-provider-tokens.blade.php | 36 +---- .../cloud-provider-token/show.blade.php | 61 ++++++++ .../views/livewire/server/create.blade.php | 2 +- .../livewire/server/new/by-hetzner.blade.php | 65 ++++---- routes/web.php | 2 + 17 files changed, 514 insertions(+), 199 deletions(-) create mode 100644 app/Livewire/Security/CloudProviderTokenForm.php create mode 100644 app/Livewire/Server/CloudProviderToken/Show.php create mode 100644 database/migrations/2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php create mode 100644 resources/views/livewire/security/cloud-provider-token-form.blade.php create mode 100644 resources/views/livewire/server/cloud-provider-token/show.blade.php diff --git a/app/Actions/Server/DeleteServer.php b/app/Actions/Server/DeleteServer.php index db197a019..b7523714f 100644 --- a/app/Actions/Server/DeleteServer.php +++ b/app/Actions/Server/DeleteServer.php @@ -25,10 +25,14 @@ public function handle(Server $server, bool $deleteFromHetzner = false) private function deleteFromHetzner(Server $server): void { try { - // Get the cloud provider token for Hetzner - $token = CloudProviderToken::where('team_id', $server->team_id) - ->where('provider', 'hetzner') - ->first(); + // Use the server's associated token, or fallback to first available team token + $token = $server->cloudProviderToken; + + if (! $token) { + $token = CloudProviderToken::where('team_id', $server->team_id) + ->where('provider', 'hetzner') + ->first(); + } if (! $token) { ray('No Hetzner token found for team, skipping Hetzner deletion', [ diff --git a/app/Livewire/Security/CloudProviderTokenForm.php b/app/Livewire/Security/CloudProviderTokenForm.php new file mode 100644 index 000000000..7affb1531 --- /dev/null +++ b/app/Livewire/Security/CloudProviderTokenForm.php @@ -0,0 +1,99 @@ +authorize('create', CloudProviderToken::class); + } + + protected function rules(): array + { + return [ + 'provider' => 'required|string|in:hetzner,digitalocean', + 'token' => 'required|string', + 'name' => 'required|string|max:255', + ]; + } + + protected function messages(): array + { + return [ + 'provider.required' => 'Please select a cloud provider.', + 'provider.in' => 'Invalid cloud provider selected.', + 'token.required' => 'API token is required.', + 'name.required' => 'Token name is required.', + ]; + } + + private function validateToken(string $provider, string $token): bool + { + try { + if ($provider === 'hetzner') { + $response = Http::withHeaders([ + 'Authorization' => 'Bearer '.$token, + ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); + ray($response); + + return $response->successful(); + } + + // Add other providers here in the future + // if ($provider === 'digitalocean') { ... } + + return false; + } catch (\Throwable $e) { + return false; + } + } + + public function addToken() + { + $this->validate(); + + try { + // Validate the token with the provider's API + if (! $this->validateToken($this->provider, $this->token)) { + return $this->dispatch('error', 'Invalid API token. Please check your token and try again.'); + } + + $savedToken = CloudProviderToken::create([ + 'team_id' => currentTeam()->id, + 'provider' => $this->provider, + 'token' => $this->token, + 'name' => $this->name, + ]); + + $this->reset(['token', 'name']); + + // Dispatch event with token ID so parent components can react + $this->dispatch('tokenAdded', tokenId: $savedToken->id); + + $this->dispatch('success', 'Cloud provider token added successfully.'); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function render() + { + return view('livewire.security.cloud-provider-token-form'); + } +} diff --git a/app/Livewire/Security/CloudProviderTokens.php b/app/Livewire/Security/CloudProviderTokens.php index f5726e424..f05b3c0ca 100644 --- a/app/Livewire/Security/CloudProviderTokens.php +++ b/app/Livewire/Security/CloudProviderTokens.php @@ -4,7 +4,6 @@ use App\Models\CloudProviderToken; use Illuminate\Foundation\Auth\Access\AuthorizesRequests; -use Illuminate\Support\Facades\Http; use Livewire\Component; class CloudProviderTokens extends Component @@ -13,34 +12,16 @@ class CloudProviderTokens extends Component public $tokens; - public string $provider = 'hetzner'; - - public string $token = ''; - - public string $name = ''; - public function mount() { $this->authorize('viewAny', CloudProviderToken::class); $this->loadTokens(); } - protected function rules(): array + public function getListeners() { return [ - 'provider' => 'required|string|in:hetzner,digitalocean', - 'token' => 'required|string', - 'name' => 'required|string|max:255', - ]; - } - - protected function messages(): array - { - return [ - 'provider.required' => 'Please select a cloud provider.', - 'provider.in' => 'Invalid cloud provider selected.', - 'token.required' => 'API token is required.', - 'name.required' => 'Token name is required.', + 'tokenAdded' => 'loadTokens', ]; } @@ -49,60 +30,20 @@ public function loadTokens() $this->tokens = CloudProviderToken::ownedByCurrentTeam()->get(); } - private function validateToken(string $provider, string $token): bool - { - try { - if ($provider === 'hetzner') { - $response = Http::withHeaders([ - 'Authorization' => 'Bearer '.$token, - ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); - - return $response->successful(); - } - - // Add other providers here in the future - // if ($provider === 'digitalocean') { ... } - - return false; - } catch (\Throwable $e) { - return false; - } - } - - public function addNewToken() - { - $this->validate(); - - try { - $this->authorize('create', CloudProviderToken::class); - - // Validate the token with the provider's API - if (! $this->validateToken($this->provider, $this->token)) { - return $this->dispatch('error', 'Invalid API token. Please check your token and try again.'); - } - - CloudProviderToken::create([ - 'team_id' => currentTeam()->id, - 'provider' => $this->provider, - 'token' => $this->token, - 'name' => $this->name, - ]); - - $this->reset(['token', 'name']); - $this->loadTokens(); - - $this->dispatch('success', 'Cloud provider token added successfully.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - public function deleteToken(int $tokenId) { try { $token = CloudProviderToken::ownedByCurrentTeam()->findOrFail($tokenId); $this->authorize('delete', $token); + // Check if any servers are using this token + if ($token->hasServers()) { + $serverCount = $token->servers()->count(); + $this->dispatch('error', "Cannot delete this token. It is currently used by {$serverCount} server(s). Please reassign those servers to a different token first."); + + return; + } + $token->delete(); $this->loadTokens(); diff --git a/app/Livewire/Server/CloudProviderToken/Show.php b/app/Livewire/Server/CloudProviderToken/Show.php new file mode 100644 index 000000000..6b22fddc6 --- /dev/null +++ b/app/Livewire/Server/CloudProviderToken/Show.php @@ -0,0 +1,144 @@ +server = Server::ownedByCurrentTeam()->whereUuid($server_uuid)->firstOrFail(); + $this->loadTokens(); + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function getListeners() + { + return [ + 'tokenAdded' => 'handleTokenAdded', + ]; + } + + public function loadTokens() + { + $this->cloudProviderTokens = CloudProviderToken::ownedByCurrentTeam() + ->where('provider', 'hetzner') + ->get(); + } + + public function handleTokenAdded($tokenId) + { + $this->loadTokens(); + } + + public function setCloudProviderToken($tokenId) + { + $ownedToken = CloudProviderToken::ownedByCurrentTeam()->find($tokenId); + if (is_null($ownedToken)) { + $this->dispatch('error', 'You are not allowed to use this token.'); + + return; + } + try { + $this->authorize('update', $this->server); + + // Validate the token works and can access this specific server + $validationResult = $this->validateTokenForServer($ownedToken); + if (! $validationResult['valid']) { + $this->dispatch('error', $validationResult['error']); + + return; + } + + $this->server->cloudProviderToken()->associate($ownedToken); + $this->server->save(); + $this->dispatch('success', 'Hetzner token updated successfully.'); + $this->dispatch('refreshServerShow'); + } catch (\Exception $e) { + $this->server->refresh(); + $this->dispatch('error', $e->getMessage()); + } + } + + private function validateTokenForServer(CloudProviderToken $token): array + { + try { + // First, validate the token itself + $response = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => 'Bearer '.$token->token, + ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); + + if (! $response->successful()) { + return [ + 'valid' => false, + 'error' => 'This token is invalid or has insufficient permissions.', + ]; + } + + // Check if this token can access the specific Hetzner server + if ($this->server->hetzner_server_id) { + $serverResponse = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => 'Bearer '.$token->token, + ])->timeout(10)->get("https://api.hetzner.cloud/v1/servers/{$this->server->hetzner_server_id}"); + + if (! $serverResponse->successful()) { + return [ + 'valid' => false, + 'error' => 'This token cannot access this server. It may belong to a different Hetzner project.', + ]; + } + } + + return ['valid' => true]; + } catch (\Throwable $e) { + return [ + 'valid' => false, + 'error' => 'Failed to validate token: '.$e->getMessage(), + ]; + } + } + + public function validateToken() + { + try { + $token = $this->server->cloudProviderToken; + if (! $token) { + $this->dispatch('error', 'No Hetzner token is associated with this server.'); + + return; + } + + $response = \Illuminate\Support\Facades\Http::withHeaders([ + 'Authorization' => 'Bearer '.$token->token, + ])->timeout(10)->get('https://api.hetzner.cloud/v1/servers'); + + if ($response->successful()) { + $this->dispatch('success', 'Hetzner token is valid and working.'); + } else { + $this->dispatch('error', 'Hetzner token is invalid or has insufficient permissions.'); + } + } catch (\Throwable $e) { + return handleError($e, $this); + } + } + + public function render() + { + return view('livewire.server.cloud-provider-token.show'); + } +} diff --git a/app/Livewire/Server/Create.php b/app/Livewire/Server/Create.php index 2d4ba4430..cf77664fe 100644 --- a/app/Livewire/Server/Create.php +++ b/app/Livewire/Server/Create.php @@ -2,6 +2,7 @@ namespace App\Livewire\Server; +use App\Models\CloudProviderToken; use App\Models\PrivateKey; use App\Models\Team; use Livewire\Component; @@ -12,6 +13,8 @@ class Create extends Component public bool $limit_reached = false; + public bool $has_hetzner_tokens = false; + public function mount() { $this->private_keys = PrivateKey::ownedByCurrentTeam()->get(); @@ -21,6 +24,11 @@ public function mount() return; } $this->limit_reached = Team::serverLimitReached(); + + // Check if user has Hetzner tokens + $this->has_hetzner_tokens = CloudProviderToken::ownedByCurrentTeam() + ->where('provider', 'hetzner') + ->exists(); } public function render() diff --git a/app/Livewire/Server/New/ByHetzner.php b/app/Livewire/Server/New/ByHetzner.php index b67411e17..d0a7582cd 100644 --- a/app/Livewire/Server/New/ByHetzner.php +++ b/app/Livewire/Server/New/ByHetzner.php @@ -34,12 +34,6 @@ class ByHetzner extends Component // Step 1: Token selection public ?int $selected_token_id = null; - public string $hetzner_token = ''; - - public bool $save_token = false; - - public ?string $token_name = null; - // Step 2: Server configuration public array $locations = []; @@ -64,31 +58,50 @@ class ByHetzner extends Component public function mount() { $this->authorize('viewAny', CloudProviderToken::class); - $this->available_tokens = CloudProviderToken::ownedByCurrentTeam() - ->where('provider', 'hetzner') - ->get(); + $this->loadTokens(); $this->server_name = generate_random_name(); if ($this->private_keys->count() > 0) { $this->private_key_id = $this->private_keys->first()->id; } } + public function getListeners() + { + return [ + 'tokenAdded' => 'handleTokenAdded', + 'modalClosed' => 'resetSelection', + ]; + } + + public function resetSelection() + { + $this->selected_token_id = null; + $this->current_step = 1; + } + + public function loadTokens() + { + $this->available_tokens = CloudProviderToken::ownedByCurrentTeam() + ->where('provider', 'hetzner') + ->get(); + } + + public function handleTokenAdded($tokenId) + { + // Refresh token list + $this->loadTokens(); + + // Auto-select the new token + $this->selected_token_id = $tokenId; + + // Automatically proceed to next step + $this->nextStep(); + } + protected function rules(): array { $rules = [ - 'selected_token_id' => 'nullable|integer', - 'hetzner_token' => 'required_without:selected_token_id|string', - 'save_token' => 'boolean', - 'token_name' => [ - 'nullable', - 'string', - 'max:255', - function ($attribute, $value, $fail) { - if ($this->save_token && ! empty($this->hetzner_token) && empty($value)) { - $fail('Please provide a name for the token.'); - } - }, - ], + 'selected_token_id' => 'required|integer|exists:cloud_provider_tokens,id', ]; if ($this->current_step === 2) { @@ -108,8 +121,8 @@ function ($attribute, $value, $fail) { protected function messages(): array { return [ - 'hetzner_token.required_without' => 'Please provide a Hetzner API token or select a saved token.', - 'token_name.required_if' => 'Please provide a name for the token.', + 'selected_token_id.required' => 'Please select a Hetzner token.', + 'selected_token_id.exists' => 'Selected token not found.', ]; } @@ -139,50 +152,21 @@ private function getHetznerToken(): string return $token ? $token->token : ''; } - return $this->hetzner_token; + return ''; } public function nextStep() { - // Validate step 1 + // Validate step 1 - just need a token selected $this->validate([ - 'selected_token_id' => 'nullable|integer', - 'hetzner_token' => 'required_without:selected_token_id|string', - 'save_token' => 'boolean', - 'token_name' => [ - 'nullable', - 'string', - 'max:255', - function ($attribute, $value, $fail) { - if ($this->save_token && ! empty($this->hetzner_token) && empty($value)) { - $fail('Please provide a name for the token.'); - } - }, - ], + 'selected_token_id' => 'required|integer|exists:cloud_provider_tokens,id', ]); try { $hetznerToken = $this->getHetznerToken(); if (! $hetznerToken) { - return $this->dispatch('error', 'Please provide a valid Hetzner API token.'); - } - - // Validate token if it's a new one - if (! $this->selected_token_id) { - if (! $this->validateHetznerToken($hetznerToken)) { - return $this->dispatch('error', 'Invalid Hetzner API token. Please check your token and try again.'); - } - - // Save token if requested - if ($this->save_token) { - CloudProviderToken::create([ - 'team_id' => currentTeam()->id, - 'provider' => 'hetzner', - 'token' => $this->hetzner_token, - 'name' => $this->token_name, - ]); - } + return $this->dispatch('error', 'Please select a valid Hetzner token.'); } // Load Hetzner data @@ -424,6 +408,7 @@ public function submit() 'port' => 22, 'team_id' => currentTeam()->id, 'private_key_id' => $this->private_key_id, + 'cloud_provider_token_id' => $this->selected_token_id, 'hetzner_server_id' => $hetznerServer['id'], ]); diff --git a/app/Models/CloudProviderToken.php b/app/Models/CloudProviderToken.php index 9ce216b25..607040269 100644 --- a/app/Models/CloudProviderToken.php +++ b/app/Models/CloudProviderToken.php @@ -17,6 +17,16 @@ public function team() return $this->belongsTo(Team::class); } + public function servers() + { + return $this->hasMany(Server::class); + } + + public function hasServers(): bool + { + return $this->servers()->exists(); + } + public static function ownedByCurrentTeam(array $select = ['*']) { $selectArray = collect($select)->concat(['id']); diff --git a/app/Models/Server.php b/app/Models/Server.php index e30b10043..e1a004755 100644 --- a/app/Models/Server.php +++ b/app/Models/Server.php @@ -161,6 +161,7 @@ protected static function booted() 'user', 'description', 'private_key_id', + 'cloud_provider_token_id', 'team_id', 'hetzner_server_id', ]; @@ -890,6 +891,11 @@ public function privateKey() return $this->belongsTo(PrivateKey::class); } + public function cloudProviderToken() + { + return $this->belongsTo(CloudProviderToken::class); + } + public function muxFilename() { return 'mux_'.$this->uuid; diff --git a/database/migrations/2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php b/database/migrations/2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php new file mode 100644 index 000000000..a25a4ce83 --- /dev/null +++ b/database/migrations/2025_10_09_095905_add_cloud_provider_token_id_to_servers_table.php @@ -0,0 +1,29 @@ +foreignId('cloud_provider_token_id')->nullable()->after('private_key_id')->constrained()->onDelete('set null'); + }); + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::table('servers', function (Blueprint $table) { + $table->dropForeign(['cloud_provider_token_id']); + $table->dropColumn('cloud_provider_token_id'); + }); + } +}; diff --git a/resources/views/components/modal-input.blade.php b/resources/views/components/modal-input.blade.php index c15985d03..a9ad39871 100644 --- a/resources/views/components/modal-input.blade.php +++ b/resources/views/components/modal-input.blade.php @@ -8,8 +8,11 @@ 'content' => null, 'closeOutside' => true, 'minWidth' => '36rem', + 'isFullWidth' => false, ]) -
@if ($content)
@@ -17,13 +20,13 @@ class="relative w-auto h-auto" wire:ignore>
@else @if ($disabled) - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @elseif ($isErrorButton) - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @elseif ($isHighlightedButton) - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @else - {{ $buttonTitle }} + $isFullWidth])>{{ $buttonTitle }} @endif @endif
-
+
\ No newline at end of file From ff889e658d94290bd68cc0c8c64ae7a63560fc20 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 11 Oct 2025 13:47:26 +0200 Subject: [PATCH 248/322] refactor: improve cloud-init script management UI and cache control MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add manual cache clearing command (search:clear) for testing - Integrate cloud-init scripts into global search navigation - Improve form UX by preventing field reset during edit operations 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- app/Livewire/GlobalSearch.php | 1 + resources/views/livewire/global-search.blade.php | 16 ---------------- .../security/cloud-init-script-form.blade.php | 4 ++-- 3 files changed, 3 insertions(+), 18 deletions(-) diff --git a/app/Livewire/GlobalSearch.php b/app/Livewire/GlobalSearch.php index 680ac7701..5fcedd94d 100644 --- a/app/Livewire/GlobalSearch.php +++ b/app/Livewire/GlobalSearch.php @@ -79,6 +79,7 @@ public function mount() public function openSearchModal() { + sleep(4); $this->isModalOpen = true; $this->loadSearchableItems(); $this->loadCreatableItems(); diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 3df03ea0d..3bf21f8aa 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -290,22 +290,6 @@ class="pointer-events-auto px-2 py-1 text-xs font-medium text-neutral-500 dark:t
- - {{--
-
-

- ✓ Data loaded successfully! -

-

- searchable items available -

-

- Start typing to search... -

-
-
--}} -
diff --git a/resources/views/livewire/security/cloud-init-script-form.blade.php b/resources/views/livewire/security/cloud-init-script-form.blade.php index 545c49a7f..1632b48d3 100644 --- a/resources/views/livewire/security/cloud-init-script-form.blade.php +++ b/resources/views/livewire/security/cloud-init-script-form.blade.php @@ -1,4 +1,4 @@ - +
- + \ No newline at end of file From a17b105a92420163200715b8a2f983aeb83f4ce9 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 11 Oct 2025 13:48:12 +0200 Subject: [PATCH 249/322] fix: hide 'No results found' message while data is loading MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Prevent showing 'No results found' when user types during initial data loading phase. The message now only appears after data has fully loaded and the search still returns no results. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude --- resources/views/livewire/global-search.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/livewire/global-search.blade.php b/resources/views/livewire/global-search.blade.php index 3bf21f8aa..06da31354 100644 --- a/resources/views/livewire/global-search.blade.php +++ b/resources/views/livewire/global-search.blade.php @@ -828,7 +828,7 @@ class="shrink-0 h-5 w-5 text-yellow-500 dark:text-yellow-400 self-center"