Merge branch 'next' into feat-db-ssl

This commit is contained in:
🏔️ Peak
2025-02-07 23:01:46 +01:00
committed by GitHub
42 changed files with 408 additions and 95 deletions

View File

@@ -12,6 +12,7 @@ on:
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md
env:
GITHUB_REGISTRY: ghcr.io

View File

@@ -12,6 +12,7 @@ on:
- docker/coolify-realtime/Dockerfile
- docker/testing-host/Dockerfile
- templates/**
- CHANGELOG.md
env:
GITHUB_REGISTRY: ghcr.io

View File

@@ -0,0 +1,36 @@
name: Generate Changelog
on:
push:
branches: [ main ]
workflow_dispatch:
permissions:
contents: write
jobs:
changelog:
name: Generate changelog
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Generate changelog
uses: orhun/git-cliff-action@v4
with:
config: cliff.toml
args: --verbose
env:
OUTPUT: CHANGELOG.md
GITHUB_REPO: ${{ github.repository }}
- name: Commit
run: |
git config user.name 'github-actions[bot]'
git config user.email 'github-actions[bot]@users.noreply.github.com'
git add CHANGELOG.md
git commit -m "docs: update changelog"
git push https://${{ secrets.GITHUB_TOKEN }}@github.com/${GITHUB_REPOSITORY}.git main

1
.gitignore vendored
View File

@@ -36,3 +36,4 @@ scripts/load-test/*
.env.dusk.local
docker/coolify-realtime/node_modules
.DS_Store
Changelog.md

View File

@@ -53,6 +53,7 @@ Special thanks to our biggest sponsors!
* [SupaGuide](https://supa.guide/?ref=coolify.io) - A comprehensive resource hub offering guides and tutorials for web development using Supabase.
* [GoldenVM](https://billing.goldenvm.com/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [Tigris](https://tigrisdata.com/?ref=coolify.io) - A fully managed serverless object storage service compatible with Amazon S3 API. Offers high performance, scalability, and built-in search capabilities for efficient data management.
* [Convex](https://convex.link/coolify.io) - Convex is the open-source reactive database for web app developers.
* [Cloudify.ro](https://cloudify.ro/?ref=coolify.io) - A cloud hosting provider offering scalable infrastructure solutions for businesses of all sizes.
* [Syntaxfm](https://syntax.fm/?ref=coolify.io) - Podcast for web developers.
* [PFGlabs](https://pfglabs.com/?ref=coolify.io) - Build real project with Golang.

View File

@@ -12,19 +12,24 @@ class StartService
public string $jobQueue = 'high';
public function handle(Service $service)
public function handle(Service $service, bool $pullLatestImages = false, bool $stopBeforeStart = false)
{
$service->parse();
if ($stopBeforeStart) {
StopService::run(service: $service, dockerCleanup: false);
}
$service->saveComposeConfigs();
$commands[] = 'cd '.$service->workdir();
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
if ($pullLatestImages) {
$commands[] = "echo 'Pulling images.'";
$commands[] = 'docker compose pull';
}
if ($service->networks()->count() > 0) {
$commands[] = "echo 'Creating Docker network.'";
$commands[] = "docker network inspect $service->uuid >/dev/null 2>&1 || docker network create --attachable $service->uuid";
}
$commands[] = 'echo Starting service.';
$commands[] = "echo 'Pulling images.'";
$commands[] = 'docker compose pull';
$commands[] = "echo 'Starting containers.'";
$commands[] = 'docker compose up -d --remove-orphans --force-recreate --build';
$commands[] = "docker network connect $service->uuid coolify-proxy >/dev/null 2>&1 || true";
if (data_get($service, 'connect_to_docker_network')) {

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Actions\Shared;
use App\Models\Service;
use Lorisleiva\Actions\Concerns\AsAction;
class PullImage
{
use AsAction;
public function handle(Service $resource)
{
$resource->saveComposeConfigs();
$commands[] = 'cd '.$resource->workdir();
$commands[] = "echo 'Saved configuration files to {$resource->workdir()}.'";
$commands[] = 'docker compose pull';
$server = data_get($resource, 'server');
if (! $server) {
return;
}
instant_remote_process($commands, $resource->server);
}
}

View File

@@ -1388,6 +1388,108 @@ class ApplicationsController extends Controller
return response()->json($this->removeSensitiveData($application));
}
#[OA\Get(
summary: 'Get application logs.',
description: 'Get application logs by UUID.',
path: '/applications/{uuid}/logs',
operationId: 'get-application-logs-by-uuid',
security: [
['bearerAuth' => []],
],
tags: ['Applications'],
parameters: [
new OA\Parameter(
name: 'uuid',
in: 'path',
description: 'UUID of the application.',
required: true,
schema: new OA\Schema(
type: 'string',
format: 'uuid',
)
),
new OA\Parameter(
name: 'lines',
in: 'query',
description: 'Number of lines to show from the end of the logs.',
required: false,
schema: new OA\Schema(
type: 'integer',
format: 'int32',
default: 100,
)
),
],
responses: [
new OA\Response(
response: 200,
description: 'Get application logs by UUID.',
content: [
new OA\MediaType(
mediaType: 'application/json',
schema: new OA\Schema(
type: 'object',
properties: [
'logs' => ['type' => 'string'],
]
)
),
]
),
new OA\Response(
response: 401,
ref: '#/components/responses/401',
),
new OA\Response(
response: 400,
ref: '#/components/responses/400',
),
new OA\Response(
response: 404,
ref: '#/components/responses/404',
),
]
)]
public function logs_by_uuid(Request $request)
{
$teamId = getTeamIdFromToken();
if (is_null($teamId)) {
return invalidTokenResponse();
}
$uuid = $request->route('uuid');
if (! $uuid) {
return response()->json(['message' => 'UUID is required.'], 400);
}
$application = Application::ownedByCurrentTeamAPI($teamId)->where('uuid', $request->uuid)->first();
if (! $application) {
return response()->json(['message' => 'Application not found.'], 404);
}
$containers = getCurrentApplicationContainerStatus($application->destination->server, $application->id);
if ($containers->count() == 0) {
return response()->json([
'message' => 'Application is not running.',
], 400);
}
$container = $containers->first();
$status = getContainerStatus($application->destination->server, $container['Names']);
if ($status !== 'running') {
return response()->json([
'message' => 'Application is not running.',
], 400);
}
$lines = $request->query->get('lines', 100) ?: 100;
$logs = getContainerLogs($application->destination->server, $container['ID'], $lines);
return response()->json([
'logs' => $logs,
]);
}
#[OA\Delete(
summary: 'Delete',
description: 'Delete application by UUID.',

View File

@@ -37,7 +37,7 @@ class Bitbucket extends Controller
$headers = $request->headers->all();
$x_bitbucket_token = data_get($headers, 'x-hub-signature.0', '');
$x_bitbucket_event = data_get($headers, 'x-event-key.0', '');
$handled_events = collect(['repo:push', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
$handled_events = collect(['repo:push', 'pullrequest:updated', 'pullrequest:created', 'pullrequest:rejected', 'pullrequest:fulfilled']);
if (! $handled_events->contains($x_bitbucket_event)) {
return response([
'status' => 'failed',
@@ -48,6 +48,7 @@ class Bitbucket extends Controller
$branch = data_get($payload, 'push.changes.0.new.name');
$full_name = data_get($payload, 'repository.full_name');
$commit = data_get($payload, 'push.changes.0.new.target.hash');
if (!$branch) {
return response([
'status' => 'failed',
@@ -55,7 +56,7 @@ class Bitbucket extends Controller
]);
}
}
if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
if ($x_bitbucket_event === 'pullrequest:updated' || $x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:rejected' || $x_bitbucket_event === 'pullrequest:fulfilled') {
$branch = data_get($payload, 'pullrequest.destination.branch.name');
$base_branch = data_get($payload, 'pullrequest.source.branch.name');
$full_name = data_get($payload, 'repository.full_name');
@@ -119,7 +120,7 @@ class Bitbucket extends Controller
]);
}
}
if ($x_bitbucket_event === 'pullrequest:created') {
if ($x_bitbucket_event === 'pullrequest:created' || $x_bitbucket_event === 'pullrequest:updated') {
if ($application->isPRDeployable()) {
$deployment_uuid = new Cuid2;
$found = ApplicationPreview::where('application_id', $application->id)->where('pull_request_id', $pull_request_id)->first();

View File

@@ -253,6 +253,9 @@ class ApplicationDeploymentJob implements ShouldBeEncrypted, ShouldQueue
return;
}
try {
// Make sure the private key is stored in the filesystem
$this->server->privateKey->storeInFileSystem();
// Generate custom host<->ip mapping
$allContainers = instant_remote_process(["docker network inspect {$this->destination->network} -f '{{json .Containers}}' "], $this->server);

View File

@@ -81,7 +81,7 @@ class Select extends Component
public function loadServices()
{
$services = get_service_templates(true);
$services = get_service_templates();
$services = collect($services)->map(function ($service, $key) {
$default_logo = 'images/default.webp';
$logo = data_get($service, 'logo', $default_logo);

View File

@@ -4,7 +4,6 @@ namespace App\Livewire\Project\Service;
use App\Actions\Service\StartService;
use App\Actions\Service\StopService;
use App\Actions\Shared\PullImage;
use App\Enums\ProcessStatus;
use App\Events\ServiceStatusChanged;
use App\Models\Service;
@@ -85,8 +84,7 @@ class Navbar extends Component
public function start()
{
$this->service->parse();
$activity = StartService::run($this->service);
$activity = StartService::run($this->service, pullLatestImages: true);
$this->dispatch('activityMonitor', $activity->id);
}
@@ -98,8 +96,7 @@ class Navbar extends Component
$activity->properties->status = ProcessStatus::ERROR->value;
$activity->save();
}
$this->service->parse();
$activity = StartService::run($this->service);
$activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true);
$this->dispatch('activityMonitor', $activity->id);
} catch (\Exception $e) {
$this->dispatch('error', $e->getMessage());
@@ -129,10 +126,7 @@ class Navbar extends Component
return;
}
StopService::run(service: $this->service, dockerCleanup: false);
$this->service->parse();
$this->dispatch('imagePulled');
$activity = StartService::run($this->service);
$activity = StartService::run($this->service, stopBeforeStart: true);
$this->dispatch('activityMonitor', $activity->id);
}
@@ -144,11 +138,7 @@ class Navbar extends Component
return;
}
PullImage::run($this->service);
StopService::run(service: $this->service, dockerCleanup: false);
$this->service->parse();
$this->dispatch('imagePulled');
$activity = StartService::run($this->service);
$activity = StartService::run($this->service, pullLatestImages: true, stopBeforeStart: true);
$this->dispatch('activityMonitor', $activity->id);
}

View File

@@ -44,7 +44,7 @@ class DeploymentFailed extends CustomEmailNotification
if (str($this->fqdn)->explode(',')->count() > 1) {
$this->fqdn = str($this->fqdn)->explode(',')->first();
}
$this->deployment_url = base_url()."/project/{$this->project_uuid}/environments/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
$this->deployment_url = base_url()."/project/{$this->project_uuid}/environment/{$this->environment_uuid}/application/{$this->application->uuid}/deployment/{$this->deployment_uuid}";
}
public function via(object $notifiable): array
@@ -175,9 +175,9 @@ class DeploymentFailed extends CustomEmailNotification
}
}
$description .= "\n\n**Project:** ".data_get($this->application, 'environment.project.name');
$description .= "\n**Environment:** {$this->environment_name}";
$description .= "\n**Deployment Logs:** {$this->deployment_url}";
$description .= "\n\n*Project:* ".data_get($this->application, 'environment.project.name');
$description .= "\n*Environment:* {$this->environment_name}";
$description .= "\n*<{$this->deployment_url}|Deployment Logs>*";
return new SlackMessage(
title: $title,

View File

@@ -195,9 +195,9 @@ class DeploymentSuccess extends CustomEmailNotification
}
}
$description .= "\n\n**Project:** ".data_get($this->application, 'environment.project.name');
$description .= "\n**Environment:** {$this->environment_name}";
$description .= "\n**Deployment Logs:** {$this->deployment_url}";
$description .= "\n\n*Project:* ".data_get($this->application, 'environment.project.name');
$description .= "\n*Environment:* {$this->environment_name}";
$description .= "\n*<{$this->deployment_url}|Deployment Logs>*";
return new SlackMessage(
title: $title,

View File

@@ -103,9 +103,9 @@ class StatusChanged extends CustomEmailNotification
$title = 'Application stopped';
$description = "{$this->resource_name} has been stopped";
$description .= "\n\n**Project:** ".data_get($this->resource, 'environment.project.name');
$description .= "\n**Environment:** {$this->environment_name}";
$description .= "\n**Application URL:** {$this->resource_url}";
$description .= "\n\n*Project:* ".data_get($this->resource, 'environment.project.name');
$description .= "\n*Environment:* {$this->environment_name}";
$description .= "\n*Application URL:* {$this->resource_url}";
return new SlackMessage(
title: $title,

View File

@@ -93,7 +93,7 @@ class ContainerRestarted extends CustomEmailNotification
$description = "A resource ({$this->name}) has been restarted automatically on {$this->server->name}";
if ($this->url) {
$description .= "\n**Resource URL:** {$this->url}";
$description .= "\n*Resource URL:* {$this->url}";
}
return new SlackMessage(

View File

@@ -93,7 +93,7 @@ class ContainerStopped extends CustomEmailNotification
$description = "A resource ({$this->name}) has been stopped unexpectedly on {$this->server->name}";
if ($this->url) {
$description .= "\n**Resource URL:** {$this->url}";
$description .= "\n*Resource URL:* {$this->url}";
}
return new SlackMessage(

View File

@@ -79,8 +79,8 @@ class BackupFailed extends CustomEmailNotification
$title = 'Database backup failed';
$description = "Database backup for {$this->name} (db:{$this->database_name}) has FAILED.";
$description .= "\n\n**Frequency:** {$this->frequency}";
$description .= "\n\n**Error Output:**\n{$this->output}";
$description .= "\n\n*Frequency:* {$this->frequency}";
$description .= "\n\n*Error Output:* {$this->output}";
return new SlackMessage(
title: $title,

View File

@@ -77,7 +77,7 @@ class BackupSuccess extends CustomEmailNotification
$title = 'Database backup successful';
$description = "Database backup for {$this->name} (db:{$this->database_name}) was successful.";
$description .= "\n\n**Frequency:** {$this->frequency}";
$description .= "\n\n*Frequency:* {$this->frequency}";
return new SlackMessage(
title: $title,

View File

@@ -101,11 +101,11 @@ class TaskFailed extends CustomEmailNotification
$description = "Scheduled task ({$this->task->name}) failed.";
if ($this->output) {
$description .= "\n\n**Error Output:**\n{$this->output}";
$description .= "\n\n*Error Output:* {$this->output}";
}
if ($this->url) {
$description .= "\n\n**Task URL:** {$this->url}";
$description .= "\n\n*Task URL:* {$this->url}";
}
return new SlackMessage(

View File

@@ -96,7 +96,7 @@ class TaskSuccess extends CustomEmailNotification
$description = "Scheduled task ({$this->task->name}) succeeded.";
if ($this->url) {
$description .= "\n\n**Task URL:** {$this->url}";
$description .= "\n\n*Task URL:* {$this->url}";
}
return new SlackMessage(

View File

@@ -852,6 +852,23 @@ function validateComposeFile(string $compose, int $server_id): string|Throwable
}
}
function getContainerLogs(Server $server, string $container_id, int $lines = 100): string
{
if ($server->isSwarm()) {
$output = instant_remote_process([
"docker service logs -n {$lines} {$container_id}",
], $server);
} else {
$output = instant_remote_process([
"docker logs -n {$lines} {$container_id}",
], $server);
}
$output .= removeAnsiColors($output);
return $output;
}
function escapeEnvVariables($value)
{
$search = ['\\', "\r", "\t", "\x0", '"', "'"];

View File

@@ -440,11 +440,7 @@ function sslip(Server $server)
function get_service_templates(bool $force = false): Collection
{
if (isDev()) {
$services = File::get(base_path('templates/service-templates.json'));
return collect(json_decode($services))->sortKeys();
}
if ($force) {
try {
$response = Http::retry(3, 1000)->get(config('constants.services.official'));

84
cliff.toml Normal file
View File

@@ -0,0 +1,84 @@
# git-cliff ~ default configuration file
# https://git-cliff.org/docs/configuration
#
# Lines starting with "#" are comments.
# Configuration options are organized into tables and keys.
# See documentation for more information on available options.
[changelog]
# template for the changelog header
header = """
# Changelog\n
All notable changes to this project will be documented in this file.\n
"""
# template for the changelog body
# https://keats.github.io/tera/docs/#introduction
body = """
{% if version %}\
## [{{ version | trim_start_matches(pat="v") }}] - {{ timestamp | date(format="%Y-%m-%d") }}
{% else %}\
## [unreleased]
{% endif %}\
{% for group, commits in commits | group_by(attribute="group") %}
### {{ group | striptags | trim | upper_first }}
{% for commit in commits %}
- {% if commit.scope %}*({{ commit.scope }})* {% endif %}\
{% if commit.breaking %}[**breaking**] {% endif %}\
{{ commit.message | upper_first }}\
{% endfor %}
{% endfor %}\n
"""
# template for the changelog footer
footer = """
<!-- generated by git-cliff -->
"""
# remove the leading and trailing s
trim = true
# postprocessors
postprocessors = [
# { pattern = '<REPO>', replace = "https://github.com/orhun/git-cliff" }, # replace repository URL
]
# render body even when there are no releases to process
# render_always = true
# output file path
# output = "test.md"
[git]
# parse the commits based on https://www.conventionalcommits.org
conventional_commits = true
# filter out the commits that are not conventional
filter_unconventional = true
# process each line of a commit as an individual commit
split_commits = false
# regex for preprocessing the commit messages
commit_preprocessors = [
# Replace issue numbers
#{ pattern = '\((\w+\s)?#([0-9]+)\)', replace = "([#${2}](<REPO>/issues/${2}))"},
# Check spelling of the commit with https://github.com/crate-ci/typos
# If the spelling is incorrect, it will be automatically fixed.
#{ pattern = '.*', replace_command = 'typos --write-changes -' },
]
# regex for parsing and grouping commits
commit_parsers = [
{ message = "^feat", group = "<!-- 0 -->🚀 Features" },
{ message = "^fix", group = "<!-- 1 -->🐛 Bug Fixes" },
{ message = "^doc", group = "<!-- 3 -->📚 Documentation" },
{ message = "^perf", group = "<!-- 4 -->⚡ Performance" },
{ message = "^refactor", group = "<!-- 2 -->🚜 Refactor" },
{ message = "^style", group = "<!-- 5 -->🎨 Styling" },
{ message = "^test", group = "<!-- 6 -->🧪 Testing" },
{ message = "^chore\\(release\\): prepare for", skip = true },
{ message = "^chore\\(deps.*\\)", skip = true },
{ message = "^chore\\(pr\\)", skip = true },
{ message = "^chore\\(pull\\)", skip = true },
{ message = "^chore|^ci", group = "<!-- 7 -->⚙️ Miscellaneous Tasks" },
{ body = ".*security", group = "<!-- 8 -->🛡️ Security" },
{ message = "^revert", group = "<!-- 9 -->◀️ Revert" },
{ message = ".*", group = "<!-- 10 -->💼 Other" },
]
# filter out the commits that are not matched by commit parsers
filter_commits = false
# sort the tags topologically
topo_order = false
# sort the commits inside sections by oldest/newest order
sort_commits = "oldest"

View File

@@ -2,7 +2,7 @@
return [
'coolify' => [
'version' => '4.0.0-beta.391',
'version' => '4.0.0-beta.392',
'helper_version' => '1.0.6',
'realtime_version' => '1.0.5',
'self_hosted' => env('SELF_HOSTED', true),

View File

@@ -14,7 +14,7 @@ services:
- /data/coolify/webhooks-during-maintenance:/var/www/html/storage/app/webhooks-during-maintenance
environment:
- APP_ENV=${APP_ENV:-production}
- PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-128M}
- PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-256M}
- PHP_FPM_PM_CONTROL=${PHP_FPM_PM_CONTROL:-dynamic}
- PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1}
- PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1}

View File

@@ -14,7 +14,7 @@ services:
- /data/coolify/webhooks-during-maintenance:/var/www/html/storage/app/webhooks-during-maintenance
environment:
- APP_ENV=${APP_ENV:-production}
- PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-128M}
- PHP_MEMORY_LIMIT=${PHP_MEMORY_LIMIT:-256M}
- PHP_FPM_PM_CONTROL=${PHP_FPM_PM_CONTROL:-dynamic}
- PHP_FPM_PM_START_SERVERS=${PHP_FPM_PM_START_SERVERS:-1}
- PHP_FPM_PM_MIN_SPARE_SERVERS=${PHP_FPM_PM_MIN_SPARE_SERVERS:-1}

45
public/svgs/bugsink.svg Normal file
View File

@@ -0,0 +1,45 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" width="64" height="64">
<path d="M0 0 C5.37575301 0.15272026 5.37575301 0.15272026 8.0625 1.49609375 C9.70233879 4.77577133 9.24095638 7.86748064 9.0625 11.49609375 C7.7425 11.49609375 6.4225 11.49609375 5.0625 11.49609375 C4.7325 9.51609375 4.4025 7.53609375 4.0625 5.49609375 C2.7425 5.16609375 1.4225 4.83609375 0.0625 4.49609375 C-0.2675 7.46609375 -0.5975 10.43609375 -0.9375 13.49609375 C0.0525 13.82609375 1.0425 14.15609375 2.0625 14.49609375 C2.3925 15.48609375 2.7225 16.47609375 3.0625 17.49609375 C4.00609375 17.43808594 4.9496875 17.38007813 5.921875 17.3203125 C20.14484656 16.82050928 30.90017372 21.43736377 42.0625 30.49609375 C43.25371752 34.06974632 42.8726346 36.16232372 42.3125 39.87109375 C42.15265625 40.99257813 41.9928125 42.1140625 41.828125 43.26953125 C39.91675079 51.32460829 34.66136142 54.24220217 28.0625 58.49609375 C27.00869141 59.26759766 27.00869141 59.26759766 25.93359375 60.0546875 C19.1488378 64.5993153 11.97955462 64.73411922 4.0625 63.49609375 C-4.14924937 60.94090874 -12.3142081 56.04309642 -17.9375 49.49609375 C-19.89011374 43.63825252 -19.96003647 37.53544979 -18.9375 31.49609375 C-16.38874006 28.24334164 -13.51595222 26.47909886 -9.9375 24.49609375 C-7.52628141 22.539754 -7.52628141 22.539754 -7.8125 18.87109375 C-7.85375 17.75734375 -7.895 16.64359375 -7.9375 15.49609375 C-7.2775 15.49609375 -6.6175 15.49609375 -5.9375 15.49609375 C-5.90011719 14.7484375 -5.86273438 14.00078125 -5.82421875 13.23046875 C-5.75847656 12.245625 -5.69273438 11.26078125 -5.625 10.24609375 C-5.56699219 9.2715625 -5.50898438 8.29703125 -5.44921875 7.29296875 C-4.78466028 3.66072552 -3.79827954 0.97254335 0 0 Z " fill="#64CADA" transform="translate(20.9375,0.50390625)"/>
<path d="M0 0 C14.02690092 7.81552059 14.02690092 7.81552059 15.9375 11.63671875 C10.82030642 18.65458424 4.43762699 22.41403241 -3.0625 26.63671875 C-3.98160156 27.17039062 -4.90070312 27.7040625 -5.84765625 28.25390625 C-10.80932119 30.96863482 -15.36626365 33.15635227 -21.0625 31.63671875 C-28.75065664 28.39722552 -36.22642123 24.42197389 -43.0625 19.63671875 C-43.0625 18.97671875 -43.0625 18.31671875 -43.0625 17.63671875 C-42.27875 17.43046875 -41.495 17.22421875 -40.6875 17.01171875 C-35.76976245 15.14637002 -31.50407897 12.4280668 -27.0625 9.63671875 C-27.0625 10.29671875 -27.0625 10.95671875 -27.0625 11.63671875 C-26.0725 10.97671875 -25.0825 10.31671875 -24.0625 9.63671875 C-22.01953125 9.44140625 -22.01953125 9.44140625 -19.875 9.51171875 C-17.9878125 9.57359375 -17.9878125 9.57359375 -16.0625 9.63671875 C-14.96591064 12.92648683 -15.26296862 14.34975642 -16.0625 17.63671875 C-18.0425 17.63671875 -20.0225 17.63671875 -22.0625 17.63671875 C-22.7225 16.31671875 -23.3825 14.99671875 -24.0625 13.63671875 C-25.0525 13.63671875 -26.0425 13.63671875 -27.0625 13.63671875 C-26.9903125 14.27480469 -26.918125 14.91289063 -26.84375 15.5703125 C-26.7509375 16.39660156 -26.658125 17.22289063 -26.5625 18.07421875 C-26.4696875 18.89792969 -26.376875 19.72164062 -26.28125 20.5703125 C-26.0625 22.63671875 -26.0625 22.63671875 -26.0625 23.63671875 C-25.505625 23.73984375 -24.94875 23.84296875 -24.375 23.94921875 C-22.0625 24.63671875 -22.0625 24.63671875 -19.875 26.44921875 C-17.20550326 27.90835028 -17.20550326 27.90835028 -14.84765625 27.08203125 C-10.67315622 25.33645425 -7.28137668 23.77862189 -5.0625 19.63671875 C-6.75844156 15.43676935 -8.03043168 12.32476429 -11.875 9.76171875 C-15.25298919 8.56948727 -18.59587518 7.5380412 -22.0625 6.63671875 C-22.3925 4.98671875 -22.7225 3.33671875 -23.0625 1.63671875 C-24.7125 1.96671875 -26.3625 2.29671875 -28.0625 2.63671875 C-27.7325 0.98671875 -27.4025 -0.66328125 -27.0625 -2.36328125 C-18.20705096 -5.3150976 -8.27631235 -3.92450137 0 0 Z " fill="#7BD4E2" transform="translate(48.0625,21.36328125)"/>
<path d="M0 0 C1.09051795 3.27155385 0.91420524 4.56403753 0.25 7.875 C0.01023437 9.13957031 0.01023437 9.13957031 -0.234375 10.4296875 C-2.47935196 17.96639587 -7.66851204 20.96585891 -14 25 C-14.79535156 25.51433594 -15.59070313 26.02867188 -16.41015625 26.55859375 C-21.2001956 29.45890917 -24.40083956 30.59565537 -30 30 C-30 26.37 -30 22.74 -30 19 C-28.45892578 18.27296875 -28.45892578 18.27296875 -26.88671875 17.53125 C-17.11814785 12.83775233 -7.57279343 7.96491218 0 0 Z " fill="#188093" transform="translate(63,34)"/>
<path d="M0 0 C0.33 0.66 0.66 1.32 1 2 C1.99 1.34 2.98 0.68 4 0 C6.04296875 -0.1953125 6.04296875 -0.1953125 8.1875 -0.125 C10.0746875 -0.063125 10.0746875 -0.063125 12 0 C13.09658936 3.28976808 12.79953138 4.71303767 12 8 C10.02 8 8.04 8 6 8 C5.34 6.68 4.68 5.36 4 4 C3.01 4 2.02 4 1 4 C1.0721875 4.63808594 1.144375 5.27617188 1.21875 5.93359375 C1.3115625 6.75988281 1.404375 7.58617187 1.5 8.4375 C1.5928125 9.26121094 1.685625 10.08492187 1.78125 10.93359375 C2 13 2 13 2 14 C2.8353125 14.1546875 2.8353125 14.1546875 3.6875 14.3125 C6 15 6 15 8.1875 16.8125 C10.85699674 18.27163153 10.85699674 18.27163153 13.21484375 17.4453125 C17.31150102 15.73228563 20.98143486 14.17170128 23 10 C23 9.01 23 8.02 23 7 C24.32 8.32 25.64 9.64 27 11 C28.98 10.34 30.96 9.68 33 9 C32.9296875 10.73828125 32.9296875 10.73828125 32 13 C29.71481575 14.57508224 27.55874838 15.89290131 25.125 17.1875 C24.16787109 17.72020508 24.16787109 17.72020508 23.19140625 18.26367188 C17.80546753 21.22650038 13.17740908 23.15299138 7 22 C-0.69653825 18.81924205 -8.17998348 14.77401157 -15 10 C-15 9.34 -15 8.68 -15 8 C-14.195625 7.79375 -13.39125 7.5875 -12.5625 7.375 C-7.889527 5.57139638 -4.07383996 2.87884691 0 0 Z " fill="#8AD5DC" transform="translate(20,31)"/>
<path d="M0 0 C3.80302094 0.54419268 6.59073493 1.61472759 9.34765625 4.3359375 C11.03045149 7.22855299 12.26035643 10.17533926 13.34765625 13.3359375 C7.273258 19.21777557 7.273258 19.21777557 3.41015625 19.7109375 C2.72953125 19.5871875 2.04890625 19.4634375 1.34765625 19.3359375 C1.01765625 20.3259375 0.68765625 21.3159375 0.34765625 22.3359375 C0.01765625 21.6759375 -0.31234375 21.0159375 -0.65234375 20.3359375 C-4.11054911 17.83834474 -6.38912004 16.97051832 -10.65234375 17.3359375 C-10.32234375 16.6759375 -9.99234375 16.0159375 -9.65234375 15.3359375 C-9.58283834 13.79569754 -9.56782018 12.25258762 -9.58984375 10.7109375 C-9.59886719 9.89367188 -9.60789062 9.07640625 -9.6171875 8.234375 C-9.62878906 7.60789062 -9.64039062 6.98140625 -9.65234375 6.3359375 C-8.00234375 5.6759375 -6.35234375 5.0159375 -4.65234375 4.3359375 C-4.98234375 5.3259375 -5.31234375 6.3159375 -5.65234375 7.3359375 C-5.32234375 8.3259375 -4.99234375 9.3159375 -4.65234375 10.3359375 C-2.67234375 10.0059375 -0.69234375 9.6759375 1.34765625 9.3359375 C1.16203125 8.7378125 0.97640625 8.1396875 0.78515625 7.5234375 C0.34765625 5.3359375 0.34765625 5.3359375 1.34765625 2.3359375 C0.08953125 2.5009375 -1.16859375 2.6659375 -2.46484375 2.8359375 C-4.9169096 3.15751991 -7.16885069 3.3359375 -9.65234375 3.3359375 C-6.67741706 -0.21326302 -4.44442462 -0.18789437 0 0 Z " fill="#6A111C" transform="translate(30.65234375,28.6640625)"/>
<path d="M0 0 C5.37575301 0.15272026 5.37575301 0.15272026 8.0625 1.49609375 C9.70233879 4.77577133 9.24095638 7.86748064 9.0625 11.49609375 C7.7425 11.49609375 6.4225 11.49609375 5.0625 11.49609375 C4.7325 9.51609375 4.4025 7.53609375 4.0625 5.49609375 C2.7425 5.16609375 1.4225 4.83609375 0.0625 4.49609375 C-0.2675 7.46609375 -0.5975 10.43609375 -0.9375 13.49609375 C0.0525 13.82609375 1.0425 14.15609375 2.0625 14.49609375 C2.0625 15.81609375 2.0625 17.13609375 2.0625 18.49609375 C1.4025 18.82609375 0.7425 19.15609375 0.0625 19.49609375 C-0.65909424 21.13972509 -1.33101421 22.80659761 -1.9375 24.49609375 C-4.10624252 23.99005383 -5.93717627 23.49625562 -7.9375 22.49609375 C-7.9375 20.18609375 -7.9375 17.87609375 -7.9375 15.49609375 C-7.2775 15.49609375 -6.6175 15.49609375 -5.9375 15.49609375 C-5.90011719 14.7484375 -5.86273438 14.00078125 -5.82421875 13.23046875 C-5.75847656 12.245625 -5.69273438 11.26078125 -5.625 10.24609375 C-5.56699219 9.2715625 -5.50898438 8.29703125 -5.44921875 7.29296875 C-4.78466028 3.66072552 -3.79827954 0.97254335 0 0 Z " fill="#253433" transform="translate(20.9375,0.50390625)"/>
<path d="M0 0 C5.91577376 2.74660925 10.90479475 5.93467666 16 10 C13.55226831 15.20142984 9.59788619 17.82188865 5 21 C5.0309375 19.6078125 5.0309375 19.6078125 5.0625 18.1875 C5.15769604 14.97713989 5.15769604 14.97713989 4 12 C2.35448038 11.28272222 0.68577711 10.61674772 -1 10 C-1.66 9.34 -2.32 8.68 -3 8 C-2.34 7.01 -1.68 6.02 -1 5 C-0.61500109 3.34450469 -0.27206865 1.6777567 0 0 Z " fill="#7ED8E4" transform="translate(48,22)"/>
<path d="M0 0 C0.33 0.66 0.66 1.32 1 2 C1.99 1.34 2.98 0.68 4 0 C6.04296875 -0.1953125 6.04296875 -0.1953125 8.1875 -0.125 C10.0746875 -0.063125 10.0746875 -0.063125 12 0 C13.09658936 3.28976808 12.79953138 4.71303767 12 8 C10.02 8 8.04 8 6 8 C5.34 6.68 4.68 5.36 4 4 C-0.02147098 4 -2.82309945 5.68383605 -6 8 C-7.4662686 10.08451836 -7.4662686 10.08451836 -8 12 C-7.319375 12.268125 -6.63875 12.53625 -5.9375 12.8125 C-2.60289191 14.16053306 0.69743237 15.57536298 4 17 C4 17.99 4 18.98 4 20 C-2.84895855 18.06824246 -9.5547668 14.61982455 -15 10 C-15 9.34 -15 8.68 -15 8 C-14.195625 7.79375 -13.39125 7.5875 -12.5625 7.375 C-7.889527 5.57139638 -4.07383996 2.87884691 0 0 Z " fill="#7DD4E2" transform="translate(20,31)"/>
<path d="M0 0 C0.66 1.98 1.32 3.96 2 6 C1.21625 6.37125 0.4325 6.7425 -0.375 7.125 C-4.28168807 9.05974076 -7.9407111 11.38343592 -11.6328125 13.6953125 C-13.81263989 14.89673551 -15.54551219 15.64000845 -18 16 C-19 15 -19 15 -19.515625 12.76953125 C-18.91189413 9.52676466 -18.41614865 9.21815092 -15.859375 7.32421875 C-14.50132889 6.42727049 -13.13084653 5.54893384 -11.75 4.6875 C-11.06808594 4.23310547 -10.38617188 3.77871094 -9.68359375 3.31054688 C-4.55597979 0 -4.55597979 0 0 0 Z " fill="#2499AE" transform="translate(25,23)"/>
<path d="M0 0 C0.66 0.33 1.32 0.66 2 1 C2 2.66666667 2 4.33333333 2 6 C4.64 5.34 7.28 4.68 10 4 C10.21192221 9.19209404 9.5912689 13.126739 8 18 C7.55269531 17.6390625 7.10539062 17.278125 6.64453125 16.90625 C2.76135613 13.86557578 2.76135613 13.86557578 -1.9375 12.6875 C-2.618125 12.790625 -3.29875 12.89375 -4 13 C-3.67 12.34 -3.34 11.68 -3 11 C-3.00861703 8.69063671 -3.13055027 6.39944225 -3.2578125 4.09375 C-3.17273438 3.4028125 -3.08765625 2.711875 -3 2 C-2.01 1.34 -1.02 0.68 0 0 Z " fill="#A62E3F" transform="translate(24,33)"/>
<path d="M0 0 C1.45880109 0.14107747 2.91703551 0.28802415 4.375 0.4375 C5.59316406 0.55931641 5.59316406 0.55931641 6.8359375 0.68359375 C9 1 9 1 11 2 C11 2.66 11 3.32 11 4 C11.7425 4.2475 12.485 4.495 13.25 4.75 C16.20124062 6.09147301 17.84814974 7.60905526 20 10 C18 13 18 13 15.875 13.6875 C15.25625 13.790625 14.6375 13.89375 14 14 C13.54109375 13.46890625 13.0821875 12.9378125 12.609375 12.390625 C6.84878792 5.60474421 6.84878792 5.60474421 0 0 Z " fill="#DCE6E7" transform="translate(33,29)"/>
<path d="M0 0 C1.94326172 -0.02126953 1.94326172 -0.02126953 3.92578125 -0.04296875 C7.5537588 0.17930609 10.3207728 0.86690778 13.6875 2.1875 C13.3575 3.1775 13.0275 4.1675 12.6875 5.1875 C5.7575 4.5275 -1.1725 3.8675 -8.3125 3.1875 C-8.3125 3.8475 -8.3125 4.5075 -8.3125 5.1875 C-9.3025 5.5175 -10.2925 5.8475 -11.3125 6.1875 C-10.9825 4.5375 -10.6525 2.8875 -10.3125 1.1875 C-6.73036361 -0.00654546 -3.77628742 0.018676 0 0 Z " fill="#8BD7E4" transform="translate(31.3125,17.8125)"/>
<path d="M0 0 C2.08997373 3.39620731 2.2632246 6.05163095 2 10 C1.67 10.33 1.34 10.66 1 11 C-5.39534884 10.30232558 -5.39534884 10.30232558 -8 9 C-7.61479436 6.46089803 -7.29902057 5.27248877 -5.37109375 3.515625 C-4.73300781 3.09796875 -4.09492188 2.6803125 -3.4375 2.25 C-2.79683594 1.82203125 -2.15617187 1.3940625 -1.49609375 0.953125 C-1.00238281 0.63859375 -0.50867188 0.3240625 0 0 Z " fill="#789BA7" transform="translate(20,34)"/>
<path d="M0 0 C1.81618856 1.11903546 3.62785526 2.24541284 5.4375 3.375 C6.95150391 4.31472656 6.95150391 4.31472656 8.49609375 5.2734375 C11 7 11 7 12 9 C10 12 10 12 6.875 12.6875 C5.451875 12.8421875 5.451875 12.8421875 4 13 C2.46554906 9.93109813 3.45015711 7.29905734 4 4 C3.01 4.66 2.02 5.32 1 6 C0.01 6 -0.98 6 -2 6 C-1.49396008 3.83125748 -1.00016187 2.00032373 0 0 Z " fill="#8CD5E2" transform="translate(52,24)"/>
<path d="M0 0 C1.32 0.99 2.64 1.98 4 3 C3.24074219 3.43570312 2.48148438 3.87140625 1.69921875 4.3203125 C-5.89376915 8.67709254 -5.89376915 8.67709254 -10 16 C-10.66 15.67 -11.32 15.34 -12 15 C-12.5625 12.4375 -12.5625 12.4375 -12 9 C-8.41928922 5.44139237 -4.18499816 2.78999877 0 0 Z " fill="#91D6E0" transform="translate(14,23)"/>
<path d="M0 0 C3.75635569 0.75127114 5.83210307 1.24005726 9 3 C4.93846154 8.78461538 4.93846154 8.78461538 0.1875 9.875 C-0.864375 9.91625 -1.91625 9.9575 -3 10 C-2.01 6.7 -1.02 3.4 0 0 Z " fill="#2E222D" transform="translate(35,38)"/>
<path d="M0 0 C1.36421031 2.72842061 0.87807211 4.60953318 0.5625 7.625 C0.46066406 8.62789062 0.35882812 9.63078125 0.25390625 10.6640625 C0.17011719 11.43492188 0.08632813 12.20578125 0 13 C0.66 13 1.32 13 2 13 C1.67 15.64 1.34 18.28 1 21 C-0.32 21.33 -1.64 21.66 -3 22 C-3.33 21.34 -3.66 20.68 -4 20 C-3.67 19.01 -3.34 18.02 -3 17 C-3.66 17 -4.32 17 -5 17 C-4.71125 16.21625 -4.4225 15.4325 -4.125 14.625 C-2.93722932 10.79773892 -2.17712633 7.01237617 -1.46484375 3.07421875 C-1 1 -1 1 0 0 Z " fill="#304747" transform="translate(19,3)"/>
<path d="M0 0 C0.99 0.66 1.98 1.32 3 2 C3.40843923 4.71203652 3.13336867 7.2437142 3 10 C1.68 10 0.36 10 -1 10 C-1.33 8.02 -1.66 6.04 -2 4 C-3.32 3.67 -4.64 3.34 -6 3 C-6.33 5.97 -6.66 8.94 -7 12 C-6.01 12.33 -5.02 12.66 -4 13 C-4 14.32 -4 15.64 -4 17 C-6 18.75 -6 18.75 -8 20 C-7.49396008 17.83125748 -7.00016187 16.00032373 -6 14 C-6.66 14 -7.32 14 -8 14 C-8.02696365 12.20841511 -8.04637917 10.41671527 -8.0625 8.625 C-8.07410156 7.62726562 -8.08570312 6.62953125 -8.09765625 5.6015625 C-8 3 -8 3 -7 1 C-5.02 1 -3.04 1 -1 1 C0.35439668 3.70879335 0.06501451 6.00933268 0 9 C0.66 9 1.32 9 2 9 C1.34 6.03 0.68 3.06 0 0 Z " fill="#0D1D1D" transform="translate(27,2)"/>
<path d="M0 0 C0.125 6.625 0.125 6.625 -1 10 C-3.875 9.6875 -3.875 9.6875 -7 9 C-7.66 8.01 -8.32 7.02 -9 6 C-8.34 6 -7.68 6 -7 6 C-7 4.68 -7 3.36 -7 2 C-1.125 0 -1.125 0 0 0 Z " fill="#B01720" transform="translate(34,37)"/>
<path d="M0 0 C2.64 0 5.28 0 8 0 C9.09658936 3.28976808 8.79953138 4.71303767 8 8 C6.02 8 4.04 8 2 8 C0.23537317 4.91190305 0 3.76687864 0 0 Z " fill="#E7979B" transform="translate(24,31)"/>
<path d="M0 0 C2.5 1.8125 2.5 1.8125 5 4 C5 4.99 5 5.98 5 7 C-4.22551253 12.74031891 -4.22551253 12.74031891 -10 12 C-10 11.34 -10 10.68 -10 10 C-8.9275 9.773125 -7.855 9.54625 -6.75 9.3125 C-2.61394449 7.86488057 -1.19085792 6.74271562 1 3 C0.67 2.01 0.34 1.02 0 0 Z " fill="#7D9CA4" transform="translate(42,38)"/>
<path d="M0 0 C0.7734375 0.00386719 1.546875 0.00773437 2.34375 0.01171875 C4.5 0.3125 4.5 0.3125 7.5 2.3125 C7.6875 4.9375 7.6875 4.9375 7.5 7.3125 C5.85 6.9825 4.2 6.6525 2.5 6.3125 C2.83 4.9925 3.16 3.6725 3.5 2.3125 C2.241875 2.4775 0.98375 2.6425 -0.3125 2.8125 C-2.76456585 3.13408241 -5.01650694 3.3125 -7.5 3.3125 C-5.13249637 0.43659014 -3.69770505 -0.08011694 0 0 Z " fill="#C55853" transform="translate(28.5,28.6875)"/>
<path d="M0 0 C1.29550781 -0.00515625 2.59101562 -0.0103125 3.92578125 -0.015625 C7.53629431 0.23932296 10.33210112 0.93905346 13.6875 2.25 C13.3575 3.24 13.0275 4.23 12.6875 5.25 C12.0275 5.25 11.3675 5.25 10.6875 5.25 C10.6875 4.59 10.6875 3.93 10.6875 3.25 C3.66944143 2.14912807 -3.21815767 2.15266908 -10.3125 2.25 C-6.56108259 -0.25094494 -4.47317558 -0.01769802 0 0 Z " fill="#98D6DE" transform="translate(31.3125,17.75)"/>
<path d="M0 0 C8.90763766 -0.45293073 8.90763766 -0.45293073 13 3 C13 3.99 13 4.98 13 6 C11.02 6 9.04 6 7 6 C7 5.01 7 4.02 7 3 C5.824375 2.814375 5.824375 2.814375 4.625 2.625 C2 2 2 2 0 0 Z " fill="#B4D2D5" transform="translate(17,45)"/>
<path d="M0 0 C1.12758089 3.38274266 0.81750262 4.76778223 0.0625 8.1875 C-0.13214844 9.08855469 -0.32679687 9.98960938 -0.52734375 10.91796875 C-0.68332031 11.60503906 -0.83929688 12.29210938 -1 13 C-1.33 13 -1.66 13 -2 13 C-2 11.02 -2 9.04 -2 7 C-3.98 7.33 -5.96 7.66 -8 8 C-5.33333333 5.33333333 -2.66666667 2.66666667 0 0 Z " fill="#2E8E9B" transform="translate(63,34)"/>
<path d="M0 0 C5.63877557 -0.58737246 8.58058781 0.52521757 13.30078125 3.61328125 C15 5 15 5 17 8 C16.67 8.99 16.34 9.98 16 11 C15.2575 10.21625 14.515 9.4325 13.75 8.625 C11.45566682 6.43495469 9.87841142 5.17268614 7 4 C7 3.34 7 2.68 7 2 C4.69 1.67 2.38 1.34 0 1 C0 0.67 0 0.34 0 0 Z " fill="#8CD2E0" transform="translate(37,29)"/>
<path d="M0 0 C0.99 0 1.98 0 3 0 C3.04254356 1.99954746 3.04080783 4.00041636 3 6 C2.67 6.33 2.34 6.66 2 7 C-0.33944736 6.71269945 -2.6739143 6.38063221 -5 6 C-4.01 5.67 -3.02 5.34 -2 5 C-2 4.01 -2 3.02 -2 2 C-1.34 2 -0.68 2 0 2 C0 1.34 0 0.68 0 0 Z " fill="#73898C" transform="translate(19,38)"/>
<path d="M0 0 C0.66 0 1.32 0 2 0 C3.20272819 2.40545638 3.10071472 3.94996953 3.0625 6.625 C3.05347656 7.44226562 3.04445312 8.25953125 3.03515625 9.1015625 C3.02355469 9.72804688 3.01195312 10.35453125 3 11 C2.01 11 1.02 11 0 11 C0 7.37 0 3.74 0 0 Z " fill="#238FA3" transform="translate(33,53)"/>
<path d="M0 0 C0.99 0 1.98 0 3 0 C3.66 0.99 4.32 1.98 5 3 C7.55183404 4.20450304 7.55183404 4.20450304 10 5 C9.67 6.32 9.34 7.64 9 9 C8.67 8.34 8.34 7.68 8 7 C4.54179464 4.50240724 2.26322371 3.63458082 -2 4 C-1.34 2.68 -0.68 1.36 0 0 Z " fill="#673B42" transform="translate(22,42)"/>
<path d="M0 0 C0.66 0 1.32 0 2 0 C2 0.66 2 1.32 2 2 C3.98 2.66 5.96 3.32 8 4 C8 5.65 8 7.3 8 9 C6.84775972 8.07038578 5.70340824 7.1309875 4.5625 6.1875 C3.60537109 5.40439453 3.60537109 5.40439453 2.62890625 4.60546875 C1 3 1 3 0 0 Z " fill="#D4D1D2" transform="translate(40,34)"/>
<path d="M0 0 C3.55780196 0.60990891 6.6828589 1.5783681 10 3 C10 3.99 10 4.98 10 6 C5.56909529 4.79157144 3.01887244 3.48331435 0 0 Z " fill="#8EDAE8" transform="translate(14,45)"/>
<path d="M0 0 C1.98 0.495 1.98 0.495 4 1 C3.34 2.65 2.68 4.3 2 6 C1.01 6 0.02 6 -1 6 C-0.67 4.02 -0.34 2.04 0 0 Z " fill="#080718" transform="translate(37,39)"/>
<path d="M0 0 C-1.1875 1.5 -1.1875 1.5 -3 3 C-5.5 3.1875 -5.5 3.1875 -8 3 C-8.99 3 -9.98 3 -11 3 C-8.21756596 -1.17365106 -4.53441502 -0.22300402 0 0 Z " fill="#2C4254" transform="translate(32,29)"/>
<path d="M0 0 C0.66 0.33 1.32 0.66 2 1 C2 2.65 2 4.3 2 6 C-0.31 5.34 -2.62 4.68 -5 4 C-3.35 2.68 -1.7 1.36 0 0 Z " fill="#2B9BB2" transform="translate(21,23)"/>
<path d="M0 0 C1.29858939 0.56775536 2.58870441 1.15491663 3.875 1.75 C4.59429687 2.07484375 5.31359375 2.3996875 6.0546875 2.734375 C8.3370674 4.21929686 9.00375898 5.50415408 10 8 C9.34 8 8.68 8 8 8 C7.67 7.34 7.34 6.68 7 6 C5.34948712 4.88365848 5.34948712 4.88365848 3.4375 3.875 C2.303125 3.25625 1.16875 2.6375 0 2 C0 1.34 0 0.68 0 0 Z " fill="#C9F0F8" transform="translate(43,32)"/>
<path d="M0 0 C2.475 0.99 2.475 0.99 5 2 C4.34 3.32 3.68 4.64 3 6 C2.01 5.67 1.02 5.34 0 5 C0 3.35 0 1.7 0 0 Z " fill="#9C2029" transform="translate(35,31)"/>
<path d="M0 0 C0.66 0 1.32 0 2 0 C2.66 1.98 3.32 3.96 4 6 C2.68 6.33 1.36 6.66 0 7 C-0.38133299 5.0085944 -0.71325582 3.00720923 -1 1 C-0.67 0.67 -0.34 0.34 0 0 Z " fill="#3494A9" transform="translate(23,23)"/>
<path d="M0 0 C1.32 0.33 2.64 0.66 4 1 C3.67 1.99 3.34 2.98 3 4 C1.02 4.33 -0.96 4.66 -3 5 C-2.67 4.01 -2.34 3.02 -2 2 C-1.34 2 -0.68 2 0 2 C0 1.34 0 0.68 0 0 Z " fill="#495E5A" transform="translate(17,15)"/>
<path d="M0 0 C2.475 0.99 2.475 0.99 5 2 C4.01 3.485 4.01 3.485 3 5 C2.01 5 1.02 5 0 5 C0 3.35 0 1.7 0 0 Z " fill="#FBD3CF" transform="translate(27,33)"/>
<path d="M0 0 C2.64 0 5.28 0 8 0 C8.33 0.99 8.66 1.98 9 3 C6.03 2.67 3.06 2.34 0 2 C0 1.34 0 0.68 0 0 Z " fill="#A68483" transform="translate(24,31)"/>
<path d="M0 0 C0.33 0.66 0.66 1.32 1 2 C1.99 1.67 2.98 1.34 4 1 C3.67 1.99 3.34 2.98 3 4 C1.02 4.33 -0.96 4.66 -3 5 C-3 4.01 -3 3.02 -3 2 C-2.01 1.34 -1.02 0.68 0 0 Z " fill="#89D0D9" transform="translate(20,31)"/>
<path d="M0 0 C1.45922693 0.11409593 2.91740598 0.24165544 4.375 0.375 C5.59316406 0.47941406 5.59316406 0.47941406 6.8359375 0.5859375 C9 1 9 1 11 3 C6.17156286 3 4.0096486 2.67309907 0 0 Z " fill="#BFD8DC" transform="translate(33,29)"/>
</svg>

After

Width:  |  Height:  |  Size: 20 KiB

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Destinations | Coolify
</x-slot>
<div class="flex items-start gap-2">
<div class="flex items-center gap-2">
<h1>Destinations</h1>
@if ($servers->count() > 0)
<x-modal-input buttonTitle="+ Add" title="New Destination">

View File

@@ -39,7 +39,7 @@
@if ($currentRoute === 'project.service.configuration')
<livewire:project.service.stack-form :service="$service" />
<h3>Services</h3>
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-1">
<div class="grid grid-cols-1 gap-2 pt-4 xl:grid-cols-1" wire:poll.10s="check_status">
@foreach ($applications as $application)
<div @class([
'border-l border-dashed border-red-500 ' => str(

View File

@@ -165,10 +165,12 @@
return;
}
$wire.$dispatch('info', 'Service restart in progress.');
window.dispatchEvent(new CustomEvent('startservice'));
$wire.$call('restart');
});
$wire.$on('pullAndRestartEvent', () => {
$wire.$dispatch('info', 'Pulling new images.');
$wire.$dispatch('info', 'Pulling new images and restarting service.');
window.dispatchEvent(new CustomEvent('startservice'));
$wire.$call('pullAndRestartEvent');
});
$wire.on('imagePulled', () => {

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Servers | Coolify
</x-slot>
<div class="flex items-start gap-2">
<div class="flex items-center gap-2">
<h1>Servers</h1>
<x-modal-input buttonTitle="+ Add" title="New Server" :closeOutside="false">
<livewire:server.create />

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Project Variable | Coolify
</x-slot>
<div class="flex gap-2">
<div class="flex gap-2 items-center">
<h1>Shared Variables for {{data_get($project,'name')}}</h1>
<x-modal-input buttonTitle="+ Add" title="New Shared Variable">
<livewire:project.shared.environment-variable.add :shared="true" />

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Team Variables | Coolify
</x-slot>
<div class="flex gap-2">
<div class="flex gap-2 items-center">
<h1>Team Shared Variables</h1>
<x-modal-input buttonTitle="+ Add" title="New Shared Variable">
<livewire:project.shared.environment-variable.add :shared="true" />

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Storages | Coolify
</x-slot>
<div class="flex items-start gap-2">
<div class="flex items-center gap-2">
<h1>S3 Storages</h1>
<x-modal-input buttonTitle="+ Add" title="New S3 Storage" :closeOutside="false">
<livewire:storage.create />

View File

@@ -2,7 +2,7 @@
<x-slot:title>
Sources | Coolify
</x-slot>
<div class="flex items-start gap-2">
<div class="flex items-center gap-2">
<h1>Sources</h1>
<x-modal-input buttonTitle="+ Add" title="New GitHub App" :closeOutside="false">
<livewire:source.github.create />

View File

@@ -88,6 +88,7 @@ Route::group([
Route::patch('/applications/{uuid}/envs', [ApplicationsController::class, 'update_env_by_uuid'])->middleware(['api.ability:write']);
Route::delete('/applications/{uuid}/envs/{env_uuid}', [ApplicationsController::class, 'delete_env_by_uuid'])->middleware(['api.ability:write']);
// Route::post('/applications/{uuid}/execute', [ApplicationsController::class, 'execute_command_by_uuid'])->middleware(['ability:write']);
Route::get('/applications/{uuid}/logs', [ApplicationsController::class, 'logs_by_uuid'])->middleware(['api.ability:read']);
Route::match(['get', 'post'], '/applications/{uuid}/start', [ApplicationsController::class, 'action_deploy'])->middleware(['api.ability:write']);
Route::match(['get', 'post'], '/applications/{uuid}/restart', [ApplicationsController::class, 'action_restart'])->middleware(['api.ability:write']);

View File

@@ -0,0 +1,41 @@
# documentation: https://www.bugsink.com/docs/
# slogan: Self-hosted Error Tracking
# tags: python, error-tracking, django, mysql
# logo: svgs/bugsink.svg
# port: 8000
services:
mysql:
image: 'mysql:latest'
restart: unless-stopped
environment:
- 'MYSQL_ROOT_PASSWORD=${SERVICE_PASSWORD_ROOT}'
- 'MYSQL_DATABASE=${MYSQL_DATABASE:-bugsink}'
- 'MYSQL_USER=${SERVICE_USER_BUGSINK}'
- 'MYSQL_PASSWORD=${SERVICE_PASSWORD_BUGSINK}'
volumes:
- 'my-datavolume:/var/lib/mysql'
healthcheck:
test:
- CMD
- mysqladmin
- ping
- '-h'
- 127.0.0.1
interval: 5s
timeout: 20s
retries: 10
web:
image: bugsink/bugsink
restart: unless-stopped
environment:
- SECRET_KEY=$SERVICE_PASSWORD_64_BUGSINK
- 'CREATE_SUPERUSER=admin:${SERVICE_PASSWORD_BUGSINK}'
- SERVICE_FQDN_BUGSINK_8000
- 'BASE_URL=${SERVICE_FQDN_BUGSINK_8000}'
- 'DATABASE_URL=mysql://${SERVICE_USER_BUGSINK}:$SERVICE_PASSWORD_BUGSINK@mysql:3306/${MYSQL_DATABASE:-bugsink}'
depends_on:
mysql:
condition: service_healthy
volumes:
my-datavolume:

View File

@@ -1,5 +1,5 @@
# documentation: https://nitropage.com
# slogan: Nitropage is an extensible visual website builder, offering a growing collection of versatile building blocks, focal-point image cropping and sovereign font management.
# documentation: https://nitropage.org
# slogan: Nitropage is an extensible, visual website builder, offering a growing library of versatile building blocks, focal-point image cropping and sovereign font management.
# tags: nitropage, builder, editor, wysiwyg, cms, content, management
# logo: svgs/nitropage.svg
# port: 3000

View File

@@ -1,5 +1,5 @@
# documentation: https://nitropage.com
# slogan: Nitropage is an extensible visual website builder, offering a growing collection of versatile building blocks, focal-point image cropping and sovereign font management.
# documentation: https://nitropage.org
# slogan: Nitropage is an extensible, visual website builder, offering a growing library of versatile building blocks, focal-point image cropping and sovereign font management.
# tags: nitropage, builder, editor, wysiwyg, cms, content, management
# logo: svgs/nitropage.svg
# port: 3000

View File

@@ -268,6 +268,20 @@
"minversion": "0.0.0",
"port": "10000"
},
"bugsink": {
"documentation": "https://www.bugsink.com/docs/?utm_source=coolify.io",
"slogan": "Self-hosted Error Tracking",
"compose": "c2VydmljZXM6CiAgbXlzcWw6CiAgICBpbWFnZTogJ215c3FsOmxhdGVzdCcKICAgIHJlc3RhcnQ6IHVubGVzcy1zdG9wcGVkCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnTVlTUUxfUk9PVF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfUk9PVH0nCiAgICAgIC0gJ01ZU1FMX0RBVEFCQVNFPSR7TVlTUUxfREFUQUJBU0U6LWJ1Z3Npbmt9JwogICAgICAtICdNWVNRTF9VU0VSPSR7U0VSVklDRV9VU0VSX0JVR1NJTkt9JwogICAgICAtICdNWVNRTF9QQVNTV09SRD0ke1NFUlZJQ0VfUEFTU1dPUkRfQlVHU0lOS30nCiAgICB2b2x1bWVzOgogICAgICAtICdteS1kYXRhdm9sdW1lOi92YXIvbGliL215c3FsJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIG15c3FsYWRtaW4KICAgICAgICAtIHBpbmcKICAgICAgICAtICctaCcKICAgICAgICAtIDEyNy4wLjAuMQogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCiAgd2ViOgogICAgaW1hZ2U6IGJ1Z3NpbmsvYnVnc2luawogICAgcmVzdGFydDogdW5sZXNzLXN0b3BwZWQKICAgIGVudmlyb25tZW50OgogICAgICAtIFNFQ1JFVF9LRVk9JFNFUlZJQ0VfUEFTU1dPUkRfNjRfQlVHU0lOSwogICAgICAtICdDUkVBVEVfU1VQRVJVU0VSPWFkbWluOiR7U0VSVklDRV9QQVNTV09SRF9CVUdTSU5LfScKICAgICAgLSBTRVJWSUNFX0ZRRE5fQlVHU0lOS184MDAwCiAgICAgIC0gJ0JBU0VfVVJMPSR7U0VSVklDRV9GUUROX0JVR1NJTktfODAwMH0nCiAgICAgIC0gJ0RBVEFCQVNFX1VSTD1teXNxbDovLyR7U0VSVklDRV9VU0VSX0JVR1NJTkt9OiRTRVJWSUNFX1BBU1NXT1JEX0JVR1NJTktAbXlzcWw6MzMwNi8ke01ZU1FMX0RBVEFCQVNFOi1idWdzaW5rfScKICAgIGRlcGVuZHNfb246CiAgICAgIG15c3FsOgogICAgICAgIGNvbmRpdGlvbjogc2VydmljZV9oZWFsdGh5CnZvbHVtZXM6CiAgbXktZGF0YXZvbHVtZTogbnVsbAo=",
"tags": [
"python",
"error-tracking",
"django",
"mysql"
],
"logo": "svgs/bugsink.svg",
"minversion": "0.0.0",
"port": "8000"
},
"calcom": {
"documentation": "https://cal.com/docs?utm_source=coolify.io",
"slogan": "Scheduling infrastructure for everyone.",
@@ -2002,7 +2016,7 @@
"transformation",
"service"
],
"logo": "svgs/coolify.png",
"logo": "svgs/coolify-transparent.png",
"minversion": "0.0.0",
"port": "3000"
},
@@ -2101,8 +2115,8 @@
"port": "8081"
},
"nitropage-with-postgresql": {
"documentation": "https://nitropage.com?utm_source=coolify.io",
"slogan": "Nitropage is an extensible visual website builder, offering a growing collection of versatile building blocks, focal-point image cropping and sovereign font management.",
"documentation": "https://nitropage.org?utm_source=coolify.io",
"slogan": "Nitropage is an extensible, visual website builder, offering a growing library of versatile building blocks, focal-point image cropping and sovereign font management.",
"compose": "c2VydmljZXM6CiAgbml0cm9wYWdlOgogICAgaW1hZ2U6IGNvZGViZXJnLm9yZy9uaXRyb3BhZ2Uvbml0cm9wYWdlCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTklUUk9QQUdFXzMwMDAKICAgICAgLSAnTlBfQVVUSF9TQUxUPSR7U0VSVklDRV9CQVNFNjRfU0FMVH0nCiAgICAgIC0gJ05QX0FVVEhfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X1NFU1NJT059JwogICAgICAtICdEQVRBQkFTRV9VUkw9cG9zdGdyZXNxbDovLyR7U0VSVklDRV9VU0VSX1BPU1RHUkVTUUx9OiR7U0VSVklDRV9QQVNTV09SRF9QT1NUR1JFU1FMfUBwb3N0Z3Jlc3FsOjU0MzIvJHtQT1NUR1JFU1FMX0RBVEFCQVNFOi1uaXRyb3BhZ2V9JwogICAgdm9sdW1lczoKICAgICAgLSAnbml0cm9wYWdlLWRhdGE6L2FwcC8uZGF0YScKICAgIGRlcGVuZHNfb246CiAgICAgIHBvc3RncmVzcWw6CiAgICAgICAgY29uZGl0aW9uOiBzZXJ2aWNlX2hlYWx0aHkKICAgIGhlYWx0aGNoZWNrOgogICAgICB0ZXN0OgogICAgICAgIC0gQ01ECiAgICAgICAgLSBjdXJsCiAgICAgICAgLSAnLWYnCiAgICAgICAgLSAnaHR0cDovLzEyNy4wLjAuMTozMDAwL2FkbWluJwogICAgICBpbnRlcnZhbDogMnMKICAgICAgdGltZW91dDogMTBzCiAgICAgIHJldHJpZXM6IDE1CiAgcG9zdGdyZXNxbDoKICAgIGltYWdlOiAncG9zdGdyZXM6MTYtYWxwaW5lJwogICAgdm9sdW1lczoKICAgICAgLSAnbml0cm9wYWdlLXBvc3RncmVzcWwtZGF0YTovdmFyL2xpYi9wb3N0Z3Jlc3FsL2RhdGEnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSAnUE9TVEdSRVNfVVNFUj0ke1NFUlZJQ0VfVVNFUl9QT1NUR1JFU1FMfScKICAgICAgLSAnUE9TVEdSRVNfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEX1BPU1RHUkVTUUx9JwogICAgICAtICdQT1NUR1JFU19EQj0ke1BPU1RHUkVTUUxfREFUQUJBU0U6LW5pdHJvcGFnZX0nCiAgICBoZWFsdGhjaGVjazoKICAgICAgdGVzdDoKICAgICAgICAtIENNRC1TSEVMTAogICAgICAgIC0gJ3BnX2lzcmVhZHkgLVUgJCR7UE9TVEdSRVNfVVNFUn0gLWQgJCR7UE9TVEdSRVNfREJ9JwogICAgICBpbnRlcnZhbDogNXMKICAgICAgdGltZW91dDogMjBzCiAgICAgIHJldHJpZXM6IDEwCg==",
"tags": [
"nitropage",
@@ -2118,8 +2132,8 @@
"port": "3000"
},
"nitropage": {
"documentation": "https://nitropage.com?utm_source=coolify.io",
"slogan": "Nitropage is an extensible visual website builder, offering a growing collection of versatile building blocks, focal-point image cropping and sovereign font management.",
"documentation": "https://nitropage.org?utm_source=coolify.io",
"slogan": "Nitropage is an extensible, visual website builder, offering a growing library of versatile building blocks, focal-point image cropping and sovereign font management.",
"compose": "c2VydmljZXM6CiAgbml0cm9wYWdlOgogICAgaW1hZ2U6ICdjb2RlYmVyZy5vcmcvbml0cm9wYWdlL25pdHJvcGFnZTpzcWxpdGUnCiAgICBlbnZpcm9ubWVudDoKICAgICAgLSBTRVJWSUNFX0ZRRE5fTklUUk9QQUdFXzMwMDAKICAgICAgLSAnTlBfQVVUSF9TQUxUPSR7U0VSVklDRV9CQVNFNjRfU0FMVH0nCiAgICAgIC0gJ05QX0FVVEhfUEFTU1dPUkQ9JHtTRVJWSUNFX1BBU1NXT1JEXzY0X1NFU1NJT059JwogICAgICAtICdEQVRBQkFTRV9VUkw9ZmlsZTouLi8uLi8uZGF0YS9kZXYuZGInCiAgICB2b2x1bWVzOgogICAgICAtICduaXRyb3BhZ2UtZGF0YTovYXBwLy5kYXRhJwogICAgaGVhbHRoY2hlY2s6CiAgICAgIHRlc3Q6CiAgICAgICAgLSBDTUQKICAgICAgICAtIGN1cmwKICAgICAgICAtICctZicKICAgICAgICAtICdodHRwOi8vMTI3LjAuMC4xOjMwMDAvYWRtaW4nCiAgICAgIGludGVydmFsOiAycwogICAgICB0aW1lb3V0OiAxMHMKICAgICAgcmV0cmllczogMTUK",
"tags": [
"nitropage",

View File

@@ -1,10 +1,10 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.391"
"version": "4.0.0-beta.392"
},
"nightly": {
"version": "4.0.0-beta.392"
"version": "4.0.0-beta.393"
},
"helper": {
"version": "1.0.6"