@@ -27,6 +27,8 @@ class StartDatabaseProxy
|
||||
$server = data_get($database, 'destination.server');
|
||||
$containerName = data_get($database, 'uuid');
|
||||
$proxyContainerName = "{$database->uuid}-proxy";
|
||||
$isSSLEnabled = $database->enable_ssl ?? false;
|
||||
|
||||
if ($database->getMorphClass() === \App\Models\ServiceDatabase::class) {
|
||||
$databaseType = $database->databaseType();
|
||||
$network = $database->service->uuid;
|
||||
@@ -42,6 +44,12 @@ class StartDatabaseProxy
|
||||
'standalone-mongodb' => 27017,
|
||||
default => throw new \Exception("Unsupported database type: $databaseType"),
|
||||
};
|
||||
if ($isSSLEnabled) {
|
||||
$internalPort = match ($databaseType) {
|
||||
'standalone-redis', 'standalone-keydb', 'standalone-dragonfly' => 6380,
|
||||
default => throw new \Exception("Unsupported database type: $databaseType"),
|
||||
};
|
||||
}
|
||||
|
||||
$configuration_dir = database_proxy_dir($database->uuid);
|
||||
if (isDev()) {
|
||||
|
@@ -19,6 +19,7 @@ class StartService
|
||||
StopService::run(service: $service, dockerCleanup: false);
|
||||
}
|
||||
$service->saveComposeConfigs();
|
||||
$service->isConfigurationChanged(save: true);
|
||||
$commands[] = 'cd '.$service->workdir();
|
||||
$commands[] = "echo 'Saved configuration files to {$service->workdir()}.'";
|
||||
if ($pullLatestImages) {
|
||||
|
@@ -23,7 +23,7 @@ class CleanupInstanceStuffsJob implements ShouldBeEncrypted, ShouldBeUnique, Sho
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('cleanup-instance-stuffs'))->dontRelease()];
|
||||
return [(new WithoutOverlapping('cleanup-instance-stuffs'))->expireAfter(60)->dontRelease()];
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
|
@@ -31,7 +31,7 @@ class DockerCleanupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('docker-cleanup-'.$this->server->uuid))->dontRelease()];
|
||||
return [(new WithoutOverlapping('docker-cleanup-'.$this->server->uuid))->expireAfter(600)->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server, public bool $manualCleanup = false) {}
|
||||
|
@@ -70,7 +70,7 @@ class PushServerUpdateJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('push-server-update-'.$this->server->uuid))->dontRelease()];
|
||||
return [(new WithoutOverlapping('push-server-update-'.$this->server->uuid))->expireAfter(30)->dontRelease()];
|
||||
}
|
||||
|
||||
public function backoff(): int
|
||||
|
@@ -23,7 +23,7 @@ class RestartProxyJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('restart-proxy-'.$this->server->uuid))->dontRelease()];
|
||||
return [(new WithoutOverlapping('restart-proxy-'.$this->server->uuid))->expireAfter(60)->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
@@ -28,7 +28,7 @@ class ServerCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('server-check-'.$this->server->uuid))->dontRelease()];
|
||||
return [(new WithoutOverlapping('server-check-'.$this->server->uuid))->expireAfter(60)->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
@@ -19,11 +19,11 @@ class ServerPatchCheckJob implements ShouldBeEncrypted, ShouldQueue
|
||||
|
||||
public $tries = 3;
|
||||
|
||||
public $timeout = 600; // 10 minutes timeout
|
||||
public $timeout = 600;
|
||||
|
||||
public function middleware(): array
|
||||
{
|
||||
return [(new WithoutOverlapping('server-patch-check-'.$this->server->uuid))->dontRelease()];
|
||||
return [(new WithoutOverlapping('server-patch-check-'.$this->server->uuid))->expireAfter(600)->dontRelease()];
|
||||
}
|
||||
|
||||
public function __construct(public Server $server) {}
|
||||
|
@@ -56,7 +56,6 @@ class CloneMe extends Component
|
||||
$this->project_id = $this->project->id;
|
||||
$this->servers = currentTeam()
|
||||
->servers()
|
||||
->with('destinations')
|
||||
->get()
|
||||
->reject(fn ($server) => $server->isBuildServer());
|
||||
$this->newName = str($this->project->name.'-clone-'.(string) new Cuid2)->slug();
|
||||
|
@@ -63,7 +63,7 @@ class Heading extends Component
|
||||
$this->service->databases->each(function ($database) {
|
||||
$database->refresh();
|
||||
});
|
||||
if (is_null($this->service->config_hash) || $this->service->isConfigurationChanged()) {
|
||||
if (is_null($this->service->config_hash)) {
|
||||
$this->service->isConfigurationChanged(true);
|
||||
}
|
||||
$this->dispatch('configurationChanged');
|
||||
|
@@ -170,6 +170,7 @@ class Show extends Component
|
||||
$this->syncData(true);
|
||||
$this->dispatch('success', 'Environment variable updated.');
|
||||
$this->dispatch('envsUpdated');
|
||||
$this->dispatch('configurationChanged');
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e);
|
||||
}
|
||||
|
@@ -68,11 +68,16 @@ class Terminal extends Component
|
||||
|
||||
// Escape the identifier for shell usage
|
||||
$escapedIdentifier = escapeshellarg($identifier);
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$escapedIdentifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
$shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '.
|
||||
'if [ -f ~/.profile ]; then . ~/.profile; fi && '.
|
||||
'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi';
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$escapedIdentifier} sh -c '{$shellCommand}'");
|
||||
} else {
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n "$SHELL" ]; then exec $SHELL; else sh; fi');
|
||||
$shellCommand = 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && '.
|
||||
'if [ -f ~/.profile ]; then . ~/.profile; fi && '.
|
||||
'if [ -n "$SHELL" ] && [ -x "$SHELL" ]; then exec $SHELL; else sh; fi';
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, $shellCommand);
|
||||
}
|
||||
|
||||
// ssh command is sent back to frontend then to websocket
|
||||
// this is done because the websocket connection is not available here
|
||||
// a better solution would be to remove websocket on NodeJS and work with something like
|
||||
|
118
app/Livewire/Settings/Advanced.php
Normal file
118
app/Livewire/Settings/Advanced.php
Normal file
@@ -0,0 +1,118 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Auth;
|
||||
use Hash;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Advanced extends Component
|
||||
{
|
||||
#[Validate('required')]
|
||||
public Server $server;
|
||||
|
||||
public InstanceSettings $settings;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_registration_enabled;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $do_not_track;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_dns_validation_enabled;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $custom_dns_servers = null;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_api_enabled;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $allowed_ips = null;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_sponsorship_popup_enabled;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $disable_two_step_confirmation;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
if (! isInstanceAdmin()) {
|
||||
return redirect()->route('dashboard');
|
||||
}
|
||||
$this->server = Server::findOrFail(0);
|
||||
$this->settings = instanceSettings();
|
||||
$this->custom_dns_servers = $this->settings->custom_dns_servers;
|
||||
$this->allowed_ips = $this->settings->allowed_ips;
|
||||
$this->do_not_track = $this->settings->do_not_track;
|
||||
$this->is_registration_enabled = $this->settings->is_registration_enabled;
|
||||
$this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
|
||||
$this->is_api_enabled = $this->settings->is_api_enabled;
|
||||
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
|
||||
$this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->validate();
|
||||
|
||||
$this->custom_dns_servers = str($this->custom_dns_servers)->replaceEnd(',', '')->trim();
|
||||
$this->custom_dns_servers = str($this->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
|
||||
return str($dns)->trim()->lower();
|
||||
})->unique()->implode(',');
|
||||
|
||||
$this->allowed_ips = str($this->allowed_ips)->replaceEnd(',', '')->trim();
|
||||
$this->allowed_ips = str($this->allowed_ips)->trim()->explode(',')->map(function ($ip) {
|
||||
return str($ip)->trim();
|
||||
})->unique()->implode(',');
|
||||
|
||||
$this->instantSave();
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
$this->settings->is_registration_enabled = $this->is_registration_enabled;
|
||||
$this->settings->do_not_track = $this->do_not_track;
|
||||
$this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
|
||||
$this->settings->custom_dns_servers = $this->custom_dns_servers;
|
||||
$this->settings->is_api_enabled = $this->is_api_enabled;
|
||||
$this->settings->allowed_ips = $this->allowed_ips;
|
||||
$this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
|
||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
|
||||
$this->settings->save();
|
||||
$this->dispatch('success', 'Settings updated!');
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleTwoStepConfirmation($password): bool
|
||||
{
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true;
|
||||
$this->settings->save();
|
||||
$this->dispatch('success', 'Two step confirmation has been disabled.');
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.advanced');
|
||||
}
|
||||
}
|
@@ -2,11 +2,8 @@
|
||||
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Jobs\CheckForUpdatesJob;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Livewire\Attributes\Computed;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
@@ -15,10 +12,7 @@ class Index extends Component
|
||||
{
|
||||
public InstanceSettings $settings;
|
||||
|
||||
protected Server $server;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_auto_update_enabled;
|
||||
public Server $server;
|
||||
|
||||
#[Validate('nullable|string|max:255')]
|
||||
public ?string $fqdn = null;
|
||||
@@ -29,48 +23,18 @@ class Index extends Component
|
||||
#[Validate('required|integer|min:1025|max:65535')]
|
||||
public int $public_port_max;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $custom_dns_servers = null;
|
||||
|
||||
#[Validate('nullable|string|max:255')]
|
||||
public ?string $instance_name = null;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $allowed_ips = null;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $public_ipv4 = null;
|
||||
|
||||
#[Validate('nullable|string')]
|
||||
public ?string $public_ipv6 = null;
|
||||
|
||||
#[Validate('string')]
|
||||
public string $auto_update_frequency;
|
||||
|
||||
#[Validate('string|required')]
|
||||
public string $update_check_frequency;
|
||||
|
||||
#[Validate('required|string|timezone')]
|
||||
public string $instance_timezone;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $do_not_track;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_registration_enabled;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_dns_validation_enabled;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_api_enabled;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $disable_two_step_confirmation;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_sponsorship_popup_enabled;
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.index');
|
||||
@@ -80,27 +44,16 @@ class Index extends Component
|
||||
{
|
||||
if (! isInstanceAdmin()) {
|
||||
return redirect()->route('dashboard');
|
||||
} else {
|
||||
}
|
||||
$this->settings = instanceSettings();
|
||||
$this->server = Server::findOrFail(0);
|
||||
$this->fqdn = $this->settings->fqdn;
|
||||
$this->public_port_min = $this->settings->public_port_min;
|
||||
$this->public_port_max = $this->settings->public_port_max;
|
||||
$this->custom_dns_servers = $this->settings->custom_dns_servers;
|
||||
$this->instance_name = $this->settings->instance_name;
|
||||
$this->allowed_ips = $this->settings->allowed_ips;
|
||||
$this->public_ipv4 = $this->settings->public_ipv4;
|
||||
$this->public_ipv6 = $this->settings->public_ipv6;
|
||||
$this->do_not_track = $this->settings->do_not_track;
|
||||
$this->is_auto_update_enabled = $this->settings->is_auto_update_enabled;
|
||||
$this->is_registration_enabled = $this->settings->is_registration_enabled;
|
||||
$this->is_dns_validation_enabled = $this->settings->is_dns_validation_enabled;
|
||||
$this->is_api_enabled = $this->settings->is_api_enabled;
|
||||
$this->auto_update_frequency = $this->settings->auto_update_frequency;
|
||||
$this->update_check_frequency = $this->settings->update_check_frequency;
|
||||
$this->instance_timezone = $this->settings->instance_timezone;
|
||||
$this->disable_two_step_confirmation = $this->settings->disable_two_step_confirmation;
|
||||
$this->is_sponsorship_popup_enabled = $this->settings->is_sponsorship_popup_enabled;
|
||||
}
|
||||
}
|
||||
|
||||
#[Computed]
|
||||
@@ -115,30 +68,13 @@ class Index extends Component
|
||||
public function instantSave($isSave = true)
|
||||
{
|
||||
$this->validate();
|
||||
if ($this->settings->is_auto_update_enabled === true) {
|
||||
$this->validate([
|
||||
'auto_update_frequency' => ['required', 'string'],
|
||||
]);
|
||||
}
|
||||
|
||||
$this->settings->fqdn = $this->fqdn;
|
||||
$this->settings->public_port_min = $this->public_port_min;
|
||||
$this->settings->public_port_max = $this->public_port_max;
|
||||
$this->settings->custom_dns_servers = $this->custom_dns_servers;
|
||||
$this->settings->instance_name = $this->instance_name;
|
||||
$this->settings->allowed_ips = $this->allowed_ips;
|
||||
$this->settings->public_ipv4 = $this->public_ipv4;
|
||||
$this->settings->public_ipv6 = $this->public_ipv6;
|
||||
$this->settings->do_not_track = $this->do_not_track;
|
||||
$this->settings->is_auto_update_enabled = $this->is_auto_update_enabled;
|
||||
$this->settings->is_registration_enabled = $this->is_registration_enabled;
|
||||
$this->settings->is_dns_validation_enabled = $this->is_dns_validation_enabled;
|
||||
$this->settings->is_api_enabled = $this->is_api_enabled;
|
||||
$this->settings->auto_update_frequency = $this->auto_update_frequency;
|
||||
$this->settings->update_check_frequency = $this->update_check_frequency;
|
||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation;
|
||||
$this->settings->instance_timezone = $this->instance_timezone;
|
||||
$this->settings->is_sponsorship_popup_enabled = $this->is_sponsorship_popup_enabled;
|
||||
if ($isSave) {
|
||||
$this->settings->save();
|
||||
$this->dispatch('success', 'Settings updated!');
|
||||
@@ -149,7 +85,6 @@ class Index extends Component
|
||||
{
|
||||
try {
|
||||
$error_show = false;
|
||||
$this->server = Server::findOrFail(0);
|
||||
$this->resetErrorBag();
|
||||
|
||||
if (! validate_timezone($this->instance_timezone)) {
|
||||
@@ -166,46 +101,15 @@ class Index extends Component
|
||||
}
|
||||
$this->validate();
|
||||
|
||||
if ($this->is_auto_update_enabled && ! validate_cron_expression($this->auto_update_frequency)) {
|
||||
$this->dispatch('error', 'Invalid Cron / Human expression for Auto Update Frequency.');
|
||||
if (empty($this->auto_update_frequency)) {
|
||||
$this->auto_update_frequency = '0 0 * * *';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! validate_cron_expression($this->update_check_frequency)) {
|
||||
$this->dispatch('error', 'Invalid Cron / Human expression for Update Check Frequency.');
|
||||
if (empty($this->update_check_frequency)) {
|
||||
$this->update_check_frequency = '0 * * * *';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->settings->is_dns_validation_enabled && $this->settings->fqdn) {
|
||||
if (! validate_dns_entry($this->settings->fqdn, $this->server)) {
|
||||
$this->dispatch('error', "Validating DNS failed.<br><br>Make sure you have added the DNS records correctly.<br><br>{$this->settings->fqdn}->{$this->server->ip}<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
|
||||
if ($this->settings->is_dns_validation_enabled && $this->fqdn) {
|
||||
if (! validate_dns_entry($this->fqdn, $this->server)) {
|
||||
$this->dispatch('error', "Validating DNS failed.<br><br>Make sure you have added the DNS records correctly.<br><br>{$this->fqdn}->{$this->server->ip}<br><br>Check this <a target='_blank' class='underline dark:text-white' href='https://coolify.io/docs/knowledge-base/dns-configuration'>documentation</a> for further help.");
|
||||
$error_show = true;
|
||||
}
|
||||
}
|
||||
if ($this->settings->fqdn) {
|
||||
check_domain_usage(domain: $this->settings->fqdn);
|
||||
if ($this->fqdn) {
|
||||
check_domain_usage(domain: $this->fqdn);
|
||||
}
|
||||
$this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->replaceEnd(',', '')->trim();
|
||||
$this->settings->custom_dns_servers = str($this->settings->custom_dns_servers)->trim()->explode(',')->map(function ($dns) {
|
||||
return str($dns)->trim()->lower();
|
||||
});
|
||||
$this->settings->custom_dns_servers = $this->settings->custom_dns_servers->unique();
|
||||
$this->settings->custom_dns_servers = $this->settings->custom_dns_servers->implode(',');
|
||||
|
||||
$this->settings->allowed_ips = str($this->settings->allowed_ips)->replaceEnd(',', '')->trim();
|
||||
$this->settings->allowed_ips = str($this->settings->allowed_ips)->trim()->explode(',')->map(function ($ip) {
|
||||
return str($ip)->trim();
|
||||
});
|
||||
$this->settings->allowed_ips = $this->settings->allowed_ips->unique();
|
||||
$this->settings->allowed_ips = $this->settings->allowed_ips->implode(',');
|
||||
|
||||
$this->instantSave(isSave: false);
|
||||
|
||||
@@ -218,31 +122,4 @@ class Index extends Component
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkManually()
|
||||
{
|
||||
CheckForUpdatesJob::dispatchSync();
|
||||
$this->dispatch('updateAvailable');
|
||||
$settings = instanceSettings();
|
||||
if ($settings->new_version_available) {
|
||||
$this->dispatch('success', 'New version available!');
|
||||
} else {
|
||||
$this->dispatch('success', 'No new version available.');
|
||||
}
|
||||
}
|
||||
|
||||
public function toggleTwoStepConfirmation($password): bool
|
||||
{
|
||||
if (! Hash::check($password, Auth::user()->password)) {
|
||||
$this->addError('password', 'The provided password is incorrect.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->settings->disable_two_step_confirmation = $this->disable_two_step_confirmation = true;
|
||||
$this->settings->save();
|
||||
$this->dispatch('success', 'Two step confirmation has been disabled.');
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
101
app/Livewire/Settings/Updates.php
Normal file
101
app/Livewire/Settings/Updates.php
Normal file
@@ -0,0 +1,101 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Settings;
|
||||
|
||||
use App\Jobs\CheckForUpdatesJob;
|
||||
use App\Models\InstanceSettings;
|
||||
use App\Models\Server;
|
||||
use Livewire\Attributes\Validate;
|
||||
use Livewire\Component;
|
||||
|
||||
class Updates extends Component
|
||||
{
|
||||
public InstanceSettings $settings;
|
||||
|
||||
public Server $server;
|
||||
|
||||
#[Validate('string')]
|
||||
public string $auto_update_frequency;
|
||||
|
||||
#[Validate('string|required')]
|
||||
public string $update_check_frequency;
|
||||
|
||||
#[Validate('boolean')]
|
||||
public bool $is_auto_update_enabled;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->server = Server::findOrFail(0);
|
||||
|
||||
$this->settings = instanceSettings();
|
||||
$this->auto_update_frequency = $this->settings->auto_update_frequency;
|
||||
$this->update_check_frequency = $this->settings->update_check_frequency;
|
||||
$this->is_auto_update_enabled = $this->settings->is_auto_update_enabled;
|
||||
}
|
||||
|
||||
public function instantSave()
|
||||
{
|
||||
try {
|
||||
if ($this->settings->is_auto_update_enabled === true) {
|
||||
$this->validate([
|
||||
'auto_update_frequency' => ['required', 'string'],
|
||||
]);
|
||||
}
|
||||
$this->settings->auto_update_frequency = $this->auto_update_frequency;
|
||||
$this->settings->update_check_frequency = $this->update_check_frequency;
|
||||
$this->settings->is_auto_update_enabled = $this->is_auto_update_enabled;
|
||||
$this->settings->save();
|
||||
$this->dispatch('success', 'Settings updated!');
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
$this->resetErrorBag();
|
||||
$this->validate();
|
||||
|
||||
if ($this->is_auto_update_enabled && ! validate_cron_expression($this->auto_update_frequency)) {
|
||||
$this->dispatch('error', 'Invalid Cron / Human expression for Auto Update Frequency.');
|
||||
if (empty($this->auto_update_frequency)) {
|
||||
$this->auto_update_frequency = '0 0 * * *';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (! validate_cron_expression($this->update_check_frequency)) {
|
||||
$this->dispatch('error', 'Invalid Cron / Human expression for Update Check Frequency.');
|
||||
if (empty($this->update_check_frequency)) {
|
||||
$this->update_check_frequency = '0 * * * *';
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->instantSave();
|
||||
$this->server->setupDynamicProxyConfiguration();
|
||||
} catch (\Exception $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
}
|
||||
|
||||
public function checkManually()
|
||||
{
|
||||
CheckForUpdatesJob::dispatchSync();
|
||||
$this->dispatch('updateAvailable');
|
||||
$settings = instanceSettings();
|
||||
if ($settings->new_version_available) {
|
||||
$this->dispatch('success', 'New version available!');
|
||||
} else {
|
||||
$this->dispatch('success', 'No new version available.');
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.settings.updates');
|
||||
}
|
||||
}
|
@@ -46,7 +46,7 @@ class SettingsBackup extends Component
|
||||
{
|
||||
if (! isInstanceAdmin()) {
|
||||
return redirect()->route('dashboard');
|
||||
} else {
|
||||
}
|
||||
$settings = instanceSettings();
|
||||
$this->server = Server::findOrFail(0);
|
||||
$this->database = StandalonePostgresql::whereName('coolify-db')->first();
|
||||
@@ -72,7 +72,6 @@ class SettingsBackup extends Component
|
||||
$this->settings = $settings;
|
||||
$this->s3s = $s3s;
|
||||
}
|
||||
}
|
||||
|
||||
public function addCoolifyDatabase()
|
||||
{
|
||||
|
@@ -31,7 +31,7 @@ class Form extends Component
|
||||
'storage.endpoint' => 'Endpoint',
|
||||
];
|
||||
|
||||
public function test_s3_connection()
|
||||
public function testConnection()
|
||||
{
|
||||
try {
|
||||
$this->storage->testConnection(shouldSave: true);
|
||||
@@ -45,6 +45,8 @@ class Form extends Component
|
||||
public function delete()
|
||||
{
|
||||
try {
|
||||
$this->authorize('delete', $this->storage);
|
||||
|
||||
$this->storage->delete();
|
||||
|
||||
return redirect()->route('storage.index');
|
||||
@@ -57,7 +59,7 @@ class Form extends Component
|
||||
{
|
||||
$this->validate();
|
||||
try {
|
||||
$this->test_s3_connection();
|
||||
$this->testConnection();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
@@ -887,7 +887,7 @@ $schema://$host {
|
||||
|
||||
public function muxFilename()
|
||||
{
|
||||
return $this->uuid;
|
||||
return 'mux_'.$this->uuid;
|
||||
}
|
||||
|
||||
public function team()
|
||||
|
66
app/Policies/S3StoragePolicy.php
Normal file
66
app/Policies/S3StoragePolicy.php
Normal file
@@ -0,0 +1,66 @@
|
||||
<?php
|
||||
|
||||
namespace App\Policies;
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use App\Models\Server;
|
||||
use App\Models\User;
|
||||
|
||||
class S3StoragePolicy
|
||||
{
|
||||
/**
|
||||
* Determine whether the user can view any models.
|
||||
*/
|
||||
public function viewAny(User $user): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can view the model.
|
||||
*/
|
||||
public function view(User $user, S3Storage $storage): bool
|
||||
{
|
||||
return $user->teams()->where('id', $storage->team_id)->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create models.
|
||||
*/
|
||||
public function create(User $user): bool
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can update the model.
|
||||
*/
|
||||
public function update(User $user, Server $server): bool
|
||||
{
|
||||
return $user->teams()->get()->firstWhere('id', $server->team_id) !== null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can delete the model.
|
||||
*/
|
||||
public function delete(User $user, S3Storage $storage): bool
|
||||
{
|
||||
return $user->teams()->where('id', $storage->team_id)->exists();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can restore the model.
|
||||
*/
|
||||
public function restore(User $user, S3Storage $storage): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can permanently delete the model.
|
||||
*/
|
||||
public function forceDelete(User $user, S3Storage $storage): bool
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
@@ -2,7 +2,7 @@
|
||||
|
||||
return [
|
||||
'coolify' => [
|
||||
'version' => '4.0.0-beta.420.1',
|
||||
'version' => '4.0.0-beta.420.2',
|
||||
'helper_version' => '1.0.8',
|
||||
'realtime_version' => '1.0.9',
|
||||
'self_hosted' => env('SELF_HOSTED', true),
|
||||
|
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.420"
|
||||
"version": "4.0.0-beta.420.2"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.0.0-beta.421"
|
||||
"version": "4.0.0-beta.420.3"
|
||||
},
|
||||
"helper": {
|
||||
"version": "1.0.8"
|
||||
|
7
public/svgs/excalidraw.svg
Normal file
7
public/svgs/excalidraw.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1000" height="1000">
|
||||
<rect width="1000" height="1000" rx="200" ry="200" fill="#fff" />
|
||||
<svg viewBox="0 0 107 101" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2">
|
||||
<path style="fill:none" d="M24 17h121v121H24z" transform="matrix(.8843 0 0 .83471 -21.223 -14.19)" />
|
||||
<path d="M119.81 105.98a.549.549 0 0 0-.53-.12c-4.19-6.19-9.52-12.06-14.68-17.73l-.85-.93c0-.11-.05-.21-.12-.3a.548.548 0 0 0-.34-.2l-.17-.18-.12-.09c-.15-.32-.53-.56-.95-.35-1.58.81-3 1.97-4.4 3.04-1.87 1.43-3.7 2.92-5.42 4.52-.7.65-1.39 1.33-1.97 2.09-.28.37-.07.72.27.87-1.22 1.2-2.45 2.45-3.68 3.74-.11.12-.17.28-.16.44.01.16.09.31.22.41l2.16 1.65s.01.03.03.04c3.09 3.05 8.51 7.28 14.25 11.76.85.67 1.71 1.34 2.57 2.01.39.47.76.94 1.12 1.4.19.25.55.3.8.11.13.1.26.21.39.31a.57.57 0 0 0 .8-.1c.07-.09.1-.2.11-.31.04 0 .07.03.1.03.15 0 .31-.06.42-.18l10.18-11.12a.56.56 0 0 0-.04-.8l.01-.01Zm-29.23-3.85c.07.09.14.17.21.25 1.16.98 2.4 2.04 3.66 3.12l-5.12-3.91s-.32-.22-.52-.36c-.11-.08-.21-.16-.31-.24l-.38-.32s.07-.07.1-.11l.35-.35c1.72-1.74 4.67-4.64 6.19-6.06-1.61 1.62-4.87 6.37-4.17 7.98h-.01Zm17.53 13.81-4.22-3.22c-1.65-1.71-3.43-3.4-5.24-5.03 2.28 1.76 4.23 3.25 4.52 3.51 2.21 1.97 2.11 1.61 3.63 2.91l1.83 1.33c-.18.16-.36.33-.53.49l.01.01Zm1.06.81-.08-.06c.16-.13.33-.25.49-.38l-.4.44h-.01ZM42.24 51.45c.14.72.27 1.43.4 2.11.69 3.7 1.33 7.03 2.55 9.56l.48 1.92c.19.73.46 1.64.71 1.83 2.85 2.52 7.22 6.28 11.89 9.82.21.16.5.15.7-.01.01.02.03.03.04.04.11.1.24.15.38.15.16 0 .31-.06.42-.19 5.98-6.65 10.43-12.12 13.6-16.7.2-.25.3-.54.29-.84.2-.24.41-.48.6-.68a.558.558 0 0 0-.1-.86.578.578 0 0 0-.17-.36c-1.39-1.34-2.42-2.31-3.46-3.28-1.84-1.72-3.74-3.5-7.77-7.51-.02-.02-.05-.04-.07-.06a.555.555 0 0 0-.22-.14c-1.11-.39-3.39-.78-6.26-1.28-4.22-.72-10-1.72-15.2-3.27h-.04v-.01s-.02 0-.03.02h-.01l.04-.02s-.31.01-.37.04c-.08.04-.14.09-.19.15-.05.06-.09.12-.47.2-.38.08.08 0 .11 0h-.11v.03c.07.34.05.58.16.97-.02.1.21 1.02.24 1.11l1.83 7.26h.03Zm30.95 6.54s-.03.04-.04.05l-.64-.71c.22.21.44.42.68.66Zm-7.09 9.39s-.07.08-.1.12l-.02-.02c.04-.03.08-.07.13-.1h-.01Zm-7.07 8.47Zm3.02-28.57c.35.35 1.74 1.65 2.06 1.97-1.45-.66-5.06-2.34-6.74-2.88 1.65.29 3.93.66 4.68.91Zm-19.18-2.77c.84 1.44 1.5 6.49 2.16 11.4-.37-1.58-.69-3.12-.99-4.6-.52-2.56-1-4.85-1.67-6.88.14.01.31.03.49.05 0 .01 0 .02.02.03h-.01Zm-.29-1.21c-.23-.02-.44-.04-.62-.05-.02-.04-.03-.08-.04-.12l.66.18v-.01Zm-2.22.45v-.02.02ZM118.9 42.57c.04-.23-1.1-1.24-.74-1.26.85-.04.86-1.35 0-1.31-1.13.06-2.27.32-3.37.53-1.98.37-3.95.78-5.92 1.21-4.39.94-8.77 1.93-13.1 3.11-1.36.37-2.86.7-4.11 1.36-.42.22-.4.67-.17.95-.09.05-.18.08-.28.09-.37.07-.74.13-1.11.19a.566.566 0 0 0-.39.86c-2.32 3.1-4.96 6.44-7.82 9.95-2.81 3.21-5.73 6.63-8.72 10.14-9.41 11.06-20.08 23.6-31.9 34.64-.23.21-.24.57-.03.8.05.06.12.1.19.13-.16.15-.32.3-.48.44-.1.09-.14.2-.16.32-.08.08-.16.17-.23.25-.21.23-.2.59.03.8.23.21.59.2.8-.03.04-.04.08-.09.12-.13a.84.84 0 0 1 1.22 0c.69.74 1.34 1.44 1.95 2.09l-1.38-1.15a.57.57 0 0 0-.8.07c-.2.24-.17.6.07.8l14.82 12.43c.11.09.24.13.37.13.15 0 .29-.06.4-.17l.36-.36a.56.56 0 0 0 .63-.12c20.09-20.18 36.27-35.43 54.8-49.06.17-.12.25-.32.23-.51a.57.57 0 0 0 .48-.39c3.42-10.46 4.08-19.72 4.28-24.27 0-.03.01-.05.02-.07.02-.05.03-.1.04-.14.03-.11.05-.19.05-.19.26-.78.17-1.53-.15-2.15v.02ZM82.98 58.94c.9-1.03 1.79-2.04 2.67-3.02-5.76 7.58-15.3 19.26-28.81 33.14 9.2-10.18 18.47-20.73 26.14-30.12Zm-32.55 52.81-.03-.03c.11.02.19.04.2.04a.47.47 0 0 0-.17 0v-.01Zm6.9 6.42-.05-.04.03-.03c.02 0 .03.02.04.02 0 .02-.02.03-.03.05h.01Zm8.36-7.21 1.38-1.44c.01.01.02.03.03.05-.47.46-.94.93-1.42 1.39h.01Zm2.24-2.21c.26-.3.56-.65.87-1.02.01-.01.02-.03.04-.04 3.29-3.39 6.68-6.82 10.18-10.25.02-.02.05-.04.07-.06.86-.66 1.82-1.39 2.72-2.08-4.52 4.32-9.11 8.78-13.88 13.46v-.01Zm21.65-55.88c-1.86 2.42-3.9 5.56-5.63 8.07-5.46 7.91-23.04 27.28-23.43 27.65-2.71 2.62-10.88 10.46-16.09 15.37-.14.13-.25.24-.34.35a.794.794 0 0 1 .03-1.13c24.82-23.4 39.88-42.89 46-51.38-.13.33-.24.69-.55 1.09l.01-.02Zm16.51 7.1-.01.02c0-.02-.02-.07.01-.02Zm-.91-5.13Zm-5.89 9.45c-2.26-1.31-3.32-3.27-2.71-5.25l.19-.66c.08-.19.17-.38.28-.57.59-.98 1.49-1.85 2.52-2.36.05-.02.1-.03.15-.04a.795.795 0 0 1-.04-.43c.05-.31.25-.58.66-.58.67 0 2.75.62 3.54 1.3.24.19.47.4.68.63.3.35.74.92.96 1.33.13.06.23.62.38.91.14.46.2.93.18 1.4 0 .02 0 .02.01.03-.03.07 0 .37-.04.4-.1.72-.36 1.43-.75 2.05-.04.05-.07.11-.11.16 0 .01-.02.02-.03.04-.3.43-.65.83-1.08 1.13-1.26.89-2.73 1.16-4.2.79a6.33 6.33 0 0 1-.57-.25l-.02-.03Zm16.27-1.63c-.49 2.05-1.09 4.19-1.8 6.38-.03.08-.03.16-.03.23-.1.01-.19.05-.27.11-4.44 3.26-8.73 6.62-12.98 10.11 3.67-3.32 7.39-6.62 11.23-9.95a6.409 6.409 0 0 0 2.11-3.74l.56-3.37.03-.1c.25-.71 1.34-.4 1.17.33h-.02Z" style="fill:#6965db;fill-rule:nonzero" transform="matrix(1 0 0 1 -26.41 -29.49)" />
|
||||
</svg>
|
||||
</svg>
|
After Width: | Height: | Size: 4.8 KiB |
@@ -42,7 +42,7 @@
|
||||
}
|
||||
|
||||
@utility button {
|
||||
@apply flex gap-2 justify-center items-center px-2 py-1 text-sm text-black normal-case rounded-sm border outline-0 cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-none disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
|
||||
@apply flex gap-2 justify-center items-center px-2 py-1 text-sm text-black normal-case rounded-sm border outline-0 cursor-pointer bg-neutral-200/50 border-neutral-300 hover:bg-neutral-300 dark:bg-coolgray-200 dark:text-white dark:hover:text-white dark:hover:bg-coolgray-500 dark:border-coolgray-300 hover:text-black disabled:cursor-not-allowed min-w-fit dark:disabled:text-neutral-600 disabled:border-transparent disabled:hover:bg-transparent disabled:bg-transparent disabled:text-neutral-300;
|
||||
}
|
||||
|
||||
@utility alert-success {
|
||||
|
@@ -5,19 +5,19 @@
|
||||
<nav class="flex items-center gap-6 min-h-10 whitespace-nowrap">
|
||||
<a class="{{ request()->routeIs('settings.index') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.index') }}">
|
||||
<button>Configuration</button>
|
||||
Configuration
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('settings.backup') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.backup') }}">
|
||||
<button>Backup</button>
|
||||
Backup
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('settings.email') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.email') }}">
|
||||
<button>Transactional Email</button>
|
||||
Transactional Email
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('settings.oauth') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('settings.oauth') }}">
|
||||
<button>OAuth</button>
|
||||
OAuth
|
||||
</a>
|
||||
<div class="flex-1"></div>
|
||||
</nav>
|
||||
|
8
resources/views/components/settings/sidebar.blade.php
Normal file
8
resources/views/components/settings/sidebar.blade.php
Normal file
@@ -0,0 +1,8 @@
|
||||
<div class="flex flex-col items-start gap-2 min-w-fit">
|
||||
<a class="menu-item {{ $activeMenu === 'general' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('settings.index') }}">General</a>
|
||||
<a class="menu-item {{ $activeMenu === 'advanced' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('settings.advanced') }}">Advanced</a>
|
||||
<a class="menu-item {{ $activeMenu === 'updates' ? 'menu-item-active' : '' }}"
|
||||
href="{{ route('settings.updates') }}">Updates</a>
|
||||
</div>
|
@@ -9,16 +9,16 @@
|
||||
<div class="navbar-main">
|
||||
<nav class="flex items-center gap-6 min-h-10">
|
||||
<a class="{{ request()->routeIs('team.index') ? 'dark:text-white' : '' }}" href="{{ route('team.index') }}">
|
||||
<button>General</button>
|
||||
General
|
||||
</a>
|
||||
<a class="{{ request()->routeIs('team.member.index') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('team.member.index') }}">
|
||||
<button>Members</button>
|
||||
Members
|
||||
</a>
|
||||
@if (isInstanceAdmin())
|
||||
<a class="{{ request()->routeIs('team.admin-view') ? 'dark:text-white' : '' }}"
|
||||
href="{{ route('team.admin-view') }}">
|
||||
<button>Admin View</button>
|
||||
Admin View
|
||||
</a>
|
||||
@endif
|
||||
<div class="flex-1"></div>
|
||||
|
@@ -63,12 +63,13 @@
|
||||
<section>
|
||||
<h3 class="pb-2">Servers</h3>
|
||||
@if ($servers->count() > 0)
|
||||
<div class="grid grid-cols-1 gap-2 xl:grid-cols-2">
|
||||
<div class="grid grid-cols-1 gap-4 xl:grid-cols-2">
|
||||
@foreach ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-red-500' => !$server->settings->is_reachable,
|
||||
'border-red-500' =>
|
||||
!$server->settings->is_reachable || $server->settings->force_disabled,
|
||||
])>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
|
@@ -11,13 +11,13 @@
|
||||
@endif
|
||||
</div>
|
||||
<div class="subtitle">Network endpoints to deploy your resources.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-1">
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
@forelse ($servers as $server)
|
||||
@forelse ($server->destinations() as $destination)
|
||||
@if ($destination->getMorphClass() === 'App\Models\StandaloneDocker')
|
||||
<a class="box group"
|
||||
href="{{ route('destination.show', ['destination_uuid' => data_get($destination, 'uuid')]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">{{ $destination->name }}</div>
|
||||
<div class="box-description">Server: {{ $destination->server->name }}</div>
|
||||
</div>
|
||||
|
@@ -2,5 +2,5 @@
|
||||
<x-modal-confirmation buttonFullWidth title="Confirm Team Deletion?" buttonTitle="Delete Team" isErrorButton
|
||||
submitAction="delete" :actions="['The current Team will be permanently deleted.']" confirmationText="{{ $team }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Team Name below"
|
||||
shortConfirmationLabel="Team Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Team Name" />
|
||||
</div>
|
||||
|
@@ -7,86 +7,101 @@
|
||||
<div class="subtitle ">Quickly clone all resources to a new project or environment.</div>
|
||||
</div>
|
||||
<x-forms.input required id="newName" label="New Name" />
|
||||
<x-forms.button isHighlighted wire:click="clone('project')" class="mt-4">Clone to a new Project</x-forms.button>
|
||||
<x-forms.button isHighlighted wire:click="clone('environment')" class="mt-4">Clone to a new Environment</x-forms.button>
|
||||
{{--
|
||||
<div class="mt-8">
|
||||
<h3 class="text-lg font-bold mb-2">Clone Volume Data</h3>
|
||||
<div class="text-sm text-gray-600 dark:text-gray-300 mb-4">
|
||||
Clone your volume data to the new resources volumes. This process requires a brief container downtime to ensure data consistency.
|
||||
</div>
|
||||
<div wire:poll>
|
||||
@if(!$cloneVolumeData)
|
||||
<div wire:key="volume-disabled">
|
||||
<x-modal-confirmation
|
||||
title="Enable Volume Data Cloning?"
|
||||
buttonTitle="Enable Volume Cloning"
|
||||
submitAction="toggleVolumeCloning(true)"
|
||||
:actions="['This will temporarily stop all the containers to copy the volume data to the new resources to ensure data consistency.', 'The process runs in the background and may take a few minutes.']"
|
||||
:confirmWithPassword="false"
|
||||
:confirmWithText="false"
|
||||
/>
|
||||
</div>
|
||||
@else
|
||||
<div wire:key="volume-enabled" class="max-w-md">
|
||||
<x-forms.checkbox
|
||||
label="Clone Volume Data"
|
||||
id="cloneVolumeData"
|
||||
wire:model="cloneVolumeData"
|
||||
wire:change="toggleVolumeCloning(false)"
|
||||
:checked="$cloneVolumeData"
|
||||
helper="Volume Data will be cloned to the new resources. Containers will be temporarily stopped during the cloning process." />
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</div> --}}
|
||||
|
||||
<h3 class="pt-8 pb-2">Servers</h3>
|
||||
<div>Choose the server and network to clone the resources to.</div>
|
||||
<div class="flex flex-col gap-4">
|
||||
@foreach ($servers->sortBy('id') as $server)
|
||||
<div class="p-4">
|
||||
<h4>{{ $server->name }}</h4>
|
||||
<div class="pt-4 pb-2">Docker Networks</div>
|
||||
<div class="grid grid-cols-1 gap-2 pb-4 lg:grid-cols-4">
|
||||
@foreach ($server->destinations() as $destination)
|
||||
<div class="cursor-pointer box-without-bg group"
|
||||
:class="'{{ $selectedDestination === $destination->id }}' ? 'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'"
|
||||
wire:click="selectServer('{{ $server->id }}', '{{ $destination->id }}')">
|
||||
{{ $destination->name }}
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
</div>
|
||||
|
||||
<h3 class="pt-8 pb-2">Resources</h3>
|
||||
<div>These will be cloned to the new project</div>
|
||||
<div class="grid grid-cols-1 gap-2 pt-4 opacity-95 lg:grid-cols-2 xl:grid-cols-3">
|
||||
@foreach ($environment->applications->sortBy('name') as $application)
|
||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
||||
<h3 class="pt-8 ">Destination Server</h3>
|
||||
<div class="pb-2">Choose the server and network to clone the resources to.</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="font-bold dark:text-white">{{ $application->name }}</div>
|
||||
<div class="description">{{ $application->description }}</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Server</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Network</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($servers->sortBy('id') as $server)
|
||||
@foreach ($server->destinations() as $destination)
|
||||
<tr class="cursor-pointer hover:bg-coolgray-50 dark:hover:bg-coolgray-200"
|
||||
wire:click="selectServer('{{ $server->id }}', '{{ $destination->id }}')">
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white"
|
||||
:class="'{{ $selectedDestination === $destination->id }}' ?
|
||||
'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'">
|
||||
{{ $server->name }}</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white "
|
||||
:class="'{{ $selectedDestination === $destination->id }}' ?
|
||||
'bg-coollabs text-white' : 'dark:bg-coolgray-100 bg-white'">
|
||||
{{ $destination->name }}
|
||||
</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<h3 class="pt-8">Resources</h3>
|
||||
<div class="pb-2">These will be cloned to the new project</div>
|
||||
<div class="flex flex-col pt-4">
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
<div class="inline-block min-w-full">
|
||||
<div class="overflow-hidden">
|
||||
<table class="min-w-full">
|
||||
<thead>
|
||||
<tr>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Name</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Type</th>
|
||||
<th class="px-5 py-3 text-xs font-medium text-left uppercase">Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
@foreach ($environment->applications->sortBy('name') as $application)
|
||||
<tr>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||
{{ $application->name }}</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Application</td>
|
||||
<td class="px-5 py-4 text-sm dark:text-white">
|
||||
{{ $application->description ?: '-' }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@foreach ($environment->databases()->sortBy('name') as $database)
|
||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
||||
<div class="flex flex-col">
|
||||
<div class="font-bold dark:text-white">{{ $database->name }}</div>
|
||||
<div class="description">{{ $database->description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||
{{ $database->name }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Database</td>
|
||||
<td class="px-5 py-4 text-sm dark:text-white">
|
||||
{{ $database->description ?: '-' }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
@foreach ($environment->services->sortBy('name') as $service)
|
||||
<div class="bg-white cursor-default box-without-bg dark:bg-coolgray-100 group">
|
||||
<div class="flex flex-col">
|
||||
<div class="font-bold dark:text-white">{{ $service->name }}</div>
|
||||
<div class="description">{{ $service->description }}</div>
|
||||
</div>
|
||||
</div>
|
||||
<tr>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap font-bold dark:text-white">
|
||||
{{ $service->name }}
|
||||
</td>
|
||||
<td class="px-5 py-4 text-sm whitespace-nowrap dark:text-white">Service</td>
|
||||
<td class="px-5 py-4 text-sm dark:text-white">
|
||||
{{ $service->description ?: '-' }}</td>
|
||||
</tr>
|
||||
@endforeach
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-4 pt-4 w-full">
|
||||
<x-forms.button isHighlighted class="w-full" wire:click="clone('project')" :disabled="!filled($selectedDestination)">Clone to new
|
||||
Project</x-forms.button>
|
||||
<x-forms.button isHighlighted class="w-full" wire:click="clone('environment')" :disabled="!filled($selectedDestination)">Clone to new
|
||||
Environment</x-forms.button>
|
||||
</div>
|
||||
</form>
|
||||
|
@@ -8,7 +8,8 @@
|
||||
@forelse($executions as $execution)
|
||||
<div wire:key="{{ data_get($execution, 'id') }}" @class([
|
||||
'flex flex-col border-l-2 transition-colors p-4 bg-white dark:bg-coolgray-100 text-black dark:text-white',
|
||||
'border-blue-500/50 border-dashed' => data_get($execution, 'status') === 'running',
|
||||
'border-blue-500/50 border-dashed' =>
|
||||
data_get($execution, 'status') === 'running',
|
||||
'border-error' => data_get($execution, 'status') === 'failed',
|
||||
'border-success' => data_get($execution, 'status') === 'success',
|
||||
])>
|
||||
@@ -20,16 +21,19 @@
|
||||
<div class="flex items-center gap-2 mb-2">
|
||||
<span @class([
|
||||
'px-3 py-1 rounded-md text-xs font-medium tracking-wide shadow-xs',
|
||||
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' => data_get($execution, 'status') === 'running',
|
||||
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' => data_get($execution, 'status') === 'failed',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' => data_get($execution, 'status') === 'success',
|
||||
'bg-blue-100/80 text-blue-700 dark:bg-blue-500/20 dark:text-blue-300 dark:shadow-blue-900/5' =>
|
||||
data_get($execution, 'status') === 'running',
|
||||
'bg-red-100 text-red-800 dark:bg-red-900/30 dark:text-red-200 dark:shadow-red-900/5' =>
|
||||
data_get($execution, 'status') === 'failed',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200 dark:shadow-green-900/5' =>
|
||||
data_get($execution, 'status') === 'success',
|
||||
])>
|
||||
@php
|
||||
$statusText = match (data_get($execution, 'status')) {
|
||||
'success' => 'Success',
|
||||
'running' => 'In Progress',
|
||||
'failed' => 'Failed',
|
||||
default => ucfirst(data_get($execution, 'status'))
|
||||
default => ucfirst(data_get($execution, 'status')),
|
||||
};
|
||||
@endphp
|
||||
{{ $statusText }}
|
||||
@@ -38,8 +42,10 @@
|
||||
<div class="text-gray-600 dark:text-gray-400 text-sm">
|
||||
Started: {{ formatDateInServerTimezone(data_get($execution, 'created_at'), $this->server()) }}
|
||||
@if (data_get($execution, 'status') !== 'running')
|
||||
<br>Ended: {{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}
|
||||
<br>Duration: {{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }}
|
||||
<br>Ended:
|
||||
{{ formatDateInServerTimezone(data_get($execution, 'finished_at'), $this->server()) }}
|
||||
<br>Duration:
|
||||
{{ calculateDuration(data_get($execution, 'created_at'), data_get($execution, 'finished_at')) }}
|
||||
<br>Finished {{ \Carbon\Carbon::parse(data_get($execution, 'finished_at'))->diffForHumans() }}
|
||||
@endif
|
||||
</div>
|
||||
@@ -60,17 +66,29 @@
|
||||
</div>
|
||||
<span @class([
|
||||
'px-2 py-1 rounded-sm text-xs font-medium',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get($execution, 'local_storage_deleted', false),
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 'local_storage_deleted', false),
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get(
|
||||
$execution,
|
||||
'local_storage_deleted',
|
||||
false),
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get(
|
||||
$execution,
|
||||
'local_storage_deleted',
|
||||
false),
|
||||
])>
|
||||
<span class="flex items-center gap-1">
|
||||
@if (!data_get($execution, 'local_storage_deleted', false))
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path>
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
@endif
|
||||
Local Storage
|
||||
@@ -79,17 +97,29 @@
|
||||
@if ($backup->save_s3)
|
||||
<span @class([
|
||||
'px-2 py-1 rounded-sm text-xs font-medium',
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get($execution, 's3_storage_deleted', false),
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get($execution, 's3_storage_deleted', false),
|
||||
'bg-green-100 text-green-800 dark:bg-green-900/30 dark:text-green-200' => !data_get(
|
||||
$execution,
|
||||
's3_storage_deleted',
|
||||
false),
|
||||
'bg-gray-100 text-gray-600 dark:bg-gray-800/50 dark:text-gray-400' => data_get(
|
||||
$execution,
|
||||
's3_storage_deleted',
|
||||
false),
|
||||
])>
|
||||
<span class="flex items-center gap-1">
|
||||
@if (!data_get($execution, 's3_storage_deleted', false))
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z" clip-rule="evenodd"></path>
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zm3.707-9.293a1 1 0 00-1.414-1.414L9 10.586 7.707 9.293a1 1 0 00-1.414 1.414l2 2a1 1 0 001.414 0l4-4z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
@else
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z" clip-rule="evenodd"></path>
|
||||
<svg class="w-3 h-3" fill="currentColor" viewBox="0 0 20 20"
|
||||
xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd"
|
||||
d="M10 18a8 8 0 100-16 8 8 0 000 16zM8.707 7.293a1 1 0 00-1.414 1.414L8.586 10l-1.293 1.293a1 1 0 101.414 1.414L10 11.414l1.293 1.293a1 1 0 001.414-1.414L11.414 10l1.293-1.293a1 1 0 00-1.414-1.414L10 8.586 8.707 7.293z"
|
||||
clip-rule="evenodd"></path>
|
||||
</svg>
|
||||
@endif
|
||||
S3 Storage
|
||||
@@ -108,11 +138,10 @@
|
||||
x-on:click="download_file('{{ data_get($execution, 'id') }}')">Download</x-forms.button>
|
||||
@endif
|
||||
<x-modal-confirmation title="Confirm Backup Deletion?" buttonTitle="Delete" isErrorButton
|
||||
submitAction="deleteBackup({{ data_get($execution, 'id') }})"
|
||||
:checkboxes="$checkboxes"
|
||||
submitAction="deleteBackup({{ data_get($execution, 'id') }})" :checkboxes="$checkboxes"
|
||||
:actions="['This backup will be permanently deleted from local storage.']" confirmationText="{{ data_get($execution, 'filename') }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Backup Filename below"
|
||||
shortConfirmationLabel="Backup Filename" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Backup Filename" 1 />
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
|
@@ -253,7 +253,8 @@
|
||||
@endif
|
||||
@if ($current_step === 'destinations')
|
||||
<h2>Select a destination</h2>
|
||||
<div>Destinations are used to segregate resources by network. If you are unsure, select the default
|
||||
<div class="pb-4">Destinations are used to segregate resources by network. If you are unsure, select the
|
||||
default
|
||||
Standalone Docker (coolify).</div>
|
||||
<div class="flex flex-col justify-center gap-4 text-left xl:flex-row xl:flex-wrap">
|
||||
@if ($server->isSwarm())
|
||||
|
@@ -11,11 +11,11 @@
|
||||
buttonTitle="Convert to Application" submitAction="convertToApplication" :actions="['The selected resource will be converted to an application.']"
|
||||
confirmationText="{{ Str::headline($database->name) }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
||||
shortConfirmationLabel="Service Database Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Service Database Name" />
|
||||
<x-modal-confirmation title="Confirm Service Database Deletion?" buttonTitle="Delete" isErrorButton
|
||||
submitAction="delete" :actions="['The selected service database container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($database->name) }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Database Name below"
|
||||
shortConfirmationLabel="Service Database Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Service Database Name" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
|
@@ -21,7 +21,7 @@
|
||||
]"
|
||||
confirmationText="{{ $fs_path }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
||||
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Filepath" />
|
||||
@else
|
||||
@if (!$fileStorage->is_binary)
|
||||
<x-modal-confirmation :ignoreWire="false" title="Confirm File Conversion to Directory?"
|
||||
@@ -37,7 +37,7 @@
|
||||
isErrorButton submitAction="delete" :checkboxes="$fileDeletionCheckboxes" :actions="['The selected file will be permanently deleted from the container.']"
|
||||
confirmationText="{{ $fs_path }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Filepath below"
|
||||
shortConfirmationLabel="Filepath" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Filepath" />
|
||||
@endif
|
||||
</div>
|
||||
@if (!$fileStorage->is_directory)
|
||||
|
@@ -11,11 +11,11 @@
|
||||
buttonTitle="Convert to Database" submitAction="convertToDatabase" :actions="['The selected resource will be converted to a service database.']"
|
||||
confirmationText="{{ Str::headline($application->name) }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
||||
shortConfirmationLabel="Service Application Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Service Application Name" />
|
||||
<x-modal-confirmation title="Confirm Service Application Deletion?" buttonTitle="Delete" isErrorButton
|
||||
submitAction="delete" :actions="['The selected service application container will be stopped and permanently deleted.']" confirmationText="{{ Str::headline($application->name) }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Service Application Name below"
|
||||
shortConfirmationLabel="Service Application Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Service Application Name" />
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
|
@@ -7,5 +7,5 @@
|
||||
<x-modal-confirmation title="Confirm Resource Deletion?" buttonTitle="Delete" isErrorButton submitAction="delete"
|
||||
buttonTitle="Delete" :checkboxes="$checkboxes" :actions="['Permanently delete all containers of this resource.']" confirmationText="{{ $resourceName }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Resource Name below"
|
||||
shortConfirmationLabel="Resource Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Resource Name" />
|
||||
</div>
|
||||
|
@@ -70,7 +70,7 @@
|
||||
'This will stop the all running applications on this server and remove it as a deployment destination.',
|
||||
]" confirmationText="{{ data_get($destination, 'server.name') }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Remove application from server" />
|
||||
shortConfirmationLabel="Server Name" />
|
||||
</div>
|
||||
</div>
|
||||
@endforeach
|
||||
|
@@ -48,10 +48,10 @@
|
||||
<x-forms.checkbox instantSave id="is_build_time"
|
||||
helper="If you are using Docker, remember to modify the file to be ready to receive the build time args. Ex.: for docker file, add `ARG name_of_the_variable`, or dockercompose add `- 'name_of_the_variable=${name_of_the_variable}'`"
|
||||
label="Is Build Variable?" />
|
||||
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
|
||||
<x-forms.checkbox instantSave id="is_literal"
|
||||
helper="This means that when you use $VARIABLES in a value, it should be interpreted as the actual characters '$VARIABLES' and not as the value of a variable named VARIABLE.<br><br>Useful if you have $ sign in your value and there are some characters after it, but you would not like to interpolate it from another value. In this case, you should set this to true."
|
||||
label="Is Literal?" />
|
||||
<x-forms.checkbox instantSave id="is_multiline" label="Is Multiline?" />
|
||||
@else
|
||||
@if ($is_shared)
|
||||
<x-forms.checkbox instantSave id="is_build_time"
|
||||
|
@@ -43,7 +43,7 @@
|
||||
|
||||
@if ($type === 'server')
|
||||
<livewire:server.navbar :server="$servers->first()" />
|
||||
@if ($servers->first()->isTerminalEnabled())
|
||||
@if ($servers->first()->isTerminalEnabled() && $servers->first()->isFunctional())
|
||||
<form class="w-full flex gap-2 items-start" wire:submit="$dispatchSelf('connectToServer')"
|
||||
wire:init="$dispatchSelf('connectToServer')">
|
||||
<h2 class="pb-4">Terminal</h2>
|
||||
@@ -54,7 +54,7 @@
|
||||
<livewire:project.shared.terminal />
|
||||
</div>
|
||||
@else
|
||||
<div>Terminal access is disabled on this server.</div>
|
||||
<div>Server is not functional or terminal access is disabled.</div>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
@@ -60,7 +60,7 @@
|
||||
'If the persistent storage/volume is actvily used by a resource data will be lost.',
|
||||
]" confirmationText="{{ $storage->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Storage Name below"
|
||||
shortConfirmationLabel="Storage Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Storage Name" />
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
|
@@ -1,6 +1,5 @@
|
||||
<div>
|
||||
<x-security.navbar />
|
||||
|
||||
<div class="flex gap-2">
|
||||
<h2 class="pb-4">Private Keys</h2>
|
||||
<x-modal-input buttonTitle="+ Add" title="New Private Key">
|
||||
@@ -9,18 +8,19 @@
|
||||
<x-modal-confirmation title="Confirm unused SSH Key Deletion?" buttonTitle="Delete unused SSH Keys" isErrorButton
|
||||
submitAction="cleanupUnusedKeys" :actions="['All unused SSH keys (marked with unused) are permanently deleted.']" :confirmWithText="false" :confirmWithPassword="false" />
|
||||
</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
@forelse ($privateKeys as $key)
|
||||
<a class="box group"
|
||||
href="{{ route('security.private-key.show', ['private_key_uuid' => data_get($key, 'uuid')]) }}">
|
||||
<div class="flex flex-col mx-6">
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ data_get($key, 'name') }}
|
||||
</div>
|
||||
<div class="box-description">
|
||||
{{ $key->description }}
|
||||
@if (!$key->isInUse())
|
||||
<span class="inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-yellow-400 text-black">Unused</span>
|
||||
<span
|
||||
class="inline-flex items-center px-2 py-0.5 rounded-sm text-xs font-medium bg-yellow-400 text-black">Unused</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
|
@@ -4,29 +4,30 @@
|
||||
</x-slot>
|
||||
<x-security.navbar />
|
||||
<div x-data="{ showPrivateKey: false }">
|
||||
<form class="flex flex-col gap-2" wire:submit='changePrivateKey'>
|
||||
<div class="flex items-end gap-2">
|
||||
<h2>Private Key</h2>
|
||||
<form class="flex flex-col" wire:submit='changePrivateKey'>
|
||||
<div class="flex items-start gap-2">
|
||||
<h2 class="pb-4">Private Key</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
@if (data_get($private_key, 'id') > 0)
|
||||
<x-modal-confirmation
|
||||
title="Confirm Private Key Deletion?"
|
||||
isErrorButton
|
||||
buttonTitle="Delete"
|
||||
submitAction="delete({{ $private_key->id }})"
|
||||
:actions="['This private key will be permanently deleted.', 'All servers connected to this private key will stop working.', 'Any git app using this private key will stop working.']"
|
||||
<x-modal-confirmation title="Confirm Private Key Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete({{ $private_key->id }})" :actions="[
|
||||
'This private key will be permanently deleted.',
|
||||
'All servers connected to this private key will stop working.',
|
||||
'Any git app using this private key will stop working.',
|
||||
]"
|
||||
confirmationText="{{ $private_key->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Private Key Name below"
|
||||
shortConfirmationLabel="Private Key Name"
|
||||
:confirmWithPassword="false"
|
||||
step2ButtonText="Delete Private Key"
|
||||
/>
|
||||
shortConfirmationLabel="Private Key Name" :confirmWithPassword="false"
|
||||
step2ButtonText="Delete Private Key" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="private_key.name" label="Name" required />
|
||||
<x-forms.input id="private_key.description" label="Description" />
|
||||
</div>
|
||||
<div>
|
||||
<div class="flex items-end gap-2 py-2 ">
|
||||
<div class="pl-1">Public Key</div>
|
||||
@@ -56,6 +57,7 @@
|
||||
<x-forms.textarea rows="10" id="private_key.private_key" required />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@@ -42,8 +42,7 @@
|
||||
]"
|
||||
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
||||
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
||||
shortConfirmationLabel="Confirmation text"
|
||||
step3ButtonText="Disable Cloudflare Tunnel" />
|
||||
shortConfirmationLabel="Confirmation text" />
|
||||
@else
|
||||
<x-modal-confirmation title="Disable Cloudflare Tunnel?"
|
||||
buttonTitle="Disable Cloudflare Tunnel" isErrorButton
|
||||
@@ -55,8 +54,7 @@
|
||||
]"
|
||||
confirmationText="DISABLE CLOUDFLARE TUNNEL"
|
||||
confirmationLabel="Please type the confirmation text to disable Cloudflare Tunnel."
|
||||
shortConfirmationLabel="Confirmation text"
|
||||
step3ButtonText="Disable Cloudflare Tunnel" />
|
||||
shortConfirmationLabel="Confirmation text" />
|
||||
@endif
|
||||
|
||||
</div>
|
||||
@@ -120,7 +118,7 @@
|
||||
'If you missed something, the connection will not work.',
|
||||
]" confirmationText="I manually configured Cloudflare Tunnel"
|
||||
confirmationLabel="Please type the confirmation text to confirm that you manually configured Cloudflare Tunnel."
|
||||
shortConfirmationLabel="Confirmation text" step3ButtonText="Confirm" />
|
||||
shortConfirmationLabel="Confirmation text" />
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
|
@@ -18,12 +18,12 @@
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Server Name" />
|
||||
@else
|
||||
<x-modal-confirmation title="Confirm Server Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete" :actions="['This server will be permanently deleted.']" confirmationText="{{ $server->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the Server Name below"
|
||||
shortConfirmationLabel="Server Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="Server Name" />
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
|
@@ -9,15 +9,11 @@
|
||||
</x-modal-input>
|
||||
</div>
|
||||
<div class="subtitle">All your servers are here.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
@forelse ($servers as $server)
|
||||
<a href="{{ route('server.show', ['server_uuid' => data_get($server, 'uuid')]) }}"
|
||||
@class([
|
||||
'gap-2 border cursor-pointer box group',
|
||||
'border-transparent' =>
|
||||
$server->settings->is_reachable &&
|
||||
$server->settings->is_usable &&
|
||||
!$server->settings->force_disabled,
|
||||
'border-red-500' =>
|
||||
!$server->settings->is_reachable || $server->settings->force_disabled,
|
||||
])>
|
||||
|
79
resources/views/livewire/settings/advanced.blade.php
Normal file
79
resources/views/livewire/settings/advanced.blade.php
Normal file
@@ -0,0 +1,79 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Advanced Settings | Coolify
|
||||
</x-slot>
|
||||
<x-settings.navbar />
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-settings.sidebar activeMenu="advanced" />
|
||||
<form wire:submit='submit' class="flex flex-col">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Advanced</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4">Advanced settings for your Coolify instance.</div>
|
||||
|
||||
<div class="flex flex-col gap-1 md:w-96">
|
||||
<x-forms.checkbox instantSave id="is_registration_enabled"
|
||||
helper="If enabled, users can register themselves. If disabled, only administrators can create new users."
|
||||
label="Registration Allowed" />
|
||||
<x-forms.checkbox instantSave id="do_not_track"
|
||||
helper="If enabled, Coolify will not track any data. This is useful if you are concerned about privacy."
|
||||
label="Do Not Track" />
|
||||
<h4 class="pt-4">DNS Settings</h4>
|
||||
<x-forms.checkbox instantSave id="is_dns_validation_enabled"
|
||||
helper="If you set a custom domain, Coolify will validate the domain in your DNS provider."
|
||||
label="DNS Validation" />
|
||||
<x-forms.input id="custom_dns_servers" label="Custom DNS Servers"
|
||||
helper="DNS servers to validate domains against. A comma separated list of DNS servers."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
<h4 class="pt-4">API Settings</h4>
|
||||
<x-forms.checkbox instantSave id="is_api_enabled" label="API Access"
|
||||
helper="If enabled, the API will be enabled. If disabled, the API will be disabled." />
|
||||
<x-forms.input id="allowed_ips" label="Allowed IPs for API Access"
|
||||
helper="Allowed IP lists for the API. A comma separated list of IPs. Empty means you allow from everywhere."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
<h4 class="pt-4">Confirmation Settings</h4>
|
||||
<div class="md:w-96 pb-1">
|
||||
<x-forms.checkbox instantSave id="is_sponsorship_popup_enabled" label="Show Sponsorship Popup"
|
||||
helper="When enabled, sponsorship popups will be shown monthly to users. When disabled, the sponsorship popup will be permanently hidden for all users." />
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex flex-col gap-1">
|
||||
@if ($disable_two_step_confirmation)
|
||||
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-enabled">
|
||||
<x-forms.checkbox instantSave id="disable_two_step_confirmation"
|
||||
label="Disable Two Step Confirmation"
|
||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
||||
</div>
|
||||
@else
|
||||
<div class="md:w-96 pb-4 flex items-center justify-between gap-2"
|
||||
wire:key="two-step-confirmation-disabled">
|
||||
<label class="flex items-center gap-2">
|
||||
Disable Two Step Confirmation
|
||||
<x-helper
|
||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers.">
|
||||
</x-helper>
|
||||
</label>
|
||||
<x-modal-confirmation title="Disable Two Step Confirmation?" buttonTitle="Disable" isErrorButton
|
||||
submitAction="toggleTwoStepConfirmation" :actions="[
|
||||
'Two Step confirmation will be disabled globally.',
|
||||
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
||||
'The risk of accidental actions will increase.',
|
||||
]"
|
||||
confirmationText="DISABLE TWO STEP CONFIRMATION"
|
||||
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
||||
shortConfirmationLabel="Confirmation text" />
|
||||
</div>
|
||||
<div class="w-full px-4 py-2 mb-4 text-white rounded-xs border-l-4 border-red-500 bg-error">
|
||||
<p class="font-bold">Warning!</p>
|
||||
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and
|
||||
increases
|
||||
the risk of accidental actions. This is not recommended for production servers.</p>
|
||||
</div>
|
||||
@endif
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@@ -3,23 +3,25 @@
|
||||
Settings | Coolify
|
||||
</x-slot>
|
||||
<x-settings.navbar />
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-settings.sidebar activeMenu="general" />
|
||||
<form wire:submit='submit' class="flex flex-col">
|
||||
<div class="flex items-center gap-2 pb-2">
|
||||
<h2>Configuration</h2>
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>General</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div>General configuration for your Coolify instance.</div>
|
||||
<div class="pb-4">General configuration for your Coolify instance.</div>
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<h4 class="pt-6">Instance Settings</h4>
|
||||
<div class="flex flex-wrap items-end gap-2">
|
||||
<div class="flex gap-2 md:flex-row flex-col w-full">
|
||||
<x-forms.input id="fqdn" label="Instance's Domain"
|
||||
<x-forms.input id="fqdn" label="Domain"
|
||||
helper="Enter the full domain name (FQDN) of the instance, including 'https://' if you want to secure the dashboard with HTTPS. Setting this will make the dashboard accessible via this domain, secured by HTTPS, instead of just the IP address."
|
||||
placeholder="https://coolify.yourdomain.com" />
|
||||
<x-forms.input id="instance_name" label="Instance's Name" placeholder="Coolify" />
|
||||
<x-forms.input id="instance_name" label="Name" placeholder="Coolify"
|
||||
helper="Custom name for your Coolify instance, shown in the URL." />
|
||||
<div class="w-full" x-data="{
|
||||
open: false,
|
||||
search: '{{ $settings->instance_timezone ?: '' }}',
|
||||
@@ -67,95 +69,15 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="flex gap-2 md:flex-row flex-col w-full">
|
||||
<x-forms.input id="public_ipv4" type="password" label="Instance's IPv4"
|
||||
<x-forms.input id="public_ipv4" type="password" label="Instance's Public IPv4"
|
||||
helper="Enter the IPv4 address of the instance.<br><br>It is useful if you have several IPv4 addresses and Coolify could not detect the correct one."
|
||||
placeholder="1.2.3.4" autocomplete="new-password" />
|
||||
<x-forms.input id="public_ipv6" type="password" label="Instance's IPv6"
|
||||
<x-forms.input id="public_ipv6" type="password" label="Instance's Public IPv6"
|
||||
helper="Enter the IPv6 address of the instance.<br><br>It is useful if you have several IPv6 addresses and Coolify could not detect the correct one."
|
||||
placeholder="2001:db8::1" autocomplete="new-password" />
|
||||
</div>
|
||||
<h4 class="w-full pt-6">DNS Validation</h4>
|
||||
<div class="md:w-96">
|
||||
<x-forms.checkbox instantSave id="is_dns_validation_enabled" label="Enabled" />
|
||||
</div>
|
||||
<x-forms.input id="custom_dns_servers" label="DNS Servers"
|
||||
helper="DNS servers to validate FQDNs against. A comma separated list of DNS servers."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
</div>
|
||||
|
||||
{{-- <div class="flex gap-2 ">
|
||||
<x-forms.input type="number" id="public_port_min" label="Public Port Min" />
|
||||
<x-forms.input type="number" id="public_port_max" label="Public Port Max" />
|
||||
</div> --}}
|
||||
|
||||
</div>
|
||||
<h4 class="pt-6">API</h4>
|
||||
<div class="md:w-96 pb-2">
|
||||
<x-forms.checkbox instantSave id="is_api_enabled" label="Enabled" />
|
||||
</div>
|
||||
<x-forms.input id="allowed_ips" label="Allowed IPs"
|
||||
helper="Allowed IP lists for the API. A comma separated list of IPs. Empty means you allow from everywhere."
|
||||
placeholder="1.1.1.1,8.8.8.8" />
|
||||
<h4 class="pt-6">Update</h4>
|
||||
<div class="text-right md:w-96 pb-4">
|
||||
@if (!is_null(config('constants.coolify.autoupdate', null)))
|
||||
<div class="text-right md:w-96">
|
||||
<x-forms.checkbox instantSave helper="AUTOUPDATE is set in .env file, you need to modify it there."
|
||||
disabled checked="{{ config('constants.coolify.autoupdate') }}" label="Auto Update Enabled" />
|
||||
</div>
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Auto Update Enabled" />
|
||||
@endif
|
||||
</div>
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input required id="update_check_frequency" label="Update Check Frequency"
|
||||
placeholder="0 * * * *"
|
||||
helper="Cron expression for update check frequency (check for new Coolify versions and pull new Service Templates from CDN).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every hour." />
|
||||
<x-forms.button wire:click='checkManually'>Check Manually</x-forms.button>
|
||||
</div>
|
||||
|
||||
@if (is_null(config('constants.coolify.autoupdate', null)) && $is_auto_update_enabled)
|
||||
<x-forms.input required id="auto_update_frequency" label="Auto Update Frequency" placeholder="0 0 * * *"
|
||||
helper="Cron expression for auto update frequency (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||
@endif
|
||||
</div>
|
||||
|
||||
<h4 class="pt-6">Advanced</h4>
|
||||
<div class="text-right md:w-96">
|
||||
<x-forms.checkbox instantSave id="is_registration_enabled" label="Registration Allowed" />
|
||||
<x-forms.checkbox instantSave id="do_not_track" label="Do Not Track" />
|
||||
</div>
|
||||
|
||||
<h4 class="py-4">Confirmation Settings</h4>
|
||||
<div class="md:w-96 ">
|
||||
<x-forms.checkbox instantSave id="is_sponsorship_popup_enabled" label="Show Sponsorship Popup"
|
||||
helper="When enabled, sponsorship popups will be shown monthly to users. When disabled, the sponsorship popup will be permanently hidden for all users." />
|
||||
</div>
|
||||
|
||||
@if ($disable_two_step_confirmation)
|
||||
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-enabled">
|
||||
<x-forms.checkbox instantSave id="disable_two_step_confirmation" label="Disable Two Step Confirmation"
|
||||
helper="When disabled, you will not need to confirm actions with a text and user password. This significantly reduces security and may lead to accidental deletions or unwanted changes. Use with extreme caution, especially on production servers." />
|
||||
</div>
|
||||
@else
|
||||
<div class="md:w-96 pb-4" wire:key="two-step-confirmation-disabled">
|
||||
<x-modal-confirmation title="Disable Two Step Confirmation?"
|
||||
buttonTitle="Disable Two Step Confirmation" isErrorButton submitAction="toggleTwoStepConfirmation"
|
||||
:actions="[
|
||||
'Two Step confirmation will be disabled globally.',
|
||||
'Disabling two step confirmation reduces security (as anyone can easily delete anything).',
|
||||
'The risk of accidental actions will increase.',
|
||||
]" confirmationText="DISABLE TWO STEP CONFIRMATION"
|
||||
confirmationLabel="Please type the confirmation text to disable two step confirmation."
|
||||
shortConfirmationLabel="Confirmation text" step3ButtonText="Disable Two Step Confirmation" />
|
||||
</div>
|
||||
<div class="w-full px-4 py-2 mb-4 text-white rounded-xs border-l-4 border-red-500 bg-error">
|
||||
<p class="font-bold">Warning!</p>
|
||||
<p>Disabling two step confirmation reduces security (as anyone can easily delete anything) and
|
||||
increases
|
||||
the risk of accidental actions. This is not recommended for production servers.</p>
|
||||
</div>
|
||||
@endif
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
51
resources/views/livewire/settings/updates.blade.php
Normal file
51
resources/views/livewire/settings/updates.blade.php
Normal file
@@ -0,0 +1,51 @@
|
||||
<div>
|
||||
<x-slot:title>
|
||||
Auto Update | Coolify
|
||||
</x-slot>
|
||||
<x-settings.navbar />
|
||||
<div x-data="{ activeTab: window.location.hash ? window.location.hash.substring(1) : 'general' }" class="flex flex-col h-full gap-8 sm:flex-row">
|
||||
<x-settings.sidebar activeMenu="updates" />
|
||||
<form wire:submit='submit' class="flex flex-col w-full">
|
||||
<div class="flex items-center gap-2">
|
||||
<h2>Updates</h2>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="pb-4">Your instance's update settings.</div>
|
||||
|
||||
|
||||
<div class="flex flex-col gap-2">
|
||||
<div class="flex items-end gap-2">
|
||||
<x-forms.input required id="update_check_frequency" label="Update Check Frequency"
|
||||
placeholder="0 * * * *"
|
||||
helper="Frequency (cron expression) to check for new Coolify versions and pull new Service Templates from CDN.<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every hour." />
|
||||
<x-forms.button wire:click='checkManually'>Check Manually</x-forms.button>
|
||||
</div>
|
||||
|
||||
<h4 class="pt-4">Auto Update</h4>
|
||||
|
||||
<div class="text-right md:w-64">
|
||||
@if (!is_null(config('constants.coolify.autoupdate', null)))
|
||||
<div class="text-right">
|
||||
<x-forms.checkbox instantSave
|
||||
helper="AUTOUPDATE is set in .env file, you need to modify it there." disabled
|
||||
checked="{{ config('constants.coolify.autoupdate') }}" label="Enabled" />
|
||||
</div>
|
||||
@else
|
||||
<x-forms.checkbox instantSave id="is_auto_update_enabled" label="Enabled" />
|
||||
@endif
|
||||
</div>
|
||||
@if (is_null(config('constants.coolify.autoupdate', null)) && $is_auto_update_enabled)
|
||||
<x-forms.input required id="auto_update_frequency" label="Frequency (cron expression)"
|
||||
placeholder="0 0 * * *"
|
||||
helper="Frequency (cron expression) (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||
@else
|
||||
<x-forms.input required label="Frequency (cron expression)" disabled placeholder="disabled"
|
||||
helper="Frequency (cron expression) (automatically update coolify).<br>You can use every_minute, hourly, daily, weekly, monthly, yearly.<br><br>Default is every day at 00:00" />
|
||||
@endif
|
||||
</div>
|
||||
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
@@ -1,21 +1,28 @@
|
||||
<div>
|
||||
<form class="flex flex-col gap-2 pb-6" wire:submit='submit'>
|
||||
<div class="flex items-start gap-2">
|
||||
<div class="pb-4">
|
||||
<div class="">
|
||||
<h1>Storage Details</h1>
|
||||
<div class="subtitle">{{ $storage->name }}</div>
|
||||
<div class="flex items-center gap-2 pb-4">
|
||||
<div>Current Status:</div>
|
||||
@if ($storage->is_usable)
|
||||
<div>Usable</div>
|
||||
<span
|
||||
class="px-2 py-1 text-xs font-semibold text-green-800 bg-green-100 rounded dark:text-green-100 dark:bg-green-800">
|
||||
Usable
|
||||
</span>
|
||||
@else
|
||||
<div class="text-red-500">Not Usable</div>
|
||||
<span
|
||||
class="px-2 py-1 text-xs font-semibold text-red-800 bg-red-100 rounded dark:text-red-100 dark:bg-red-800">
|
||||
Not Usable
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
<x-forms.button wire:click="test_s3_connection">
|
||||
Validate Connection
|
||||
</x-forms.button>
|
||||
|
||||
<x-modal-confirmation title="Confirm Storage Deletion?" isErrorButton buttonTitle="Delete"
|
||||
submitAction="delete({{ $storage->id }})" :actions="[
|
||||
'The selected storage location will be permanently deleted from Coolify.',
|
||||
@@ -37,5 +44,8 @@
|
||||
<x-forms.input required type="password" label="Access Key" id="storage.key" />
|
||||
<x-forms.input required type="password" label="Secret Key" id="storage.secret" />
|
||||
</div>
|
||||
<x-forms.button class="mt-4" isHighlighted wire:click="testConnection">
|
||||
Validate Connection
|
||||
</x-forms.button>
|
||||
</form>
|
||||
</div>
|
||||
|
@@ -9,10 +9,10 @@
|
||||
</x-modal-input>
|
||||
</div>
|
||||
<div class="subtitle">S3 storages for backups.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
@forelse ($s3 as $storage)
|
||||
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer box group border-transparent'])>
|
||||
<div class="flex flex-col mx-6">
|
||||
<a href="/storages/{{ $storage->uuid }}" @class(['gap-2 border cursor-pointer box group'])>
|
||||
<div class="flex flex-col justify-center mx-6">
|
||||
<div class="box-title">
|
||||
{{ $storage->name }}
|
||||
</div>
|
||||
@@ -20,7 +20,10 @@
|
||||
{{ $storage->description }}
|
||||
</div>
|
||||
@if (!$storage->is_usable)
|
||||
<div class="text-red-500">Not Usable</div>
|
||||
<span
|
||||
class="px-2 py-1 text-xs font-semibold text-red-800 bg-red-100 rounded dark:text-red-100 dark:bg-red-800">
|
||||
Not Usable
|
||||
</span>
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
|
@@ -7,8 +7,8 @@
|
||||
</div>
|
||||
<div class="flex flex-wrap gap-2 ">
|
||||
@forelse ($tags as $oneTag)
|
||||
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs hover:bg-coollabs-100'"
|
||||
class="w-64 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold"
|
||||
<a :class="{{ $tag?->id == $oneTag->id }} && 'dark:bg-coollabs'"
|
||||
class="w-32 box-without-bg dark:bg-coolgray-100 dark:text-white font-bold dark:hover:bg-coollabs-100 flex justify-center items-center"
|
||||
href="{{ route('tags.show', ['tagName' => $oneTag->name]) }}">{{ $oneTag->name }}</a>
|
||||
@empty
|
||||
<div>No tags yet defined yet. Go to a resource and add a tag there.</div>
|
||||
@@ -16,7 +16,7 @@
|
||||
</div>
|
||||
@if (isset($tag))
|
||||
<div>
|
||||
<h3 class="py-4">Details</h3>
|
||||
<h3 class="py-4">Tag Details</h3>
|
||||
<div class="flex items-end gap-2 ">
|
||||
<div class="w-[500px]">
|
||||
<x-forms.input readonly label="Deploy Webhook URL" id="webhook" />
|
||||
@@ -35,7 +35,7 @@
|
||||
@if (isset($applications) && count($applications) > 0)
|
||||
@foreach ($applications as $application)
|
||||
<a href="{{ $application->link() }}" class="box group">
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col justify-center">
|
||||
<div class="box-title">
|
||||
{{ $application->project()->name }}/{{ $application->environment->name }}
|
||||
</div>
|
||||
|
@@ -3,12 +3,16 @@
|
||||
Team Admin | Coolify
|
||||
</x-slot>
|
||||
<x-team.navbar />
|
||||
<h2>Admin View</h2>
|
||||
<div class="subtitle">
|
||||
Manage users of this instance.
|
||||
</div>
|
||||
<form wire:submit="submitSearch" class="flex flex-col gap-2 lg:flex-row">
|
||||
<x-forms.input wire:model="search" placeholder="Search for a user" />
|
||||
<x-forms.button type="submit">Search</x-forms.button>
|
||||
</form>
|
||||
<h3 class="pt-4">Users</h3>
|
||||
<div class="flex flex-col gap-2 ">
|
||||
<h3 class="py-4">Users</h3>
|
||||
<div class="grid grid-cols-1 gap-2 lg:grid-cols-2">
|
||||
@forelse ($users as $user)
|
||||
<div wire:key="user-{{ $user->id }}"
|
||||
class="flex items-center justify-center gap-2 bg-white box-without-bg dark:bg-coolgray-100">
|
||||
@@ -23,7 +27,7 @@
|
||||
]"
|
||||
confirmationText="{{ $user->name }}"
|
||||
confirmationLabel="Please confirm the execution of the actions by entering the User Name below"
|
||||
shortConfirmationLabel="User Name" step3ButtonText="Permanently Delete" />
|
||||
shortConfirmationLabel="User Name" />
|
||||
</div>
|
||||
</div>
|
||||
@empty
|
||||
|
@@ -4,17 +4,19 @@
|
||||
</x-slot>
|
||||
<x-team.navbar />
|
||||
|
||||
<form class="flex flex-col gap-2 pb-6" wire:submit='submit'>
|
||||
<div class="flex items-end gap-2">
|
||||
<form class="flex flex-col" wire:submit='submit'>
|
||||
<h2>General</h2>
|
||||
<div class="subtitle">
|
||||
Manage the general settings of this team.
|
||||
</div>
|
||||
|
||||
<div class="flex items-end gap-2 pb-6">
|
||||
<x-forms.input id="team.name" label="Name" required />
|
||||
<x-forms.input id="team.description" label="Description" />
|
||||
<x-forms.button type="submit">
|
||||
Save
|
||||
</x-forms.button>
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<x-forms.input id="team.name" label="Name" required />
|
||||
<x-forms.input id="team.description" label="Description" />
|
||||
</div>
|
||||
</form>
|
||||
|
||||
<div>
|
||||
|
@@ -4,7 +4,9 @@
|
||||
</x-slot>
|
||||
<x-team.navbar />
|
||||
<h2>Members</h2>
|
||||
|
||||
<div class="subtitle">
|
||||
Manage or invite members of this team.
|
||||
</div>
|
||||
<div class="flex flex-col">
|
||||
<div class="flex flex-col">
|
||||
<div class="overflow-x-auto">
|
||||
@@ -38,8 +40,8 @@
|
||||
@else
|
||||
<h2>Invite New Member</h2>
|
||||
@if (isInstanceAdmin())
|
||||
<div class="pb-4 text-xs dark:text-warning">You need to configure (as root team) <a href="/settings#smtp"
|
||||
class="underline dark:text-warning">Transactional
|
||||
<div class="pb-4 text-xs dark:text-warning">You need to configure (as root team) <a
|
||||
href="/settings#smtp" class="underline dark:text-warning">Transactional
|
||||
Emails</a>
|
||||
before
|
||||
you can invite a
|
||||
|
@@ -1,8 +0,0 @@
|
||||
<x-layout>
|
||||
<x-security.navbar />
|
||||
<a class="text-center hover:no-underline group" href="{{ route('security.private-key.index') }}">
|
||||
<div class="dark:group-hover:text-white">
|
||||
<div>Private Keys</div>
|
||||
</div>
|
||||
</a>
|
||||
</x-layout>
|
@@ -9,24 +9,28 @@
|
||||
</x-modal-input>
|
||||
</div>
|
||||
<div class="subtitle">Git sources for your applications.</div>
|
||||
<div class="grid gap-2 lg:grid-cols-2">
|
||||
<div class="grid gap-4 lg:grid-cols-2">
|
||||
@forelse ($sources as $source)
|
||||
@if ($source->getMorphClass() === 'App\Models\GithubApp')
|
||||
<a class="flex gap-4 text-center hover:no-underline box group"
|
||||
<a class="flex gap-2 text-center hover:no-underline box group"
|
||||
href="{{ route('source.github.show', ['github_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||
<x-git-icon class="dark:text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
|
||||
<div class="text-left dark:group-hover:text-white">
|
||||
{{-- <x-git-icon class="dark:text-white w-8 h-8 mt-1" git="{{ $source->getMorphClass() }}" /> --}}
|
||||
<div class="text-left dark:group-hover:text-white flex flex-col justify-center mx-6">
|
||||
<div class="box-title">{{ $source->name }}</div>
|
||||
@if (is_null($source->app_id))
|
||||
<span class="box-description text-error! ">Configuration is not finished.</span>
|
||||
@else
|
||||
@if ($source->organization)
|
||||
<span class="box-description">Organization: {{ $source->organization }}</span>
|
||||
@endif
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
@endif
|
||||
@if ($source->getMorphClass() === 'App\Models\GitlabApp')
|
||||
{{-- @if ($source->getMorphClass() === 'App\Models\GitlabApp')
|
||||
<a class="flex gap-4 text-center hover:no-underline box group"
|
||||
href="{{ route('source.gitlab.show', ['gitlab_app_uuid' => data_get($source, 'uuid')]) }}">
|
||||
<x-git-icon class="dark:text-white w-9 h-9" git="{{ $source->getMorphClass() }}" />
|
||||
<x-git-icon class="dark:text-white w-8 h-8" git="{{ $source->getMorphClass() }}" />
|
||||
<div class="text-left dark:group-hover:text-white">
|
||||
<div>{{ $source->name }}</div>
|
||||
@if (is_null($source->app_id))
|
||||
@@ -34,7 +38,7 @@
|
||||
@endif
|
||||
</div>
|
||||
</a>
|
||||
@endif
|
||||
@endif --}}
|
||||
@empty
|
||||
<div>
|
||||
<div>No sources found.</div>
|
||||
|
@@ -52,7 +52,9 @@ use App\Livewire\Server\Proxy\Show as ProxyShow;
|
||||
use App\Livewire\Server\Resources as ResourcesShow;
|
||||
use App\Livewire\Server\Security\Patches;
|
||||
use App\Livewire\Server\Show as ServerShow;
|
||||
use App\Livewire\Settings\Advanced as SettingsAdvanced;
|
||||
use App\Livewire\Settings\Index as SettingsIndex;
|
||||
use App\Livewire\Settings\Updates as SettingsUpdates;
|
||||
use App\Livewire\SettingsBackup;
|
||||
use App\Livewire\SettingsEmail;
|
||||
use App\Livewire\SettingsOauth;
|
||||
@@ -105,6 +107,9 @@ Route::middleware(['auth', 'verified'])->group(function () {
|
||||
Route::get('/subscription/new', SubscriptionIndex::class)->name('subscription.index');
|
||||
|
||||
Route::get('/settings', SettingsIndex::class)->name('settings.index');
|
||||
Route::get('/settings/advanced', SettingsAdvanced::class)->name('settings.advanced');
|
||||
Route::get('/settings/updates', SettingsUpdates::class)->name('settings.updates');
|
||||
|
||||
Route::get('/settings/backup', SettingsBackup::class)->name('settings.backup');
|
||||
Route::get('/settings/email', SettingsEmail::class)->name('settings.email');
|
||||
Route::get('/settings/oauth', SettingsOauth::class)->name('settings.oauth');
|
||||
|
@@ -5,14 +5,17 @@
|
||||
|
||||
services:
|
||||
appwrite:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
container_name: appwrite
|
||||
volumes:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-config:/storage/config:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
depends_on:
|
||||
- appwrite-mariadb
|
||||
- appwrite-redis
|
||||
@@ -21,10 +24,12 @@ services:
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_LOCALE=${_APP_LOCALE:-en}
|
||||
- _APP_COMPRESSION_MIN_SIZE_BYTES=${_APP_COMPRESSION_MIN_SIZE_BYTES}
|
||||
- _APP_CONSOLE_WHITELIST_ROOT=${_APP_CONSOLE_WHITELIST_ROOT:-enabled}
|
||||
- _APP_CONSOLE_WHITELIST_EMAILS=${_APP_CONSOLE_WHITELIST_EMAILS}
|
||||
- _APP_CONSOLE_SESSION_ALERTS=${_APP_CONSOLE_SESSION_ALERTS}
|
||||
- _APP_CONSOLE_WHITELIST_IPS=${_APP_CONSOLE_WHITELIST_IPS}
|
||||
- _APP_CONSOLE_HOSTNAMES=${_APP_CONSOLE_HOSTNAMES:-localhost,appwrite.io,*.appwrite.io}
|
||||
- _APP_CONSOLE_HOSTNAMES=${_APP_CONSOLE_HOSTNAMES}
|
||||
- _APP_SYSTEM_EMAIL_NAME=${_APP_SYSTEM_EMAIL_NAME:-Appwrite}
|
||||
- _APP_SYSTEM_EMAIL_ADDRESS=${_APP_SYSTEM_EMAIL_ADDRESS:-team@appwrite.io}
|
||||
- _APP_SYSTEM_TEAM_EMAIL=${_APP_SYSTEM_TEAM_EMAIL:-team@appwrite.io}
|
||||
@@ -33,10 +38,12 @@ services:
|
||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION:-disabled}
|
||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS=${_APP_OPTIONS_ROUTER_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME:-localhost}
|
||||
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA:-::1}
|
||||
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A:-127.0.0.1}
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
@@ -63,6 +70,7 @@ services:
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
@@ -79,21 +87,26 @@ services:
|
||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT:-30000000}
|
||||
- _APP_COMPUTE_SIZE_LIMIT=${_APP_COMPUTE_SIZE_LIMIT:-30000000}
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||
- _APP_FUNCTIONS_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES:-node-20.0,php-8.2,python-3.11,ruby-3.2}
|
||||
- _APP_SITES_RUNTIMES=${_APP_SITES_RUNTIMES}
|
||||
- _APP_DOMAIN_SITES=${_APP_DOMAIN_SITES:-appwrite.network}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_MAINTENANCE_INTERVAL=${_APP_MAINTENANCE_INTERVAL:-86400}
|
||||
- _APP_MAINTENANCE_DELAY=${_APP_MAINTENANCE_DELAY}
|
||||
- _APP_MAINTENANCE_START_TIME=${_APP_MAINTENANCE_START_TIME}
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||
- _APP_SMS_PROVIDER=${_APP_SMS_PROVIDER}
|
||||
@@ -112,13 +125,13 @@ services:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
||||
|
||||
appwrite-console:
|
||||
image: appwrite/console:5.0.12
|
||||
image: appwrite/console:6.0.13
|
||||
container_name: appwrite-console
|
||||
environment:
|
||||
- SERVICE_FQDN_APPWRITE=/console
|
||||
|
||||
appwrite-realtime:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: realtime
|
||||
container_name: appwrite-realtime
|
||||
depends_on:
|
||||
@@ -129,6 +142,7 @@ services:
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPTIONS_ABUSE=${_APP_OPTIONS_ABUSE:-enabled}
|
||||
- _APP_OPTIONS_ROUTER_PROTECTION=${_APP_OPTIONS_ROUTER_PROTECTION:-disabled}
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
@@ -143,7 +157,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-audits:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-audits
|
||||
container_name: appwrite-worker-audits
|
||||
depends_on:
|
||||
@@ -165,7 +179,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-webhooks:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-webhooks
|
||||
container_name: appwrite-worker-webhooks
|
||||
depends_on:
|
||||
@@ -189,7 +203,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-deletes:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-deletes
|
||||
container_name: appwrite-worker-deletes
|
||||
depends_on:
|
||||
@@ -199,6 +213,7 @@ services:
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
- appwrite-cache:/storage/cache:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-certificates:/storage/certificates:rw
|
||||
environment:
|
||||
@@ -215,10 +230,11 @@ services:
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
@@ -240,10 +256,13 @@ services:
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||
- _APP_MAINTENANCE_RETENTION_EXECUTION=${_APP_MAINTENANCE_RETENTION_EXECUTION:-1209600}
|
||||
- _APP_SYSTEM_SECURITY_EMAIL_ADDRESS=${_APP_SYSTEM_SECURITY_EMAIL_ADDRESS}
|
||||
- _APP_EMAIL_CERTIFICATES=${_APP_EMAIL_CERTIFICATES}
|
||||
|
||||
appwrite-worker-databases:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-databases
|
||||
container_name: appwrite-worker-databases
|
||||
depends_on:
|
||||
@@ -265,7 +284,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-builds:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-builds
|
||||
container_name: appwrite-worker-builds
|
||||
depends_on:
|
||||
@@ -273,7 +292,9 @@ services:
|
||||
- appwrite-mariadb
|
||||
volumes:
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-uploads:/storage/uploads:rw
|
||||
environment:
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
@@ -294,18 +315,20 @@ services:
|
||||
- _APP_VCS_GITHUB_PRIVATE_KEY=${_APP_VCS_GITHUB_PRIVATE_KEY}
|
||||
- _APP_VCS_GITHUB_APP_ID=${_APP_VCS_GITHUB_APP_ID}
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_FUNCTIONS_SIZE_LIMIT=${_APP_FUNCTIONS_SIZE_LIMIT:-30000000}
|
||||
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||
- _APP_COMPUTE_SIZE_LIMIT=${_APP_COMPUTE_SIZE_LIMIT:-30000000}
|
||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPTIONS_FUNCTIONS_FORCE_HTTPS=${_APP_OPTIONS_FUNCTIONS_FORCE_HTTPS:-disabled}
|
||||
- _APP_OPTIONS_ROUTER_FORCE_HTTPS=${_APP_OPTIONS_ROUTER_FORCE_HTTPS:-disabled}
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- _APP_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
@@ -322,9 +345,10 @@ services:
|
||||
- _APP_STORAGE_WASABI_SECRET=${_APP_STORAGE_WASABI_SECRET}
|
||||
- _APP_STORAGE_WASABI_REGION=${_APP_STORAGE_WASABI_REGION:-eu-central-1}
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
- _APP_DOMAIN_SITES=${_APP_DOMAIN_SITES}
|
||||
|
||||
appwrite-worker-certificates:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-certificates
|
||||
container_name: appwrite-worker-certificates
|
||||
depends_on:
|
||||
@@ -338,10 +362,11 @@ services:
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||
- _APP_EMAIL_CERTIFICATES=${_APP_EMAIL_CERTIFICATES:-enabled}
|
||||
- _APP_EMAIL_SECURITY=${_APP_EMAIL_SECURITY:-certs@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
@@ -354,7 +379,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-functions:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-functions
|
||||
container_name: appwrite-worker-functions
|
||||
depends_on:
|
||||
@@ -377,9 +402,10 @@ services:
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_FUNCTIONS_TIMEOUT=${_APP_FUNCTIONS_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_BUILD_TIMEOUT=${_APP_FUNCTIONS_BUILD_TIMEOUT:-900}
|
||||
- _APP_FUNCTIONS_CPUS=${_APP_FUNCTIONS_CPUS:-0}
|
||||
- _APP_FUNCTIONS_MEMORY=${_APP_FUNCTIONS_MEMORY:-0}
|
||||
- _APP_SITES_TIMEOUT=${_APP_SITES_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_BUILD_TIMEOUT=${_APP_COMPUTE_BUILD_TIMEOUT:-900}
|
||||
- _APP_COMPUTE_CPUS=${_APP_COMPUTE_CPUS:-0}
|
||||
- _APP_COMPUTE_MEMORY=${_APP_COMPUTE_MEMORY:-0}
|
||||
- _APP_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_EXECUTOR_HOST=${_APP_EXECUTOR_HOST:-http://appwrite-executor/v1}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
@@ -388,7 +414,7 @@ services:
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
|
||||
appwrite-worker-mails:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-mails
|
||||
container_name: appwrite-worker-mails
|
||||
depends_on:
|
||||
@@ -415,9 +441,10 @@ services:
|
||||
- _APP_SMTP_PASSWORD=${_APP_SMTP_PASSWORD}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_OPTIONS_FORCE_HTTPS=${_APP_OPTIONS_FORCE_HTTPS:-disabled}
|
||||
|
||||
appwrite-worker-messaging:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-messaging
|
||||
container_name: appwrite-worker-messaging
|
||||
volumes:
|
||||
@@ -445,6 +472,7 @@ services:
|
||||
- _APP_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- _APP_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION:-us-east-1}
|
||||
- _APP_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- _APP_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||
- _APP_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- _APP_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- _APP_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION:-us-east-1}
|
||||
@@ -463,9 +491,11 @@ services:
|
||||
- _APP_STORAGE_WASABI_BUCKET=${_APP_STORAGE_WASABI_BUCKET}
|
||||
|
||||
appwrite-worker-migrations:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-migrations
|
||||
container_name: appwrite-worker-migrations
|
||||
volumes:
|
||||
- appwrite-imports:/storage/imports:rw
|
||||
depends_on:
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
@@ -473,7 +503,9 @@ services:
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||
- _APP_EMAIL_SECURITY=${_APP_EMAIL_SECURITY:-certs@appwrite.io}
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
@@ -489,7 +521,7 @@ services:
|
||||
- _APP_MIGRATIONS_FIREBASE_CLIENT_SECRET=${_APP_MIGRATIONS_FIREBASE_CLIENT_SECRET}
|
||||
|
||||
appwrite-task-maintenance:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: maintenance
|
||||
container_name: appwrite-task-maintenance
|
||||
depends_on:
|
||||
@@ -498,7 +530,9 @@ services:
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_DOMAIN=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET=$SERVICE_URL_APPWRITE
|
||||
- _APP_DOMAIN_TARGET_CNAME=${_APP_DOMAIN_TARGET_CNAME}
|
||||
- _APP_DOMAIN_TARGET_AAAA=${_APP_DOMAIN_TARGET_AAAA}
|
||||
- _APP_DOMAIN_TARGET_A=${_APP_DOMAIN_TARGET_A}
|
||||
- _APP_DOMAIN_FUNCTIONS=$SERVICE_URL_APPWRITE
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
@@ -515,14 +549,14 @@ services:
|
||||
- _APP_MAINTENANCE_RETENTION_CACHE=${_APP_MAINTENANCE_RETENTION_CACHE:-2592000}
|
||||
- _APP_MAINTENANCE_RETENTION_ABUSE=${_APP_MAINTENANCE_RETENTION_ABUSE:-86400}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT=${_APP_MAINTENANCE_RETENTION_AUDIT:-1209600}
|
||||
- _APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE=${_APP_MAINTENANCE_RETENTION_AUDIT_CONSOLE}
|
||||
- _APP_MAINTENANCE_RETENTION_USAGE_HOURLY=${_APP_MAINTENANCE_RETENTION_USAGE_HOURLY:-8640000}
|
||||
- _APP_MAINTENANCE_RETENTION_SCHEDULES=${_APP_MAINTENANCE_RETENTION_SCHEDULES:-86400}
|
||||
|
||||
appwrite-worker-usage:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
entrypoint: worker-usage
|
||||
container_name: appwrite-worker-usage
|
||||
restart: unless-stopped
|
||||
appwrite-task-stats-resources:
|
||||
image: appwrite/appwrite:1.7.4
|
||||
container_name: appwrite-task-stats-resources
|
||||
entrypoint: stats-resources
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
@@ -541,12 +575,37 @@ services:
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
||||
- _APP_DATABASE_SHARED_TABLES=${_APP_DATABASE_SHARED_TABLES}
|
||||
- _APP_STATS_RESOURCES_INTERVAL=${_APP_STATS_RESOURCES_INTERVAL}
|
||||
|
||||
appwrite-worker-usage-dump:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
entrypoint: worker-usage-dump
|
||||
container_name: appwrite-worker-usage-dump
|
||||
appwrite-worker-stats-resources:
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-stats-resources
|
||||
container_name: appwrite-worker-stats-resources
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
environment:
|
||||
- _APP_ENV=${_APP_ENV:-production}
|
||||
- _APP_WORKER_PER_CORE=${_APP_WORKER_PER_CORE:-6}
|
||||
- _APP_OPENSSL_KEY_V1=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- _APP_DB_HOST=${_APP_DB_HOST:-appwrite-mariadb}
|
||||
- _APP_DB_PORT=${_APP_DB_PORT:-3306}
|
||||
- _APP_DB_SCHEMA=${_APP_DB_SCHEMA:-appwrite}
|
||||
- _APP_DB_USER=$SERVICE_USER_MARIADB
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
- _APP_REDIS_HOST=${_APP_REDIS_HOST:-appwrite-redis}
|
||||
- _APP_REDIS_PORT=${_APP_REDIS_PORT:-6379}
|
||||
- _APP_REDIS_USER=${_APP_REDIS_USER}
|
||||
- _APP_REDIS_PASS=${_APP_REDIS_PASS}
|
||||
- _APP_USAGE_STATS=${_APP_USAGE_STATS:-enabled}
|
||||
- _APP_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- _APP_STATS_RESOURCES_INTERVAL=${_APP_STATS_RESOURCES_INTERVAL}
|
||||
|
||||
appwrite-worker-stats-usage:
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: worker-stats-usage
|
||||
container_name: appwrite-worker-stats-usage
|
||||
depends_on:
|
||||
- appwrite-redis
|
||||
- appwrite-mariadb
|
||||
@@ -568,7 +627,7 @@ services:
|
||||
- _APP_USAGE_AGGREGATION_INTERVAL=${_APP_USAGE_AGGREGATION_INTERVAL:-30}
|
||||
|
||||
appwrite-task-scheduler-functions:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: schedule-functions
|
||||
container_name: appwrite-task-scheduler-functions
|
||||
depends_on:
|
||||
@@ -589,7 +648,7 @@ services:
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
|
||||
appwrite-task-scheduler-executions:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: schedule-executions
|
||||
container_name: appwrite-task-scheduler-executions
|
||||
depends_on:
|
||||
@@ -610,7 +669,7 @@ services:
|
||||
- _APP_DB_PASS=$SERVICE_PASSWORD_MARIADB
|
||||
|
||||
appwrite-task-scheduler-messages:
|
||||
image: appwrite/appwrite:1.6.0
|
||||
image: appwrite/appwrite:1.7.4
|
||||
entrypoint: schedule-messages
|
||||
container_name: appwrite-task-scheduler-messages
|
||||
depends_on:
|
||||
@@ -636,33 +695,40 @@ services:
|
||||
environment:
|
||||
- _APP_ASSISTANT_OPENAI_API_KEY=${_APP_ASSISTANT_OPENAI_API_KEY}
|
||||
|
||||
appwrite-browser:
|
||||
image: appwrite/browser:0.2.4
|
||||
container_name: appwrite-browser
|
||||
|
||||
openruntimes-executor:
|
||||
container_name: openruntimes-executor
|
||||
hostname: appwrite-executor
|
||||
stop_signal: SIGINT
|
||||
image: openruntimes/executor:0.6.11
|
||||
image: openruntimes/executor:0.7.14
|
||||
networks:
|
||||
- runtimes
|
||||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock
|
||||
- appwrite-builds:/storage/builds:rw
|
||||
- appwrite-functions:/storage/functions:rw
|
||||
- appwrite-sites:/storage/sites:rw
|
||||
- /tmp:/tmp:rw
|
||||
environment:
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_FUNCTIONS_INACTIVE_THRESHOLD}
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_FUNCTIONS_MAINTENANCE_INTERVAL}
|
||||
- OPR_EXECUTOR_NETWORK=${_APP_FUNCTIONS_RUNTIMES_NETWORK:-runtimes}
|
||||
- OPR_EXECUTOR_INACTIVE_TRESHOLD=${_APP_COMPUTE_INACTIVE_THRESHOLD}
|
||||
- OPR_EXECUTOR_MAINTENANCE_INTERVAL=${_APP_COMPUTE_MAINTENANCE_INTERVAL}
|
||||
- OPR_EXECUTOR_NETWORK=${_APP_COMPUTE_RUNTIMES_NETWORK:-runtimes}
|
||||
- OPR_EXECUTOR_DOCKER_HUB_USERNAME=${_APP_DOCKER_HUB_USERNAME}
|
||||
- OPR_EXECUTOR_DOCKER_HUB_PASSWORD=${_APP_DOCKER_HUB_PASSWORD}
|
||||
- OPR_EXECUTOR_ENV=${_APP_ENV:-production}
|
||||
- OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES}
|
||||
- OPR_EXECUTOR_RUNTIMES=${_APP_FUNCTIONS_RUNTIMES},${_APP_SITES_RUNTIMES}
|
||||
- OPR_EXECUTOR_SECRET=$SERVICE_PASSWORD_64_APPWRITE
|
||||
- OPR_EXECUTOR_RUNTIME_VERSIONS=v5
|
||||
- OPR_EXECUTOR_LOGGING_CONFIG=${_APP_LOGGING_CONFIG}
|
||||
- OPR_EXECUTOR_STORAGE_DEVICE=${_APP_STORAGE_DEVICE:-local}
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY:-local}
|
||||
- OPR_EXECUTOR_STORAGE_S3_ACCESS_KEY=${_APP_STORAGE_S3_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_S3_SECRET=${_APP_STORAGE_S3_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_S3_REGION=${_APP_STORAGE_S3_REGION}
|
||||
- OPR_EXECUTOR_STORAGE_S3_BUCKET=${_APP_STORAGE_S3_BUCKET}
|
||||
- OPR_EXECUTOR_STORAGE_S3_ENDPOINT=${_APP_STORAGE_S3_ENDPOINT}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_ACCESS_KEY=${_APP_STORAGE_DO_SPACES_ACCESS_KEY}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_SECRET=${_APP_STORAGE_DO_SPACES_SECRET}
|
||||
- OPR_EXECUTOR_STORAGE_DO_SPACES_REGION=${_APP_STORAGE_DO_SPACES_REGION}
|
||||
@@ -703,6 +769,7 @@ services:
|
||||
--maxmemory-samples 5
|
||||
volumes:
|
||||
- appwrite-redis:/data:rw
|
||||
|
||||
networks:
|
||||
runtimes:
|
||||
name: runtimes
|
||||
@@ -712,7 +779,9 @@ volumes:
|
||||
appwrite-redis:
|
||||
appwrite-cache:
|
||||
appwrite-uploads:
|
||||
appwrite-imports:
|
||||
appwrite-certificates:
|
||||
appwrite-functions:
|
||||
appwrite-sites:
|
||||
appwrite-builds:
|
||||
appwrite-config:
|
||||
|
@@ -6,7 +6,7 @@
|
||||
|
||||
services:
|
||||
authentik-server:
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.4.1}
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.6.3}
|
||||
restart: unless-stopped
|
||||
command: server
|
||||
environment:
|
||||
@@ -35,7 +35,7 @@ services:
|
||||
redis:
|
||||
condition: service_healthy
|
||||
authentik-worker:
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.4.1}
|
||||
image: ghcr.io/goauthentik/server:${AUTHENTIK_TAG:-2025.6.3}
|
||||
restart: unless-stopped
|
||||
command: worker
|
||||
environment:
|
||||
|
21
templates/compose/excalidraw.yaml
Normal file
21
templates/compose/excalidraw.yaml
Normal file
@@ -0,0 +1,21 @@
|
||||
# documentation: https://docs.excalidraw.com/docs
|
||||
# slogan: Virtual whiteboard for sketching hand-drawn like diagrams
|
||||
# tags: canvas,diagrams,drawing,productivity,whiteboard
|
||||
# logo: svgs/excalidraw.svg
|
||||
# port: 80
|
||||
|
||||
services:
|
||||
excalidraw:
|
||||
image: excalidraw/excalidraw:latest
|
||||
environment:
|
||||
- SERVICE_FQDN_EXCALIDRAW_80
|
||||
healthcheck:
|
||||
test:
|
||||
- CMD
|
||||
- wget
|
||||
- '--spider'
|
||||
- '--quiet'
|
||||
- 'http://localhost'
|
||||
interval: 10s
|
||||
timeout: 5s
|
||||
retries: 10
|
File diff suppressed because one or more lines are too long
@@ -1,10 +1,10 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.420.1"
|
||||
"version": "4.0.0-beta.420.2"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.0.0-beta.421"
|
||||
"version": "4.0.0-beta.420.3"
|
||||
},
|
||||
"helper": {
|
||||
"version": "1.0.8"
|
||||
|
Reference in New Issue
Block a user