feat(database): offer Valkey as an image of the Redis database type

When a user creates a Redis database, a new step asks for Redis 7.2
(default) or Valkey 9. Valkey uses the same binaries (redis-* symlinks),
config, and data format, so the Redis start action runs it unchanged.
The UI now names the type "Redis / Valkey" and shows a combined logo,
and global search accepts "new valkey".

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Andras Bacsai
2026-11-06 12:37:36 +01:00
co-authored by Claude Opus 5.5
parent 878d77bd66
commit 41877198b3
10 changed files with 149 additions and 36 deletions
+6 -5
View File
@@ -207,6 +207,7 @@ class GlobalSearch extends Component
'new mysql' => 'mysql',
'new mariadb' => 'mariadb',
'new redis' => 'redis',
'new valkey' => 'redis',
'new keydb' => 'keydb',
'new dragonfly' => 'dragonfly',
'new sqlite' => 'sqlite',
@@ -477,7 +478,7 @@ class GlobalSearch extends Component
'link' => $db->link(),
'project' => $db->environment->project->name ?? null,
'environment' => $db->environment->name ?? null,
'search_text' => strtolower($db->name.' '.$db->uuid.' redis '.$db->description.' database databases db'),
'search_text' => strtolower($db->name.' '.$db->uuid.' redis valkey '.$db->description.' database databases db'),
];
})
);
@@ -1324,12 +1325,12 @@ class GlobalSearch extends Component
]);
$items->push([
'name' => 'Redis',
'description' => 'In-memory data structure store',
'quickcommand' => '(type: new redis)',
'name' => 'Redis / Valkey',
'description' => 'In-memory data structure store (Redis or Valkey)',
'quickcommand' => '(type: new redis or new valkey)',
'type' => 'redis',
'category' => 'Databases',
'logo' => 'svgs/redis.svg',
'logo' => 'svgs/resources/redis-valkey.svg',
'resourceType' => 'database',
]);
@@ -16,6 +16,6 @@ class StatusInfo extends Component
protected function databaseLabel(): string
{
return 'Redis';
return 'Redis / Valkey';
}
}
+18 -14
View File
@@ -38,6 +38,12 @@ class Select extends Component
public Collection|array $allServices = [];
/** Database types that ask for an image before the database is created. */
private const DATABASE_IMAGE_STEPS = [
'postgresql' => 'select-postgresql-type',
'redis' => 'select-redis-type',
];
public bool $isDatabase = false;
public bool $includeSwarm = true;
@@ -50,8 +56,6 @@ class Select extends Component
public ?string $selectedEnvironment = null;
public string $postgresql_type = 'postgres:18-alpine';
public ?string $existingPostgresqlUrl = null;
protected $queryString = [
@@ -72,20 +76,21 @@ class Select extends Component
$this->environments = $project->environments;
$this->selectedEnvironment = $this->environments->where('uuid', data_get($this->parameters, 'environment_uuid'))->firstOrFail()->name;
// Check if we have all required params for PostgreSQL type selection
// Check if we have all required params for the database image step
// This handles navigation from global search
$queryType = request()->query('type');
$queryServerId = request()->query('server_id');
$queryDestination = request()->query('destination');
$imageStep = self::DATABASE_IMAGE_STEPS[$queryType] ?? null;
if ($queryType === 'postgresql' && $queryServerId !== null && $queryDestination) {
if ($imageStep && $queryServerId !== null && $queryDestination) {
$server = Server::isUsable()->whereKey($queryServerId)->first();
if ($server && $this->findDestination($server, $queryDestination)) {
$this->type = $queryType;
$this->server_id = $server->id;
$this->destination_uuid = $queryDestination;
$this->server = $server;
$this->current_step = 'select-postgresql-type';
$this->current_step = $imageStep;
}
}
} catch (\Exception $e) {
@@ -235,9 +240,10 @@ class Select extends Component
],
[
'id' => 'redis',
'name' => 'Redis',
'description' => 'An in-memory key-value store used as a database, cache, and message broker.',
'logo' => resource_logo_url('redis'),
'name' => 'Redis / Valkey',
'description' => 'An in-memory key-value store for caching, queues, and sessions.',
'logo' => resource_logo_url('redis-valkey'),
'logoDark' => resource_logo_url('redis-valkey-dark'),
],
[
'id' => 'keydb',
@@ -484,24 +490,22 @@ class Select extends Component
return $server->standaloneDockers->concat($server->swarmDockers)->firstWhere('uuid', $destinationUuid);
}
public function setPostgresqlType(string $type)
public function setDatabaseImage(string $image)
{
$this->postgresql_type = $type;
return redirect()->route('project.resource.create', [
'project_uuid' => $this->parameters['project_uuid'],
'environment_uuid' => $this->parameters['environment_uuid'],
'type' => $this->type,
'destination' => $this->destination_uuid,
'server_id' => $this->server_id,
'database_image' => $this->postgresql_type,
'database_image' => $image,
]);
}
public function whatToDoNext()
{
if ($this->type === 'postgresql') {
$this->current_step = 'select-postgresql-type';
if (isset(self::DATABASE_IMAGE_STEPS[$this->type])) {
$this->current_step = self::DATABASE_IMAGE_STEPS[$this->type];
} else {
return redirect()->route('project.resource.create', [
'project_uuid' => $this->parameters['project_uuid'],
+7 -1
View File
@@ -52,7 +52,13 @@ class Create extends Component
databaseImage: $database_image
);
} elseif ($type->value() === 'redis') {
$database = create_standalone_redis($environment->id, $destination);
// Redis requires database_image (Redis or Valkey) to be explicitly set
if (! $database_image) {
$this->type = $type->value();
return;
}
$database = create_standalone_redis($environment->id, $destination, ['image' => $database_image]);
} elseif ($type->value() === 'mongodb') {
$database = create_standalone_mongodb($environment->id, $destination);
} elseif ($type->value() === 'mysql') {
+1 -1
View File
@@ -43,7 +43,7 @@ class EnvironmentCanvas
private const DATABASE_ENGINE_NAMES = [
'postgresql' => 'PostgreSQL',
'redis' => 'Redis',
'redis' => 'Redis / Valkey',
'mongodb' => 'MongoDB',
'mysql' => 'MySQL',
'mariadb' => 'MariaDB',
@@ -0,0 +1,24 @@
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="200" rx="55.2101" fill="url(#redis_valkey_bg)"/>
<g transform="translate(59,100) scale(0.56) translate(-100,-100)"><g clip-path="url(#clip0_12315_229)">
<path d="M171.818 135.901C163.497 140.238 120.39 157.962 111.213 162.747C102.036 167.532 96.9377 167.485 89.6877 164.02C82.4383 160.554 36.5652 142.024 28.3017 138.074C24.172 136.101 22 134.434 22 132.86V117.1C22 117.1 81.7214 104.099 91.3627 100.64C101.003 97.1805 104.348 97.0557 112.553 100.061C120.759 103.067 169.818 111.919 177.927 114.889L177.924 130.427C177.925 131.985 176.054 133.694 171.818 135.901Z" fill="#912626"/>
<path d="M171.815 120.233C163.494 124.568 120.389 142.293 111.212 147.077C102.035 151.862 96.9369 151.815 89.6875 148.35C82.4375 144.886 36.5663 126.353 28.3033 122.406C20.0404 118.456 19.8674 115.738 27.9842 112.559C36.1009 109.38 81.7206 91.4818 91.3631 88.0227C101.004 84.5649 104.348 84.4388 112.553 87.4453C120.758 90.4506 163.606 107.506 171.714 110.475C179.824 113.448 180.136 115.896 171.815 120.233Z" fill="#C6302B"/>
<path d="M171.818 110.394C163.497 114.732 120.39 132.455 111.213 137.241C102.036 142.025 96.9377 141.978 89.6877 138.513C82.4377 135.049 36.5652 116.517 28.3017 112.567C24.172 110.594 22 108.93 22 107.355V91.5924C22 91.5924 81.7214 78.592 91.3627 75.133C101.003 71.6739 104.348 71.5485 112.553 74.5543C120.759 77.5602 169.819 86.4097 177.927 89.3802L177.924 104.92C177.925 106.477 176.054 108.186 171.818 110.394Z" fill="#912626"/>
<path d="M171.815 94.7324C163.494 99.0691 120.389 116.792 111.212 121.578C102.035 126.362 96.9369 126.315 89.6875 122.849C82.4375 119.386 36.5663 100.854 28.3033 96.9056C20.0404 92.9569 19.8674 90.2379 27.9842 87.0584C36.1009 83.8808 81.7212 65.9815 91.3631 62.523C101.004 59.0646 104.348 58.9391 112.553 61.945C120.758 64.9503 163.606 82.0042 171.714 84.9747C179.824 87.9471 180.136 90.3956 171.815 94.7324Z" fill="#C6302B"/>
<path d="M171.818 83.9531C163.497 88.2899 120.39 106.014 111.213 110.801C102.036 115.584 96.9377 115.538 89.6877 112.072C82.4377 108.608 36.5652 90.0757 28.3017 86.1276C24.172 84.1523 22 82.4877 22 80.915V65.1517C22 65.1517 81.7214 52.1519 91.3627 48.6935C101.003 45.2338 104.348 45.1096 112.553 48.1148C120.759 51.1207 169.819 59.9702 177.927 62.9407L177.924 78.4798C177.925 80.0361 176.054 81.7452 171.818 83.9531Z" fill="#912626"/>
<path d="M171.815 68.2805C163.494 72.6172 120.388 90.3418 111.211 95.1256C102.035 99.9094 96.9366 99.8625 89.6872 96.3986C82.4378 92.9328 36.566 74.4018 28.3036 70.4531C20.0401 66.505 19.8677 63.7854 27.9839 60.6065C36.1006 57.4283 81.7209 39.5314 91.3628 36.0717C101.004 32.6127 104.348 32.4885 112.552 35.4943C120.758 38.5002 163.606 55.5541 171.713 58.5247C179.824 61.4946 180.135 63.9438 171.815 68.2805Z" fill="#C6302B"/>
<path d="M119.018 52.9557L105.612 54.3474L102.611 61.5688L97.7637 53.5105L82.2837 52.1194L93.8345 47.9538L90.3688 41.5596L101.183 45.7891L111.378 42.4513L108.623 49.063L119.018 52.9557ZM101.811 87.9894L76.7909 77.6123L112.642 72.1091L101.811 87.9894ZM67.1228 56.9696C77.7058 56.9696 86.2848 60.2952 86.2848 64.3968C86.2848 68.4997 77.7058 71.8247 67.1228 71.8247C56.5399 71.8247 47.9608 68.499 47.9608 64.3968C47.9608 60.2952 56.5399 56.9696 67.1228 56.9696Z" fill="white"/>
<path d="M134.861 54.9244L156.079 63.3092L134.879 71.686L134.861 54.9244Z" fill="#621B1C"/>
<path d="M111.387 64.2094L134.861 54.9238L134.879 71.6854L132.577 72.5856L111.387 64.2094Z" fill="#9A2928"/>
</g></g>
<g transform="translate(146,100) scale(1.15) translate(-31.16,-36.85)"><path fill="#6983FF" fill-rule="evenodd" d="M 13.482285 60.694962 L 0.998384 52.884399 L 0.998384 19.502914 L 31.527868 2.001205 L 61.317604 19.532024 L 61.317604 54.64489 L 31.054855 71.68927 L 20.548372 65.115807 L 20.548372 51.041328 L 20.548372 49.119896 L 14.851504 45.555508 L 14.851504 27.453159 L 31.346497 17.99712 L 47.464485 27.482262 L 47.464485 46.451157 L 34.703495 53.638138 L 34.703495 45.998573 C 38.52874 44.52552 41.274452 40.739189 41.274452 36.270489 C 41.274452 30.510658 36.712814 25.88438 31.158138 25.88438 C 25.603172 25.88438 21.041817 30.510658 21.041817 36.270489 C 21.041817 40.739189 23.787249 44.52552 27.612494 45.998573 L 27.612494 60.473576 L 31.261133 62.756348 L 53.635483 50.15464 L 53.635483 23.924595 L 31.477489 10.884869 L 8.680504 23.953705 L 8.680504 48.628967 L 13.482285 51.633297 L 13.482285 60.694962 Z M 31.158138 31.498383 C 33.671822 31.498383 35.660439 33.664162 35.660439 36.270489 C 35.660439 38.876804 33.671822 41.042587 31.158138 41.042587 C 28.644447 41.042587 26.655558 38.876804 26.655558 36.270489 C 26.655558 33.664162 28.644447 31.498383 31.158138 31.498383 Z"/></g>
<defs>
<clipPath id="clip0_12315_229">
<rect width="155.959" height="134" fill="white" transform="translate(22 33)"/>
</clipPath>
<linearGradient id="redis_valkey_bg" x1="0" y1="0" x2="200" y2="200" gradientUnits="userSpaceOnUse">
<stop stop-color="#C6302B" stop-opacity="0.34"/>
<stop offset="1" stop-color="#6983FF" stop-opacity="0.30"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

+24
View File
@@ -0,0 +1,24 @@
<svg width="200" height="200" viewBox="0 0 200 200" fill="none" xmlns="http://www.w3.org/2000/svg">
<rect width="200" height="200" rx="55.2101" fill="url(#redis_valkey_bg)"/>
<g transform="translate(59,100) scale(0.56) translate(-100,-100)"><g clip-path="url(#clip0_12315_229)">
<path d="M171.818 135.901C163.497 140.238 120.39 157.962 111.213 162.747C102.036 167.532 96.9377 167.485 89.6877 164.02C82.4383 160.554 36.5652 142.024 28.3017 138.074C24.172 136.101 22 134.434 22 132.86V117.1C22 117.1 81.7214 104.099 91.3627 100.64C101.003 97.1805 104.348 97.0557 112.553 100.061C120.759 103.067 169.818 111.919 177.927 114.889L177.924 130.427C177.925 131.985 176.054 133.694 171.818 135.901Z" fill="#912626"/>
<path d="M171.815 120.233C163.494 124.568 120.389 142.293 111.212 147.077C102.035 151.862 96.9369 151.815 89.6875 148.35C82.4375 144.886 36.5663 126.353 28.3033 122.406C20.0404 118.456 19.8674 115.738 27.9842 112.559C36.1009 109.38 81.7206 91.4818 91.3631 88.0227C101.004 84.5649 104.348 84.4388 112.553 87.4453C120.758 90.4506 163.606 107.506 171.714 110.475C179.824 113.448 180.136 115.896 171.815 120.233Z" fill="#C6302B"/>
<path d="M171.818 110.394C163.497 114.732 120.39 132.455 111.213 137.241C102.036 142.025 96.9377 141.978 89.6877 138.513C82.4377 135.049 36.5652 116.517 28.3017 112.567C24.172 110.594 22 108.93 22 107.355V91.5924C22 91.5924 81.7214 78.592 91.3627 75.133C101.003 71.6739 104.348 71.5485 112.553 74.5543C120.759 77.5602 169.819 86.4097 177.927 89.3802L177.924 104.92C177.925 106.477 176.054 108.186 171.818 110.394Z" fill="#912626"/>
<path d="M171.815 94.7324C163.494 99.0691 120.389 116.792 111.212 121.578C102.035 126.362 96.9369 126.315 89.6875 122.849C82.4375 119.386 36.5663 100.854 28.3033 96.9056C20.0404 92.9569 19.8674 90.2379 27.9842 87.0584C36.1009 83.8808 81.7212 65.9815 91.3631 62.523C101.004 59.0646 104.348 58.9391 112.553 61.945C120.758 64.9503 163.606 82.0042 171.714 84.9747C179.824 87.9471 180.136 90.3956 171.815 94.7324Z" fill="#C6302B"/>
<path d="M171.818 83.9531C163.497 88.2899 120.39 106.014 111.213 110.801C102.036 115.584 96.9377 115.538 89.6877 112.072C82.4377 108.608 36.5652 90.0757 28.3017 86.1276C24.172 84.1523 22 82.4877 22 80.915V65.1517C22 65.1517 81.7214 52.1519 91.3627 48.6935C101.003 45.2338 104.348 45.1096 112.553 48.1148C120.759 51.1207 169.819 59.9702 177.927 62.9407L177.924 78.4798C177.925 80.0361 176.054 81.7452 171.818 83.9531Z" fill="#912626"/>
<path d="M171.815 68.2805C163.494 72.6172 120.388 90.3418 111.211 95.1256C102.035 99.9094 96.9366 99.8625 89.6872 96.3986C82.4378 92.9328 36.566 74.4018 28.3036 70.4531C20.0401 66.505 19.8677 63.7854 27.9839 60.6065C36.1006 57.4283 81.7209 39.5314 91.3628 36.0717C101.004 32.6127 104.348 32.4885 112.552 35.4943C120.758 38.5002 163.606 55.5541 171.713 58.5247C179.824 61.4946 180.135 63.9438 171.815 68.2805Z" fill="#C6302B"/>
<path d="M119.018 52.9557L105.612 54.3474L102.611 61.5688L97.7637 53.5105L82.2837 52.1194L93.8345 47.9538L90.3688 41.5596L101.183 45.7891L111.378 42.4513L108.623 49.063L119.018 52.9557ZM101.811 87.9894L76.7909 77.6123L112.642 72.1091L101.811 87.9894ZM67.1228 56.9696C77.7058 56.9696 86.2848 60.2952 86.2848 64.3968C86.2848 68.4997 77.7058 71.8247 67.1228 71.8247C56.5399 71.8247 47.9608 68.499 47.9608 64.3968C47.9608 60.2952 56.5399 56.9696 67.1228 56.9696Z" fill="white"/>
<path d="M134.861 54.9244L156.079 63.3092L134.879 71.686L134.861 54.9244Z" fill="#621B1C"/>
<path d="M111.387 64.2094L134.861 54.9238L134.879 71.6854L132.577 72.5856L111.387 64.2094Z" fill="#9A2928"/>
</g></g>
<g transform="translate(146,100) scale(1.15) translate(-31.16,-36.85)"><path fill="#123678" fill-rule="evenodd" d="M 13.482285 60.694962 L 0.998384 52.884399 L 0.998384 19.502914 L 31.527868 2.001205 L 61.317604 19.532024 L 61.317604 54.64489 L 31.054855 71.68927 L 20.548372 65.115807 L 20.548372 51.041328 L 20.548372 49.119896 L 14.851504 45.555508 L 14.851504 27.453159 L 31.346497 17.99712 L 47.464485 27.482262 L 47.464485 46.451157 L 34.703495 53.638138 L 34.703495 45.998573 C 38.52874 44.52552 41.274452 40.739189 41.274452 36.270489 C 41.274452 30.510658 36.712814 25.88438 31.158138 25.88438 C 25.603172 25.88438 21.041817 30.510658 21.041817 36.270489 C 21.041817 40.739189 23.787249 44.52552 27.612494 45.998573 L 27.612494 60.473576 L 31.261133 62.756348 L 53.635483 50.15464 L 53.635483 23.924595 L 31.477489 10.884869 L 8.680504 23.953705 L 8.680504 48.628967 L 13.482285 51.633297 L 13.482285 60.694962 Z M 31.158138 31.498383 C 33.671822 31.498383 35.660439 33.664162 35.660439 36.270489 C 35.660439 38.876804 33.671822 41.042587 31.158138 41.042587 C 28.644447 41.042587 26.655558 38.876804 26.655558 36.270489 C 26.655558 33.664162 28.644447 31.498383 31.158138 31.498383 Z"/></g>
<defs>
<clipPath id="clip0_12315_229">
<rect width="155.959" height="134" fill="white" transform="translate(22 33)"/>
</clipPath>
<linearGradient id="redis_valkey_bg" x1="0" y1="0" x2="200" y2="200" gradientUnits="userSpaceOnUse">
<stop stop-color="#C6302B" stop-opacity="0.34"/>
<stop offset="1" stop-color="#6983FF" stop-opacity="0.30"/>
</linearGradient>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 5.0 KiB

@@ -257,7 +257,7 @@
'new private github', 'new private gh', 'new private deploy', 'new deploy key',
'new dockerfile', 'new docker compose', 'new compose', 'new docker image', 'new image',
'new postgresql', 'new postgres', 'new mysql', 'new mariadb',
'new redis', 'new keydb', 'new dragonfly', 'new mongodb', 'new mongo', 'new clickhouse', 'new sqlite'
'new redis', 'new valkey', 'new keydb', 'new dragonfly', 'new mongodb', 'new mongo', 'new clickhouse', 'new sqlite'
];
if (this.scope === 'global' && exactMatchCommands.includes(trimmed)) {
const matchingItem = this.creatableItems.find(item => {
@@ -3,7 +3,7 @@
<x-unsaved-bar action="submit" />
<x-application.settings-section id="database-details-section" title="Database details"
description="Manage the identity, container image, and credentials of this Redis database.">
description="Manage the identity, container image, and credentials of this Redis / Valkey database.">
<x-slot:actions>
<x-modal-input title="Resource details" buttonTitle="Details">
<livewire:project.shared.resource-details :resource="$database" />
@@ -14,10 +14,10 @@
<x-forms.input label="Description" id="description" canGate="update" :canResource="$database" />
<div class="lg:col-span-2">
<x-forms.input label="Image" id="image" required canGate="update" :canResource="$database"
helper="Use a published Redis image from Docker Hub." />
helper="Use a published Redis or Valkey image from Docker Hub, for example redis:7.2 or valkey/valkey:9-alpine." />
</div>
</div>
<x-application.settings-subsection id="credentials-section" title="Credentials" helper="Keep these values aligned with the credentials configured inside Redis.">
<x-application.settings-subsection id="credentials-section" title="Credentials" helper="Keep these values aligned with the credentials configured inside Redis / Valkey.">
<x-callout type="warning" title="{{ $database->started_at ? 'Keep credentials synchronized' : 'Verify the initial credentials' }}">
@if ($database->started_at)
Changing values here does not update Redis. Update Redis first, then synchronize the values here so
@@ -99,15 +99,15 @@
id="customDockerRunOptions" label="Custom Docker options" canGate="update"
:canResource="$database" />
@endif
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override only the Redis directives you need. All other defaults remain active.">
<x-application.settings-subsection id="configuration-section" title="Configuration" helper="Override only the Redis / Valkey directives you need. All other defaults remain active.">
@if ($isPasswordHiddenForMember)
<x-forms.input label="Custom Redis configuration" disabled value="Hidden (only admins can view)" />
<x-forms.input label="Custom Redis / Valkey configuration" disabled value="Hidden (only admins can view)" />
@else
<x-forms.textarea placeholder="# maxmemory 256mb
# maxmemory-policy allkeys-lru
# timeout 300"
helper="Coolify automatically applies requirepass using the password above. If you override requirepass here, keep both values identical."
label="Custom Redis configuration" rows="10" id="redisConf" canGate="update"
label="Custom Redis / Valkey configuration" rows="10" id="redisConf" canGate="update"
:canResource="$database" />
@endif
</x-application.settings-subsection>
@@ -805,7 +805,7 @@
<div class="grid grid-cols-1 gap-3 lg:grid-cols-2">
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('postgres:18-alpine'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('postgres:18-alpine'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PostgreSQL 18 <span
@@ -828,7 +828,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('postgres:17-alpine'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('postgres:17-alpine'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PostgreSQL 17</div>
@@ -849,7 +849,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('postgres:16-alpine'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('postgres:16-alpine'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PostgreSQL 16</div>
@@ -870,7 +870,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('supabase/postgres:17.4.1.032'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('supabase/postgres:17.4.1.032'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">Supabase PostgreSQL</div>
@@ -891,7 +891,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('postgis/postgis:17-3.5-alpine'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('postgis/postgis:17-3.5-alpine'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PostGIS <span
@@ -914,7 +914,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('pgvector/pgvector:pg18'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('pgvector/pgvector:pg18'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PGVector 18</div>
@@ -935,7 +935,7 @@
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setPostgresqlType('pgvector/pgvector:pg17'))"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('pgvector/pgvector:pg17'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">PGVector 17</div>
@@ -957,6 +957,60 @@
</div>
</div>
@endif
@if ($current_step === 'select-redis-type')
<div x-data="{ selecting: false }">
<div class="mb-4">
<h2 class="text-[15px]! font-semibold!">Select a Redis or Valkey image</h2>
<p class="mt-1 text-[12px] text-neutral-500 dark:text-fg-dim">Both work with the same clients, commands,
and configuration.</p>
</div>
<div class="grid grid-cols-1 gap-3 lg:grid-cols-2">
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('valkey/valkey:9-alpine'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">Valkey 9 <span
class="ml-1 rounded-full bg-coollabs/10 px-2 py-0.5 text-[10px] font-medium text-coollabs dark:bg-brand/15 dark:text-brand-light">Default</span></div>
<div class="mt-1 pr-8 text-[11px] leading-4 text-neutral-500 dark:text-fg-faint">
An open-source (BSD) fork of Redis from the Linux Foundation. It works with all Redis clients.
</div>
</div>
<a href="https://hub.docker.com/r/valkey/valkey/" target="_blank"
@click.stop
class="absolute top-2 right-2 flex size-7 items-center justify-center rounded-md text-neutral-400 transition-colors hover:bg-neutral-100 hover:text-black dark:text-fg-faint dark:hover:bg-white/[0.06] dark:hover:text-fg"
title="View documentation">
<svg class="w-4 h-4 text-neutral-600 dark:text-neutral-400" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</a>
</div>
<div class="group relative flex min-h-24 items-center gap-3 rounded-[10px] border border-neutral-200 bg-white p-4 transition-colors hover:border-neutral-300 hover:bg-neutral-50 dark:border-white/[0.07] dark:bg-surface dark:hover:border-white/[0.12] dark:hover:bg-white/[0.035]"
:class="{ 'cursor-pointer': !selecting, 'cursor-not-allowed opacity-50': selecting }"
x-on:click="!selecting && (selecting = true, $wire.setDatabaseImage('redis:7.2'))"
:disabled="selecting">
<div class="flex flex-col">
<div class="text-[13px] font-semibold text-black dark:text-fg">Redis 7.2</div>
<div class="mt-1 pr-8 text-[11px] leading-4 text-neutral-500 dark:text-fg-faint">
The original in-memory key-value store.
</div>
</div>
<a href="https://hub.docker.com/_/redis/" target="_blank"
@click.stop
class="absolute top-2 right-2 flex size-7 items-center justify-center rounded-md text-neutral-400 transition-colors hover:bg-neutral-100 hover:text-black dark:text-fg-faint dark:hover:bg-white/[0.06] dark:hover:text-fg"
title="View documentation">
<svg class="w-4 h-4 text-neutral-600 dark:text-neutral-400" fill="none"
stroke="currentColor" viewBox="0 0 24 24">
<path stroke-linecap="round" stroke-linejoin="round" stroke-width="2"
d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z" />
</svg>
</a>
</div>
</div>
</div>
@endif
@if ($current_step === 'existing-postgresql')
<x-application.settings-section title="Connect an existing PostgreSQL database"
description="Provide the connection URL for the database Coolify should use.">