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 01/56] 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 02/56] 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 03/56] 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 04/56] 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 05/56] 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 06/56] 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 07/56] 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 08/56] 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 09/56] 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 10/56] 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 11/56] 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 12/56] 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 13/56] 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 14/56] 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 97c22ab57041d2613d538c64f1886f2a8547b1b3 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Sat, 6 Sep 2025 04:00:48 +0530 Subject: [PATCH 15/56] 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 16/56] 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 17/56] 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 e6798ebf5e8d7181de0ce9f0cdf40d91a21d1f88 Mon Sep 17 00:00:00 2001 From: thesloppyguy Date: Mon, 8 Sep 2025 02:23:40 +0530 Subject: [PATCH 18/56] 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 57a1e7a076bc358d125fafe881f3ebf4673e4f76 Mon Sep 17 00:00:00 2001 From: SAHIL Date: Sun, 14 Sep 2025 20:07:40 +0530 Subject: [PATCH 19/56] 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 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 20/56] 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 9dd8709407c62de2b971a855028f8b7ef2398049 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Mon, 29 Sep 2025 10:52:08 +0000 Subject: [PATCH 21/56] 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 22/56] 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 23/56] 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 b4403580d07520190eb2fc4948920027e950ea18 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Oct 2025 18:37:26 +0000 Subject: [PATCH 24/56] docs: update changelog --- CHANGELOG.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3447b223b..90c5b3bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,54 @@ ## [unreleased] ### 🚀 Features +- *(user-deletion)* Implement file locking to prevent concurrent user deletions and enhance error handling +- *(ui)* Enhance resource operations interface with dynamic selection for cloning and moving resources +- *(global-search)* Integrate projects and environments into global search functionality +- *(storage)* Consolidate storage management into a single component with enhanced UI +- *(deployments)* Add support for Coolify variables in Dockerfile + +### 🐛 Bug Fixes + +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(ui)* Update docker registry image helper text for clarity +- *(ui)* Correct HTML structure and improve clarity in Docker cleanup options +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(api)* Correct OpenAPI schema annotations for array items +- *(ui)* Improve queued deployment status readability in dark mode +- *(git)* Handle additional repository URL cases for 'tangled' and improve branch assignment logic +- *(git)* Enhance error handling for missing branch information during deployment +- *(git)* Trim whitespace from repository, branch, and commit SHA fields +- *(deployments)* Order deployments by ID for consistent retrieval + +### 💼 Other + +- *(storage)* Enhance file storage management with new properties and UI improvements +- *(core)* Update projects property type and enhance UI styling +- *(components)* Adjust SVG icon sizes for consistency across applications and services +- *(components)* Auto-focus first input in modal on open +- *(styles)* Enhance focus styles for buttons and links +- *(components)* Enhance close button accessibility in modal + +### 🚜 Refactor + +- *(global-search)* Change event listener to window level for global search modal +- *(dashboard)* Remove deployment loading logic and introduce DeploymentsIndicator component for better UI management +- *(dashboard)* Replace project navigation method with direct link in UI +- *(global-search)* Improve event handling and cleanup in global search component + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.433 and nightly version to 4.0.0-beta.434 in configuration files + +## [4.0.0-beta.432] - 2025-09-29 + +### 🚀 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 From d63802e03d16dde3ef7b3ebc4804ae18d8dbe22d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Thu, 2 Oct 2025 18:34:39 +0200 Subject: [PATCH 25/56] feat(deployments): add log copying functionality to clipboard in dev --- .../Project/Application/DeploymentNavbar.php | 22 +++++++++++++++++++ .../application/deployment-navbar.blade.php | 3 +++ 2 files changed, 25 insertions(+) diff --git a/app/Livewire/Project/Application/DeploymentNavbar.php b/app/Livewire/Project/Application/DeploymentNavbar.php index dccd1e499..ebdc014ae 100644 --- a/app/Livewire/Project/Application/DeploymentNavbar.php +++ b/app/Livewire/Project/Application/DeploymentNavbar.php @@ -50,6 +50,28 @@ public function force_start() } } + public function copyLogsToClipboard(): string + { + $logs = json_decode($this->application_deployment_queue->logs, associative: true, flags: JSON_THROW_ON_ERROR); + + if (! $logs) { + return ''; + } + + $markdown = "# Deployment Logs\n\n"; + $markdown .= "```\n"; + + foreach ($logs as $log) { + if (isset($log['output'])) { + $markdown .= $log['output']."\n"; + } + } + + $markdown .= "```\n"; + + return $markdown; + } + public function cancel() { $deployment_uuid = $this->application_deployment_queue->deployment_uuid; diff --git a/resources/views/livewire/project/application/deployment-navbar.blade.php b/resources/views/livewire/project/application/deployment-navbar.blade.php index effb6b6fe..60c660bf7 100644 --- a/resources/views/livewire/project/application/deployment-navbar.blade.php +++ b/resources/views/livewire/project/application/deployment-navbar.blade.php @@ -5,6 +5,9 @@ @else Show Debug Logs @endif + @if (isDev()) + Copy Logs + @endif @if (data_get($application_deployment_queue, 'status') === 'queued') Force Start @endif From 2216832f67efef68b2af1649bf03101dc8c2ff01 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 09:20:05 +0200 Subject: [PATCH 26/56] fix(deployments): enhance builder container management and environment variable handling - Added a new method to restart the builder container with the actual commit value, ensuring accurate deployment. - Improved the generation of environment variables by consolidating user-defined and Coolify-specific variables. - Updated Dockerfile modification logic to handle environment variables more effectively, including support for multiline variables. - Enhanced logging for better visibility during deployment processes. --- app/Jobs/ApplicationDeploymentJob.php | 116 +++++++++++++++++--------- 1 file changed, 76 insertions(+), 40 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 04b11b9b4..965eab68e 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1526,7 +1526,6 @@ private function prepare_builder_image() $this->dockerConfigFileExists = instant_remote_process(["test -f {$this->serverUserHomeDir}/.docker/config.json && echo 'OK' || echo 'NOK'"], $this->server); $env_flags = $this->generate_docker_env_flags_for_secrets(); - if ($this->use_build_server) { if ($this->dockerConfigFileExists === 'NOK') { throw new RuntimeException('Docker config file (~/.docker/config.json) not found on the build server. Please run "docker login" to login to the docker registry on the server.'); @@ -1553,6 +1552,18 @@ private function prepare_builder_image() $this->run_pre_deployment_command(); } + private function restart_builder_container_with_actual_commit() + { + // Stop and remove the current helper container + $this->graceful_shutdown_container($this->deployment_uuid); + + // Clear cached env_args to force regeneration with actual SOURCE_COMMIT value + $this->env_args = null; + + // Restart the helper container with updated environment variables (including actual SOURCE_COMMIT) + $this->prepare_builder_image(); + } + private function deploy_to_additional_destinations() { if ($this->application->additional_networks->count() === 0) { @@ -1621,6 +1632,8 @@ private function set_coolify_variables() if (isset($this->application->git_branch)) { $this->coolify_variables .= "COOLIFY_BRANCH={$this->application->git_branch} "; } + $this->coolify_variables .= "COOLIFY_RESOURCE_UUID={$this->application->uuid} "; + $this->coolify_variables .= "COOLIFY_CONTAINER_NAME={$this->container_name} "; } private function check_git_if_build_needed() @@ -1688,6 +1701,12 @@ private function check_git_if_build_needed() $this->application_deployment_queue->save(); } $this->set_coolify_variables(); + + // Restart helper container with actual SOURCE_COMMIT value + if ($this->application->settings->use_build_secrets && $this->commit !== 'HEAD') { + $this->application_deployment_queue->addLogEntry('Restarting helper container with actual SOURCE_COMMIT value.'); + $this->restart_builder_container_with_actual_commit(); + } } private function clone_repository() @@ -1936,7 +1955,6 @@ private function generate_env_variables() $this->env_args = collect([]); $this->env_args->put('SOURCE_COMMIT', $this->commit); $coolify_envs = $this->generate_coolify_env_variables(); - // For build process, include only environment variables where is_buildtime = true if ($this->pull_request_id === 0) { // Get environment variables that are marked as available during build @@ -1991,6 +2009,12 @@ private function generate_env_variables() } } } + + // Merge COOLIFY_* variables into env_args for build process + // This ensures they're available for both build args and build secrets + $coolify_envs->each(function ($value, $key) { + $this->env_args->put($key, $value); + }); } private function generate_compose_file() @@ -2610,6 +2634,8 @@ private function build_image() } else { // Dockerfile buildpack if ($this->dockerBuildkitSupported) { + // Modify the Dockerfile to use build secrets + $this->modify_dockerfile_for_secrets("{$this->workdir}{$this->dockerfile_location}"); // Use BuildKit with secrets $secrets_flags = $this->build_secrets ? " {$this->build_secrets}" : ''; if ($this->force_rebuild) { @@ -2764,7 +2790,6 @@ private function generate_build_env_variables() $this->generate_env_variables(); $variables = collect([])->merge($this->env_args); } - // Analyze build variables for potential issues if ($variables->isNotEmpty()) { $this->analyzeBuildTimeVariables($variables); @@ -2809,9 +2834,13 @@ private function generate_docker_env_flags_for_secrets() return ''; } - $variables = $this->pull_request_id === 0 - ? $this->application->environment_variables()->where('key', 'not like', 'NIXPACKS_%')->where('is_buildtime', true)->get() - : $this->application->environment_variables_preview()->where('key', 'not like', 'NIXPACKS_%')->where('is_buildtime', true)->get(); + // Generate env variables if not already done + // This populates $this->env_args with both user-defined and COOLIFY_* variables + if (! $this->env_args || $this->env_args->isEmpty()) { + $this->generate_env_variables(); + } + + $variables = $this->env_args; if ($variables->isEmpty()) { return ''; @@ -2819,12 +2848,19 @@ private function generate_docker_env_flags_for_secrets() $secrets_hash = $this->generate_secrets_hash($variables); + // Get database env vars to check for multiline flag + $env_vars = $this->pull_request_id === 0 + ? $this->application->environment_variables()->where('is_buildtime', true)->get() + : $this->application->environment_variables_preview()->where('is_buildtime', true)->get(); + // Map to simple array format for the helper function - $vars_array = $variables->map(function ($env) { + $vars_array = $variables->map(function ($value, $key) use ($env_vars) { + $env = $env_vars->firstWhere('key', $key); + return [ - 'key' => $env->key, - 'value' => $env->real_value, - 'is_multiline' => $env->is_multiline, + 'key' => $key, + 'value' => $value, + 'is_multiline' => $env ? $env->is_multiline : false, ]; }); @@ -2890,7 +2926,6 @@ private function add_build_env_variables_to_dockerfile() 'save' => 'dockerfile', ]); $dockerfile = collect(str($this->saved_outputs->get('dockerfile'))->trim()->explode("\n")); - if ($this->pull_request_id === 0) { // Only add environment variables that are available during build $envs = $this->application->environment_variables() @@ -2975,16 +3010,19 @@ private function modify_dockerfile_for_secrets($dockerfile_path) $dockerfile->prepend('# syntax=docker/dockerfile:1'); } - // Get environment variables for secrets - $variables = $this->pull_request_id === 0 - ? $this->application->environment_variables()->where('key', 'not like', 'NIXPACKS_%')->where('is_buildtime', true)->get() - : $this->application->environment_variables_preview()->where('key', 'not like', 'NIXPACKS_%')->where('is_buildtime', true)->get(); + // Generate env variables if not already done + // This populates $this->env_args with both user-defined and COOLIFY_* variables + if (! $this->env_args || $this->env_args->isEmpty()) { + $this->generate_env_variables(); + } + + $variables = $this->env_args; if ($variables->isEmpty()) { return; } // Generate mount strings for all secrets - $mountStrings = $variables->map(fn ($env) => "--mount=type=secret,id={$env->key},env={$env->key}")->implode(' '); + $mountStrings = $variables->map(fn ($value, $key) => "--mount=type=secret,id={$key},env={$key}")->implode(' '); // Add mount for the secrets hash to ensure cache invalidation $mountStrings .= ' --mount=type=secret,id=COOLIFY_BUILD_SECRETS_HASH,env=COOLIFY_BUILD_SECRETS_HASH'; @@ -3012,8 +3050,6 @@ private function modify_dockerfile_for_secrets($dockerfile_path) executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$dockerfile_path} > /dev/null"), 'hidden' => true, ]); - - $this->application_deployment_queue->addLogEntry('Modified Dockerfile to use build secrets.'); } } @@ -3023,15 +3059,13 @@ private function modify_dockerfiles_for_compose($composeFile) return; } - $variables = $this->pull_request_id === 0 - ? $this->application->environment_variables() - ->where('key', 'not like', 'NIXPACKS_%') - ->where('is_buildtime', true) - ->get() - : $this->application->environment_variables_preview() - ->where('key', 'not like', 'NIXPACKS_%') - ->where('is_buildtime', true) - ->get(); + // Generate env variables if not already done + // This populates $this->env_args with both user-defined and COOLIFY_* variables + if (! $this->env_args || $this->env_args->isEmpty()) { + $this->generate_env_variables(); + } + + $variables = $this->env_args; if ($variables->isEmpty()) { $this->application_deployment_queue->addLogEntry('No build-time variables to add to Dockerfiles.'); @@ -3105,8 +3139,8 @@ private function modify_dockerfiles_for_compose($composeFile) $isMultiStage = count($fromIndices) > 1; $argsToAdd = collect([]); - foreach ($variables as $env) { - $argsToAdd->push("ARG {$env->key}"); + foreach ($variables as $key => $value) { + $argsToAdd->push("ARG {$key}"); } ray($argsToAdd); @@ -3177,19 +3211,22 @@ private function modify_dockerfiles_for_compose($composeFile) private function add_build_secrets_to_compose($composeFile) { - // Get environment variables for secrets - $variables = $this->pull_request_id === 0 - ? $this->application->environment_variables()->where('key', 'not like', 'NIXPACKS_%')->get() - : $this->application->environment_variables_preview()->where('key', 'not like', 'NIXPACKS_%')->get(); + // Generate env variables if not already done + // This populates $this->env_args with both user-defined and COOLIFY_* variables + if (! $this->env_args || $this->env_args->isEmpty()) { + $this->generate_env_variables(); + } + + $variables = $this->env_args; if ($variables->isEmpty()) { return $composeFile; } $secrets = []; - foreach ($variables as $env) { - $secrets[$env->key] = [ - 'environment' => $env->key, + foreach ($variables as $key => $value) { + $secrets[$key] = [ + 'environment' => $key, ]; } @@ -3204,9 +3241,9 @@ private function add_build_secrets_to_compose($composeFile) if (! isset($service['build']['secrets'])) { $service['build']['secrets'] = []; } - foreach ($variables as $env) { - if (! in_array($env->key, $service['build']['secrets'])) { - $service['build']['secrets'][] = $env->key; + foreach ($variables as $key => $value) { + if (! in_array($key, $service['build']['secrets'])) { + $service['build']['secrets'][] = $key; } } } @@ -3325,7 +3362,6 @@ private function next(string $status) queue_next_deployment($this->application); if ($status === ApplicationDeploymentStatus::FINISHED->value) { - ray($this->application->team()->id); event(new ApplicationConfigurationChanged($this->application->team()->id)); if (! $this->only_this_server) { From d7819bef9359b7b194962741835f70d780f8ef99 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 07:28:58 +0000 Subject: [PATCH 27/56] docs: update changelog --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c5b3bda..56190f7a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ ## [unreleased] ### 🚀 Features +- *(deployments)* Enhance Docker build argument handling for multiline variables +- *(deployments)* Add log copying functionality to clipboard in dev + +### 🐛 Bug Fixes + +- *(deployments)* Enhance builder container management and environment variable handling + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update version numbers for Coolify releases +- *(versions)* Bump Coolify stable version to 4.0.0-beta.434 + +## [4.0.0-beta.433] - 2025-10-01 + +### 🚀 Features + - *(user-deletion)* Implement file locking to prevent concurrent user deletions and enhance error handling - *(ui)* Enhance resource operations interface with dynamic selection for cloning and moving resources - *(global-search)* Integrate projects and environments into global search functionality @@ -43,6 +59,7 @@ ### 🚜 Refactor ### 📚 Documentation +- Update changelog - Update changelog - Update changelog From f8e97501ce006f0c1eb42be172e9181594ff6bd1 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 09:41:59 +0200 Subject: [PATCH 28/56] feat(deployments): generate SERVICE_NAME environment variables from Docker Compose services - Added functionality to generate environment variables for each service defined in the Docker Compose file, transforming service names into uppercase and replacing special characters. - Updated the service parser to merge these generated variables with existing environment variables, enhancing deployment configuration. --- app/Models/Service.php | 16 +++++++++++++++- bootstrap/helpers/parsers.php | 5 ++++- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/app/Models/Service.php b/app/Models/Service.php index d42d471c6..c9bf4cbcd 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -1263,6 +1263,21 @@ public function saveComposeConfigs() $commands[] = "cd $workdir"; $commands[] = 'rm -f .env || true'; + $envs = collect([]); + + // Generate SERVICE_NAME_* environment variables from docker-compose services + if ($this->docker_compose) { + try { + $dockerCompose = \Symfony\Component\Yaml\Yaml::parse($this->docker_compose); + $services = data_get($dockerCompose, 'services', []); + foreach ($services as $serviceName => $_) { + $envs->push('SERVICE_NAME_'.str($serviceName)->replace('-', '_')->replace('.', '_')->upper().'='.$serviceName); + } + } catch (\Exception $e) { + ray($e->getMessage()); + } + } + $envs_from_coolify = $this->environment_variables()->get(); $sorted = $envs_from_coolify->sortBy(function ($env) { if (str($env->key)->startsWith('SERVICE_')) { @@ -1274,7 +1289,6 @@ public function saveComposeConfigs() return 3; }); - $envs = collect([]); foreach ($sorted as $env) { $envs->push("{$env->key}={$env->real_value}"); } diff --git a/bootstrap/helpers/parsers.php b/bootstrap/helpers/parsers.php index 25cc5d0a6..a588ed882 100644 --- a/bootstrap/helpers/parsers.php +++ b/bootstrap/helpers/parsers.php @@ -1172,6 +1172,9 @@ function serviceParser(Service $resource): Collection $parsedServices = collect([]); + // Generate SERVICE_NAME variables for docker compose services + $serviceNameEnvironments = generateDockerComposeServiceName($services); + $allMagicEnvironments = collect([]); // Presave services foreach ($services as $serviceName => $service) { @@ -1988,7 +1991,7 @@ function serviceParser(Service $resource): Collection $payload['volumes'] = $volumesParsed; } if ($environment->count() > 0 || $coolifyEnvironments->count() > 0) { - $payload['environment'] = $environment->merge($coolifyEnvironments); + $payload['environment'] = $environment->merge($coolifyEnvironments)->merge($serviceNameEnvironments); } if ($logging) { $payload['logging'] = $logging; From b474eb411da779bb9be5a028e68351b15c558517 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 07:42:51 +0000 Subject: [PATCH 29/56] docs: update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56190f7a2..45c73b44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,16 @@ ### 🚀 Features - *(deployments)* Enhance Docker build argument handling for multiline variables - *(deployments)* Add log copying functionality to clipboard in dev +- *(deployments)* Generate SERVICE_NAME environment variables from Docker Compose services ### 🐛 Bug Fixes - *(deployments)* Enhance builder container management and environment variable handling +### 📚 Documentation + +- Update changelog + ### ⚙️ Miscellaneous Tasks - *(versions)* Update version numbers for Coolify releases From 4b0f65c9269842edc51d42c04c63b62d6f583eca Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 10:15:47 +0200 Subject: [PATCH 30/56] refactor(environment-variables): adjust ordering logic for environment variables - Updated the ordering logic in the environment_variables methods for both Application and Service models to prioritize required variables over service-prefixed keys. - This change enhances the clarity and organization of environment variable retrieval, ensuring that essential variables are listed first. --- app/Models/Application.php | 12 ++++++------ app/Models/Service.php | 6 +++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/app/Models/Application.php b/app/Models/Application.php index 4f1796790..914d9948d 100644 --- a/app/Models/Application.php +++ b/app/Models/Application.php @@ -739,9 +739,9 @@ public function environment_variables() return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', false) ->orderByRaw(" - CASE - WHEN LOWER(key) LIKE 'service_%' THEN 1 - WHEN is_required = true AND (value IS NULL OR value = '') THEN 2 + CASE + WHEN is_required = true THEN 1 + WHEN LOWER(key) LIKE 'service_%' THEN 2 ELSE 3 END, LOWER(key) ASC @@ -767,9 +767,9 @@ public function environment_variables_preview() return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->where('is_preview', true) ->orderByRaw(" - CASE - WHEN LOWER(key) LIKE 'service_%' THEN 1 - WHEN is_required = true AND (value IS NULL OR value = '') THEN 2 + CASE + WHEN is_required = true THEN 1 + WHEN LOWER(key) LIKE 'service_%' THEN 2 ELSE 3 END, LOWER(key) ASC diff --git a/app/Models/Service.php b/app/Models/Service.php index c9bf4cbcd..063c8cba4 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -1231,9 +1231,9 @@ public function environment_variables() { return $this->morphMany(EnvironmentVariable::class, 'resourceable') ->orderByRaw(" - CASE - WHEN LOWER(key) LIKE 'service_%' THEN 1 - WHEN is_required = true AND (value IS NULL OR value = '') THEN 2 + CASE + WHEN is_required = true THEN 1 + WHEN LOWER(key) LIKE 'service_%' THEN 2 ELSE 3 END, LOWER(key) ASC From 50383c7a35bb71d0cd3786ea0ca7f43e409999c5 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 10:16:08 +0200 Subject: [PATCH 31/56] chore(versions): update Coolify version numbers to 4.0.0-beta.435 and 4.0.0-beta.436 - Incremented the stable version in constants.php and versions.json to 4.0.0-beta.435. - Updated the nightly version in versions.json and other/nightly/versions.json to 4.0.0-beta.436. - Ensured consistency across versioning files for the latest release. --- config/constants.php | 2 +- other/nightly/versions.json | 4 ++-- versions.json | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/config/constants.php b/config/constants.php index ddda70d19..01eaa7fa1 100644 --- a/config/constants.php +++ b/config/constants.php @@ -2,7 +2,7 @@ return [ 'coolify' => [ - 'version' => '4.0.0-beta.434', + 'version' => '4.0.0-beta.435', 'helper_version' => '1.0.11', 'realtime_version' => '1.0.10', 'self_hosted' => env('SELF_HOSTED', true), diff --git a/other/nightly/versions.json b/other/nightly/versions.json index b5cf3360a..2e5cc5e84 100644 --- a/other/nightly/versions.json +++ b/other/nightly/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.433" + "version": "4.0.0-beta.435" }, "nightly": { - "version": "4.0.0-beta.434" + "version": "4.0.0-beta.436" }, "helper": { "version": "1.0.11" diff --git a/versions.json b/versions.json index cb9fb7dc2..2e5cc5e84 100644 --- a/versions.json +++ b/versions.json @@ -1,10 +1,10 @@ { "coolify": { "v4": { - "version": "4.0.0-beta.434" + "version": "4.0.0-beta.435" }, "nightly": { - "version": "4.0.0-beta.435" + "version": "4.0.0-beta.436" }, "helper": { "version": "1.0.11" From b4f2d8caf18f4900473e79cc203da23ca83f4ca6 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 08:32:39 +0000 Subject: [PATCH 32/56] docs: update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45c73b44f..aefabfd29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # Changelog All notable changes to this project will be documented in this file. -## [unreleased] +## [4.0.0-beta.434] - 2025-10-03 ### 🚀 Features @@ -16,6 +16,7 @@ ### 🐛 Bug Fixes ### 📚 Documentation +- Update changelog - Update changelog ### ⚙️ Miscellaneous Tasks @@ -258,6 +259,7 @@ ## [4.0.0-beta.427] - 2025-09-15 ### 🚀 Features +- Add Ente Photos service template - *(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 75f590bc815f4970dba3e6566b7f5dff9cc1e120 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 33/56] 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 35a1d7cdabd71477aa34abb20051d385116d3f59 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 34/56] 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 fbb428568..d97e4e771 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 2fd056a19..9b81021bd 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 f16fdc7fdf98e70e3d40f225d389e19354e35d98 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 35/56] 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 0d7914c71a4199a5a3933d1751f80b9c563bf73a 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 36/56] 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 886eaf563b353829ce95172170054f9ee82b9dec 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 37/56] 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 d97e4e771..e2c950fd3 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 9b81021bd..8d02d8f95 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 d9d82d5cc4500d7bb911c1b4a1c2cc229c329487 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 38/56] 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 ae3ea6ed92fea8e97f7c8eb94b0f150e16d7a4a7 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 39/56] 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 fd752377d2ec9ec03c4196ba135e53d02427a858 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 40/56] 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 e2c950fd3..7d8cc6af1 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 8d02d8f95..7d05eb1ef 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 f3e8963bd13169d9db6281a558af4ddf3a1e55d7 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Wed, 1 Oct 2025 18:37:26 +0000 Subject: [PATCH 41/56] docs: update changelog --- CHANGELOG.md | 48 ++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 48 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3447b223b..90c5b3bda 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,54 @@ ## [unreleased] ### 🚀 Features +- *(user-deletion)* Implement file locking to prevent concurrent user deletions and enhance error handling +- *(ui)* Enhance resource operations interface with dynamic selection for cloning and moving resources +- *(global-search)* Integrate projects and environments into global search functionality +- *(storage)* Consolidate storage management into a single component with enhanced UI +- *(deployments)* Add support for Coolify variables in Dockerfile + +### 🐛 Bug Fixes + +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(ui)* Update docker registry image helper text for clarity +- *(ui)* Correct HTML structure and improve clarity in Docker cleanup options +- *(workflows)* Update CLAUDE API key reference in GitHub Actions workflow +- *(api)* Correct OpenAPI schema annotations for array items +- *(ui)* Improve queued deployment status readability in dark mode +- *(git)* Handle additional repository URL cases for 'tangled' and improve branch assignment logic +- *(git)* Enhance error handling for missing branch information during deployment +- *(git)* Trim whitespace from repository, branch, and commit SHA fields +- *(deployments)* Order deployments by ID for consistent retrieval + +### 💼 Other + +- *(storage)* Enhance file storage management with new properties and UI improvements +- *(core)* Update projects property type and enhance UI styling +- *(components)* Adjust SVG icon sizes for consistency across applications and services +- *(components)* Auto-focus first input in modal on open +- *(styles)* Enhance focus styles for buttons and links +- *(components)* Enhance close button accessibility in modal + +### 🚜 Refactor + +- *(global-search)* Change event listener to window level for global search modal +- *(dashboard)* Remove deployment loading logic and introduce DeploymentsIndicator component for better UI management +- *(dashboard)* Replace project navigation method with direct link in UI +- *(global-search)* Improve event handling and cleanup in global search component + +### 📚 Documentation + +- Update changelog +- Update changelog + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update coolify version to 4.0.0-beta.433 and nightly version to 4.0.0-beta.434 in configuration files + +## [4.0.0-beta.432] - 2025-09-29 + +### 🚀 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 From 3020ad3b8cbec8d1107386dbff5cfd1837983487 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 07:28:58 +0000 Subject: [PATCH 42/56] docs: update changelog --- CHANGELOG.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90c5b3bda..56190f7a2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,22 @@ ## [unreleased] ### 🚀 Features +- *(deployments)* Enhance Docker build argument handling for multiline variables +- *(deployments)* Add log copying functionality to clipboard in dev + +### 🐛 Bug Fixes + +- *(deployments)* Enhance builder container management and environment variable handling + +### ⚙️ Miscellaneous Tasks + +- *(versions)* Update version numbers for Coolify releases +- *(versions)* Bump Coolify stable version to 4.0.0-beta.434 + +## [4.0.0-beta.433] - 2025-10-01 + +### 🚀 Features + - *(user-deletion)* Implement file locking to prevent concurrent user deletions and enhance error handling - *(ui)* Enhance resource operations interface with dynamic selection for cloning and moving resources - *(global-search)* Integrate projects and environments into global search functionality @@ -43,6 +59,7 @@ ### 🚜 Refactor ### 📚 Documentation +- Update changelog - Update changelog - Update changelog From ee7daca28455d1f22a7447ba95946ca3b2f24bff Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 07:42:51 +0000 Subject: [PATCH 43/56] docs: update changelog --- CHANGELOG.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 56190f7a2..45c73b44f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,11 +8,16 @@ ### 🚀 Features - *(deployments)* Enhance Docker build argument handling for multiline variables - *(deployments)* Add log copying functionality to clipboard in dev +- *(deployments)* Generate SERVICE_NAME environment variables from Docker Compose services ### 🐛 Bug Fixes - *(deployments)* Enhance builder container management and environment variable handling +### 📚 Documentation + +- Update changelog + ### ⚙️ Miscellaneous Tasks - *(versions)* Update version numbers for Coolify releases From d2254f6d18c0acc827ba9cb6387af25a0208aba9 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" Date: Fri, 3 Oct 2025 08:32:39 +0000 Subject: [PATCH 44/56] docs: update changelog --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 45c73b44f..aefabfd29 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # Changelog All notable changes to this project will be documented in this file. -## [unreleased] +## [4.0.0-beta.434] - 2025-10-03 ### 🚀 Features @@ -16,6 +16,7 @@ ### 🐛 Bug Fixes ### 📚 Documentation +- Update changelog - Update changelog ### ⚙️ Miscellaneous Tasks @@ -258,6 +259,7 @@ ## [4.0.0-beta.427] - 2025-09-15 ### 🚀 Features +- Add Ente Photos service template - *(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 ac40a65d412877a02bc08d985e36c62b1bbd2b8f Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 10:34:11 +0200 Subject: [PATCH 45/56] fix: ente photos --- templates/compose/ente-photos-with-s3.yaml | 95 +++++++++++++++++ templates/compose/ente-photos.yaml | 117 +++++++++------------ templates/compose/ente.yaml | 81 -------------- templates/service-templates-latest.json | 21 +++- templates/service-templates.json | 21 +++- 5 files changed, 187 insertions(+), 148 deletions(-) create mode 100644 templates/compose/ente-photos-with-s3.yaml delete mode 100644 templates/compose/ente.yaml diff --git a/templates/compose/ente-photos-with-s3.yaml b/templates/compose/ente-photos-with-s3.yaml new file mode 100644 index 000000000..6ee902d6c --- /dev/null +++ b/templates/compose/ente-photos-with-s3.yaml @@ -0,0 +1,95 @@ +# 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=${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:-} + - 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: quay.io/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" + volumes: + - minio-data:/data + healthcheck: + test: ["CMD", "mc", "ready", "local"] + interval: 5s + timeout: 20s + retries: 10 + + 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/compose/ente-photos.yaml b/templates/compose/ente-photos.yaml index 6ee902d6c..03fdc4f1e 100644 --- a/templates/compose/ente-photos.yaml +++ b/templates/compose/ente-photos.yaml @@ -10,86 +10,73 @@ services: 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=${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:-} - - APPS_ACCOUNTS=${APPS_ACCOUNTS:-} - volumes: - - museum-data:/data - - museum-config:/config + + - 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} + + - 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_started + volumes: + - museum-data:/data:rw healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/ping"] + test: ["CMD", "wget", "-qO-", "http://localhost:8080/ping"] + interval: 60s + timeout: 5s + retries: 3 + start_period: 10s + + web: + image: ghcr.io/ente-io/web + environment: + - SERVICE_URL_WEB_3000 + - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} + - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} + + healthcheck: + test: ["CMD", "curl", "--fail", "http://localhost:3000"] interval: 30s timeout: 10s retries: 3 + start_period: 10s postgres: - image: postgres:15-alpine + image: postgres:15 environment: - - POSTGRES_USER=${SERVICE_USER_POSTGRES} + - POSTGRES_USER=${SERVICE_USER_POSTGRES:-pguser} - POSTGRES_PASSWORD=${SERVICE_PASSWORD_POSTGRES} - - POSTGRES_DB=${POSTGRES_DB:-ente_db} + - POSTGRES_DB=${SERVICE_DB_NAME:-ente_db} volumes: - postgres-data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${SERVICE_USER_POSTGRES} -d ${POSTGRES_DB:-ente_db}"] + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] interval: 10s timeout: 5s retries: 5 + start_period: 30s - minio: - image: quay.io/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" - volumes: - - minio-data:/data - healthcheck: - test: ["CMD", "mc", "ready", "local"] - interval: 5s - timeout: 20s - retries: 10 - - 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/compose/ente.yaml b/templates/compose/ente.yaml deleted file mode 100644 index 355b55b1c..000000000 --- a/templates/compose/ente.yaml +++ /dev/null @@ -1,81 +0,0 @@ -# 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 - -services: - museum: - image: ghcr.io/ente-io/server:latest - 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} - - - 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 - volumes: - - museum-data:/data:rw - healthcheck: - test: ["CMD", "wget", "-qO-", "http://localhost:8080/ping"] - interval: 60s - timeout: 5s - retries: 3 - start_period: 10s - - web: - image: ghcr.io/ente-io/web - environment: - - SERVICE_URL_WEB_3000 - - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} - - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} - - healthcheck: - test: ["CMD", "curl", "--fail", "http://localhost:3000"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 10s - - postgres: - image: postgres:15 - environment: - - 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 ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 10s - timeout: 5s - retries: 5 - start_period: 30s - diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 7d8cc6af1..1e0753648 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -948,10 +948,29 @@ "minversion": "0.0.0", "port": "6555" }, + "ente-photos-with-s3": { + "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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTRVJWSUNFX1VSTF9NSU5JT18zMjAwfScKICAgICAgLSBTM19CMl9FVV9DRU5fUkVHSU9OPWV1LWNlbnRyYWwtMgogICAgICAtIFMzX0IyX0VVX0NFTl9CVUNLRVQ9YjItZXUtY2VuCiAgICAgIC0gJ0VOQ1JZUFRJT05fS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9FTkNSWVBUSU9OfScKICAgICAgLSAnSEFTSF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0hBU0h9JwogICAgICAtICdKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9JwogICAgICAtIEVOVEVfSU5URVJOQUxfQURNSU49MTU4MDU1OTk2MjM4NjQzOAogICAgICAtICdBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0nCiAgICAgIC0gJ0FQUFNfQ0FTVD0ke0FQUFNfQ0FTVDotfScKICAgICAgLSAnQVBQU19BQ0NPVU5UUz0ke0FQUFNfQUNDT1VOVFM6LX0nCiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfSAtZCAke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgbWluaW86CiAgICBpbWFnZTogJ3F1YXkuaW8vbWluaW8vbWluaW86bGF0ZXN0JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", + "tags": [ + "photos", + "gallery", + "backup", + "encryption", + "privacy", + "self-hosted", + "google-photos", + "alternative" + ], + "category": "media", + "logo": "svgs/ente-photos.svg", + "minversion": "0.0.0", + "port": "8080" + }, "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": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gJ0VOVEVfSFRUUF9VU0VfVExTPSR7RU5URV9IVFRQX1VTRV9UTFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9BUFBTX1BVQkxJQ19BTEJVTVM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMn0nCiAgICAgIC0gJ0VOVEVfQVBQU19DQVNUPSR7U0VSVklDRV9VUkxfV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMX0nCiAgICAgIC0gJ0VOVEVfREJfSE9TVD0ke0VOVEVfREJfSE9TVDotcG9zdGdyZXN9JwogICAgICAtICdFTlRFX0RCX1BPUlQ9JHtFTlRFX0RCX1BPUlQ6LTU0MzJ9JwogICAgICAtICdFTlRFX0RCX05BTUU9JHtFTlRFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgICAtICdFTlRFX0RCX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVM6LXBndXNlcn0nCiAgICAgIC0gJ0VOVEVfREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnRU5URV9LRVlfRU5DUllQVElPTj0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9FTkNSWVBUSU9OfScKICAgICAgLSAnRU5URV9LRVlfSEFTSD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF82NF9IQVNIfScKICAgICAgLSAnRU5URV9KV1RfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0X0pXVH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfQURNSU49JHtFTlRFX0lOVEVSTkFMX0FETUlOOi0xNTgwNTU5OTYyMzg2NDM4fScKICAgICAgLSAnRU5URV9JTlRFUk5BTF9ESVNBQkxFX1JFR0lTVFJBVElPTj0ke0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT046LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQVJFX0xPQ0FMX0JVQ0tFVFM9JHtQUklNQVJZX1NUT1JBR0VfQVJFX0xPQ0FMX0JVQ0tFVFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fVVNFX1BBVEhfU1RZTEVfVVJMUz0ke1BSSU1BUllfU1RPUkFHRV9VU0VfUEFUSF9TVFlMRV9VUkxTOi10cnVlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fS0VZPSR7UzNfU1RPUkFHRV9LRVk6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1MzX1NUT1JBR0VfU0VDUkVUOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1MzX1NUT1JBR0VfRU5EUE9JTlQ6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1JFR0lPTj0ke1MzX1NUT1JBR0VfUkVHSU9OOi11cy1lYXN0LTF9JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9CVUNLRVQ9JHtTM19TVE9SQUdFX0JVQ0tFVDo/fScKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YTpydycKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLXFPLScKICAgICAgICAtICdodHRwOi8vbG9jYWxob3N0OjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDYwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAzCiAgICAgIHN0YXJ0X3BlcmlvZDogMTBzCiAgd2ViOgogICAgaW1hZ2U6IGdoY3IuaW8vZW50ZS1pby93ZWIKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX1dFQl8zMDAwCiAgICAgIC0gJ0VOVEVfQVBJX09SSUdJTj0ke1NFUlZJQ0VfVVJMX01VU0VVTX0nCiAgICAgIC0gJ0VOVEVfQUxCVU1TX09SSUdJTj0ke1NFUlZJQ0VfVVJMX1dFQl8zMDAyfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLS1mYWlsJwogICAgICAgIC0gJ2h0dHA6Ly9sb2NhbGhvc3Q6MzAwMCcKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogICAgICBzdGFydF9wZXJpb2Q6IDEwcwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1NFUlZJQ0VfREJfTkFNRTotZW50ZV9kYn0nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlcy1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAke1BPU1RHUkVTX1VTRVJ9IC1kICR7UE9TVEdSRVNfREJ9JwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKICAgICAgc3RhcnRfcGVyaW9kOiAzMHMK", "tags": [ "photos", "gallery", diff --git a/templates/service-templates.json b/templates/service-templates.json index 7d05eb1ef..d9175648c 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -948,10 +948,29 @@ "minversion": "0.0.0", "port": "6555" }, + "ente-photos-with-s3": { + "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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtIFBPU1RHUkVTX0hPU1Q9cG9zdGdyZXMKICAgICAgLSBQT1NUR1JFU19QT1JUPTU0MzIKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0tFWT0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0VORFBPSU5UPSR7U0VSVklDRV9GUUROX01JTklPXzMyMDB9JwogICAgICAtIFMzX0IyX0VVX0NFTl9SRUdJT049ZXUtY2VudHJhbC0yCiAgICAgIC0gUzNfQjJfRVVfQ0VOX0JVQ0tFVD1iMi1ldS1jZW4KICAgICAgLSAnRU5DUllQVElPTl9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0VOQ1JZUFRJT059JwogICAgICAtICdIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0nCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0pXVH0nCiAgICAgIC0gRU5URV9JTlRFUk5BTF9BRE1JTj0xNTgwNTU5OTYyMzg2NDM4CiAgICAgIC0gJ0FQUFNfUFVCTElDX0FMQlVNUz0ke0FQUFNfUFVCTElDX0FMQlVNUzotfScKICAgICAgLSAnQVBQU19DQVNUPSR7QVBQU19DQVNUOi19JwogICAgICAtICdBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ211c2V1bS1kYXRhOi9kYXRhJwogICAgICAtICdtdXNldW0tY29uZmlnOi9jb25maWcnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNS1hbHBpbmUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9IC1kICR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKICBtaW5pbzoKICAgIGltYWdlOiAncXVheS5pby9taW5pby9taW5pbzpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", + "tags": [ + "photos", + "gallery", + "backup", + "encryption", + "privacy", + "self-hosted", + "google-photos", + "alternative" + ], + "category": "media", + "logo": "svgs/ente-photos.svg", + "minversion": "0.0.0", + "port": "8080" + }, "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": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtICdFTlRFX0hUVFBfVVNFX1RMUz0ke0VOVEVfSFRUUF9VU0VfVExTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfQVBQU19QVUJMSUNfQUxCVU1TPSR7U0VSVklDRV9GUUROX1dFQl8zMDAyfScKICAgICAgLSAnRU5URV9BUFBTX0NBU1Q9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDF9JwogICAgICAtICdFTlRFX0RCX0hPU1Q9JHtFTlRFX0RCX0hPU1Q6LXBvc3RncmVzfScKICAgICAgLSAnRU5URV9EQl9QT1JUPSR7RU5URV9EQl9QT1JUOi01NDMyfScKICAgICAgLSAnRU5URV9EQl9OQU1FPSR7RU5URV9EQl9OQU1FOi1lbnRlX2RifScKICAgICAgLSAnRU5URV9EQl9VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdFTlRFX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ0VOVEVfS0VZX0VOQ1JZUFRJT049JHtTRVJWSUNFX1JFQUxCQVNFNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0VOVEVfS0VZX0hBU0g9JHtTRVJWSUNFX1JFQUxCQVNFNjRfNjRfSEFTSH0nCiAgICAgIC0gJ0VOVEVfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9KV1R9JwogICAgICAtICdFTlRFX0lOVEVSTkFMX0FETUlOPSR7RU5URV9JTlRFUk5BTF9BRE1JTjotMTU4MDU1OTk2MjM4NjQzOH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT049JHtFTlRFX0lOVEVSTkFMX0RJU0FCTEVfUkVHSVNUUkFUSU9OOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0FSRV9MT0NBTF9CVUNLRVRTPSR7UFJJTUFSWV9TVE9SQUdFX0FSRV9MT0NBTF9CVUNLRVRTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1VTRV9QQVRIX1NUWUxFX1VSTFM9JHtQUklNQVJZX1NUT1JBR0VfVVNFX1BBVEhfU1RZTEVfVVJMUzotdHJ1ZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0tFWT0ke1MzX1NUT1JBR0VfS0VZOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTM19TVE9SQUdFX1NFQ1JFVDo/fScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTM19TVE9SQUdFX0VORFBPSU5UOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9SRUdJT049JHtTM19TVE9SQUdFX1JFR0lPTjotdXMtZWFzdC0xfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQlVDS0VUPSR7UzNfU1RPUkFHRV9CVUNLRVQ6P30nCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGE6cncnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gd2dldAogICAgICAgIC0gJy1xTy0nCiAgICAgICAgLSAnaHR0cDovL2xvY2FsaG9zdDo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiA2MHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMwogICAgICBzdGFydF9wZXJpb2Q6IDEwcwogIHdlYjoKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vd2ViCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fV0VCXzMwMDAKICAgICAgLSAnRU5URV9BUElfT1JJR0lOPSR7U0VSVklDRV9GUUROX01VU0VVTX0nCiAgICAgIC0gJ0VOVEVfQUxCVU1TX09SSUdJTj0ke1NFUlZJQ0VfRlFETl9XRUJfMzAwMn0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy0tZmFpbCcKICAgICAgICAtICdodHRwOi8vbG9jYWxob3N0OjMwMDAnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICAgICAgc3RhcnRfcGVyaW9kOiAxMHMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFUzotcGd1c2VyfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtTRVJWSUNFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtQT1NUR1JFU19VU0VSfSAtZCAke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgICAgIHN0YXJ0X3BlcmlvZDogMzBzCg==", "tags": [ "photos", "gallery", From e17fbd3b560f858b3510802d2c2c5ce0fefbe25c Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 10:47:55 +0200 Subject: [PATCH 46/56] refactor: update ente photos configuration for improved service management - Enhanced environment variable configuration for the server and web services, including database and encryption settings. - Updated health check intervals and retries for better reliability. - Changed MinIO service configuration to use port 9000 and adjusted health checks accordingly. - Improved volume management for data persistence. These changes aim to streamline the deployment process and ensure better service health monitoring. --- templates/compose/ente-photos-with-s3.yaml | 70 ++++++++++++++-------- templates/compose/ente-photos.yaml | 24 ++++---- templates/service-templates-latest.json | 4 +- templates/service-templates.json | 4 +- 4 files changed, 59 insertions(+), 43 deletions(-) diff --git a/templates/compose/ente-photos-with-s3.yaml b/templates/compose/ente-photos-with-s3.yaml index 6ee902d6c..96d74b1a8 100644 --- a/templates/compose/ente-photos-with-s3.yaml +++ b/templates/compose/ente-photos-with-s3.yaml @@ -10,12 +10,26 @@ services: 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} + - 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 @@ -24,16 +38,6 @@ services: - 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:-} - - APPS_ACCOUNTS=${APPS_ACCOUNTS:-} volumes: - museum-data:/data - museum-config:/config @@ -43,11 +47,23 @@ services: minio: condition: service_started healthcheck: - test: ["CMD", "curl", "-f", "http://127.0.0.1:8080/ping"] - interval: 30s - timeout: 10s - retries: 3 + test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/ping"] + interval: 5s + timeout: 5s + retries: 10 + web: + image: ghcr.io/ente-io/web + environment: + - SERVICE_URL_WEB_3000 + - ENTE_API_ORIGIN=${SERVICE_URL_MUSEUM} + - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} + + healthcheck: + test: ["CMD", "curl", "--fail", "http://127.0.0.1:3000"] + interval: 5s + timeout: 5s + retries: 10 postgres: image: postgres:15-alpine environment: @@ -57,18 +73,18 @@ services: volumes: - postgres-data:/var/lib/postgresql/data healthcheck: - test: ["CMD-SHELL", "pg_isready -U ${SERVICE_USER_POSTGRES} -d ${POSTGRES_DB:-ente_db}"] - interval: 10s + test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] + interval: 5s timeout: 5s - retries: 5 + retries: 10 minio: image: quay.io/minio/minio:latest environment: - - SERVICE_URL_MINIO_3200 + - SERVICE_URL_MINIO_9000 - MINIO_ROOT_USER=${SERVICE_USER_MINIO} - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} - command: server /data --address ":3200" --console-address ":3201" + command: server /data --address ":9000" --console-address ":9001" volumes: - minio-data:/data healthcheck: @@ -79,6 +95,8 @@ services: minio-init: image: minio/mc:latest + exclude_from_hc: true + restart: no depends_on: minio: condition: service_healthy @@ -87,7 +105,7 @@ services: - MINIO_ROOT_PASSWORD=${SERVICE_PASSWORD_MINIO} entrypoint: > /bin/sh -c " - mc alias set minio http://minio:3200 $${MINIO_ROOT_USER} $${MINIO_ROOT_PASSWORD}; + 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; diff --git a/templates/compose/ente-photos.yaml b/templates/compose/ente-photos.yaml index 03fdc4f1e..851e13563 100644 --- a/templates/compose/ente-photos.yaml +++ b/templates/compose/ente-photos.yaml @@ -43,13 +43,13 @@ services: postgres: condition: service_healthy volumes: - - museum-data:/data:rw + - museum-data:/data + - museum-config:/config healthcheck: - test: ["CMD", "wget", "-qO-", "http://localhost:8080/ping"] - interval: 60s + test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/ping"] + interval: 5s timeout: 5s - retries: 3 - start_period: 10s + retries: 10 web: image: ghcr.io/ente-io/web @@ -59,11 +59,10 @@ services: - ENTE_ALBUMS_ORIGIN=${SERVICE_URL_WEB_3002} healthcheck: - test: ["CMD", "curl", "--fail", "http://localhost:3000"] - interval: 30s - timeout: 10s - retries: 3 - start_period: 10s + test: ["CMD", "curl", "--fail", "http://127.0.0.1:3000"] + interval: 5s + timeout: 5s + retries: 10 postgres: image: postgres:15 @@ -75,8 +74,7 @@ services: - postgres-data:/var/lib/postgresql/data healthcheck: test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"] - interval: 10s + interval: 5s timeout: 5s - retries: 5 - start_period: 30s + retries: 10 diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 1e0753648..7b6aacef8 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -951,7 +951,7 @@ "ente-photos-with-s3": { "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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTRVJWSUNFX1VSTF9NSU5JT18zMjAwfScKICAgICAgLSBTM19CMl9FVV9DRU5fUkVHSU9OPWV1LWNlbnRyYWwtMgogICAgICAtIFMzX0IyX0VVX0NFTl9CVUNLRVQ9YjItZXUtY2VuCiAgICAgIC0gJ0VOQ1JZUFRJT05fS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9FTkNSWVBUSU9OfScKICAgICAgLSAnSEFTSF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0hBU0h9JwogICAgICAtICdKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9JwogICAgICAtIEVOVEVfSU5URVJOQUxfQURNSU49MTU4MDU1OTk2MjM4NjQzOAogICAgICAtICdBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0nCiAgICAgIC0gJ0FQUFNfQ0FTVD0ke0FQUFNfQ0FTVDotfScKICAgICAgLSAnQVBQU19BQ0NPVU5UUz0ke0FQUFNfQUNDT1VOVFM6LX0nCiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfSAtZCAke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgbWluaW86CiAgICBpbWFnZTogJ3F1YXkuaW8vbWluaW8vbWluaW86bGF0ZXN0JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gJ0VOVEVfSFRUUF9VU0VfVExTPSR7RU5URV9IVFRQX1VTRV9UTFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9BUFBTX1BVQkxJQ19BTEJVTVM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMn0nCiAgICAgIC0gJ0VOVEVfQVBQU19DQVNUPSR7U0VSVklDRV9VUkxfV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMX0nCiAgICAgIC0gJ0VOVEVfREJfSE9TVD0ke0VOVEVfREJfSE9TVDotcG9zdGdyZXN9JwogICAgICAtICdFTlRFX0RCX1BPUlQ9JHtFTlRFX0RCX1BPUlQ6LTU0MzJ9JwogICAgICAtICdFTlRFX0RCX05BTUU9JHtFTlRFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgICAtICdFTlRFX0RCX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVM6LXBndXNlcn0nCiAgICAgIC0gJ0VOVEVfREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnRU5URV9LRVlfRU5DUllQVElPTj0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9FTkNSWVBUSU9OfScKICAgICAgLSAnRU5URV9LRVlfSEFTSD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF82NF9IQVNIfScKICAgICAgLSAnRU5URV9KV1RfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0X0pXVH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfQURNSU49JHtFTlRFX0lOVEVSTkFMX0FETUlOOi0xNTgwNTU5OTYyMzg2NDM4fScKICAgICAgLSAnRU5URV9JTlRFUk5BTF9ESVNBQkxFX1JFR0lTVFJBVElPTj0ke0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT046LWZhbHNlfScKICAgICAgLSBTM19BUkVfTE9DQUxfQlVDS0VUUz10cnVlCiAgICAgIC0gUzNfVVNFX1BBVEhfU1RZTEVfVVJMUz10cnVlCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9LRVk9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9JwogICAgICAtIFMzX0IyX0VVX0NFTl9SRUdJT049ZXUtY2VudHJhbC0yCiAgICAgIC0gUzNfQjJfRVVfQ0VOX0JVQ0tFVD1iMi1ldS1jZW4KICAgIHZvbHVtZXM6CiAgICAgIC0gJ211c2V1bS1kYXRhOi9kYXRhJwogICAgICAtICdtdXNldW0tY29uZmlnOi9jb25maWcnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctcU8tJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICB3ZWI6CiAgICBpbWFnZTogZ2hjci5pby9lbnRlLWlvL3dlYgogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfV0VCXzMwMDAKICAgICAgLSAnRU5URV9BUElfT1JJR0lOPSR7U0VSVklDRV9VUkxfTVVTRVVNfScKICAgICAgLSAnRU5URV9BTEJVTVNfT1JJR0lOPSR7U0VSVklDRV9VUkxfV0VCXzMwMDJ9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctLWZhaWwnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMDAwJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7UE9TVEdSRVNfVVNFUn0gLWQgJHtQT1NUR1JFU19EQn0nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvOgogICAgaW1hZ2U6ICdxdWF5LmlvL21pbmlvL21pbmlvOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzkwMDAKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAvZGF0YSAtLWFkZHJlc3MgIjo5MDAwIiAtLWNvbnNvbGUtYWRkcmVzcyAiOjkwMDEiJwogICAgdm9sdW1lczoKICAgICAgLSAnbWluaW8tZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBtYwogICAgICAgIC0gcmVhZHkKICAgICAgICAtIGxvY2FsCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBtaW5pby1pbml0OgogICAgaW1hZ2U6ICdtaW5pby9tYzpsYXRlc3QnCiAgICBleGNsdWRlX2Zyb21faGM6IHRydWUKICAgIHJlc3RhcnQ6ICdubycKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzo5MDAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", "tags": [ "photos", "gallery", @@ -970,7 +970,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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gJ0VOVEVfSFRUUF9VU0VfVExTPSR7RU5URV9IVFRQX1VTRV9UTFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9BUFBTX1BVQkxJQ19BTEJVTVM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMn0nCiAgICAgIC0gJ0VOVEVfQVBQU19DQVNUPSR7U0VSVklDRV9VUkxfV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMX0nCiAgICAgIC0gJ0VOVEVfREJfSE9TVD0ke0VOVEVfREJfSE9TVDotcG9zdGdyZXN9JwogICAgICAtICdFTlRFX0RCX1BPUlQ9JHtFTlRFX0RCX1BPUlQ6LTU0MzJ9JwogICAgICAtICdFTlRFX0RCX05BTUU9JHtFTlRFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgICAtICdFTlRFX0RCX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVM6LXBndXNlcn0nCiAgICAgIC0gJ0VOVEVfREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnRU5URV9LRVlfRU5DUllQVElPTj0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9FTkNSWVBUSU9OfScKICAgICAgLSAnRU5URV9LRVlfSEFTSD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF82NF9IQVNIfScKICAgICAgLSAnRU5URV9KV1RfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0X0pXVH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfQURNSU49JHtFTlRFX0lOVEVSTkFMX0FETUlOOi0xNTgwNTU5OTYyMzg2NDM4fScKICAgICAgLSAnRU5URV9JTlRFUk5BTF9ESVNBQkxFX1JFR0lTVFJBVElPTj0ke0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT046LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQVJFX0xPQ0FMX0JVQ0tFVFM9JHtQUklNQVJZX1NUT1JBR0VfQVJFX0xPQ0FMX0JVQ0tFVFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fVVNFX1BBVEhfU1RZTEVfVVJMUz0ke1BSSU1BUllfU1RPUkFHRV9VU0VfUEFUSF9TVFlMRV9VUkxTOi10cnVlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fS0VZPSR7UzNfU1RPUkFHRV9LRVk6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1MzX1NUT1JBR0VfU0VDUkVUOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1MzX1NUT1JBR0VfRU5EUE9JTlQ6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1JFR0lPTj0ke1MzX1NUT1JBR0VfUkVHSU9OOi11cy1lYXN0LTF9JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9CVUNLRVQ9JHtTM19TVE9SQUdFX0JVQ0tFVDo/fScKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YTpydycKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLXFPLScKICAgICAgICAtICdodHRwOi8vbG9jYWxob3N0OjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDYwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAzCiAgICAgIHN0YXJ0X3BlcmlvZDogMTBzCiAgd2ViOgogICAgaW1hZ2U6IGdoY3IuaW8vZW50ZS1pby93ZWIKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX1dFQl8zMDAwCiAgICAgIC0gJ0VOVEVfQVBJX09SSUdJTj0ke1NFUlZJQ0VfVVJMX01VU0VVTX0nCiAgICAgIC0gJ0VOVEVfQUxCVU1TX09SSUdJTj0ke1NFUlZJQ0VfVVJMX1dFQl8zMDAyfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLS1mYWlsJwogICAgICAgIC0gJ2h0dHA6Ly9sb2NhbGhvc3Q6MzAwMCcKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogICAgICBzdGFydF9wZXJpb2Q6IDEwcwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNScKICAgIGVudmlyb25tZW50OgogICAgICAtICdQT1NUR1JFU19VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1NFUlZJQ0VfREJfTkFNRTotZW50ZV9kYn0nCiAgICB2b2x1bWVzOgogICAgICAtICdwb3N0Z3Jlcy1kYXRhOi92YXIvbGliL3Bvc3RncmVzcWwvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAncGdfaXNyZWFkeSAtVSAke1BPU1RHUkVTX1VTRVJ9IC1kICR7UE9TVEdSRVNfREJ9JwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKICAgICAgc3RhcnRfcGVyaW9kOiAzMHMK", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gJ0VOVEVfSFRUUF9VU0VfVExTPSR7RU5URV9IVFRQX1VTRV9UTFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9BUFBTX1BVQkxJQ19BTEJVTVM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMn0nCiAgICAgIC0gJ0VOVEVfQVBQU19DQVNUPSR7U0VSVklDRV9VUkxfV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX1VSTF9XRUJfMzAwMX0nCiAgICAgIC0gJ0VOVEVfREJfSE9TVD0ke0VOVEVfREJfSE9TVDotcG9zdGdyZXN9JwogICAgICAtICdFTlRFX0RCX1BPUlQ9JHtFTlRFX0RCX1BPUlQ6LTU0MzJ9JwogICAgICAtICdFTlRFX0RCX05BTUU9JHtFTlRFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgICAtICdFTlRFX0RCX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVM6LXBndXNlcn0nCiAgICAgIC0gJ0VOVEVfREJfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnRU5URV9LRVlfRU5DUllQVElPTj0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9FTkNSWVBUSU9OfScKICAgICAgLSAnRU5URV9LRVlfSEFTSD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF82NF9IQVNIfScKICAgICAgLSAnRU5URV9KV1RfU0VDUkVUPSR7U0VSVklDRV9SRUFMQkFTRTY0X0pXVH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfQURNSU49JHtFTlRFX0lOVEVSTkFMX0FETUlOOi0xNTgwNTU5OTYyMzg2NDM4fScKICAgICAgLSAnRU5URV9JTlRFUk5BTF9ESVNBQkxFX1JFR0lTVFJBVElPTj0ke0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT046LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQVJFX0xPQ0FMX0JVQ0tFVFM9JHtQUklNQVJZX1NUT1JBR0VfQVJFX0xPQ0FMX0JVQ0tFVFM6LWZhbHNlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fVVNFX1BBVEhfU1RZTEVfVVJMUz0ke1BSSU1BUllfU1RPUkFHRV9VU0VfUEFUSF9TVFlMRV9VUkxTOi10cnVlfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fS0VZPSR7UzNfU1RPUkFHRV9LRVk6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1MzX1NUT1JBR0VfU0VDUkVUOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1MzX1NUT1JBR0VfRU5EUE9JTlQ6P30nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1JFR0lPTj0ke1MzX1NUT1JBR0VfUkVHSU9OOi11cy1lYXN0LTF9JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9CVUNLRVQ9JHtTM19TVE9SQUdFX0JVQ0tFVDo/fScKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIHdnZXQKICAgICAgICAtICctcU8tJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICB3ZWI6CiAgICBpbWFnZTogZ2hjci5pby9lbnRlLWlvL3dlYgogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfV0VCXzMwMDAKICAgICAgLSAnRU5URV9BUElfT1JJR0lOPSR7U0VSVklDRV9VUkxfTVVTRVVNfScKICAgICAgLSAnRU5URV9BTEJVTVNfT1JJR0lOPSR7U0VSVklDRV9VUkxfV0VCXzMwMDJ9JwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctLWZhaWwnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMDAwJwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMTAKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFUzotcGd1c2VyfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtTRVJWSUNFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtQT1NUR1JFU19VU0VSfSAtZCAke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDEwCg==", "tags": [ "photos", "gallery", diff --git a/templates/service-templates.json b/templates/service-templates.json index d9175648c..ad422bdc5 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -951,7 +951,7 @@ "ente-photos-with-s3": { "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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtIFBPU1RHUkVTX0hPU1Q9cG9zdGdyZXMKICAgICAgLSBQT1NUR1JFU19QT1JUPTU0MzIKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0tFWT0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0VORFBPSU5UPSR7U0VSVklDRV9GUUROX01JTklPXzMyMDB9JwogICAgICAtIFMzX0IyX0VVX0NFTl9SRUdJT049ZXUtY2VudHJhbC0yCiAgICAgIC0gUzNfQjJfRVVfQ0VOX0JVQ0tFVD1iMi1ldS1jZW4KICAgICAgLSAnRU5DUllQVElPTl9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0VOQ1JZUFRJT059JwogICAgICAtICdIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0nCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0pXVH0nCiAgICAgIC0gRU5URV9JTlRFUk5BTF9BRE1JTj0xNTgwNTU5OTYyMzg2NDM4CiAgICAgIC0gJ0FQUFNfUFVCTElDX0FMQlVNUz0ke0FQUFNfUFVCTElDX0FMQlVNUzotfScKICAgICAgLSAnQVBQU19DQVNUPSR7QVBQU19DQVNUOi19JwogICAgICAtICdBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ211c2V1bS1kYXRhOi9kYXRhJwogICAgICAtICdtdXNldW0tY29uZmlnOi9jb25maWcnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNS1hbHBpbmUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9IC1kICR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKICBtaW5pbzoKICAgIGltYWdlOiAncXVheS5pby9taW5pby9taW5pbzpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtICdFTlRFX0hUVFBfVVNFX1RMUz0ke0VOVEVfSFRUUF9VU0VfVExTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfQVBQU19QVUJMSUNfQUxCVU1TPSR7U0VSVklDRV9GUUROX1dFQl8zMDAyfScKICAgICAgLSAnRU5URV9BUFBTX0NBU1Q9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDF9JwogICAgICAtICdFTlRFX0RCX0hPU1Q9JHtFTlRFX0RCX0hPU1Q6LXBvc3RncmVzfScKICAgICAgLSAnRU5URV9EQl9QT1JUPSR7RU5URV9EQl9QT1JUOi01NDMyfScKICAgICAgLSAnRU5URV9EQl9OQU1FPSR7RU5URV9EQl9OQU1FOi1lbnRlX2RifScKICAgICAgLSAnRU5URV9EQl9VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdFTlRFX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ0VOVEVfS0VZX0VOQ1JZUFRJT049JHtTRVJWSUNFX1JFQUxCQVNFNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0VOVEVfS0VZX0hBU0g9JHtTRVJWSUNFX1JFQUxCQVNFNjRfNjRfSEFTSH0nCiAgICAgIC0gJ0VOVEVfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9KV1R9JwogICAgICAtICdFTlRFX0lOVEVSTkFMX0FETUlOPSR7RU5URV9JTlRFUk5BTF9BRE1JTjotMTU4MDU1OTk2MjM4NjQzOH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT049JHtFTlRFX0lOVEVSTkFMX0RJU0FCTEVfUkVHSVNUUkFUSU9OOi1mYWxzZX0nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTRVJWSUNFX0ZRRE5fTUlOSU9fMzIwMH0nCiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGEnCiAgICAgIC0gJ211c2V1bS1jb25maWc6L2NvbmZpZycKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9zdGFydGVkCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gd2dldAogICAgICAgIC0gJy1xTy0nCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAxMAogIHdlYjoKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vd2ViCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fV0VCXzMwMDAKICAgICAgLSAnRU5URV9BUElfT1JJR0lOPSR7U0VSVklDRV9GUUROX01VU0VVTX0nCiAgICAgIC0gJ0VOVEVfQUxCVU1TX09SSUdJTj0ke1NFUlZJQ0VfRlFETl9XRUJfMzAwMn0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy0tZmFpbCcKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjMwMDAnCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAxMAogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNS1hbHBpbmUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtQT1NUR1JFU19VU0VSfSAtZCAke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDEwCiAgbWluaW86CiAgICBpbWFnZTogJ3F1YXkuaW8vbWluaW8vbWluaW86bGF0ZXN0JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9GUUROX01JTklPXzkwMDAKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgY29tbWFuZDogJ3NlcnZlciAvZGF0YSAtLWFkZHJlc3MgIjo5MDAwIiAtLWNvbnNvbGUtYWRkcmVzcyAiOjkwMDEiJwogICAgdm9sdW1lczoKICAgICAgLSAnbWluaW8tZGF0YTovZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBtYwogICAgICAgIC0gcmVhZHkKICAgICAgICAtIGxvY2FsCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiAyMHMKICAgICAgcmV0cmllczogMTAKICBtaW5pby1pbml0OgogICAgaW1hZ2U6ICdtaW5pby9tYzpsYXRlc3QnCiAgICBleGNsdWRlX2Zyb21faGM6IHRydWUKICAgIHJlc3RhcnQ6ICdubycKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzo5MDAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", "tags": [ "photos", "gallery", @@ -970,7 +970,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": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtICdFTlRFX0hUVFBfVVNFX1RMUz0ke0VOVEVfSFRUUF9VU0VfVExTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfQVBQU19QVUJMSUNfQUxCVU1TPSR7U0VSVklDRV9GUUROX1dFQl8zMDAyfScKICAgICAgLSAnRU5URV9BUFBTX0NBU1Q9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDF9JwogICAgICAtICdFTlRFX0RCX0hPU1Q9JHtFTlRFX0RCX0hPU1Q6LXBvc3RncmVzfScKICAgICAgLSAnRU5URV9EQl9QT1JUPSR7RU5URV9EQl9QT1JUOi01NDMyfScKICAgICAgLSAnRU5URV9EQl9OQU1FPSR7RU5URV9EQl9OQU1FOi1lbnRlX2RifScKICAgICAgLSAnRU5URV9EQl9VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdFTlRFX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ0VOVEVfS0VZX0VOQ1JZUFRJT049JHtTRVJWSUNFX1JFQUxCQVNFNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0VOVEVfS0VZX0hBU0g9JHtTRVJWSUNFX1JFQUxCQVNFNjRfNjRfSEFTSH0nCiAgICAgIC0gJ0VOVEVfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9KV1R9JwogICAgICAtICdFTlRFX0lOVEVSTkFMX0FETUlOPSR7RU5URV9JTlRFUk5BTF9BRE1JTjotMTU4MDU1OTk2MjM4NjQzOH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT049JHtFTlRFX0lOVEVSTkFMX0RJU0FCTEVfUkVHSVNUUkFUSU9OOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0FSRV9MT0NBTF9CVUNLRVRTPSR7UFJJTUFSWV9TVE9SQUdFX0FSRV9MT0NBTF9CVUNLRVRTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1VTRV9QQVRIX1NUWUxFX1VSTFM9JHtQUklNQVJZX1NUT1JBR0VfVVNFX1BBVEhfU1RZTEVfVVJMUzotdHJ1ZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0tFWT0ke1MzX1NUT1JBR0VfS0VZOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTM19TVE9SQUdFX1NFQ1JFVDo/fScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTM19TVE9SQUdFX0VORFBPSU5UOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9SRUdJT049JHtTM19TVE9SQUdFX1JFR0lPTjotdXMtZWFzdC0xfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQlVDS0VUPSR7UzNfU1RPUkFHRV9CVUNLRVQ6P30nCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGE6cncnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gd2dldAogICAgICAgIC0gJy1xTy0nCiAgICAgICAgLSAnaHR0cDovL2xvY2FsaG9zdDo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiA2MHMKICAgICAgdGltZW91dDogNXMKICAgICAgcmV0cmllczogMwogICAgICBzdGFydF9wZXJpb2Q6IDEwcwogIHdlYjoKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vd2ViCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fV0VCXzMwMDAKICAgICAgLSAnRU5URV9BUElfT1JJR0lOPSR7U0VSVklDRV9GUUROX01VU0VVTX0nCiAgICAgIC0gJ0VOVEVfQUxCVU1TX09SSUdJTj0ke1NFUlZJQ0VfRlFETl9XRUJfMzAwMn0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRAogICAgICAgIC0gY3VybAogICAgICAgIC0gJy0tZmFpbCcKICAgICAgICAtICdodHRwOi8vbG9jYWxob3N0OjMwMDAnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICAgICAgc3RhcnRfcGVyaW9kOiAxMHMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFUzotcGd1c2VyfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfScKICAgICAgLSAnUE9TVEdSRVNfREI9JHtTRVJWSUNFX0RCX05BTUU6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtQT1NUR1JFU19VU0VSfSAtZCAke1BPU1RHUkVTX0RCfScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgICAgIHN0YXJ0X3BlcmlvZDogMzBzCg==", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtICdFTlRFX0hUVFBfVVNFX1RMUz0ke0VOVEVfSFRUUF9VU0VfVExTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfQVBQU19QVUJMSUNfQUxCVU1TPSR7U0VSVklDRV9GUUROX1dFQl8zMDAyfScKICAgICAgLSAnRU5URV9BUFBTX0NBU1Q9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDR9JwogICAgICAtICdFTlRFX0FQUFNfQUNDT1VOVFM9JHtTRVJWSUNFX0ZRRE5fV0VCXzMwMDF9JwogICAgICAtICdFTlRFX0RCX0hPU1Q9JHtFTlRFX0RCX0hPU1Q6LXBvc3RncmVzfScKICAgICAgLSAnRU5URV9EQl9QT1JUPSR7RU5URV9EQl9QT1JUOi01NDMyfScKICAgICAgLSAnRU5URV9EQl9OQU1FPSR7RU5URV9EQl9OQU1FOi1lbnRlX2RifScKICAgICAgLSAnRU5URV9EQl9VU0VSPSR7U0VSVklDRV9VU0VSX1BPU1RHUkVTOi1wZ3VzZXJ9JwogICAgICAtICdFTlRFX0RCX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ0VOVEVfS0VZX0VOQ1JZUFRJT049JHtTRVJWSUNFX1JFQUxCQVNFNjRfRU5DUllQVElPTn0nCiAgICAgIC0gJ0VOVEVfS0VZX0hBU0g9JHtTRVJWSUNFX1JFQUxCQVNFNjRfNjRfSEFTSH0nCiAgICAgIC0gJ0VOVEVfSldUX1NFQ1JFVD0ke1NFUlZJQ0VfUkVBTEJBU0U2NF9KV1R9JwogICAgICAtICdFTlRFX0lOVEVSTkFMX0FETUlOPSR7RU5URV9JTlRFUk5BTF9BRE1JTjotMTU4MDU1OTk2MjM4NjQzOH0nCiAgICAgIC0gJ0VOVEVfSU5URVJOQUxfRElTQUJMRV9SRUdJU1RSQVRJT049JHtFTlRFX0lOVEVSTkFMX0RJU0FCTEVfUkVHSVNUUkFUSU9OOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0FSRV9MT0NBTF9CVUNLRVRTPSR7UFJJTUFSWV9TVE9SQUdFX0FSRV9MT0NBTF9CVUNLRVRTOi1mYWxzZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX1VTRV9QQVRIX1NUWUxFX1VSTFM9JHtQUklNQVJZX1NUT1JBR0VfVVNFX1BBVEhfU1RZTEVfVVJMUzotdHJ1ZX0nCiAgICAgIC0gJ0VOVEVfUzNfQjJfRVVfQ0VOX0tFWT0ke1MzX1NUT1JBR0VfS0VZOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTM19TVE9SQUdFX1NFQ1JFVDo/fScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTM19TVE9SQUdFX0VORFBPSU5UOj99JwogICAgICAtICdFTlRFX1MzX0IyX0VVX0NFTl9SRUdJT049JHtTM19TVE9SQUdFX1JFR0lPTjotdXMtZWFzdC0xfScKICAgICAgLSAnRU5URV9TM19CMl9FVV9DRU5fQlVDS0VUPSR7UzNfU1RPUkFHRV9CVUNLRVQ6P30nCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgdm9sdW1lczoKICAgICAgLSAnbXVzZXVtLWRhdGE6L2RhdGEnCiAgICAgIC0gJ211c2V1bS1jb25maWc6L2NvbmZpZycKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSB3Z2V0CiAgICAgICAgLSAnLXFPLScKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDEwCiAgd2ViOgogICAgaW1hZ2U6IGdoY3IuaW8vZW50ZS1pby93ZWIKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9XRUJfMzAwMAogICAgICAtICdFTlRFX0FQSV9PUklHSU49JHtTRVJWSUNFX0ZRRE5fTVVTRVVNfScKICAgICAgLSAnRU5URV9BTEJVTVNfT1JJR0lOPSR7U0VSVklDRV9GUUROX1dFQl8zMDAyfScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLS1mYWlsJwogICAgICAgIC0gJ2h0dHA6Ly8xMjcuMC4wLjE6MzAwMCcKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDEwCiAgcG9zdGdyZXM6CiAgICBpbWFnZTogJ3Bvc3RncmVzOjE1JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVM6LXBndXNlcn0nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7U0VSVklDRV9EQl9OQU1FOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7UE9TVEdSRVNfVVNFUn0gLWQgJHtQT1NUR1JFU19EQn0nCiAgICAgIGludGVydmFsOiA1cwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiAxMAo=", "tags": [ "photos", "gallery", From 590de8ce375782b99dfde990da92f78b24c63d93 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:31:00 +0200 Subject: [PATCH 47/56] feat(docker): enhance Docker image handling with new validation and parsing logic - Refactored DockerImage component to use separate properties for image name, tag, and SHA256 digest. - Introduced DockerImageFormat validation rule to enforce correct image format. - Updated DockerImageParser to handle new parsing logic for image tags and SHA256 hashes. - Enhanced UI to separate input fields for image name, tag, and SHA256 digest, improving user experience. - Added comprehensive tests for DockerImageParser to ensure accurate parsing and validation of image formats. --- app/Livewire/Project/New/DockerImage.php | 29 ++- app/Rules/DockerImageFormat.php | 41 ++++ app/Services/DockerImageParser.php | 37 ++-- .../project/new/docker-image.blade.php | 25 ++- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- tests/Unit/DockerImageParserTest.php | 206 +++++++++--------- 7 files changed, 209 insertions(+), 133 deletions(-) create mode 100644 app/Rules/DockerImageFormat.php diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index c1403a819..dd928b5e1 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -12,7 +12,11 @@ class DockerImage extends Component { - public string $dockerImage = ''; + public string $imageName = ''; + + public string $imageTag = ''; + + public string $imageSha256 = ''; public array $parameters; @@ -27,11 +31,30 @@ public function mount() public function submit() { $this->validate([ - 'dockerImage' => 'required', + 'imageName' => ['required', 'string'], + 'imageTag' => ['nullable', 'string', 'regex:/^[a-z0-9][a-z0-9._-]*$/i'], + 'imageSha256' => ['nullable', 'string', 'regex:/^[a-f0-9]{64}$/i'], ]); + // Validate that either tag or sha256 is provided, but not both + if ($this->imageTag && $this->imageSha256) { + $this->addError('imageTag', 'Provide either a tag or SHA256 digest, not both.'); + $this->addError('imageSha256', 'Provide either a tag or SHA256 digest, not both.'); + + return; + } + + // Build the full Docker image string + if ($this->imageSha256) { + $dockerImage = $this->imageName.'@sha256:'.$this->imageSha256; + } elseif ($this->imageTag) { + $dockerImage = $this->imageName.':'.$this->imageTag; + } else { + $dockerImage = $this->imageName.':latest'; + } + $parser = new DockerImageParser; - $parser->parse($this->dockerImage); + $parser->parse($dockerImage); $destination_uuid = $this->query['destination']; $destination = StandaloneDocker::where('uuid', $destination_uuid)->first(); diff --git a/app/Rules/DockerImageFormat.php b/app/Rules/DockerImageFormat.php new file mode 100644 index 000000000..a6a78a76c --- /dev/null +++ b/app/Rules/DockerImageFormat.php @@ -0,0 +1,41 @@ + 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); + // Check for @sha256: format first (e.g., nginx@sha256:abc123...) + if (preg_match('/^(.+)@sha256:([a-f0-9]{64})$/i', $imageString, $matches)) { + $mainPart = $matches[1]; + $this->tag = $matches[2]; + $this->isImageHash = true; } else { - $mainPart = $imageString; - $this->tag = 'latest'; - $this->isImageHash = false; + // Split by : to handle the tag, but be careful with registry ports + $lastColon = strrpos($imageString, ':'); + $hasSlash = str_contains($imageString, '/'); + + // If the last colon appears after the last slash, it's a tag + // Otherwise it might be a port in the registry URL + 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 diff --git a/resources/views/livewire/project/new/docker-image.blade.php b/resources/views/livewire/project/new/docker-image.blade.php index af1005a88..54c175b82 100644 --- a/resources/views/livewire/project/new/docker-image.blade.php +++ b/resources/views/livewire/project/new/docker-image.blade.php @@ -1,4 +1,4 @@ -
+

Create a new Application

You can deploy an existing Docker Image from any Registry.
@@ -7,12 +7,23 @@ Save
- + +
+ + + +
diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 7d8cc6af1..6d61b12ef 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": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01VU0VVTV84MDgwCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gUzNfQVJFX0xPQ0FMX0JVQ0tFVFM9dHJ1ZQogICAgICAtIFMzX1VTRV9QQVRIX1NUWUxFX1VSTFM9dHJ1ZQogICAgICAtICdTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX1NFQ1JFVD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgICAtICdTM19CMl9FVV9DRU5fRU5EUE9JTlQ9JHtTRVJWSUNFX1VSTF9NSU5JT18zMjAwfScKICAgICAgLSBTM19CMl9FVV9DRU5fUkVHSU9OPWV1LWNlbnRyYWwtMgogICAgICAtIFMzX0IyX0VVX0NFTl9CVUNLRVQ9YjItZXUtY2VuCiAgICAgIC0gJ0VOQ1JZUFRJT05fS0VZPSR7U0VSVklDRV9QQVNTV09SRF82NF9FTkNSWVBUSU9OfScKICAgICAgLSAnSEFTSF9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0hBU0h9JwogICAgICAtICdKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9JwogICAgICAtIEVOVEVfSU5URVJOQUxfQURNSU49MTU4MDU1OTk2MjM4NjQzOAogICAgICAtICdBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0nCiAgICAgIC0gJ0FQUFNfQ0FTVD0ke0FQUFNfQ0FTVDotfScKICAgICAgLSAnQVBQU19BQ0NPVU5UUz0ke0FQUFNfQUNDT1VOVFM6LX0nCiAgICB2b2x1bWVzOgogICAgICAtICdtdXNldW0tZGF0YTovZGF0YScKICAgICAgLSAnbXVzZXVtLWNvbmZpZzovY29uZmlnJwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTo4MDgwL3BpbmcnCiAgICAgIGludGVydmFsOiAzMHMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDMKICBwb3N0Z3JlczoKICAgIGltYWdlOiAncG9zdGdyZXM6MTUtYWxwaW5lJwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ3Bvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQtU0hFTEwKICAgICAgICAtICdwZ19pc3JlYWR5IC1VICR7U0VSVklDRV9VU0VSX1BPU1RHUkVTfSAtZCAke1BPU1RHUkVTX0RCOi1lbnRlX2RifScKICAgICAgaW50ZXJ2YWw6IDEwcwogICAgICB0aW1lb3V0OiA1cwogICAgICByZXRyaWVzOiA1CiAgbWluaW86CiAgICBpbWFnZTogJ3F1YXkuaW8vbWluaW8vbWluaW86bGF0ZXN0JwogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", "tags": [ "photos", "gallery", diff --git a/templates/service-templates.json b/templates/service-templates.json index 7d05eb1ef..4ae838a89 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": "IyBkb2N1bWVudGF0aW9uOiBodHRwczovL2hlbHAuZW50ZS5pby9zZWxmLWhvc3RpbmcvaW5zdGFsbGF0aW9uL2NvbXBvc2UKIyBzbG9nYW46IEVudGUgUGhvdG9zIGlzIGEgZnVsbHkgb3BlbiBzb3VyY2UsIEVuZCB0byBFbmQgRW5jcnlwdGVkIGFsdGVybmF0aXZlIHRvIEdvb2dsZSBQaG90b3MgYW5kIEFwcGxlIFBob3Rvcy4KIyBjYXRlZ29yeTogbWVkaWEKIyB0YWdzOiBwaG90b3MsZ2FsbGVyeSxiYWNrdXAsZW5jcnlwdGlvbixwcml2YWN5LHNlbGYtaG9zdGVkLGdvb2dsZS1waG90b3MsYWx0ZXJuYXRpdmUKIyBsb2dvOiBzdmdzL2VudGUtcGhvdG9zLnN2ZwojIHBvcnQ6IDgwODAKCnNlcnZpY2VzOgogIG11c2V1bToKICAgIGltYWdlOiBnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdAogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gU0VSVklDRV9VUkxfTVVTRVVNXzgwODAKICAgICAgIyBEYXRhYmFzZSBjb25maWd1cmF0aW9uCiAgICAgIC0gUE9TVEdSRVNfSE9TVD1wb3N0Z3JlcwogICAgICAtIFBPU1RHUkVTX1BPUlQ9NTQzMgogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICAgIC0gUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30KICAgICAgLSBQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9CiAgICAgICMgUzMvTWluSU8gY29uZmlndXJhdGlvbgogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSBTM19CMl9FVV9DRU5fS0VZPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgICAtIFMzX0IyX0VVX0NFTl9FTkRQT0lOVD0ke1NFUlZJQ0VfVVJMX01JTklPXzMyMDB9CiAgICAgIC0gUzNfQjJfRVVfQ0VOX1JFR0lPTj1ldS1jZW50cmFsLTIKICAgICAgLSBTM19CMl9FVV9DRU5fQlVDS0VUPWIyLWV1LWNlbgogICAgICAjIFNlY3VyaXR5IGtleXMKICAgICAgLSBFTkNSWVBUSU9OX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfRU5DUllQVElPTn0KICAgICAgLSBIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0KICAgICAgLSBKV1RfU0VDUkVUPSR7U0VSVklDRV9QQVNTV09SRF82NF9KV1R9CiAgICAgICMgQWRtaW4gcGVybWlzc2lvbnMgKGdyYW50cyBmaXJzdCBhY2NvdW50IGFkbWluIGFjY2VzcykKICAgICAgLSBFTlRFX0lOVEVSTkFMX0FETUlOPTE1ODA1NTk5NjIzODY0MzgKICAgICAgIyBBcHAgVVJMcyAob3B0aW9uYWwgLSBmb3Igd2ViIGludGVyZmFjZSkKICAgICAgLSBBUFBTX1BVQkxJQ19BTEJVTVM9JHtBUFBTX1BVQkxJQ19BTEJVTVM6LX0KICAgICAgLSBBUFBTX0NBU1Q9JHtBUFBTX0NBU1Q6LX0KICAgICAgLSBBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfQogICAgdm9sdW1lczoKICAgICAgLSBtdXNldW0tZGF0YTovZGF0YQogICAgICAtIG11c2V1bS1jb25maWc6L2NvbmZpZwogICAgZGVwZW5kc19vbjoKICAgICAgcG9zdGdyZXM6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgICAgbWluaW86CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX3N0YXJ0ZWQKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OiBbIkNNRCIsICJjdXJsIiwgIi1mIiwgImh0dHA6Ly8xMjcuMC4wLjE6ODA4MC9waW5nIl0KICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwoKICBwb3N0Z3JlczoKICAgIGltYWdlOiBwb3N0Z3JlczoxNS1hbHBpbmUKICAgIGVudmlyb25tZW50OgogICAgICAtIFBPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9CiAgICAgIC0gUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTfQogICAgICAtIFBPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9CiAgICB2b2x1bWVzOgogICAgICAtIHBvc3RncmVzLWRhdGE6L3Zhci9saWIvcG9zdGdyZXNxbC9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQtU0hFTEwiLCAicGdfaXNyZWFkeSAtVSAke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30gLWQgJHtQT1NUR1JFU19EQjotZW50ZV9kYn0iXQogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKCiAgbWluaW86CiAgICBpbWFnZTogcXVheS5pby9taW5pby9taW5pbzpsYXRlc3QKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX01JTklPXzMyMDAKICAgICAgLSBNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99CiAgICAgIC0gTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99CiAgICBjb21tYW5kOiBzZXJ2ZXIgL2RhdGEgLS1hZGRyZXNzICI6MzIwMCIgLS1jb25zb2xlLWFkZHJlc3MgIjozMjAxIgogICAgdm9sdW1lczoKICAgICAgLSBtaW5pby1kYXRhOi9kYXRhCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDogWyJDTUQiLCAibWMiLCAicmVhZHkiLCAibG9jYWwiXQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCgogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogbWluaW8vbWM6bGF0ZXN0CiAgICBkZXBlbmRzX29uOgogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZW52aXJvbm1lbnQ6CiAgICAgIC0gTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfQogICAgICAtIE1JTklPX1JPT1RfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfQogICAgZW50cnlwb2ludDogPgogICAgICAvYmluL3NoIC1jICIKICAgICAgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07CiAgICAgIG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsKICAgICAgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOwogICAgICBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsKICAgICAgIgo=", + "compose": "c2VydmljZXM6CiAgbXVzZXVtOgogICAgaW1hZ2U6ICdnaGNyLmlvL2VudGUtaW8vc2VydmVyOmxhdGVzdCcKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9NVVNFVU1fODA4MAogICAgICAtIFBPU1RHUkVTX0hPU1Q9cG9zdGdyZXMKICAgICAgLSBQT1NUR1JFU19QT1JUPTU0MzIKICAgICAgLSAnUE9TVEdSRVNfREI9JHtQT1NUR1JFU19EQjotZW50ZV9kYn0nCiAgICAgIC0gJ1BPU1RHUkVTX1VTRVI9JHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9JwogICAgICAtICdQT1NUR1JFU19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUE9TVEdSRVN9JwogICAgICAtIFMzX0FSRV9MT0NBTF9CVUNLRVRTPXRydWUKICAgICAgLSBTM19VU0VfUEFUSF9TVFlMRV9VUkxTPXRydWUKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0tFWT0ke1NFUlZJQ0VfVVNFUl9NSU5JT30nCiAgICAgIC0gJ1MzX0IyX0VVX0NFTl9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEX01JTklPfScKICAgICAgLSAnUzNfQjJfRVVfQ0VOX0VORFBPSU5UPSR7U0VSVklDRV9GUUROX01JTklPXzMyMDB9JwogICAgICAtIFMzX0IyX0VVX0NFTl9SRUdJT049ZXUtY2VudHJhbC0yCiAgICAgIC0gUzNfQjJfRVVfQ0VOX0JVQ0tFVD1iMi1ldS1jZW4KICAgICAgLSAnRU5DUllQVElPTl9LRVk9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0VOQ1JZUFRJT059JwogICAgICAtICdIQVNIX0tFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfNjRfSEFTSH0nCiAgICAgIC0gJ0pXVF9TRUNSRVQ9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X0pXVH0nCiAgICAgIC0gRU5URV9JTlRFUk5BTF9BRE1JTj0xNTgwNTU5OTYyMzg2NDM4CiAgICAgIC0gJ0FQUFNfUFVCTElDX0FMQlVNUz0ke0FQUFNfUFVCTElDX0FMQlVNUzotfScKICAgICAgLSAnQVBQU19DQVNUPSR7QVBQU19DQVNUOi19JwogICAgICAtICdBUFBTX0FDQ09VTlRTPSR7QVBQU19BQ0NPVU5UUzotfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJ211c2V1bS1kYXRhOi9kYXRhJwogICAgICAtICdtdXNldW0tY29uZmlnOi9jb25maWcnCiAgICBkZXBlbmRzX29uOgogICAgICBwb3N0Z3JlczoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgICBtaW5pbzoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2Vfc3RhcnRlZAogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjgwODAvcGluZycKICAgICAgaW50ZXJ2YWw6IDMwcwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMwogIHBvc3RncmVzOgogICAgaW1hZ2U6ICdwb3N0Z3JlczoxNS1hbHBpbmUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU30nCiAgICAgIC0gJ1BPU1RHUkVTX0RCPSR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgdm9sdW1lczoKICAgICAgLSAncG9zdGdyZXMtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJHtTRVJWSUNFX1VTRVJfUE9TVEdSRVN9IC1kICR7UE9TVEdSRVNfREI6LWVudGVfZGJ9JwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDVzCiAgICAgIHJldHJpZXM6IDUKICBtaW5pbzoKICAgIGltYWdlOiAncXVheS5pby9taW5pby9taW5pbzpsYXRlc3QnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTUlOSU9fMzIwMAogICAgICAtICdNSU5JT19ST09UX1VTRVI9JHtTRVJWSUNFX1VTRVJfTUlOSU99JwogICAgICAtICdNSU5JT19ST09UX1BBU1NXT1JEPSR7U0VSVklDRV9QQVNTV09SRF9NSU5JT30nCiAgICBjb21tYW5kOiAnc2VydmVyIC9kYXRhIC0tYWRkcmVzcyAiOjMyMDAiIC0tY29uc29sZS1hZGRyZXNzICI6MzIwMSInCiAgICB2b2x1bWVzOgogICAgICAtICdtaW5pby1kYXRhOi9kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG1jCiAgICAgICAgLSByZWFkeQogICAgICAgIC0gbG9jYWwKICAgICAgaW50ZXJ2YWw6IDVzCiAgICAgIHRpbWVvdXQ6IDIwcwogICAgICByZXRyaWVzOiAxMAogIG1pbmlvLWluaXQ6CiAgICBpbWFnZTogJ21pbmlvL21jOmxhdGVzdCcKICAgIGRlcGVuZHNfb246CiAgICAgIG1pbmlvOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTUlOSU9fUk9PVF9VU0VSPSR7U0VSVklDRV9VU0VSX01JTklPfScKICAgICAgLSAnTUlOSU9fUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfTUlOSU99JwogICAgZW50cnlwb2ludDogIi9iaW4vc2ggLWMgXCIgbWMgYWxpYXMgc2V0IG1pbmlvIGh0dHA6Ly9taW5pbzozMjAwICQke01JTklPX1JPT1RfVVNFUn0gJCR7TUlOSU9fUk9PVF9QQVNTV09SRH07IG1jIG1iIG1pbmlvL2IyLWV1LWNlbiAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vd2FzYWJpLWV1LWNlbnRyYWwtMi12MyAtLWlnbm9yZS1leGlzdGluZzsgbWMgbWIgbWluaW8vc2N3LWV1LWZyLXYzIC0taWdub3JlLWV4aXN0aW5nOyBlY2hvICdNaW5JTyBidWNrZXRzIGNyZWF0ZWQgc3VjY2Vzc2Z1bGx5JzsgXCJcbiIK", "tags": [ "photos", "gallery", diff --git a/tests/Unit/DockerImageParserTest.php b/tests/Unit/DockerImageParserTest.php index f41a9b170..6102a90b2 100644 --- a/tests/Unit/DockerImageParserTest.php +++ b/tests/Unit/DockerImageParserTest.php @@ -1,115 +1,109 @@ parse('nginx:latest'); + + expect($parser->getImageName())->toBe('nginx') + ->and($parser->getTag())->toBe('latest') + ->and($parser->isImageHash())->toBeFalse() + ->and($parser->toString())->toBe('nginx:latest'); +}); + +it('parses image with sha256 hash using colon format', function () { + $parser = new DockerImageParser; + $hash = '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0'; + $parser->parse("ghcr.io/benjaminehowe/rail-disruptions:{$hash}"); + + expect($parser->getFullImageNameWithoutTag())->toBe('ghcr.io/benjaminehowe/rail-disruptions') + ->and($parser->getTag())->toBe($hash) + ->and($parser->isImageHash())->toBeTrue() + ->and($parser->toString())->toBe("ghcr.io/benjaminehowe/rail-disruptions@sha256:{$hash}") + ->and($parser->getFullImageNameWithHash())->toBe("ghcr.io/benjaminehowe/rail-disruptions@sha256:{$hash}"); +}); + +it('parses image with sha256 hash using at sign format', function () { + $parser = new DockerImageParser; + $hash = '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0'; + $parser->parse("nginx@sha256:{$hash}"); + + expect($parser->getImageName())->toBe('nginx') + ->and($parser->getTag())->toBe($hash) + ->and($parser->isImageHash())->toBeTrue() + ->and($parser->toString())->toBe("nginx@sha256:{$hash}") + ->and($parser->getFullImageNameWithHash())->toBe("nginx@sha256:{$hash}"); +}); + +it('parses registry image with hash', function () { + $parser = new DockerImageParser; + $hash = 'abc123def456789abcdef123456789abcdef123456789abcdef123456789abc1'; + $parser->parse("docker.io/library/nginx:{$hash}"); + + expect($parser->getFullImageNameWithoutTag())->toBe('docker.io/library/nginx') + ->and($parser->getTag())->toBe($hash) + ->and($parser->isImageHash())->toBeTrue() + ->and($parser->toString())->toBe("docker.io/library/nginx@sha256:{$hash}"); +}); + +it('parses image without tag defaults to latest', function () { + $parser = new DockerImageParser; + $parser->parse('nginx'); + + expect($parser->getImageName())->toBe('nginx') + ->and($parser->getTag())->toBe('latest') + ->and($parser->isImageHash())->toBeFalse() + ->and($parser->toString())->toBe('nginx:latest'); +}); + +it('parses registry with port', function () { + $parser = new DockerImageParser; + $parser->parse('registry.example.com:5000/myapp:latest'); + + expect($parser->getFullImageNameWithoutTag())->toBe('registry.example.com:5000/myapp') + ->and($parser->getTag())->toBe('latest') + ->and($parser->isImageHash())->toBeFalse(); +}); + +it('parses registry with port and hash', function () { + $parser = new DockerImageParser; + $hash = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; + $parser->parse("registry.example.com:5000/myapp:{$hash}"); + + expect($parser->getFullImageNameWithoutTag())->toBe('registry.example.com:5000/myapp') + ->and($parser->getTag())->toBe($hash) + ->and($parser->isImageHash())->toBeTrue() + ->and($parser->toString())->toBe("registry.example.com:5000/myapp@sha256:{$hash}"); +}); + +it('identifies valid sha256 hashes', function () { + $validHashes = [ + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0', + '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef', + 'abcdef1234567890abcdef1234567890abcdef1234567890abcdef1234567890', + ]; + + foreach ($validHashes as $hash) { $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()); + $parser->parse("image:{$hash}"); + expect($parser->isImageHash())->toBeTrue("Hash {$hash} should be recognized as valid SHA256"); } +}); - public function test_parses_image_with_sha256_hash() - { +it('identifies invalid sha256 hashes', function () { + $invalidHashes = [ + 'latest', + 'v1.2.3', + 'abc123', // too short + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf', // too short + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf00', // too long + '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cfg0', // invalid char + ]; + + foreach ($invalidHashes as $hash) { $parser = new DockerImageParser; - $hash = '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf0'; - $parser->parse("ghcr.io/benjaminehowe/rail-disruptions:{$hash}"); - - $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()); + $parser->parse("image:{$hash}"); + expect($parser->isImageHash())->toBeFalse("Hash {$hash} should not be recognized as valid SHA256"); } - - public function test_parses_registry_image_with_hash() - { - $parser = new DockerImageParser; - $hash = 'abc123def456789abcdef123456789abcdef123456789abcdef123456789abc1'; - $parser->parse("docker.io/library/nginx:{$hash}"); - - $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()); - } - - public function test_parses_image_without_tag_defaults_to_latest() - { - $parser = new DockerImageParser; - $parser->parse('nginx'); - - $this->assertEquals('nginx', $parser->getImageName()); - $this->assertEquals('latest', $parser->getTag()); - $this->assertFalse($parser->isImageHash()); - $this->assertEquals('nginx:latest', $parser->toString()); - } - - public function test_parses_registry_with_port() - { - $parser = new DockerImageParser; - $parser->parse('registry.example.com:5000/myapp:latest'); - - $this->assertEquals('registry.example.com:5000/myapp', $parser->getFullImageNameWithoutTag()); - $this->assertEquals('latest', $parser->getTag()); - $this->assertFalse($parser->isImageHash()); - } - - public function test_parses_registry_with_port_and_hash() - { - $parser = new DockerImageParser; - $hash = '1234567890abcdef1234567890abcdef1234567890abcdef1234567890abcdef'; - $parser->parse("registry.example.com:5000/myapp:{$hash}"); - - $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()); - } - - public function test_identifies_valid_sha256_hashes() - { - $parser = new DockerImageParser; - - // 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"); - } - } - - public function test_identifies_invalid_sha256_hashes() - { - $parser = new DockerImageParser; - - // Invalid SHA256 hashes - $invalidHashes = [ - 'latest', - 'v1.2.3', - 'abc123', // too short - '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf', // too short - '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cf00', // too long - '59e02939b1bf39f16c93138a28727aec520bb916da021180ae502c61626b3cfg0', // invalid char - ]; - - foreach ($invalidHashes as $hash) { - $parser->parse("image:{$hash}"); - $this->assertFalse($parser->isImageHash(), "Hash {$hash} should not be recognized as valid SHA256"); - } - } -} +}); From 7d99d6ad34114e111583cd8d6ac35dcdc729a508 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:42:29 +0200 Subject: [PATCH 48/56] feat(docker): improve Docker image submission logic with enhanced parsing - Added logic to strip 'sha256:' prefix and remove '@sha256' suffix from user input for image SHA256 and name. - Updated image name handling to append '@sha256' when using a digest, ensuring correct formatting. - Enhanced validation and parsing for Docker images to improve user experience and data integrity. --- app/Livewire/Project/New/DockerImage.php | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/app/Livewire/Project/New/DockerImage.php b/app/Livewire/Project/New/DockerImage.php index dd928b5e1..e105c956a 100644 --- a/app/Livewire/Project/New/DockerImage.php +++ b/app/Livewire/Project/New/DockerImage.php @@ -30,6 +30,16 @@ public function mount() public function submit() { + // Strip 'sha256:' prefix if user pasted it + if ($this->imageSha256) { + $this->imageSha256 = preg_replace('/^sha256:/i', '', trim($this->imageSha256)); + } + + // Remove @sha256 from image name if user added it + if ($this->imageName) { + $this->imageName = preg_replace('/@sha256$/i', '', trim($this->imageName)); + } + $this->validate([ 'imageName' => ['required', 'string'], 'imageTag' => ['nullable', 'string', 'regex:/^[a-z0-9][a-z0-9._-]*$/i'], @@ -72,6 +82,12 @@ public function submit() // Determine the image tag based on whether it's a hash or regular tag $imageTag = $parser->isImageHash() ? 'sha256-'.$parser->getTag() : $parser->getTag(); + // Append @sha256 to image name if using digest and not already present + $imageName = $parser->getFullImageNameWithoutTag(); + if ($parser->isImageHash() && ! str_ends_with($imageName, '@sha256')) { + $imageName .= '@sha256'; + } + $application = Application::create([ 'name' => 'docker-image-'.new Cuid2, 'repository_project_id' => 0, @@ -79,7 +95,7 @@ public function submit() 'git_branch' => 'main', 'build_pack' => 'dockerimage', 'ports_exposes' => 80, - 'docker_registry_image_name' => $parser->getFullImageNameWithoutTag(), + 'docker_registry_image_name' => $imageName, 'docker_registry_image_tag' => $parser->getTag(), 'environment_id' => $environment->id, 'destination_id' => $destination->id, From 41a8ea870f8fffcd9f105d373fd2a95f1bb13596 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 11:49:20 +0200 Subject: [PATCH 49/56] feat(docker): refine Docker image processing in application creation - Enhanced logic to process Docker image name and tag, including stripping 'sha256:' prefix and removing '@sha256' suffix. - Implemented validation to check for valid SHA256 hashes and conditionally append '@sha256' to the image name. - Defaulted the image tag to 'latest' if not provided, improving user experience and data integrity. --- .../Api/ApplicationsController.php | 27 +++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/ApplicationsController.php b/app/Http/Controllers/Api/ApplicationsController.php index ce9e723d4..065d7f767 100644 --- a/app/Http/Controllers/Api/ApplicationsController.php +++ b/app/Http/Controllers/Api/ApplicationsController.php @@ -1512,9 +1512,32 @@ private function create_application(Request $request, $type) if ($return instanceof \Illuminate\Http\JsonResponse) { return $return; } - if (! $request->docker_registry_image_tag) { - $request->offsetSet('docker_registry_image_tag', 'latest'); + // Process docker image name and tag for SHA256 digests + $dockerImageName = $request->docker_registry_image_name; + $dockerImageTag = $request->docker_registry_image_tag; + + // Strip 'sha256:' prefix if user provided it in the tag + if ($dockerImageTag) { + $dockerImageTag = preg_replace('/^sha256:/i', '', trim($dockerImageTag)); } + + // Remove @sha256 from image name if user added it + if ($dockerImageName) { + $dockerImageName = preg_replace('/@sha256$/i', '', trim($dockerImageName)); + } + + // Check if tag is a valid SHA256 hash (64 hex characters) + $isSha256Hash = $dockerImageTag && preg_match('/^[a-f0-9]{64}$/i', $dockerImageTag); + + // Append @sha256 to image name if using digest and not already present + if ($isSha256Hash && ! str_ends_with($dockerImageName, '@sha256')) { + $dockerImageName .= '@sha256'; + } + + // Set processed values back to request + $request->offsetSet('docker_registry_image_name', $dockerImageName); + $request->offsetSet('docker_registry_image_tag', $dockerImageTag ?: 'latest'); + $application = new Application; removeUnnecessaryFieldsFromRequest($request); From b4cfb78f86be7f11f2d28f97b795554a63762fee Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 16:39:57 +0200 Subject: [PATCH 50/56] feat(storage): add read-only volume handling and UI notifications - Introduced `isReadOnlyVolume` method in `LocalFileVolume` and `LocalPersistentVolume` models to determine if a volume is read-only based on Docker Compose configuration. - Updated `FileStorage` and `Show` components to set `isReadOnly` state during mounting. - Enhanced UI to display notifications for read-only volumes, preventing modification actions in the interface. - Refactored file storage and directory management forms to conditionally enable or disable actions based on read-only status. --- app/Livewire/Project/Service/FileStorage.php | 4 + app/Livewire/Project/Shared/Storages/Show.php | 5 + app/Models/LocalFileVolume.php | 58 ++++++ app/Models/LocalPersistentVolume.php | 66 +++++++ .../project/service/file-storage.blade.php | 124 +++++++----- .../project/service/storage.blade.php | 186 ++++++++++++++---- .../project/shared/storages/show.blade.php | 3 + 7 files changed, 358 insertions(+), 88 deletions(-) diff --git a/app/Livewire/Project/Service/FileStorage.php b/app/Livewire/Project/Service/FileStorage.php index 2933a8cca..7f0caaba3 100644 --- a/app/Livewire/Project/Service/FileStorage.php +++ b/app/Livewire/Project/Service/FileStorage.php @@ -34,6 +34,8 @@ class FileStorage extends Component public bool $permanently_delete = true; + public bool $isReadOnly = false; + protected $rules = [ 'fileStorage.is_directory' => 'required', 'fileStorage.fs_path' => 'required', @@ -52,6 +54,8 @@ public function mount() $this->workdir = null; $this->fs_path = $this->fileStorage->fs_path; } + + $this->isReadOnly = $this->fileStorage->isReadOnlyVolume(); } public function convertToDirectory() diff --git a/app/Livewire/Project/Shared/Storages/Show.php b/app/Livewire/Project/Shared/Storages/Show.php index 3928ee1d4..4f57cbfa6 100644 --- a/app/Livewire/Project/Shared/Storages/Show.php +++ b/app/Livewire/Project/Shared/Storages/Show.php @@ -37,6 +37,11 @@ class Show extends Component 'host_path' => 'host', ]; + public function mount() + { + $this->isReadOnly = $this->storage->isReadOnlyVolume(); + } + public function submit() { $this->authorize('update', $this->resource); diff --git a/app/Models/LocalFileVolume.php b/app/Models/LocalFileVolume.php index b3e71d75d..376ea9c5e 100644 --- a/app/Models/LocalFileVolume.php +++ b/app/Models/LocalFileVolume.php @@ -5,6 +5,7 @@ use App\Events\FileStorageChanged; use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Symfony\Component\Yaml\Yaml; class LocalFileVolume extends BaseModel { @@ -192,4 +193,61 @@ public function scopeWherePlainMountPath($query, $path) { return $query->get()->where('plain_mount_path', $path); } + + // Check if this volume is read-only by parsing the docker-compose content + public function isReadOnlyVolume(): bool + { + try { + // Only check for services + $service = $this->service; + if (! $service || ! method_exists($service, 'service')) { + return false; + } + + $actualService = $service->service; + if (! $actualService || ! $actualService->docker_compose_raw) { + return false; + } + + // Parse the docker-compose content + $compose = Yaml::parse($actualService->docker_compose_raw); + if (! isset($compose['services'])) { + return false; + } + + // Find the service that this volume belongs to + $serviceName = $service->name; + if (! isset($compose['services'][$serviceName]['volumes'])) { + return false; + } + + $volumes = $compose['services'][$serviceName]['volumes']; + + // Check each volume to find a match + foreach ($volumes as $volume) { + // Volume can be string like "host:container:ro" or "host:container" + if (is_string($volume)) { + $parts = explode(':', $volume); + + // Check if this volume matches our fs_path and mount_path + if (count($parts) >= 2) { + $hostPath = $parts[0]; + $containerPath = $parts[1]; + $options = $parts[2] ?? null; + + // Match based on fs_path and mount_path + if ($hostPath === $this->fs_path && $containerPath === $this->mount_path) { + return $options === 'ro'; + } + } + } + } + + return false; + } catch (\Throwable $e) { + ray($e->getMessage(), 'Error checking read-only volume'); + + return false; + } + } } diff --git a/app/Models/LocalPersistentVolume.php b/app/Models/LocalPersistentVolume.php index 00dc15fea..e7862478b 100644 --- a/app/Models/LocalPersistentVolume.php +++ b/app/Models/LocalPersistentVolume.php @@ -4,6 +4,7 @@ use Illuminate\Database\Eloquent\Casts\Attribute; use Illuminate\Database\Eloquent\Model; +use Symfony\Component\Yaml\Yaml; class LocalPersistentVolume extends Model { @@ -48,4 +49,69 @@ protected function hostPath(): Attribute } ); } + + // Check if this volume is read-only by parsing the docker-compose content + public function isReadOnlyVolume(): bool + { + try { + // Get the resource (can be application, service, or database) + $resource = $this->resource; + if (! $resource) { + return false; + } + + // Only check for services + if (! method_exists($resource, 'service')) { + return false; + } + + $actualService = $resource->service; + if (! $actualService || ! $actualService->docker_compose_raw) { + return false; + } + + // Parse the docker-compose content + $compose = Yaml::parse($actualService->docker_compose_raw); + if (! isset($compose['services'])) { + return false; + } + + // Find the service that this volume belongs to + $serviceName = $resource->name; + if (! isset($compose['services'][$serviceName]['volumes'])) { + return false; + } + + $volumes = $compose['services'][$serviceName]['volumes']; + + // Check each volume to find a match + foreach ($volumes as $volume) { + // Volume can be string like "host:container:ro" or "host:container" + if (is_string($volume)) { + $parts = explode(':', $volume); + + // Check if this volume matches our mount_path + if (count($parts) >= 2) { + $containerPath = $parts[1]; + $options = $parts[2] ?? null; + + // Match based on mount_path + // Remove leading slash from mount_path if present for comparison + $mountPath = str($this->mount_path)->ltrim('/')->toString(); + $containerPathClean = str($containerPath)->ltrim('/')->toString(); + + if ($mountPath === $containerPathClean || $this->mount_path === $containerPath) { + return $options === 'ro'; + } + } + } + } + + return false; + } catch (\Throwable $e) { + ray($e->getMessage(), 'Error checking read-only persistent volume'); + + return false; + } + } } diff --git a/resources/views/livewire/project/service/file-storage.blade.php b/resources/views/livewire/project/service/file-storage.blade.php index 3aa24b087..dc8f949fa 100644 --- a/resources/views/livewire/project/service/file-storage.blade.php +++ b/resources/views/livewire/project/service/file-storage.blade.php @@ -1,5 +1,14 @@
+ @if ($isReadOnly) +
+ @if ($fileStorage->is_directory) + This directory is mounted as read-only and cannot be modified from the UI. + @else + This file is mounted as read-only and cannot be modified from the UI. + @endif +
+ @endif
@@ -7,58 +16,75 @@
- @can('update', $resource) -
- @if ($fileStorage->is_directory) - - - @else - @if (!$fileStorage->is_binary) - + @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 +
+ @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 + @else + {{-- Read-only view --}} + @if (!$fileStorage->is_directory) @if (data_get($resource, 'settings.is_preserve_repository_enabled'))
- @endcan + @endif @endif
diff --git a/resources/views/livewire/project/service/storage.blade.php b/resources/views/livewire/project/service/storage.blade.php index 47ee99114..d55bd801a 100644 --- a/resources/views/livewire/project/service/storage.blade.php +++ b/resources/views/livewire/project/service/storage.blade.php @@ -23,7 +23,8 @@ volumeModalOpen: false, fileModalOpen: false, directoryModalOpen: false - }" @close-storage-modal.window=" + }" + @close-storage-modal.window=" if ($event.detail === 'volume') volumeModalOpen = false; if ($event.detail === 'file') fileModalOpen = false; if ($event.detail === 'directory') directoryModalOpen = false; @@ -45,8 +46,7 @@
- + -
+ x-init="$watch('volumeModalOpen', value => { + if (value) { + $nextTick(() => { + const input = $el.querySelector('input'); + input?.focus(); + }) + } + })"> +
Docker Volumes mounted to the container.
@if ($isSwarm) -
Swarm Mode detected: You need to set a shared volume - (EFS/NFS/etc) on all the worker nodes if you would like to use a persistent +
Swarm Mode detected: You need to set a shared + volume + (EFS/NFS/etc) on all the worker nodes if you would like to use a + persistent volumes.
@endif
@if ($isSwarm) - @else - @endif - + Add @@ -169,15 +179,24 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5
-
+ x-init="$watch('fileModalOpen', value => { + if (value) { + $nextTick(() => { + const input = $el.querySelector('input'); + input?.focus(); + }) + } + })"> +
Actual file mounted from the host system to the container.
+ label="Destination Path" required + helper="File location inside the container" /> @@ -219,18 +238,27 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5
- + x-init="$watch('directoryModalOpen', value => { + if (value) { + $nextTick(() => { + const input = $el.querySelector('input'); + input?.focus(); + }) + } + })"> +
Directory mounted from the host system to the container.
- + Add @@ -270,19 +298,22 @@ class="absolute top-0 right-0 flex items-center justify-center w-8 h-8 mt-5 mr-5 {{-- Tabs Navigation --}}
@endif @else - @if ($resource->persistentStorages()->get()->count() > 0) -

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

- @endif - @if ($resource->persistentStorages()->get()->count() > 0) - - @endif - @if ($fileStorage->count() > 0) -
- @foreach ($fileStorage->sort() as $fileStorage) - - @endforeach +
+
+
+

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

+
- @endif + + @if ($resource->persistentStorages()->get()->count() === 0 && $fileStorage->count() == 0) +
No storage found.
+ @endif + + @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 +
@endif
diff --git a/resources/views/livewire/project/shared/storages/show.blade.php b/resources/views/livewire/project/shared/storages/show.blade.php index 8c0ba0c06..798a97d94 100644 --- a/resources/views/livewire/project/shared/storages/show.blade.php +++ b/resources/views/livewire/project/shared/storages/show.blade.php @@ -1,6 +1,9 @@
@if ($isReadOnly) +
+ This volume is mounted as read-only and cannot be modified from the UI. +
@if ($isFirst)
@if ( From 4cf600445a83a96cd206f8fc3db4d8f19b02197d Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:05:32 +0200 Subject: [PATCH 51/56] feat(service): add Elasticsearch password handling in extraFields method - Implemented logic to retrieve and display the default user password for Elasticsearch in the extraFields method of the Service model. - Enhanced data collection for environment variables related to Elasticsearch, improving service configuration management. --- app/Models/Service.php | 15 +++++++++++++++ templates/service-templates-latest.json | 22 ++++++++++++++++++++++ templates/service-templates.json | 22 ++++++++++++++++++++++ 3 files changed, 59 insertions(+) diff --git a/app/Models/Service.php b/app/Models/Service.php index 063c8cba4..c4b8623e0 100644 --- a/app/Models/Service.php +++ b/app/Models/Service.php @@ -547,6 +547,21 @@ public function extraFields() } $fields->put('Grafana', $data->toArray()); break; + case $image->contains('elasticsearch'): + $data = collect([]); + $elastic_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ELASTICSEARCH')->first(); + if ($elastic_password) { + $data = $data->merge([ + 'Password (default user: elastic)' => [ + 'key' => data_get($elastic_password, 'key'), + 'value' => data_get($elastic_password, 'value'), + 'rules' => 'required', + 'isPassword' => true, + ], + ]); + } + $fields->put('Elasticsearch', $data->toArray()); + break; case $image->contains('directus'): $data = collect([]); $admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first(); diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index 7b6aacef8..c9b1393a1 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -899,6 +899,28 @@ "minversion": "0.0.0", "port": "80" }, + "elasticsearch-kibana": { + "documentation": "https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker?utm_source=coolify.io", + "slogan": "Elastic + Kibana is a Free and Open Source Search, Monitoring, and Visualization Stack", + "compose": "c2VydmljZXM6CiAgZWxhc3RpY3NlYXJjaDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGVsYXN0aWNzZWFyY2gKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0VTX0pBVkFfT1BUUz0tWG1zNTEybSAtWG14NTEybScKICAgICAgLSBkaXNjb3ZlcnkudHlwZT1zaW5nbGUtbm9kZQogICAgICAtIGJvb3RzdHJhcC5tZW1vcnlfbG9jaz10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuZW5hYmxlZD10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuaHR0cC5zc2wuZW5hYmxlZD1mYWxzZQogICAgICAtIHhwYWNrLnNlY3VyaXR5LnRyYW5zcG9ydC5zc2wuZW5hYmxlZD1mYWxzZQogICAgdm9sdW1lczoKICAgICAgLSAnL2V0Yy9sb2NhbHRpbWU6L2V0Yy9sb2NhbHRpbWU6cm8nCiAgICAgIC0gJ2VsYXN0aWNzZWFyY2gtZGF0YTovdXNyL3NoYXJlL2VsYXN0aWNzZWFyY2gvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtLXVzZXIgZWxhc3RpYzoke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0gLS1zaWxlbnQgLS1mYWlsIGh0dHA6Ly9sb2NhbGhvc3Q6OTIwMC9fY2x1c3Rlci9oZWFsdGggfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAyNAogIGtpYmFuYToKICAgIGltYWdlOiAna2liYW5hOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYQogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX0tJQkFOQV81NjAxCiAgICAgIC0gJ1NFUlZFUl9OQU1FPSR7U0VSVklDRV9VUkxfS0lCQU5BfScKICAgICAgLSAnU0VSVkVSX1BVQkxJQ0JBU0VVUkw9JHtTRVJWSUNFX1VSTF9LSUJBTkF9JwogICAgICAtICdFTEFTVElDU0VBUkNIX0hPU1RTPWh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAnCiAgICAgIC0gRUxBU1RJQ1NFQVJDSF9VU0VSTkFNRT1raWJhbmFfc3lzdGVtCiAgICAgIC0gJ0VMQVNUSUNTRUFSQ0hfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX0tJQkFOQX0nCiAgICAgIC0gJ1hQQUNLX1NFQ1VSSVRZX0VOQ1JZUFRJT05LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1hQQUNLU0VDVVJJVFl9JwogICAgICAtICdYUEFDS19SRVBPUlRJTkdfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tSRVBPUlRJTkd9JwogICAgICAtICdYUEFDS19FTkNSWVBURURTQVZFRE9CSkVDVFNfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tFTkNSWVBURURTQVZFRE9CSkVDVFN9JwogICAgICAtICdURUxFTUVUUllfT1BUSU49JHtURUxFTUVUUllfT1BUSU46LWZhbHNlfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJy9ldGMvbG9jYWx0aW1lOi9ldGMvbG9jYWx0aW1lOnJvJwogICAgICAtICdraWJhbmEtZGF0YTovdXNyL3NoYXJlL2tpYmFuYS9kYXRhJwogICAgZGVwZW5kc19vbjoKICAgICAgc2V0dXA6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtcyBodHRwOi8vbG9jYWxob3N0OjU2MDEvYXBpL3N0YXR1cyB8IGdyZXAgLXEgJycibGV2ZWwiOiJhdmFpbGFibGUiJycgfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxMjAKICBzZXR1cDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYS1zZXR1cAogICAgZGVwZW5kc19vbjoKICAgICAgZWxhc3RpY3NlYXJjaDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZXhjbHVkZV9mcm9tX2hjOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0tJQkFOQV9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfS0lCQU5BfScKICAgIGVudHJ5cG9pbnQ6CiAgICAgIC0gc2gKICAgICAgLSAnLWMnCiAgICAgIC0gImVjaG8gXCJTZXR0aW5nIHVwIEtpYmFuYSB1c2VyIHBhc3N3b3JkLi4uXCJcblxudW50aWwgY3VybCAtcyAtdSBcImVsYXN0aWM6JHtFTEFTVElDX1BBU1NXT1JEfVwiIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX2NsdXN0ZXIvaGVhbHRoIHwgZ3JlcCAtcSAnXCJzdGF0dXNcIjpcImdyZWVuXFx8eWVsbG93XCInOyBkb1xuICBlY2hvIFwiV2FpdGluZyBmb3IgRWxhc3RpY3NlYXJjaC4uLlwiXG4gIHNsZWVwIDJcbmRvbmVcblxuZWNobyBcIlNldHRpbmcgcGFzc3dvcmQgZm9yIGtpYmFuYV9zeXN0ZW0gdXNlci4uLlwiXG5jdXJsIC1zIC1YIFBPU1QgLXUgXCJlbGFzdGljOiR7RUxBU1RJQ19QQVNTV09SRH1cIiBcXFxuICAtSCBcIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvblwiIFxcXG4gIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX3NlY3VyaXR5L3VzZXIva2liYW5hX3N5c3RlbS9fcGFzc3dvcmQgXFxcbiAgLWQgXCJ7XFxcInBhc3N3b3JkXFxcIjpcXFwiJHtLSUJBTkFfUEFTU1dPUkR9XFxcIn1cIiB8fCBleGl0IDFcblxuZWNobyBcIktpYmFuYSBzZXR1cCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIiCiAgICByZXN0YXJ0OiAnbm8nCg==", + "tags": [ + "elastic", + "kibana", + "elasticsearch", + "search", + "visualization", + "logging", + "monitoring", + "observability", + "analytics", + "stack", + "devops" + ], + "category": null, + "logo": "svgs/elasticsearch.svg", + "minversion": "0.0.0", + "port": "5601" + }, "elasticsearch": { "documentation": "https://www.elastic.co/products/elasticsearch?utm_source=coolify.io", "slogan": "Elasticsearch is free and Open Source, Distributed, RESTful Search Engine.", diff --git a/templates/service-templates.json b/templates/service-templates.json index ad422bdc5..2cdecfcc6 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -899,6 +899,28 @@ "minversion": "0.0.0", "port": "80" }, + "elasticsearch-kibana": { + "documentation": "https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker?utm_source=coolify.io", + "slogan": "Elastic + Kibana is a Free and Open Source Search, Monitoring, and Visualization Stack", + "compose": "c2VydmljZXM6CiAgZWxhc3RpY3NlYXJjaDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGVsYXN0aWNzZWFyY2gKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0VTX0pBVkFfT1BUUz0tWG1zNTEybSAtWG14NTEybScKICAgICAgLSBkaXNjb3ZlcnkudHlwZT1zaW5nbGUtbm9kZQogICAgICAtIGJvb3RzdHJhcC5tZW1vcnlfbG9jaz10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuZW5hYmxlZD10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuaHR0cC5zc2wuZW5hYmxlZD1mYWxzZQogICAgICAtIHhwYWNrLnNlY3VyaXR5LnRyYW5zcG9ydC5zc2wuZW5hYmxlZD1mYWxzZQogICAgdm9sdW1lczoKICAgICAgLSAnL2V0Yy9sb2NhbHRpbWU6L2V0Yy9sb2NhbHRpbWU6cm8nCiAgICAgIC0gJ2VsYXN0aWNzZWFyY2gtZGF0YTovdXNyL3NoYXJlL2VsYXN0aWNzZWFyY2gvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtLXVzZXIgZWxhc3RpYzoke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0gLS1zaWxlbnQgLS1mYWlsIGh0dHA6Ly9sb2NhbGhvc3Q6OTIwMC9fY2x1c3Rlci9oZWFsdGggfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAyNAogIGtpYmFuYToKICAgIGltYWdlOiAna2liYW5hOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYQogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9LSUJBTkFfNTYwMQogICAgICAtICdTRVJWRVJfTkFNRT0ke1NFUlZJQ0VfRlFETl9LSUJBTkF9JwogICAgICAtICdTRVJWRVJfUFVCTElDQkFTRVVSTD0ke1NFUlZJQ0VfRlFETl9LSUJBTkF9JwogICAgICAtICdFTEFTVElDU0VBUkNIX0hPU1RTPWh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAnCiAgICAgIC0gRUxBU1RJQ1NFQVJDSF9VU0VSTkFNRT1raWJhbmFfc3lzdGVtCiAgICAgIC0gJ0VMQVNUSUNTRUFSQ0hfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX0tJQkFOQX0nCiAgICAgIC0gJ1hQQUNLX1NFQ1VSSVRZX0VOQ1JZUFRJT05LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1hQQUNLU0VDVVJJVFl9JwogICAgICAtICdYUEFDS19SRVBPUlRJTkdfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tSRVBPUlRJTkd9JwogICAgICAtICdYUEFDS19FTkNSWVBURURTQVZFRE9CSkVDVFNfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tFTkNSWVBURURTQVZFRE9CSkVDVFN9JwogICAgICAtICdURUxFTUVUUllfT1BUSU49JHtURUxFTUVUUllfT1BUSU46LWZhbHNlfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJy9ldGMvbG9jYWx0aW1lOi9ldGMvbG9jYWx0aW1lOnJvJwogICAgICAtICdraWJhbmEtZGF0YTovdXNyL3NoYXJlL2tpYmFuYS9kYXRhJwogICAgZGVwZW5kc19vbjoKICAgICAgc2V0dXA6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtcyBodHRwOi8vbG9jYWxob3N0OjU2MDEvYXBpL3N0YXR1cyB8IGdyZXAgLXEgJycibGV2ZWwiOiJhdmFpbGFibGUiJycgfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxMjAKICBzZXR1cDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYS1zZXR1cAogICAgZGVwZW5kc19vbjoKICAgICAgZWxhc3RpY3NlYXJjaDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZXhjbHVkZV9mcm9tX2hjOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0tJQkFOQV9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfS0lCQU5BfScKICAgIGVudHJ5cG9pbnQ6CiAgICAgIC0gc2gKICAgICAgLSAnLWMnCiAgICAgIC0gImVjaG8gXCJTZXR0aW5nIHVwIEtpYmFuYSB1c2VyIHBhc3N3b3JkLi4uXCJcblxudW50aWwgY3VybCAtcyAtdSBcImVsYXN0aWM6JHtFTEFTVElDX1BBU1NXT1JEfVwiIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX2NsdXN0ZXIvaGVhbHRoIHwgZ3JlcCAtcSAnXCJzdGF0dXNcIjpcImdyZWVuXFx8eWVsbG93XCInOyBkb1xuICBlY2hvIFwiV2FpdGluZyBmb3IgRWxhc3RpY3NlYXJjaC4uLlwiXG4gIHNsZWVwIDJcbmRvbmVcblxuZWNobyBcIlNldHRpbmcgcGFzc3dvcmQgZm9yIGtpYmFuYV9zeXN0ZW0gdXNlci4uLlwiXG5jdXJsIC1zIC1YIFBPU1QgLXUgXCJlbGFzdGljOiR7RUxBU1RJQ19QQVNTV09SRH1cIiBcXFxuICAtSCBcIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvblwiIFxcXG4gIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX3NlY3VyaXR5L3VzZXIva2liYW5hX3N5c3RlbS9fcGFzc3dvcmQgXFxcbiAgLWQgXCJ7XFxcInBhc3N3b3JkXFxcIjpcXFwiJHtLSUJBTkFfUEFTU1dPUkR9XFxcIn1cIiB8fCBleGl0IDFcblxuZWNobyBcIktpYmFuYSBzZXR1cCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIiCiAgICByZXN0YXJ0OiAnbm8nCg==", + "tags": [ + "elastic", + "kibana", + "elasticsearch", + "search", + "visualization", + "logging", + "monitoring", + "observability", + "analytics", + "stack", + "devops" + ], + "category": null, + "logo": "svgs/elasticsearch.svg", + "minversion": "0.0.0", + "port": "5601" + }, "elasticsearch": { "documentation": "https://www.elastic.co/products/elasticsearch?utm_source=coolify.io", "slogan": "Elasticsearch is free and Open Source, Distributed, RESTful Search Engine.", From c14497303f687de988adbfd83bd3f42059366952 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Fri, 3 Oct 2025 20:06:27 +0200 Subject: [PATCH 52/56] fix(elasticsearch): update Elasticsearch and Kibana configuration for enhanced security and setup - Removed unnecessary environment variables and added security settings for Elasticsearch and Kibana. - Implemented password setup for the kibana_system user during the Kibana setup process. - Updated healthcheck commands for both services to ensure proper monitoring and readiness. - Introduced a new setup service for Kibana to streamline user password configuration. --- .../compose/elasticsearch-with-kibana.yaml | 91 +++++++++---------- templates/service-templates-latest.json | 2 +- templates/service-templates.json | 2 +- 3 files changed, 44 insertions(+), 51 deletions(-) diff --git a/templates/compose/elasticsearch-with-kibana.yaml b/templates/compose/elasticsearch-with-kibana.yaml index f200d2813..6cc08d889 100644 --- a/templates/compose/elasticsearch-with-kibana.yaml +++ b/templates/compose/elasticsearch-with-kibana.yaml @@ -10,86 +10,79 @@ services: 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 + - ELASTIC_PASSWORD=${SERVICE_PASSWORD_ELASTICSEARCH} + - 'ES_JAVA_OPTS=-Xms512m -Xmx512m' + - discovery.type=single-node + - bootstrap.memory_lock=true + - xpack.security.enabled=true + - xpack.security.http.ssl.enabled=false + - xpack.security.transport.ssl.enabled=false volumes: - - '/etc/localtime:/etc/localtime:ro' # Sync container timezone with host + - '/etc/localtime:/etc/localtime:ro' - 'elasticsearch-data:/usr/share/elasticsearch/data' healthcheck: test: - CMD-SHELL - - 'curl --user elastic:${SERVICE_PASSWORD_ELASTICSEARCH} --silent --fail http://localhost:9200/_cluster/health' + - 'curl --user elastic:${SERVICE_PASSWORD_ELASTICSEARCH} --silent --fail http://localhost:9200/_cluster/health || exit 1' 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_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 - - '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) + - 'SERVER_NAME=${SERVICE_URL_KIBANA}' + - 'SERVER_PUBLICBASEURL=${SERVICE_URL_KIBANA}' + - 'ELASTICSEARCH_HOSTS=http://elasticsearch:9200' + - 'ELASTICSEARCH_USERNAME=kibana_system' + - 'ELASTICSEARCH_PASSWORD=${SERVICE_PASSWORD_KIBANA}' + - 'XPACK_SECURITY_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKSECURITY}' + - 'XPACK_REPORTING_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKREPORTING}' + - 'XPACK_ENCRYPTEDSAVEDOBJECTS_ENCRYPTIONKEY=${SERVICE_PASSWORD_XPACKENCRYPTEDSAVEDOBJECTS}' + - 'TELEMETRY_OPTIN=${TELEMETRY_OPTIN:-false}' volumes: - - '/etc/localtime:/etc/localtime:ro' # Sync container timezone with host + - '/etc/localtime:/etc/localtime:ro' - 'kibana-data:/usr/share/kibana/data' depends_on: - elasticsearch: - condition: service_healthy + setup: + condition: service_completed_successfully 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 + - "curl -s http://localhost:5601/api/status | grep -q '\"level\":\"available\"' || exit 1" interval: 10s timeout: 10s retries: 120 - kibana-token-generator: - image: 'alpine:latest' - container_name: kibana-token-generator + + setup: + image: 'elastic/elasticsearch:9.1.2' + container_name: kibana-setup depends_on: elasticsearch: condition: service_healthy exclude_from_hc: true environment: - - 'ELASTIC_PASSWORD=${SERVICE_PASSWORD_ELASTICSEARCH}' # Needed to authenticate the ELASTICSEARCH_SERVICEACCOUNTTOKEN creation request + - 'ELASTIC_PASSWORD=${SERVICE_PASSWORD_ELASTICSEARCH}' + - 'KIBANA_PASSWORD=${SERVICE_PASSWORD_KIBANA}' entrypoint: - sh - '-c' - | - apk add --no-cache curl jq >/dev/null 2>&1 - echo "Generating Kibana service token..." + echo "Setting up Kibana user password..." - 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) + until curl -s -u "elastic:${ELASTIC_PASSWORD}" http://elasticsearch:9200/_cluster/health | grep -q '"status":"green\|yellow"'; do + echo "Waiting for Elasticsearch..." + sleep 2 + done - 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 + echo "Setting password for kibana_system user..." + curl -s -X POST -u "elastic:${ELASTIC_PASSWORD}" \ + -H "Content-Type: application/json" \ + http://elasticsearch:9200/_security/user/kibana_system/_password \ + -d "{\"password\":\"${KIBANA_PASSWORD}\"}" || exit 1 + + echo "Kibana setup completed successfully" + restart: 'no' diff --git a/templates/service-templates-latest.json b/templates/service-templates-latest.json index c9b1393a1..39bc024bd 100644 --- a/templates/service-templates-latest.json +++ b/templates/service-templates-latest.json @@ -899,7 +899,7 @@ "minversion": "0.0.0", "port": "80" }, - "elasticsearch-kibana": { + "elasticsearch-with-kibana": { "documentation": "https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker?utm_source=coolify.io", "slogan": "Elastic + Kibana is a Free and Open Source Search, Monitoring, and Visualization Stack", "compose": "c2VydmljZXM6CiAgZWxhc3RpY3NlYXJjaDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGVsYXN0aWNzZWFyY2gKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0VTX0pBVkFfT1BUUz0tWG1zNTEybSAtWG14NTEybScKICAgICAgLSBkaXNjb3ZlcnkudHlwZT1zaW5nbGUtbm9kZQogICAgICAtIGJvb3RzdHJhcC5tZW1vcnlfbG9jaz10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuZW5hYmxlZD10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuaHR0cC5zc2wuZW5hYmxlZD1mYWxzZQogICAgICAtIHhwYWNrLnNlY3VyaXR5LnRyYW5zcG9ydC5zc2wuZW5hYmxlZD1mYWxzZQogICAgdm9sdW1lczoKICAgICAgLSAnL2V0Yy9sb2NhbHRpbWU6L2V0Yy9sb2NhbHRpbWU6cm8nCiAgICAgIC0gJ2VsYXN0aWNzZWFyY2gtZGF0YTovdXNyL3NoYXJlL2VsYXN0aWNzZWFyY2gvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtLXVzZXIgZWxhc3RpYzoke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0gLS1zaWxlbnQgLS1mYWlsIGh0dHA6Ly9sb2NhbGhvc3Q6OTIwMC9fY2x1c3Rlci9oZWFsdGggfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAyNAogIGtpYmFuYToKICAgIGltYWdlOiAna2liYW5hOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYQogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfVVJMX0tJQkFOQV81NjAxCiAgICAgIC0gJ1NFUlZFUl9OQU1FPSR7U0VSVklDRV9VUkxfS0lCQU5BfScKICAgICAgLSAnU0VSVkVSX1BVQkxJQ0JBU0VVUkw9JHtTRVJWSUNFX1VSTF9LSUJBTkF9JwogICAgICAtICdFTEFTVElDU0VBUkNIX0hPU1RTPWh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAnCiAgICAgIC0gRUxBU1RJQ1NFQVJDSF9VU0VSTkFNRT1raWJhbmFfc3lzdGVtCiAgICAgIC0gJ0VMQVNUSUNTRUFSQ0hfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX0tJQkFOQX0nCiAgICAgIC0gJ1hQQUNLX1NFQ1VSSVRZX0VOQ1JZUFRJT05LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1hQQUNLU0VDVVJJVFl9JwogICAgICAtICdYUEFDS19SRVBPUlRJTkdfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tSRVBPUlRJTkd9JwogICAgICAtICdYUEFDS19FTkNSWVBURURTQVZFRE9CSkVDVFNfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tFTkNSWVBURURTQVZFRE9CSkVDVFN9JwogICAgICAtICdURUxFTUVUUllfT1BUSU49JHtURUxFTUVUUllfT1BUSU46LWZhbHNlfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJy9ldGMvbG9jYWx0aW1lOi9ldGMvbG9jYWx0aW1lOnJvJwogICAgICAtICdraWJhbmEtZGF0YTovdXNyL3NoYXJlL2tpYmFuYS9kYXRhJwogICAgZGVwZW5kc19vbjoKICAgICAgc2V0dXA6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtcyBodHRwOi8vbG9jYWxob3N0OjU2MDEvYXBpL3N0YXR1cyB8IGdyZXAgLXEgJycibGV2ZWwiOiJhdmFpbGFibGUiJycgfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxMjAKICBzZXR1cDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYS1zZXR1cAogICAgZGVwZW5kc19vbjoKICAgICAgZWxhc3RpY3NlYXJjaDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZXhjbHVkZV9mcm9tX2hjOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0tJQkFOQV9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfS0lCQU5BfScKICAgIGVudHJ5cG9pbnQ6CiAgICAgIC0gc2gKICAgICAgLSAnLWMnCiAgICAgIC0gImVjaG8gXCJTZXR0aW5nIHVwIEtpYmFuYSB1c2VyIHBhc3N3b3JkLi4uXCJcblxudW50aWwgY3VybCAtcyAtdSBcImVsYXN0aWM6JHtFTEFTVElDX1BBU1NXT1JEfVwiIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX2NsdXN0ZXIvaGVhbHRoIHwgZ3JlcCAtcSAnXCJzdGF0dXNcIjpcImdyZWVuXFx8eWVsbG93XCInOyBkb1xuICBlY2hvIFwiV2FpdGluZyBmb3IgRWxhc3RpY3NlYXJjaC4uLlwiXG4gIHNsZWVwIDJcbmRvbmVcblxuZWNobyBcIlNldHRpbmcgcGFzc3dvcmQgZm9yIGtpYmFuYV9zeXN0ZW0gdXNlci4uLlwiXG5jdXJsIC1zIC1YIFBPU1QgLXUgXCJlbGFzdGljOiR7RUxBU1RJQ19QQVNTV09SRH1cIiBcXFxuICAtSCBcIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvblwiIFxcXG4gIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX3NlY3VyaXR5L3VzZXIva2liYW5hX3N5c3RlbS9fcGFzc3dvcmQgXFxcbiAgLWQgXCJ7XFxcInBhc3N3b3JkXFxcIjpcXFwiJHtLSUJBTkFfUEFTU1dPUkR9XFxcIn1cIiB8fCBleGl0IDFcblxuZWNobyBcIktpYmFuYSBzZXR1cCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIiCiAgICByZXN0YXJ0OiAnbm8nCg==", diff --git a/templates/service-templates.json b/templates/service-templates.json index 2cdecfcc6..9ba329247 100644 --- a/templates/service-templates.json +++ b/templates/service-templates.json @@ -899,7 +899,7 @@ "minversion": "0.0.0", "port": "80" }, - "elasticsearch-kibana": { + "elasticsearch-with-kibana": { "documentation": "https://www.elastic.co/docs/deploy-manage/deploy/self-managed/install-kibana-with-docker?utm_source=coolify.io", "slogan": "Elastic + Kibana is a Free and Open Source Search, Monitoring, and Visualization Stack", "compose": "c2VydmljZXM6CiAgZWxhc3RpY3NlYXJjaDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGVsYXN0aWNzZWFyY2gKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0VTX0pBVkFfT1BUUz0tWG1zNTEybSAtWG14NTEybScKICAgICAgLSBkaXNjb3ZlcnkudHlwZT1zaW5nbGUtbm9kZQogICAgICAtIGJvb3RzdHJhcC5tZW1vcnlfbG9jaz10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuZW5hYmxlZD10cnVlCiAgICAgIC0geHBhY2suc2VjdXJpdHkuaHR0cC5zc2wuZW5hYmxlZD1mYWxzZQogICAgICAtIHhwYWNrLnNlY3VyaXR5LnRyYW5zcG9ydC5zc2wuZW5hYmxlZD1mYWxzZQogICAgdm9sdW1lczoKICAgICAgLSAnL2V0Yy9sb2NhbHRpbWU6L2V0Yy9sb2NhbHRpbWU6cm8nCiAgICAgIC0gJ2VsYXN0aWNzZWFyY2gtZGF0YTovdXNyL3NoYXJlL2VsYXN0aWNzZWFyY2gvZGF0YScKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtLXVzZXIgZWxhc3RpYzoke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0gLS1zaWxlbnQgLS1mYWlsIGh0dHA6Ly9sb2NhbGhvc3Q6OTIwMC9fY2x1c3Rlci9oZWFsdGggfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAyNAogIGtpYmFuYToKICAgIGltYWdlOiAna2liYW5hOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYQogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFUlZJQ0VfRlFETl9LSUJBTkFfNTYwMQogICAgICAtICdTRVJWRVJfTkFNRT0ke1NFUlZJQ0VfRlFETl9LSUJBTkF9JwogICAgICAtICdTRVJWRVJfUFVCTElDQkFTRVVSTD0ke1NFUlZJQ0VfRlFETl9LSUJBTkF9JwogICAgICAtICdFTEFTVElDU0VBUkNIX0hPU1RTPWh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAnCiAgICAgIC0gRUxBU1RJQ1NFQVJDSF9VU0VSTkFNRT1raWJhbmFfc3lzdGVtCiAgICAgIC0gJ0VMQVNUSUNTRUFSQ0hfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX0tJQkFOQX0nCiAgICAgIC0gJ1hQQUNLX1NFQ1VSSVRZX0VOQ1JZUFRJT05LRVk9JHtTRVJWSUNFX1BBU1NXT1JEX1hQQUNLU0VDVVJJVFl9JwogICAgICAtICdYUEFDS19SRVBPUlRJTkdfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tSRVBPUlRJTkd9JwogICAgICAtICdYUEFDS19FTkNSWVBURURTQVZFRE9CSkVDVFNfRU5DUllQVElPTktFWT0ke1NFUlZJQ0VfUEFTU1dPUkRfWFBBQ0tFTkNSWVBURURTQVZFRE9CSkVDVFN9JwogICAgICAtICdURUxFTUVUUllfT1BUSU49JHtURUxFTUVUUllfT1BUSU46LWZhbHNlfScKICAgIHZvbHVtZXM6CiAgICAgIC0gJy9ldGMvbG9jYWx0aW1lOi9ldGMvbG9jYWx0aW1lOnJvJwogICAgICAtICdraWJhbmEtZGF0YTovdXNyL3NoYXJlL2tpYmFuYS9kYXRhJwogICAgZGVwZW5kc19vbjoKICAgICAgc2V0dXA6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2NvbXBsZXRlZF9zdWNjZXNzZnVsbHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ELVNIRUxMCiAgICAgICAgLSAnY3VybCAtcyBodHRwOi8vbG9jYWxob3N0OjU2MDEvYXBpL3N0YXR1cyB8IGdyZXAgLXEgJycibGV2ZWwiOiJhdmFpbGFibGUiJycgfHwgZXhpdCAxJwogICAgICBpbnRlcnZhbDogMTBzCiAgICAgIHRpbWVvdXQ6IDEwcwogICAgICByZXRyaWVzOiAxMjAKICBzZXR1cDoKICAgIGltYWdlOiAnZWxhc3RpYy9lbGFzdGljc2VhcmNoOjkuMS4yJwogICAgY29udGFpbmVyX25hbWU6IGtpYmFuYS1zZXR1cAogICAgZGVwZW5kc19vbjoKICAgICAgZWxhc3RpY3NlYXJjaDoKICAgICAgICBjb25kaXRpb246IHNlcnZpY2VfaGVhbHRoeQogICAgZXhjbHVkZV9mcm9tX2hjOiB0cnVlCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnRUxBU1RJQ19QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfRUxBU1RJQ1NFQVJDSH0nCiAgICAgIC0gJ0tJQkFOQV9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfS0lCQU5BfScKICAgIGVudHJ5cG9pbnQ6CiAgICAgIC0gc2gKICAgICAgLSAnLWMnCiAgICAgIC0gImVjaG8gXCJTZXR0aW5nIHVwIEtpYmFuYSB1c2VyIHBhc3N3b3JkLi4uXCJcblxudW50aWwgY3VybCAtcyAtdSBcImVsYXN0aWM6JHtFTEFTVElDX1BBU1NXT1JEfVwiIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX2NsdXN0ZXIvaGVhbHRoIHwgZ3JlcCAtcSAnXCJzdGF0dXNcIjpcImdyZWVuXFx8eWVsbG93XCInOyBkb1xuICBlY2hvIFwiV2FpdGluZyBmb3IgRWxhc3RpY3NlYXJjaC4uLlwiXG4gIHNsZWVwIDJcbmRvbmVcblxuZWNobyBcIlNldHRpbmcgcGFzc3dvcmQgZm9yIGtpYmFuYV9zeXN0ZW0gdXNlci4uLlwiXG5jdXJsIC1zIC1YIFBPU1QgLXUgXCJlbGFzdGljOiR7RUxBU1RJQ19QQVNTV09SRH1cIiBcXFxuICAtSCBcIkNvbnRlbnQtVHlwZTogYXBwbGljYXRpb24vanNvblwiIFxcXG4gIGh0dHA6Ly9lbGFzdGljc2VhcmNoOjkyMDAvX3NlY3VyaXR5L3VzZXIva2liYW5hX3N5c3RlbS9fcGFzc3dvcmQgXFxcbiAgLWQgXCJ7XFxcInBhc3N3b3JkXFxcIjpcXFwiJHtLSUJBTkFfUEFTU1dPUkR9XFxcIn1cIiB8fCBleGl0IDFcblxuZWNobyBcIktpYmFuYSBzZXR1cCBjb21wbGV0ZWQgc3VjY2Vzc2Z1bGx5XCIiCiAgICByZXN0YXJ0OiAnbm8nCg==", From 158747c8b133c852dc1bf0e626ee4e5246292efa Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 4 Oct 2025 15:06:49 +0200 Subject: [PATCH 53/56] refactor(deployment): streamline environment variable generation in ApplicationDeploymentJob - Removed redundant logic for merging COOLIFY_* variables into env_args. - Simplified the process of adding environment variables by directly incorporating generated COOLIFY environment variables. - Enhanced clarity and maintainability of the generate_env_variables method. --- app/Jobs/ApplicationDeploymentJob.php | 41 ++++----------------------- 1 file changed, 5 insertions(+), 36 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 91e105f56..93f730335 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -1965,10 +1965,14 @@ private function generate_env_variables() { $this->env_args = collect([]); $this->env_args->put('SOURCE_COMMIT', $this->commit); + $coolify_envs = $this->generate_coolify_env_variables(); + $coolify_envs->each(function ($value, $key) { + $this->env_args->put($key, $value); + }); + // For build process, include only environment variables where is_buildtime = true if ($this->pull_request_id === 0) { - // Get environment variables that are marked as available during build $envs = $this->application->environment_variables() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) @@ -1977,24 +1981,9 @@ private function generate_env_variables() foreach ($envs as $env) { if (! is_null($env->real_value)) { $this->env_args->put($env->key, $env->real_value); - if (str($env->real_value)->startsWith('$')) { - $variable_key = str($env->real_value)->after('$'); - if ($variable_key->startsWith('COOLIFY_')) { - $variable = $coolify_envs->get($variable_key->value()); - if (filled($variable)) { - $this->env_args->prepend($variable, $variable_key->value()); - } - } else { - $variable = $this->application->environment_variables()->where('key', $variable_key)->first(); - if ($variable) { - $this->env_args->prepend($variable->real_value, $env->key); - } - } - } } } } else { - // Get preview environment variables that are marked as available during build $envs = $this->application->environment_variables_preview() ->where('key', 'not like', 'NIXPACKS_%') ->where('is_buildtime', true) @@ -2003,29 +1992,9 @@ private function generate_env_variables() foreach ($envs as $env) { if (! is_null($env->real_value)) { $this->env_args->put($env->key, $env->real_value); - if (str($env->real_value)->startsWith('$')) { - $variable_key = str($env->real_value)->after('$'); - if ($variable_key->startsWith('COOLIFY_')) { - $variable = $coolify_envs->get($variable_key->value()); - if (filled($variable)) { - $this->env_args->prepend($variable, $variable_key->value()); - } - } else { - $variable = $this->application->environment_variables_preview()->where('key', $variable_key)->first(); - if ($variable) { - $this->env_args->prepend($variable->real_value, $env->key); - } - } - } } } } - - // Merge COOLIFY_* variables into env_args for build process - // This ensures they're available for both build args and build secrets - $coolify_envs->each(function ($value, $key) { - $this->env_args->put($key, $value); - }); } private function generate_compose_file() From 4b947a0d64157ea083ead95d5e6ad2671d1afac6 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 4 Oct 2025 18:02:20 +0200 Subject: [PATCH 54/56] refactor(deployment): enhance deployment data retrieval and relationships - Updated the deployments method in DeploymentsIndicator to include application environment and project relationships for better data context. - Refactored the application method in ApplicationDeploymentQueue to use Eloquent relationships instead of manual fetching, improving performance and readability. - Enhanced the deployments indicator view to display application environment and project names, providing clearer deployment context. --- app/Livewire/DeploymentsIndicator.php | 3 ++- app/Models/ApplicationDeploymentQueue.php | 6 ++---- resources/views/livewire/deployments-indicator.blade.php | 3 +++ 3 files changed, 7 insertions(+), 5 deletions(-) diff --git a/app/Livewire/DeploymentsIndicator.php b/app/Livewire/DeploymentsIndicator.php index 0293ad6c6..ac9cfd1c2 100644 --- a/app/Livewire/DeploymentsIndicator.php +++ b/app/Livewire/DeploymentsIndicator.php @@ -16,7 +16,8 @@ public function deployments() { $servers = Server::ownedByCurrentTeam()->get(); - return ApplicationDeploymentQueue::whereIn('status', ['in_progress', 'queued']) + return ApplicationDeploymentQueue::with(['application.environment.project']) + ->whereIn('status', ['in_progress', 'queued']) ->whereIn('server_id', $servers->pluck('id')) ->orderBy('id') ->get([ diff --git a/app/Models/ApplicationDeploymentQueue.php b/app/Models/ApplicationDeploymentQueue.php index 8df6877ab..4e8eee10f 100644 --- a/app/Models/ApplicationDeploymentQueue.php +++ b/app/Models/ApplicationDeploymentQueue.php @@ -41,11 +41,9 @@ class ApplicationDeploymentQueue extends Model { protected $guarded = []; - public function application(): Attribute + public function application() { - return Attribute::make( - get: fn () => Application::find($this->application_id), - ); + return $this->belongsTo(Application::class); } public function server(): Attribute diff --git a/resources/views/livewire/deployments-indicator.blade.php b/resources/views/livewire/deployments-indicator.blade.php index ed24249e0..7f3cc23ed 100644 --- a/resources/views/livewire/deployments-indicator.blade.php +++ b/resources/views/livewire/deployments-indicator.blade.php @@ -68,6 +68,9 @@ class="flex items-start gap-3 p-3 rounded-lg dark:bg-coolgray-200 bg-gray-50 tra {{ $deployment->application_name }}

+ {{ $deployment->application?->environment?->project?->name }} / {{ $deployment->application?->environment?->name }} +

+

{{ $deployment->server_name }}

@if ($deployment->pull_request_id) From 06dfcff55951a80c799e52fa261c4ad85f1e30e7 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sat, 4 Oct 2025 19:19:15 +0200 Subject: [PATCH 55/56] refactor(deployment): standardize environment variable handling in ApplicationDeploymentJob - Replaced the use of a dynamic env_filename with a consistent .env file reference across deployment methods. - Simplified the generation and saving of build-time and runtime environment variables, ensuring they are always written to the .env file. - Enhanced clarity in the deployment process by removing redundant logic and ensuring environment variables are handled uniformly. --- app/Jobs/ApplicationDeploymentJob.php | 434 ++++++++++++++++++-------- 1 file changed, 303 insertions(+), 131 deletions(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 93f730335..7bbcd67c9 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -116,16 +116,12 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue private $env_args; - private $environment_variables; - private $env_nixpacks_args; private $docker_compose; private $docker_compose_base64; - private ?string $env_filename = null; - private ?string $nixpacks_plan = null; private Collection $nixpacks_plan_json; @@ -356,7 +352,7 @@ public function handle(): void } $this->application_deployment_queue->addLogEntry("Gracefully shutting down build container: {$this->deployment_uuid}"); - $this->graceful_shutdown_container($this->deployment_uuid); + // $this->graceful_shutdown_container($this->deployment_uuid); ServiceStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); } @@ -576,7 +572,6 @@ private function deploy_docker_compose_buildpack() if ($this->application->settings->is_raw_compose_deployment_enabled) { $this->application->oldRawParser(); $yaml = $composeFile = $this->application->docker_compose_raw; - $this->generate_runtime_environment_variables(); // For raw compose, we cannot automatically add secrets configuration // User must define it manually in their docker-compose file @@ -585,16 +580,14 @@ private function deploy_docker_compose_buildpack() } } else { $composeFile = $this->application->parse(pull_request_id: $this->pull_request_id, preview_id: data_get($this->preview, 'id')); - $this->generate_runtime_environment_variables(); - if (filled($this->env_filename)) { - $services = collect(data_get($composeFile, 'services', [])); - $services = $services->map(function ($service, $name) { - $service['env_file'] = [$this->env_filename]; + // Always add .env file to services + $services = collect(data_get($composeFile, 'services', [])); + $services = $services->map(function ($service, $name) { + $service['env_file'] = ['.env']; - return $service; - }); - $composeFile['services'] = $services->toArray(); - } + return $service; + }); + $composeFile['services'] = $services->toArray(); if (empty($composeFile)) { $this->application_deployment_queue->addLogEntry('Failed to parse docker-compose file.'); $this->fail('Failed to parse docker-compose file.'); @@ -620,6 +613,9 @@ private function deploy_docker_compose_buildpack() // Build new container to limit downtime. $this->application_deployment_queue->addLogEntry('Pulling & building required images.'); + // Save build-time .env file BEFORE the build + $this->save_buildtime_environment_variables(); + if ($this->docker_compose_custom_build_command) { // Prepend DOCKER_BUILDKIT=1 if BuildKit is supported $build_command = $this->docker_compose_custom_build_command; @@ -635,9 +631,8 @@ private function deploy_docker_compose_buildpack() if ($this->dockerBuildkitSupported) { $command = "DOCKER_BUILDKIT=1 {$command}"; } - if (filled($this->env_filename)) { - $command .= " --env-file {$this->workdir}/{$this->env_filename}"; - } + // Always use .env file + $command .= " --env-file {$this->workdir}/.env"; if ($this->force_rebuild) { $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} build --pull --no-cache"; } else { @@ -657,6 +652,10 @@ private function deploy_docker_compose_buildpack() ); } + // Save runtime environment variables AFTER the build + // This overwrites the build-time .env with ALL variables (build-time + runtime) + $this->save_runtime_environment_variables(); + $this->stop_running_container(force: true); $this->application_deployment_queue->addLogEntry('Starting new application.'); $networkId = $this->application->uuid; @@ -690,9 +689,8 @@ private function deploy_docker_compose_buildpack() $this->docker_compose_location = '/docker-compose.yaml'; $command = "{$this->coolify_variables} docker compose"; - if (filled($this->env_filename)) { - $command .= " --env-file {$server_workdir}/{$this->env_filename}"; - } + // Always use .env file + $command .= " --env-file {$server_workdir}/.env"; $command .= " --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"; $this->execute_remote_command( ['command' => $command, 'hidden' => true], @@ -707,9 +705,8 @@ private function deploy_docker_compose_buildpack() } else { $command = "{$this->coolify_variables} docker compose"; if ($this->preserveRepository) { - if (filled($this->env_filename)) { - $command .= " --env-file {$server_workdir}/{$this->env_filename}"; - } + // Always use .env file + $command .= " --env-file {$server_workdir}/.env"; $command .= " --project-name {$this->application->uuid} --project-directory {$server_workdir} -f {$server_workdir}{$this->docker_compose_location} up -d"; $this->write_deployment_configurations(); @@ -717,9 +714,8 @@ private function deploy_docker_compose_buildpack() ['command' => $command, 'hidden' => true], ); } else { - if (filled($this->env_filename)) { - $command .= " --env-file {$this->workdir}/{$this->env_filename}"; - } + // Always use .env file + $command .= " --env-file {$this->workdir}/.env"; $command .= " --project-name {$this->application->uuid} --project-directory {$this->workdir} -f {$this->workdir}{$this->docker_compose_location} up -d"; $this->execute_remote_command( [executeInDocker($this->deployment_uuid, $command), 'hidden' => true], @@ -753,9 +749,18 @@ private function deploy_dockerfile_buildpack() } $this->cleanup_git(); $this->generate_compose_file(); + + // Save build-time .env file BEFORE the build + $this->save_buildtime_environment_variables(); + $this->generate_build_env_variables(); $this->add_build_env_variables_to_dockerfile(); $this->build_image(); + + // Save runtime environment variables AFTER the build + // This overwrites the build-time .env with ALL variables (build-time + runtime) + $this->save_runtime_environment_variables(); + $this->push_to_docker_registry(); $this->rolling_update(); } @@ -779,11 +784,15 @@ private function deploy_nixpacks_buildpack() $this->cleanup_git(); $this->generate_nixpacks_confs(); $this->generate_compose_file(); + + // Save build-time .env file BEFORE the build for Nixpacks + $this->save_buildtime_environment_variables(); + $this->generate_build_env_variables(); $this->build_image(); // For Nixpacks, save runtime environment variables AFTER the build - // to prevent them from being accessible during the build process + // This overwrites the build-time .env with ALL variables (build-time + runtime) $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); @@ -807,7 +816,16 @@ private function deploy_static_buildpack() $this->clone_repository(); $this->cleanup_git(); $this->generate_compose_file(); + + // Save build-time .env file BEFORE the build + $this->save_buildtime_environment_variables(); + $this->build_static_image(); + + // Save runtime environment variables AFTER the build + // This overwrites the build-time .env with ALL variables (build-time + runtime) + $this->save_runtime_environment_variables(); + $this->push_to_docker_registry(); $this->rolling_update(); } @@ -1060,8 +1078,6 @@ private function generate_runtime_environment_variables() $envs->push($key.'='.$item); }); if ($this->pull_request_id === 0) { - $this->env_filename = '.env'; - // Generate SERVICE_ variables first for dockercompose if ($this->build_pack === 'dockercompose') { $domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]); @@ -1120,8 +1136,6 @@ private function generate_runtime_environment_variables() $envs->push('HOST=0.0.0.0'); } } else { - $this->env_filename = '.env'; - // Generate SERVICE_ variables first for dockercompose preview if ($this->build_pack === 'dockercompose') { $domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]); @@ -1176,99 +1190,250 @@ private function generate_runtime_environment_variables() $envs->push('HOST=0.0.0.0'); } } - if ($envs->isEmpty()) { - if ($this->env_filename) { - if ($this->use_build_server) { - $this->server = $this->original_server; - $this->execute_remote_command( - [ - 'command' => "rm -f $this->configuration_dir/{$this->env_filename}", - 'hidden' => true, - 'ignore_errors' => true, - ] - ); - $this->server = $this->build_server; - $this->execute_remote_command( - [ - 'command' => "rm -f $this->configuration_dir/{$this->env_filename}", - 'hidden' => true, - 'ignore_errors' => true, - ] - ); - } else { - $this->execute_remote_command( - [ - 'command' => "rm -f $this->configuration_dir/{$this->env_filename}", - 'hidden' => true, - 'ignore_errors' => true, - ] - ); - } - } - $this->env_filename = null; - } else { - // For Nixpacks builds, we save the .env file AFTER the build to prevent - // runtime-only variables from being accessible during the build process - if ($this->application->build_pack !== 'nixpacks' || $this->skip_build) { - $envs_base64 = base64_encode($envs->implode("\n")); - $this->execute_remote_command( - [ - executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/{$this->env_filename} > /dev/null"), - ], - ); - if ($this->use_build_server) { - $this->server = $this->original_server; - $this->execute_remote_command( - [ - "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null", - ] - ); - $this->server = $this->build_server; - } else { - $this->execute_remote_command( - [ - "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null", - ] - ); - } - } - } - $this->environment_variables = $envs; + // Return the generated environment variables instead of storing them globally + return $envs; } private function save_runtime_environment_variables() { - // This method saves the .env file with runtime variables - // It should be called AFTER the build for Nixpacks to prevent runtime-only variables - // from being accessible during the build process + // This method saves the .env file with ALL runtime variables + // For builds, it should be called AFTER the build to include runtime-only variables - if ($this->environment_variables && $this->environment_variables->isNotEmpty() && $this->env_filename) { - $envs_base64 = base64_encode($this->environment_variables->implode("\n")); + // Generate runtime environment variables locally + $environment_variables = $this->generate_runtime_environment_variables(); - // Write .env file to workdir (for container runtime) + // Handle empty environment variables + if ($environment_variables->isEmpty()) { + // For Docker Compose, we need to create an empty .env file + // because we always reference it in the compose file + if ($this->build_pack === 'dockercompose') { + $this->application_deployment_queue->addLogEntry('Creating empty .env file (no environment variables defined).'); + + // Create empty .env file + $this->execute_remote_command( + [ + executeInDocker($this->deployment_uuid, "touch $this->workdir/.env"), + ] + ); + + // Also create in configuration directory + if ($this->use_build_server) { + $this->server = $this->original_server; + $this->execute_remote_command( + [ + "touch $this->configuration_dir/.env", + ] + ); + $this->server = $this->build_server; + } else { + $this->execute_remote_command( + [ + "touch $this->configuration_dir/.env", + ] + ); + } + } else { + // For non-Docker Compose deployments, clean up any existing .env files + if ($this->use_build_server) { + $this->server = $this->original_server; + $this->execute_remote_command( + [ + 'command' => "rm -f $this->configuration_dir/.env", + 'hidden' => true, + 'ignore_errors' => true, + ] + ); + $this->server = $this->build_server; + $this->execute_remote_command( + [ + 'command' => "rm -f $this->configuration_dir/.env", + 'hidden' => true, + 'ignore_errors' => true, + ] + ); + } else { + $this->execute_remote_command( + [ + 'command' => "rm -f $this->configuration_dir/.env", + 'hidden' => true, + 'ignore_errors' => true, + ] + ); + } + } + + return; + } + + // Write the environment variables to file + $envs_base64 = base64_encode($environment_variables->implode("\n")); + + // Write .env file to workdir (for container runtime) + $this->application_deployment_queue->addLogEntry('Creating .env file with runtime variables for build phase.', hidden: true); + $this->execute_remote_command( + [ + executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/.env > /dev/null"), + ], + [ + executeInDocker($this->deployment_uuid, "cat $this->workdir/.env"), + 'hidden' => true, + + ] + ); + + // Write .env file to configuration directory + if ($this->use_build_server) { + $this->server = $this->original_server; $this->execute_remote_command( [ - executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/{$this->env_filename} > /dev/null"), + "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/.env > /dev/null", + ] + ); + $this->server = $this->build_server; + } else { + $this->execute_remote_command( + [ + "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/.env > /dev/null", + ] + ); + } + } + + private function generate_buildtime_environment_variables() + { + $envs = collect([]); + $coolify_envs = $this->generate_coolify_env_variables(); + + // Add COOLIFY variables + $coolify_envs->each(function ($item, $key) use ($envs) { + $envs->push($key.'='.$item); + }); + + // Add SERVICE_NAME variables for Docker Compose builds + if ($this->build_pack === 'dockercompose') { + if ($this->pull_request_id === 0) { + // Generate SERVICE_NAME for dockercompose services from processed compose + if ($this->application->settings->is_raw_compose_deployment_enabled) { + $dockerCompose = Yaml::parse($this->application->docker_compose_raw); + } else { + $dockerCompose = Yaml::parse($this->application->docker_compose); + } + $services = data_get($dockerCompose, 'services', []); + foreach ($services as $serviceName => $_) { + $envs->push('SERVICE_NAME_'.str($serviceName)->upper().'='.$serviceName); + } + + // Generate SERVICE_FQDN & SERVICE_URL for non-PR deployments + $domains = collect(json_decode($this->application->docker_compose_domains)) ?? collect([]); + foreach ($domains as $forServiceName => $domain) { + $parsedDomain = data_get($domain, 'domain'); + if (filled($parsedDomain)) { + $parsedDomain = str($parsedDomain)->explode(',')->first(); + $coolifyUrl = Url::fromString($parsedDomain); + $coolifyScheme = $coolifyUrl->getScheme(); + $coolifyFqdn = $coolifyUrl->getHost(); + $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); + $envs->push('SERVICE_URL_'.str($forServiceName)->upper().'='.$coolifyUrl->__toString()); + $envs->push('SERVICE_FQDN_'.str($forServiceName)->upper().'='.$coolifyFqdn); + } + } + } else { + // Generate SERVICE_NAME for preview deployments + $rawDockerCompose = Yaml::parse($this->application->docker_compose_raw); + $rawServices = data_get($rawDockerCompose, 'services', []); + foreach ($rawServices as $rawServiceName => $_) { + $envs->push('SERVICE_NAME_'.str($rawServiceName)->upper().'='.addPreviewDeploymentSuffix($rawServiceName, $this->pull_request_id)); + } + + // Generate SERVICE_FQDN & SERVICE_URL for preview deployments with PR-specific domains + $domains = collect(json_decode(data_get($this->preview, 'docker_compose_domains'))) ?? collect([]); + foreach ($domains as $forServiceName => $domain) { + $parsedDomain = data_get($domain, 'domain'); + if (filled($parsedDomain)) { + $parsedDomain = str($parsedDomain)->explode(',')->first(); + $coolifyUrl = Url::fromString($parsedDomain); + $coolifyScheme = $coolifyUrl->getScheme(); + $coolifyFqdn = $coolifyUrl->getHost(); + $coolifyUrl = $coolifyUrl->withScheme($coolifyScheme)->withHost($coolifyFqdn)->withPort(null); + $envs->push('SERVICE_URL_'.str($forServiceName)->upper().'='.$coolifyUrl->__toString()); + $envs->push('SERVICE_FQDN_'.str($forServiceName)->upper().'='.$coolifyFqdn); + } + } + } + } + + // Add build-time user variables only + if ($this->pull_request_id === 0) { + $sorted_environment_variables = $this->application->environment_variables() + ->where('key', 'not like', 'NIXPACKS_%') + ->where('is_buildtime', true) // ONLY build-time variables + ->orderBy($this->application->settings->is_env_sorting_enabled ? 'key' : 'id') + ->get(); + + // For Docker Compose, filter out SERVICE_FQDN and SERVICE_URL as we generate these + if ($this->build_pack === 'dockercompose') { + $sorted_environment_variables = $sorted_environment_variables->filter(function ($env) { + return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_'); + }); + } + + foreach ($sorted_environment_variables as $env) { + $envs->push($env->key.'='.$env->real_value); + } + } else { + $sorted_environment_variables = $this->application->environment_variables_preview() + ->where('key', 'not like', 'NIXPACKS_%') + ->where('is_buildtime', true) // ONLY build-time variables + ->orderBy($this->application->settings->is_env_sorting_enabled ? 'key' : 'id') + ->get(); + + // For Docker Compose, filter out SERVICE_FQDN and SERVICE_URL as we generate these with PR-specific values + if ($this->build_pack === 'dockercompose') { + $sorted_environment_variables = $sorted_environment_variables->filter(function ($env) { + return ! str($env->key)->startsWith('SERVICE_FQDN_') && ! str($env->key)->startsWith('SERVICE_URL_'); + }); + } + + foreach ($sorted_environment_variables as $env) { + $envs->push($env->key.'='.$env->real_value); + } + } + + // Return the generated environment variables + return $envs; + } + + private function save_buildtime_environment_variables() + { + // Generate build-time environment variables locally + $environment_variables = $this->generate_buildtime_environment_variables(); + + // Save .env file for build phase + if ($environment_variables->isNotEmpty()) { + $envs_base64 = base64_encode($environment_variables->implode("\n")); + + $this->application_deployment_queue->addLogEntry('Creating .env file with build-time variables for build phase.', hidden: true); + + $this->execute_remote_command( + [ + executeInDocker($this->deployment_uuid, "echo '$envs_base64' | base64 -d | tee $this->workdir/.env > /dev/null"), + ], + [ + executeInDocker($this->deployment_uuid, "cat $this->workdir/.env"), + 'hidden' => true, ], ); + } elseif ($this->build_pack === 'dockercompose') { + // For Docker Compose, create an empty .env file even if there are no build-time variables + // This ensures the file exists when referenced in docker-compose commands + $this->application_deployment_queue->addLogEntry('Creating empty .env file for build phase (no build-time variables defined).', hidden: true); - // Write .env file to configuration directory - if ($this->use_build_server) { - $this->server = $this->original_server; - $this->execute_remote_command( - [ - "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null", - ] - ); - $this->server = $this->build_server; - } else { - $this->execute_remote_command( - [ - "echo '$envs_base64' | base64 -d | tee $this->configuration_dir/{$this->env_filename} > /dev/null", - ] - ); - } + $this->execute_remote_command( + [ + executeInDocker($this->deployment_uuid, "touch $this->workdir/.env"), + ] + ); } } @@ -1483,15 +1648,18 @@ private function deploy_pull_request() $this->generate_nixpacks_confs(); } $this->generate_compose_file(); + + // Save build-time .env file BEFORE the build + $this->save_buildtime_environment_variables(); + $this->generate_build_env_variables(); if ($this->application->build_pack === 'dockerfile') { $this->add_build_env_variables_to_dockerfile(); } $this->build_image(); - // For Nixpacks, save runtime environment variables AFTER the build - if ($this->application->build_pack === 'nixpacks') { - $this->save_runtime_environment_variables(); - } + + // This overwrites the build-time .env with ALL variables (build-time + runtime) + $this->save_runtime_environment_variables(); $this->push_to_docker_registry(); $this->rolling_update(); } @@ -2005,7 +2173,6 @@ private function generate_compose_file() $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->application->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); - $this->generate_runtime_environment_variables(); if (data_get($this->application, 'custom_labels')) { $this->application->parseContainerLabels(); $labels = collect(preg_split("/\r\n|\n|\r/", base64_decode($this->application->custom_labels))); @@ -2074,9 +2241,8 @@ private function generate_compose_file() ], ], ]; - if (filled($this->env_filename)) { - $docker_compose['services'][$this->container_name]['env_file'] = [$this->env_filename]; - } + // Always use .env file + $docker_compose['services'][$this->container_name]['env_file'] = ['.env']; $docker_compose['services'][$this->container_name]['healthcheck'] = [ 'test' => [ 'CMD-SHELL', @@ -2368,13 +2534,12 @@ private function build_image() // Coolify variables are already included in the secrets from generate_build_env_variables // build_secrets is already a string at this point } else { - // Traditional build args approach - $this->environment_variables->filter(function ($key, $value) { - return str($key)->startsWith('COOLIFY_'); - })->each(function ($key, $value) { + // Traditional build args approach - generate COOLIFY_ variables locally + // Generate COOLIFY_ variables locally for build args + $coolify_envs = $this->generate_coolify_env_variables(); + $coolify_envs->each(function ($value, $key) { $this->build_args->push("--build-arg '{$key}'"); }); - $this->build_args = $this->build_args instanceof \Illuminate\Support\Collection ? $this->build_args->implode(' ') : (string) $this->build_args; @@ -2904,6 +3069,7 @@ private function add_build_env_variables_to_dockerfile() executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), 'hidden' => true, 'save' => 'dockerfile', + 'ignore_errors' => true, ]); $dockerfile = collect(str($this->saved_outputs->get('dockerfile'))->trim()->explode("\n")); if ($this->pull_request_id === 0) { @@ -2962,10 +3128,17 @@ private function add_build_env_variables_to_dockerfile() } $dockerfile_base64 = base64_encode($dockerfile->implode("\n")); - $this->execute_remote_command([ - executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"), - 'hidden' => true, - ]); + $this->application_deployment_queue->addLogEntry('Final Dockerfile:', type: 'info'); + $this->execute_remote_command( + [ + executeInDocker($this->deployment_uuid, "echo '{$dockerfile_base64}' | base64 -d | tee {$this->workdir}{$this->dockerfile_location} > /dev/null"), + 'hidden' => true, + ], + [ + executeInDocker($this->deployment_uuid, "cat {$this->workdir}{$this->dockerfile_location}"), + 'hidden' => true, + 'ignore_errors' => true, + ]); } } @@ -3123,7 +3296,6 @@ private function modify_dockerfiles_for_compose($composeFile) $argsToAdd->push("ARG {$key}"); } - ray($argsToAdd); if ($argsToAdd->isEmpty()) { $this->application_deployment_queue->addLogEntry("Service {$serviceName}: No build-time variables to add."); From 239ecd4056fbff6b5499179d263cf60da4ada000 Mon Sep 17 00:00:00 2001 From: Andras Bacsai <5845193+andrasbacsai@users.noreply.github.com> Date: Sun, 5 Oct 2025 11:39:22 +0200 Subject: [PATCH 56/56] fix dev only thingy --- app/Jobs/ApplicationDeploymentJob.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Jobs/ApplicationDeploymentJob.php b/app/Jobs/ApplicationDeploymentJob.php index 7bbcd67c9..2a3f20f37 100644 --- a/app/Jobs/ApplicationDeploymentJob.php +++ b/app/Jobs/ApplicationDeploymentJob.php @@ -352,7 +352,7 @@ public function handle(): void } $this->application_deployment_queue->addLogEntry("Gracefully shutting down build container: {$this->deployment_uuid}"); - // $this->graceful_shutdown_container($this->deployment_uuid); + $this->graceful_shutdown_container($this->deployment_uuid); ServiceStatusChanged::dispatch(data_get($this->application, 'environment.project.team.id')); }