# Conflicts:
#	templates/service-templates.json
This commit is contained in:
Alexander 2024-07-13 01:08:17 +02:00
commit 77a6a6e46a
41 changed files with 362 additions and 178 deletions

View File

@ -2,8 +2,6 @@
)
[![Bounty Issues](https://img.shields.io/static/v1?labelColor=grey&color=6366f1&label=Algora&message=%F0%9F%92%8E+Bounty+issues&style=for-the-badge)](https://console.algora.io/org/coollabsio/bounties/new)
[![Open Bounties](https://img.shields.io/endpoint?url=https%3A%2F%2Fconsole.algora.io%2Fapi%2Fshields%2Fcoollabsio%2Fbounties%3Fstatus%3Dopen&style=for-the-badge)](https://console.algora.io/org/coollabsio/bounties?status=open)
[![Rewarded Bounties](https://img.shields.io/endpoint?url=https%3A%2F%2Fconsole.algora.io%2Fapi%2Fshields%2Fcoollabsio%2Fbounties%3Fstatus%3Dcompleted&style=for-the-badge)](https://console.algora.io/org/coollabsio/bounties?status=completed)
# About the Project
@ -49,6 +47,7 @@ # Donations
<a href="https://coolify.ad.vin/?ref=coolify.io" target="_blank"><img src="./other/logos/advin.png" alt="advin logo" width="250"/></a>
<a href="https://trieve.ai/?ref=coolify.io" target="_blank"><img src="./other/logos/trieve_bg.png" alt="trieve logo" width="180"/></a>
<a href="https://blacksmith.sh/?ref=coolify.io" target="_blank"><img src="./other/logos/blacksmith.svg" alt="blacksmith logo" width="200"/></a>
<a href="https://latitude.sh/?ref=coolify.io" target="_blank"><img src="./other/logos/latitude.svg" alt="latitude logo" width="200"/></a>
## Github Sponsors ($40+)
<a href="https://serpapi.com/?ref=coolify.io"><img width="60px" alt="SerpAPI" src="https://github.com/serpapi.png"/></a>

View File

@ -2,6 +2,7 @@
namespace App\Console\Commands;
use App\Actions\Server\StopSentinel;
use App\Enums\ApplicationDeploymentStatus;
use App\Jobs\CleanupHelperContainersJob;
use App\Models\ApplicationDeploymentQueue;
@ -23,6 +24,16 @@ public function handle()
{
$this->alive();
get_public_ips();
if (version_compare('4.0.0-beta.312', config('version'), '<=')) {
$servers = Server::all();
foreach ($servers as $server) {
$server->settings->update(['is_metrics_enabled' => false]);
if ($server->isFunctional()) {
StopSentinel::dispatch($server);
}
}
}
$full_cleanup = $this->option('full-cleanup');
$cleanup_deployments = $this->option('cleanup-deployments');

View File

@ -27,7 +27,7 @@ public function __construct($userId = null)
public function broadcastOn(): ?array
{
if ($this->userId) {
if (! is_null($this->userId)) {
return [
new PrivateChannel("user.{$this->userId}"),
];

View File

@ -65,7 +65,7 @@ public function register(): void
if ($e instanceof RuntimeException) {
return;
}
$this->settings = InstanceSettings::get();
$this->settings = \App\Models\InstanceSettings::get();
if ($this->settings->do_not_track) {
return;
}

View File

@ -3,7 +3,6 @@
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use App\Models\InstanceSettings;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Http;
use OpenApi\Attributes as OA;
@ -85,7 +84,7 @@ public function enable_api(Request $request)
if ($teamId !== '0') {
return response()->json(['message' => 'You are not allowed to enable the API.'], 403);
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$settings->update(['is_api_enabled' => true]);
return response()->json(['message' => 'API enabled.'], 200);
@ -136,7 +135,7 @@ public function disable_api(Request $request)
if ($teamId !== '0') {
return response()->json(['message' => 'You are not allowed to disable the API.'], 403);
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$settings->update(['is_api_enabled' => false]);
return response()->json(['message' => 'API disabled.'], 200);

View File

@ -4,7 +4,6 @@
use App\Http\Controllers\Controller;
use App\Models\Application;
use App\Models\InstanceSettings;
use App\Models\Project;
use App\Models\Server as ModelsServer;
use Illuminate\Http\Request;
@ -301,7 +300,7 @@ public function domains_by_server(Request $request)
$projects = Project::where('team_id', $teamId)->get();
$domains = collect();
$applications = $projects->pluck('applications')->flatten();
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if ($applications->count() > 0) {
foreach ($applications as $application) {
$ip = $application->destination->server->ip;

View File

@ -2,7 +2,6 @@
namespace App\Http\Middleware;
use App\Models\InstanceSettings;
use Closure;
use Illuminate\Http\Request;
use Symfony\Component\HttpFoundation\Response;
@ -15,7 +14,7 @@ public function handle(Request $request, Closure $next): Response
if (isCloud()) {
return $next($request);
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if ($settings->is_api_enabled === false) {
return response()->json(['success' => true, 'message' => 'API is disabled.'], 403);
}

View File

@ -2,7 +2,6 @@
namespace App\Jobs;
use App\Models\InstanceSettings;
use App\Models\Server;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldBeEncrypted;
@ -36,7 +35,7 @@ public function handle(): void
$latest_version = get_latest_version_of_coolify();
instant_remote_process(["docker pull -q ghcr.io/coollabsio/coolify:{$latest_version}"], $server, false);
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$current_version = config('version');
if (! $settings->is_auto_update_enabled) {
return;

View File

@ -2,7 +2,6 @@
namespace App\Livewire;
use App\Models\InstanceSettings;
use DanHarrin\LivewireRateLimiting\WithRateLimiting;
use Illuminate\Notifications\Messages\MailMessage;
use Illuminate\Support\Facades\Http;
@ -48,7 +47,7 @@ public function submit()
]
);
$mail->subject("[HELP]: {$this->subject}");
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$type = set_transanctional_email_settings($settings);
if (! $type) {
$url = 'https://app.coolify.io/api/feedback';

View File

@ -2,7 +2,6 @@
namespace App\Livewire\Notifications;
use App\Models\InstanceSettings;
use App\Models\Team;
use App\Notifications\Test;
use Livewire\Component;
@ -173,7 +172,7 @@ public function submitResend()
public function copyFromInstanceSettings()
{
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if ($settings->smtp_enabled) {
$team = currentTeam();
$team->update([

View File

@ -350,7 +350,6 @@ public function submit($showToaster = true)
$this->checkFqdns();
$this->application->save();
if (! $this->customLabels && $this->application->destination->server->proxyType() !== 'NONE') {
$this->customLabels = str(implode('|coolify|', generateLabelsApplication($this->application)))->replace('|coolify|', "\n");
$this->application->custom_labels = base64_encode($this->customLabels);
@ -364,6 +363,7 @@ public function submit($showToaster = true)
}
}
$this->validate();
if ($this->ports_exposes !== $this->application->ports_exposes || $this->is_container_label_escape_enabled !== $this->application->settings->is_container_label_escape_enabled) {
$this->resetDefaultLabels();
}
@ -390,6 +390,7 @@ public function submit($showToaster = true)
}
if ($this->application->build_pack === 'dockercompose') {
$this->application->docker_compose_domains = json_encode($this->parsedServiceDomains);
foreach ($this->parsedServiceDomains as $serviceName => $service) {
$domain = data_get($service, 'domain');
if ($domain) {
@ -399,6 +400,9 @@ public function submit($showToaster = true)
check_domain_usage(resource: $this->application);
}
}
if ($this->application->isDirty('docker_compose_domains')) {
$this->resetDefaultLabels();
}
}
$this->application->custom_labels = base64_encode($this->customLabels);
$this->application->save();

View File

@ -3,32 +3,63 @@
namespace App\Livewire\Project\Shared;
use App\Models\Tag;
use Livewire\Attributes\Validate;
use Livewire\Component;
// Refactored ✅
class Tags extends Component
{
public $resource = null;
public ?string $new_tag = null;
#[Validate('required|string|min:2')]
public string $newTags;
public $tags = [];
protected $listeners = [
'refresh' => '$refresh',
];
protected $rules = [
'resource.tags.*.name' => 'required|string|min:2',
'new_tag' => 'required|string|min:2',
];
protected $validationAttributes = [
'new_tag' => 'tag',
];
public $filteredTags = [];
public function mount()
{
$this->loadTags();
}
public function loadTags()
{
$this->tags = Tag::ownedByCurrentTeam()->get();
$this->filteredTags = $this->tags->filter(function ($tag) {
return ! $this->resource->tags->contains($tag);
});
}
public function submit()
{
try {
$this->validate();
$tags = str($this->newTags)->trim()->explode(' ');
foreach ($tags as $tag) {
if (strlen($tag) < 2) {
$this->dispatch('error', 'Invalid tag.', "Tag <span class='dark:text-warning'>$tag</span> is invalid. Min length is 2.");
continue;
}
if ($this->resource->tags()->where('name', $tag)->exists()) {
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$tag</span> already added.");
continue;
}
$found = Tag::ownedByCurrentTeam()->where(['name' => $tag])->exists();
if (! $found) {
$found = Tag::create([
'name' => $tag,
'team_id' => currentTeam()->id,
]);
}
$this->resource->tags()->attach($found->id);
}
$this->refresh();
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function addTag(string $id, string $name)
@ -39,8 +70,9 @@ public function addTag(string $id, string $name)
return;
}
$this->resource->tags()->syncWithoutDetaching($id);
$this->resource->tags()->attach($id);
$this->refresh();
$this->dispatch('success', 'Tag added.');
} catch (\Exception $e) {
return handleError($e, $this);
}
@ -50,12 +82,12 @@ public function deleteTag(string $id)
{
try {
$this->resource->tags()->detach($id);
$found_more_tags = Tag::where(['id' => $id, 'team_id' => currentTeam()->id])->first();
if ($found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) {
$found_more_tags = Tag::ownedByCurrentTeam()->find($id);
if ($found_more_tags && $found_more_tags->applications()->count() == 0 && $found_more_tags->services()->count() == 0) {
$found_more_tags->delete();
}
$this->refresh();
$this->dispatch('success', 'Tag deleted.');
} catch (\Exception $e) {
return handleError($e, $this);
}
@ -63,41 +95,8 @@ public function deleteTag(string $id)
public function refresh()
{
$this->resource->load(['tags']);
$this->tags = Tag::ownedByCurrentTeam()->get();
$this->new_tag = null;
}
public function submit()
{
try {
$this->validate([
'new_tag' => 'required|string|min:2',
]);
$tags = str($this->new_tag)->trim()->explode(' ');
foreach ($tags as $tag) {
if ($this->resource->tags()->where('name', $tag)->exists()) {
$this->dispatch('error', 'Duplicate tags.', "Tag <span class='dark:text-warning'>$tag</span> already added.");
continue;
}
$found = Tag::where(['name' => $tag, 'team_id' => currentTeam()->id])->first();
if (! $found) {
$found = Tag::create([
'name' => $tag,
'team_id' => currentTeam()->id,
]);
}
$this->resource->tags()->syncWithoutDetaching($found->id);
}
$this->refresh();
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function render()
{
return view('livewire.project.shared.tags');
$this->resource->refresh(); // Remove this when legacy_model_binding is false
$this->loadTags();
$this->reset('newTags');
}
}

View File

@ -4,49 +4,61 @@
use Livewire\Component;
// Refactored ✅
class Webhooks extends Component
{
public $resource;
public ?string $deploywebhook = null;
public ?string $deploywebhook;
public ?string $githubManualWebhook = null;
public ?string $githubManualWebhook;
public ?string $gitlabManualWebhook = null;
public ?string $gitlabManualWebhook;
public ?string $bitbucketManualWebhook = null;
public ?string $bitbucketManualWebhook;
public ?string $giteaManualWebhook = null;
public ?string $giteaManualWebhook;
protected $rules = [
'resource.manual_webhook_secret_github' => 'nullable|string',
'resource.manual_webhook_secret_gitlab' => 'nullable|string',
'resource.manual_webhook_secret_bitbucket' => 'nullable|string',
'resource.manual_webhook_secret_gitea' => 'nullable|string',
];
public ?string $githubManualWebhookSecret = null;
public function saveSecret()
public ?string $gitlabManualWebhookSecret = null;
public ?string $bitbucketManualWebhookSecret = null;
public ?string $giteaManualWebhookSecret = null;
public function mount()
{
// ray()->clearAll();
// ray()->showQueries();
$this->deploywebhook = generateDeployWebhook($this->resource);
$this->githubManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_github');
$this->githubManualWebhook = generateGitManualWebhook($this->resource, 'github');
$this->gitlabManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_gitlab');
$this->gitlabManualWebhook = generateGitManualWebhook($this->resource, 'gitlab');
$this->bitbucketManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_bitbucket');
$this->bitbucketManualWebhook = generateGitManualWebhook($this->resource, 'bitbucket');
$this->giteaManualWebhookSecret = data_get($this->resource, 'manual_webhook_secret_gitea');
$this->giteaManualWebhook = generateGitManualWebhook($this->resource, 'gitea');
}
public function submit()
{
try {
$this->validate();
$this->resource->save();
$this->authorize('update', $this->resource);
$this->resource->update([
'manual_webhook_secret_github' => $this->githubManualWebhookSecret,
'manual_webhook_secret_gitlab' => $this->gitlabManualWebhookSecret,
'manual_webhook_secret_bitbucket' => $this->bitbucketManualWebhookSecret,
'manual_webhook_secret_gitea' => $this->giteaManualWebhookSecret,
]);
$this->dispatch('success', 'Secret Saved.');
} catch (\Exception $e) {
return handleError($e, $this);
}
}
public function mount()
{
$this->deploywebhook = generateDeployWebhook($this->resource);
$this->githubManualWebhook = generateGitManualWebhook($this->resource, 'github');
$this->gitlabManualWebhook = generateGitManualWebhook($this->resource, 'gitlab');
$this->bitbucketManualWebhook = generateGitManualWebhook($this->resource, 'bitbucket');
$this->giteaManualWebhook = generateGitManualWebhook($this->resource, 'gitea');
}
public function render()
{
return view('livewire.project.shared.webhooks');
}
}

View File

@ -18,7 +18,7 @@ class Index extends Component
public function mount()
{
if (isInstanceAdmin()) {
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$database = StandalonePostgresql::whereName('coolify-db')->first();
$s3s = S3Storage::whereTeamId(0)->get() ?? [];
if ($database) {

View File

@ -29,7 +29,7 @@ public function mount()
abort(404);
}
$this->instance_id = config('app.id');
$this->settings = InstanceSettings::get();
$this->settings = \App\Models\InstanceSettings::get();
}
public function render()

View File

@ -4,7 +4,6 @@
use App\Jobs\GithubAppPermissionJob;
use App\Models\GithubApp;
use App\Models\InstanceSettings;
use Illuminate\Support\Facades\Http;
use Livewire\Component;
@ -100,7 +99,7 @@ public function mount()
return redirect()->route('source.all');
}
$this->applications = $this->github_app->applications;
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$this->github_app->makeVisible('client_secret')->makeVisible('webhook_secret');
$this->name = str($this->github_app->name)->kebab();

View File

@ -23,7 +23,7 @@ public function mount()
if (data_get(currentTeam(), 'subscription') && isSubscriptionActive()) {
return redirect()->route('subscription.show');
}
$this->settings = InstanceSettings::get();
$this->settings = \App\Models\InstanceSettings::get();
$this->alreadySubscribed = currentTeam()->subscription()->exists();
}

View File

@ -318,7 +318,7 @@ public function setupDefault404Redirect()
public function setupDynamicProxyConfiguration()
{
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$dynamic_config_path = $this->proxyPath().'/dynamic';
if ($this->proxyType() === 'TRAEFIK_V2') {
$file = "$dynamic_config_path/coolify.yaml";

View File

@ -2,7 +2,6 @@
namespace App\Notifications\Channels;
use App\Models\InstanceSettings;
use App\Models\User;
use Exception;
use Illuminate\Mail\Message;
@ -14,7 +13,7 @@ class TransactionalEmailChannel
{
public function send(User $notifiable, Notification $notification): void
{
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (! data_get($settings, 'smtp_enabled') && ! data_get($settings, 'resend_enabled')) {
Log::info('SMTP/Resend not enabled');

View File

@ -18,7 +18,7 @@ class ResetPassword extends Notification
public function __construct($token)
{
$this->settings = InstanceSettings::get();
$this->settings = \App\Models\InstanceSettings::get();
$this->token = $token;
}

View File

@ -2,8 +2,10 @@
namespace App\Providers;
use App\Models\InstanceSettings;
use App\Models\PersonalAccessToken;
use Illuminate\Support\Facades\Http;
use Illuminate\Support\Facades\View;
use Illuminate\Support\ServiceProvider;
use Laravel\Sanctum\Sanctum;
@ -14,6 +16,7 @@ public function register(): void {}
public function boot(): void
{
Sanctum::usePersonalAccessTokenModel(PersonalAccessToken::class);
Http::macro('github', function (string $api_url, ?string $github_access_token = null) {
if ($github_access_token) {
return Http::withHeaders([
@ -27,5 +30,9 @@ public function boot(): void
])->baseUrl($api_url);
}
});
// if (! env('CI')) {
// View::share('instanceSettings', InstanceSettings::get());
// }
}
}

View File

@ -6,7 +6,6 @@
use App\Actions\Fortify\ResetUserPassword;
use App\Actions\Fortify\UpdateUserPassword;
use App\Actions\Fortify\UpdateUserProfileInformation;
use App\Models\InstanceSettings;
use App\Models\OauthSetting;
use App\Models\User;
use Illuminate\Cache\RateLimiting\Limit;
@ -45,7 +44,7 @@ public function boot(): void
{
Fortify::createUsersUsing(CreateNewUser::class);
Fortify::registerView(function () {
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (! $settings->is_registration_enabled) {
return redirect()->route('login');
}
@ -57,7 +56,7 @@ public function boot(): void
});
Fortify::loginView(function () {
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$enabled_oauth_providers = OauthSetting::where('enabled', true)->get();
$users = User::count();
if ($users == 0) {

View File

@ -40,6 +40,7 @@
'ubuntu debian raspbian',
'centos fedora rhel ol rocky amzn almalinux',
'sles opensuse-leap opensuse-tumbleweed',
'arch',
];
const SHARED_VARIABLE_TYPES = ['team', 'project', 'environment'];

View File

@ -244,13 +244,13 @@ function generate_application_name(string $git_repository, string $git_branch, ?
function is_transactional_emails_active(): bool
{
return isEmailEnabled(InstanceSettings::get());
return isEmailEnabled(\App\Models\InstanceSettings::get());
}
function set_transanctional_email_settings(?InstanceSettings $settings = null): ?string
{
if (! $settings) {
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
}
config()->set('mail.from.address', data_get($settings, 'smtp_from_address'));
config()->set('mail.from.name', data_get($settings, 'smtp_from_name'));
@ -284,7 +284,7 @@ function base_ip(): string
if (isDev()) {
return 'localhost';
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if ($settings->public_ipv4) {
return "$settings->public_ipv4";
}
@ -312,7 +312,7 @@ function getFqdnWithoutPort(string $fqdn)
*/
function base_url(bool $withPort = true): string
{
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if ($settings->fqdn) {
return $settings->fqdn;
}
@ -379,7 +379,7 @@ function send_internal_notification(string $message): void
}
function send_user_an_email(MailMessage $mail, string $email, ?string $cc = null): void
{
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$type = set_transanctional_email_settings($settings);
if (! $type) {
throw new Exception('No email settings found.');
@ -774,6 +774,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
$allServices = get_service_templates();
$topLevelVolumes = collect(data_get($yaml, 'volumes', []));
$topLevelNetworks = collect(data_get($yaml, 'networks', []));
$topLevelConfigs = collect(data_get($yaml, 'configs', []));
$topLevelSecrets = collect(data_get($yaml, 'secrets', []));
$services = data_get($yaml, 'services');
$generatedServiceFQDNS = collect([]);
@ -1402,6 +1404,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'services' => $services->toArray(),
'volumes' => $topLevelVolumes->toArray(),
'networks' => $topLevelNetworks->toArray(),
'configs' => $topLevelConfigs->toArray(),
'secrets' => $topLevelSecrets->toArray(),
];
$yaml = data_forget($yaml, 'services.*.volumes.*.content');
$resource->docker_compose_raw = Yaml::dump($yaml, 10, 2);
@ -1441,6 +1445,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
}
$topLevelNetworks = collect(data_get($yaml, 'networks', []));
$topLevelConfigs = collect(data_get($yaml, 'configs', []));
$topLevelSecrets = collect(data_get($yaml, 'secrets', []));
$services = data_get($yaml, 'services');
$generatedServiceFQDNS = collect([]);
@ -2027,14 +2033,20 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
domains: $fqdns,
serviceLabels: $serviceLabels,
generate_unique_uuid: $resource->build_pack === 'dockercompose',
image: data_get($service, 'image')
image: data_get($service, 'image'),
is_force_https_enabled: $resource->isForceHttpsEnabled(),
is_gzip_enabled: $resource->isGzipEnabled(),
is_stripprefix_enabled: $resource->isStripprefixEnabled(),
));
$serviceLabels = $serviceLabels->merge(fqdnLabelsForCaddy(
network: $resource->destination->network,
uuid: $resource->uuid,
domains: $fqdns,
serviceLabels: $serviceLabels,
image: data_get($service, 'image')
image: data_get($service, 'image'),
is_force_https_enabled: $resource->isForceHttpsEnabled(),
is_gzip_enabled: $resource->isGzipEnabled(),
is_stripprefix_enabled: $resource->isStripprefixEnabled(),
));
}
}
@ -2080,6 +2092,8 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
'services' => $services->toArray(),
'volumes' => $topLevelVolumes->toArray(),
'networks' => $topLevelNetworks->toArray(),
'configs' => $topLevelConfigs->toArray(),
'secrets' => $topLevelSecrets->toArray(),
];
if ($isSameDockerComposeFile) {
$resource->docker_compose_raw = Yaml::dump($yaml, 10, 2);
@ -2244,7 +2258,7 @@ function validate_dns_entry(string $fqdn, Server $server)
if (str($host)->contains('sslip.io')) {
return true;
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
$is_dns_validation_enabled = data_get($settings, 'is_dns_validation_enabled');
if (! $is_dns_validation_enabled) {
return true;
@ -2364,7 +2378,7 @@ function checkIfDomainIsAlreadyUsed(Collection|array $domains, ?string $teamId =
if ($domainFound) {
return true;
}
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (data_get($settings, 'fqdn')) {
$domain = data_get($settings, 'fqdn');
if (str($domain)->endsWith('/')) {
@ -2381,7 +2395,6 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null
if ($resource) {
if ($resource->getMorphClass() === 'App\Models\Application' && $resource->build_pack === 'dockercompose') {
$domains = data_get(json_decode($resource->docker_compose_domains, true), '*.domain');
ray($domains);
$domains = collect($domains);
} else {
$domains = collect($resource->fqdns);
@ -2437,7 +2450,7 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null
}
}
if ($resource) {
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (data_get($settings, 'fqdn')) {
$domain = data_get($settings, 'fqdn');
if (str($domain)->endsWith('/')) {
@ -2512,7 +2525,7 @@ function get_public_ips()
{
try {
echo "Refreshing public ips!\n";
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
[$first, $second] = Process::concurrently(function (Pool $pool) {
$pool->path(__DIR__)->command('curl -4s https://ifconfig.io');
$pool->path(__DIR__)->command('curl -6s https://ifconfig.io');

View File

@ -32,6 +32,7 @@
"poliander/cron": "^3.0",
"purplepixie/phpdns": "^2.1",
"pusher/pusher-php-server": "^7.2",
"resend/resend-laravel": "^0.13.0",
"sentry/sentry-laravel": "^4.6",
"socialiteproviders/microsoft-azure": "^5.1",
"spatie/laravel-activitylog": "^4.7.3",
@ -106,4 +107,4 @@
},
"minimum-stability": "stable",
"prefer-stable": true
}
}

128
composer.lock generated
View File

@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "c7c9cc002a9765c2395717c69ba8bfc6",
"content-hash": "cb17445966de6094aef5a92ee59d1d77",
"packages": [
{
"name": "amphp/amp",
@ -7129,6 +7129,132 @@
],
"time": "2024-07-01T14:24:45+00:00"
},
{
"name": "resend/resend-laravel",
"version": "v0.13.0",
"source": {
"type": "git",
"url": "https://github.com/resend/resend-laravel.git",
"reference": "23aed22df0d0b23c2952da2aaed6a8b88d301a8a"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/resend/resend-laravel/zipball/23aed22df0d0b23c2952da2aaed6a8b88d301a8a",
"reference": "23aed22df0d0b23c2952da2aaed6a8b88d301a8a",
"shasum": ""
},
"require": {
"illuminate/http": "^10.0|^11.0",
"illuminate/support": "^10.0|^11.0",
"php": "^8.1",
"resend/resend-php": "^0.12.0",
"symfony/mailer": "^6.2|^7.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.14",
"mockery/mockery": "^1.5",
"orchestra/testbench": "^8.17|^9.0",
"pestphp/pest": "^2.0"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "1.x-dev"
},
"laravel": {
"providers": [
"Resend\\Laravel\\ResendServiceProvider"
]
}
},
"autoload": {
"psr-4": {
"Resend\\Laravel\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Resend and contributors",
"homepage": "https://github.com/resend/resend-laravel/contributors"
}
],
"description": "Resend for Laravel",
"homepage": "https://resend.com/",
"keywords": [
"api",
"client",
"laravel",
"php",
"resend",
"sdk"
],
"support": {
"issues": "https://github.com/resend/resend-laravel/issues",
"source": "https://github.com/resend/resend-laravel/tree/v0.13.0"
},
"time": "2024-07-08T18:51:42+00:00"
},
{
"name": "resend/resend-php",
"version": "v0.12.0",
"source": {
"type": "git",
"url": "https://github.com/resend/resend-php.git",
"reference": "37fb79bb8160ce2de521bf37484ba59e89236521"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/resend/resend-php/zipball/37fb79bb8160ce2de521bf37484ba59e89236521",
"reference": "37fb79bb8160ce2de521bf37484ba59e89236521",
"shasum": ""
},
"require": {
"guzzlehttp/guzzle": "^7.5",
"php": "^8.1.0"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^3.13",
"mockery/mockery": "^1.6",
"pestphp/pest": "^2.0"
},
"type": "library",
"autoload": {
"files": [
"src/Resend.php"
],
"psr-4": {
"Resend\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Resend and contributors",
"homepage": "https://github.com/resend/resend-php/contributors"
}
],
"description": "Resend PHP library.",
"homepage": "https://resend.com/",
"keywords": [
"api",
"client",
"php",
"resend",
"sdk"
],
"support": {
"issues": "https://github.com/resend/resend-php/issues",
"source": "https://github.com/resend/resend-php/tree/v0.12.0"
},
"time": "2024-03-04T03:16:28+00:00"
},
{
"name": "revolt/event-loop",
"version": "v1.0.6",

View File

@ -7,7 +7,7 @@
// The release version of your application
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
'release' => '4.0.0-beta.309',
'release' => '4.0.0-beta.313',
// When left empty or `null` the Laravel environment will be used
'environment' => config('app.env'),

View File

@ -1,3 +1,3 @@
<?php
return '4.0.0-beta.309';
return '4.0.0-beta.313';

View File

@ -27,14 +27,14 @@ public function run(): void
$ipv4 = Process::run('curl -4s https://ifconfig.io')->output();
$ipv4 = trim($ipv4);
$ipv4 = filter_var($ipv4, FILTER_VALIDATE_IP);
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (is_null($settings->public_ipv4) && $ipv4) {
$settings->update(['public_ipv4' => $ipv4]);
}
$ipv6 = Process::run('curl -6s https://ifconfig.io')->output();
$ipv6 = trim($ipv6);
$ipv6 = filter_var($ipv6, FILTER_VALIDATE_IP);
$settings = InstanceSettings::get();
$settings = \App\Models\InstanceSettings::get();
if (is_null($settings->public_ipv6) && $ipv6) {
$settings->update(['public_ipv6' => $ipv6]);
}

View File

@ -17,6 +17,7 @@ ARG TARGETPLATFORM
# https://github.com/cloudflare/cloudflared/releases
ARG CLOUDFLARED_VERSION=2024.4.1
ARG POSTGRES_VERSION=15
ARG CI=true
WORKDIR /var/www/html

1
other/logos/latitude.svg Normal file
View File

@ -0,0 +1 @@
<svg xmlns="http://www.w3.org/2000/svg" width="349" height="64" fill="#ffffff" viewBox="0 0 349 64" ><path fill="#ffffff" d="M76.094 52V7.581h-6.917V52h6.917zM95.64 52.761c3.616 0 7.677-1.776 9.518-4.759V52h6.853V22.43h-6.853v3.997c-1.841-2.982-5.394-4.759-9.328-4.759-9.201 0-14.722 6.854-14.722 15.547 0 8.693 5.013 15.546 14.531 15.546zm1.015-6.155c-5.394 0-8.63-3.997-8.63-9.391s3.236-9.392 8.63-9.392c5.901 0 8.756 4.316 8.756 9.392s-2.855 9.391-8.756 9.391zM132.621 46.162c-2.729 0-4.315-.634-4.315-5.774V28.204h6.79V22.43h-6.79v-8.947h-6.917v8.947h-5.013v5.774h5.013v13.77c0 9.963 6.219 10.407 9.582 10.407 2.031 0 4.061-.19 5.14-.381v-6.092c-.698.127-2.411.254-3.49.254zM144.247 18.178c3.045 0 5.14-2.284 5.14-5.14 0-2.855-2.095-5.14-5.14-5.14-3.046 0-5.14 2.285-5.14 5.14 0 2.856 2.094 5.14 5.14 5.14zM147.673 52V22.43h-6.853V52h6.853zM168.299 46.162c-2.728 0-4.315-.634-4.315-5.774V28.204h6.79V22.43h-6.79v-8.947h-6.916v8.947h-5.013v5.774h5.013v13.77c0 9.963 6.218 10.407 9.581 10.407 2.031 0 4.061-.19 5.14-.381v-6.092c-.698.127-2.411.254-3.49.254zM187.159 52.761c4.251 0 7.361-1.713 9.137-4.886V52h6.917V22.43h-6.917v16.689c0 4.251-1.903 7.741-7.17 7.741-4.505 0-6.028-2.792-6.028-7.551v-16.88h-6.917v18.593c0 7.932 4.505 11.74 10.978 11.74zM232.247 26.427c-1.84-2.982-5.394-4.759-9.328-4.759-9.201 0-14.722 6.854-14.722 15.547 0 8.693 5.013 15.546 14.532 15.546 3.616 0 7.678-1.776 9.518-4.759V52h6.853V7.581h-6.853v18.846zm-8.503 20.18c-5.394 0-8.63-3.998-8.63-9.392 0-5.394 3.236-9.392 8.63-9.392 5.901 0 8.757 4.316 8.757 9.392s-2.856 9.391-8.757 9.391zM273.099 35.692c0-8.313-5.711-14.024-14.15-14.024-9.011 0-14.849 6.092-14.849 15.547 0 9.582 5.774 15.546 15.102 15.546 7.107 0 12.691-3.87 13.58-9.39h-6.98c-1.142 2.283-3.173 3.362-6.6 3.362-5.013 0-8.058-2.538-8.249-7.234h21.956c.127-1.65.19-2.601.19-3.807zm-22.146-1.46c.064-4.188 2.983-7.107 7.869-7.107 4.759 0 7.424 2.539 7.487 7.108h-15.356zM281.59 52.508c2.983 0 5.394-2.475 5.394-5.394s-2.411-5.33-5.394-5.33a5.321 5.321 0 00-5.33 5.33c0 2.919 2.348 5.394 5.33 5.394zM303.931 52.761c7.17 0 11.675-3.426 11.675-9.2 0-4.189-2.665-7.234-6.853-8.44l-5.901-1.713c-2.729-.762-3.681-1.84-3.681-3.427 0-1.777 1.777-3.046 4.252-3.046 3.236 0 5.14 1.46 5.14 3.934h6.789c0-5.71-4.441-9.2-11.675-9.2-6.6 0-11.359 3.68-11.359 8.693 0 4.188 2.348 7.17 6.473 8.312l5.901 1.587c3.173.825 3.871 1.84 3.871 3.49 0 2.094-1.65 3.49-4.252 3.49-3.553 0-6.028-1.777-6.028-4.315h-6.917c0 5.647 5.331 9.835 12.565 9.835zM337.5 21.668c-4.378 0-7.805 1.714-9.645 4.886V7.581h-6.916V52h6.916V35.755c0-5.203 2.538-8.185 7.044-8.185 4.822 0 6.472 2.728 6.472 9.01V52h6.917V33.408c0-7.742-3.681-11.74-10.788-11.74zM50.552 47.654l-5.29 15.762H14.805l5.29-15.762h30.457zM33.744.584H14.863L0 44.875h18.88L33.744.584z" data-darkreader-inline-fill="" style="--darkreader-inline-fill: #ffffff;"></path></svg>

After

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -8,7 +8,7 @@
@use('App\Models\InstanceSettings')
@php
$instanceSettings = InstanceSettings::first();
$instanceSettings = \App\Models\InstanceSettings::get();
$name = null;
if ($instanceSettings) {

View File

@ -109,7 +109,7 @@
<livewire:project.service.storage :resource="$application" />
</div>
<div x-cloak x-show="activeTab === 'webhooks'">
<livewire:project.shared.webhooks :resource="$application" />
<livewire:project.shared.webhooks :resource="$application" lazy />
</div>
<div x-cloak x-show="activeTab === 'previews'">
<livewire:project.application.previews :application="$application" />
@ -133,7 +133,7 @@
<livewire:project.shared.metrics :resource="$application" />
</div>
<div x-cloak x-show="activeTab === 'tags'">
<livewire:project.shared.tags :resource="$application" />
<livewire:project.shared.tags :resource="$application" lazy />
</div>
<div x-cloak x-show="activeTab === 'danger'">
<livewire:project.shared.danger :resource="$application" />

View File

@ -99,7 +99,7 @@
<livewire:project.shared.metrics :resource="$database" />
</div>
<div x-cloak x-show="activeTab === 'tags'">
<livewire:project.shared.tags :resource="$database" />
<livewire:project.shared.tags :resource="$database" lazy />
</div>
<div x-cloak x-show="activeTab === 'danger'">
<livewire:project.shared.danger :resource="$database" />

View File

@ -1,5 +1,5 @@
<x-forms.select wire:model.live="selectedEnvironment">
<option value="edit">Create/Edit Environments</option>
<option value="edit">Create / Edit</option>
<option disabled>-----</option>
@foreach ($environments as $environment)
<option value="{{ $environment->name }}">{{ $environment->name }}

View File

@ -13,7 +13,7 @@
it.</div>
@else
@if (!str($resource->status)->contains('running'))
<div class="alert alert-warning">Metrics are only available when the application is running!</div>
<div class="alert alert-warning">Metrics are only available when this resource is running!</div>
@else
<x-forms.select label="Interval" wire:change="setInterval" id="interval">
<option value="5">5 minutes (live)</option>

View File

@ -1,10 +1,18 @@
<div>
<h2>Tags</h2>
<div class="flex flex-wrap gap-2 pt-4">
@if (data_get($this->resource, 'tags'))
@forelse (data_get($this->resource,'tags') as $tagId => $tag)
<div
class="px-2 py-1 text-center rounded select-none dark:text-white w-fit bg-neutral-200 hover:bg-neutral-300 dark:bg-coolgray-100 dark:hover:bg-coolgray-200">
<form wire:submit='submit' class="flex items-end gap-2">
<div class="w-64">
<x-forms.input label="Create new or assign existing tags"
helper="You add more at once with space separated list: web api something<br><br>If the tag does not exists, it will be created."
wire:model="newTags" placeholder="example: prod app1 user" />
</div>
<x-forms.button type="submit">Add</x-forms.button>
</form>
@if (data_get($this->resource, 'tags') && count(data_get($this->resource, 'tags')) > 0)
<h3 class="pt-4">Assigned Tags</h3>
<div class="flex flex-wrap gap-2 pt-4">
@foreach (data_get($this->resource, 'tags') as $tagId => $tag)
<div class="button">
{{ $tag->name }}
<svg wire:click="deleteTag('{{ $tag->id }}')" xmlns="http://www.w3.org/2000/svg" fill="none"
viewBox="0 0 24 24"
@ -13,24 +21,14 @@ class="inline-block w-3 h-3 rounded cursor-pointer stroke-current hover:bg-red-5
</path>
</svg>
</div>
@empty
<div class="py-1">No tags yet</div>
@endforelse
@endif
</div>
<form wire:submit='submit' class="flex items-end gap-2 pt-4">
<div class="w-64">
<x-forms.input label="Create new or assign existing tags"
helper="You add more at once with space separated list: web api something<br><br>If the tag does not exists, it will be created."
wire:model="new_tag" />
@endforeach
</div>
<x-forms.button type="submit">Add</x-forms.button>
</form>
@if (count($tags) > 0)
@endif
@if (count($filteredTags) > 0)
<h3 class="pt-4">Exisiting Tags</h3>
<div>Click to add quickly</div>
<div class="flex flex-wrap gap-2 pt-4">
@foreach ($tags as $tag)
@foreach ($filteredTags as $tag)
<x-forms.button wire:click="addTag('{{ $tag->id }}','{{ $tag->name }}')">
{{ $tag->name }}</x-forms.button>
@endforeach

View File

@ -13,13 +13,13 @@
<div>
<h3>Manual Git Webhooks</h3>
@if ($githubManualWebhook && $gitlabManualWebhook)
<form wire:submit='saveSecret' class="flex flex-col gap-2">
<form wire:submit='submit' class="flex flex-col gap-2">
<div class="flex items-end gap-2">
<x-forms.input helper="Content Type in GitHub configuration could be json or form-urlencoded."
readonly label="GitHub" id="githubManualWebhook"></x-forms.input>
<x-forms.input type="password"
helper="Need to set a secret to be able to use this webhook. It should match with the secret in GitHub."
label="GitHub Webhook Secret" id="resource.manual_webhook_secret_github"></x-forms.input>
label="GitHub Webhook Secret" id="githubManualWebhookSecret"></x-forms.input>
</div>
<a target="_blank" class="flex hover:no-underline" href="{{ $resource?->gitWebhook }}">
@ -31,21 +31,19 @@
<x-forms.input readonly label="GitLab" id="gitlabManualWebhook"></x-forms.input>
<x-forms.input type="password"
helper="Need to set a secret to be able to use this webhook. It should match with the secret in GitLab."
label="GitLab Webhook Secret" id="resource.manual_webhook_secret_gitlab"></x-forms.input>
label="GitLab Webhook Secret" id="gitlabManualWebhookSecret"></x-forms.input>
</div>
<div class="flex gap-2">
<x-forms.input readonly label="Bitbucket" id="bitbucketManualWebhook"></x-forms.input>
<x-forms.input type="password"
helper="Need to set a secret to be able to use this webhook. It should match with the secret in Bitbucket."
label="Bitbucket Webhook Secret"
id="resource.manual_webhook_secret_bitbucket"></x-forms.input>
label="Bitbucket Webhook Secret" id="bitbucketManualWebhookSecret"></x-forms.input>
</div>
<div class="flex gap-2">
<x-forms.input readonly label="Gitea" id="giteaManualWebhook"></x-forms.input>
<x-forms.input type="password"
helper="Need to set a secret to be able to use this webhook. It should match with the secret in Gitea."
label="Gitea Webhook Secret"
id="resource.manual_webhook_secret_gitea"></x-forms.input>
label="Gitea Webhook Secret" id="giteaManualWebhookSecret"></x-forms.input>
</div>
<x-forms.button type="submit">Save</x-forms.button>
</form>

View File

@ -146,15 +146,13 @@ class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-1
</div>
<div class="flex items-center gap-2 pt-4 pb-2">
<h3>Sentinel</h3>
@if ($server->isSentinelEnabled())
<x-forms.button wire:click='restartSentinel'>Restart</x-forms.button>
@endif
{{-- @if ($server->isSentinelEnabled()) --}}
{{-- <x-forms.button wire:click='restartSentinel'>Restart</x-forms.button> --}}
{{-- @endif --}}
</div>
<div class="w-64">
<div>Metrics are disabled until a few bugs are fixed.</div>
{{-- <div class="w-64">
<x-forms.checkbox instantSave id="server.settings.is_metrics_enabled" label="Enable Metrics" />
{{-- <x-forms.checkbox instantSave id="server.settings.is_server_api_enabled" label="Enable Server API"
helper="You need to open port 12172 on your firewall. This API will be used to gather data from your server, which makes Coolify a lot faster than relying on SSH connections." />
<x-forms.button wire:click='checkPortForServerApi'>Check Port for Server API</x-forms.button> --}}
</div>
<div class="pt-4">
<div class="flex flex-wrap gap-2 sm:flex-nowrap">
@ -166,7 +164,7 @@ class="w-full mt-8 mb-4 font-bold box-without-bg bg-coollabs hover:bg-coollabs-1
<x-forms.input id="server.settings.metrics_history_days" label="Metrics history (days)" required
helper="How many days should the metrics data should be reserved." />
</div>
</div>
</div> --}}
@endif
</form>
</div>

View File

@ -12,13 +12,15 @@ services:
- SERVER_URL=$SERVICE_FQDN_TWENTY
- FRONT_BASE_URL=$SERVICE_FQDN_TWENTY
- ENABLE_DB_MIGRATIONS=true
- SIGN_IN_PREFILLED=false
- CACHE_STORAGE_TYPE=${CACHE_STORAGE_TYPE:-redis}
- REDIS_HOST=redis
- REDIS_PORT=6379
- STORAGE_TYPE=${STORAGE_TYPE:-local}
- STORAGE_S3_REGION=$STORAGE_S3_REGION
- STORAGE_S3_NAME=$STORAGE_S3_NAME
- STORAGE_S3_ENDPOINT=$STORAGE_S3_ENDPOINT
# https://twenty.com/developers/section/self-hosting/self-hosting-var#security
- API_RATE_LIMITING_TTL=${API_RATE_LIMITING_TTL:-100}
- API_RATE_LIMITING_LIMIT=${API_RATE_LIMITING_LIMIT:-100}
# https://twenty.com/developers/section/self-hosting/self-hosting-var#tokens
- ACCESS_TOKEN_SECRET=$SERVICE_BASE64_32_ACCESS
- LOGIN_TOKEN_SECRET=$SERVICE_BASE64_32_LOGIN
- REFRESH_TOKEN_SECRET=$SERVICE_BASE64_32_REFRESH
@ -26,6 +28,26 @@ services:
- POSTGRES_ADMIN_PASSWORD=$SERVICE_PASSWORD_POSTGRES
- PG_DATABASE_URL=postgres://postgres:$SERVICE_PASSWORD_POSTGRES@postgres:5432/default
# https://twenty.com/developers/section/self-hosting/self-hosting-var#auth
- IS_SIGN_UP_DISABLED=${IS_SIGN_UP_DISABLED:-false}
- PASSWORD_RESET_TOKEN_EXPIRES_IN=${PASSWORD_RESET_TOKEN_EXPIRES_IN:-5m}
# https://twenty.com/developers/section/self-hosting/self-hosting-var#workspace-cleaning
- WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION=$WORKSPACE_INACTIVE_DAYS_BEFORE_NOTIFICATION
- WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION=$WORKSPACE_INACTIVE_DAYS_BEFORE_DELETION
# https://twenty.com/developers/section/self-hosting/self-hosting-var#captcha
- STORAGE_TYPE=${STORAGE_TYPE:-local}
- STORAGE_S3_REGION=$STORAGE_S3_REGION
- STORAGE_S3_NAME=$STORAGE_S3_NAME
- STORAGE_S3_ENDPOINT=$STORAGE_S3_ENDPOINT
- STORAGE_S3_ACCESS_KEY_ID=$STORAGE_S3_ACCESS_KEY_ID
- STORAGE_S3_SECRET_ACCESS_KEY=$STORAGE_S3_SECRET_ACCESS_KEY
# https://twenty.com/developers/section/self-hosting/self-hosting-var#message-queue
- MESSAGE_QUEUE_TYPE=$MESSAGE_QUEUE_TYPE
# https://twenty.com/developers/section/self-hosting/self-hosting-var#email
- EMAIL_FROM_ADDRESS=$EMAIL_FROM_ADDRESS
- EMAIL_FROM_NAME=$EMAIL_FROM_NAME
- EMAIL_SYSTEM_ADDRESS=$EMAIL_SYSTEM_ADDRESS
@ -35,10 +57,12 @@ services:
- EMAIL_SMTP_USER=$EMAIL_SMTP_USER
- EMAIL_SMTP_PASSWORD=$EMAIL_SMTP_PASSWORD
# https://twenty.com/developers/section/self-hosting/self-hosting-var#debug-/-development
- SIGN_IN_PREFILLED=false
- DEBUG_MODE=${DEBUG_MODE:-false}
# https://twenty.com/developers/section/self-hosting/self-hosting-var#telemetry
- TELEMETRY_ENABLED=${TELEMETRY_ENABLED:-false}
- CACHE_STORAGE_TYPE=${CACHE_STORAGE_TYPE:-redis}
- REDIS_HOST=redis
- REDIS_PORT=6379
depends_on:
postgres:
condition: service_healthy

View File

@ -1,7 +1,7 @@
{
"coolify": {
"v4": {
"version": "4.0.0-beta.309"
"version": "4.0.0-beta.313"
}
}
}