Compare commits
304 Commits
v4.0.0-bet
...
new-servic
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
41c20ebc87 | ||
|
|
5ab347da76 | ||
|
|
5946e8c33c | ||
|
|
9f1a637471 | ||
|
|
2a1c1e872a | ||
|
|
e66b455b87 | ||
|
|
d7199e1095 | ||
|
|
53691083a5 | ||
|
|
d0d791d5c3 | ||
|
|
7da6b016f5 | ||
|
|
77b3a3f284 | ||
|
|
751a3dcd85 | ||
|
|
b10a22960f | ||
|
|
7c8ebcdb03 | ||
|
|
b0743076f3 | ||
|
|
826b4b09b7 | ||
|
|
df7494b0f0 | ||
|
|
02fbd253b1 | ||
|
|
a61ced89f0 | ||
|
|
f10dea28a6 | ||
|
|
987b7a9e2d | ||
|
|
bedf9814ea | ||
|
|
aa2e170160 | ||
|
|
416e6368b9 | ||
|
|
80954534c7 | ||
|
|
6780bd897e | ||
|
|
1ddfbaa9d5 | ||
|
|
32aaf95444 | ||
|
|
28852fd705 | ||
|
|
3ba76c5068 | ||
|
|
cd1998eebf | ||
|
|
53dfda903f | ||
|
|
689c875884 | ||
|
|
5d20e452be | ||
|
|
097f24394c | ||
|
|
e583d64dc6 | ||
|
|
974325e6b8 | ||
|
|
de08f67435 | ||
|
|
aa7d950f50 | ||
|
|
67b7d15aca | ||
|
|
23a4536db1 | ||
|
|
7c3a9d2f71 | ||
|
|
a0877814c6 | ||
|
|
a95a62bb64 | ||
|
|
6ac2a1f9e7 | ||
|
|
d031911ada | ||
|
|
ab8bb8dc4e | ||
|
|
1c6d47f2fc | ||
|
|
742df4f5df | ||
|
|
2522ecf832 | ||
|
|
974b4b92c1 | ||
|
|
052fcd2520 | ||
|
|
8af41b533c | ||
|
|
17b852ce1d | ||
|
|
f4c88d3600 | ||
|
|
9c2b24b9d0 | ||
|
|
4e6bf6bb8d | ||
|
|
74571d99a1 | ||
|
|
4bcfe1c0b8 | ||
|
|
b25ef93a8e | ||
|
|
e6db0b9798 | ||
|
|
2805681a30 | ||
|
|
22dc06f1f2 | ||
|
|
30b1d076d2 | ||
|
|
c486281816 | ||
|
|
71d28492b8 | ||
|
|
1914b505ed | ||
|
|
8c78e9adf0 | ||
|
|
e1168bebe0 | ||
|
|
bb8a276aa9 | ||
|
|
8d543d40cc | ||
|
|
f5ca820be8 | ||
|
|
09d1ca79b9 | ||
|
|
5fcd432c76 | ||
|
|
837796debf | ||
|
|
16817993fa | ||
|
|
2b818285b8 | ||
|
|
5c83b573b6 | ||
|
|
46f226c3f7 | ||
|
|
7aa60adc98 | ||
|
|
a2cfa1423d | ||
|
|
cdedf3b25c | ||
|
|
63f329d123 | ||
|
|
0b084060ee | ||
|
|
2c895927f6 | ||
|
|
db8c59eaaf | ||
|
|
b31cfd1604 | ||
|
|
8c503bc7fc | ||
|
|
c4ee91930d | ||
|
|
8fd103cc77 | ||
|
|
40f2c7a1f9 | ||
|
|
3f8324d09e | ||
|
|
eee292b02f | ||
|
|
2b4dc1f9c8 | ||
|
|
dd29827a14 | ||
|
|
dfe290b546 | ||
|
|
4eeb7ee7c6 | ||
|
|
51813463b8 | ||
|
|
da8a45391c | ||
|
|
673081ffb3 | ||
|
|
8f6c01ba49 | ||
|
|
40852995b4 | ||
|
|
e6bb1deaa9 | ||
|
|
2dc3177a7a | ||
|
|
facbd9a50d | ||
|
|
a0532afb24 | ||
|
|
a725a6eaf2 | ||
|
|
3fd3660960 | ||
|
|
5898e0ac4a | ||
|
|
4f4743cc7f | ||
|
|
3b3362daf0 | ||
|
|
cd199ed81d | ||
|
|
7e32a37729 | ||
|
|
58c3cea0c0 | ||
|
|
1c10a43321 | ||
|
|
370a0b1eec | ||
|
|
282ff4e670 | ||
|
|
af09472679 | ||
|
|
0f5e75f9bf | ||
|
|
053ee63606 | ||
|
|
6d6d6bfc87 | ||
|
|
7665a1787f | ||
|
|
846e45134e | ||
|
|
a8d8df7d8b | ||
|
|
283fe47f5c | ||
|
|
88367d8af1 | ||
|
|
506f733632 | ||
|
|
9f2e7851f7 | ||
|
|
8269e9d29d | ||
|
|
8803cae54c | ||
|
|
c1930e3dfc | ||
|
|
c717b6859b | ||
|
|
57e646a91e | ||
|
|
4624a381b1 | ||
|
|
6928b0a2c8 | ||
|
|
2da6f66e85 | ||
|
|
a1124a885d | ||
|
|
9448d0f0d2 | ||
|
|
e446354d97 | ||
|
|
36f0874b23 | ||
|
|
c8aa09359f | ||
|
|
128d732438 | ||
|
|
3b97bb1341 | ||
|
|
a4c8f83d17 | ||
|
|
5d7d7179c4 | ||
|
|
0ca9885ddf | ||
|
|
acd6eedf40 | ||
|
|
4f4453b17c | ||
|
|
d60d90de92 | ||
|
|
ce49f4806d | ||
|
|
82daf6c420 | ||
|
|
f1eb43815e | ||
|
|
be9041d592 | ||
|
|
c2c0afa0ba | ||
|
|
611f70d79f | ||
|
|
43e8ab7ec6 | ||
|
|
59c54b8aec | ||
|
|
f0f685b78a | ||
|
|
c54d77515b | ||
|
|
9435be7cce | ||
|
|
f2ccc4059d | ||
|
|
21c6510e9d | ||
|
|
2ca73695b3 | ||
|
|
31193a9f66 | ||
|
|
9f5257bf8a | ||
|
|
78a34dbef1 | ||
|
|
f4d650b03f | ||
|
|
97ee34f1a1 | ||
|
|
9014062b48 | ||
|
|
a8f230b5eb | ||
|
|
94ee525e0a | ||
|
|
d4ace01633 | ||
|
|
49bcd7b8e6 | ||
|
|
5f613df4e0 | ||
|
|
65aeebd9fa | ||
|
|
f26d2e1d0b | ||
|
|
a1d395ff0c | ||
|
|
4e9126887f | ||
|
|
5fa650122d | ||
|
|
ee7f8200ac | ||
|
|
d2a8f31a1c | ||
|
|
2468d0044b | ||
|
|
81b8a58415 | ||
|
|
7442d19611 | ||
|
|
8c024ddb57 | ||
|
|
d990a5691d | ||
|
|
2181ef381b | ||
|
|
c80f5be974 | ||
|
|
358f6575f8 | ||
|
|
de0f34734b | ||
|
|
33cb2d150d | ||
|
|
5f07b473e9 | ||
|
|
5bcd813792 | ||
|
|
a0bb523507 | ||
|
|
0b4fc38d6b | ||
|
|
82c834915d | ||
|
|
d637675ce3 | ||
|
|
e71c04a0c7 | ||
|
|
885b3bdea7 | ||
|
|
9d6757aeb7 | ||
|
|
d84d0a816b | ||
|
|
0da31c34b5 | ||
|
|
ccdaf59ecb | ||
|
|
3fc9cf90ab | ||
|
|
c4be720b20 | ||
|
|
aabe27efd1 | ||
|
|
dce02c1576 | ||
|
|
b324303505 | ||
|
|
a8982379c9 | ||
|
|
6dd0bd0742 | ||
|
|
1d3494a6ba | ||
|
|
ee5eb427c9 | ||
|
|
ad7b5e6e1c | ||
|
|
73bd344147 | ||
|
|
ef448280d8 | ||
|
|
5282248cb4 | ||
|
|
14c9f25c57 | ||
|
|
44b3d08d86 | ||
|
|
5da1f48ae1 | ||
|
|
2bc1b9027c | ||
|
|
1c7ca56756 | ||
|
|
d70faea845 | ||
|
|
fdb5cab875 | ||
|
|
bb6cb8edc9 | ||
|
|
a6ec2b92fb | ||
|
|
436a1d945f | ||
|
|
a6a3abc273 | ||
|
|
c4e702f096 | ||
|
|
31df222798 | ||
|
|
e91939a4ea | ||
|
|
ceccd093d2 | ||
|
|
66bb4e0fc1 | ||
|
|
dd3ff38df7 | ||
|
|
69553ec314 | ||
|
|
7bb1bf0ae3 | ||
|
|
a1a8f1336a | ||
|
|
207fe1d709 | ||
|
|
059535a676 | ||
|
|
765a74ca4f | ||
|
|
e03e4f2e91 | ||
|
|
0ab432d5e6 | ||
|
|
6f25b548c7 | ||
|
|
d55e4bf381 | ||
|
|
ec216254b5 | ||
|
|
fbb36bfe8e | ||
|
|
dd782e75f5 | ||
|
|
2be2f0ac79 | ||
|
|
97943db5f4 | ||
|
|
bbd2748ad7 | ||
|
|
a530804a71 | ||
|
|
8ca8ab82b0 | ||
|
|
024ad8e943 | ||
|
|
4d86b556a4 | ||
|
|
73e38ff951 | ||
|
|
d6be14c34c | ||
|
|
6aa7cfc479 | ||
|
|
1b0e2e1257 | ||
|
|
2cf0f4facc | ||
|
|
a6e50ce24e | ||
|
|
0494f9a7e5 | ||
|
|
dd8d0a62d8 | ||
|
|
c5fd7ba48a | ||
|
|
8166163b00 | ||
|
|
b8fcdf74e6 | ||
|
|
c402d7f543 | ||
|
|
565cb54dba | ||
|
|
14c8023197 | ||
|
|
44ceb097f3 | ||
|
|
d469f4bc8f | ||
|
|
eb5765979f | ||
|
|
611e80c987 | ||
|
|
7645047d75 | ||
|
|
918d8e783a | ||
|
|
135eb83da4 | ||
|
|
3c72035711 | ||
|
|
15733eaa55 | ||
|
|
a4dedb8369 | ||
|
|
c1eb01fac5 | ||
|
|
f3360beafe | ||
|
|
1e46b63041 | ||
|
|
cf99ec70e9 | ||
|
|
4b14c7e220 | ||
|
|
e1bcae7aaf | ||
|
|
2fc0ce1720 | ||
|
|
d5e6a643aa | ||
|
|
58831b8992 | ||
|
|
fd4316e2ed | ||
|
|
dfb9081d4e | ||
|
|
1653fcbddc | ||
|
|
71bb1f5e17 | ||
|
|
ce926afdaa | ||
|
|
b4175658e9 | ||
|
|
f080a4bf30 | ||
|
|
58dcf769e4 | ||
|
|
20acb4363b | ||
|
|
a219942987 | ||
|
|
22a58eea8f | ||
|
|
868bbaf5a9 | ||
|
|
18ae29ba99 | ||
|
|
c3e80fbc18 | ||
|
|
e7d45ac876 | ||
|
|
48886cac84 | ||
|
|
7d1f760c53 | ||
|
|
5262676596 |
1
.github/workflows/coolify-helper.yml
vendored
@@ -98,3 +98,4 @@ jobs:
|
||||
if: always()
|
||||
with:
|
||||
webhook: ${{ secrets.DISCORD_WEBHOOK_PROD_RELEASE_CHANNEL }}
|
||||
|
||||
|
||||
17
app/Actions/Application/GenerateConfig.php
Normal file
@@ -0,0 +1,17 @@
|
||||
<?php
|
||||
|
||||
namespace App\Actions\Application;
|
||||
|
||||
use App\Models\Application;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
|
||||
class GenerateConfig
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Application $application, bool $is_json = false)
|
||||
{
|
||||
ray()->clearAll();
|
||||
return $application->generateConfig(is_json: $is_json);
|
||||
}
|
||||
}
|
||||
@@ -22,7 +22,7 @@ class CheckConfiguration
|
||||
];
|
||||
$proxy_configuration = instant_remote_process($payload, $server, false);
|
||||
if ($reset || ! $proxy_configuration || is_null($proxy_configuration)) {
|
||||
$proxy_configuration = str(generate_default_proxy_configuration($server))->trim()->value;
|
||||
$proxy_configuration = str(generate_default_proxy_configuration($server))->trim()->value();
|
||||
}
|
||||
if (! $proxy_configuration || is_null($proxy_configuration)) {
|
||||
throw new \Exception('Could not generate proxy configuration');
|
||||
|
||||
@@ -2,14 +2,17 @@
|
||||
|
||||
namespace App\Actions\Proxy;
|
||||
|
||||
use App\Enums\ProxyTypes;
|
||||
use App\Models\Server;
|
||||
use Lorisleiva\Actions\Concerns\AsAction;
|
||||
use Symfony\Component\Yaml\Yaml;
|
||||
|
||||
class CheckProxy
|
||||
{
|
||||
use AsAction;
|
||||
|
||||
public function handle(Server $server, $fromUI = false)
|
||||
// It should return if the proxy should be started (true) or not (false)
|
||||
public function handle(Server $server, $fromUI = false): bool
|
||||
{
|
||||
if (! $server->isFunctional()) {
|
||||
return false;
|
||||
@@ -62,22 +65,42 @@ class CheckProxy
|
||||
$ip = 'host.docker.internal';
|
||||
}
|
||||
|
||||
$connection80 = @fsockopen($ip, '80');
|
||||
$connection443 = @fsockopen($ip, '443');
|
||||
$port80 = is_resource($connection80) && fclose($connection80);
|
||||
$port443 = is_resource($connection443) && fclose($connection443);
|
||||
if ($port80) {
|
||||
if ($fromUI) {
|
||||
throw new \Exception("Port 80 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||
$portsToCheck = ['80', '443'];
|
||||
|
||||
try {
|
||||
if ($server->proxyType() !== ProxyTypes::NONE->value) {
|
||||
$proxyCompose = CheckConfiguration::run($server);
|
||||
if (isset($proxyCompose)) {
|
||||
$yaml = Yaml::parse($proxyCompose);
|
||||
$portsToCheck = [];
|
||||
if ($server->proxyType() === ProxyTypes::TRAEFIK->value) {
|
||||
$ports = data_get($yaml, 'services.traefik.ports');
|
||||
} elseif ($server->proxyType() === ProxyTypes::CADDY->value) {
|
||||
$ports = data_get($yaml, 'services.caddy.ports');
|
||||
}
|
||||
if (isset($ports)) {
|
||||
foreach ($ports as $port) {
|
||||
$portsToCheck[] = str($port)->before(':')->value();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
$portsToCheck = [];
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
ray($e->getMessage());
|
||||
}
|
||||
if ($port443) {
|
||||
if ($fromUI) {
|
||||
throw new \Exception("Port 443 is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||
} else {
|
||||
return false;
|
||||
if (count($portsToCheck) === 0) {
|
||||
return false;
|
||||
}
|
||||
foreach ($portsToCheck as $port) {
|
||||
$connection = @fsockopen($ip, $port);
|
||||
if (is_resource($connection) && fclose($connection)) {
|
||||
if ($fromUI) {
|
||||
throw new \Exception("Port $port is in use.<br>You must stop the process using this port.<br>Docs: <a target='_blank' href='https://coolify.io/docs'>https://coolify.io/docs</a><br>Discord: <a target='_blank' href='https://coollabs.io/discord'>https://coollabs.io/discord</a>");
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ class StartProxy
|
||||
}
|
||||
SaveConfiguration::run($server, $configuration);
|
||||
$docker_compose_yml_base64 = base64_encode($configuration);
|
||||
$server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value;
|
||||
$server->proxy->last_applied_settings = str($docker_compose_yml_base64)->pipe('md5')->value();
|
||||
$server->save();
|
||||
if ($server->isSwarm()) {
|
||||
$commands = $commands->merge([
|
||||
|
||||
50
app/Console/Commands/CheckApplicationDeploymentQueue.php
Normal file
@@ -0,0 +1,50 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Enums\ApplicationDeploymentStatus;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CheckApplicationDeploymentQueue extends Command
|
||||
{
|
||||
protected $signature = 'check:deployment-queue {--force} {--seconds=3600}';
|
||||
|
||||
protected $description = 'Check application deployment queue.';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
$seconds = $this->option('seconds');
|
||||
$deployments = ApplicationDeploymentQueue::whereIn('status', [
|
||||
ApplicationDeploymentStatus::IN_PROGRESS,
|
||||
ApplicationDeploymentStatus::QUEUED,
|
||||
])->where('created_at', '<=', now()->subSeconds($seconds))->get();
|
||||
if ($deployments->isEmpty()) {
|
||||
$this->info('No deployments found in the last '.$seconds.' seconds.');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
$this->info('Found '.$deployments->count().' deployments created in the last '.$seconds.' seconds.');
|
||||
|
||||
foreach ($deployments as $deployment) {
|
||||
if ($this->option('force')) {
|
||||
$this->info('Deployment '.$deployment->id.' created at '.$deployment->created_at.' is older than '.$seconds.' seconds. Setting status to failed.');
|
||||
$this->cancelDeployment($deployment);
|
||||
} else {
|
||||
$this->info('Deployment '.$deployment->id.' created at '.$deployment->created_at.' is older than '.$seconds.' seconds. Setting status to failed.');
|
||||
if ($this->confirm('Do you want to cancel this deployment?', true)) {
|
||||
$this->cancelDeployment($deployment);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private function cancelDeployment(ApplicationDeploymentQueue $deployment)
|
||||
{
|
||||
$deployment->update(['status' => ApplicationDeploymentStatus::FAILED]);
|
||||
if ($deployment->server?->isFunctional()) {
|
||||
remote_process(['docker rm -f '.$deployment->deployment_uuid], $deployment->server, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,9 +7,9 @@ use Illuminate\Console\Command;
|
||||
|
||||
class CleanupApplicationDeploymentQueue extends Command
|
||||
{
|
||||
protected $signature = 'cleanup:application-deployment-queue {--team-id=}';
|
||||
protected $signature = 'cleanup:deployment-queue {--team-id=}';
|
||||
|
||||
protected $description = 'CleanupApplicationDeploymentQueue';
|
||||
protected $description = 'Cleanup application deployment queue.';
|
||||
|
||||
public function handle()
|
||||
{
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
|
||||
|
||||
use App\Jobs\CleanupHelperContainersJob;
|
||||
use App\Models\Application;
|
||||
use App\Models\ApplicationDeploymentQueue;
|
||||
use App\Models\ApplicationPreview;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
use App\Models\ScheduledTask;
|
||||
@@ -47,6 +48,17 @@ class CleanupStuckedResources extends Command
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stucked resources: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$applicationsDeploymentQueue = ApplicationDeploymentQueue::get();
|
||||
foreach ($applicationsDeploymentQueue as $applicationDeploymentQueue) {
|
||||
if (is_null($applicationDeploymentQueue->application)) {
|
||||
echo "Deleting stuck application deployment queue: {$applicationDeploymentQueue->id}\n";
|
||||
$applicationDeploymentQueue->delete();
|
||||
}
|
||||
}
|
||||
} catch (\Throwable $e) {
|
||||
echo "Error in cleaning stuck application deployment queue: {$e->getMessage()}\n";
|
||||
}
|
||||
try {
|
||||
$applications = Application::withTrashed()->whereNotNull('deleted_at')->get();
|
||||
foreach ($applications as $application) {
|
||||
|
||||
@@ -78,7 +78,7 @@ class ServicesGenerate extends Command
|
||||
if ($logo->count() > 0) {
|
||||
$logo = str($logo[0])->after('# logo:')->trim()->value();
|
||||
} else {
|
||||
$logo = 'svgs/unknown.svg';
|
||||
$logo = 'svgs/coolify.png';
|
||||
}
|
||||
$minversion = collect(preg_grep('/^# minversion:/', explode("\n", $content)))->values();
|
||||
if ($minversion->count() > 0) {
|
||||
|
||||
@@ -94,7 +94,9 @@ class SshMultiplexingHelper
|
||||
$muxPersistTime = config('constants.ssh.mux_persist_time');
|
||||
|
||||
$scp_command = "timeout $timeout scp ";
|
||||
|
||||
if ($server->isIpv6()) {
|
||||
$scp_command .= '-6 ';
|
||||
}
|
||||
if (self::isMultiplexingEnabled()) {
|
||||
$scp_command .= "-o ControlMaster=auto -o ControlPath=$muxSocket -o ControlPersist={$muxPersistTime} ";
|
||||
self::ensureMultiplexedConnection($server);
|
||||
@@ -136,8 +138,8 @@ class SshMultiplexingHelper
|
||||
|
||||
$ssh_command .= self::getCommonSshOptions($server, $sshKeyLocation, config('constants.ssh.connection_timeout'), config('constants.ssh.server_interval'));
|
||||
|
||||
$command = "PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/host/usr/local/sbin:/host/usr/local/bin:/host/usr/sbin:/host/usr/bin:/host/sbin:/host/bin && $command";
|
||||
$delimiter = Hash::make($command);
|
||||
$delimiter = base64_encode($delimiter);
|
||||
$command = str_replace($delimiter, '', $command);
|
||||
|
||||
$ssh_command .= "{$server->user}@{$server->ip} 'bash -se' << \\$delimiter".PHP_EOL
|
||||
|
||||
@@ -744,8 +744,10 @@ class ApplicationsController extends Controller
|
||||
$application->destination_id = $destination->id;
|
||||
$application->destination_type = $destination->getMorphClass();
|
||||
$application->environment_id = $environment->id;
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
if (isset($useBuildServer)) {
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
}
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
@@ -842,8 +844,10 @@ class ApplicationsController extends Controller
|
||||
$application->environment_id = $environment->id;
|
||||
$application->source_type = $githubApp->getMorphClass();
|
||||
$application->source_id = $githubApp->id;
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
if (isset($useBuildServer)) {
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
}
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
@@ -936,8 +940,10 @@ class ApplicationsController extends Controller
|
||||
$application->destination_id = $destination->id;
|
||||
$application->destination_type = $destination->getMorphClass();
|
||||
$application->environment_id = $environment->id;
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
if (isset($useBuildServer)) {
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
}
|
||||
$application->save();
|
||||
$application->refresh();
|
||||
if (! $application->settings->is_container_label_readonly_enabled) {
|
||||
@@ -1017,8 +1023,10 @@ class ApplicationsController extends Controller
|
||||
$application->destination_id = $destination->id;
|
||||
$application->destination_type = $destination->getMorphClass();
|
||||
$application->environment_id = $environment->id;
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
if (isset($useBuildServer)) {
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
}
|
||||
|
||||
$application->git_repository = 'coollabsio/coolify';
|
||||
$application->git_branch = 'main';
|
||||
@@ -1077,8 +1085,10 @@ class ApplicationsController extends Controller
|
||||
$application->destination_id = $destination->id;
|
||||
$application->destination_type = $destination->getMorphClass();
|
||||
$application->environment_id = $environment->id;
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
if (isset($useBuildServer)) {
|
||||
$application->settings->is_build_server_enabled = $useBuildServer;
|
||||
$application->settings->save();
|
||||
}
|
||||
|
||||
$application->git_repository = 'coollabsio/coolify';
|
||||
$application->git_branch = 'main';
|
||||
@@ -1555,8 +1565,11 @@ class ApplicationsController extends Controller
|
||||
$instantDeploy = $request->instant_deploy;
|
||||
|
||||
$use_build_server = $request->use_build_server;
|
||||
$application->settings->is_build_server_enabled = $use_build_server;
|
||||
$application->settings->save();
|
||||
|
||||
if (isset($use_build_server)) {
|
||||
$application->settings->is_build_server_enabled = $use_build_server;
|
||||
$application->settings->save();
|
||||
}
|
||||
|
||||
removeUnnecessaryFieldsFromRequest($request);
|
||||
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Jobs;
|
||||
|
||||
use App\Actions\Database\StopDatabase;
|
||||
use App\Events\BackupCreated;
|
||||
use App\Models\S3Storage;
|
||||
use App\Models\ScheduledDatabaseBackup;
|
||||
@@ -24,7 +23,6 @@ use Illuminate\Foundation\Bus\Dispatchable;
|
||||
use Illuminate\Queue\InteractsWithQueue;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use Illuminate\Support\Str;
|
||||
use Visus\Cuid2\Cuid2;
|
||||
|
||||
class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
@@ -63,31 +61,32 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
public function __construct($backup)
|
||||
{
|
||||
$this->backup = $backup;
|
||||
$this->team = Team::find($backup->team_id);
|
||||
if (is_null($this->team)) {
|
||||
return;
|
||||
}
|
||||
if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') {
|
||||
$this->database = data_get($this->backup, 'database');
|
||||
$this->server = $this->database->service->server;
|
||||
$this->s3 = $this->backup->s3;
|
||||
} else {
|
||||
$this->database = data_get($this->backup, 'database');
|
||||
$this->server = $this->database->destination->server;
|
||||
$this->s3 = $this->backup->s3;
|
||||
}
|
||||
}
|
||||
|
||||
public function handle(): void
|
||||
{
|
||||
try {
|
||||
// Check if team is exists
|
||||
if (is_null($this->team)) {
|
||||
StopDatabase::run($this->database);
|
||||
$this->database->delete();
|
||||
$this->team = Team::find($this->backup->team_id);
|
||||
if (! $this->team) {
|
||||
$this->backup->delete();
|
||||
|
||||
return;
|
||||
}
|
||||
if (data_get($this->backup, 'database_type') === 'App\Models\ServiceDatabase') {
|
||||
$this->database = data_get($this->backup, 'database');
|
||||
$this->server = $this->database->service->server;
|
||||
$this->s3 = $this->backup->s3;
|
||||
} else {
|
||||
$this->database = data_get($this->backup, 'database');
|
||||
$this->server = $this->database->destination->server;
|
||||
$this->s3 = $this->backup->s3;
|
||||
}
|
||||
if (is_null($this->server)) {
|
||||
throw new \Exception('Server not found?!');
|
||||
}
|
||||
if (is_null($this->database)) {
|
||||
throw new \Exception('Database not found?!');
|
||||
}
|
||||
|
||||
BackupCreated::dispatch($this->team->id);
|
||||
|
||||
@@ -237,7 +236,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
}
|
||||
}
|
||||
$this->backup_dir = backup_dir().'/databases/'.str($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name;
|
||||
|
||||
if ($this->database->name === 'coolify-db') {
|
||||
$databasesToBackup = ['coolify'];
|
||||
$this->directory_name = $this->container_name = 'coolify-db';
|
||||
@@ -250,6 +248,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
try {
|
||||
if (str($databaseType)->contains('postgres')) {
|
||||
$this->backup_file = "/pg-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
if ($this->backup->dump_all) {
|
||||
$this->backup_file = '/pg-dump-all-'.Carbon::now()->timestamp.'.gz';
|
||||
}
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@@ -278,6 +279,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->backup_standalone_mongodb($database);
|
||||
} elseif (str($databaseType)->contains('mysql')) {
|
||||
$this->backup_file = "/mysql-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
if ($this->backup->dump_all) {
|
||||
$this->backup_file = '/mysql-dump-all-'.Carbon::now()->timestamp.'.gz';
|
||||
}
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@@ -287,6 +291,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->backup_standalone_mysql($database);
|
||||
} elseif (str($databaseType)->contains('mariadb')) {
|
||||
$this->backup_file = "/mariadb-dump-$database-".Carbon::now()->timestamp.'.dmp';
|
||||
if ($this->backup->dump_all) {
|
||||
$this->backup_file = '/mariadb-dump-all-'.Carbon::now()->timestamp.'.gz';
|
||||
}
|
||||
$this->backup_location = $this->backup_dir.$this->backup_file;
|
||||
$this->backup_log = ScheduledDatabaseBackupExecution::create([
|
||||
'database_name' => $database,
|
||||
@@ -325,7 +332,9 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
send_internal_notification('DatabaseBackupJob failed with: '.$e->getMessage());
|
||||
throw $e;
|
||||
} finally {
|
||||
BackupCreated::dispatch($this->team->id);
|
||||
if ($this->team) {
|
||||
BackupCreated::dispatch($this->team->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -384,7 +393,11 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
if ($this->postgres_password) {
|
||||
$backupCommand .= " -e PGPASSWORD=$this->postgres_password";
|
||||
}
|
||||
$backupCommand .= " $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $database > $this->backup_location";
|
||||
if ($this->backup->dump_all) {
|
||||
$backupCommand .= " $this->container_name pg_dumpall --username {$this->database->postgres_user} | gzip > $this->backup_location";
|
||||
} else {
|
||||
$backupCommand .= " $this->container_name pg_dump --format=custom --no-acl --no-owner --username {$this->database->postgres_user} $database > $this->backup_location";
|
||||
}
|
||||
|
||||
$commands[] = $backupCommand;
|
||||
ray($commands);
|
||||
@@ -405,8 +418,11 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
try {
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location";
|
||||
ray($commands);
|
||||
if ($this->backup->dump_all) {
|
||||
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} --all-databases --single-transaction --quick --lock-tables=false --compress | gzip > $this->backup_location";
|
||||
} else {
|
||||
$commands[] = "docker exec $this->container_name mysqldump -u root -p{$this->database->mysql_root_password} $database > $this->backup_location";
|
||||
}
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
$this->backup_output = trim($this->backup_output);
|
||||
if ($this->backup_output === '') {
|
||||
@@ -424,7 +440,11 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
{
|
||||
try {
|
||||
$commands[] = 'mkdir -p '.$this->backup_dir;
|
||||
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location";
|
||||
if ($this->backup->dump_all) {
|
||||
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} --all-databases --single-transaction --quick --lock-tables=false --compress > $this->backup_location";
|
||||
} else {
|
||||
$commands[] = "docker exec $this->container_name mariadb-dump -u root -p{$this->database->mariadb_root_password} $database > $this->backup_location";
|
||||
}
|
||||
ray($commands);
|
||||
$this->backup_output = instant_remote_process($commands, $this->server);
|
||||
$this->backup_output = trim($this->backup_output);
|
||||
@@ -466,34 +486,6 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
}
|
||||
}
|
||||
|
||||
// private function upload_to_s3(): void
|
||||
// {
|
||||
// try {
|
||||
// if (is_null($this->s3)) {
|
||||
// return;
|
||||
// }
|
||||
// $key = $this->s3->key;
|
||||
// $secret = $this->s3->secret;
|
||||
// // $region = $this->s3->region;
|
||||
// $bucket = $this->s3->bucket;
|
||||
// $endpoint = $this->s3->endpoint;
|
||||
// $this->s3->testConnection(shouldSave: true);
|
||||
// $configName = new Cuid2;
|
||||
|
||||
// $s3_copy_dir = str($this->backup_location)->replace(backup_dir(), '/var/www/html/storage/app/backups/');
|
||||
// $commands[] = "docker exec coolify bash -c 'mc config host add {$configName} {$endpoint} $key $secret'";
|
||||
// $commands[] = "docker exec coolify bash -c 'mc cp $s3_copy_dir {$configName}/{$bucket}{$this->backup_dir}/'";
|
||||
// instant_remote_process($commands, $this->server);
|
||||
// $this->add_to_backup_output('Uploaded to S3.');
|
||||
// } catch (\Throwable $e) {
|
||||
// $this->add_to_backup_output($e->getMessage());
|
||||
// throw $e;
|
||||
// } finally {
|
||||
// $removeConfigCommands[] = "docker exec coolify bash -c 'mc config remove {$configName}'";
|
||||
// $removeConfigCommands[] = "docker exec coolify bash -c 'mc alias rm {$configName}'";
|
||||
// instant_remote_process($removeConfigCommands, $this->server, false);
|
||||
// }
|
||||
// }
|
||||
private function upload_to_s3(): void
|
||||
{
|
||||
try {
|
||||
@@ -515,10 +507,27 @@ class DatabaseBackupJob implements ShouldBeEncrypted, ShouldQueue
|
||||
$this->ensureHelperImageAvailable();
|
||||
|
||||
$fullImageName = $this->getFullImageName();
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro {$fullImageName}";
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
|
||||
|
||||
if (isDev()) {
|
||||
if ($this->database->name === 'coolify-db') {
|
||||
$backup_location_from = '/var/lib/docker/volumes/coolify_dev_backups_data/_data/coolify/coolify-db-'.$this->server->ip.$this->backup_file;
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $backup_location_from:$this->backup_location:ro {$fullImageName}";
|
||||
} else {
|
||||
$backup_location_from = '/var/lib/docker/volumes/coolify_dev_backups_data/_data/databases/'.str($this->team->name)->slug().'-'.$this->team->id.'/'.$this->directory_name.$this->backup_file;
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $backup_location_from:$this->backup_location:ro {$fullImageName}";
|
||||
}
|
||||
} else {
|
||||
$commands[] = "docker run -d --network {$network} --name backup-of-{$this->backup->uuid} --rm -v $this->backup_location:$this->backup_location:ro {$fullImageName}";
|
||||
}
|
||||
if ($this->s3->isHetzner()) {
|
||||
$endpointWithoutBucket = 'https://'.str($endpoint)->after('https://')->after('.')->value();
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc alias set --path=off --api=S3v4 temporary {$endpointWithoutBucket} $key $secret";
|
||||
} else {
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc config host add temporary {$endpoint} $key $secret";
|
||||
}
|
||||
$commands[] = "docker exec backup-of-{$this->backup->uuid} mc cp $this->backup_location temporary/$bucket{$this->backup_dir}/";
|
||||
instant_remote_process($commands, $this->server);
|
||||
|
||||
$this->add_to_backup_output('Uploaded to S3.');
|
||||
} catch (\Throwable $e) {
|
||||
$this->add_to_backup_output($e->getMessage());
|
||||
|
||||
@@ -30,7 +30,7 @@ class Dashboard extends Component
|
||||
|
||||
public function cleanup_queue()
|
||||
{
|
||||
Artisan::queue('cleanup:application-deployment-queue', [
|
||||
Artisan::queue('cleanup:deployment-queue', [
|
||||
'--team-id' => currentTeam()->id,
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ class Help extends Component
|
||||
send_user_an_email($mail, auth()->user()?->email, 'hi@coollabs.io');
|
||||
}
|
||||
$this->dispatch('success', 'Feedback sent.', 'We will get in touch with you as soon as possible.');
|
||||
$this->reset('description', 'subject');
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Livewire\Project\Application;
|
||||
|
||||
use App\Actions\Application\GenerateConfig;
|
||||
use App\Models\Application;
|
||||
use Illuminate\Support\Collection;
|
||||
use Livewire\Component;
|
||||
@@ -413,4 +414,16 @@ class General extends Component
|
||||
$this->dispatch('configurationChanged');
|
||||
}
|
||||
}
|
||||
public function downloadConfig()
|
||||
{
|
||||
$config = GenerateConfig::run($this->application, true);
|
||||
$fileName = str($this->application->name)->slug()->append('_config.json');
|
||||
|
||||
return response()->streamDownload(function () use ($config) {
|
||||
echo $config;
|
||||
}, $fileName, [
|
||||
'Content-Type' => 'application/json',
|
||||
'Content-Disposition' => 'attachment; filename=' . $fileName,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ class BackupEdit extends Component
|
||||
'backup.save_s3' => 'required|boolean',
|
||||
'backup.s3_storage_id' => 'nullable|integer',
|
||||
'backup.databases_to_backup' => 'nullable',
|
||||
'backup.dump_all' => 'required|boolean',
|
||||
];
|
||||
|
||||
protected $validationAttributes = [
|
||||
@@ -40,6 +41,7 @@ class BackupEdit extends Component
|
||||
'backup.save_s3' => 'Save to S3',
|
||||
'backup.s3_storage_id' => 'S3 Storage',
|
||||
'backup.databases_to_backup' => 'Databases to Backup',
|
||||
'backup.dump_all' => 'Backup All Databases',
|
||||
];
|
||||
|
||||
protected $messages = [
|
||||
|
||||
@@ -26,7 +26,7 @@ class ScheduledBackups extends Component
|
||||
public function mount(): void
|
||||
{
|
||||
if ($this->selectedBackupId) {
|
||||
$this->setSelectedBackup($this->selectedBackupId);
|
||||
$this->setSelectedBackup($this->selectedBackupId, true);
|
||||
}
|
||||
$this->parameters = get_route_parameters();
|
||||
if ($this->database->getMorphClass() === 'App\Models\ServiceDatabase') {
|
||||
@@ -37,10 +37,13 @@ class ScheduledBackups extends Component
|
||||
$this->s3s = currentTeam()->s3s;
|
||||
}
|
||||
|
||||
public function setSelectedBackup($backupId)
|
||||
public function setSelectedBackup($backupId, $force = false)
|
||||
{
|
||||
if ($this->selectedBackupId === $backupId && ! $force) {
|
||||
return;
|
||||
}
|
||||
$this->selectedBackupId = $backupId;
|
||||
$this->selectedBackup = $this->database->scheduledBackups->find($this->selectedBackupId);
|
||||
$this->selectedBackup = $this->database->scheduledBackups->find($backupId);
|
||||
if (is_null($this->selectedBackup)) {
|
||||
$this->selectedBackupId = null;
|
||||
}
|
||||
|
||||
@@ -31,10 +31,12 @@ class PublicGitRepository extends Component
|
||||
|
||||
public bool $isStatic = false;
|
||||
|
||||
public bool $checkCoolifyConfig = true;
|
||||
|
||||
public ?string $publish_directory = null;
|
||||
|
||||
// In case of docker compose
|
||||
public ?string $base_directory = null;
|
||||
public string $base_directory = '/';
|
||||
|
||||
public ?string $docker_compose_location = '/docker-compose.yaml';
|
||||
// End of docker compose
|
||||
@@ -97,6 +99,7 @@ class PublicGitRepository extends Component
|
||||
$this->base_directory = '/'.$this->base_directory;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public function updatedDockerComposeLocation()
|
||||
@@ -275,6 +278,7 @@ class PublicGitRepository extends Component
|
||||
'destination_id' => $destination->id,
|
||||
'destination_type' => $destination_class,
|
||||
'build_pack' => $this->build_pack,
|
||||
'base_directory' => $this->base_directory,
|
||||
];
|
||||
} else {
|
||||
$application_init = [
|
||||
@@ -289,6 +293,7 @@ class PublicGitRepository extends Component
|
||||
'source_id' => $this->git_source->id,
|
||||
'source_type' => $this->git_source->getMorphClass(),
|
||||
'build_pack' => $this->build_pack,
|
||||
'base_directory' => $this->base_directory,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -303,11 +308,15 @@ class PublicGitRepository extends Component
|
||||
|
||||
$application->settings->is_static = $this->isStatic;
|
||||
$application->settings->save();
|
||||
|
||||
$fqdn = generateFqdn($destination->server, $application->uuid);
|
||||
$application->fqdn = $fqdn;
|
||||
$application->save();
|
||||
|
||||
if ($this->checkCoolifyConfig) {
|
||||
// $config = loadConfigFromGit($this->repository_url, $this->git_branch, $this->base_directory, $this->query['server_id'], auth()->user()->currentTeam()->id);
|
||||
// if ($config) {
|
||||
// $application->setConfig($config);
|
||||
// }
|
||||
}
|
||||
return redirect()->route('project.application.configuration', [
|
||||
'application_uuid' => $application->uuid,
|
||||
'environment_name' => $environment->name,
|
||||
|
||||
@@ -108,6 +108,21 @@ class Navbar extends Component
|
||||
|
||||
return;
|
||||
}
|
||||
StopService::run(service: $this->service, dockerCleanup: false);
|
||||
$this->service->parse();
|
||||
$this->dispatch('imagePulled');
|
||||
$activity = StartService::run($this->service);
|
||||
$this->dispatch('activityMonitor', $activity->id);
|
||||
}
|
||||
|
||||
public function pullAndRestartEvent()
|
||||
{
|
||||
$this->checkDeployments();
|
||||
if ($this->isDeploymentProgress) {
|
||||
$this->dispatch('error', 'There is a deployment in progress.');
|
||||
|
||||
return;
|
||||
}
|
||||
PullImage::run($this->service);
|
||||
StopService::run(service: $this->service, dockerCleanup: false);
|
||||
$this->service->parse();
|
||||
|
||||
@@ -48,14 +48,6 @@ class Add extends Component
|
||||
public function submit()
|
||||
{
|
||||
$this->validate();
|
||||
// if (str($this->value)->startsWith('{{') && str($this->value)->endsWith('}}')) {
|
||||
// $type = str($this->value)->after('{{')->before('.')->value;
|
||||
// if (! collect(SHARED_VARIABLE_TYPES)->contains($type)) {
|
||||
// $this->dispatch('error', 'Invalid shared variable type.', 'Valid types are: team, project, environment.');
|
||||
|
||||
// return;
|
||||
// }
|
||||
// }
|
||||
$this->dispatch('saveKey', [
|
||||
'key' => $this->key,
|
||||
'value' => $this->value,
|
||||
|
||||
@@ -53,30 +53,16 @@ class All extends Component
|
||||
|
||||
public function sortEnvironmentVariables()
|
||||
{
|
||||
if ($this->resource->type() === 'application') {
|
||||
$this->resource->load(['environment_variables', 'environment_variables_preview']);
|
||||
} else {
|
||||
$this->resource->load(['environment_variables']);
|
||||
if (! data_get($this->resource, 'settings.is_env_sorting_enabled')) {
|
||||
if ($this->resource->environment_variables) {
|
||||
$this->resource->environment_variables = $this->resource->environment_variables->sortBy('order')->values();
|
||||
}
|
||||
|
||||
if ($this->resource->environment_variables_preview) {
|
||||
$this->resource->environment_variables_preview = $this->resource->environment_variables_preview->sortBy('order')->values();
|
||||
}
|
||||
}
|
||||
|
||||
$sortBy = data_get($this->resource, 'settings.is_env_sorting_enabled') ? 'key' : 'order';
|
||||
|
||||
$sortFunction = function ($variables) use ($sortBy) {
|
||||
if (! $variables) {
|
||||
return $variables;
|
||||
}
|
||||
if ($sortBy === 'key') {
|
||||
return $variables->sortBy(function ($item) {
|
||||
return strtolower($item->key);
|
||||
}, SORT_NATURAL | SORT_FLAG_CASE)->values();
|
||||
} else {
|
||||
return $variables->sortBy('order')->values();
|
||||
}
|
||||
};
|
||||
|
||||
$this->resource->environment_variables = $sortFunction($this->resource->environment_variables);
|
||||
$this->resource->environment_variables_preview = $sortFunction($this->resource->environment_variables_preview);
|
||||
|
||||
$this->getDevView();
|
||||
}
|
||||
|
||||
@@ -121,6 +107,8 @@ class All extends Component
|
||||
$this->sortEnvironmentVariables();
|
||||
} catch (\Throwable $e) {
|
||||
return handleError($e, $this);
|
||||
} finally {
|
||||
$this->refreshEnvs();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -34,9 +34,9 @@ class Terminal extends Component
|
||||
if ($status !== 'running') {
|
||||
return;
|
||||
}
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$identifier} sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "docker exec -it {$identifier} sh -c 'PATH=\$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
} else {
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, "sh -c 'if [ -f ~/.profile ]; then . ~/.profile; fi; if [ -n \"\$SHELL\" ]; then exec \$SHELL; else sh; fi'");
|
||||
$command = SshMultiplexingHelper::generateSshCommand($server, 'PATH=$PATH:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin && if [ -f ~/.profile ]; then . ~/.profile; fi && if [ -n "$SHELL" ]; then exec $SHELL; else sh; fi');
|
||||
}
|
||||
|
||||
// ssh command is sent back to frontend then to websocket
|
||||
|
||||
41
app/Livewire/Project/Shared/UploadConfig.php
Normal file
@@ -0,0 +1,41 @@
|
||||
<?php
|
||||
|
||||
namespace App\Livewire\Project\Shared;
|
||||
|
||||
use App\Models\Application;
|
||||
use Livewire\Component;
|
||||
|
||||
class UploadConfig extends Component
|
||||
{
|
||||
public $config;
|
||||
public $applicationId;
|
||||
public function mount() {
|
||||
if (isDev()) {
|
||||
$this->config = '{
|
||||
"build_pack": "nixpacks",
|
||||
"base_directory": "/nodejs",
|
||||
"publish_directory": "/",
|
||||
"ports_exposes": "3000",
|
||||
"settings": {
|
||||
"is_static": false
|
||||
}
|
||||
}';
|
||||
}
|
||||
}
|
||||
public function uploadConfig()
|
||||
{
|
||||
try {
|
||||
$application = Application::findOrFail($this->applicationId);
|
||||
$application->setConfig($this->config);
|
||||
$this->dispatch('success', 'Application settings updated');
|
||||
} catch (\Exception $e) {
|
||||
$this->dispatch('error', $e->getMessage());
|
||||
return;
|
||||
}
|
||||
|
||||
}
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.project.shared.upload-config');
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,8 @@ class ApiTokens extends Component
|
||||
|
||||
public bool $readOnly = true;
|
||||
|
||||
public bool $rootAccess = false;
|
||||
|
||||
public array $permissions = ['read-only'];
|
||||
|
||||
public $isApiEnabled;
|
||||
@@ -35,12 +37,11 @@ class ApiTokens extends Component
|
||||
if ($this->viewSensitiveData) {
|
||||
$this->permissions[] = 'view:sensitive';
|
||||
$this->permissions = array_diff($this->permissions, ['*']);
|
||||
$this->rootAccess = false;
|
||||
} else {
|
||||
$this->permissions = array_diff($this->permissions, ['view:sensitive']);
|
||||
}
|
||||
if (count($this->permissions) == 0) {
|
||||
$this->permissions = ['*'];
|
||||
}
|
||||
$this->makeSureOneIsSelected();
|
||||
}
|
||||
|
||||
public function updatedReadOnly()
|
||||
@@ -48,11 +49,30 @@ class ApiTokens extends Component
|
||||
if ($this->readOnly) {
|
||||
$this->permissions[] = 'read-only';
|
||||
$this->permissions = array_diff($this->permissions, ['*']);
|
||||
$this->rootAccess = false;
|
||||
} else {
|
||||
$this->permissions = array_diff($this->permissions, ['read-only']);
|
||||
}
|
||||
if (count($this->permissions) == 0) {
|
||||
$this->makeSureOneIsSelected();
|
||||
}
|
||||
|
||||
public function updatedRootAccess()
|
||||
{
|
||||
if ($this->rootAccess) {
|
||||
$this->permissions = ['*'];
|
||||
$this->readOnly = false;
|
||||
$this->viewSensitiveData = false;
|
||||
} else {
|
||||
$this->readOnly = true;
|
||||
$this->permissions = ['read-only'];
|
||||
}
|
||||
}
|
||||
|
||||
public function makeSureOneIsSelected()
|
||||
{
|
||||
if (count($this->permissions) == 0) {
|
||||
$this->permissions = ['read-only'];
|
||||
$this->readOnly = true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,12 +82,6 @@ class ApiTokens extends Component
|
||||
$this->validate([
|
||||
'description' => 'required|min:3|max:255',
|
||||
]);
|
||||
// if ($this->viewSensitiveData) {
|
||||
// $this->permissions[] = 'view:sensitive';
|
||||
// }
|
||||
// if ($this->readOnly) {
|
||||
// $this->permissions[] = 'read-only';
|
||||
// }
|
||||
$token = auth()->user()->createToken($this->description, $this->permissions);
|
||||
$this->tokens = auth()->user()->tokens;
|
||||
session()->flash('token', $token->plainTextToken);
|
||||
|
||||
@@ -30,6 +30,11 @@ class ConfigureCloudflareTunnels extends Component
|
||||
public function submit()
|
||||
{
|
||||
try {
|
||||
if (str($this->ssh_domain)->contains('https://')) {
|
||||
$this->ssh_domain = str($this->ssh_domain)->replace('https://', '')->replace('http://', '')->trim();
|
||||
// remove / from the end
|
||||
$this->ssh_domain = str($this->ssh_domain)->replace('/', '');
|
||||
}
|
||||
$server = Server::ownedByCurrentTeam()->where('id', $this->server_id)->firstOrFail();
|
||||
ConfigureCloudflared::dispatch($server, $this->cloudflare_token);
|
||||
$server->settings->is_cloudflare_tunnel = true;
|
||||
|
||||
@@ -4,7 +4,7 @@ namespace App\Livewire\Server\Proxy;
|
||||
|
||||
use App\Actions\Docker\GetContainersStatus;
|
||||
use App\Actions\Proxy\CheckProxy;
|
||||
use App\Jobs\ContainerStatusJob;
|
||||
use App\Actions\Proxy\StartProxy;
|
||||
use App\Models\Server;
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -44,7 +44,10 @@ class Status extends Component
|
||||
}
|
||||
$this->numberOfPolls++;
|
||||
}
|
||||
CheckProxy::run($this->server, true);
|
||||
$shouldStart = CheckProxy::run($this->server, true);
|
||||
if ($shouldStart) {
|
||||
StartProxy::run($this->server, false);
|
||||
}
|
||||
$this->dispatch('proxyStatusUpdated');
|
||||
if ($this->server->proxy->status === 'running') {
|
||||
$this->polling = false;
|
||||
|
||||
@@ -43,15 +43,17 @@ class Create extends Component
|
||||
'endpoint' => 'Endpoint',
|
||||
];
|
||||
|
||||
public function mount()
|
||||
public function updatedEndpoint($value)
|
||||
{
|
||||
if (isDev()) {
|
||||
$this->name = 'Local MinIO';
|
||||
$this->description = 'Local MinIO';
|
||||
$this->key = 'minioadmin';
|
||||
$this->secret = 'minioadmin';
|
||||
$this->bucket = 'local';
|
||||
$this->endpoint = 'http://coolify-minio:9000';
|
||||
if (! str($value)->startsWith('https://') && ! str($value)->startsWith('http://')) {
|
||||
$this->endpoint = 'https://'.$value;
|
||||
$value = $this->endpoint;
|
||||
}
|
||||
|
||||
if (str($value)->contains('your-objectstorage.com') && ! isset($this->bucket)) {
|
||||
$this->bucket = str($value)->after('//')->before('.');
|
||||
} elseif (str($value)->contains('your-objectstorage.com')) {
|
||||
$this->bucket = $this->bucket ?: str($value)->after('//')->before('.');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Process\InvokedProcess;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Process;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
use OpenApi\Attributes as OA;
|
||||
use RuntimeException;
|
||||
@@ -143,6 +144,9 @@ class Application extends BaseModel
|
||||
}
|
||||
$application->tags()->detach();
|
||||
$application->previews()->delete();
|
||||
foreach ($application->deployment_queue as $deployment) {
|
||||
$deployment->delete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@@ -710,6 +714,11 @@ class Application extends BaseModel
|
||||
return $this->hasMany(ApplicationPreview::class);
|
||||
}
|
||||
|
||||
public function deployment_queue()
|
||||
{
|
||||
return $this->hasMany(ApplicationDeploymentQueue::class);
|
||||
}
|
||||
|
||||
public function destination()
|
||||
{
|
||||
return $this->morphTo();
|
||||
@@ -1419,4 +1428,67 @@ class Application extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function generateConfig($is_json = false)
|
||||
{
|
||||
$config = collect([]);
|
||||
if ($this->build_pack = 'nixpacks') {
|
||||
$config = collect([
|
||||
'build_pack' => 'nixpacks',
|
||||
'docker_registry_image_name' => $this->docker_registry_image_name,
|
||||
'docker_registry_image_tag' => $this->docker_registry_image_tag,
|
||||
'install_command' => $this->install_command,
|
||||
'build_command' => $this->build_command,
|
||||
'start_command' => $this->start_command,
|
||||
'base_directory' => $this->base_directory,
|
||||
'publish_directory' => $this->publish_directory,
|
||||
'custom_docker_run_options' => $this->custom_docker_run_options,
|
||||
'ports_exposes' => $this->ports_exposes,
|
||||
'ports_mappings' => $this->ports_mapping,
|
||||
'settings' => collect([
|
||||
'is_static' => $this->settings->is_static,
|
||||
]),
|
||||
]);
|
||||
}
|
||||
$config = $config->filter(function ($value) {
|
||||
return str($value)->isNotEmpty();
|
||||
});
|
||||
if ($is_json) {
|
||||
return json_encode($config, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES);
|
||||
}
|
||||
|
||||
return $config;
|
||||
}
|
||||
public function setConfig($config) {
|
||||
|
||||
$config = $config;
|
||||
$validator = Validator::make(['config' => $config], [
|
||||
'config' => 'required|json',
|
||||
]);
|
||||
if ($validator->fails()) {
|
||||
throw new \Exception('Invalid JSON format');
|
||||
}
|
||||
$config = json_decode($config, true);
|
||||
|
||||
$deepValidator = Validator::make(['config' => $config], [
|
||||
'config.build_pack' => 'required|string',
|
||||
'config.base_directory' => 'required|string',
|
||||
'config.publish_directory' => 'required|string',
|
||||
'config.ports_exposes' => 'required|string',
|
||||
'config.settings.is_static' => 'required|boolean',
|
||||
]);
|
||||
if ($deepValidator->fails()) {
|
||||
throw new \Exception('Invalid data');
|
||||
}
|
||||
$config = $deepValidator->validated()['config'];
|
||||
|
||||
try {
|
||||
$settings = data_get($config, 'settings', []);
|
||||
data_forget($config, 'settings');
|
||||
$this->update($config);
|
||||
$this->settings()->update($settings);
|
||||
} catch (\Exception $e) {
|
||||
throw new \Exception('Failed to update application settings');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Carbon;
|
||||
use OpenApi\Attributes as OA;
|
||||
@@ -39,6 +40,20 @@ class ApplicationDeploymentQueue extends Model
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
public function application(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => Application::find($this->application_id),
|
||||
);
|
||||
}
|
||||
|
||||
public function server(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn () => Server::find($this->server_id),
|
||||
);
|
||||
}
|
||||
|
||||
public function setStatus(string $status)
|
||||
{
|
||||
$this->update([
|
||||
|
||||
@@ -24,9 +24,11 @@ class Project extends BaseModel
|
||||
{
|
||||
protected $guarded = [];
|
||||
|
||||
protected $appends = ['default_environment'];
|
||||
|
||||
public static function ownedByCurrentTeam()
|
||||
{
|
||||
return Project::whereTeamId(currentTeam()->id)->orderBy('name');
|
||||
return Project::whereTeamId(currentTeam()->id)->orderByRaw('LOWER(name)');
|
||||
}
|
||||
|
||||
protected static function booted()
|
||||
@@ -131,7 +133,7 @@ class Project extends BaseModel
|
||||
return $this->postgresqls()->get()->merge($this->redis()->get())->merge($this->mongodbs()->get())->merge($this->mysqls()->get())->merge($this->mariadbs()->get())->merge($this->keydbs()->get())->merge($this->dragonflies()->get())->merge($this->clickhouses()->get());
|
||||
}
|
||||
|
||||
public function default_environment()
|
||||
public function getDefaultEnvironmentAttribute()
|
||||
{
|
||||
$default = $this->environments()->where('name', 'production')->first();
|
||||
if ($default) {
|
||||
|
||||
@@ -40,6 +40,16 @@ class S3Storage extends BaseModel
|
||||
return "{$this->endpoint}/{$this->bucket}";
|
||||
}
|
||||
|
||||
public function isHetzner()
|
||||
{
|
||||
return str($this->endpoint)->contains('your-objectstorage.com');
|
||||
}
|
||||
|
||||
public function isDigitalOcean()
|
||||
{
|
||||
return str($this->endpoint)->contains('digitaloceanspaces.com');
|
||||
}
|
||||
|
||||
public function testConnection(bool $shouldSave = false)
|
||||
{
|
||||
try {
|
||||
|
||||
@@ -448,11 +448,19 @@ $schema://$host {
|
||||
// Should move everything except /caddy and /nginx to /traefik
|
||||
// The code needs to be modified as well, so maybe it does not worth it
|
||||
if ($proxyType === ProxyTypes::TRAEFIK->value) {
|
||||
$proxy_path = $proxy_path;
|
||||
// Do nothing
|
||||
} elseif ($proxyType === ProxyTypes::CADDY->value) {
|
||||
$proxy_path = $proxy_path.'/caddy';
|
||||
if (isDev()) {
|
||||
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/caddy';
|
||||
} else {
|
||||
$proxy_path = $proxy_path.'/caddy';
|
||||
}
|
||||
} elseif ($proxyType === ProxyTypes::NGINX->value) {
|
||||
$proxy_path = $proxy_path.'/nginx';
|
||||
if (isDev()) {
|
||||
$proxy_path = '/var/lib/docker/volumes/coolify_dev_coolify_data/_data/proxy/nginx';
|
||||
} else {
|
||||
$proxy_path = $proxy_path.'/nginx';
|
||||
}
|
||||
}
|
||||
|
||||
return $proxy_path;
|
||||
@@ -460,15 +468,6 @@ $schema://$host {
|
||||
|
||||
public function proxyType()
|
||||
{
|
||||
// $proxyType = $this->proxy->get('type');
|
||||
// if ($proxyType === ProxyTypes::NONE->value) {
|
||||
// return $proxyType;
|
||||
// }
|
||||
// if (is_null($proxyType)) {
|
||||
// $this->proxy->type = ProxyTypes::TRAEFIK->value;
|
||||
// $this->proxy->status = ProxyStatus::EXITED->value;
|
||||
// $this->save();
|
||||
// }
|
||||
return data_get($this->proxy, 'type');
|
||||
}
|
||||
|
||||
@@ -1221,4 +1220,9 @@ $schema://$host {
|
||||
|
||||
return instant_remote_process($commands, $this, false);
|
||||
}
|
||||
|
||||
public function isIpv6(): bool
|
||||
{
|
||||
return str($this->ip)->contains(':');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -283,9 +283,147 @@ class Service extends BaseModel
|
||||
$fields = collect([]);
|
||||
$applications = $this->applications()->get();
|
||||
foreach ($applications as $application) {
|
||||
$image = str($application->image)->before(':')->value();
|
||||
$image = str($application->image)->before(':');
|
||||
if ($image->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
switch ($image) {
|
||||
case str($image)?->contains('rabbitmq'):
|
||||
case $image->contains('label-studio'):
|
||||
$data = collect([]);
|
||||
$username = $this->environment_variables()->where('key', 'LABEL_STUDIO_USERNAME')->first();
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LABELSTUDIO')->first();
|
||||
if ($username) {
|
||||
$data = $data->merge([
|
||||
'Username' => [
|
||||
'key' => 'LABEL_STUDIO_USERNAME',
|
||||
'value' => data_get($username, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($password) {
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => 'LABEL_STUDIO_PASSWORD',
|
||||
'value' => data_get($password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
}
|
||||
$fields->put('Label Studio', $data->toArray());
|
||||
break;
|
||||
case $image->contains('litellm'):
|
||||
$data = collect([]);
|
||||
$username = $this->environment_variables()->where('key', 'SERVICE_USER_UI')->first();
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UI')->first();
|
||||
if ($username) {
|
||||
$data = $data->merge([
|
||||
'Username' => [
|
||||
'key' => data_get($username, 'key'),
|
||||
'value' => data_get($username, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($password) {
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => data_get($password, 'key'),
|
||||
'value' => data_get($password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
}
|
||||
$fields->put('Litellm', $data->toArray());
|
||||
break;
|
||||
case $image->contains('langfuse'):
|
||||
$data = collect([]);
|
||||
$email = $this->environment_variables()->where('key', 'LANGFUSE_INIT_USER_EMAIL')->first();
|
||||
if ($email) {
|
||||
$data = $data->merge([
|
||||
'Admin Email' => [
|
||||
'key' => 'LANGFUSE_INIT_USER_EMAIL',
|
||||
'value' => data_get($email, 'value'),
|
||||
'rules' => 'required|email',
|
||||
],
|
||||
]);
|
||||
}
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_LANGFUSE')->first();
|
||||
ray('password', $password);
|
||||
if ($password) {
|
||||
$data = $data->merge([
|
||||
'Admin Password' => [
|
||||
'key' => 'LANGFUSE_INIT_USER_PASSWORD',
|
||||
'value' => data_get($password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
}
|
||||
$fields->put('Langfuse', $data->toArray());
|
||||
break;
|
||||
case $image->contains('invoiceninja'):
|
||||
$data = collect([]);
|
||||
$email = $this->environment_variables()->where('key', 'IN_USER_EMAIL')->first();
|
||||
$data = $data->merge([
|
||||
'Email' => [
|
||||
'key' => 'IN_USER_EMAIL',
|
||||
'value' => data_get($email, 'value'),
|
||||
'rules' => 'required|email',
|
||||
],
|
||||
]);
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_INVOICENINJAUSER')->first();
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => 'IN_PASSWORD',
|
||||
'value' => data_get($password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
$fields->put('Invoice Ninja', $data->toArray());
|
||||
break;
|
||||
case $image->contains('argilla'):
|
||||
$data = collect([]);
|
||||
$api_key = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_APIKEY')->first();
|
||||
$data = $data->merge([
|
||||
'API Key' => [
|
||||
'key' => data_get($api_key, 'key'),
|
||||
'value' => data_get($api_key, 'value'),
|
||||
'isPassword' => true,
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
$data = $data->merge([
|
||||
'API Key' => [
|
||||
'key' => data_get($api_key, 'key'),
|
||||
'value' => data_get($api_key, 'value'),
|
||||
'isPassword' => true,
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
$username = $this->environment_variables()->where('key', 'ARGILLA_USERNAME')->first();
|
||||
$data = $data->merge([
|
||||
'Username' => [
|
||||
'key' => data_get($username, 'key'),
|
||||
'value' => data_get($username, 'value'),
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ARGILLA')->first();
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => data_get($password, 'key'),
|
||||
'value' => data_get($password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
$fields->put('Argilla', $data->toArray());
|
||||
break;
|
||||
case $image->contains('rabbitmq'):
|
||||
$data = collect([]);
|
||||
$host_port = $this->environment_variables()->where('key', 'PORT')->first();
|
||||
$username = $this->environment_variables()->where('key', 'SERVICE_USER_RABBITMQ')->first();
|
||||
@@ -320,7 +458,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('RabbitMQ', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('tolgee'):
|
||||
case $image->contains('tolgee'):
|
||||
$data = collect([]);
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_TOLGEE')->first();
|
||||
$data = $data->merge([
|
||||
@@ -343,7 +481,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Tolgee', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('logto'):
|
||||
case $image->contains('logto'):
|
||||
$data = collect([]);
|
||||
$logto_endpoint = $this->environment_variables()->where('key', 'LOGTO_ENDPOINT')->first();
|
||||
$logto_admin_endpoint = $this->environment_variables()->where('key', 'LOGTO_ADMIN_ENDPOINT')->first();
|
||||
@@ -367,7 +505,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Logto', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('unleash-server'):
|
||||
case $image->contains('unleash-server'):
|
||||
$data = collect([]);
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_UNLEASH')->first();
|
||||
$data = $data->merge([
|
||||
@@ -390,7 +528,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Unleash', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('grafana'):
|
||||
case $image->contains('grafana'):
|
||||
$data = collect([]);
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GRAFANA')->first();
|
||||
$data = $data->merge([
|
||||
@@ -413,7 +551,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Grafana', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('directus'):
|
||||
case $image->contains('directus'):
|
||||
$data = collect([]);
|
||||
$admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first();
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
|
||||
@@ -439,7 +577,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Directus', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('kong'):
|
||||
case $image->contains('kong'):
|
||||
$data = collect([]);
|
||||
$dashboard_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();
|
||||
$dashboard_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
|
||||
@@ -463,7 +601,7 @@ class Service extends BaseModel
|
||||
]);
|
||||
}
|
||||
$fields->put('Supabase', $data->toArray());
|
||||
case str($image)?->contains('minio'):
|
||||
case $image->contains('minio'):
|
||||
$data = collect([]);
|
||||
$console_url = $this->environment_variables()->where('key', 'MINIO_BROWSER_REDIRECT_URL')->first();
|
||||
$s3_api_url = $this->environment_variables()->where('key', 'MINIO_SERVER_URL')->first();
|
||||
@@ -516,7 +654,7 @@ class Service extends BaseModel
|
||||
|
||||
$fields->put('MinIO', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('weblate'):
|
||||
case $image->contains('weblate'):
|
||||
$data = collect([]);
|
||||
$admin_email = $this->environment_variables()->where('key', 'WEBLATE_ADMIN_EMAIL')->first();
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_WEBLATE')->first();
|
||||
@@ -542,7 +680,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Weblate', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('meilisearch'):
|
||||
case $image->contains('meilisearch'):
|
||||
$data = collect([]);
|
||||
$SERVICE_PASSWORD_MEILISEARCH = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_MEILISEARCH')->first();
|
||||
if ($SERVICE_PASSWORD_MEILISEARCH) {
|
||||
@@ -556,7 +694,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Meilisearch', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('ghost'):
|
||||
case $image->contains('ghost'):
|
||||
$data = collect([]);
|
||||
$MAIL_OPTIONS_AUTH_PASS = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_PASS')->first();
|
||||
$MAIL_OPTIONS_AUTH_USER = $this->environment_variables()->where('key', 'MAIL_OPTIONS_AUTH_USER')->first();
|
||||
@@ -616,45 +754,8 @@ class Service extends BaseModel
|
||||
|
||||
$fields->put('Ghost', $data->toArray());
|
||||
break;
|
||||
default:
|
||||
$data = collect([]);
|
||||
$admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();
|
||||
// Chaskiq
|
||||
$admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first();
|
||||
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
|
||||
if ($admin_user) {
|
||||
$data = $data->merge([
|
||||
'User' => [
|
||||
'key' => 'SERVICE_USER_ADMIN',
|
||||
'value' => data_get($admin_user, 'value', 'admin'),
|
||||
'readonly' => true,
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($admin_password) {
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => 'SERVICE_PASSWORD_ADMIN',
|
||||
'value' => data_get($admin_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($admin_email) {
|
||||
$data = $data->merge([
|
||||
'Email' => [
|
||||
'key' => 'ADMIN_EMAIL',
|
||||
'value' => data_get($admin_email, 'value'),
|
||||
'rules' => 'required|email',
|
||||
],
|
||||
]);
|
||||
}
|
||||
$fields->put('Admin', $data->toArray());
|
||||
break;
|
||||
case str($image)?->contains('vaultwarden'):
|
||||
case $image->contains('vaultwarden'):
|
||||
$data = collect([]);
|
||||
|
||||
$DATABASE_URL = $this->environment_variables()->where('key', 'DATABASE_URL')->first();
|
||||
@@ -720,7 +821,7 @@ class Service extends BaseModel
|
||||
|
||||
$fields->put('Vaultwarden', $data);
|
||||
break;
|
||||
case str($image)->contains('gitlab/gitlab'):
|
||||
case $image->contains('gitlab/gitlab'):
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_GITLAB')->first();
|
||||
$data = collect([]);
|
||||
if ($password) {
|
||||
@@ -744,7 +845,7 @@ class Service extends BaseModel
|
||||
|
||||
$fields->put('GitLab', $data->toArray());
|
||||
break;
|
||||
case str($image)->contains('code-server'):
|
||||
case $image->contains('code-server'):
|
||||
$data = collect([]);
|
||||
$password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_64_PASSWORDCODESERVER')->first();
|
||||
if ($password) {
|
||||
@@ -770,14 +871,78 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('Code Server', $data->toArray());
|
||||
break;
|
||||
case $image->contains('elestio/strapi'):
|
||||
$data = collect([]);
|
||||
$license = $this->environment_variables()->where('key', 'STRAPI_LICENSE')->first();
|
||||
if ($license) {
|
||||
$data = $data->merge([
|
||||
'License' => [
|
||||
'key' => data_get($license, 'key'),
|
||||
'value' => data_get($license, 'value'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
$nodeEnv = $this->environment_variables()->where('key', 'NODE_ENV')->first();
|
||||
if ($nodeEnv) {
|
||||
$data = $data->merge([
|
||||
'Node Environment' => [
|
||||
'key' => data_get($nodeEnv, 'key'),
|
||||
'value' => data_get($nodeEnv, 'value'),
|
||||
],
|
||||
]);
|
||||
}
|
||||
|
||||
$fields->put('Strapi', $data->toArray());
|
||||
break;
|
||||
default:
|
||||
$data = collect([]);
|
||||
$admin_user = $this->environment_variables()->where('key', 'SERVICE_USER_ADMIN')->first();
|
||||
// Chaskiq
|
||||
$admin_email = $this->environment_variables()->where('key', 'ADMIN_EMAIL')->first();
|
||||
|
||||
$admin_password = $this->environment_variables()->where('key', 'SERVICE_PASSWORD_ADMIN')->first();
|
||||
if ($admin_user) {
|
||||
$data = $data->merge([
|
||||
'User' => [
|
||||
'key' => 'SERVICE_USER_ADMIN',
|
||||
'value' => data_get($admin_user, 'value', 'admin'),
|
||||
'readonly' => true,
|
||||
'rules' => 'required',
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($admin_password) {
|
||||
$data = $data->merge([
|
||||
'Password' => [
|
||||
'key' => 'SERVICE_PASSWORD_ADMIN',
|
||||
'value' => data_get($admin_password, 'value'),
|
||||
'rules' => 'required',
|
||||
'isPassword' => true,
|
||||
],
|
||||
]);
|
||||
}
|
||||
if ($admin_email) {
|
||||
$data = $data->merge([
|
||||
'Email' => [
|
||||
'key' => 'ADMIN_EMAIL',
|
||||
'value' => data_get($admin_email, 'value'),
|
||||
'rules' => 'required|email',
|
||||
],
|
||||
]);
|
||||
}
|
||||
$fields->put('Admin', $data->toArray());
|
||||
break;
|
||||
}
|
||||
}
|
||||
$databases = $this->databases()->get();
|
||||
|
||||
foreach ($databases as $database) {
|
||||
$image = str($database->image)->before(':')->value();
|
||||
$image = str($database->image)->before(':');
|
||||
if ($image->isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
switch ($image) {
|
||||
case str($image)->contains('postgres'):
|
||||
case $image->contains('postgres'):
|
||||
$userVariables = ['SERVICE_USER_POSTGRES', 'SERVICE_USER_POSTGRESQL'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_POSTGRES', 'SERVICE_PASSWORD_POSTGRESQL'];
|
||||
$dbNameVariables = ['POSTGRESQL_DATABASE', 'POSTGRES_DB'];
|
||||
@@ -815,7 +980,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('PostgreSQL', $data->toArray());
|
||||
break;
|
||||
case str($image)->contains('mysql'):
|
||||
case $image->contains('mysql'):
|
||||
$userVariables = ['SERVICE_USER_MYSQL', 'SERVICE_USER_WORDPRESS', 'MYSQL_USER'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_MYSQL', 'SERVICE_PASSWORD_WORDPRESS', 'MYSQL_PASSWORD'];
|
||||
$rootPasswordVariables = ['SERVICE_PASSWORD_MYSQLROOT', 'SERVICE_PASSWORD_ROOT'];
|
||||
@@ -865,7 +1030,7 @@ class Service extends BaseModel
|
||||
}
|
||||
$fields->put('MySQL', $data->toArray());
|
||||
break;
|
||||
case str($image)->contains('mariadb'):
|
||||
case $image->contains('mariadb'):
|
||||
$userVariables = ['SERVICE_USER_MARIADB', 'SERVICE_USER_WORDPRESS', '_APP_DB_USER', 'SERVICE_USER_MYSQL', 'MYSQL_USER'];
|
||||
$passwordVariables = ['SERVICE_PASSWORD_MARIADB', 'SERVICE_PASSWORD_WORDPRESS', '_APP_DB_PASS', 'MYSQL_PASSWORD'];
|
||||
$rootPasswordVariables = ['SERVICE_PASSWORD_MARIADBROOT', 'SERVICE_PASSWORD_ROOT', '_APP_DB_ROOT_PASS', 'MYSQL_ROOT_PASSWORD'];
|
||||
@@ -1052,12 +1217,12 @@ class Service extends BaseModel
|
||||
public function environment_variables(): HasMany
|
||||
{
|
||||
|
||||
return $this->hasMany(EnvironmentVariable::class)->orderByRaw("key LIKE 'SERVICE%' DESC, value ASC");
|
||||
return $this->hasMany(EnvironmentVariable::class)->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
|
||||
}
|
||||
|
||||
public function environment_variables_preview(): HasMany
|
||||
{
|
||||
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->orderBy('key', 'asc');
|
||||
return $this->hasMany(EnvironmentVariable::class)->where('is_preview', true)->orderByRaw("LOWER(key) LIKE LOWER('SERVICE%') DESC, LOWER(key) ASC");
|
||||
}
|
||||
|
||||
public function workdir()
|
||||
@@ -1108,7 +1273,6 @@ class Service extends BaseModel
|
||||
$real_value = escapeEnvVariables($env->real_value);
|
||||
}
|
||||
}
|
||||
ray("echo \"{$env->key}={$real_value}\" >> .env");
|
||||
$commands[] = "echo \"{$env->key}={$real_value}\" >> .env";
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,4 +112,9 @@ class ServiceApplication extends BaseModel
|
||||
{
|
||||
getFilesystemVolumesFromServer($this, $isInit);
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,4 +115,13 @@ class ServiceDatabase extends BaseModel
|
||||
{
|
||||
return $this->morphMany(ScheduledDatabaseBackup::class, 'database');
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return str($this->databaseType())->contains('mysql') ||
|
||||
str($this->databaseType())->contains('postgres') ||
|
||||
str($this->databaseType())->contains('postgis') ||
|
||||
str($this->databaseType())->contains('mariadb') ||
|
||||
str($this->databaseType())->contains('mongodb');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,4 +294,9 @@ class StandaloneClickhouse extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,4 +294,9 @@ class StandaloneDragonfly extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,4 +294,9 @@ class StandaloneKeydb extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -294,4 +294,9 @@ class StandaloneMariadb extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -314,4 +314,9 @@ class StandaloneMongodb extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -295,4 +295,9 @@ class StandaloneMysql extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -296,4 +296,9 @@ class StandalonePostgresql extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -290,4 +290,9 @@ class StandaloneRedis extends BaseModel
|
||||
return $parsedCollection->toArray();
|
||||
}
|
||||
}
|
||||
|
||||
public function isBackupSolutionAvailable()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,12 +20,16 @@ const RESTART_MODE = 'unless-stopped';
|
||||
const DATABASE_DOCKER_IMAGES = [
|
||||
'bitnami/mariadb',
|
||||
'bitnami/mongodb',
|
||||
'bitnami/mysql',
|
||||
'bitnami/postgresql',
|
||||
'bitnami/redis',
|
||||
'mysql',
|
||||
'bitnami/mysql',
|
||||
'mysql/mysql-server',
|
||||
'mariadb',
|
||||
'postgis/postgis',
|
||||
'postgres',
|
||||
'bitnami/postgresql',
|
||||
'supabase/postgres',
|
||||
'elestio/postgres',
|
||||
'mongo',
|
||||
'redis',
|
||||
'memcached',
|
||||
@@ -33,7 +37,6 @@ const DATABASE_DOCKER_IMAGES = [
|
||||
'neo4j',
|
||||
'influxdb',
|
||||
'clickhouse/clickhouse-server',
|
||||
'supabase/postgres',
|
||||
];
|
||||
const SPECIFIC_SERVICES = [
|
||||
'quay.io/minio/minio',
|
||||
|
||||
@@ -325,38 +325,20 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels->push('traefik.http.middlewares.gzip.compress=true');
|
||||
$labels->push('traefik.http.middlewares.redirect-to-https.redirectscheme.scheme=https');
|
||||
|
||||
$basic_auth = false;
|
||||
$basic_auth_middleware = null;
|
||||
$redirect = false;
|
||||
$redirect_middleware = null;
|
||||
$middlewares_from_labels = collect([]);
|
||||
|
||||
if ($serviceLabels) {
|
||||
$basic_auth = $serviceLabels->contains(function ($value) {
|
||||
return str_contains($value, 'basicauth');
|
||||
});
|
||||
if ($basic_auth) {
|
||||
$basic_auth_middleware = $serviceLabels
|
||||
->map(function ($item) {
|
||||
if (preg_match('/traefik\.http\.middlewares\.(.*?)\.basicauth\.users/', $item, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
})
|
||||
->filter()
|
||||
->first();
|
||||
}
|
||||
$redirect = $serviceLabels->contains(function ($value) {
|
||||
return str_contains($value, 'redirectregex');
|
||||
});
|
||||
if ($redirect) {
|
||||
$redirect_middleware = $serviceLabels
|
||||
->map(function ($item) {
|
||||
if (preg_match('/traefik\.http\.middlewares\.(.*?)\.redirectregex\.regex/', $item, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
})
|
||||
->filter()
|
||||
->first();
|
||||
}
|
||||
$middlewares_from_labels = $serviceLabels->map(function ($item) {
|
||||
if (preg_match('/traefik\.http\.middlewares\.(.*?)(\.|$)/', $item, $matches)) {
|
||||
return $matches[1];
|
||||
}
|
||||
if (preg_match('/coolify\.traefik\.middlewares=(.*)/', $item, $matches)) {
|
||||
return explode(',', $matches[1]);
|
||||
}
|
||||
return null;
|
||||
})->flatten()
|
||||
->filter()
|
||||
->unique();
|
||||
}
|
||||
foreach ($domains as $loop => $domain) {
|
||||
try {
|
||||
@@ -404,20 +386,15 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels->push("traefik.http.services.{$https_label}.loadbalancer.server.port=$port");
|
||||
}
|
||||
if ($path !== '/') {
|
||||
// Middleware handling
|
||||
$middlewares = collect([]);
|
||||
if ($is_stripprefix_enabled && ! str($image)->contains('ghost')) {
|
||||
if ($is_stripprefix_enabled && !str($image)->contains('ghost')) {
|
||||
$labels->push("traefik.http.middlewares.{$https_label}-stripprefix.stripprefix.prefixes={$path}");
|
||||
$middlewares->push("{$https_label}-stripprefix");
|
||||
}
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
if ($basic_auth && $basic_auth_middleware) {
|
||||
$middlewares->push($basic_auth_middleware);
|
||||
}
|
||||
if ($redirect && $redirect_middleware) {
|
||||
$middlewares->push($redirect_middleware);
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
}
|
||||
@@ -425,10 +402,13 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels = $labels->merge($redirect_to_non_www);
|
||||
$middlewares->push($to_non_www_name);
|
||||
}
|
||||
if ($redirect_direction === 'www' && ! str($host)->startsWith('www.')) {
|
||||
if ($redirect_direction === 'www' && !str($host)->startsWith('www.')) {
|
||||
$labels = $labels->merge($redirect_to_www);
|
||||
$middlewares->push($to_www_name);
|
||||
}
|
||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||
$middlewares->push($middleware_name);
|
||||
});
|
||||
if ($middlewares->isNotEmpty()) {
|
||||
$middlewares = $middlewares->join(',');
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares={$middlewares}");
|
||||
@@ -437,13 +417,7 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$middlewares = collect([]);
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
if ($basic_auth && $basic_auth_middleware) {
|
||||
$middlewares->push($basic_auth_middleware);
|
||||
}
|
||||
if ($redirect && $redirect_middleware) {
|
||||
$middlewares->push($redirect_middleware);
|
||||
}
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
}
|
||||
@@ -455,6 +429,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels = $labels->merge($redirect_to_www);
|
||||
$middlewares->push($to_www_name);
|
||||
}
|
||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||
$middlewares->push($middleware_name);
|
||||
});
|
||||
if ($middlewares->isNotEmpty()) {
|
||||
$middlewares = $middlewares->join(',');
|
||||
$labels->push("traefik.http.routers.{$https_label}.middlewares={$middlewares}");
|
||||
@@ -490,12 +467,6 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
if ($basic_auth && $basic_auth_middleware) {
|
||||
$middlewares->push($basic_auth_middleware);
|
||||
}
|
||||
if ($redirect && $redirect_middleware) {
|
||||
$middlewares->push($redirect_middleware);
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
}
|
||||
@@ -507,6 +478,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels = $labels->merge($redirect_to_www);
|
||||
$middlewares->push($to_www_name);
|
||||
}
|
||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||
$middlewares->push($middleware_name);
|
||||
});
|
||||
if ($middlewares->isNotEmpty()) {
|
||||
$middlewares = $middlewares->join(',');
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares={$middlewares}");
|
||||
@@ -516,12 +490,6 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
if ($is_gzip_enabled) {
|
||||
$middlewares->push('gzip');
|
||||
}
|
||||
if ($basic_auth && $basic_auth_middleware) {
|
||||
$middlewares->push($basic_auth_middleware);
|
||||
}
|
||||
if ($redirect && $redirect_middleware) {
|
||||
$middlewares->push($redirect_middleware);
|
||||
}
|
||||
if (str($image)->contains('ghost')) {
|
||||
$middlewares->push('redir-ghost');
|
||||
}
|
||||
@@ -533,6 +501,9 @@ function fqdnLabelsForTraefik(string $uuid, Collection $domains, bool $is_force_
|
||||
$labels = $labels->merge($redirect_to_www);
|
||||
$middlewares->push($to_www_name);
|
||||
}
|
||||
$middlewares_from_labels->each(function ($middleware_name) use ($middlewares) {
|
||||
$middlewares->push($middleware_name);
|
||||
});
|
||||
if ($middlewares->isNotEmpty()) {
|
||||
$middlewares = $middlewares->join(',');
|
||||
$labels->push("traefik.http.routers.{$http_label}.middlewares={$middlewares}");
|
||||
|
||||
@@ -1,14 +1,11 @@
|
||||
<?php
|
||||
|
||||
use App\Models\S3Storage;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
function set_s3_target(S3Storage $s3)
|
||||
{
|
||||
$is_digital_ocean = false;
|
||||
if ($s3->endpoint) {
|
||||
$is_digital_ocean = Str::contains($s3->endpoint, 'digitaloceanspaces.com');
|
||||
}
|
||||
|
||||
config()->set('filesystems.disks.custom-s3', [
|
||||
'driver' => 's3',
|
||||
'region' => $s3['region'],
|
||||
@@ -17,7 +14,7 @@ function set_s3_target(S3Storage $s3)
|
||||
'bucket' => $s3['bucket'],
|
||||
'endpoint' => $s3['endpoint'],
|
||||
'use_path_style_endpoint' => true,
|
||||
'bucket_endpoint' => $is_digital_ocean,
|
||||
'bucket_endpoint' => $s3->isHetzner() || $s3->isDigitalOcean(),
|
||||
'aws_url' => $s3->awsUrl(),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -522,6 +522,11 @@ function sslip(Server $server)
|
||||
|
||||
function get_service_templates(bool $force = false): Collection
|
||||
{
|
||||
if (isDev()) {
|
||||
$services = File::get(base_path('templates/service-templates.json'));
|
||||
|
||||
return collect(json_decode($services))->sortKeys();
|
||||
}
|
||||
if ($force) {
|
||||
try {
|
||||
$response = Http::retry(3, 1000)->get(config('constants.services.official'));
|
||||
@@ -708,7 +713,9 @@ function getTopLevelNetworks(Service|Application $resource)
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
if (is_string($networkDetails) || is_int($networkDetails)) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -758,7 +765,9 @@ function getTopLevelNetworks(Service|Application $resource)
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
if (is_string($networkDetails) || is_int($networkDetails)) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -824,6 +833,31 @@ function convertToArray($collection)
|
||||
return $collection;
|
||||
}
|
||||
|
||||
function parseCommandFromMagicEnvVariable(Str|string $key): Stringable
|
||||
{
|
||||
$value = str($key);
|
||||
$count = substr_count($value->value(), '_');
|
||||
if ($count === 2) {
|
||||
if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) {
|
||||
// SERVICE_FQDN_UMAMI
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
} else {
|
||||
// SERVICE_BASE64_UMAMI
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
}
|
||||
}
|
||||
if ($count === 3) {
|
||||
if ($value->startsWith('SERVICE_FQDN') || $value->startsWith('SERVICE_URL')) {
|
||||
// SERVICE_FQDN_UMAMI_1000
|
||||
$command = $value->after('SERVICE_')->before('_');
|
||||
} else {
|
||||
// SERVICE_BASE64_64_UMAMI
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
}
|
||||
}
|
||||
|
||||
return str($command);
|
||||
}
|
||||
function parseEnvVariable(Str|string $value)
|
||||
{
|
||||
$value = str($value);
|
||||
@@ -855,6 +889,7 @@ function parseEnvVariable(Str|string $value)
|
||||
} else {
|
||||
// SERVICE_BASE64_64_UMAMI
|
||||
$command = $value->after('SERVICE_')->beforeLast('_');
|
||||
ray($command);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1184,14 +1219,16 @@ function check_domain_usage(ServiceApplication|Application|null $resource = null
|
||||
function parseCommandsByLineForSudo(Collection $commands, Server $server): array
|
||||
{
|
||||
$commands = $commands->map(function ($line) {
|
||||
if (! str(trim($line))->startsWith([
|
||||
'cd',
|
||||
'command',
|
||||
'echo',
|
||||
'true',
|
||||
'if',
|
||||
'fi',
|
||||
])) {
|
||||
if (
|
||||
! str(trim($line))->startsWith([
|
||||
'cd',
|
||||
'command',
|
||||
'echo',
|
||||
'true',
|
||||
'if',
|
||||
'fi',
|
||||
])
|
||||
) {
|
||||
return "sudo $line";
|
||||
}
|
||||
|
||||
@@ -1606,7 +1643,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
if (is_string($networkDetails) || is_int($networkDetails)) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2521,7 +2560,9 @@ function parseDockerComposeFile(Service|Application $resource, bool $isNew = fal
|
||||
return $value == $networkName || $key == $networkName;
|
||||
});
|
||||
if (! $networkExists) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
if (is_string($networkDetails) || is_int($networkDetails)) {
|
||||
$topLevelNetworks->put($networkDetails, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2982,11 +3023,22 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
if ($isDatabase) {
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
$applicationFound = ServiceApplication::where('name', $serviceName)->where('image', $image)->where('service_id', $resource->id)->first();
|
||||
if ($applicationFound) {
|
||||
$savedService = $applicationFound;
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $applicationFound->name,
|
||||
'image' => $applicationFound->image,
|
||||
'service_id' => $applicationFound->service_id,
|
||||
]);
|
||||
$applicationFound->delete();
|
||||
} else {
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$savedService = ServiceApplication::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
@@ -3096,7 +3148,7 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
foreach ($magicEnvironments as $key => $value) {
|
||||
$key = str($key);
|
||||
$value = replaceVariables($value);
|
||||
$command = $key->after('SERVICE_')->before('_');
|
||||
$command = parseCommandFromMagicEnvVariable($key);
|
||||
$found = $resource->environment_variables()->where('key', $key->value())->where($nameOfId, $resource->id)->first();
|
||||
if ($found) {
|
||||
continue;
|
||||
@@ -3207,12 +3259,24 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
if ($serviceName === 'plausible') {
|
||||
$predefinedPort = '8000';
|
||||
}
|
||||
|
||||
if ($isDatabase) {
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
$applicationFound = ServiceApplication::where('name', $serviceName)->where('image', $image)->where('service_id', $resource->id)->first();
|
||||
if ($applicationFound) {
|
||||
$savedService = $applicationFound;
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $applicationFound->name,
|
||||
'image' => $applicationFound->image,
|
||||
'service_id' => $applicationFound->service_id,
|
||||
]);
|
||||
$applicationFound->delete();
|
||||
} else {
|
||||
$savedService = ServiceDatabase::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
'image' => $image,
|
||||
'service_id' => $resource->id,
|
||||
]);
|
||||
}
|
||||
} else {
|
||||
$savedService = ServiceApplication::firstOrCreate([
|
||||
'name' => $serviceName,
|
||||
@@ -3643,6 +3707,18 @@ function newParser(Application|Service $resource, int $pull_request_id = 0, ?int
|
||||
});
|
||||
}
|
||||
$serviceLabels = $labels->merge($defaultLabels);
|
||||
if ($serviceLabels->count() > 0) {
|
||||
if ($isApplication) {
|
||||
$isContainerLabelEscapeEnabled = data_get($resource, 'settings.is_container_label_escape_enabled');
|
||||
} else {
|
||||
$isContainerLabelEscapeEnabled = data_get($resource, 'is_container_label_escape_enabled');
|
||||
}
|
||||
if ($isContainerLabelEscapeEnabled) {
|
||||
$serviceLabels = $serviceLabels->map(function ($value, $key) {
|
||||
return escapeDollarSign($value);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (! $isDatabase && $fqdns instanceof Collection && $fqdns->count() > 0) {
|
||||
if ($isApplication) {
|
||||
$shouldGenerateLabelsExactly = $resource->destination->server->settings->generate_exact_labels;
|
||||
@@ -3863,14 +3939,19 @@ function convertComposeEnvironmentToArray($environment)
|
||||
{
|
||||
$convertedServiceVariables = collect([]);
|
||||
if (isAssociativeArray($environment)) {
|
||||
// Example: $environment = ['FOO' => 'bar', 'BAZ' => 'qux'];
|
||||
if ($environment instanceof Collection) {
|
||||
$changedEnvironment = collect([]);
|
||||
$environment->each(function ($value, $key) use ($changedEnvironment) {
|
||||
$parts = explode('=', $value, 2);
|
||||
if (count($parts) === 2) {
|
||||
$key = $parts[0];
|
||||
$realValue = $parts[1] ?? '';
|
||||
$changedEnvironment->put($key, $realValue);
|
||||
if (is_numeric($key)) {
|
||||
$parts = explode('=', $value, 2);
|
||||
if (count($parts) === 2) {
|
||||
$key = $parts[0];
|
||||
$realValue = $parts[1] ?? '';
|
||||
$changedEnvironment->put($key, $realValue);
|
||||
} else {
|
||||
$changedEnvironment->put($key, $value);
|
||||
}
|
||||
} else {
|
||||
$changedEnvironment->put($key, $value);
|
||||
}
|
||||
@@ -3880,12 +3961,15 @@ function convertComposeEnvironmentToArray($environment)
|
||||
}
|
||||
$convertedServiceVariables = $environment;
|
||||
} else {
|
||||
// Example: $environment = ['FOO=bar', 'BAZ=qux'];
|
||||
foreach ($environment as $value) {
|
||||
$parts = explode('=', $value, 2);
|
||||
$key = $parts[0];
|
||||
$realValue = $parts[1] ?? '';
|
||||
if ($key) {
|
||||
$convertedServiceVariables->put($key, $realValue);
|
||||
if (is_string($value)) {
|
||||
$parts = explode('=', $value, 2);
|
||||
$key = $parts[0];
|
||||
$realValue = $parts[1] ?? '';
|
||||
if ($key) {
|
||||
$convertedServiceVariables->put($key, $realValue);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3897,3 +3981,31 @@ function instanceSettings()
|
||||
{
|
||||
return InstanceSettings::get();
|
||||
}
|
||||
|
||||
function loadConfigFromGit(string $repository, string $branch, string $base_directory, int $server_id, int $team_id) {
|
||||
|
||||
$server = Server::find($server_id)->where('team_id', $team_id)->first();
|
||||
if (!$server) {
|
||||
return;
|
||||
}
|
||||
$uuid = new Cuid2();
|
||||
$cloneCommand = "git clone --no-checkout -b $branch $repository .";
|
||||
$workdir = rtrim($base_directory, '/');
|
||||
$fileList = collect([".$workdir/coolify.json"]);
|
||||
$commands = collect([
|
||||
"rm -rf /tmp/{$uuid}",
|
||||
"mkdir -p /tmp/{$uuid}",
|
||||
"cd /tmp/{$uuid}",
|
||||
$cloneCommand,
|
||||
'git sparse-checkout init --cone',
|
||||
"git sparse-checkout set {$fileList->implode(' ')}",
|
||||
'git read-tree -mu HEAD',
|
||||
"cat .$workdir/coolify.json",
|
||||
'rm -rf /tmp/{$uuid}',
|
||||
]);
|
||||
try {
|
||||
return instant_remote_process($commands, $server);
|
||||
} catch (\Exception $e) {
|
||||
// continue
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ return [
|
||||
|
||||
// The release version of your application
|
||||
// Example with dynamic git hash: trim(exec('git --git-dir ' . base_path('.git') . ' log --pretty="%h" -n1 HEAD'))
|
||||
'release' => '4.0.0-beta.349',
|
||||
'release' => '4.0.0-beta.357',
|
||||
// When left empty or `null` the Laravel environment will be used
|
||||
'environment' => config('app.env'),
|
||||
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
<?php
|
||||
return '4.0.0-beta.357';
|
||||
|
||||
return '4.0.0-beta.349';
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('scheduled_database_backups', function (Blueprint $table) {
|
||||
$table->boolean('dump_all')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('scheduled_database_backups', function (Blueprint $table) {
|
||||
$table->dropColumn('dump_all');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -58,6 +58,7 @@ services:
|
||||
SOKETI_DEFAULT_APP_ID: "${PUSHER_APP_ID:-coolify}"
|
||||
SOKETI_DEFAULT_APP_KEY: "${PUSHER_APP_KEY:-coolify}"
|
||||
SOKETI_DEFAULT_APP_SECRET: "${PUSHER_APP_SECRET:-coolify}"
|
||||
entrypoint: ["/bin/sh", "/soketi-entrypoint.sh"]
|
||||
vite:
|
||||
image: node:20
|
||||
pull_policy: always
|
||||
|
||||
@@ -113,7 +113,7 @@ services:
|
||||
retries: 10
|
||||
timeout: 2s
|
||||
soketi:
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.2'
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.3'
|
||||
ports:
|
||||
- "${SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
|
||||
@@ -1,9 +1,27 @@
|
||||
FROM quay.io/soketi/soketi:1.6-16-alpine
|
||||
|
||||
ARG TARGETPLATFORM
|
||||
# https://github.com/cloudflare/cloudflared/releases
|
||||
ARG CLOUDFLARED_VERSION=2024.4.1
|
||||
|
||||
WORKDIR /terminal
|
||||
RUN apk add --no-cache openssh-client make g++ python3
|
||||
RUN apk add --no-cache openssh-client make g++ python3 curl
|
||||
COPY docker/coolify-realtime/package.json ./
|
||||
RUN npm i
|
||||
RUN npm rebuild node-pty --update-binary
|
||||
COPY docker/coolify-realtime/soketi-entrypoint.sh /soketi-entrypoint.sh
|
||||
COPY docker/coolify-realtime/terminal-server.js /terminal/terminal-server.js
|
||||
|
||||
RUN /bin/sh -c "if [[ ${TARGETPLATFORM} == 'linux/amd64' ]]; then \
|
||||
echo 'amd64' && \
|
||||
curl -sSL https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-amd64 -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared \
|
||||
;fi"
|
||||
|
||||
RUN /bin/sh -c "if [[ ${TARGETPLATFORM} == 'linux/arm64' ]]; then \
|
||||
echo 'arm64' && \
|
||||
curl -L https://github.com/cloudflare/cloudflared/releases/download/${CLOUDFLARED_VERSION}/cloudflared-linux-arm64 -o /usr/local/bin/cloudflared && chmod +x /usr/local/bin/cloudflared \
|
||||
;fi"
|
||||
|
||||
|
||||
|
||||
ENTRYPOINT ["/bin/sh", "/soketi-entrypoint.sh"]
|
||||
|
||||
@@ -1,11 +1,19 @@
|
||||
#!/bin/sh
|
||||
# Function to timestamp logs
|
||||
|
||||
# Check if the first argument is 'watch'
|
||||
if [ "$1" = "watch" ]; then
|
||||
WATCH_MODE="--watch"
|
||||
else
|
||||
WATCH_MODE=""
|
||||
fi
|
||||
|
||||
timestamp() {
|
||||
date "+%Y-%m-%d %H:%M:%S"
|
||||
}
|
||||
|
||||
# Start the terminal server in the background with logging
|
||||
node /terminal/terminal-server.js > >(while read line; do echo "$(timestamp) [TERMINAL] $line"; done) 2>&1 &
|
||||
node $WATCH_MODE /terminal/terminal-server.js > >(while read line; do echo "$(timestamp) [TERMINAL] $line"; done) 2>&1 &
|
||||
TERMINAL_PID=$!
|
||||
|
||||
# Start the Soketi process in the background with logging
|
||||
|
||||
@@ -61,9 +61,13 @@ wss.on('connection', (ws) => {
|
||||
const userSession = { ws, userId, ptyProcess: null, isActive: false };
|
||||
userSessions.set(userId, userSession);
|
||||
|
||||
ws.on('message', (message) => handleMessage(userSession, message));
|
||||
ws.on('message', (message) => {
|
||||
handleMessage(userSession, message);
|
||||
|
||||
});
|
||||
ws.on('error', (err) => handleError(err, userId));
|
||||
ws.on('close', () => handleClose(userId));
|
||||
|
||||
});
|
||||
|
||||
const messageHandlers = {
|
||||
@@ -108,7 +112,6 @@ function parseMessage(message) {
|
||||
|
||||
async function handleCommand(ws, command, userId) {
|
||||
const userSession = userSessions.get(userId);
|
||||
|
||||
if (userSession && userSession.isActive) {
|
||||
const result = await killPtyProcess(userId);
|
||||
if (!result) {
|
||||
@@ -127,6 +130,7 @@ async function handleCommand(ws, command, userId) {
|
||||
cols: 80,
|
||||
rows: 30,
|
||||
cwd: process.env.HOME,
|
||||
env: {},
|
||||
};
|
||||
|
||||
// NOTE: - Initiates a process within the Terminal container
|
||||
@@ -139,13 +143,16 @@ async function handleCommand(ws, command, userId) {
|
||||
|
||||
ws.send('pty-ready');
|
||||
|
||||
ptyProcess.onData((data) => ws.send(data));
|
||||
ptyProcess.onData((data) => {
|
||||
ws.send(data);
|
||||
});
|
||||
|
||||
// when parent closes
|
||||
ptyProcess.onExit(({ exitCode, signal }) => {
|
||||
console.error(`Process exited with code ${exitCode} and signal ${signal}`);
|
||||
ws.send('pty-exited');
|
||||
userSession.isActive = false;
|
||||
|
||||
});
|
||||
|
||||
if (timeout) {
|
||||
@@ -179,7 +186,7 @@ async function killPtyProcess(userId) {
|
||||
|
||||
// session.ptyProcess.kill() wont work here because of https://github.com/moby/moby/issues/9098
|
||||
// patch with https://github.com/moby/moby/issues/9098#issuecomment-189743947
|
||||
session.ptyProcess.write('kill -TERM -$$ && exit\n');
|
||||
session.ptyProcess.write('set +o history\nkill -TERM -$$ && exit\nset -o history\n');
|
||||
|
||||
setTimeout(() => {
|
||||
if (!session.isActive || !session.ptyProcess) {
|
||||
@@ -228,5 +235,5 @@ function extractHereDocContent(commandString) {
|
||||
}
|
||||
|
||||
server.listen(6002, () => {
|
||||
console.log('Server listening on port 6002');
|
||||
console.log('Coolify realtime terminal server listening on port 6002. Let the hacking begin!');
|
||||
});
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
"auth.register": "S'enregistrer",
|
||||
"auth.registration_disabled": "L'enregistrement est désactivé. Merci de contacter l'administateur.",
|
||||
"auth.reset_password": "Réinitialiser le mot de passe",
|
||||
"auth.failed": "Aucune correspondance n'a été trouvé pour les informations d'identification renseignées.",
|
||||
"auth.failed": "Aucune correspondance n'a été trouvée pour les informations d'identification renseignées.",
|
||||
"auth.failed.callback": "Erreur lors du processus de retour de la plateforme de connexion.",
|
||||
"auth.failed.password": "Le mot de passe renseigné est incorrect.",
|
||||
"auth.failed.email": "Aucun utilisateur avec cette adresse email n'a été trouvé.",
|
||||
|
||||
@@ -46,6 +46,9 @@ services:
|
||||
- PUSHER_APP_ID
|
||||
- PUSHER_APP_KEY
|
||||
- PUSHER_APP_SECRET
|
||||
- TERMINAL_PROTOCOL
|
||||
- TERMINAL_HOST
|
||||
- TERMINAL_PORT
|
||||
- AUTOUPDATE
|
||||
- SELF_HOSTED
|
||||
- SSH_MUX_ENABLED
|
||||
@@ -110,7 +113,7 @@ services:
|
||||
retries: 10
|
||||
timeout: 2s
|
||||
soketi:
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.2'
|
||||
image: 'ghcr.io/coollabsio/coolify-realtime:1.0.3'
|
||||
ports:
|
||||
- "${SOKETI_PORT:-6001}:6001"
|
||||
- "6002:6002"
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
{
|
||||
"coolify": {
|
||||
"v4": {
|
||||
"version": "4.0.0-beta.349"
|
||||
"version": "4.0.0-beta.354"
|
||||
},
|
||||
"nightly": {
|
||||
"version": "4.0.0-beta.350"
|
||||
"version": "4.0.0-beta.355"
|
||||
},
|
||||
"helper": {
|
||||
"version": "1.0.1"
|
||||
"version": "1.0.2"
|
||||
},
|
||||
"realtime": {
|
||||
"version": "1.0.2"
|
||||
"version": "1.0.3"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
9
package-lock.json
generated
@@ -10,7 +10,7 @@
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"alpinejs": "3.14.0",
|
||||
"cookie": "^0.6.0",
|
||||
"cookie": "^0.7.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"ioredis": "5.4.1",
|
||||
"node-pty": "^1.0.0",
|
||||
@@ -960,10 +960,9 @@
|
||||
"integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
|
||||
},
|
||||
"node_modules/cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw==",
|
||||
"license": "MIT",
|
||||
"version": "0.7.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.0.tgz",
|
||||
"integrity": "sha512-qCf+V4dtlNhSRXGAZatc1TasyFO6GjohcOul807YOb5ik3+kQSnb4d7iajeCL8QHaJ4uZEjCgiCJerKXwdRVlQ==",
|
||||
"engines": {
|
||||
"node": ">= 0.6"
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"@xterm/addon-fit": "^0.10.0",
|
||||
"@xterm/xterm": "^5.5.0",
|
||||
"alpinejs": "3.14.0",
|
||||
"cookie": "^0.6.0",
|
||||
"cookie": "^0.7.0",
|
||||
"dotenv": "^16.4.5",
|
||||
"ioredis": "5.4.1",
|
||||
"node-pty": "^1.0.0",
|
||||
|
||||
88
public/svgs/affine.svg
Normal file
@@ -0,0 +1,88 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 500 500" width="500" height="500" style="width:100%;height:100%;transform:translate3d(0,0,0);content-visibility:visible">
|
||||
<defs>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="a"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="g"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="b"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="c"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="d"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="e"/>
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0z" transform="translate(250 250)" style="display:block" id="f"/>
|
||||
<mask id="r" mask-type="alpha">
|
||||
<use xlink:href="#a"/>
|
||||
</mask>
|
||||
<mask id="p" mask-type="alpha">
|
||||
<use xlink:href="#b"/>
|
||||
</mask>
|
||||
<mask id="n" mask-type="alpha">
|
||||
<use xlink:href="#c"/>
|
||||
</mask>
|
||||
<mask id="m" mask-type="alpha">
|
||||
<use xlink:href="#d"/>
|
||||
</mask>
|
||||
<mask id="l" mask-type="alpha">
|
||||
<use xlink:href="#e"/>
|
||||
</mask>
|
||||
<mask id="k" mask-type="alpha">
|
||||
<use xlink:href="#f"/>
|
||||
</mask>
|
||||
<mask id="j" mask-type="alpha">
|
||||
<use xlink:href="#g"/>
|
||||
</mask>
|
||||
<clipPath id="h">
|
||||
<path d="M0 0h500v500H0z"/>
|
||||
</clipPath>
|
||||
<clipPath id="i">
|
||||
<path d="M0 0h500v500H0z"/>
|
||||
</clipPath>
|
||||
<clipPath id="s">
|
||||
<path d="M0 0h1920v1080H0z"/>
|
||||
</clipPath>
|
||||
<clipPath id="q">
|
||||
<path d="M0 0h1920v1080H0z"/>
|
||||
</clipPath>
|
||||
<clipPath id="o">
|
||||
<path d="M0 0h1920v1080H0z"/>
|
||||
</clipPath>
|
||||
</defs>
|
||||
<g clip-path="url(#h)">
|
||||
<g clip-path="url(#i)" transform="translate(0 24)" style="display:block">
|
||||
<path d="M-6.816-205.027c-20.92 36.208-170.344 294.875-187.382 324.715-1.947 4.684 1.644 10.592 6.749 10.684 1.368.132 11.815.066 13.815.079 97.651.04 259.272-.026 357.187 0 1.526 0 3.79.013 3.895-.079.618.053 1.105-.198 1.658-.224 4.25-1.276 6.815-6.276 5.091-10.447-.408-.592-.237-.67-1.342-2.486C143.266 31.247 71.403-93.101 21.696-179.24c-3.052-5.052-11.868-20.735-14.881-25.774-2.96-5.144-10.684-5.21-13.644 0zm-20.511-11.842c9.105-16.065 30.997-20.709 45.904-9.762 3.566 2.645 6.513 6.039 8.763 9.762l4.96 8.592 9.921 17.183L200.973 83.875l9.921 17.183c1.671 2.987 3.21 5.25 5.236 9.644 1.605 4.105 2.435 8.539 2.29 12.973-.382 13.381-9.974 25.656-22.881 29.248-4.184 1.184-9.144 1.237-11.986 1.184-98.112-.118-259.378.092-357.187 0-6.723-.237-14.512.763-21.906-1.197-17.788-4.96-27.683-25.183-20.578-42.234 17.486-31.524 167.371-290.153 188.791-327.545" transform="translate(250 250)" style="display:block"/>
|
||||
<g mask="url(#j)" style="display:block">
|
||||
<path d="m202.134 244.025 41.827 72.456c2.684 4.658 9.407 4.658 12.091 0l41.826-72.456c2.684-4.658-.671-10.473-6.039-10.473h-83.652c-5.368 0-8.736 5.815-6.039 10.473zm44.182 47.642-21.525-37.274c-1.645-2.842.408-6.394 3.697-6.394h43.05c3.276 0 5.328 3.552 3.697 6.394l-21.525 37.274c-1.645 2.842-5.736 2.842-7.381 0z"/>
|
||||
</g>
|
||||
<g mask="url(#k)" style="display:block">
|
||||
<path d="M230.369 47.341c-22.906 53.22-42.589 115.018-23.274 172.146 2.802 7.868 6.288 15.42 10.604 22.591l-12.486 7.302c-4.684-7.881-8.618-16.486-11.657-25.222-17.749-52.128-4.526-108.427 14.486-158.029 3.197-8.184 6.605-16.262 10.157-24.248l12.157 5.447z"/>
|
||||
</g>
|
||||
<g mask="url(#l)" style="display:block">
|
||||
<path d="M448.039 356.347c-34.642-46.457-78.31-94.402-137.451-106.23-8.21-1.5-16.499-2.263-24.867-2.105l-.079-14.46c9.17-.118 18.578.776 27.669 2.513 54.01 10.697 96.165 50.286 129.61 91.56 5.486 6.855 10.776 13.855 15.92 20.92z"/>
|
||||
</g>
|
||||
<g mask="url(#m)" style="display:block">
|
||||
<path d="M71.59 390.345c57.549-6.776 120.914-20.617 160.727-65.93 5.408-6.355 10.21-13.158 14.262-20.486l12.565 7.158c-4.487 7.999-9.973 15.709-16.012 22.709-36.274 41.432-91.626 58.141-144.096 66.469a586 586 0 0 1-26.077 3.329l-1.355-13.249z"/>
|
||||
</g>
|
||||
<g mask="url(#n)" style="display:block">
|
||||
<g clip-path="url(#o)" transform="translate(-710 -290)">
|
||||
<path d="m26.6-48.803-69.413 93.109-5.881-7.184 62.386-93.517z" transform="translate(990.142 584.502)" style="display:block"/>
|
||||
<path d="M-69.58 28.086 57.952-72.23l11.212 14.81-133.09 92.966z" transform="translate(988.235 608.382)" style="display:block"/>
|
||||
<path d="m-101.789 16.832 210.317-98.614 8.268 18.054-214.415 89.649z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
<path d="m-165.267 36.82 324.014-66.518 4.06 20.75-326.033 56.216z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
</g>
|
||||
</g>
|
||||
<g mask="url(#p)" style="display:block">
|
||||
<g clip-path="url(#q)" transform="rotate(120 689.283 205.728)">
|
||||
<path d="m26.6-48.803-69.413 93.109-5.881-7.184 62.386-93.517z" transform="translate(990.142 584.502)" style="display:block"/>
|
||||
<path d="M-69.58 28.086 57.952-72.23l11.212 14.81-133.09 92.966z" transform="translate(988.235 608.382)" style="display:block"/>
|
||||
<path d="m-101.789 16.832 210.317-98.614 8.268 18.054-214.415 89.649z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
<path d="m-165.267 36.82 324.014-66.518 4.06 20.75-326.033 56.216z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
</g>
|
||||
</g>
|
||||
<g mask="url(#r)" style="display:block">
|
||||
<g clip-path="url(#s)" transform="rotate(-120 520.37 615.193)">
|
||||
<path d="m26.6-48.803-69.413 93.109-5.881-7.184 62.386-93.517z" transform="translate(990.142 584.502)" style="display:block"/>
|
||||
<path d="M-69.58 28.086 57.952-72.23l11.212 14.81-133.09 92.966z" transform="translate(988.235 608.382)" style="display:block"/>
|
||||
<path d="m-101.789 16.832 210.317-98.614 8.268 18.054-214.415 89.649z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
<path d="m-165.267 36.82 324.014-66.518 4.06 20.75-326.033 56.216z" transform="translate(981.847 640.913)" style="display:block"/>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 9.0 KiB |
166
public/svgs/anythingllm.svg
Normal file
@@ -0,0 +1,166 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0.00 0.00 245.00 245.00">
|
||||
<path stroke="#919393" stroke-width="2.00" fill="none" stroke-linecap="butt" vector-effect="non-scaling-stroke" d="
|
||||
M 187.03 159.00
|
||||
L 161.49 159.00
|
||||
A 1.24 1.24 0.0 0 1 160.48 158.48
|
||||
Q 153.96 149.33 147.89 140.81
|
||||
C 145.78 137.86 141.80 138.01 139.49 140.67
|
||||
C 136.43 144.17 133.65 147.56 136.44 151.42
|
||||
Q 142.22 159.39 148.22 167.98
|
||||
Q 152.74 174.47 160.49 174.57
|
||||
Q 173.94 174.73 188.79 174.60
|
||||
C 196.64 174.52 203.24 168.72 203.23 160.63
|
||||
Q 203.16 123.84 203.20 83.74
|
||||
C 203.21 78.41 199.97 73.56 195.17 71.35
|
||||
Q 191.90 69.85 186.23 69.92
|
||||
Q 173.94 70.08 161.37 69.94
|
||||
C 156.39 69.89 152.10 71.63 149.08 75.49
|
||||
Q 117.03 116.46 84.45 158.09
|
||||
A 2.37 2.35 -70.9 0 1 82.59 159.00
|
||||
L 57.21 159.00
|
||||
Q 56.65 159.00 56.65 158.45
|
||||
L 56.66 85.95
|
||||
Q 56.66 85.31 57.30 85.31
|
||||
L 83.00 85.31
|
||||
A 0.80 0.79 71.0 0 1 83.63 85.62
|
||||
Q 90.51 94.60 97.61 104.71
|
||||
C 99.47 107.36 103.07 108.21 105.48 105.83
|
||||
Q 107.60 103.72 109.70 100.67
|
||||
C 110.60 99.36 110.38 97.79 110.28 96.30
|
||||
Q 110.23 95.62 109.82 95.07
|
||||
Q 103.03 85.94 96.91 77.34
|
||||
C 93.63 72.73 89.66 69.98 84.18 70.00
|
||||
Q 71.60 70.05 56.56 69.96
|
||||
C 50.37 69.93 45.44 72.61 42.63 78.14
|
||||
Q 41.19 80.99 41.25 87.27
|
||||
Q 41.55 120.87 41.27 158.11
|
||||
Q 41.23 162.77 42.32 165.57
|
||||
Q 44.32 170.75 49.37 173.22
|
||||
Q 52.63 174.81 60.03 174.72
|
||||
Q 72.58 174.56 82.84 174.65
|
||||
Q 91.13 174.73 95.47 169.18
|
||||
Q 127.35 128.40 160.51 86.00
|
||||
A 1.81 1.80 18.9 0 1 161.93 85.31
|
||||
L 187.42 85.31
|
||||
A 0.40 0.40 0.0 0 1 187.82 85.71
|
||||
L 187.82 158.21
|
||||
Q 187.82 159.00 187.03 159.00"
|
||||
/>
|
||||
<path fill="#222627" d="
|
||||
M 46.00 0.00
|
||||
L 198.80 0.00
|
||||
Q 221.03 2.81 233.86 19.40
|
||||
Q 244.84 33.61 244.80 52.00
|
||||
Q 244.65 120.20 244.83 188.95
|
||||
Q 244.86 199.26 243.39 205.30
|
||||
Q 241.12 214.72 235.86 222.46
|
||||
C 234.56 224.37 232.98 226.08 231.56 227.86
|
||||
Q 229.92 229.91 227.88 231.54
|
||||
C 226.00 233.04 224.26 234.66 222.24 236.01
|
||||
Q 214.15 241.39 204.78 243.49
|
||||
Q 198.73 244.86 188.67 244.83
|
||||
Q 119.30 244.65 52.55 244.80
|
||||
Q 32.84 244.84 18.81 233.38
|
||||
Q 2.64 220.18 0.00 198.69
|
||||
L 0.00 45.76
|
||||
Q 1.42 35.66 4.33 29.79
|
||||
Q 17.17 3.86 46.00 0.00
|
||||
Z
|
||||
M 187.03 159.00
|
||||
L 161.49 159.00
|
||||
A 1.24 1.24 0.0 0 1 160.48 158.48
|
||||
Q 153.96 149.33 147.89 140.81
|
||||
C 145.78 137.86 141.80 138.01 139.49 140.67
|
||||
C 136.43 144.17 133.65 147.56 136.44 151.42
|
||||
Q 142.22 159.39 148.22 167.98
|
||||
Q 152.74 174.47 160.49 174.57
|
||||
Q 173.94 174.73 188.79 174.60
|
||||
C 196.64 174.52 203.24 168.72 203.23 160.63
|
||||
Q 203.16 123.84 203.20 83.74
|
||||
C 203.21 78.41 199.97 73.56 195.17 71.35
|
||||
Q 191.90 69.85 186.23 69.92
|
||||
Q 173.94 70.08 161.37 69.94
|
||||
C 156.39 69.89 152.10 71.63 149.08 75.49
|
||||
Q 117.03 116.46 84.45 158.09
|
||||
A 2.37 2.35 -70.9 0 1 82.59 159.00
|
||||
L 57.21 159.00
|
||||
Q 56.65 159.00 56.65 158.45
|
||||
L 56.66 85.95
|
||||
Q 56.66 85.31 57.30 85.31
|
||||
L 83.00 85.31
|
||||
A 0.80 0.79 71.0 0 1 83.63 85.62
|
||||
Q 90.51 94.60 97.61 104.71
|
||||
C 99.47 107.36 103.07 108.21 105.48 105.83
|
||||
Q 107.60 103.72 109.70 100.67
|
||||
C 110.60 99.36 110.38 97.79 110.28 96.30
|
||||
Q 110.23 95.62 109.82 95.07
|
||||
Q 103.03 85.94 96.91 77.34
|
||||
C 93.63 72.73 89.66 69.98 84.18 70.00
|
||||
Q 71.60 70.05 56.56 69.96
|
||||
C 50.37 69.93 45.44 72.61 42.63 78.14
|
||||
Q 41.19 80.99 41.25 87.27
|
||||
Q 41.55 120.87 41.27 158.11
|
||||
Q 41.23 162.77 42.32 165.57
|
||||
Q 44.32 170.75 49.37 173.22
|
||||
Q 52.63 174.81 60.03 174.72
|
||||
Q 72.58 174.56 82.84 174.65
|
||||
Q 91.13 174.73 95.47 169.18
|
||||
Q 127.35 128.40 160.51 86.00
|
||||
A 1.81 1.80 18.9 0 1 161.93 85.31
|
||||
L 187.42 85.31
|
||||
A 0.40 0.40 0.0 0 1 187.82 85.71
|
||||
L 187.82 158.21
|
||||
Q 187.82 159.00 187.03 159.00
|
||||
Z"
|
||||
/>
|
||||
<path fill="#ffffff" d="
|
||||
M 187.82 158.21
|
||||
L 187.82 85.71
|
||||
A 0.40 0.40 0.0 0 0 187.42 85.31
|
||||
L 161.93 85.31
|
||||
A 1.81 1.80 18.9 0 0 160.51 86.00
|
||||
Q 127.35 128.40 95.47 169.18
|
||||
Q 91.13 174.73 82.84 174.65
|
||||
Q 72.58 174.56 60.03 174.72
|
||||
Q 52.63 174.81 49.37 173.22
|
||||
Q 44.32 170.75 42.32 165.57
|
||||
Q 41.23 162.77 41.27 158.11
|
||||
Q 41.55 120.87 41.25 87.27
|
||||
Q 41.19 80.99 42.63 78.14
|
||||
C 45.44 72.61 50.37 69.93 56.56 69.96
|
||||
Q 71.60 70.05 84.18 70.00
|
||||
C 89.66 69.98 93.63 72.73 96.91 77.34
|
||||
Q 103.03 85.94 109.82 95.07
|
||||
Q 110.23 95.62 110.28 96.30
|
||||
C 110.38 97.79 110.60 99.36 109.70 100.67
|
||||
Q 107.60 103.72 105.48 105.83
|
||||
C 103.07 108.21 99.47 107.36 97.61 104.71
|
||||
Q 90.51 94.60 83.63 85.62
|
||||
A 0.80 0.79 71.0 0 0 83.00 85.31
|
||||
L 57.30 85.31
|
||||
Q 56.66 85.31 56.66 85.95
|
||||
L 56.65 158.45
|
||||
Q 56.65 159.00 57.21 159.00
|
||||
L 82.59 159.00
|
||||
A 2.37 2.35 -70.9 0 0 84.45 158.09
|
||||
Q 117.03 116.46 149.08 75.49
|
||||
C 152.10 71.63 156.39 69.89 161.37 69.94
|
||||
Q 173.94 70.08 186.23 69.92
|
||||
Q 191.90 69.85 195.17 71.35
|
||||
C 199.97 73.56 203.21 78.41 203.20 83.74
|
||||
Q 203.16 123.84 203.23 160.63
|
||||
C 203.24 168.72 196.64 174.52 188.79 174.60
|
||||
Q 173.94 174.73 160.49 174.57
|
||||
Q 152.74 174.47 148.22 167.98
|
||||
Q 142.22 159.39 136.44 151.42
|
||||
C 133.65 147.56 136.43 144.17 139.49 140.67
|
||||
C 141.80 138.01 145.78 137.86 147.89 140.81
|
||||
Q 153.96 149.33 160.48 158.48
|
||||
A 1.24 1.24 0.0 0 0 161.49 159.00
|
||||
L 187.03 159.00
|
||||
Q 187.82 159.00 187.82 158.21
|
||||
Z"
|
||||
/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.1 KiB |
BIN
public/svgs/argilla.png
Normal file
|
After Width: | Height: | Size: 18 KiB |
15
public/svgs/bitcoin.svg
Normal file
@@ -0,0 +1,15 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<!-- Creator: CorelDRAW 2019 (64-Bit) -->
|
||||
<svg xmlns="http://www.w3.org/2000/svg" xml:space="preserve" width="100%" height="100%" version="1.1" shape-rendering="geometricPrecision" text-rendering="geometricPrecision" image-rendering="optimizeQuality" fill-rule="evenodd" clip-rule="evenodd"
|
||||
viewBox="0 0 4091.27 4091.73"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns:xodm="http://www.corel.com/coreldraw/odm/2003">
|
||||
<g id="Layer_x0020_1">
|
||||
<metadata id="CorelCorpID_0Corel-Layer"/>
|
||||
<g id="_1421344023328">
|
||||
<path fill="#F7931A" fill-rule="nonzero" d="M4030.06 2540.77c-273.24,1096.01 -1383.32,1763.02 -2479.46,1489.71 -1095.68,-273.24 -1762.69,-1383.39 -1489.33,-2479.31 273.12,-1096.13 1383.2,-1763.19 2479,-1489.95 1096.06,273.24 1763.03,1383.51 1489.76,2479.57l0.02 -0.02z"/>
|
||||
<path fill="white" fill-rule="nonzero" d="M2947.77 1754.38c40.72,-272.26 -166.56,-418.61 -450,-516.24l91.95 -368.8 -224.5 -55.94 -89.51 359.09c-59.02,-14.72 -119.63,-28.59 -179.87,-42.34l90.16 -361.46 -224.36 -55.94 -92 368.68c-48.84,-11.12 -96.81,-22.11 -143.35,-33.69l0.26 -1.16 -309.59 -77.31 -59.72 239.78c0,0 166.56,38.18 163.05,40.53 90.91,22.69 107.35,82.87 104.62,130.57l-104.74 420.15c6.26,1.59 14.38,3.89 23.34,7.49 -7.49,-1.86 -15.46,-3.89 -23.73,-5.87l-146.81 588.57c-11.11,27.62 -39.31,69.07 -102.87,53.33 2.25,3.26 -163.17,-40.72 -163.17,-40.72l-111.46 256.98 292.15 72.83c54.35,13.63 107.61,27.89 160.06,41.3l-92.9 373.03 224.24 55.94 92 -369.07c61.26,16.63 120.71,31.97 178.91,46.43l-91.69 367.33 224.51 55.94 92.89 -372.33c382.82,72.45 670.67,43.24 791.83,-303.02 97.63,-278.78 -4.86,-439.58 -206.26,-544.44 146.69,-33.83 257.18,-130.31 286.64,-329.61l-0.07 -0.05zm-512.93 719.26c-69.38,278.78 -538.76,128.08 -690.94,90.29l123.28 -494.2c152.17,37.99 640.17,113.17 567.67,403.91zm69.43 -723.3c-63.29,253.58 -453.96,124.75 -580.69,93.16l111.77 -448.21c126.73,31.59 534.85,90.55 468.94,355.05l-0.02 0z"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.0 KiB |
1
public/svgs/clickhouse.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="215" height="90" viewBox="0 0 100 43" fill="currentColor" xmlns="http://www.w3.org/2000/svg"><g clip-path="url(#clip0_378_10860)"><rect x="2.70837" y="2.875" width="2.24992" height="20.2493" rx="0.236664" fill="currentColor" /><rect x="7.2085" y="2.875" width="2.24992" height="20.2493" rx="0.236664" fill="currentColor" /><rect x="11.7086" y="2.875" width="2.24992" height="20.2493" rx="0.236664" fill="currentColor" /><rect x="16.2076" y="2.875" width="2.24992" height="20.2493" rx="0.236664" fill="currentColor" /><rect x="20.7087" y="10.7502" width="2.24992" height="4.49985" rx="0.236664" fill="currentColor" /></g></svg>
|
||||
|
After Width: | Height: | Size: 642 B |
7
public/svgs/cloudbeaver.svg
Normal file
@@ -0,0 +1,7 @@
|
||||
<svg width="47" height="30" viewBox="0 0 47 30" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M38.7759 14.1873C38.5379 14.1873 38.7759 14.1873 38.7759 14.1873C38.7759 6.60302 31.8594 0 24.0793 0C18.3479 0 13.236 3.37708 11.0359 8.16627C10.9594 8.16474 11.0363 8.16474 10.9594 8.16474C4.91834 8.16474 0 13.4481 0 19.3371C0 23.5291 1.79123 26.7912 5.40029 28.5334C5.97588 27.949 7.40249 27.9389 8.13884 27.5428C6.84539 27.1249 5.79299 26.2659 4.66867 25.4489C0.803302 22.6401 1.38287 15.7952 3.91798 13.4851C7.97916 9.78429 12.4979 10.7237 12.4979 10.7237L13.059 9.50237C13.9945 7.46591 15.8766 1.56091 24.4742 1.66552C33.5675 1.77619 36.0433 11.1473 36.0467 14.2713C36.0464 14.284 36.0463 14.2969 36.0463 14.3097L36.0415 16.517L38.2972 16.326C38.4759 16.3108 38.6533 16.3031 38.8244 16.3031C42.127 16.3031 45.4997 18.8079 45.4997 22.0274C45.4997 25.2468 42.127 27.9805 38.8244 27.9805H20.1518C20.3643 28.0866 22.5177 30 26.0633 30H38.8244C43.2765 30 46.8855 26.4818 46.8855 22.1418C46.8855 17.8019 43.228 14.1873 38.7759 14.1873Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.8004 9.8463C31.95 9.53546 29.7648 9.74492 28.2297 10.3292C27.4766 10.6158 26.8793 10.9921 26.674 11.4423C26.1107 12.6779 29.5611 14.8228 30.9519 14.4284C31.6146 14.2404 32.5663 12.8654 32.9903 11.6624C33.2918 10.8073 33.3271 10.0389 32.8004 9.8463Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M25.0842 10.8637C24.6901 10.8148 23.8755 10.7075 23.6155 10.4203C23.0338 9.77811 22.1014 9.60573 21.4237 9.75105C20.7054 9.90502 20.3232 10.7199 20.8163 11.7331C21.0382 12.189 20.9819 12.7384 20.7558 13.148C21.462 12.5069 22.1221 11.9844 22.6119 11.7331C23.5772 11.2382 24.4333 10.9815 25.0842 10.8637Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M32.1314 20.2602C32.1314 20.2602 31.4272 22.5942 30.9343 23.6582C30.4998 24.5958 30.3622 24.5209 30.0482 24.6307C30.1662 24.34 30.2513 23.9586 30.4061 23.3149C30.5923 22.5406 30.4061 22.3368 30.4061 22.3368C30.162 23.4955 29.7824 24.3235 29.46 24.8668C29.0416 25.0032 28.5273 25.0913 28.1527 24.9452C27.6246 24.7393 27.5349 22.3195 27.5349 22.1823C29.8332 22.3368 31.0575 21.4272 32.1314 20.2602ZM20.8335 17.7094C20.8821 17.934 20.9363 18.1447 20.9929 18.349C20.9577 18.3105 20.9391 18.2896 20.9391 18.2896C20.9391 18.2896 20.9842 18.3913 21.0538 18.5659C21.1504 18.8876 21.2571 19.1817 21.3709 19.4538C21.7489 20.6371 22.1519 22.4536 21.5511 23.5925C21.1018 24.4441 15.3943 28.2867 25.1501 29.9574L33.9076 27.9808C30.0498 27.4718 31.5994 24.4504 32.5187 22.8344C33.622 20.8947 33.9986 19.6596 34.2362 17.8778C34.3792 16.8067 34.274 16.0052 34.2439 15.8123C34.2392 15.7831 34.2362 15.7669 34.2362 15.7669C34.2362 15.7669 34.232 15.8268 34.2207 15.9294L34.2362 15.6639C34.2362 15.6639 33.5397 18.3926 32.1666 19.3708C31.8471 19.5983 31.6426 19.7498 31.5115 19.8517C31.6499 19.3431 32.1686 17.1988 31.4272 16.0244C31.4272 16.0244 31.12 20.9578 28.4217 21.2197C25.7233 21.4816 21.9208 18.7903 20.8335 17.7094Z" fill="white"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M13.0693 17.5462C12.9609 18.1371 12.9143 18.6691 12.9312 19.1378C12.4068 19.9482 8.62053 28.7229 3.91797 24.7801C4.7226 25.4678 5.40027 28.5338 5.40027 28.5338C9.82341 31.0535 12.8862 21.1715 13.2359 20.5234C13.5211 21.1173 14.0027 22.3232 16.6758 22.3769C16.6758 22.3769 13.5399 20.8782 14.9397 16.901C16.3395 12.9238 18.4087 9.54824 21.2501 7.98749C24.0914 6.42674 26.9623 6.53321 29.603 7.63149C29.603 7.63149 25.6177 4.05998 21.0383 6.75964C18.4072 8.31077 16.6555 10.0319 15.4497 11.7959C14.4386 11.9719 13.2092 11.8129 12.7108 11.8129C12.0807 11.8129 11.1087 12.2295 11.548 13.7373C11.9783 15.2138 13.1659 16.707 13.0693 17.5462Z" fill="white"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.7 KiB |
BIN
public/svgs/coolify.png
Normal file
|
After Width: | Height: | Size: 4.1 KiB |
BIN
public/svgs/cryptgeon.png
Normal file
|
After Width: | Height: | Size: 76 KiB |
10
public/svgs/dozzle.svg
Normal file
@@ -0,0 +1,10 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="256px" height="256px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:1" fill="#222222" d="M -0.5,-0.5 C 84.8333,-0.5 170.167,-0.5 255.5,-0.5C 255.5,84.8333 255.5,170.167 255.5,255.5C 170.167,255.5 84.8333,255.5 -0.5,255.5C -0.5,170.167 -0.5,84.8333 -0.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fbda56" d="M 161.5,179.5 C 160.957,179.56 160.624,179.893 160.5,180.5C 184.157,181.5 207.824,181.833 231.5,181.5C 231.5,186.833 231.5,192.167 231.5,197.5C 199.167,197.5 166.833,197.5 134.5,197.5C 134.813,194.753 134.48,192.086 133.5,189.5C 132.893,189.624 132.56,189.957 132.5,190.5C 115.506,204.774 95.8393,210.94 73.5,209C 58.1984,207.118 42.8651,205.618 27.5,204.5C 32.8364,149.128 38.5031,93.795 44.5,38.5C 59.7916,40.3257 75.1249,41.8257 90.5,43C 113.794,44.8067 132.127,55.14 145.5,74C 173.165,74.5 200.831,74.6666 228.5,74.5C 228.91,80.6208 228.41,86.6208 227,92.5C 205.158,121.53 183.324,150.53 161.5,179.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#222222" d="M 64.5,58.5 C 74.4468,59.9949 84.4468,61.1616 94.5,62C 117.983,67.1515 131.483,81.6515 135,105.5C 135.624,124.968 132.958,143.968 127,162.5C 119.558,178.614 107.058,187.781 89.5,190C 76.8083,190.293 64.1416,189.793 51.5,188.5C 56.0225,145.186 60.3558,101.852 64.5,58.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#252422" d="M 153.5,93.5 C 169.328,92.3386 185.328,92.1719 201.5,93C 185,114.833 168.5,136.667 152,158.5C 155.973,140.11 157.307,121.443 156,102.5C 155.34,99.322 154.507,96.322 153.5,93.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#6d6133" d="M 161.5,179.5 C 185.167,180.167 208.833,180.833 232.5,181.5C 232.167,181.5 231.833,181.5 231.5,181.5C 207.824,181.833 184.157,181.5 160.5,180.5C 160.624,179.893 160.957,179.56 161.5,179.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#d6ba4d" d="M 231.5,181.5 C 231.833,181.5 232.167,181.5 232.5,181.5C 232.5,187.167 232.5,192.833 232.5,198.5C 199.5,198.5 166.5,198.5 133.5,198.5C 133.806,195.615 133.473,192.948 132.5,190.5C 132.56,189.957 132.893,189.624 133.5,189.5C 134.48,192.086 134.813,194.753 134.5,197.5C 166.833,197.5 199.167,197.5 231.5,197.5C 231.5,192.167 231.5,186.833 231.5,181.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.4 KiB |
BIN
public/svgs/easyappointments.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
public/svgs/flowise.png
Normal file
|
After Width: | Height: | Size: 7.1 KiB |
BIN
public/svgs/freshrss.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
BIN
public/svgs/getoutline.jpeg
Normal file
|
After Width: | Height: | Size: 5.5 KiB |
11
public/svgs/homarr.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="484px" height="329px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.947" fill="#f95251" d="M 157.5,-0.5 C 158.833,-0.5 160.167,-0.5 161.5,-0.5C 200.102,3.59921 222.268,24.9325 228,63.5C 228.667,88.5 228.667,113.5 228,138.5C 222.962,132.265 216.629,130.265 209,132.5C 208.667,109.167 208.333,85.8333 208,62.5C 202.332,36.3319 186.165,21.9986 159.5,19.5C 141.783,20.273 127.949,27.9397 118,42.5C 112.924,38.3791 107.757,34.3791 102.5,30.5C 115.97,11.5969 134.303,1.26361 157.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:0.947" fill="#f95251" d="M 321.5,-0.5 C 322.833,-0.5 324.167,-0.5 325.5,-0.5C 348.697,1.26361 367.03,11.5969 380.5,30.5C 375.243,34.3791 370.076,38.3791 365,42.5C 349.005,21.3908 328.505,15.2242 303.5,24C 287.107,31.7273 277.607,44.5606 275,62.5C 274.667,85.8333 274.333,109.167 274,132.5C 266.371,130.265 260.038,132.265 255,138.5C 254.333,113.5 254.333,88.5 255,63.5C 260.732,24.9325 282.898,3.59921 321.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:0.984" fill="#f95251" d="M -0.5,139.5 C -0.5,137.167 -0.5,134.833 -0.5,132.5C 19.5,132.5 39.5,132.5 59.5,132.5C 51.7127,98.1844 43.3793,64.0177 34.5,30C 83.3876,36.5512 118.554,62.0512 140,106.5C 159.513,155.397 153.846,201.064 123,243.5C 114.899,253.77 105.399,262.437 94.5,269.5C 90.7735,258.059 87.6068,246.392 85,234.5C 39.0428,218.384 10.5428,186.717 -0.5,139.5 Z"/></g>
|
||||
<g><path style="opacity:0.984" fill="#f95251" d="M 483.5,132.5 C 483.5,134.833 483.5,137.167 483.5,139.5C 472.457,186.717 443.957,218.384 398,234.5C 395.393,246.392 392.226,258.059 388.5,269.5C 351.514,243.037 332.514,206.871 331.5,161C 333.865,105.236 359.865,64.9024 409.5,40C 421.97,34.3953 434.97,31.0619 448.5,30C 439.621,64.0177 431.287,98.1844 423.5,132.5C 443.5,132.5 463.5,132.5 483.5,132.5 Z"/></g>
|
||||
<g><path style="opacity:0.95" fill="#f95251" d="M 211.5,170.5 C 225.127,170.958 231.627,177.958 231,191.5C 226.507,203.825 218.007,207.659 205.5,203C 197.535,196.871 195.369,189.037 199,179.5C 201.917,174.637 206.083,171.637 211.5,170.5 Z"/></g>
|
||||
<g><path style="opacity:0.949" fill="#f95251" d="M 265.5,170.5 C 280.848,170.68 287.348,178.347 285,193.5C 279.06,204.76 270.227,207.593 258.5,202C 249.176,192.625 249.176,183.292 258.5,174C 260.925,172.787 263.259,171.621 265.5,170.5 Z"/></g>
|
||||
<g><path style="opacity:0.987" fill="#f95251" d="M 388.5,328.5 C 386.5,328.5 384.5,328.5 382.5,328.5C 285.992,327.966 189.325,326.966 92.5,325.5C 120.96,261.579 170.294,227.913 240.5,224.5C 299.804,226.887 345.304,252.887 377,302.5C 381.676,310.846 385.509,319.513 388.5,328.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.8 KiB |
11
public/svgs/homebox.svg
Normal file
@@ -0,0 +1,11 @@
|
||||
<svg viewBox="0 0 10817 9730" xmlns="http://www.w3.org/2000/svg" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:5.42683">
|
||||
<path d="M9310.16 2560.9c245.302 249.894 419.711 539.916 565.373 845.231 47.039 98.872 36.229 215.514-28.2 304.05-64.391 88.536-172.099 134.676-280.631 120.28 0 .053-.039.053-.039.053" style="fill:gray;stroke:#000;stroke-width:206.41px"/>
|
||||
<path d="M5401.56 487.044c-127.958 6.227-254.855 40.77-370.992 103.628-765.271 414.225-2397.45 1297.68-3193.03 1728.32-137.966 74.669-250.327 183.605-328.791 313.046l3963.09 2122.43s-249.048 416.428-470.593 786.926c-189.24 316.445-592.833 429.831-919.198 258.219l-2699.36-1419.32v2215.59c0 226.273 128.751 435.33 337.755 548.466 764.649 413.885 2620.97 1418.66 3385.59 1832.51 209.018 113.137 466.496 113.137 675.514 0 764.623-413.857 2620.94-1418.63 3385.59-1832.51 208.989-113.136 337.743-322.193 337.743-548.466v-3513.48c0-318.684-174.59-611.722-454.853-763.409-795.543-430.632-2427.75-1314.09-3193.02-1728.32-141.693-76.684-299.364-111.227-455.442-103.628" style="fill:#dadada;stroke:#000;stroke-width:206.42px"/>
|
||||
<path d="M5471.83 4754.46V504.71c-127.958 6.226-325.127 23.1-441.264 85.958-765.271 414.225-2397.45 1297.68-3193.03 1728.32-137.966 74.669-250.327 183.605-328.791 313.046l3963.09 2122.43Z" style="fill:gray;stroke:#000;stroke-width:206.42px"/>
|
||||
<path d="m1459.34 2725.96-373.791 715.667c-177.166 339.292-46.417 758 292.375 936.167l4.75 2.5m0 0 2699.37 1419.29c326.374 171.625 729.916 58.25 919.165-258.208 221.542-370.5 470.583-786.917 470.583-786.917l-3963.04-2122.42-2.167 3.458-47.25 90.458" style="fill:#dadada;stroke:#000;stroke-width:206.42px"/>
|
||||
<path d="M5443.74 520.879v4149.79" style="fill:none;stroke:#000;stroke-width:153.5px"/>
|
||||
<path d="M8951.41 4102.72c0-41.65-22.221-80.136-58.291-100.961-36.069-20.825-80.51-20.825-116.58 0l-2439.92 1408.69c-36.07 20.825-58.29 59.311-58.29 100.961V7058c0 41.65 22.22 80.136 58.29 100.961 36.07 20.825 80.51 20.825 116.58 0l2439.92-1408.69c36.07-20.825 58.291-59.312 58.291-100.962v-1546.59Z" style="fill:#567f67"/>
|
||||
<path d="M8951.41 4102.72c0-41.65-22.221-80.136-58.291-100.961-36.069-20.825-80.51-20.825-116.58 0l-2439.92 1408.69c-36.07 20.825-58.29 59.311-58.29 100.961V7058c0 41.65 22.22 80.136 58.29 100.961 36.07 20.825 80.51 20.825 116.58 0l2439.92-1408.69c36.07-20.825 58.291-59.312 58.291-100.962v-1546.59ZM6463.98 5551.29v1387.06l2301.77-1328.92V4222.37L6463.98 5551.29Z"/>
|
||||
<path d="M5443.76 9041.74v-4278.4" style="fill:none;stroke:#000;stroke-width:206.44px;stroke-linejoin:miter"/>
|
||||
<path d="m5471.79 4773.86 3829.35-2188.22" style="fill:none;stroke:#000;stroke-width:206.43px;stroke-linejoin:miter"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.7 KiB |
66
public/svgs/immich.svg
Normal file
@@ -0,0 +1,66 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!-- Generator: Adobe Illustrator 28.3.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<svg version="1.1" id="Router_Medium_x5F_Black_00000037681990313894948460000012967653829507626171_"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 792 792"
|
||||
style="enable-background:new 0 0 792 792;" xml:space="preserve">
|
||||
<style type="text/css">
|
||||
.st0{fill:#ACCBFA;}
|
||||
.st1{fill:#FA2921;}
|
||||
.st2{fill:#ED79B5;}
|
||||
.st3{fill:#FFB400;}
|
||||
.st4{fill:#1E83F7;}
|
||||
.st5{fill:#18C249;}
|
||||
</style>
|
||||
<g>
|
||||
<path class="st0" d="M110.16,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
|
||||
C95.71,543.8,102.32,537.4,110.16,537.4z M97.98,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
|
||||
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
|
||||
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
|
||||
<path class="st0" d="M265.44,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
|
||||
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
|
||||
c-6.81,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.69-5.99-8.05-9.71-15.49-9.71
|
||||
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
|
||||
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.81,0,10.74,4.54,11.98,10.53
|
||||
c6.19-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.73-16.73,29.11-16.73
|
||||
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
|
||||
C271.43,685.04,265.44,679.26,265.44,671.82z"/>
|
||||
<path class="st0" d="M431.45,671.82c0-3.51,1.03-9.5,1.03-13.22v-35.72c0-12.6-6.61-20.85-17.96-20.85
|
||||
c-7.43,0-14.04,3.72-18.38,10.94c0.41,2.27,0.62,4.54,0.62,7.02v38.61c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.22,13.22
|
||||
c-6.82,0-12.8-5.78-12.8-13.22c0-3.51,1.03-9.5,1.03-13.22v-36.34c0-3.92-0.62-7.43-2.06-10.53c-2.68-5.99-8.05-9.71-15.49-9.71
|
||||
c-7.64,0-13.83,3.92-18.38,10.94v45.63c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.99,13.22-13.01,13.22c-7.23,0-13.01-5.78-13.01-13.22
|
||||
c0-3.51,0.83-9.5,0.83-13.22v-47.7c0-3.72-1.86-10.32-1.86-13.42c0-7.43,5.37-13.22,12.6-13.22c6.82,0,10.74,4.54,11.98,10.53
|
||||
c6.2-8.26,14.87-13.42,26.22-13.42c13.42,0,23.13,6.4,29.11,16.73c6.81-10.74,16.72-16.73,29.11-16.73
|
||||
c20.86,0,36.75,15.07,36.75,39.23v37.99c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.57,13.22-13.01,13.22
|
||||
C437.44,685.04,431.45,679.26,431.45,671.82z"/>
|
||||
<path class="st0" d="M491.33,537.4c7.85,0,14.25,6.4,14.25,14.04c0,7.85-6.4,14.04-14.25,14.04s-14.45-6.19-14.45-14.04
|
||||
C476.87,543.8,483.48,537.4,491.33,537.4z M479.15,610.7c0-3.72-0.83-9.71-0.83-13.22c0-7.43,5.78-13.22,13.01-13.22
|
||||
s13.01,5.78,13.01,13.22c0,3.51-1.03,9.5-1.03,13.22v47.9c0,3.72,1.03,9.71,1.03,13.22c0,7.43-5.78,13.22-13.01,13.22
|
||||
s-13.01-5.78-13.01-13.22c0-3.51,0.83-9.5,0.83-13.22V610.7z"/>
|
||||
<path class="st0" d="M522.09,634.04c0-29.11,18.17-52.65,48.32-52.65c15.9,0,30.56,7.23,37.17,17.97c2.48,3.92,2.89,6.19,2.89,8.05
|
||||
c0,6.4-4.96,11.77-12.18,11.77c-4.75,0-9.08-2.68-10.94-7.43c-2.89-6.4-8.47-10.12-16.93-10.12c-15.9,0-24.78,14.25-24.78,32.21
|
||||
c0,18.17,9.29,32.21,25.4,32.21c8.67,0,14.87-3.1,17.76-9.5c2.06-4.34,5.99-8.05,11.36-8.05c7.43,0,11.98,5.16,11.98,11.56
|
||||
c0,3.1-1.24,6.81-3.92,10.32c-6.82,9.09-19.62,16.31-37.17,16.31C540.06,686.69,522.09,663.56,522.09,634.04z"/>
|
||||
<path class="st0" d="M690.17,671.82c0-3.51,0.83-9.5,0.83-13.22v-35.3c0-12.6-7.02-21.27-19-21.27c-8.26,0-15.28,3.92-19.82,10.32
|
||||
v46.25c0,3.72,0.83,9.71,0.83,13.22c0,7.43-5.78,13.22-13.01,13.22s-13.01-5.78-13.01-13.22c0-3.51,1.03-9.5,1.03-13.22v-99.94
|
||||
c0-3.72-1.03-9.71-1.03-13.22c0-7.43,5.99-13.22,13.01-13.22c7.23,0,13.01,5.78,13.01,13.22c0,3.51-0.83,9.5-0.83,13.22v33.66
|
||||
c6.2-6.81,15.07-10.94,26.43-10.94c21.27,0,36.55,15.9,36.55,38.61v38.61c0,3.72,1.03,9.71,1.03,13.22
|
||||
c0,7.43-5.99,13.22-13.01,13.22C695.95,685.04,690.17,679.26,690.17,671.82z"/>
|
||||
</g>
|
||||
<g>
|
||||
<path class="st1" d="M376.76,216.42c28.32,25.07,51.15,51.95,65.83,77.27c25.23-45.12,42.08-98.73,42.3-132.88
|
||||
c0-0.24,0-0.46,0-0.66c0-50.53-50.41-70.2-93.82-70.2s-93.82,19.66-93.82,70.2c0,0.69,0,1.62,0,2.73
|
||||
C321.44,173.62,350.14,192.84,376.76,216.42z"/>
|
||||
<path class="st2" d="M222.27,354.21c17.7-19.69,44.85-41.04,75.5-59.08c32.6-19.19,65.21-32.59,93.83-38.73
|
||||
c-35.11-37.94-80.89-70.53-113.31-81.29c-0.23-0.07-0.44-0.14-0.63-0.21c-48.06-15.61-82.34,26.25-95.75,67.54
|
||||
c-13.42,41.29-10.29,95.31,37.77,110.92C220.33,353.58,221.21,353.86,222.27,354.21z"/>
|
||||
<path class="st3" d="M600.73,241.74c-13.42-41.29-47.69-83.15-95.75-67.54c-0.66,0.21-1.54,0.5-2.6,0.84
|
||||
c-2.75,26.34-12.16,59.57-26.36,92.17c-15.09,34.68-33.6,64.69-53.14,86.48c50.7,10.05,106.9,9.52,139.45-0.83
|
||||
c0.23-0.07,0.44-0.14,0.63-0.21C611.02,337.05,614.15,283.03,600.73,241.74z"/>
|
||||
<path class="st4" d="M348.22,394.58c-8.17-36.93-10.84-72.09-7.84-101.2c-46.93,21.67-92.08,55.14-112.33,82.64
|
||||
c-0.14,0.19-0.27,0.37-0.39,0.54c-29.7,40.88-0.48,86.42,34.64,111.94s87.46,39.24,117.16-1.64c0.41-0.56,0.95-1.31,1.6-2.21
|
||||
C367.81,461.72,355.9,429.3,348.22,394.58z"/>
|
||||
<path class="st5" d="M554.19,373.91c-25.9,5.53-60.41,6.84-95.81,3.42c-37.65-3.64-71.91-11.96-98.67-23.82
|
||||
c6.11,51.33,23.99,104.61,43.89,132.37c0.14,0.19,0.27,0.37,0.39,0.54c29.7,40.88,82.04,27.16,117.16,1.64S585.5,417,555.8,376.12
|
||||
C555.39,375.56,554.85,374.81,554.19,373.91z"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.5 KiB |
BIN
public/svgs/infisical.png
Normal file
|
After Width: | Height: | Size: 4.0 KiB |
6
public/svgs/it-tools.svg
Normal file
@@ -0,0 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="512px" height="512px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.995" fill="#18a057" d="M 230.5,-0.5 C 247.5,-0.5 264.5,-0.5 281.5,-0.5C 290.12,3.28885 296.287,9.62218 300,18.5C 299.871,28.5889 300.704,38.4222 302.5,48C 326.717,53.6219 349.217,63.1219 370,76.5C 376.469,71.0323 382.636,65.199 388.5,59C 398.925,52.0844 409.591,51.7511 420.5,58C 432,68.1667 442.833,79 453,90.5C 459,100.5 459,110.5 453,120.5C 447.017,127.317 440.851,133.984 434.5,140.5C 447.998,161.821 457.498,184.821 463,209.5C 474.144,210.648 485.31,211.815 496.5,213C 503.496,216.822 508.496,222.322 511.5,229.5C 511.5,246.5 511.5,263.5 511.5,280.5C 508.841,288.664 503.508,294.497 495.5,298C 484.573,299.444 473.573,300.277 462.5,300.5C 457.369,325.4 448.036,348.566 434.5,370C 441.693,377.526 448.526,385.359 455,393.5C 458.667,402.825 458.001,411.825 453,420.5C 443.167,430.333 433.333,440.167 423.5,450C 414.895,457.565 405.229,459.232 394.5,455C 386.322,448.153 378.155,441.32 370,434.5C 348.501,447.828 325.334,457.161 300.5,462.5C 301.01,473.958 300.177,485.291 298,496.5C 294.006,504.342 287.839,509.342 279.5,511.5C 263.167,511.5 246.833,511.5 230.5,511.5C 222.336,508.841 216.503,503.508 213,495.5C 212,484.833 211,474.167 210,463.5C 198.505,459.749 187.005,455.915 175.5,452C 173.842,451.275 173.342,450.108 174,448.5C 192.195,429.971 210.695,411.805 229.5,394C 293.836,401.915 343.336,378.748 378,324.5C 408.025,263.569 400.691,207.569 356,156.5C 315.267,118.147 267.767,106.314 213.5,121C 164.374,138.458 132.874,172.291 119,222.5C 117.485,228.075 116.485,233.742 116,239.5C 115.261,253.906 115.594,268.239 117,282.5C 98.8333,300.667 80.6667,318.833 62.5,337C 61.552,337.483 60.552,337.649 59.5,337.5C 54.8294,325.486 51.1627,313.153 48.5,300.5C 37.4331,300.188 26.4331,299.355 15.5,298C 7.189,293.843 1.85567,287.343 -0.5,278.5C -0.5,262.833 -0.5,247.167 -0.5,231.5C 2.22646,223.578 7.22646,217.411 14.5,213C 25.7307,211.098 37.0641,210.265 48.5,210.5C 53.718,185.511 63.0513,162.178 76.5,140.5C 71.2189,133.716 65.3855,127.383 59,121.5C 51.8558,110.353 52.1892,99.353 60,88.5C 69.8333,78.6667 79.6667,68.8333 89.5,59C 98.3002,53.1199 107.633,52.1199 117.5,56C 125.629,62.4604 133.463,69.2938 141,76.5C 162.028,62.9274 184.861,53.4274 209.5,48C 210.93,37.2282 212.097,26.3949 213,15.5C 216.503,7.49214 222.336,2.15881 230.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:0.99" fill="#1d1d1d" d="M 52.5,511.5 C 46.5,511.5 40.5,511.5 34.5,511.5C 16.5,506.167 4.83333,494.5 -0.5,476.5C -0.5,470.167 -0.5,463.833 -0.5,457.5C 1.14258,451.876 3.64258,446.542 7,441.5C 55.9723,391.528 105.306,341.861 155,292.5C 141.187,245.876 152.02,206.042 187.5,173C 216.657,150.235 248.991,143.902 284.5,154C 289.202,158.922 290.702,164.755 289,171.5C 275,186.167 261,200.833 247,215.5C 234.564,236.922 238.73,254.422 259.5,268C 272.178,272.999 284.178,271.666 295.5,264C 309.596,248.899 324.596,234.899 340.5,222C 353.68,220.169 360.513,226.003 361,239.5C 365.554,290.573 345.387,328.073 300.5,352C 273.591,363.046 246.258,364.379 218.5,356C 169.472,405.361 120.139,454.361 70.5,503C 64.8398,506.712 58.8398,509.545 52.5,511.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.4 KiB |
67
public/svgs/kimai.svg
Normal file
@@ -0,0 +1,67 @@
|
||||
<svg cursor="default" enable-background="new" height="512" viewBox="0 0 440 440" width="512"
|
||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<radialGradient id="a" cx="611" cy="41.266644"
|
||||
gradientTransform="matrix(1.1673343 0 0 1.4196623 -102.24121 -19.722475)"
|
||||
gradientUnits="userSpaceOnUse" r="160.5">
|
||||
<stop offset="0" stop-color="#01fd00" />
|
||||
<stop offset="1" stop-color="#009d39" />
|
||||
</radialGradient>
|
||||
<radialGradient id="b" cx="873.78265" cy="-16.37981"
|
||||
gradientTransform="matrix(1.9295131 -1.1140049 1.1550268 2.0005649 -1087.6858 1104.8947)"
|
||||
gradientUnits="userSpaceOnUse" r="55.747124">
|
||||
<stop offset="0" stop-color="#f9f9f9" />
|
||||
<stop offset="1" stop-color="#fff" />
|
||||
</radialGradient>
|
||||
<linearGradient id="c" gradientUnits="userSpaceOnUse" x1="611.14288" x2="610.57141"
|
||||
y1="234.57143" y2="-110.91601">
|
||||
<stop offset="0" stop-color="#f2f2f2" />
|
||||
<stop offset="1" stop-color="#f2f2f2" />
|
||||
</linearGradient>
|
||||
<g transform="translate(-390.56693 181.56689)">
|
||||
<g>
|
||||
<path d="m391.020508-182.838852h439.95895v439.95895h-439.95895z" fill="#fff"
|
||||
stroke="#58dd58" stroke-linejoin="round" stroke-width=".040996" visibility="hidden" />
|
||||
<circle cx="611" cy="38" fill="url(#c)" r="187.776825" />
|
||||
<circle cx="611" cy="38" fill="url(#a)" r="166.285645" stroke="#fff"
|
||||
stroke-linejoin="round" stroke-width="3" />
|
||||
<path d="m571.156433 108.308197 110-63.999998-110-64z" fill="url(#b)"
|
||||
fill-rule="evenodd" />
|
||||
</g>
|
||||
<g fill="#c7efc4" fill-rule="evenodd">
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.83616052 -.5484848 .5484848 -.83616052 0 0)" width="14"
|
||||
x="-542.46875" y="419.410309" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.45720822 -.88935968 .88935968 -.45720822 0 0)" width="14"
|
||||
x="-320.158203" y="642.978027" />
|
||||
<rect height="41" opacity=".5" ry="9" transform="rotate(-90)" width="18" x="-48.536366"
|
||||
y="718.754395" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(.47159375 -.88181593 .88181593 .47159375 0 0)" width="14"
|
||||
x="244.405457" y="673.798523" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.8503618 .52619845 -.52619845 -.8503618 0 0)" width="14"
|
||||
x="-505.884949" y="-503.867859" />
|
||||
<rect height="41" opacity=".5" ry="9" transform="scale(-1)" width="18" x="-620.297424"
|
||||
y="-187.942719" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.84033379 -.54206929 .54206929 -.84033379 0 0)" width="14"
|
||||
x="-539.16571" y="148.581909" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.45720822 -.88935968 .88935968 -.45720822 0 0)" width="14"
|
||||
x="-319.728088" y="374.804901" />
|
||||
<rect height="41" opacity=".5" ry="9" transform="rotate(-90)" width="18" x="-48.536366"
|
||||
y="460.964569" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(.47159375 -.88181593 .88181593 .47159375 0 0)" width="14"
|
||||
x="250.841736" y="406.195648" />
|
||||
<rect height="32" opacity=".5" ry="7"
|
||||
transform="matrix(-.849305 .52790248 -.52790248 -.849305 0 0)" width="14"
|
||||
x="-505.957611" y="-236.959518" />
|
||||
<g transform="scale(-1)">
|
||||
<rect height="41" opacity=".5" ry="9" width="18" x="-633.02533" y="69.120789" />
|
||||
<rect height="41" opacity=".5" ry="9" width="18" x="-606.761353" y="69.120789" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.8 KiB |
BIN
public/svgs/labelstudio.png
Normal file
|
After Width: | Height: | Size: 1.8 KiB |
BIN
public/svgs/langfuse.png
Normal file
|
After Width: | Height: | Size: 9.6 KiB |
1
public/svgs/libreoffice.svg
Normal file
|
After Width: | Height: | Size: 10 KiB |
1
public/svgs/litellm.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 36 36"><path fill="#939598" d="M0 34h36v2H0z"/><path fill="#D1D3D4" d="M3 35h33V6H21c-4 0-5 2-5 2l-4 6S0 19 0 24c0 4 6 6 6 6z"/><path fill="#231F20" d="m14 35 2-3h20v3z"/><path fill="#3B88C3" d="M0 23.999c0 4 6 6 6 6V17.125C3 19 0 21.499 0 23.999M6 30v-.001z"/><path fill="#269" d="m6 30-3 5h33v-5z"/><path fill="#3B88C3" d="m20 30 4-6h12v6z"/><path fill="#55ACEE" d="M26 8H16l-4 6h-.001 10.843c.477 0 1.108-.448 1.412-1l2.197-4c.303-.552.102-1-.451-1"/><path fill="#3B88C3" d="m25.902 10 .549-1c.303-.552.102-1-.451-1H16l-1.333 2z"/></svg>
|
||||
|
After Width: | Height: | Size: 593 B |
8
public/svgs/nitropage.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg">
|
||||
<rect transform="matrix(1 0 -.16885 .98564 0 0)" x="2.6887" y="1.2563" width="14.457" height="14.667" fill="#581c87" style="paint-order:stroke fill markers"/>
|
||||
<text x="0.74027044" y="12.170821" display="none" fill="#ffffff" font-family="'Liberation Sans'" font-size="10.583px" font-weight="bold" letter-spacing="-.66146px" stroke-width="4.2333" word-spacing="0px" xml:space="preserve"><tspan x="0.74027044" y="12.170821" fill="#ffffff" font-family="'Jost*'" font-size="10.583px" font-style="italic" font-weight="900" stroke-width="4.2333" style="paint-order:stroke fill markers">NP</tspan></text>
|
||||
<g fill="#fff" stroke-width="4.2333" aria-label="NP">
|
||||
<path d="m7.1008 4.7625-0.59266 3.3655-4.0322-3.7147-1.3229 7.7576h2.1907l0.58208-3.3655 4.0428 3.7147 1.3229-7.7576z" style="paint-order:stroke fill markers"/>
|
||||
<path d="m10.027 4.7625-1.27 7.4083h2.2966l0.39158-2.3283h0.62442c1.9156-0.021167 3.2385-0.89958 3.3867-2.54 0.14817-1.6192-0.79375-2.5188-2.6564-2.54zm2.5717 1.8415c0.48683 0.010583 0.75141 0.26458 0.67733 0.68791-0.08467 0.45508-0.508 0.6985-1.016 0.6985h-0.49742l0.24342-1.3864z" style="paint-order:stroke fill markers"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.2 KiB |
1
public/svgs/ntfy.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="50mm" height="50mm" viewBox="0 0 50 50" xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg"><defs><linearGradient id="a"><stop style="stop-color:#348878;stop-opacity:1" offset="0"/><stop style="stop-color:#56bda8;stop-opacity:1" offset="1"/></linearGradient><linearGradient xlink:href="#a" id="b" x1="160.722" y1="128.533" x2="168.412" y2="134.326" gradientUnits="userSpaceOnUse" gradientTransform="translate(-845.726 -630.598) scale(5.59448)"/></defs><g style="display:inline"><path style="color:#000;fill:url(#b);stroke:none;stroke-width:3.72347;-inkscape-stroke:none" d="M94.237 89.912H59.499c-2.388 0-4.342 1.844-4.342 4.098l.033 27.754-.648 3.738 9.297-2.806h30.396c2.388 0 4.342-1.845 4.342-4.099V94.01c0-2.254-1.954-4.098-4.342-4.098z" transform="translate(-51.147 -81.516)"/><path style="color:#000;fill:#fff;stroke:none;stroke-width:.762343;-inkscape-stroke:none" d="M58.849 86.79c-3.62 0-6.72 2.848-6.72 6.47v.002l.035 30.273-.91 6.708 12.362-3.284h30.729c3.62 0 6.72-2.852 6.72-6.473V93.26c0-3.62-3.099-6.469-6.717-6.469h-.003zm0 4.566h35.499c1.272 0 2.151.927 2.151 1.903v27.227c0 .977-.88 1.924-2.154 1.903h-31.4l-6.28 1.898.065-.37-.035-30.658c0-.977.88-1.903 2.154-1.903z" transform="translate(-51.147 -81.516)"/><g style="font-size:8.48274px;font-family:sans-serif;letter-spacing:0;word-spacing:0;fill:#000;stroke:none;stroke-width:.525121"><path style="color:#000;-inkscape-font-specification:'JetBrains Mono, Bold';fill:#fff;stroke:none;-inkscape-stroke:none" d="M62.57 116.77v-1.312l3.28-1.459q.159-.068.306-.102.158-.045.283-.068l.271-.022v-.09q-.136-.012-.271-.046-.125-.023-.283-.057-.147-.045-.306-.113l-3.28-1.459v-1.323l5.068 2.319v1.413z" transform="matrix(2.1689 0 0 2.57844 -124.28 -268.742)"/><path style="color:#000;-inkscape-font-specification:'JetBrains Mono, Bold';fill:#fff;stroke:none;-inkscape-stroke:none" d="M62.309 110.31v1.903l3.437 1.53.022.007-.022.008-3.437 1.53v1.892l.37-.17 5.221-2.39v-1.75zm.525.817 4.541 2.08v1.076l-4.541 2.078v-.732l3.12-1.389.003-.002a1.56 1.56 0 0 1 .258-.086h.006l.008-.002c.094-.027.176-.047.246-.06l.498-.041v-.574l-.24-.02a1.411 1.411 0 0 1-.231-.04l-.008-.001-.008-.002a9.077 9.077 0 0 1-.263-.053 2.781 2.781 0 0 1-.266-.097l-.004-.002-3.119-1.39z" transform="matrix(2.1689 0 0 2.57844 -124.28 -268.742)"/></g><g style="font-size:8.48274px;font-family:sans-serif;letter-spacing:0;word-spacing:0;fill:#000;stroke:none;stroke-width:.525121"><path style="color:#000;-inkscape-font-specification:'JetBrains Mono, Bold';fill:#fff;stroke:none;-inkscape-stroke:none" d="M69.171 117.754h5.43v1.278h-5.43Z" transform="matrix(2.16247 0 0 2.48294 -122.76 -261.211)"/><path style="color:#000;-inkscape-font-specification:'JetBrains Mono, Bold';fill:#fff;stroke:none;-inkscape-stroke:none" d="M68.908 117.492v1.802h5.955v-1.802zm.526.524h4.904v.754h-4.904z" transform="matrix(2.16247 0 0 2.48294 -122.76 -261.211)"/></g></g></svg>
|
||||
|
After Width: | Height: | Size: 2.9 KiB |
14
public/svgs/ollama.svg
Normal file
@@ -0,0 +1,14 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" width="4096px" height="4096px" style="shape-rendering:geometricPrecision; text-rendering:geometricPrecision; image-rendering:optimizeQuality; fill-rule:evenodd; clip-rule:evenodd" xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||
<g><path style="opacity:0.999" fill="#fefefe" d="M 1984.5,-0.5 C 2026.5,-0.5 2068.5,-0.5 2110.5,-0.5C 2537.4,15.5079 2922.4,149.008 3265.5,400C 3560.04,620.244 3781.2,898.744 3929,1235.5C 4031.4,1474.76 4086.9,1724.43 4095.5,1984.5C 4095.5,2026.5 4095.5,2068.5 4095.5,2110.5C 4079.61,2533.7 3948.11,2916.03 3701,3257.5C 3593.06,3404.12 3467.89,3534.62 3325.5,3649C 3314.27,3657.74 3302.94,3666.24 3291.5,3674.5C 3294.9,3533.77 3270.4,3398.11 3218,3267.5C 3213.27,3256.38 3208.27,3245.38 3203,3234.5C 3199.86,3228.11 3198.2,3221.44 3198,3214.5C 3233.37,3166.09 3260.04,3113.09 3278,3055.5C 3315.81,2931.9 3329.15,2805.57 3318,2676.5C 3312.19,2588.11 3293.86,2502.44 3263,2419.5C 3248.74,2385.4 3232.58,2352.23 3214.5,2320C 3228.7,2298.44 3242.54,2276.6 3256,2254.5C 3306.49,2163.1 3334.16,2065.1 3339,1960.5C 3347.09,1770.12 3293.75,1599.45 3179,1448.5C 3152.35,1414.84 3123.18,1383.34 3091.5,1354C 3073.96,1338.79 3056.13,1323.96 3038,1309.5C 3037.33,1303.83 3037.33,1298.17 3038,1292.5C 3071.33,1118.01 3070.66,943.681 3036,769.5C 3022.49,704.637 3000.82,642.637 2971,583.5C 2948.49,539.65 2918.65,501.484 2881.5,469C 2825.8,423.008 2762.8,409.008 2692.5,427C 2651.4,440.793 2615.9,463.293 2586,494.5C 2546.73,537.991 2515.73,586.991 2493,641.5C 2466.37,705.666 2447.04,771.999 2435,840.5C 2428.17,878.941 2423.17,917.608 2420,956.5C 2419.88,958.573 2418.88,959.907 2417,960.5C 2399.1,950.801 2381.27,940.967 2363.5,931C 2153.62,824.176 1943.62,823.842 1733.5,930C 1715.06,940.301 1696.56,950.467 1678,960.5C 1676.35,960.18 1675.35,959.18 1675,957.5C 1667.31,849.014 1643.31,744.347 1603,643.5C 1581.9,592.477 1553.57,546.144 1518,504.5C 1488.61,471.396 1453.44,446.562 1412.5,430C 1388.07,422.647 1363.07,419.147 1337.5,419.5C 1322.44,419.049 1307.78,421.215 1293.5,426C 1244.84,441.668 1204.68,469.502 1173,509.5C 1141.62,549.221 1116.62,592.887 1098,640.5C 1066.87,721.373 1047.53,805.04 1040,891.5C 1026.67,1023.93 1032.01,1155.6 1056,1286.5C 1057.33,1293.8 1058,1301.14 1058,1308.5C 887.035,1442.34 787.369,1617.67 759,1834.5C 747.069,1944.53 758.735,2051.86 794,2156.5C 807.02,2192.21 823.02,2226.54 842,2259.5C 854.715,2279.77 867.548,2299.93 880.5,2320C 836.781,2396.64 806.948,2478.47 791,2565.5C 783.711,2603.19 779.045,2641.19 777,2679.5C 776.333,2731.83 776.333,2784.17 777,2836.5C 782.248,2934.22 803.581,3028.22 841,3118.5C 856.12,3152.76 874.787,3184.76 897,3214.5C 897.611,3218.68 896.944,3222.68 895,3226.5C 830.268,3368.77 799.768,3518.1 803.5,3674.5C 556.783,3485.22 362.616,3252.55 221,2976.5C 83.5748,2704.13 9.74149,2415.47 -0.5,2110.5C -0.5,2068.5 -0.5,2026.5 -0.5,1984.5C 15.5079,1557.6 149.008,1172.6 400,829.5C 620.244,534.963 898.744,313.796 1235.5,166C 1474.76,63.6006 1724.43,8.10056 1984.5,-0.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#000000" d="M 3291.5,3674.5 C 3219.32,3730.61 3143.32,3781.28 3063.5,3826.5C 3086.34,3778.48 3098.17,3727.82 3099,3674.5C 3102.6,3547.82 3078.26,3426.82 3026,3311.5C 3012.26,3283.68 2998.26,3256.01 2984,3228.5C 2983.33,3211.83 2983.33,3195.17 2984,3178.5C 2986.77,3167.3 2991.43,3156.97 2998,3147.5C 3011.32,3131.52 3025.32,3116.18 3040,3101.5C 3055.7,3082.12 3068.37,3060.78 3078,3037.5C 3102.95,2974.82 3118.62,2909.82 3125,2842.5C 3135.67,2731.91 3124.67,2623.58 3092,2517.5C 3079.64,2478.12 3061.97,2441.45 3039,2407.5C 3031.38,2397.54 3023.38,2387.88 3015,2378.5C 2984.39,2332.41 2986.72,2288.07 3022,2245.5C 3066.42,2200.01 3099.09,2147.01 3120,2086.5C 3154.85,1979.03 3156.52,1871.03 3125,1762.5C 3089.97,1643.55 3024.14,1545.72 2927.5,1469C 2862.72,1419.8 2789.72,1390.13 2708.5,1380C 2686.83,1378.03 2665.16,1378.03 2643.5,1380C 2623.56,1383.05 2603.56,1385.55 2583.5,1387.5C 2544.15,1385.92 2515.31,1367.92 2497,1333.5C 2488.47,1313.24 2478.81,1293.57 2468,1274.5C 2451.43,1251.93 2434.1,1229.93 2416,1208.5C 2343.7,1135.91 2257.86,1085.74 2158.5,1058C 2140.99,1053.57 2123.33,1049.9 2105.5,1047C 2033.1,1038.03 1962.77,1046.03 1894.5,1071C 1825.56,1096.11 1763.56,1132.45 1708.5,1180C 1668.06,1216.42 1635.23,1258.58 1610,1306.5C 1603.43,1325.64 1593.77,1342.98 1581,1358.5C 1561.48,1377.23 1538.15,1386.57 1511,1386.5C 1493.39,1385.7 1475.89,1383.87 1458.5,1381C 1393.37,1374.82 1330.71,1384.49 1270.5,1410C 1181.85,1448.98 1109.68,1508.15 1054,1587.5C 957.404,1727.48 927.071,1880.82 963,2047.5C 983.321,2126.03 1021.65,2194.03 1078,2251.5C 1102.43,2283.23 1107.43,2317.89 1093,2355.5C 1089.44,2363.62 1085.11,2371.29 1080,2378.5C 1052.63,2408.91 1031.3,2443.25 1016,2481.5C 996.087,2532.48 982.42,2585.15 975,2639.5C 958.127,2755.12 965.46,2869.12 997,2981.5C 1005.9,3012.21 1017.9,3041.54 1033,3069.5C 1039.84,3080.51 1047.17,3091.18 1055,3101.5C 1069.68,3116.18 1083.68,3131.52 1097,3147.5C 1103.4,3157.04 1108.07,3167.37 1111,3178.5C 1111.67,3195.17 1111.67,3211.83 1111,3228.5C 1085.66,3274.84 1063.33,3322.51 1044,3371.5C 1005.13,3479.61 989.794,3590.94 998,3705.5C 1001.44,3737.36 1008.44,3768.36 1019,3798.5C 1022.7,3808.23 1027.2,3817.56 1032.5,3826.5C 952.208,3781.54 875.874,3730.87 803.5,3674.5C 799.768,3518.1 830.268,3368.77 895,3226.5C 896.944,3222.68 897.611,3218.68 897,3214.5C 874.787,3184.76 856.12,3152.76 841,3118.5C 803.581,3028.22 782.248,2934.22 777,2836.5C 776.333,2784.17 776.333,2731.83 777,2679.5C 779.045,2641.19 783.711,2603.19 791,2565.5C 806.948,2478.47 836.781,2396.64 880.5,2320C 867.548,2299.93 854.715,2279.77 842,2259.5C 823.02,2226.54 807.02,2192.21 794,2156.5C 758.735,2051.86 747.069,1944.53 759,1834.5C 787.369,1617.67 887.035,1442.34 1058,1308.5C 1058,1301.14 1057.33,1293.8 1056,1286.5C 1032.01,1155.6 1026.67,1023.93 1040,891.5C 1047.53,805.04 1066.87,721.373 1098,640.5C 1116.62,592.887 1141.62,549.221 1173,509.5C 1204.68,469.502 1244.84,441.668 1293.5,426C 1307.78,421.215 1322.44,419.049 1337.5,419.5C 1363.07,419.147 1388.07,422.647 1412.5,430C 1453.44,446.562 1488.61,471.396 1518,504.5C 1553.57,546.144 1581.9,592.477 1603,643.5C 1643.31,744.347 1667.31,849.014 1675,957.5C 1675.35,959.18 1676.35,960.18 1678,960.5C 1696.56,950.467 1715.06,940.301 1733.5,930C 1943.62,823.842 2153.62,824.176 2363.5,931C 2381.27,940.967 2399.1,950.801 2417,960.5C 2418.88,959.907 2419.88,958.573 2420,956.5C 2423.17,917.608 2428.17,878.941 2435,840.5C 2447.04,771.999 2466.37,705.666 2493,641.5C 2515.73,586.991 2546.73,537.991 2586,494.5C 2615.9,463.293 2651.4,440.793 2692.5,427C 2762.8,409.008 2825.8,423.008 2881.5,469C 2918.65,501.484 2948.49,539.65 2971,583.5C 3000.82,642.637 3022.49,704.637 3036,769.5C 3070.66,943.681 3071.33,1118.01 3038,1292.5C 3037.33,1298.17 3037.33,1303.83 3038,1309.5C 3056.13,1323.96 3073.96,1338.79 3091.5,1354C 3123.18,1383.34 3152.35,1414.84 3179,1448.5C 3293.75,1599.45 3347.09,1770.12 3339,1960.5C 3334.16,2065.1 3306.49,2163.1 3256,2254.5C 3242.54,2276.6 3228.7,2298.44 3214.5,2320C 3232.58,2352.23 3248.74,2385.4 3263,2419.5C 3293.86,2502.44 3312.19,2588.11 3318,2676.5C 3329.15,2805.57 3315.81,2931.9 3278,3055.5C 3260.04,3113.09 3233.37,3166.09 3198,3214.5C 3198.2,3221.44 3199.86,3228.11 3203,3234.5C 3208.27,3245.38 3213.27,3256.38 3218,3267.5C 3270.4,3398.11 3294.9,3533.77 3291.5,3674.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fefefe" d="M 1343.5,613.5 C 1345.86,613.337 1348.19,613.503 1350.5,614C 1363.25,622.08 1374.08,632.247 1383,644.5C 1406.08,678.657 1424.41,715.323 1438,754.5C 1469.67,849.867 1486.01,947.867 1487,1048.5C 1487.67,1077.83 1487.67,1107.17 1487,1136.5C 1475.83,1153 1464.67,1169.5 1453.5,1186C 1407.83,1184.32 1362.5,1187.32 1317.5,1195C 1293.64,1199.88 1269.98,1205.55 1246.5,1212C 1244.5,1212.67 1242.5,1212.67 1240.5,1212C 1237.69,1200.67 1235.52,1189.17 1234,1177.5C 1220.98,1067.87 1222.98,958.541 1240,849.5C 1250.18,786.973 1269.18,727.306 1297,670.5C 1306.8,651.693 1319.3,634.86 1334.5,620C 1337.57,617.812 1340.57,615.645 1343.5,613.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fefefe" d="M 2743.5,613.5 C 2746.98,613.184 2750.31,613.684 2753.5,615C 2767.13,624.964 2778.3,637.13 2787,651.5C 2807.31,685.784 2822.97,722.118 2834,760.5C 2858.32,848.257 2870.16,937.757 2869.5,1029C 2869.08,1081 2865.91,1132.83 2860,1184.5C 2858.99,1193.9 2857.16,1203.06 2854.5,1212C 2852.5,1212.67 2850.5,1212.67 2848.5,1212C 2813.95,1202.49 2778.95,1195.16 2743.5,1190C 2709.57,1187.05 2675.57,1185.71 2641.5,1186C 2630.33,1169.5 2619.17,1153 2608,1136.5C 2606.33,1076.74 2607.99,1017.07 2613,957.5C 2620.37,882.341 2637.04,809.341 2663,738.5C 2676.24,703.018 2693.9,670.018 2716,639.5C 2724.1,629.559 2733.27,620.893 2743.5,613.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fefefe" d="M 3063.5,3826.5 C 2768.17,3994.26 2450.5,4083.93 2110.5,4095.5C 2068.5,4095.5 2026.5,4095.5 1984.5,4095.5C 1663.69,4084.63 1361.69,4003.8 1078.5,3853C 1062.94,3844.39 1047.61,3835.56 1032.5,3826.5C 1027.2,3817.56 1022.7,3808.23 1019,3798.5C 1008.44,3768.36 1001.44,3737.36 998,3705.5C 989.794,3590.94 1005.13,3479.61 1044,3371.5C 1063.33,3322.51 1085.66,3274.84 1111,3228.5C 1111.67,3211.83 1111.67,3195.17 1111,3178.5C 1108.07,3167.37 1103.4,3157.04 1097,3147.5C 1083.68,3131.52 1069.68,3116.18 1055,3101.5C 1047.17,3091.18 1039.84,3080.51 1033,3069.5C 1017.9,3041.54 1005.9,3012.21 997,2981.5C 965.46,2869.12 958.127,2755.12 975,2639.5C 982.42,2585.15 996.087,2532.48 1016,2481.5C 1031.3,2443.25 1052.63,2408.91 1080,2378.5C 1085.11,2371.29 1089.44,2363.62 1093,2355.5C 1107.43,2317.89 1102.43,2283.23 1078,2251.5C 1021.65,2194.03 983.321,2126.03 963,2047.5C 927.071,1880.82 957.404,1727.48 1054,1587.5C 1109.68,1508.15 1181.85,1448.98 1270.5,1410C 1330.71,1384.49 1393.37,1374.82 1458.5,1381C 1475.89,1383.87 1493.39,1385.7 1511,1386.5C 1538.15,1386.57 1561.48,1377.23 1581,1358.5C 1593.77,1342.98 1603.43,1325.64 1610,1306.5C 1635.23,1258.58 1668.06,1216.42 1708.5,1180C 1763.56,1132.45 1825.56,1096.11 1894.5,1071C 1962.77,1046.03 2033.1,1038.03 2105.5,1047C 2123.33,1049.9 2140.99,1053.57 2158.5,1058C 2257.86,1085.74 2343.7,1135.91 2416,1208.5C 2434.1,1229.93 2451.43,1251.93 2468,1274.5C 2478.81,1293.57 2488.47,1313.24 2497,1333.5C 2515.31,1367.92 2544.15,1385.92 2583.5,1387.5C 2603.56,1385.55 2623.56,1383.05 2643.5,1380C 2665.16,1378.03 2686.83,1378.03 2708.5,1380C 2789.72,1390.13 2862.72,1419.8 2927.5,1469C 3024.14,1545.72 3089.97,1643.55 3125,1762.5C 3156.52,1871.03 3154.85,1979.03 3120,2086.5C 3099.09,2147.01 3066.42,2200.01 3022,2245.5C 2986.72,2288.07 2984.39,2332.41 3015,2378.5C 3023.38,2387.88 3031.38,2397.54 3039,2407.5C 3061.97,2441.45 3079.64,2478.12 3092,2517.5C 3124.67,2623.58 3135.67,2731.91 3125,2842.5C 3118.62,2909.82 3102.95,2974.82 3078,3037.5C 3068.37,3060.78 3055.7,3082.12 3040,3101.5C 3025.32,3116.18 3011.32,3131.52 2998,3147.5C 2991.43,3156.97 2986.77,3167.3 2984,3178.5C 2983.33,3195.17 2983.33,3211.83 2984,3228.5C 2998.26,3256.01 3012.26,3283.68 3026,3311.5C 3078.26,3426.82 3102.6,3547.82 3099,3674.5C 3098.17,3727.82 3086.34,3778.48 3063.5,3826.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#000000" d="M 2012.5,1851.5 C 2112.37,1846.89 2208.04,1864.39 2299.5,1904C 2385.62,1942.45 2455.79,2000.28 2510,2077.5C 2542.75,2125.73 2563.75,2178.73 2573,2236.5C 2586.91,2380.14 2536.41,2494.97 2421.5,2581C 2340.82,2637.34 2251.15,2668.01 2152.5,2673C 2079.17,2674.97 2005.83,2674.97 1932.5,2673C 1826.08,2665.77 1731.75,2628.77 1649.5,2562C 1545.11,2470.64 1503.61,2356.14 1525,2218.5C 1543.42,2138.98 1581.08,2070.31 1638,2012.5C 1724.73,1929.05 1827.89,1877.89 1947.5,1859C 1969.31,1856.53 1990.98,1854.03 2012.5,1851.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#000000" d="M 1379.5,1875.5 C 1434.55,1872.44 1476.05,1894.44 1504,1941.5C 1507.73,1949.96 1511.73,1958.29 1516,1966.5C 1522.92,2031.46 1501.09,2084.29 1450.5,2125C 1425.26,2142.77 1397.26,2149.44 1366.5,2145C 1313.36,2136.83 1277.86,2107.33 1260,2056.5C 1249.49,1997.03 1266.32,1946.86 1310.5,1906C 1330.89,1889.8 1353.89,1879.64 1379.5,1875.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#000000" d="M 2687.5,1875.5 C 2742.89,1873.11 2785.39,1895.11 2815,1941.5C 2832.9,1972.49 2840.57,2005.82 2838,2041.5C 2828.41,2090.75 2799.91,2123.59 2752.5,2140C 2699.54,2155.81 2655.04,2142.98 2619,2101.5C 2597.87,2076.91 2584.54,2048.58 2579,2016.5C 2578.33,1999.83 2578.33,1983.17 2579,1966.5C 2593.13,1927.71 2618.96,1899.87 2656.5,1883C 2666.74,1879.52 2677.07,1877.02 2687.5,1875.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#fefefe" d="M 2018.5,1983.5 C 2118.82,1978 2211.82,2001.16 2297.5,2053C 2340.25,2081.75 2376.41,2117.25 2406,2159.5C 2433.84,2203.86 2446.84,2252.19 2445,2304.5C 2439.12,2354.58 2419.45,2398.25 2386,2435.5C 2362.54,2461.31 2335.37,2482.15 2304.5,2498C 2251.11,2526.6 2194.11,2541.6 2133.5,2543C 2075.5,2543.67 2017.5,2543.67 1959.5,2543C 1884.97,2540.6 1816.97,2518.6 1755.5,2477C 1725.83,2455.33 1701,2429.16 1681,2398.5C 1637.86,2320.42 1639.19,2243.09 1685,2166.5C 1733.44,2091.82 1799.94,2039.99 1884.5,2011C 1927.96,1995.22 1972.62,1986.05 2018.5,1983.5 Z"/></g>
|
||||
<g><path style="opacity:1" fill="#000000" d="M 1964.5,2160.5 C 1974.84,2160.33 1985.17,2160.5 1995.5,2161C 1999.17,2162 2002.83,2163 2006.5,2164C 2019.36,2170.6 2032.03,2177.43 2044.5,2184.5C 2051.61,2180.57 2058.61,2176.4 2065.5,2172C 2084.44,2160.58 2104.77,2157.25 2126.5,2162C 2154.24,2173.76 2165.74,2194.6 2161,2224.5C 2159.39,2229.33 2157.39,2234 2155,2238.5C 2141.4,2256.86 2124.57,2271.36 2104.5,2282C 2095.83,2289.2 2093,2298.36 2096,2309.5C 2097.52,2320.59 2099.52,2331.59 2102,2342.5C 2102.67,2352.17 2102.67,2361.83 2102,2371.5C 2097.45,2391.05 2085.28,2402.88 2065.5,2407C 2048.08,2407.98 2030.75,2407.31 2013.5,2405C 1996.6,2395.27 1986.6,2380.77 1983.5,2361.5C 1986.88,2342.54 1990.05,2323.54 1993,2304.5C 1994.81,2296.58 1992.98,2289.75 1987.5,2284C 1971.14,2274.9 1956.31,2263.73 1943,2250.5C 1918.23,2221.25 1920.06,2193.75 1948.5,2168C 1953.54,2164.64 1958.88,2162.14 1964.5,2160.5 Z"/></g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 14 KiB |
BIN
public/svgs/organizr.png
Normal file
|
After Width: | Height: | Size: 14 KiB |
84
public/svgs/owncloud.svg
Normal file
|
After Width: | Height: | Size: 50 KiB |
1
public/svgs/postgresql.svg
Normal file
|
After Width: | Height: | Size: 12 KiB |
BIN
public/svgs/prefect.png
Normal file
|
After Width: | Height: | Size: 3.5 KiB |
16
public/svgs/qbittorrent.svg
Normal file
@@ -0,0 +1,16 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="1024" height="1024" viewBox="0 0 1024 1024">
|
||||
<title>
|
||||
qbittorrent-new-light
|
||||
</title>
|
||||
<defs>
|
||||
<linearGradient x1="34.012%" y1="0%" x2="76.373%" y2="76.805%" id="a">
|
||||
<stop stop-color="#72B4F5" offset="0%"/>
|
||||
<stop stop-color="#356EBF" offset="100%"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
<g fill="none" fill-rule="evenodd">
|
||||
<circle stroke="#DAEFFF" stroke-width="32" fill="url(#a)" cx="512" cy="512" r="496"/>
|
||||
<path d="M712.898 332.399q66.657 0 103.38 45.671 37.03 45.364 37.03 128.684t-37.34 129.61q-37.03 45.98-103.07 45.98-33.02 0-60.484-12.035-27.156-12.344-45.672-37.649h-3.703l-10.8 43.512h-36.724V196h51.227v116.65q0 39.191-2.469 70.359h2.47q35.796-50.61 106.155-50.61zm-7.406 42.894q-52.46 0-75.605 30.242-23.145 29.934-23.145 101.219t23.762 102.145q23.761 30.55 76.222 30.55 47.215 0 70.36-34.254 23.144-34.562 23.144-99.058 0-66.04-23.144-98.442-23.145-32.402-71.594-32.402z" fill="#fff"/>
|
||||
<path d="M317.273 639.45q51.227 0 74.68-27.466 23.453-27.464 24.996-92.578v-11.418q0-70.976-24.07-102.144-24.07-31.168-76.223-31.168-45.055 0-69.125 35.18-23.762 34.87-23.762 98.75 0 63.879 23.454 97.515 23.761 33.328 70.05 33.328zm-7.715 42.894q-65.421 0-102.144-45.98-36.723-45.981-36.723-128.376 0-83.011 37.032-129.609 37.03-46.598 103.07-46.598 69.433 0 106.773 52.461h2.778l7.406-46.289h40.426V828h-51.227V683.27q0-30.86 3.395-52.461h-4.012q-35.488 51.535-106.774 51.535z" fill="#c8e8ff"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.5 KiB |
BIN
public/svgs/qdrant.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
56
public/svgs/searxng.svg
Normal file
@@ -0,0 +1,56 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
xmlns:cc="http://creativecommons.org/ns#"
|
||||
xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
id="svg8"
|
||||
version="1.1"
|
||||
viewBox="0 0 92 92"
|
||||
height="92mm"
|
||||
width="92mm">
|
||||
<defs
|
||||
id="defs2" />
|
||||
<metadata
|
||||
id="metadata5">
|
||||
<rdf:RDF>
|
||||
<cc:Work
|
||||
rdf:about="">
|
||||
<dc:format>image/svg+xml</dc:format>
|
||||
<dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" />
|
||||
<dc:title></dc:title>
|
||||
</cc:Work>
|
||||
</rdf:RDF>
|
||||
</metadata>
|
||||
<g
|
||||
transform="translate(-40.921303,-17.416526)"
|
||||
id="layer1">
|
||||
<circle
|
||||
r="0"
|
||||
style="fill:none;stroke:#000000;stroke-width:12;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1"
|
||||
cy="92"
|
||||
cx="75"
|
||||
id="path3713" />
|
||||
<circle
|
||||
r="30"
|
||||
cy="53.902557"
|
||||
cx="75.921303"
|
||||
id="path834"
|
||||
style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:10;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<path
|
||||
d="m 67.514849,37.91524 a 18,18 0 0 1 21.051475,3.312407 18,18 0 0 1 3.137312,21.078282"
|
||||
id="path852"
|
||||
style="fill:none;fill-opacity:1;stroke:#3050ff;stroke-width:5;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
<rect
|
||||
transform="rotate(-46.234709)"
|
||||
ry="1.8669105e-13"
|
||||
y="122.08995"
|
||||
x="3.7063529"
|
||||
height="39.963303"
|
||||
width="18.846331"
|
||||
id="rect912"
|
||||
style="opacity:1;fill:#3050ff;fill-opacity:1;stroke:none;stroke-width:8;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.7 KiB |
BIN
public/svgs/soketi.jpeg
Normal file
|
After Width: | Height: | Size: 18 KiB |
8
public/svgs/strapi.svg
Normal file
@@ -0,0 +1,8 @@
|
||||
<svg width="64" height="64" viewBox="0 0 64 64" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M0 22.1867C0 11.7278 0 6.49832 3.24916 3.24916C6.49832 0 11.7278 0 22.1867 0H41.8133C52.2722 0 57.5017 0 60.7508 3.24916C64 6.49832 64 11.7278 64 22.1867V41.8133C64 52.2722 64 57.5017 60.7508 60.7508C57.5017 64 52.2722 64 41.8133 64H22.1867C11.7278 64 6.49832 64 3.24916 60.7508C0 57.5017 0 52.2722 0 41.8133V22.1867Z" fill="#4945FF"/>
|
||||
<path fill-rule="evenodd" clip-rule="evenodd" d="M44.156 19.4131H22.6094V30.4004H33.596V41.3864H44.5827V19.8398C44.5827 19.6041 44.3917 19.4131 44.156 19.4131Z" fill="white"/>
|
||||
<rect x="33.1719" y="30.4004" width="0.426667" height="0.426667" fill="white"/>
|
||||
<path d="M22.6172 30.4004H33.1772C33.4128 30.4004 33.6039 30.5914 33.6039 30.8271V41.3871H23.0439C22.8082 41.3871 22.6172 41.196 22.6172 40.9604V30.4004Z" fill="#9593FF"/>
|
||||
<path d="M33.6016 41.3867H44.5882L33.9657 52.0092C33.8314 52.1436 33.6016 52.0484 33.6016 51.8584V41.3867Z" fill="#9593FF"/>
|
||||
<path d="M22.6151 30.3998H12.1434C11.9534 30.3998 11.8582 30.17 11.9926 30.0356L22.6151 19.4131V30.3998Z" fill="#9593FF"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.1 KiB |
17
public/svgs/supertokens.svg
Normal file
@@ -0,0 +1,17 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="44.869" height="40.302" viewBox="0 0 44.869 40.302">
|
||||
<g id="Group_10325" data-name="Group 10325" transform="translate(0.516)">
|
||||
<path id="Exclusion_1" data-name="Exclusion 1" d="M18.621,36.98c-.1,0-.2,0-.305-.008a7.383,7.383,0,0,1-3.67-1.338c-.308-.207-.615-.429-.912-.644l-.027-.019a16.427,16.427,0,0,0-1.965-1.286,7.348,7.348,0,0,0-3.4-.847l-.165,0a5.86,5.86,0,0,0-1.338.135A1.959,1.959,0,0,0,5.934,34.7a3.214,3.214,0,0,0,.3,1.18,3.066,3.066,0,0,1,.274.709h0c-.034,0-.122-.108-.289-.313-.665-.82-2.428-2.995-4.791-3.458A1.76,1.76,0,0,1,.306,30.1C6.2,21.434,6.931,18.338,9.672,6.822l.238-1q.261-1.1.55-2.3A1.773,1.773,0,0,1,11.5,2.3L14.818.918a1.759,1.759,0,0,1,.676-.135,1.8,1.8,0,0,1,.275.021A14.322,14.322,0,0,1,20.989,0h2.3a14.32,14.32,0,0,1,5.219.8,1.77,1.77,0,0,0-1.017.539l-10,.758h0l-.7-.757A1.773,1.773,0,0,0,15.77.805a5.9,5.9,0,0,0-1.814,1.1c-1.308,1.2-1.972,3.351-1.972,6.406V20.836c0,3.056.664,5.213,1.972,6.408,1.377,1.262,3.743,1.9,7.033,1.9h2.3c3.29,0,5.656-.64,7.033-1.9,1.308-1.2,1.972-3.354,1.972-6.408V8.31c0-3.053-.664-5.208-1.972-6.406A5.912,5.912,0,0,0,28.508.8a1.825,1.825,0,0,1,.274-.021,1.749,1.749,0,0,1,.675.135L32.779,2.3a1.773,1.773,0,0,1,1.036,1.223c.613,2.556,1.133,4.837,1.511,6.5,2.1,9.24,2.891,12.7,8.2,20.511a1.759,1.759,0,0,1-1.115,2.718A8.073,8.073,0,0,0,37.9,36.443c-.108.139-.155.2-.168.2a2.225,2.225,0,0,1,.195-.49l.118-.273a3.243,3.243,0,0,0,.293-1.18,1.9,1.9,0,0,0-.657-1.524,10.157,10.157,0,0,0-2.225-.28q-.118,0-.237,0a3.506,3.506,0,0,0-2.887,1.172,5,5,0,0,0-.3.455l-.013.022a4.346,4.346,0,0,1-.365.543,1.328,1.328,0,0,1-1.083.532A4.472,4.472,0,0,1,28.737,35c-.242-.122-.44-.222-.632-.3a5.773,5.773,0,0,0-2.236-.523,3.7,3.7,0,0,0-.643.055,7.689,7.689,0,0,0-2.771,1.336c-.194.126-.386.252-.579.374A6.007,6.007,0,0,1,18.621,36.98Z" transform="translate(0 2.822)" fill="#f93" stroke="rgba(0,0,0,0)" stroke-width="1"/>
|
||||
<g id="Group_4056" data-name="Group 4056" transform="translate(5.914 22.19)">
|
||||
<path id="Path_14227" data-name="Path 14227" d="M698.042,466.44l.162-2.728,2.46-.713,1.006,3.181A4.743,4.743,0,0,0,698.042,466.44Z" transform="translate(-680.16 -451.111)" fill="#db902e"/>
|
||||
<path id="Path_14229" data-name="Path 14229" d="M660.956,448.452c0,.064,0,1.019.007,1.1-1.971-.35-3.581.3-3.53,1.77h-.017V450.9c-.081-2.846,1.322-5.229,2.111-7.863.647-2.175.943-8.8,1.467-6.608a14.459,14.459,0,0,1-.037,5.614,23.229,23.229,0,0,0,0,3.2Z" transform="translate(-657.412 -435.988)" fill="#db902e"/>
|
||||
<path id="Path_14231" data-name="Path 14231" d="M722.715,448.452c0,.064,0,1.019-.007,1.1,1.724.09,3.581.3,3.53,1.77h.017V450.9c.081-2.846-1.322-5.229-2.11-7.863-.647-2.175-.943-8.8-1.467-6.608a14.438,14.438,0,0,0,.038,5.614,23.287,23.287,0,0,1,0,3.2Z" transform="translate(-693.804 -435.988)" fill="#db902e"/>
|
||||
</g>
|
||||
<g id="Group_1803" data-name="Group 1803" transform="translate(9.16)">
|
||||
<path id="Path_14233" data-name="Path 14233" d="M678.914,391.217c3.483,0,4.746.813,5.128,1.162.671.615,1.056,2.193,1.056,4.328v12.525c0,2.135-.385,3.712-1.057,4.328-.381.349-1.643,1.161-5.127,1.161h-2.3c-3.483,0-4.746-.812-5.129-1.163-.671-.614-1.055-2.191-1.055-4.326V396.707c0-2.135.385-3.713,1.056-4.328.382-.349,1.645-1.162,5.128-1.162h2.3m0-5.644h-2.3q-6.052,0-8.94,2.644t-2.888,8.49v12.525q0,5.846,2.888,8.49t8.94,2.644h2.3q6.054,0,8.94-2.644t2.888-8.49V396.707q0-5.846-2.888-8.49t-8.94-2.644Z" transform="translate(-664.788 -385.573)" fill="#1a1a1a"/>
|
||||
</g>
|
||||
<g id="Group_1804" data-name="Group 1804" transform="translate(19.692 15.337)">
|
||||
<ellipse id="Ellipse_669" data-name="Ellipse 669" cx="2.445" cy="2.445" rx="2.445" ry="2.445" transform="translate(0 0)" fill="#1a1a1a"/>
|
||||
<path id="Path_14234" data-name="Path 14234" d="M693.3,432.955h-2.286a.517.517,0,0,1-.514-.566l.47-4.836a.516.516,0,0,1,.514-.466h1.344a.516.516,0,0,1,.514.466l.47,4.836A.517.517,0,0,1,693.3,432.955Z" transform="translate(-689.717 -424.151)" fill="#1a1a1a"/>
|
||||
</g>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 3.9 KiB |
5
public/svgs/tolgee.svg
Normal file
@@ -0,0 +1,5 @@
|
||||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg width="100%" height="100%" viewBox="0 0 200 200" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||
style="fill:#EC407A;fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2;">
|
||||
<path d="M97.16,7.27a16.94,16.94,0,0,0-1.9,24.47,16.36,16.36,0,0,0,5,3.83,3.23,3.23,0,0,1-2.9,5.77,23.14,23.14,0,0,1-11.41-13C73.83,31.1,63.46,37.09,52.82,46.51c-27.44,24.3-34.35,61.74-16.38,85.26-4.57,5.79-8,12.22-8.9,18.69a20.88,20.88,0,0,0,5.62,18c9.18,9.61,21.42,7.13,31.26,5.14,6.58-1.34,12.8-2.6,16.5-.23,3.22,2.07,3.47,3.87,3.61,4.45,2.1,9.32-5.79,13.89-7.67,16.27a1.48,1.48,0,0,0,1.13,2.4c3.48,0,9-1.18,12.34-4.08s7.16-7.9,5.89-16.32c-.08-.5-.18-1-.32-1.58-.86-3.35-3.1-7.57-8.61-11.09-7.72-4.95-17-3.07-25.22-1.41-9.76,2-16,2.85-20.37-1.71a9.13,9.13,0,0,1-2.46-8.19c.54-3.77,2.65-7.89,5.62-11.86,21.71,16.89,56.87,13.47,82.67-9.39a75.34,75.34,0,0,0,20.81-28.09A23.14,23.14,0,0,1,134.8,89a3.23,3.23,0,0,1,6.08-2.19,16.37,16.37,0,0,0,3.2,5.39,16.85,16.85,0,1,0,11.48-28,3.23,3.23,0,0,1-.51-6.44,23.41,23.41,0,0,1,12.88,2.69c2.6-14.08,3.34-31.41-2.06-37.51-4.08-4.61-20.62-8-35.18-7.76A23.48,23.48,0,0,1,130.8,25a3.23,3.23,0,0,1-6.33-1.28A16.94,16.94,0,0,0,97.16,7.27Zm63.25,21a5.29,5.29,0,0,1-.57,6.19c-1.29,1.14-2.72-.51-4.1-2.06s-3.1-3.42-1.81-4.56A5.74,5.74,0,0,1,160.41,28.27Z"/>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.3 KiB |
BIN
public/svgs/traccar.png
Normal file
|
After Width: | Height: | Size: 22 KiB |
13
public/svgs/unsend.svg
Normal file
@@ -0,0 +1,13 @@
|
||||
<svg width="512" height="512" viewBox="0 0 512 512" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<mask id="mask0_11_17" style="mask-type:alpha" maskUnits="userSpaceOnUse" x="0" y="0" width="512" height="512">
|
||||
<rect width="512" height="512" fill="black"/>
|
||||
</mask>
|
||||
<g mask="url(#mask0_11_17)">
|
||||
<path d="M375.776 63.6078C376.949 58.409 384.357 58.409 385.53 63.6078L435.035 282.926C436.338 288.703 428.294 291.55 425.673 286.239L385.137 204.087C383.303 200.37 378.003 200.37 376.169 204.087L335.632 286.239C333.012 291.55 324.967 288.703 326.271 282.926L375.776 63.6078Z" fill="#D9D9D9"/>
|
||||
<path d="M400 312C400 338.264 394.827 364.272 384.776 388.537C374.725 412.802 359.993 434.85 341.421 453.421C322.85 471.993 300.802 486.725 276.537 496.776C252.272 506.827 226.264 512 200 512C173.736 512 147.728 506.827 123.463 496.776C99.1982 486.725 77.1504 471.993 58.5786 453.421C40.0069 434.85 25.275 412.802 15.2241 388.537C5.17315 364.272 -2.2961e-06 338.264 0 312L40.7078 312C40.7078 332.919 44.828 353.632 52.8332 372.958C60.8383 392.285 72.5717 409.845 87.3634 424.637C102.155 439.428 119.715 451.162 139.041 459.167C158.368 467.172 179.081 471.292 200 471.292C220.919 471.292 241.632 467.172 260.958 459.167C280.285 451.162 297.845 439.428 312.637 424.637C327.428 409.845 339.162 392.285 347.167 372.959C355.172 353.632 359.292 332.919 359.292 312H400Z" fill="#D9D9D9"/>
|
||||
<path d="M0 20.5C0 9.17816 9.17816 0 20.5 0V0C31.8218 0 41 9.17816 41 20.5V310.5C41 321.822 31.8218 331 20.5 331V331C9.17816 331 0 321.822 0 310.5V20.5Z" fill="#D9D9D9"/>
|
||||
<path d="M359 20.5C359 9.17816 368.178 0 379.5 0V0C390.822 0 400 9.17816 400 20.5V310.5C400 321.822 390.822 331 379.5 331V331C368.178 331 359 321.822 359 310.5V20.5Z" fill="#D9D9D9"/>
|
||||
<path d="M362.06 10.2806C363.767 5.02805 369.408 2.15354 374.661 3.86019V3.86019C379.913 5.56684 382.788 11.2084 381.081 16.4609L284.977 312.239C283.27 317.492 277.629 320.367 272.376 318.66V318.66C267.123 316.953 264.249 311.312 265.956 306.059L362.06 10.2806Z" fill="#D9D9D9"/>
|
||||
<path d="M378.96 17.9405C377.254 12.688 380.128 7.04642 385.381 5.33976V5.33976C390.633 3.63311 396.275 6.50762 397.981 11.7602L494.086 307.539C495.792 312.791 492.918 318.433 487.665 320.139V320.139C482.413 321.846 476.771 318.972 475.064 313.719L378.96 17.9405Z" fill="#D9D9D9"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.2 KiB |