From 89fd4c52bc4507252e7af167d641ca2695d22c55 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Tue, 23 Dec 2025 09:57:45 +0100 Subject: [PATCH 1/6] feat: customizable database proxy timeouts --- app/Actions/Database/StartDatabaseProxy.php | 7 ++- .../Project/Database/Clickhouse/General.php | 5 ++ .../Project/Database/Dragonfly/General.php | 5 ++ .../Project/Database/Keydb/General.php | 5 ++ .../Project/Database/Mariadb/General.php | 8 +++ .../Project/Database/Mongodb/General.php | 6 ++ .../Project/Database/Mysql/General.php | 6 ++ .../Project/Database/Postgresql/General.php | 6 ++ .../Project/Database/Redis/General.php | 6 ++ app/Livewire/Project/Service/Database.php | 5 ++ ...1_add_proxy_timeout_to_database_tables.php | 60 +++++++++++++++++++ .../database/clickhouse/general.blade.php | 10 +++- .../database/dragonfly/general.blade.php | 10 +++- .../project/database/keydb/general.blade.php | 10 +++- .../database/mariadb/general.blade.php | 10 +++- .../database/mongodb/general.blade.php | 10 +++- .../project/database/mysql/general.blade.php | 10 +++- .../database/postgresql/general.blade.php | 10 +++- .../project/database/redis/general.blade.php | 10 +++- .../project/service/database.blade.php | 3 + 20 files changed, 184 insertions(+), 18 deletions(-) create mode 100644 database/migrations/2025_12_23_075711_add_proxy_timeout_to_database_tables.php diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 12fd92792..2ae672402 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -55,6 +55,8 @@ class StartDatabaseProxy if (isDev()) { $configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy'; } + $proxyTimeout = $database->proxy_timeout ?? 1800; // Default to 30 minutes if not set + $timeoutDirective = $proxyTimeout > 0 ? "proxy_timeout {$proxyTimeout}s;" : ""; $nginxconf = <<public_port; proxy_pass $containerName:$internalPort; - } + {$timeoutDirective} + } } EOF; $docker_compose = [ diff --git a/app/Livewire/Project/Database/Clickhouse/General.php b/app/Livewire/Project/Database/Clickhouse/General.php index c4a7983b8..35992e65f 100644 --- a/app/Livewire/Project/Database/Clickhouse/General.php +++ b/app/Livewire/Project/Database/Clickhouse/General.php @@ -36,6 +36,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public ?string $customDockerRunOptions = null; public ?string $dbUrl = null; @@ -80,6 +82,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', @@ -115,6 +118,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->save(); @@ -130,6 +134,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->dbUrl = $this->database->internal_db_url; diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php index 9052a4749..737f71de8 100644 --- a/app/Livewire/Project/Database/Dragonfly/General.php +++ b/app/Livewire/Project/Database/Dragonfly/General.php @@ -36,6 +36,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public ?string $customDockerRunOptions = null; public ?string $dbUrl = null; @@ -91,6 +93,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', @@ -124,6 +127,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->enable_ssl = $this->enable_ssl; @@ -139,6 +143,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->enable_ssl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Keydb/General.php b/app/Livewire/Project/Database/Keydb/General.php index 6d21988e7..bf4a3abdf 100644 --- a/app/Livewire/Project/Database/Keydb/General.php +++ b/app/Livewire/Project/Database/Keydb/General.php @@ -38,6 +38,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public ?string $customDockerRunOptions = null; public ?string $dbUrl = null; @@ -94,6 +96,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', @@ -130,6 +133,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->enable_ssl = $this->enable_ssl; @@ -146,6 +150,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->enable_ssl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index 429cfc387..a4c529ee5 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -44,6 +44,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isLogDrainEnabled = false; public ?string $customDockerRunOptions = null; @@ -79,6 +81,8 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', @@ -115,6 +119,8 @@ class General extends Component 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', + 'proxyTimeout' => 'Proxy Timeout', + 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Options', 'enableSsl' => 'Enable SSL', ]; @@ -156,6 +162,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; @@ -175,6 +182,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index ae725fa4b..03bc6be5f 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -42,6 +42,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isLogDrainEnabled = false; public ?string $customDockerRunOptions = null; @@ -78,6 +80,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', @@ -114,6 +117,7 @@ class General extends Component 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', + 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', @@ -155,6 +159,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; @@ -174,6 +179,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index cffedcd23..2cec4306c 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -44,6 +44,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isLogDrainEnabled = false; public ?string $customDockerRunOptions = null; @@ -81,6 +83,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', @@ -119,6 +122,7 @@ class General extends Component 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', + 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', @@ -161,6 +165,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; @@ -181,6 +186,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index 7ef2cdc4f..d34418157 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -48,6 +48,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isLogDrainEnabled = false; public ?string $customDockerRunOptions = null; @@ -93,6 +95,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', @@ -132,6 +135,7 @@ class General extends Component 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', + 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Run Options', 'enableSsl' => 'Enable SSL', 'sslMode' => 'SSL Mode', @@ -176,6 +180,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; @@ -198,6 +203,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index 846614d21..e5d8d14bd 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -36,6 +36,8 @@ class General extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isLogDrainEnabled = false; public ?string $customDockerRunOptions = null; @@ -74,6 +76,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'redisUsername' => 'required', @@ -106,6 +109,7 @@ class General extends Component 'portsMappings' => 'Port Mapping', 'isPublic' => 'Is Public', 'publicPort' => 'Public Port', + 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Options', 'redisUsername' => 'Redis Username', 'redisPassword' => 'Redis Password', @@ -145,6 +149,7 @@ class General extends Component $this->database->ports_mappings = $this->portsMappings; $this->database->is_public = $this->isPublic; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; $this->database->custom_docker_run_options = $this->customDockerRunOptions; $this->database->enable_ssl = $this->enableSsl; @@ -160,6 +165,7 @@ class General extends Component $this->portsMappings = $this->database->ports_mappings; $this->isPublic = $this->database->is_public; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled; $this->customDockerRunOptions = $this->database->custom_docker_run_options; $this->enableSsl = $this->database->enable_ssl; diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index 1e183c6bc..0e1eb3e30 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -31,6 +31,8 @@ class Database extends Component public ?int $publicPort = null; + public ?int $proxyTimeout = null; + public bool $isPublic = false; public bool $isLogDrainEnabled = false; @@ -43,6 +45,7 @@ class Database extends Component 'image' => 'required', 'excludeFromStatus' => 'required|boolean', 'publicPort' => 'nullable|integer', + 'proxyTimeout' => 'nullable|integer|min:0|max:86400', 'isPublic' => 'required|boolean', 'isLogDrainEnabled' => 'required|boolean', ]; @@ -75,6 +78,7 @@ class Database extends Component $this->database->image = $this->image; $this->database->exclude_from_status = $this->excludeFromStatus; $this->database->public_port = $this->publicPort; + $this->database->proxy_timeout = $this->proxyTimeout; $this->database->is_public = $this->isPublic; $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; } else { @@ -83,6 +87,7 @@ class Database extends Component $this->image = $this->database->image; $this->excludeFromStatus = $this->database->exclude_from_status ?? false; $this->publicPort = $this->database->public_port; + $this->proxyTimeout = $this->database->proxy_timeout; $this->isPublic = $this->database->is_public ?? false; $this->isLogDrainEnabled = $this->database->is_log_drain_enabled ?? false; } diff --git a/database/migrations/2025_12_23_075711_add_proxy_timeout_to_database_tables.php b/database/migrations/2025_12_23_075711_add_proxy_timeout_to_database_tables.php new file mode 100644 index 000000000..2393dd5f1 --- /dev/null +++ b/database/migrations/2025_12_23_075711_add_proxy_timeout_to_database_tables.php @@ -0,0 +1,60 @@ +integer('proxy_timeout')->default(1800)->after('public_port'); // 30 minutes default + }); + } + } + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + $tables = [ + 'standalone_postgresqls', + 'standalone_mysqls', + 'standalone_mariadbs', + 'standalone_mongodbs', + 'standalone_redis', + 'standalone_keydbs', + 'standalone_dragonflies', + 'standalone_clickhouses', + 'service_databases', + ]; + + foreach ($tables as $table) { + if (Schema::hasTable($table) && Schema::hasColumn($table, 'proxy_timeout')) { + Schema::table($table, function (Blueprint $table) { + $table->dropColumn('proxy_timeout'); + }); + } + } + } +}; \ No newline at end of file diff --git a/resources/views/livewire/project/database/clickhouse/general.blade.php b/resources/views/livewire/project/database/clickhouse/general.blade.php index 2010e0afc..bff3cadd1 100644 --- a/resources/views/livewire/project/database/clickhouse/general.blade.php +++ b/resources/views/livewire/project/database/clickhouse/general.blade.php @@ -76,8 +76,14 @@ - +
+ + +

Advanced

diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index 2b2e5d355..1537720f1 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -113,8 +113,14 @@ - +
+ + +

Advanced

diff --git a/resources/views/livewire/project/database/keydb/general.blade.php b/resources/views/livewire/project/database/keydb/general.blade.php index 00c30edff..650ef6e33 100644 --- a/resources/views/livewire/project/database/keydb/general.blade.php +++ b/resources/views/livewire/project/database/keydb/general.blade.php @@ -113,8 +113,14 @@ - +
+ + +
- +
+ + +
diff --git a/resources/views/livewire/project/database/mongodb/general.blade.php b/resources/views/livewire/project/database/mongodb/general.blade.php index a474153f1..b9098ae7e 100644 --- a/resources/views/livewire/project/database/mongodb/general.blade.php +++ b/resources/views/livewire/project/database/mongodb/general.blade.php @@ -151,8 +151,14 @@ - +
+ + +
diff --git a/resources/views/livewire/project/database/mysql/general.blade.php b/resources/views/livewire/project/database/mysql/general.blade.php index 8187878e4..e49b3310e 100644 --- a/resources/views/livewire/project/database/mysql/general.blade.php +++ b/resources/views/livewire/project/database/mysql/general.blade.php @@ -153,8 +153,14 @@ - +
+ + +

Advanced

diff --git a/resources/views/livewire/project/database/postgresql/general.blade.php b/resources/views/livewire/project/database/postgresql/general.blade.php index 7300b913a..42b43e9c0 100644 --- a/resources/views/livewire/project/database/postgresql/general.blade.php +++ b/resources/views/livewire/project/database/postgresql/general.blade.php @@ -163,8 +163,14 @@ - +
+ + +
diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index f37674186..b85a76424 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -132,8 +132,14 @@
- +
+ + +
+ @if ($db_url_public) From 14b016016503163026e863becd86f68d4f127237 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Tue, 23 Dec 2025 14:55:47 +0100 Subject: [PATCH 2/6] feat: added required timeout range to database proxy --- app/Actions/Database/StartDatabaseProxy.php | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 2ae672402..c44a69737 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -22,6 +22,17 @@ class StartDatabaseProxy public function handle(StandaloneRedis|StandalonePostgresql|StandaloneMongodb|StandaloneMysql|StandaloneMariadb|StandaloneKeydb|StandaloneDragonfly|StandaloneClickhouse|ServiceDatabase $database) { + // Validate proxy timeout + if (!isset($database->proxy_timeout) || $database->proxy_timeout === null) { + throw new \Exception('Proxy timeout is required.'); + } + if ($database->proxy_timeout <= 0) { + throw new \Exception('Proxy timeout must be greater than 0.'); + } + if ($database->proxy_timeout > 86400) { + throw new \Exception('Proxy timeout must not exceed 86400 seconds (24 hours).'); + } + $databaseType = $database->database_type; $network = data_get($database, 'destination.network'); $server = data_get($database, 'destination.server'); @@ -56,7 +67,7 @@ class StartDatabaseProxy $configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy'; } $proxyTimeout = $database->proxy_timeout ?? 1800; // Default to 30 minutes if not set - $timeoutDirective = $proxyTimeout > 0 ? "proxy_timeout {$proxyTimeout}s;" : ""; + $timeoutDirective = "proxy_timeout {$proxyTimeout}s;"; $nginxconf = << Date: Tue, 23 Dec 2025 17:52:29 +0100 Subject: [PATCH 3/6] feat: extend database proxy timeout cap to support week-long ETL jobs --- app/Actions/Database/StartDatabaseProxy.php | 4 ++-- app/Livewire/Project/Database/Clickhouse/General.php | 2 +- app/Livewire/Project/Database/Dragonfly/General.php | 2 +- app/Livewire/Project/Database/Keydb/General.php | 2 +- app/Livewire/Project/Database/Mariadb/General.php | 3 +-- app/Livewire/Project/Database/Mongodb/General.php | 2 +- app/Livewire/Project/Database/Mysql/General.php | 2 +- app/Livewire/Project/Database/Postgresql/General.php | 2 +- app/Livewire/Project/Database/Redis/General.php | 2 +- app/Livewire/Project/Service/Database.php | 2 +- .../livewire/project/database/clickhouse/general.blade.php | 2 +- .../livewire/project/database/dragonfly/general.blade.php | 2 +- .../views/livewire/project/database/keydb/general.blade.php | 2 +- .../views/livewire/project/database/mariadb/general.blade.php | 2 +- .../views/livewire/project/database/mongodb/general.blade.php | 2 +- .../views/livewire/project/database/mysql/general.blade.php | 2 +- .../livewire/project/database/postgresql/general.blade.php | 2 +- .../views/livewire/project/database/redis/general.blade.php | 2 +- resources/views/livewire/project/service/database.blade.php | 2 +- 19 files changed, 20 insertions(+), 21 deletions(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index c44a69737..4374c6eac 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -29,8 +29,8 @@ class StartDatabaseProxy if ($database->proxy_timeout <= 0) { throw new \Exception('Proxy timeout must be greater than 0.'); } - if ($database->proxy_timeout > 86400) { - throw new \Exception('Proxy timeout must not exceed 86400 seconds (24 hours).'); + if ($database->proxy_timeout > 31536000) { + throw new \Exception('Proxy timeout must not exceed 31536000 seconds (1 year).'); } $databaseType = $database->database_type; diff --git a/app/Livewire/Project/Database/Clickhouse/General.php b/app/Livewire/Project/Database/Clickhouse/General.php index 35992e65f..dda8f32f9 100644 --- a/app/Livewire/Project/Database/Clickhouse/General.php +++ b/app/Livewire/Project/Database/Clickhouse/General.php @@ -82,7 +82,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', diff --git a/app/Livewire/Project/Database/Dragonfly/General.php b/app/Livewire/Project/Database/Dragonfly/General.php index 737f71de8..6a5d693ad 100644 --- a/app/Livewire/Project/Database/Dragonfly/General.php +++ b/app/Livewire/Project/Database/Dragonfly/General.php @@ -93,7 +93,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', diff --git a/app/Livewire/Project/Database/Keydb/General.php b/app/Livewire/Project/Database/Keydb/General.php index bf4a3abdf..f5cf75bc8 100644 --- a/app/Livewire/Project/Database/Keydb/General.php +++ b/app/Livewire/Project/Database/Keydb/General.php @@ -96,7 +96,7 @@ class General extends Component 'portsMappings' => 'nullable|string', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'customDockerRunOptions' => 'nullable|string', 'dbUrl' => 'nullable|string', 'dbUrlPublic' => 'nullable|string', diff --git a/app/Livewire/Project/Database/Mariadb/General.php b/app/Livewire/Project/Database/Mariadb/General.php index a4c529ee5..048e3866b 100644 --- a/app/Livewire/Project/Database/Mariadb/General.php +++ b/app/Livewire/Project/Database/Mariadb/General.php @@ -81,8 +81,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', diff --git a/app/Livewire/Project/Database/Mongodb/General.php b/app/Livewire/Project/Database/Mongodb/General.php index 03bc6be5f..d0f8961d6 100644 --- a/app/Livewire/Project/Database/Mongodb/General.php +++ b/app/Livewire/Project/Database/Mongodb/General.php @@ -80,7 +80,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', diff --git a/app/Livewire/Project/Database/Mysql/General.php b/app/Livewire/Project/Database/Mysql/General.php index 2cec4306c..21d7554fa 100644 --- a/app/Livewire/Project/Database/Mysql/General.php +++ b/app/Livewire/Project/Database/Mysql/General.php @@ -83,7 +83,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', diff --git a/app/Livewire/Project/Database/Postgresql/General.php b/app/Livewire/Project/Database/Postgresql/General.php index d34418157..119bea8f5 100644 --- a/app/Livewire/Project/Database/Postgresql/General.php +++ b/app/Livewire/Project/Database/Postgresql/General.php @@ -95,7 +95,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'enableSsl' => 'boolean', diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index e5d8d14bd..00c3d31d3 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -76,7 +76,7 @@ class General extends Component 'portsMappings' => 'nullable', 'isPublic' => 'nullable|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isLogDrainEnabled' => 'nullable|boolean', 'customDockerRunOptions' => 'nullable', 'redisUsername' => 'required', diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php index 0e1eb3e30..e53fb682b 100644 --- a/app/Livewire/Project/Service/Database.php +++ b/app/Livewire/Project/Service/Database.php @@ -45,7 +45,7 @@ class Database extends Component 'image' => 'required', 'excludeFromStatus' => 'required|boolean', 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:86400', + 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', 'isPublic' => 'required|boolean', 'isLogDrainEnabled' => 'required|boolean', ]; diff --git a/resources/views/livewire/project/database/clickhouse/general.blade.php b/resources/views/livewire/project/database/clickhouse/general.blade.php index bff3cadd1..46e778ce5 100644 --- a/resources/views/livewire/project/database/clickhouse/general.blade.php +++ b/resources/views/livewire/project/database/clickhouse/general.blade.php @@ -81,7 +81,7 @@ canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/dragonfly/general.blade.php b/resources/views/livewire/project/database/dragonfly/general.blade.php index 1537720f1..c960e9dc5 100644 --- a/resources/views/livewire/project/database/dragonfly/general.blade.php +++ b/resources/views/livewire/project/database/dragonfly/general.blade.php @@ -118,7 +118,7 @@ canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/keydb/general.blade.php b/resources/views/livewire/project/database/keydb/general.blade.php index 650ef6e33..bfcc1cbb5 100644 --- a/resources/views/livewire/project/database/keydb/general.blade.php +++ b/resources/views/livewire/project/database/keydb/general.blade.php @@ -118,7 +118,7 @@ canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/mariadb/general.blade.php b/resources/views/livewire/project/database/mariadb/general.blade.php index 6154f9052..75e7321b0 100644 --- a/resources/views/livewire/project/database/mariadb/general.blade.php +++ b/resources/views/livewire/project/database/mariadb/general.blade.php @@ -142,7 +142,7 @@ id="publicPort" label="Public Port" canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/mongodb/general.blade.php b/resources/views/livewire/project/database/mongodb/general.blade.php index b9098ae7e..e6754798c 100644 --- a/resources/views/livewire/project/database/mongodb/general.blade.php +++ b/resources/views/livewire/project/database/mongodb/general.blade.php @@ -156,7 +156,7 @@ id="publicPort" label="Public Port" canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/mysql/general.blade.php b/resources/views/livewire/project/database/mysql/general.blade.php index e49b3310e..5c20a46ac 100644 --- a/resources/views/livewire/project/database/mysql/general.blade.php +++ b/resources/views/livewire/project/database/mysql/general.blade.php @@ -158,7 +158,7 @@ id="publicPort" label="Public Port" canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/postgresql/general.blade.php b/resources/views/livewire/project/database/postgresql/general.blade.php index 42b43e9c0..785c6b259 100644 --- a/resources/views/livewire/project/database/postgresql/general.blade.php +++ b/resources/views/livewire/project/database/postgresql/general.blade.php @@ -168,7 +168,7 @@ label="Public Port" canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index b85a76424..1c9809b51 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -137,7 +137,7 @@ id="publicPort" label="Public Port" canGate="update" :canResource="$database" /> diff --git a/resources/views/livewire/project/service/database.blade.php b/resources/views/livewire/project/service/database.blade.php index 6d6d27541..87f3b0924 100644 --- a/resources/views/livewire/project/service/database.blade.php +++ b/resources/views/livewire/project/service/database.blade.php @@ -34,7 +34,7 @@ label="Public Port" /> + helper="Maximum time in seconds to keep connections open. Default is 1800 seconds (30 minutes) and max is 31536000 seconds (1 year)" /> @if ($db_url_public) From 0b0831d9423370073e377161f7f4c4a3667c2452 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Tue, 23 Dec 2025 17:57:02 +0100 Subject: [PATCH 4/6] chore: enable database proxy TCP keepalive to stabilize long-lived stream connections --- app/Actions/Database/StartDatabaseProxy.php | 1 + 1 file changed, 1 insertion(+) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 4374c6eac..55a876868 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -81,6 +81,7 @@ class StartDatabaseProxy server { listen $database->public_port; proxy_pass $containerName:$internalPort; + proxy_socket_keepalive on; {$timeoutDirective} } } From dab0a05d3e971add1f5933439eee137a296b1248 Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Mon, 5 Jan 2026 14:22:46 +0100 Subject: [PATCH 5/6] Resolve merge conflicts with next branch - Combine proxy timeout validation with proxy_socket_keepalive refactor - Fix duplicate proxyTimeout entry in Mariadb validation attributes --- app/Actions/Database/StartDatabaseProxy.php | 3 +-- app/Livewire/Project/Database/Mariadb/General.php | 1 - 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/app/Actions/Database/StartDatabaseProxy.php b/app/Actions/Database/StartDatabaseProxy.php index 55a876868..a01d0ea48 100644 --- a/app/Actions/Database/StartDatabaseProxy.php +++ b/app/Actions/Database/StartDatabaseProxy.php @@ -44,7 +44,6 @@ class StartDatabaseProxy $databaseType = $database->databaseType(); $network = $database->service->uuid; $server = data_get($database, 'service.destination.server'); - $proxyContainerName = "{$database->service->uuid}-proxy"; $containerName = "{$database->name}-{$database->service->uuid}"; } $internalPort = match ($databaseType) { @@ -66,7 +65,7 @@ class StartDatabaseProxy if (isDev()) { $configuration_dir = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/databases/'.$database->uuid.'/proxy'; } - $proxyTimeout = $database->proxy_timeout ?? 1800; // Default to 30 minutes if not set + $proxyTimeout = $database->proxy_timeout ?? 1800; $timeoutDirective = "proxy_timeout {$proxyTimeout}s;"; $nginxconf = << 'Is Public', 'publicPort' => 'Public Port', 'proxyTimeout' => 'Proxy Timeout', - 'proxyTimeout' => 'Proxy Timeout', 'customDockerRunOptions' => 'Custom Docker Options', 'enableSsl' => 'Enable SSL', ]; From 5c4b34c497d284ec551c62ebd8f4ae70972c8d5a Mon Sep 17 00:00:00 2001 From: ShadowArcanist <162910371+ShadowArcanist@users.noreply.github.com> Date: Mon, 5 Jan 2026 14:24:33 +0100 Subject: [PATCH 6/6] Remove files deleted in next branch These files were removed in next branch as part of a refactor. Removing them to resolve merge conflicts. --- app/Livewire/Project/Service/Database.php | 233 ------------------ .../project/service/database.blade.php | 55 ----- 2 files changed, 288 deletions(-) delete mode 100644 app/Livewire/Project/Service/Database.php delete mode 100644 resources/views/livewire/project/service/database.blade.php diff --git a/app/Livewire/Project/Service/Database.php b/app/Livewire/Project/Service/Database.php deleted file mode 100644 index e53fb682b..000000000 --- a/app/Livewire/Project/Service/Database.php +++ /dev/null @@ -1,233 +0,0 @@ - 'nullable', - 'description' => 'nullable', - 'image' => 'required', - 'excludeFromStatus' => 'required|boolean', - 'publicPort' => 'nullable|integer', - 'proxyTimeout' => 'nullable|integer|min:0|max:31536000', - 'isPublic' => 'required|boolean', - 'isLogDrainEnabled' => 'required|boolean', - ]; - - public function render() - { - return view('livewire.project.service.database'); - } - - public function mount() - { - try { - $this->parameters = get_route_parameters(); - $this->authorize('view', $this->database); - if ($this->database->is_public) { - $this->db_url_public = $this->database->getServiceDatabaseUrl(); - } - $this->refreshFileStorages(); - $this->syncData(false); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - private function syncData(bool $toModel = false): void - { - if ($toModel) { - $this->database->human_name = $this->humanName; - $this->database->description = $this->description; - $this->database->image = $this->image; - $this->database->exclude_from_status = $this->excludeFromStatus; - $this->database->public_port = $this->publicPort; - $this->database->proxy_timeout = $this->proxyTimeout; - $this->database->is_public = $this->isPublic; - $this->database->is_log_drain_enabled = $this->isLogDrainEnabled; - } else { - $this->humanName = $this->database->human_name; - $this->description = $this->database->description; - $this->image = $this->database->image; - $this->excludeFromStatus = $this->database->exclude_from_status ?? false; - $this->publicPort = $this->database->public_port; - $this->proxyTimeout = $this->database->proxy_timeout; - $this->isPublic = $this->database->is_public ?? false; - $this->isLogDrainEnabled = $this->database->is_log_drain_enabled ?? false; - } - } - - public function delete($password) - { - try { - $this->authorize('delete', $this->database); - - if (! verifyPasswordConfirmation($password, $this)) { - return; - } - - $this->database->delete(); - $this->dispatch('success', 'Database deleted.'); - - return redirect()->route('project.service.configuration', $this->parameters); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSaveExclude() - { - try { - $this->authorize('update', $this->database); - $this->submit(); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSaveLogDrain() - { - try { - $this->authorize('update', $this->database); - if (! $this->database->service->destination->server->isLogDrainEnabled()) { - $this->isLogDrainEnabled = false; - $this->dispatch('error', 'Log drain is not enabled on the server. Please enable it first.'); - - return; - } - $this->submit(); - $this->dispatch('success', 'You need to restart the service for the changes to take effect.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function convertToApplication() - { - try { - $this->authorize('update', $this->database); - $service = $this->database->service; - $serviceDatabase = $this->database; - - // Check if application with same name already exists - if ($service->applications()->where('name', $serviceDatabase->name)->exists()) { - throw new \Exception('An application with this name already exists.'); - } - - // Create new parameters removing database_uuid - $redirectParams = collect($this->parameters) - ->except('database_uuid') - ->all(); - - DB::transaction(function () use ($service, $serviceDatabase) { - $service->applications()->create([ - 'name' => $serviceDatabase->name, - 'human_name' => $serviceDatabase->human_name, - 'description' => $serviceDatabase->description, - 'exclude_from_status' => $serviceDatabase->exclude_from_status, - 'is_log_drain_enabled' => $serviceDatabase->is_log_drain_enabled, - 'image' => $serviceDatabase->image, - 'service_id' => $service->id, - 'is_migrated' => true, - ]); - $serviceDatabase->delete(); - }); - - return redirect()->route('project.service.configuration', $redirectParams); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function instantSave() - { - try { - $this->authorize('update', $this->database); - if ($this->isPublic && ! $this->publicPort) { - $this->dispatch('error', 'Public port is required.'); - $this->isPublic = false; - - return; - } - $this->syncData(true); - if ($this->database->is_public) { - if (! str($this->database->status)->startsWith('running')) { - $this->dispatch('error', 'Database must be started to be publicly accessible.'); - $this->isPublic = false; - $this->database->is_public = false; - - return; - } - StartDatabaseProxy::run($this->database); - $this->db_url_public = $this->database->getServiceDatabaseUrl(); - $this->dispatch('success', 'Database is now publicly accessible.'); - } else { - StopDatabaseProxy::run($this->database); - $this->db_url_public = null; - $this->dispatch('success', 'Database is no longer publicly accessible.'); - } - $this->submit(); - } catch (\Throwable $e) { - return handleError($e, $this); - } - } - - public function refreshFileStorages() - { - $this->fileStorages = $this->database->fileStorages()->get(); - } - - public function submit() - { - try { - $this->authorize('update', $this->database); - $this->validate(); - $this->syncData(true); - $this->database->save(); - $this->database->refresh(); - $this->syncData(false); - updateCompose($this->database); - $this->dispatch('success', 'Database saved.'); - } catch (\Throwable $e) { - return handleError($e, $this); - } finally { - $this->dispatch('generateDockerCompose'); - } - } -} diff --git a/resources/views/livewire/project/service/database.blade.php b/resources/views/livewire/project/service/database.blade.php deleted file mode 100644 index 87f3b0924..000000000 --- a/resources/views/livewire/project/service/database.blade.php +++ /dev/null @@ -1,55 +0,0 @@ -
-
-
- @if ($database->human_name) -

{{ Str::headline($database->human_name) }}

- @else -

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

- @endif - Save - @can('update', $database) - - @endcan - @can('delete', $database) - - @endcan -
-
-
- - - -
-
- - - -
- @if ($db_url_public) - - @endif -
-

Advanced

-
- - -
-
-