From e77e807cdd830b71e0d6885b417c0ab14ef7de0f Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 15:54:16 +0200 Subject: [PATCH 01/18] Add UI --- .../project/database/redis/general.blade.php | 35 ++++++++----------- 1 file changed, 14 insertions(+), 21 deletions(-) diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index ceb12a802..35ee90583 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -9,48 +9,41 @@
- + +
+
+ +

Network

- +
- + @if ($db_url_public) - + @endif

Proxy

- + Proxy Logs - + - Proxy Logs + Proxy Logs
- +

Advanced

- +
+ From a2ba67ea34f33cad2bfeacf928ead01fa9a90baf Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:19:36 +0200 Subject: [PATCH 02/18] Add redis username --- app/Actions/Database/StartRedis.php | 16 +++++++++++- .../Project/Database/Redis/General.php | 25 ++++++++++++++++--- 2 files changed, 37 insertions(+), 4 deletions(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index f10afef5e..b3f240942 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -166,6 +166,14 @@ private function generate_environment_variables() $environment_variables->push("$env->key=$env->real_value"); } + $redis_version = $this->get_redis_version(); + + if (version_compare($redis_version, '6.0', '>=')) { + if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_USERNAME'))->isEmpty()) { + $environment_variables->push("REDIS_USERNAME={$this->database->redis_username}"); + } + } + if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) { $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); } @@ -173,6 +181,12 @@ private function generate_environment_variables() return $environment_variables->all(); } + private function get_redis_version() + { + $image_parts = explode(':', $this->database->image); + return $image_parts[1] ?? '0.0'; + } + private function add_custom_redis() { if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) { @@ -184,4 +198,4 @@ private function add_custom_redis() instant_scp($path, "{$this->configuration_dir}/{$filename}", $this->database->destination->server); Storage::disk('local')->delete("tmp/redis.conf_{$this->database->uuid}"); } -} +} \ No newline at end of file diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index a7ce0161a..6acd1095f 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -25,6 +25,7 @@ class General extends Component 'database.name' => 'required', 'database.description' => 'nullable', 'database.redis_conf' => 'nullable', + 'database.redis_username' => 'required', 'database.redis_password' => 'required', 'database.image' => 'required', 'database.ports_mappings' => 'nullable', @@ -37,6 +38,7 @@ class General extends Component 'database.name' => 'Name', 'database.description' => 'Description', 'database.redis_conf' => 'Redis Configuration', + 'database.redis_username' => 'Redis Username', 'database.redis_password' => 'Redis Password', 'database.image' => 'Image', 'database.ports_mappings' => 'Port Mapping', @@ -73,16 +75,33 @@ public function submit() { try { $this->validate(); - if ($this->database->redis_conf === '') { - $this->database->redis_conf = null; + + $redis_version = $this->get_redis_version(); + + if (version_compare($redis_version, '6.0', '>=')) { + if ($this->database->isDirty('redis_username')) { + $this->database->redis_username = $this->database->redis_username; + } } + + if ($this->database->isDirty('redis_password')) { + $this->database->redis_password = $this->database->redis_password; + } + $this->database->save(); + $this->dispatch('success', 'Database updated.'); } catch (Exception $e) { return handleError($e, $this); } } + private function get_redis_version() + { + $image_parts = explode(':', $this->database->image); + return $image_parts[1] ?? '0.0'; + } + public function instantSave() { try { @@ -123,4 +142,4 @@ public function render() { return view('livewire.project.database.redis.general'); } -} +} \ No newline at end of file From 388f8c4e9533bdaa5f21398bde0119dded3095e5 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:20:03 +0200 Subject: [PATCH 03/18] Security fix redis password and username logic --- app/Models/StandaloneRedis.php | 27 +++++++++++++++++++++++---- 1 file changed, 23 insertions(+), 4 deletions(-) diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index 8a202ea9e..b08825bd4 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -16,6 +16,14 @@ class StandaloneRedis extends BaseModel protected $appends = ['internal_db_url', 'external_db_url', 'database_type', 'server_status']; + protected $casts = [ + 'redis_password' => 'encrypted', + ]; + + protected $attributes = [ + 'redis_username' => 'redis', + ]; + protected static function booted() { static::created(function ($database) { @@ -205,7 +213,11 @@ public function databaseType(): Attribute protected function internalDbUrl(): Attribute { return new Attribute( - get: fn () => "redis://:{$this->redis_password}@{$this->uuid}:6379/0", + get: function () { + $redis_version = $this->get_redis_version(); + $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ""; + return "redis://{$username_part}{$this->redis_password}@{$this->uuid}:6379/0"; + } ); } @@ -214,14 +226,21 @@ protected function externalDbUrl(): Attribute return new Attribute( get: function () { if ($this->is_public && $this->public_port) { - return "redis://:{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0"; + $redis_version = $this->get_redis_version(); + $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ""; + return "redis://{$username_part}{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0"; } - return null; } ); } + private function get_redis_version() + { + $image_parts = explode(':', $this->image); + return $image_parts[1] ?? '0.0'; + } + public function environment() { return $this->belongsTo(Environment::class); @@ -285,4 +304,4 @@ public function getMetrics(int $mins = 5) return $parsedCollection->toArray(); } } -} +} \ No newline at end of file From ae7e5487791c08a0f0a40ad5554af81050346876 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:20:15 +0200 Subject: [PATCH 04/18] DB migration for redis username --- ...dis_username_to_standalone_redis_table.php | 22 +++++++++++++++++++ 1 file changed, 22 insertions(+) create mode 100644 database/migrations/2024_08_21_165435_add_redis_username_to_standalone_redis_table.php diff --git a/database/migrations/2024_08_21_165435_add_redis_username_to_standalone_redis_table.php b/database/migrations/2024_08_21_165435_add_redis_username_to_standalone_redis_table.php new file mode 100644 index 000000000..397c6a68f --- /dev/null +++ b/database/migrations/2024_08_21_165435_add_redis_username_to_standalone_redis_table.php @@ -0,0 +1,22 @@ +string('redis_username')->default('redis')->after('description'); + }); + } + + public function down(): void + { + Schema::table('standalone_redis', function (Blueprint $table) { + $table->dropColumn('redis_username'); + }); + } +}; From 68060ef37dbe94c675925ad01b09ed05fbaab5ac Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:20:28 +0200 Subject: [PATCH 05/18] typo in redis seeder --- database/seeders/StandaloneRedisSeeder.php | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/database/seeders/StandaloneRedisSeeder.php b/database/seeders/StandaloneRedisSeeder.php index e7bf3373e..7c64b17a2 100644 --- a/database/seeders/StandaloneRedisSeeder.php +++ b/database/seeders/StandaloneRedisSeeder.php @@ -11,8 +11,9 @@ class StandaloneRedisSeeder extends Seeder public function run(): void { StandaloneRedis::create([ - 'name' => 'Local PostgreSQL', - 'description' => 'Local PostgreSQL for testing', + 'name' => 'Local Redis', + 'description' => 'Local Redis for testing', + 'redis_username' => 'redis', 'redis_password' => 'redis', 'environment_id' => 1, 'destination_id' => 0, From 462acda233507c19acd541f9b3d6a2893e2a7a8a Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Wed, 21 Aug 2024 19:20:46 +0200 Subject: [PATCH 06/18] Feat: add UI for redis password and username --- .../livewire/project/database/redis/general.blade.php | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index 35ee90583..e062a4bcd 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -12,8 +12,13 @@
- - + @php + $redis_version = explode(':', $database->image)[1] ?? '0.0'; + @endphp + @if (version_compare($redis_version, '6.0', '>=')) + + @endif +

Network

@@ -46,4 +51,4 @@
- + \ No newline at end of file From 3d7a467abf936f50167cf06445c4b61d008c2ae3 Mon Sep 17 00:00:00 2001 From: ayntk-ai <122374094+ayntk-ai@users.noreply.github.com> Date: Fri, 23 Aug 2024 19:00:18 +0200 Subject: [PATCH 07/18] WIP WIP --- app/Actions/Database/StartRedis.php | 56 +++++++++++++++++++++++++---- 1 file changed, 49 insertions(+), 7 deletions(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index b3f240942..6d1548357 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -20,10 +20,42 @@ class StartRedis public function handle(StandaloneRedis $database) { $this->database = $database; + //$this->configuration_dir = database_configuration_dir().'/'.$this->database->uuid; + + //$this->add_custom_redis(); + + // $startCommand = "redis-server"; + // $additionalArgs = []; + + // if (!is_null($this->database->redis_conf) && !empty($this->database->redis_conf)) { + // ray("Using custom Redis configuration"); + // $additionalArgs[] = "{$this->configuration_dir}/redis.conf"; + + // // Check if the custom config contains a requirepass directive + // $configContent = file_get_contents("{$this->configuration_dir}/redis.conf"); + // if (strpos($configContent, 'requirepass') === false) { + // $additionalArgs[] = "--requirepass {$this->database->redis_password}"; + // ray("No requirepass in custom config, adding it as an argument"); + // } else { + // ray("requirepass found in custom config"); + // } + // } else { + // $additionalArgs[] = "--requirepass {$this->database->redis_password}"; + // $additionalArgs[] = "--appendonly yes"; + // ray("No custom config, using default arguments"); + // } + + // if (!empty($additionalArgs)) { + // $startCommand .= " " . implode(" ", $additionalArgs); + // } + + // ray("Final start command: " . $startCommand); $startCommand = "redis-server --requirepass {$this->database->redis_password} --appendonly yes"; + $container_name = $this->database->uuid; + $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ @@ -31,12 +63,14 @@ public function handle(StandaloneRedis $database) "mkdir -p $this->configuration_dir", ]; + $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_redis(); + $docker_compose = [ 'services' => [ $container_name => [ @@ -113,6 +147,7 @@ public function handle(StandaloneRedis $database) 'read_only' => true, ]; $docker_compose['services'][$container_name]['command'] = "redis-server /usr/local/etc/redis/redis.conf --requirepass {$this->database->redis_password} --appendonly yes"; + } $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); @@ -178,13 +213,20 @@ private function generate_environment_variables() $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); } - return $environment_variables->all(); - } + ray('Initial environment variables:', $environment_variables->toArray()); - private function get_redis_version() - { - $image_parts = explode(':', $this->database->image); - return $image_parts[1] ?? '0.0'; + // Overwrite with UI-set environment variables + $ui_variables = $this->database->environment_variables()->get();//this is working + ray('UI-set environment variables:', $ui_variables->toArray()); + + foreach ($ui_variables as $ui_variable) { //the overwrite is not working it is set wrong + $environment_variables = $environment_variables->reject(fn ($env) => str($env)->startsWith("{$ui_variable->key}=")); + $environment_variables->push("{$ui_variable->key}={$ui_variable->real_value}"); + } + + ray('Final environment variables:', $environment_variables->toArray()); + + return $environment_variables->all(); } private function add_custom_redis() @@ -194,7 +236,7 @@ private function add_custom_redis() } $filename = 'redis.conf'; Storage::disk('local')->put("tmp/redis.conf_{$this->database->uuid}", $this->database->redis_conf); - $path = Storage::path("tmp/redis.conf_{$this->database->uuid}"); + $path = Storage::path("tmp/redis.conf_{$this->database->uuid}"); instant_scp($path, "{$this->configuration_dir}/{$filename}", $this->database->destination->server); Storage::disk('local')->delete("tmp/redis.conf_{$this->database->uuid}"); } From 1ae145bf13de253107537b3b0018e9b433b95418 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 26 Sep 2024 19:49:33 +0200 Subject: [PATCH 08/18] Revert "typo in redis seeder" This reverts commit 68060ef37dbe94c675925ad01b09ed05fbaab5ac. --- database/seeders/StandaloneRedisSeeder.php | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/database/seeders/StandaloneRedisSeeder.php b/database/seeders/StandaloneRedisSeeder.php index 7c64b17a2..e7bf3373e 100644 --- a/database/seeders/StandaloneRedisSeeder.php +++ b/database/seeders/StandaloneRedisSeeder.php @@ -11,9 +11,8 @@ class StandaloneRedisSeeder extends Seeder public function run(): void { StandaloneRedis::create([ - 'name' => 'Local Redis', - 'description' => 'Local Redis for testing', - 'redis_username' => 'redis', + 'name' => 'Local PostgreSQL', + 'description' => 'Local PostgreSQL for testing', 'redis_password' => 'redis', 'environment_id' => 1, 'destination_id' => 0, From e5b798964dce9489d0391b7337f850789801e658 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Thu, 26 Sep 2024 20:01:35 +0200 Subject: [PATCH 09/18] Update StartRedis.php --- app/Actions/Database/StartRedis.php | 74 ++++------------------------- 1 file changed, 9 insertions(+), 65 deletions(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 6d1548357..eeddab924 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -20,42 +20,10 @@ class StartRedis public function handle(StandaloneRedis $database) { $this->database = $database; - //$this->configuration_dir = database_configuration_dir().'/'.$this->database->uuid; - - //$this->add_custom_redis(); - - // $startCommand = "redis-server"; - // $additionalArgs = []; - - // if (!is_null($this->database->redis_conf) && !empty($this->database->redis_conf)) { - // ray("Using custom Redis configuration"); - // $additionalArgs[] = "{$this->configuration_dir}/redis.conf"; - - // // Check if the custom config contains a requirepass directive - // $configContent = file_get_contents("{$this->configuration_dir}/redis.conf"); - // if (strpos($configContent, 'requirepass') === false) { - // $additionalArgs[] = "--requirepass {$this->database->redis_password}"; - // ray("No requirepass in custom config, adding it as an argument"); - // } else { - // ray("requirepass found in custom config"); - // } - // } else { - // $additionalArgs[] = "--requirepass {$this->database->redis_password}"; - // $additionalArgs[] = "--appendonly yes"; - // ray("No custom config, using default arguments"); - // } - - // if (!empty($additionalArgs)) { - // $startCommand .= " " . implode(" ", $additionalArgs); - // } - - // ray("Final start command: " . $startCommand); $startCommand = "redis-server --requirepass {$this->database->redis_password} --appendonly yes"; - $container_name = $this->database->uuid; - $this->configuration_dir = database_configuration_dir().'/'.$container_name; $this->commands = [ @@ -63,14 +31,12 @@ public function handle(StandaloneRedis $database) "mkdir -p $this->configuration_dir", ]; - $persistent_storages = $this->generate_local_persistent_volumes(); $persistent_file_volumes = $this->database->fileStorages()->get(); $volume_names = $this->generate_local_persistent_volumes_only_volume_names(); $environment_variables = $this->generate_environment_variables(); $this->add_custom_redis(); - $docker_compose = [ 'services' => [ $container_name => [ @@ -116,14 +82,7 @@ public function handle(StandaloneRedis $database) data_set($docker_compose, "services.{$container_name}.cpuset", $this->database->limits_cpuset); } if ($this->database->destination->server->isLogDrainEnabled() && $this->database->isLogDrainEnabled()) { - $docker_compose['services'][$container_name]['logging'] = [ - 'driver' => 'fluentd', - 'options' => [ - 'fluentd-address' => 'tcp://127.0.0.1:24224', - 'fluentd-async' => 'true', - 'fluentd-sub-second-precision' => 'true', - ], - ]; + $docker_compose['services'][$container_name]['logging'] = generate_fluentd_configuration(); } if (count($this->database->ports_mappings_array) > 0) { $docker_compose['services'][$container_name]['ports'] = $this->database->ports_mappings_array; @@ -147,8 +106,12 @@ public function handle(StandaloneRedis $database) 'read_only' => true, ]; $docker_compose['services'][$container_name]['command'] = "redis-server /usr/local/etc/redis/redis.conf --requirepass {$this->database->redis_password} --appendonly yes"; - } + + // Add custom docker run options + $docker_run_options = convert_docker_run_to_compose($this->database->custom_docker_run_options); + $docker_compose = generate_custom_docker_run_options_for_databases($docker_run_options, $docker_compose, $container_name, $this->database->destination->network); + $docker_compose = Yaml::dump($docker_compose, 10); $docker_compose_base64 = base64_encode($docker_compose); $this->commands[] = "echo '{$docker_compose_base64}' | base64 -d | tee $this->configuration_dir/docker-compose.yml > /dev/null"; @@ -201,30 +164,11 @@ private function generate_environment_variables() $environment_variables->push("$env->key=$env->real_value"); } - $redis_version = $this->get_redis_version(); - - if (version_compare($redis_version, '6.0', '>=')) { - if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_USERNAME'))->isEmpty()) { - $environment_variables->push("REDIS_USERNAME={$this->database->redis_username}"); - } - } - if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) { $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); } - ray('Initial environment variables:', $environment_variables->toArray()); - - // Overwrite with UI-set environment variables - $ui_variables = $this->database->environment_variables()->get();//this is working - ray('UI-set environment variables:', $ui_variables->toArray()); - - foreach ($ui_variables as $ui_variable) { //the overwrite is not working it is set wrong - $environment_variables = $environment_variables->reject(fn ($env) => str($env)->startsWith("{$ui_variable->key}=")); - $environment_variables->push("{$ui_variable->key}={$ui_variable->real_value}"); - } - - ray('Final environment variables:', $environment_variables->toArray()); + add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); return $environment_variables->all(); } @@ -236,8 +180,8 @@ private function add_custom_redis() } $filename = 'redis.conf'; Storage::disk('local')->put("tmp/redis.conf_{$this->database->uuid}", $this->database->redis_conf); - $path = Storage::path("tmp/redis.conf_{$this->database->uuid}"); + $path = Storage::path("tmp/redis.conf_{$this->database->uuid}"); instant_scp($path, "{$this->configuration_dir}/{$filename}", $this->database->destination->server); Storage::disk('local')->delete("tmp/redis.conf_{$this->database->uuid}"); } -} \ No newline at end of file +} From 902cde59057ead5d7dda36f0096d041a8cc2019f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:19:04 +0200 Subject: [PATCH 10/18] improve custom redis.conf --- app/Actions/Database/StartRedis.php | 24 +++++++++++++++++++++++- 1 file changed, 23 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index eeddab924..186ad0432 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -37,6 +37,8 @@ public function handle(StandaloneRedis $database) $environment_variables = $this->generate_environment_variables(); $this->add_custom_redis(); + $startCommand = $this->buildStartCommand(); + $docker_compose = [ 'services' => [ $container_name => [ @@ -105,7 +107,6 @@ public function handle(StandaloneRedis $database) 'target' => '/usr/local/etc/redis/redis.conf', 'read_only' => true, ]; - $docker_compose['services'][$container_name]['command'] = "redis-server /usr/local/etc/redis/redis.conf --requirepass {$this->database->redis_password} --appendonly yes"; } // Add custom docker run options @@ -173,6 +174,27 @@ private function generate_environment_variables() return $environment_variables->all(); } + private function buildStartCommand(): string + { + $hasRedisConf = ! is_null($this->database->redis_conf) && ! empty($this->database->redis_conf); + $redisConfPath = '/usr/local/etc/redis/redis.conf'; + + if ($hasRedisConf) { + $confContent = $this->database->redis_conf; + $hasRequirePass = str_contains($confContent, 'requirepass'); + + if ($hasRequirePass) { + $command = "redis-server $redisConfPath"; + } else { + $command = "redis-server $redisConfPath --requirepass {$this->database->redis_password}"; + } + } else { + $command = "redis-server --requirepass {$this->database->redis_password} --appendonly yes"; + } + + return $command; + } + private function add_custom_redis() { if (is_null($this->database->redis_conf) || empty($this->database->redis_conf)) { From c6e2c7e5e3f9531699d48f19986c476d2b198998 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 15 Oct 2024 16:35:20 +0200 Subject: [PATCH 11/18] fix start command --- app/Actions/Database/StartRedis.php | 2 -- 1 file changed, 2 deletions(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 186ad0432..3e3c5b3b9 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -21,8 +21,6 @@ public function handle(StandaloneRedis $database) { $this->database = $database; - $startCommand = "redis-server --requirepass {$this->database->redis_password} --appendonly yes"; - $container_name = $this->database->uuid; $this->configuration_dir = database_configuration_dir().'/'.$container_name; From 79caa3c26bcf0224cdfb3de30170d3fde884c66f Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:02:37 +0200 Subject: [PATCH 12/18] fix: allow setting standalone redis variables via ENVs (team variables...) --- app/Actions/Database/StartRedis.php | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 3e3c5b3b9..45a031e70 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -159,12 +159,29 @@ private function generate_local_persistent_volumes_only_volume_names() private function generate_environment_variables() { $environment_variables = collect(); + $redis_password = null; + $redis_username = null; + foreach ($this->database->runtime_environment_variables as $env) { $environment_variables->push("$env->key=$env->real_value"); + + if ($env->key === 'REDIS_PASSWORD') { + $redis_password = $env->real_value; + } elseif ($env->key === 'REDIS_USERNAME') { + $redis_username = $env->real_value; + } } - if ($environment_variables->filter(fn ($env) => str($env)->contains('REDIS_PASSWORD'))->isEmpty()) { + if (is_null($redis_password)) { $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); + } else { + $this->database->update(['redis_password' => $redis_password]); + } + + if (is_null($redis_username)) { + $environment_variables->push("REDIS_USERNAME={$this->database->redis_username}"); + } else { + $this->database->update(['redis_username' => $redis_username]); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); From 5274ae1f0b578ab4b27bc4646c1ac2cb86805c93 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:23:33 +0200 Subject: [PATCH 13/18] fix: check for username separately form password --- app/Actions/Database/StartRedis.php | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 45a031e70..56be36202 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -167,7 +167,9 @@ private function generate_environment_variables() if ($env->key === 'REDIS_PASSWORD') { $redis_password = $env->real_value; - } elseif ($env->key === 'REDIS_USERNAME') { + } + + if ($env->key === 'REDIS_USERNAME') { $redis_username = $env->real_value; } } From edad4fcd5c0b8bdc89e4e590b8336956967df635 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Tue, 15 Oct 2024 17:38:11 +0200 Subject: [PATCH 14/18] update helper text --- .../livewire/project/database/redis/general.blade.php | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index c76229d28..c5ab13d94 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -16,9 +16,11 @@ $redis_version = explode(':', $database->image)[1] ?? '0.0'; @endphp @if (version_compare($redis_version, '6.0', '>=')) - + @endif - + - \ No newline at end of file + From b9c9c1041a911824f5630b8cad87476205587558 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:20:26 +0200 Subject: [PATCH 15/18] feat: add is shared to env variables --- app/Models/EnvironmentVariable.php | 10 +++++++++ ...add_is_shared_to_environment_variables.php | 22 +++++++++++++++++++ 2 files changed, 32 insertions(+) create mode 100644 database/migrations/2024_10_15_172139_add_is_shared_to_environment_variables.php diff --git a/app/Models/EnvironmentVariable.php b/app/Models/EnvironmentVariable.php index 531c8fa40..f77d73db8 100644 --- a/app/Models/EnvironmentVariable.php +++ b/app/Models/EnvironmentVariable.php @@ -74,6 +74,9 @@ protected static function booted() 'version' => config('version'), ]); }); + static::saving(function (EnvironmentVariable $environmentVariable) { + $environmentVariable->updateIsShared(); + }); } public function service() @@ -217,4 +220,11 @@ protected function key(): Attribute set: fn (string $value) => str($value)->trim()->replace(' ', '_')->value, ); } + + protected function updateIsShared(): void + { + $type = str($this->value)->after('{{')->before('.')->value; + $isShared = str($this->value)->startsWith('{{'.$type) && str($this->value)->endsWith('}}'); + $this->is_shared = $isShared; + } } diff --git a/database/migrations/2024_10_15_172139_add_is_shared_to_environment_variables.php b/database/migrations/2024_10_15_172139_add_is_shared_to_environment_variables.php new file mode 100644 index 000000000..eb878e2f6 --- /dev/null +++ b/database/migrations/2024_10_15_172139_add_is_shared_to_environment_variables.php @@ -0,0 +1,22 @@ +boolean('is_shared')->default(false); + }); + } + + public function down() + { + Schema::table('environment_variables', function (Blueprint $table) { + $table->dropColumn('is_shared'); + }); + } +} From 6f97d589aee48b673ca6d362526cbe923c62e8e7 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:29:13 +0200 Subject: [PATCH 16/18] feat: variabel sync and support shared vars --- app/Actions/Database/StartRedis.php | 37 ++++++++----------- .../Project/Database/Redis/General.php | 30 ++++++++++++--- bootstrap/helpers/databases.php | 16 ++++++++ 3 files changed, 56 insertions(+), 27 deletions(-) diff --git a/app/Actions/Database/StartRedis.php b/app/Actions/Database/StartRedis.php index 56be36202..3705ce938 100644 --- a/app/Actions/Database/StartRedis.php +++ b/app/Actions/Database/StartRedis.php @@ -159,31 +159,26 @@ private function generate_local_persistent_volumes_only_volume_names() private function generate_environment_variables() { $environment_variables = collect(); - $redis_password = null; - $redis_username = null; foreach ($this->database->runtime_environment_variables as $env) { - $environment_variables->push("$env->key=$env->real_value"); + if ($env->is_shared) { + $environment_variables->push("$env->key=$env->real_value"); - if ($env->key === 'REDIS_PASSWORD') { - $redis_password = $env->real_value; + if ($env->key === 'REDIS_PASSWORD') { + $this->database->update(['redis_password' => $env->real_value]); + } + + if ($env->key === 'REDIS_USERNAME') { + $this->database->update(['redis_username' => $env->real_value]); + } + } else { + if ($env->key === 'REDIS_PASSWORD') { + $env->update(['value' => $this->database->redis_password]); + } elseif ($env->key === 'REDIS_USERNAME') { + $env->update(['value' => $this->database->redis_username]); + } + $environment_variables->push("$env->key=$env->real_value"); } - - if ($env->key === 'REDIS_USERNAME') { - $redis_username = $env->real_value; - } - } - - if (is_null($redis_password)) { - $environment_variables->push("REDIS_PASSWORD={$this->database->redis_password}"); - } else { - $this->database->update(['redis_password' => $redis_password]); - } - - if (is_null($redis_username)) { - $environment_variables->push("REDIS_USERNAME={$this->database->redis_username}"); - } else { - $this->database->update(['redis_username' => $redis_username]); } add_coolify_default_environment_variables($this->database, $environment_variables, $environment_variables); diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index b5b459acb..ab9b0756d 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -80,14 +80,12 @@ public function submit() $redis_version = $this->get_redis_version(); - if (version_compare($redis_version, '6.0', '>=')) { - if ($this->database->isDirty('redis_username')) { - $this->database->redis_username = $this->database->redis_username; - } + if (version_compare($redis_version, '6.0', '>=') && $this->database->isDirty('redis_username')) { + $this->updateEnvironmentVariable('REDIS_USERNAME', $this->database->redis_username); } if ($this->database->isDirty('redis_password')) { - $this->database->redis_password = $this->database->redis_password; + $this->updateEnvironmentVariable('REDIS_PASSWORD', $this->database->redis_password); } $this->database->save(); @@ -101,6 +99,7 @@ public function submit() private function get_redis_version() { $image_parts = explode(':', $this->database->image); + return $image_parts[1] ?? '0.0'; } @@ -144,4 +143,23 @@ public function render() { return view('livewire.project.database.redis.general'); } -} \ No newline at end of file + + private function updateEnvironmentVariable($key, $value) + { + $envVar = $this->database->runtime_environment_variables() + ->where('key', $key) + ->first(); + + if ($envVar) { + if (! $envVar->is_shared) { + $envVar->update(['value' => $value]); + } + } else { + $this->database->runtime_environment_variables()->create([ + 'key' => $key, + 'value' => $value, + 'is_shared' => false, + ]); + } + } +} diff --git a/bootstrap/helpers/databases.php b/bootstrap/helpers/databases.php index 950eb67b6..d77327c8f 100644 --- a/bootstrap/helpers/databases.php +++ b/bootstrap/helpers/databases.php @@ -1,5 +1,6 @@ name = generate_database_name('redis'); $database->redis_password = \Illuminate\Support\Str::password(length: 64, symbols: false); + $database->redis_username = 'default'; $database->environment_id = $environment_id; $database->destination_id = $destination->id; $database->destination_type = $destination->getMorphClass(); @@ -57,6 +59,20 @@ function create_standalone_redis($environment_id, $destination_uuid, ?array $oth } $database->save(); + EnvironmentVariable::create([ + 'key' => 'REDIS_PASSWORD', + 'value' => $database->redis_password, + 'standalone_redis_id' => $database->id, + 'is_shared' => false, + ]); + + EnvironmentVariable::create([ + 'key' => 'REDIS_USERNAME', + 'value' => $database->redis_username, + 'standalone_redis_id' => $database->id, + 'is_shared' => false, + ]); + return $database; } From 85c3270dcc4270a6c9616bb68401105493370b45 Mon Sep 17 00:00:00 2001 From: peaklabs-dev <122374094+peaklabs-dev@users.noreply.github.com> Date: Wed, 16 Oct 2024 13:44:17 +0200 Subject: [PATCH 17/18] update helper and disable input if variable is shared --- .../Project/Database/Redis/General.php | 9 +++++++++ app/Models/StandaloneRedis.php | 12 ++++++++---- .../project/database/redis/general.blade.php | 19 +++++++++++++++---- 3 files changed, 32 insertions(+), 8 deletions(-) diff --git a/app/Livewire/Project/Database/Redis/General.php b/app/Livewire/Project/Database/Redis/General.php index ab9b0756d..20a881523 100644 --- a/app/Livewire/Project/Database/Redis/General.php +++ b/app/Livewire/Project/Database/Redis/General.php @@ -4,6 +4,7 @@ use App\Actions\Database\StartDatabaseProxy; use App\Actions\Database\StopDatabaseProxy; +use App\Models\EnvironmentVariable; use App\Models\Server; use App\Models\StandaloneRedis; use Exception; @@ -144,6 +145,14 @@ public function render() return view('livewire.project.database.redis.general'); } + public function isSharedVariable($name) + { + return EnvironmentVariable::where('key', $name) + ->where('standalone_redis_id', $this->database->id) + ->where('is_shared', true) + ->exists(); + } + private function updateEnvironmentVariable($key, $value) { $envVar = $this->database->runtime_environment_variables() diff --git a/app/Models/StandaloneRedis.php b/app/Models/StandaloneRedis.php index e71eacc45..188982f47 100644 --- a/app/Models/StandaloneRedis.php +++ b/app/Models/StandaloneRedis.php @@ -21,7 +21,7 @@ class StandaloneRedis extends BaseModel ]; protected $attributes = [ - 'redis_username' => 'redis', + 'redis_username' => 'default', ]; protected static function booted() @@ -220,7 +220,8 @@ protected function internalDbUrl(): Attribute return new Attribute( get: function () { $redis_version = $this->get_redis_version(); - $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ""; + $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ''; + return "redis://{$username_part}{$this->redis_password}@{$this->uuid}:6379/0"; } ); @@ -232,9 +233,11 @@ protected function externalDbUrl(): Attribute get: function () { if ($this->is_public && $this->public_port) { $redis_version = $this->get_redis_version(); - $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ""; + $username_part = version_compare($redis_version, '6.0', '>=') ? "{$this->redis_username}:" : ''; + return "redis://{$username_part}{$this->redis_password}@{$this->destination->server->getIp}:{$this->public_port}/0"; } + return null; } ); @@ -243,6 +246,7 @@ protected function externalDbUrl(): Attribute private function get_redis_version() { $image_parts = explode(':', $this->image); + return $image_parts[1] ?? '0.0'; } @@ -309,9 +313,9 @@ public function getMetrics(int $mins = 5) return $parsedCollection->toArray(); } } + public function isBackupSolutionAvailable() { return false; } } - diff --git a/resources/views/livewire/project/database/redis/general.blade.php b/resources/views/livewire/project/database/redis/general.blade.php index c5ab13d94..e61c210b0 100644 --- a/resources/views/livewire/project/database/redis/general.blade.php +++ b/resources/views/livewire/project/database/redis/general.blade.php @@ -16,11 +16,22 @@ $redis_version = explode(':', $database->image)[1] ?? '0.0'; @endphp @if (version_compare($redis_version, '6.0', '>=')) - + @endif - + Date: Wed, 16 Oct 2024 14:04:21 +0200 Subject: [PATCH 18/18] fix: encrypt all existing redis passwords --- ...20026_encrypt_existing_redis_passwords.php | 27 +++++++++++++++++++ 1 file changed, 27 insertions(+) create mode 100644 database/migrations/2024_10_16_120026_encrypt_existing_redis_passwords.php diff --git a/database/migrations/2024_10_16_120026_encrypt_existing_redis_passwords.php b/database/migrations/2024_10_16_120026_encrypt_existing_redis_passwords.php new file mode 100644 index 000000000..3b4f11986 --- /dev/null +++ b/database/migrations/2024_10_16_120026_encrypt_existing_redis_passwords.php @@ -0,0 +1,27 @@ +chunkById(100, function ($redisInstances) { + foreach ($redisInstances as $redis) { + DB::table('standalone_redis') + ->where('id', $redis->id) + ->update(['redis_password' => Crypt::encryptString($redis->redis_password)]); + } + }); + } catch (\Exception $e) { + echo 'Encrypting Redis passwords failed.'; + echo $e->getMessage(); + } + } +}